Auth: support token login in core — exchange a validated JWT for an httpOnly hdb-session cookie - #1546
Merged
Conversation
Extends the `login` operation / request.login() to accept a `token` in addition to username/password, and extends create_authentication_tokens with purpose: 'login' to mint it. The minted token carries subject:'login' instead of 'operation', so validateOperationToken's Bearer-API path rejects it automatically — it can't double as a standing API credential, only as a one-shot ticket the login endpoint trades for a session cookie. Closes #1544.
Contributor
|
Warning Gemini encountered an error creating the review. You can try again by commenting |
Contributor
|
Reviewed; no blockers found. |
dawsontoth
approved these changes
Jul 1, 2026
Per Dawson's review — the login-scoped token comes back in the same operation_token field instead of a new login_token field, so the create_authentication_tokens response shape doesn't change based on purpose.
Contributor
|
Saved HarperFast/studio#1408 so we can integrate this into Studio when supported. |
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.
Summary
Implements #1544. Studio wants direct (non-proxied) connections to instances for SSE/streaming (studio#1398) — native
EventSourcecan't send anAuthorizationheader, so cookie auth is the fit. This gives core the missing bridge: turn a validated JWT into an httpOnlyhdb-sessioncookie.request.login()/ theloginoperation now accept atokenalongside username/password. When given, it's validated and the resulting user is written into the session (existingrequest.session.update()— no new cookie machinery).create_authentication_tokens/createTokens()gainspurpose: 'login': mints a single short-lived (1mdefault, override viaexpires_in) token instead of an operation+refresh pair, and skips the refresh-token DB write / user-change broadcast that pair triggers.Design decision taken
The issue flagged one open call: reuse a full operation token for the exchange, vs. mint a purpose-scoped token rejected by the Bearer-API path. I went with the recommended purpose-scoped option — the login token is signed with
subject: 'login'instead of'operation', sovalidateOperationToken'sjwt.verify(..., { subject: 'operation' })rejects it on asubmismatch with no extra code, andvalidateLoginTokenis the only thing that accepts it. This means the exchange ticket can't be replayed as a general API credential even if it leaked (e.g. in a log line) — confirmed in the new tests below (log lines literally readjwt subject invalid).CSRF posture (design point 3) is unchanged: the cookie is still origin-prefixed per the existing mechanism, regardless of how the session was established.
Testing
unitTests/security/tokenAuthentication.test.js— 8 new cases:purpose: 'login'mints a login-only token with no refresh-token side effects;validateLoginTokenhappy/inactive-user/non-existent-user/bad/expired paths; and the two cross-subject rejection cases (operation token rejected byvalidateLoginToken, login token rejected byvalidateOperationToken).integrationTests/apiTests/authentication.test.mjs— 2 new end-to-end cases: mint a login token →loginop → session cookie set; and a login token sent asAuthorization: Bearer→ 401.tsc --noEmitclean, full build clean, both touched unit-test files green (39/39, 31/31), both touched integration suites green (15/15, 9/9).🤖 Generated with Claude Code