Server API: OpenAPI OAuth scopes and endpoints don't match what the server uses; a disallowed client id returns 500 instead of 401
まだ誰も着手していません。
評価
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 初心者へのやさしさ
- 46/100
- issue の種類
- バグ
- 明瞭さ
- 明確に書かれている
- 活発さ
- 活発
- 技術スタック
- aws, clojure, openapi
- 領域
- api, authentication
調査の方向性
Start with deps/db-sync/src/logseq/db_sync/worker/routes/semantic.cljs for the OpenAPI scopes and OAuth URLs, then compare them with the pool discovery document and the existing OpenAPI tests. For the 500, read auth.cljs, authorization.cljs, and dispatch.cljs, and run the db-sync test suite, including the described auth-claims case. Done means scopes and endpoints match the pool and operations, and disallowed client IDs return 401 without debug fields.
索引モデルが issue の本文から書いたものです。
説明
Search first
- I searched and no similar issues were found
Searched logseq/db-test and logseq/logseq (open and closed; issue search plus a title scan of the latest 1000 issues in each) for: openapi, oauth, scopes, api-docs, api.logseq.io, dispatch error, aud not found. Not the same as #1055 (the CLI derives its OAuth endpoints from a custom sync origin) or #1023 (a graph-specific Durable Object dispatch error 500).
What Happened?
Three problems with the Logseq Server API (https://api.logseq.io, added in logseq/logseq#12896), found while working out how to test it with a real OAuth token:
1. The OpenAPI security scheme declares scope names the operations don't use. components.securitySchemes.oauth declares the scopes read and write. Every operation requires logseq/read or logseq/write, and so does /.well-known/oauth-protected-resource. A client that takes its scopes from the security scheme requests names the server never checks for.
2. The OpenAPI security scheme points at OAuth endpoints that the user pool does not publish. authorizationUrl and tokenUrl are the pool issuer plus /oauth2/authorize and /oauth2/token, on cognito-idp.us-east-1.amazonaws.com. The pool's own OpenID discovery document lists the endpoints on its hosted-UI domain (logseq-prod.auth.us-east-1.amazoncognito.com). A plain request to each URL from the spec returned HTTP 400, while the hosted-UI authorize URL returned 302. I did not attempt a full authorization flow against either.
3. A well-formed token whose client id is not allowed gets HTTP 500 dispatch error, not 401. With the correct issuer and a client id that is not on the allowlist, GET /api/v1/graphs returns 500 with debug-message: "aud not found" and the internal debug-* fields from the dispatch error handler. A token with the wrong issuer, an unparseable token, and an allowed client id with a bad signature all return 401. The source lists "aud not found" as a recoverable auth error that should become a 401.
Reproduce the Bug
All requests are unauthenticated or use an unsigned, made-up token; none needs an account.
- Scope names (problem 1):
First printscurl -s https://api.logseq.io/openapi.json | jq '.components.securitySchemes.oauth.flows.authorizationCode.scopes | keys' curl -s https://api.logseq.io/openapi.json | jq '.paths["/api/v1/graphs"].get.security'["read","write"], second prints[{"oauth":["logseq/read"]}]. - Endpoints (problem 2):
The first pair is oncurl -s https://api.logseq.io/openapi.json | jq '.components.securitySchemes.oauth.flows.authorizationCode | .authorizationUrl, .tokenUrl' curl -s https://cognito-idp.us-east-1.amazonaws.com/us-east-1_dtagLnju8/.well-known/openid-configuration | jq '.authorization_endpoint, .token_endpoint'cognito-idp.us-east-1.amazonaws.com/.../oauth2/..., the second pair onlogseq-prod.auth.us-east-1.amazoncognito.com/oauth2/.... Thencurl -s -o /dev/null -w '%{http_code}\n' <each URL from the first pair>returns 400. - The 500 (problem 3). Build an unsigned token with the pool issuer and a client id that is not allowed:
ReturnsTOKEN=$(node -e 'const b=o=>Buffer.from(JSON.stringify(o)).toString("base64url");console.log(b({alg:"RS256",kid:"x"})+"."+b({iss:"https://cognito-idp.us-east-1.amazonaws.com/us-east-1_dtagLnju8",client_id:"not-allowed",exp:Math.floor(Date.now()/1000)+3600})+".c2ln")') curl -s -w '\n%{http_code}\n' -H "Authorization: Bearer $TOKEN" https://api.logseq.io/api/v1/graphs | head -c 300{"error":"dispatch error",...,"debug-message":"aud not found",...}and 500. Repeat withissset tohttps://x, or withAuthorization: Bearer garbage: both return{"error":"unauthorized"}and 401.
Expected Behavior
- The scopes in the security scheme are
logseq/readandlogseq/write, the same strings the operations and the protected-resource metadata use. authorizationUrlandtokenUrlare endpoints the user pool actually serves, as listed in its discovery document.- A token whose client id is not allowed returns 401
unauthorized, like the other invalid-token cases, and not a 500 with debug fields.
Screenshots
Files
Browser, Desktop or Mobile Platform Information
Server side, no client involved. Probed https://api.logseq.io on 2026-10-08. Source read at logseq/logseq master ed0b0404dc (the OpenAPI document is generated from it; the live document matched). The deployed worker revision is not known.
Additional Context
Investigation (source at logseq/logseq master ed0b0404dc, checked 2026-10-08)
- Scope names — confirmed.
deps/db-sync/src/logseq/db_sync/worker/routes/semantic.cljs:395declares the scopes as{:logseq/read "…" :logseq/write "…"}, namespaced keywords used as map keys. Operations use the strings"logseq/read"and"logseq/write"(same file,:scopeentries near the top, and:security [{:oauth [scope]}]). The live document showsreadandwrite, so thelogseq/part is dropped when the document is serialised (suspected mechanism: keyword keys lose their namespace).- Using string keys fixes it. I ran the db-sync suite with a test that compares the scheme's scopes with the operations' scopes: it fails before the change (
#{"read" "write"}vs#{"logseq/read" "logseq/write"}) and passes after it (192 tests, 0 failures).
- Endpoints — confirmed for the values, suspected for impact.
semantic.cljs:393-394builds both URLs as(str issuer "/oauth2/authorize")and(str issuer "/oauth2/token"), whereissuerisCOGNITO_ISSUER(deps/db-sync/worker/wrangler.toml, thecognito-idpURL). Nothing reads the discovery document. I did not run a client against the spec URLs, so the impact on a real OAuth client is not tested.- No test covers
components.securitySchemes; the existing OpenAPI test only checks per-operation scopes.
- The 500 — confirmed live and in a unit test; cause unknown.
deps/db-sync/src/logseq/db_sync/worker/auth.cljs:34-35lists"aud not found"as recoverable, andauth-claimsshould return nil for it. The throw is atdeps/common/src/logseq/common/authorization.cljs:128.- In the db-sync test build (base
533ac4382a, same lines inauth.cljs), callingauth/auth-claimswith an unsigned token with a valid issuer and an unknownclient_idrejects withaud not foundinstead of resolving nil. Adding that test to the suite also made many later tests in the same run fail; I did not isolate why. - I did not find why the wrong-issuer case behaves differently live (401). A probe showed
verify-jwtreturns a promise rather than throwing synchronously for both cases. - The 500 body comes from
deps/db-sync/src/logseq/db_sync/worker/dispatch.cljs:233-238, which returns:debug-type,:debug-message,:debug-data,:debug-jsonand:debug-stackfor any uncaught error.
Are you willing to submit a PR?
- I'm willing to submit a PR (Thank you!)
- 主要言語
- 言語のデータがありません
- スター
- 29
- フォーク
- 2
- PR マージ指標
- 30日以内にマージされた PR はありません
環境構築
このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
logseq/db-test のほかの issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
-
難易度 2/5 1〜3時間 初心者へのやさしさ 85/100
-
Page titles with `$$`, `$&`, `` $` `` or `$'` change when block refs are resolved対応中かも @RaphaelFakhri が 20 日前に担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
-
`#Asset` label is not displayed on asset nodes when `Hide from Node` is disabled対応中かも @tiensonqin が 23 日前に担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 65/100
-
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
似ている issue
-
enhancement triage
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
ShaftHQ/SHAFT_ENGINE#7901 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
ClickHouse/clickhouse-js#1130 ·
メンテナーはふだん 1 日以内に返信
-
難易度 1/5 1時間未満 初心者へのやさしさ 75/100
DOI-USGS/pywatershed#428 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 88/100
hugohe3/ppt-master#348 ·
メンテナーはふだん 1 日以内に返信
-
bug claude Minor static-analysis
難易度 1/5 1時間未満 初心者へのやさしさ 82/100
linagora/cozy-flagship-app#1358 ·