Skip to content

fix(auth): fix cross-origin logout 401 and CORS Authorization header - #31

Merged
zhaochy1990 merged 2 commits into
masterfrom
fix/auth-cross-origin-logout-cors
Jul 29, 2026
Merged

fix(auth): fix cross-origin logout 401 and CORS Authorization header#31
zhaochy1990 merged 2 commits into
masterfrom
fix/auth-cross-origin-logout-cors

Conversation

@zhaochy1990

Copy link
Copy Markdown
Owner

Problem

After deploying the auth backend to Tencent Cloud, POST /api/auth/logout returned 401 Unauthorized. Two distinct issues were found, both around cross-origin / token-state handling.

Changes

1. Logout no longer requires a Bearer access token

/api/auth/logout was the only /api/auth/* route gated by AuthenticatedUser(), so it demanded a valid, non-expired Bearer access token. But:

  • The Logout handler only reads refresh_token from the body to revoke the session — it never uses the authenticated user identity.
  • At logout time the access token is frequently expired or already cleared by the client, yielding a 401.

Fix: route logout through ClientApp() (X-Client-Id), exactly like /refresh. Logout is now idempotent and independent of access-token state. Integration test updated.

2. CORS Access-Control-Allow-Headers lists Authorization explicitly

The header was set to the wildcard *. Per the Fetch spec, * does not cover the Authorization header, so any cross-origin request carrying a Bearer (or Basic, for /oauth) token fails the preflight and never reaches the server. Replaced with an explicit allow-list (Authorization, Content-Type, X-Client-Id); methods list made explicit too.

This keeps cross-origin Bearer endpoints (/api/users, /api/teams, /oauth) working and is the correct pattern to mirror when other services (e.g. stride-api) become cross-origin.

Testing

  • gofmt clean on all touched files.
  • Updated TestRegisterLoginRefreshLogout to send X-Client-Id for logout.
  • Note: full go build/go test requires the local replace dependency (../../../../x) + MySQL, not present in this sandbox; changes add no new imports.

Logout was the only /api/auth/* route gated by AuthenticatedUser(), so it
required a valid, non-expired Bearer access token. In practice the access
token is often expired or already cleared by the time a user logs out, which
produced a 401 (observed cross-origin behind the Tencent Cloud proxy).

The Logout handler only needs the refresh_token from the request body to
revoke the session; it never uses the authenticated user identity. Switch the
route to ClientApp() (X-Client-Id) like /refresh, making logout idempotent and
independent of access-token state. Update the integration test accordingly.
Access-Control-Allow-Headers was set to the wildcard "*". Per the Fetch
spec, "*" does NOT cover the Authorization header, so cross-origin requests
carrying a Bearer (or Basic, for /oauth) token fail the preflight and never
reach the server. Replace the wildcard with an explicit allow-list that names
Authorization, Content-Type, and X-Client-Id, and make the method allow-list
explicit too. This keeps cross-origin Bearer endpoints (/api/users, /api/teams,
/oauth) working and serves as the correct pattern for other services.
@zhaochy1990
zhaochy1990 merged commit 4a929ce into master Jul 29, 2026
7 checks passed
@zhaochy1990
zhaochy1990 deleted the fix/auth-cross-origin-logout-cors branch July 29, 2026 08:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant