Repository navigation
Conversation
The Google callback page sent the access and refresh tokens with postMessage(..., '*'). Any site could open /oauth/google/login in a popup and receive a fresh session for a user who had already consented. Add httpApi.webOrigins, an allowlist of exact origins (the schema rejects '*', paths and trailing slashes). The callback now posts once to each allowlisted origin, and the browser delivers the message only when the opener's origin matches exactly. Dev config allows http://localhost:5173. Deploy: stage and production configs must set httpApi.webOrigins (e.g. https://notex.so), or Google login will deliver no tokens. Follow-up in notes.web: useAuth.ts should accept the message only if event.origin equals the API origin and event.source is the popup. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Coverage Report
File Coverage
|
||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
🟢 Approval recommended
The focused change restricts token delivery as intended, with relevant tests and no unresolved blocking findings.
No open issues 🎉
What changed in this PR
Restricts OAuth token delivery to explicitly allowlisted web-app origins, replacing wildcard delivery.
Changes:
- Adds validated
httpApi.webOriginsconfiguration with an empty default. - Sends tokens only to configured origins and warns when none are configured.
- Adds callback tests for origin targeting, empty configuration, and missing users.
Stage and production must configure trusted web origins before deployment.
| File | Description |
|---|---|
| src/presentation/http/router/oauth.ts | Restricts token delivery and adds an empty-list warning. |
| src/presentation/http/router/oauth.test.ts | Tests callback delivery and missing-user behavior. |
| src/presentation/http/http-api.ts | Passes configured origins to the OAuth router. |
| src/infrastructure/config/index.ts | Validates exact origins and defaults to an empty list. |
| app-config.yaml | Allowlists the local development web origin. |
Review effort: Balanced
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The page served by
/oauth/google/callbacksent the new access and refresh tokens withwindow.opener.postMessage(..., '*'), so any page that opened the login popup received them. For a user who had already consented to Google login, that is enough to take over the account.Changes
httpApi.webOrigins: a list of exact web-app origins. The schema rejects'*', paths and trailing slashes. The default is[], and the devapp-config.yamlsetshttp://localhost:5173.postMessageonce for each allowlisted origin. The browser delivers the message only when the opener's origin matches exactly. If the list is empty, the API logs a warning at startup.oauth.test.tsruns the router with Google stubbed out and executes the callback script against a fakewindow.opener. It checks which origins receive the message, the empty-list case, and the 404 case.Stage and production configs must set, for example:
Without it, Google login delivers no tokens: the popup closes and the user stays logged out. Do not add custom note hostnames to this list, because users choose them.
Follow-up (notes.web)
useAuth.tsaccepts any message that hasaccessTokenandrefreshToken. It should check thatevent.originis the API origin and thatevent.sourceis the popup.Checks
yarn lint,yarn typecheckandyarn testpass locally (9 files, 167 tests).🤖 Generated with Claude Code