From 72de43d2730914ec708b55b5115f98eb8b31840e Mon Sep 17 00:00:00 2001 From: choiminyeong Date: Thu, 27 Aug 2026 23:46:19 +0900 Subject: [PATCH] docs: TASK-033 follow-up, diagnose login server_error after scope change Traced the live 'denied:server_error' login failure to Gitea 1.23.5's own GrantApplicationOAuth: it refuses to silently widen an existing OAuth2 grant's scope (grant.Scope != form.Scope -> ErrorCodeServerError, 'a grant exists with different scope'). No code change -- this is Gitea's own intended behavior. Fix is to revoke UBGitea's existing authorization from Gitea's Settings > Applications page before retrying login, so a fresh grant is created under the new scope. Co-Authored-By: Claude Sonnet 5 --- docs/development-log.md | 9 +++++++++ .../033-write-repository-oauth-scope-for-starring.md | 12 ++++++++++++ 2 files changed, 21 insertions(+) diff --git a/docs/development-log.md b/docs/development-log.md index ded0f13..c6765eb 100644 --- a/docs/development-log.md +++ b/docs/development-log.md @@ -546,3 +546,12 @@ This is the append-only implementation and handoff record shared by Codex and Cl - Known limitations: a device already logged in under the old, read-only-only scope needs one explicit re-login before starring actually works — TASK-029's refresh-token flow keeps a session alive indefinitely for the scope it was originally granted, and a refresh doesn't expand that scope. This is expected and was reported directly to the human product owner rather than silently worked around (e.g. by force-clearing the stored session on their behalf), since that kind of forced logout should be their call. Live confirmation (star actually succeeding after a fresh login) is still pending. - Next recommended task: ask the human product owner to log out and back in once, then confirm starring/unstarring actually works. Still pending from earlier in this session: TASK-030's green theme/footer-height/language-star batch, TASK-031's label/EUC-KR/timeout batch, TASK-032's swipe-direction fix, pinch-zoom/pan, CSV, PDF, and Issues/PR numbered pagination, all awaiting live confirmation. - Next owner: Claude, continuing per the standing direction. + +## 2026-08-27 — TASK-033 follow-up: diagnosed the "denied:server_error" login failure after the scope change + +- Agent and role: Claude, direct continuation of the same live session — "로그인이 안돼" (login isn't working) after installing the write:repository build; device screenshot showed "로그인 응답을 확인할 수 없습니다... [debug] denied:server_error". +- Diagnosis, not a code change: verified the running Gitea instance is 1.23.5 (via `/api/v1/version`, confirmed a modern version with full scoped-OAuth-token support, ruling out a version gap). Reproduced the authorize request's own URL directly (dummy PKCE values, real client_id/redirect_uri/scope) in a browser to confirm it reaches Gitea's login page cleanly rather than erroring at the HTTP-parsing level. Then traced `GrantApplicationOAuth` in Gitea's own source (`routers/web/auth/oauth2_provider.go`, 1.23 branch) and found the exact check responsible: `if grant.Scope != form.Scope { ...ErrorCode: ErrorCodeServerError, ErrorDescription: "a grant exists with different scope" }` — Gitea deliberately refuses to silently widen an already-existing OAuth2 grant's scope. The device's account already had a grant for this app from before TASK-033's scope change, stored under the old read-only-only scope string; the new, differently-scoped login request hits this check every time, which is exactly the "server_error" shown. +- Files changed: `tasks/033-write-repository-oauth-scope-for-starring.md` (Known limitations section) only — no source changed, since this is Gitea's own intended behavior, not a bug in the app. +- Fix (not yet done): the human product owner needs to revoke UBGitea's existing authorization from the Gitea web UI (Settings → Applications → "Authorized OAuth2 Applications" → revoke), then log in again on the device — this creates a fresh grant under the new scope and should show the consent screen listing `write:repository`. +- Next recommended task: wait for the human product owner to revoke the old grant and retry login, then confirm starring actually works. Everything else queued from earlier in this session remains pending live confirmation. +- Next owner: Claude, continuing per the standing direction once the human product owner responds. diff --git a/tasks/033-write-repository-oauth-scope-for-starring.md b/tasks/033-write-repository-oauth-scope-for-starring.md index 4319b7f..726618e 100644 --- a/tasks/033-write-repository-oauth-scope-for-starring.md +++ b/tasks/033-write-repository-oauth-scope-for-starring.md @@ -94,6 +94,18 @@ local-only bookmark, or remove the feature — and explicitly chose to add the s - Requires a manual one-time re-login on the device before starring actually works — see Design notes. Not yet done in this session. +- **The re-login itself fails with "denied:server_error" until the old grant is revoked first.** + Live-reproduced: logging in after this change showed "로그인 응답을 확인할 수 없습니다... [debug] + denied:server_error". Traced directly to Gitea 1.23.5's own source + (`routers/web/auth/oauth2_provider.go`, `GrantApplicationOAuth`): `if grant.Scope != form.Scope { ... ErrorCode: ErrorCodeServerError, ErrorDescription: "a grant exists with different scope" }` + — Gitea deliberately refuses to silently widen an existing OAuth2 grant's scope; the human + product owner's account already had a grant for this app from before this change, stored under + the old (read-only-only) scope string, and the new login's differently-scoped request hits this + exact check. This is Gitea's own intended behavior, not a bug introduced by this task or + something fixable from the client side. **Fix**: on the Gitea web UI, go to + Settings → Applications → "Authorized OAuth2 Applications" and revoke UBGitea's existing + authorization, then try logging in again on the device — a fresh grant will be created under the + new scope and the consent screen should show `write:repository` listed. Not yet confirmed live. - No change was made to retroactively reflect a repository's *already*-starred-on-the-server state when the ALL list first loads (the pre-existing, unrelated `favoriteAction` limitation noted in TASK-030 — still applies, unaffected by this task).