Skip to content

feat(server,web): add SSO logout tracking with response header#2142

Open
soneda-yuya wants to merge 11 commits intomainfrom
feat/sso-logout-tracking
Open

feat(server,web): add SSO logout tracking with response header#2142
soneda-yuya wants to merge 11 commits intomainfrom
feat/sso-logout-tracking

Conversation

@soneda-yuya
Copy link
Copy Markdown
Contributor

@soneda-yuya soneda-yuya commented Apr 1, 2026

What I've done

Server

Web

  • Read X-Latest-Logout-At header from API responses and store in Jotai atom
  • Compare latestLogoutAt with JWT iat in getAccessToken — if logout is newer, re-fetch token with cacheMode: "off" to bypass cache. In the same browser, this causes the re-fetch to fail (SSO session is already gone), resulting in the user being redirected to login.
  • Call logout mutation before Auth0 SDK logout() to record timestamp in accounts API

What I haven't done

How I tested

  • Server: go build ./... and go test ./internal/adapter/gql/... ./internal/app/... pass
  • Web: yarn type and yarn build pass

Which point I want you to review particularly

  • Server middleware and CORS configuration for X-Latest-Logout-At header
  • Frontend logout detection flow: response header capture → JWT iat comparison → cacheMode: "off" re-fetch → logout
  • Logout mutation call timing (before Auth0 SDK logout)

Memo

Checklist

  • Verified backward compatibility related to feature modifications
  • Confirmed backward compatibility for migrations
  • Verified that no personally identifiable information (PII) is included

🤖 Generated with Claude Code

soneda-yuya and others added 4 commits April 1, 2026 13:18
…ut tracking

Incorporate reearth/reearth-accounts#212 which adds latest_logout_at field,
logout mutation, and X-Latest-Logout-At response header for cross-service
SSO logout detection. Adapt to breaking API changes in workspace client types.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add logout mutation, Me.latestLogoutAt field, and X-Latest-Logout-At
response header middleware to enable cross-service SSO logout detection
by proxying to reearth-accounts API.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Compare JWT iat with X-Latest-Logout-At response header timestamp.
When a newer logout is detected, re-fetch access token with
cacheMode: "off" to ensure the session reflects the latest auth state.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Send logout GraphQL mutation to record latestLogoutAt timestamp
in accounts API before clearing the Auth0 SSO session. This enables
other services to detect the logout via X-Latest-Logout-At header.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 1, 2026 04:20
@soneda-yuya soneda-yuya changed the title feat(server,web): add server-side SSO logout tracking feat(server,web): add SSO logout tracking with response header Apr 1, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds server-side logout timestamp tracking and propagates it to the web client to detect SSO logout across sessions, refreshing tokens when the server indicates a newer logout.

Changes:

  • Server: add logout GraphQL mutation proxy + expose Me.latestLogoutAt and return X-Latest-Logout-At response header (with CORS exposure).
  • Web: capture X-Latest-Logout-At from GraphQL responses, compare against JWT iat, and force-refresh access tokens when server logout is newer.
  • Web: best-effort logout mutation call before invoking the Auth0 SDK logout.

Reviewed changes

Copilot reviewed 12 out of 13 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
web/src/services/gql/provider/links/uploadLink.ts Captures X-Latest-Logout-At from GraphQL responses and updates in-memory logout timestamp.
web/src/services/auth/logoutTimestamp.ts Adds in-memory storage/getter/updater for latest logout timestamp.
web/src/services/auth/auth0Auth.ts Adds JWT iat extraction + conditional token refresh, and sends logout mutation before Auth0 logout.
server/internal/app/auth_client.go Maps LatestLogoutAt from accounts user model into domain user builder.
server/internal/app/app.go Exposes X-Latest-Logout-At via CORS and adds middleware to attach header to private API responses.
server/internal/adapter/gql/resolver_mutation_workspace.go Adapts workspace client input types to accounts API breaking changes.
server/internal/adapter/gql/resolver_mutation_user.go Adds logout mutation and maps LatestLogoutAt from accounts user model.
server/internal/adapter/gql/gqlmodel/models_gen.go Adds latestLogoutAt field to Me GraphQL model.
server/internal/adapter/gql/gqlmodel/convert_user.go Populates Me.latestLogoutAt when available.
server/internal/adapter/gql/generated.go Regenerates gqlgen outputs for new schema fields/mutation.
server/gql/user.graphql Adds Me.latestLogoutAt and Mutation.logout.
server/go.mod / server/go.sum Bumps reearth-accounts dependency to version including logout tracking.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 1, 2026

🚀 Cloud Run Preview Deployed

🔗 Click here to open the preview in a new tab

Replace direct fetch call in auth0Auth.ts with Apollo Client mutation
via useMeMutations. Each logout call site (Dashboard, Navbar,
GlobalModal) now calls logoutFromAccount() before auth.logout().

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace module-level let variable with Jotai atom to align with
existing state management patterns. The GqlProvider passes the setter
to uploadLink as a callback, and auth0Auth reads via useLatestLogoutAt.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Address Copilot review feedback:
- Fix JWT iat parsing to handle base64url encoding (- / _ and padding)
- Extract JWT utils to jwtUtils.ts for testability
- Add unit tests for base64UrlDecode and getJwtIat
- Add server test for X-Latest-Logout-At header middleware

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add missing useLatestLogoutAt to @reearth/services/state mock
in test utils to fix CI test failures.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 26 out of 27 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Rename auth0Auth.test.ts to jwtUtils.test.ts to match tested module
- Add comment clarifying latestLogoutAt uses Unix seconds (matches JWT iat)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 26 out of 27 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants