Adding CTE session transfer token example#2747
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughThe with-cte example now demonstrates Session Transfer Token requests and redemption through a protected API route, authenticated page, client form, dashboard navigation, and expanded setup and usage documentation. ChangesSession Transfer Token example
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant AgentBrowser
participant STTRoute
participant Auth0Client
participant TargetApp
AgentBrowser->>STTRoute: Submit subject token and target login URL
STTRoute->>Auth0Client: Request Session Transfer Token
Auth0Client-->>STTRoute: Return redirect URL and expiration
STTRoute-->>AgentBrowser: Display redirect URL
AgentBrowser->>TargetApp: Open redirect URL
TargetApp->>Auth0Client: Redeem session_transfer_token during login
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 6
🧹 Nitpick comments (3)
src/utils/session-transfer-helpers.ts (1)
117-133: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winSubstring matching on server error codes may over-classify unrelated errors.
errorCode.toLowerCase().includes("setactor")/.includes("session_transfer")will reclassify any future/unexpected error code that happens to contain those substrings (e.g. a generic error mentioning "session_transfer" in a description-derived code) asSETACTOR_REQUIRED/SESSION_TRANSFER_DISABLED, masking the realEXCHANGE_FAILEDcase callers would otherwise get. Worth confirming this matches the actual set of Auth0 CTE server error codes, or tightening to an allow-list of exact known codes.Can you confirm the exact set of server-side error codes returned for the
setActor-required andsession_transferdisabled cases (from the Auth0 CTE Action / tenant configuration), to validate whether substring matching is actually necessary here?🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/utils/session-transfer-helpers.ts` around lines 117 - 133, Tighten mapSttServerError to classify only the exact, documented Auth0 CTE server error codes for setActor-required and session-transfer-disabled cases. Remove broad substring matching, use an explicit allow-list if multiple known variants exist, and return null for all unrelated or unknown error codes.src/types/token-vault.ts (1)
235-244: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winConsider narrowing
issuedTokenType's type to match its documented contract.The doc comment states
issuedTokenTypeis "AlwaysTOKEN_TYPES.SESSION_TRANSFER_TOKEN. Branch on this, nottokenType," but the field is typed as plainstring, so TypeScript won't catch typos or incorrect comparisons when consumers branch on it.♻️ Suggested tightening
- issuedTokenType: string; + issuedTokenType: TOKEN_TYPES.SESSION_TRANSFER_TOKEN | string;🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/types/token-vault.ts` around lines 235 - 244, Narrow SessionTransferTokenResult.issuedTokenType from string to the specific TOKEN_TYPES.SESSION_TRANSFER_TOKEN type (or its corresponding literal type), preserving the documented invariant so consumers receive compile-time protection when branching on this field.src/server/custom-token-exchange.test.ts (1)
1225-1391: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winAdd STT-specific DPoP nonce retry coverage.
STT bypasses the standard token-response processor and uses a bespoke retry path. Test a first
use_dpop_nonceresponse followed by a successful nonce-bearing request to prevent this authentication path from regressing silently.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/server/custom-token-exchange.test.ts` around lines 1225 - 1391, Add a test in the “5.3: wire parameters” suite for requestSessionTransferToken that mocks an initial token-endpoint response requiring use_dpop_nonce, then verifies the retry includes the returned DPoP nonce and succeeds with the expected token response. Use the existing authClient, session setup, and server request interception patterns, and assert both the retry nonce and successful result.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@examples/with-cte/app/api/stt/route.ts`:
- Around line 41-72: Validate targetLoginUrl in the route handling around
auth0.buildSessionTransferRedirect against an environment-configured allowlist
of trusted target applications, returning 400 for malformed or disallowed URLs
before forwarding it. In examples/with-cte/app/api/stt/route.ts lines 41-72,
apply this validation at the existing URL-parsing point; in
examples/with-cte/README.md lines 98-107, document that targetLoginUrl must be
trusted and app-controlled and is restricted by this demo’s allowlist.
- Around line 41-46: Validate targetLoginUrl before passing it to
buildSessionTransferRedirect: parse it explicitly and require it to match a
small env-configured allowlist of trusted target applications, rejecting
malformed or non-allowlisted values with the existing 400 invalid_request
response. Update the route’s targetLoginUrl handling and the corresponding
redirect flow so no untrusted URL can receive the session transfer token,
including the additionally referenced lines.
- Around line 79-97: Update the status selection in the CustomTokenExchangeError
handling block to remove the dead ternary and assign status codes intentionally
by error type. Keep ACTOR_UNAVAILABLE as a 400 client/session error, and map
tenant or upstream configuration failures such as SETACTOR_REQUIRED,
SESSION_TRANSFER_DISABLED, and EXCHANGE_FAILED to the appropriate server or
upstream status.
In `@examples/with-cte/README.md`:
- Around line 98-107: Add a one-line warning to the Session Transfer
walkthrough’s step 3 that targetLoginUrl must be a trusted, app-controlled
endpoint and must not come from untrusted input. Also update the targetLoginUrl
validation in buildSessionTransferRedirect or the corresponding
app/api/stt/route.ts flow to enforce trusted destinations, preserving valid
registered CTE target URLs.
In `@src/server/auth-client.ts`:
- Around line 3473-3498: Correct the actor-refresh documentation to match the
fail-fast behavior of resolveActorFromSession: in src/server/auth-client.ts
lines 3473-3498 and src/server/client.ts lines 1237-1258, state that an expired
agent ID token throws ACTOR_UNAVAILABLE and must be refreshed by the caller or
replaced with options.actor; in src/errors/oauth-errors.ts lines 226-231, state
that any expired ID token triggers ACTOR_UNAVAILABLE regardless of refresh-token
availability.
In `@src/server/custom-token-exchange.test.ts`:
- Around line 1394-1416: Update the affected session-transfer-token tests,
including the test around “should not include the STT in any session-like field
on the result” and the corresponding case near the second referenced location,
to assert that the exchange succeeded and result is non-null before inspecting
its keys or properties. Keep the existing contract assertions unchanged after
this success check.
---
Nitpick comments:
In `@src/server/custom-token-exchange.test.ts`:
- Around line 1225-1391: Add a test in the “5.3: wire parameters” suite for
requestSessionTransferToken that mocks an initial token-endpoint response
requiring use_dpop_nonce, then verifies the retry includes the returned DPoP
nonce and succeeds with the expected token response. Use the existing
authClient, session setup, and server request interception patterns, and assert
both the retry nonce and successful result.
In `@src/types/token-vault.ts`:
- Around line 235-244: Narrow SessionTransferTokenResult.issuedTokenType from
string to the specific TOKEN_TYPES.SESSION_TRANSFER_TOKEN type (or its
corresponding literal type), preserving the documented invariant so consumers
receive compile-time protection when branching on this field.
In `@src/utils/session-transfer-helpers.ts`:
- Around line 117-133: Tighten mapSttServerError to classify only the exact,
documented Auth0 CTE server error codes for setActor-required and
session-transfer-disabled cases. Remove broad substring matching, use an
explicit allow-list if multiple known variants exist, and return null for all
unrelated or unknown error codes.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 166a97d2-3f16-43fd-8dde-ff9b01ea7e52
⛔ Files ignored due to path filters (1)
examples/with-cte/pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (17)
EXAMPLES.mdexamples/with-cte/README.mdexamples/with-cte/app/api/stt/route.tsexamples/with-cte/app/dashboard/page.tsxexamples/with-cte/app/stt/page.tsxexamples/with-cte/app/stt/session-transfer-form.tsxexamples/with-cte/next-env.d.tsexamples/with-cte/pnpm-workspace.yamlsrc/errors/oauth-errors.tssrc/server/auth-client.tssrc/server/client.tssrc/server/custom-token-exchange.test.tssrc/server/index.tssrc/types/index.tssrc/types/token-vault.tssrc/utils/session-transfer-helpers.test.tssrc/utils/session-transfer-helpers.ts
There was a problem hiding this comment.
Caution
Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.
Actionable comments posted: 6
🧹 Nitpick comments (3)
src/utils/session-transfer-helpers.ts (1)
117-133: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winSubstring matching on server error codes may over-classify unrelated errors.
errorCode.toLowerCase().includes("setactor")/.includes("session_transfer")will reclassify any future/unexpected error code that happens to contain those substrings (e.g. a generic error mentioning "session_transfer" in a description-derived code) asSETACTOR_REQUIRED/SESSION_TRANSFER_DISABLED, masking the realEXCHANGE_FAILEDcase callers would otherwise get. Worth confirming this matches the actual set of Auth0 CTE server error codes, or tightening to an allow-list of exact known codes.Can you confirm the exact set of server-side error codes returned for the
setActor-required andsession_transferdisabled cases (from the Auth0 CTE Action / tenant configuration), to validate whether substring matching is actually necessary here?🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/utils/session-transfer-helpers.ts` around lines 117 - 133, Tighten mapSttServerError to classify only the exact, documented Auth0 CTE server error codes for setActor-required and session-transfer-disabled cases. Remove broad substring matching, use an explicit allow-list if multiple known variants exist, and return null for all unrelated or unknown error codes.src/types/token-vault.ts (1)
235-244: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winConsider narrowing
issuedTokenType's type to match its documented contract.The doc comment states
issuedTokenTypeis "AlwaysTOKEN_TYPES.SESSION_TRANSFER_TOKEN. Branch on this, nottokenType," but the field is typed as plainstring, so TypeScript won't catch typos or incorrect comparisons when consumers branch on it.♻️ Suggested tightening
- issuedTokenType: string; + issuedTokenType: TOKEN_TYPES.SESSION_TRANSFER_TOKEN | string;🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/types/token-vault.ts` around lines 235 - 244, Narrow SessionTransferTokenResult.issuedTokenType from string to the specific TOKEN_TYPES.SESSION_TRANSFER_TOKEN type (or its corresponding literal type), preserving the documented invariant so consumers receive compile-time protection when branching on this field.src/server/custom-token-exchange.test.ts (1)
1225-1391: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winAdd STT-specific DPoP nonce retry coverage.
STT bypasses the standard token-response processor and uses a bespoke retry path. Test a first
use_dpop_nonceresponse followed by a successful nonce-bearing request to prevent this authentication path from regressing silently.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/server/custom-token-exchange.test.ts` around lines 1225 - 1391, Add a test in the “5.3: wire parameters” suite for requestSessionTransferToken that mocks an initial token-endpoint response requiring use_dpop_nonce, then verifies the retry includes the returned DPoP nonce and succeeds with the expected token response. Use the existing authClient, session setup, and server request interception patterns, and assert both the retry nonce and successful result.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@examples/with-cte/app/api/stt/route.ts`:
- Around line 41-72: Validate targetLoginUrl in the route handling around
auth0.buildSessionTransferRedirect against an environment-configured allowlist
of trusted target applications, returning 400 for malformed or disallowed URLs
before forwarding it. In examples/with-cte/app/api/stt/route.ts lines 41-72,
apply this validation at the existing URL-parsing point; in
examples/with-cte/README.md lines 98-107, document that targetLoginUrl must be
trusted and app-controlled and is restricted by this demo’s allowlist.
- Around line 41-46: Validate targetLoginUrl before passing it to
buildSessionTransferRedirect: parse it explicitly and require it to match a
small env-configured allowlist of trusted target applications, rejecting
malformed or non-allowlisted values with the existing 400 invalid_request
response. Update the route’s targetLoginUrl handling and the corresponding
redirect flow so no untrusted URL can receive the session transfer token,
including the additionally referenced lines.
- Around line 79-97: Update the status selection in the CustomTokenExchangeError
handling block to remove the dead ternary and assign status codes intentionally
by error type. Keep ACTOR_UNAVAILABLE as a 400 client/session error, and map
tenant or upstream configuration failures such as SETACTOR_REQUIRED,
SESSION_TRANSFER_DISABLED, and EXCHANGE_FAILED to the appropriate server or
upstream status.
In `@examples/with-cte/README.md`:
- Around line 98-107: Add a one-line warning to the Session Transfer
walkthrough’s step 3 that targetLoginUrl must be a trusted, app-controlled
endpoint and must not come from untrusted input. Also update the targetLoginUrl
validation in buildSessionTransferRedirect or the corresponding
app/api/stt/route.ts flow to enforce trusted destinations, preserving valid
registered CTE target URLs.
In `@src/server/auth-client.ts`:
- Around line 3473-3498: Correct the actor-refresh documentation to match the
fail-fast behavior of resolveActorFromSession: in src/server/auth-client.ts
lines 3473-3498 and src/server/client.ts lines 1237-1258, state that an expired
agent ID token throws ACTOR_UNAVAILABLE and must be refreshed by the caller or
replaced with options.actor; in src/errors/oauth-errors.ts lines 226-231, state
that any expired ID token triggers ACTOR_UNAVAILABLE regardless of refresh-token
availability.
In `@src/server/custom-token-exchange.test.ts`:
- Around line 1394-1416: Update the affected session-transfer-token tests,
including the test around “should not include the STT in any session-like field
on the result” and the corresponding case near the second referenced location,
to assert that the exchange succeeded and result is non-null before inspecting
its keys or properties. Keep the existing contract assertions unchanged after
this success check.
---
Nitpick comments:
In `@src/server/custom-token-exchange.test.ts`:
- Around line 1225-1391: Add a test in the “5.3: wire parameters” suite for
requestSessionTransferToken that mocks an initial token-endpoint response
requiring use_dpop_nonce, then verifies the retry includes the returned DPoP
nonce and succeeds with the expected token response. Use the existing
authClient, session setup, and server request interception patterns, and assert
both the retry nonce and successful result.
In `@src/types/token-vault.ts`:
- Around line 235-244: Narrow SessionTransferTokenResult.issuedTokenType from
string to the specific TOKEN_TYPES.SESSION_TRANSFER_TOKEN type (or its
corresponding literal type), preserving the documented invariant so consumers
receive compile-time protection when branching on this field.
In `@src/utils/session-transfer-helpers.ts`:
- Around line 117-133: Tighten mapSttServerError to classify only the exact,
documented Auth0 CTE server error codes for setActor-required and
session-transfer-disabled cases. Remove broad substring matching, use an
explicit allow-list if multiple known variants exist, and return null for all
unrelated or unknown error codes.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 166a97d2-3f16-43fd-8dde-ff9b01ea7e52
⛔ Files ignored due to path filters (1)
examples/with-cte/pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (17)
EXAMPLES.mdexamples/with-cte/README.mdexamples/with-cte/app/api/stt/route.tsexamples/with-cte/app/dashboard/page.tsxexamples/with-cte/app/stt/page.tsxexamples/with-cte/app/stt/session-transfer-form.tsxexamples/with-cte/next-env.d.tsexamples/with-cte/pnpm-workspace.yamlsrc/errors/oauth-errors.tssrc/server/auth-client.tssrc/server/client.tssrc/server/custom-token-exchange.test.tssrc/server/index.tssrc/types/index.tssrc/types/token-vault.tssrc/utils/session-transfer-helpers.test.tssrc/utils/session-transfer-helpers.ts
🛑 Comments failed to post (6)
examples/with-cte/app/api/stt/route.ts (3)
41-46: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
targetLoginUrlis untrusted client input but is used exactly as the SDK warns against.
body.targetLoginUrlcomes straight from the request body and is passed unchecked intobuildSessionTransferRedirect, which embeds the freshly-minted, one-shot Session Transfer Token into the redirectLocationheader for that URL. The SDK's own docs forbuildSessionTransferRedirectstate the target "Must be a trusted, app-controlled value. Never derive this from untrusted input." — this route does precisely that, meaning a caller can redirect (and leak) a live impersonation token to any domain of their choosing. Separately, a malformed URL here throws insidenew URL(...), which isn't aCustomTokenExchangeError, so it falls into the generic 500 handler instead of a 400.Restrict
targetLoginUrlto a small allowlist (e.g. an env-configured set of trusted target apps) and validate it explicitly before use, returning 400 for both "not in allowlist" and "malformed URL".🔒 Suggested validation
+const ALLOWED_TARGET_LOGIN_URLS = (process.env.ALLOWED_TARGET_LOGIN_URLS ?? "") + .split(",") + .map((u) => u.trim()) + .filter(Boolean); + if (!body.targetLoginUrl) { return NextResponse.json( { code: "invalid_request", message: "targetLoginUrl is required." }, { status: 400 } ); } + + let targetUrl: URL; + try { + targetUrl = new URL(body.targetLoginUrl); + } catch { + return NextResponse.json( + { code: "invalid_request", message: "targetLoginUrl must be a valid URL." }, + { status: 400 } + ); + } + if (!ALLOWED_TARGET_LOGIN_URLS.includes(targetUrl.origin)) { + return NextResponse.json( + { code: "invalid_request", message: "targetLoginUrl is not an allowed target." }, + { status: 400 } + ); + }Also applies to: 63-72
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@examples/with-cte/app/api/stt/route.ts` around lines 41 - 46, Validate targetLoginUrl before passing it to buildSessionTransferRedirect: parse it explicitly and require it to match a small env-configured allowlist of trusted target applications, rejecting malformed or non-allowlisted values with the existing 400 invalid_request response. Update the route’s targetLoginUrl handling and the corresponding redirect flow so no untrusted URL can receive the session transfer token, including the additionally referenced lines.
41-72: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
targetLoginUrlis treated as trusted input in both the code and the walkthrough that teaches it, contradicting the SDK's own security warning. The SDK'sbuildSessionTransferRedirectdocs state the target URL "must be a trusted, app-controlled value" and must never come from untrusted input, yet the demo takes it directly from the client request body/form with no validation or caveat, letting a caller redirect (and leak) a live one-shot impersonation token to an arbitrary destination.
examples/with-cte/app/api/stt/route.ts#L41-L72: validatetargetLoginUrlagainst an allowlist (e.g. an env-configured set of trusted target apps) and return 400 for both malformed and disallowed values, instead of forwarding it unchecked intobuildSessionTransferRedirect.examples/with-cte/README.md#L98-L107: add a caveat in the walkthrough noting thattargetLoginUrlmust be a trusted, app-controlled value and is restricted in this demo for that reason.📍 Affects 2 files
examples/with-cte/app/api/stt/route.ts#L41-L72(this comment)examples/with-cte/README.md#L98-L107🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@examples/with-cte/app/api/stt/route.ts` around lines 41 - 72, Validate targetLoginUrl in the route handling around auth0.buildSessionTransferRedirect against an environment-configured allowlist of trusted target applications, returning 400 for malformed or disallowed URLs before forwarding it. In examples/with-cte/app/api/stt/route.ts lines 41-72, apply this validation at the existing URL-parsing point; in examples/with-cte/README.md lines 98-107, document that targetLoginUrl must be trusted and app-controlled and is restricted by this demo’s allowlist.
79-97: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Dead ternary — both branches return the same status.
err.code === CustomTokenExchangeErrorCode.ACTOR_UNAVAILABLE ? 400 : 400always evaluates to400; the conditional has no effect. This reads like an incomplete edit — likely meant to differentiateACTOR_UNAVAILABLE(client/session issue → 400) from tenant-config failures likeSETACTOR_REQUIRED/SESSION_TRANSFER_DISABLED/EXCHANGE_FAILED(arguably 500/502, since they indicate upstream Action/tenant misconfiguration rather than bad client input).🐛 Suggested fix
- const status = - err.code === CustomTokenExchangeErrorCode.ACTOR_UNAVAILABLE ? 400 : 400; + const status = + err.code === CustomTokenExchangeErrorCode.EXCHANGE_FAILED || + err.code === CustomTokenExchangeErrorCode.SETACTOR_REQUIRED || + err.code === CustomTokenExchangeErrorCode.SESSION_TRANSFER_DISABLED + ? 500 + : 400;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.} catch (err: unknown) { if (err instanceof CustomTokenExchangeError) { const status = err.code === CustomTokenExchangeErrorCode.EXCHANGE_FAILED || err.code === CustomTokenExchangeErrorCode.SETACTOR_REQUIRED || err.code === CustomTokenExchangeErrorCode.SESSION_TRANSFER_DISABLED ? 500 : 400; return NextResponse.json( { code: err.code, message: err.message, cause: err.cause && typeof err.cause === "object" && "code" in err.cause ? { code: (err.cause as { code?: string }).code, message: (err.cause as { message?: string }).message } : undefined }, { status } ); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@examples/with-cte/app/api/stt/route.ts` around lines 79 - 97, Update the status selection in the CustomTokenExchangeError handling block to remove the dead ternary and assign status codes intentionally by error type. Keep ACTOR_UNAVAILABLE as a 400 client/session error, and map tenant or upstream configuration failures such as SETACTOR_REQUIRED, SESSION_TRANSFER_DISABLED, and EXCHANGE_FAILED to the appropriate server or upstream status.examples/with-cte/README.md (1)
98-107: 🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win
Walkthrough doesn't warn that
targetLoginUrlmust be a trusted value.Step 3 tells the reader to type any target login URL into the form, with no note that this must be a trusted, app-controlled endpoint (the SDK's own
buildSessionTransferRedirectdocs explicitly warn against deriving it from untrusted input). Worth a one-line caveat here, alongside fixing the underlying validation gap inapp/api/stt/route.ts.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@examples/with-cte/README.md` around lines 98 - 107, Add a one-line warning to the Session Transfer walkthrough’s step 3 that targetLoginUrl must be a trusted, app-controlled endpoint and must not come from untrusted input. Also update the targetLoginUrl validation in buildSessionTransferRedirect or the corresponding app/api/stt/route.ts flow to enforce trusted destinations, preserving valid registered CTE target URLs.src/server/auth-client.ts (1)
3473-3498: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Actor-refresh documentation is inconsistent with the actual (fail-fast) behavior across three files. All three sites describe
requestSessionTransferToken's actor resolution as if an expired agent ID token gets auto-refreshed, butresolveActorFromSession(per the provided helper source) only checks the current session'sexpclaim and immediately throwsACTOR_UNAVAILABLEtelling the caller to refresh manually — there is no refresh attempt, regardless of refresh-token availability.
src/server/auth-client.ts#L3473-L3498: reword line 3481 ("The actor is sourced from the agent session's ID token (refreshed if expired).") to state that an expired ID token throwsACTOR_UNAVAILABLEand must be refreshed by the caller or overridden viaoptions.actor.src/server/client.ts#L1237-L1258: reword line 1242 ("The actor defaults to the agent session's ID token (refreshed if expired).") the same way.src/errors/oauth-errors.ts#L226-L231: reword theACTOR_UNAVAILABLEdoc's "missing or expired with no refresh token" phrasing to avoid implying refresh-token-conditional auto-refresh; state plainly that any expired ID token triggers this error regardless of refresh-token presence.📍 Affects 3 files
src/server/auth-client.ts#L3473-L3498(this comment)src/server/client.ts#L1237-L1258src/errors/oauth-errors.ts#L226-L231🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/server/auth-client.ts` around lines 3473 - 3498, Correct the actor-refresh documentation to match the fail-fast behavior of resolveActorFromSession: in src/server/auth-client.ts lines 3473-3498 and src/server/client.ts lines 1237-1258, state that an expired agent ID token throws ACTOR_UNAVAILABLE and must be refreshed by the caller or replaced with options.actor; in src/errors/oauth-errors.ts lines 226-231, state that any expired ID token triggers ACTOR_UNAVAILABLE regardless of refresh-token availability.src/server/custom-token-exchange.test.ts (1)
1394-1416: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Assert success before checking absent properties.
Both tests can pass with a
nullresult, so exchange failures would not fail the intended contract checks.Proposed fix
-const [, result] = await authClient.requestSessionTransferToken( +const [error, result] = await authClient.requestSessionTransferToken( ... ); +expect(error).toBeNull(); +expect(result).not.toBeNull(); -const [, response] = await authClient.customTokenExchange({ +const [error, response] = await authClient.customTokenExchange({ ... }); +expect(error).toBeNull(); +expect(response).not.toBeNull();Also applies to: 1629-1636
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/server/custom-token-exchange.test.ts` around lines 1394 - 1416, Update the affected session-transfer-token tests, including the test around “should not include the STT in any session-like field on the result” and the corresponding case near the second referenced location, to assert that the exchange succeeded and result is non-null before inspecting its keys or properties. Keep the existing contract assertions unchanged after this success check.
65af9ff to
4e50dcd
Compare
10c6841 to
670003f
Compare
0aecb22 to
45eb74f
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@examples/with-cte/app/api/stt/route.ts`:
- Around line 46-64: Validate that the parsed result in the request-body
handling flow is a non-null object before accessing subjectToken or
subjectTokenType. Return the existing invalid_request 400 response for null and
other non-object JSON bodies, while preserving the current required-field
validation for valid objects.
- Around line 137-164: Update the error branch in the route handler to classify
errors by a guarded object check and string-valued error.code, rather than
instanceof CustomTokenExchangeError. Use the validated code to map
CustomTokenExchangeErrorCode values to the existing 400/500 statuses, while
preserving the current response fields and cause handling.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: eab257a8-5bed-408c-a34a-6f5085892c7b
📒 Files selected for processing (6)
examples/with-cte/.gitignoreexamples/with-cte/README.mdexamples/with-cte/app/api/stt/route.tsexamples/with-cte/app/dashboard/page.tsxexamples/with-cte/app/stt/page.tsxexamples/with-cte/app/stt/session-transfer-form.tsx
🚧 Files skipped from review as they are similar to previous changes (3)
- examples/with-cte/app/stt/page.tsx
- examples/with-cte/app/stt/session-transfer-form.tsx
- examples/with-cte/README.md
📋 Changes
Adds a Session Transfer Token (STT) demo to the
examples/with-cteexample — the initiator flow where an authenticated agent establishes a web session as a customer in a target app, without the customer's password.What this example validates
auth0.requestSessionTransferToken()mints a one-shot STT, sourcing the actor from the agent's session ID token.auth0.buildSessionTransferRedirect()builds the redirect that carries the STT to the target app's login URL.actclaim (sub= customer,act.sub= agent, no refresh token).How to run
See the example README for setup and step-by-step instructions:
examples/with-cte/README.md📎 References
feat/cte-session-transfer-token🎯 Testing
Manual, end-to-end against a live tenant following
examples/with-cte/README.md. Verified: silent STT redemption, session established as the impersonated customer withact.sub= agent, and no refresh token issued.Summary by CodeRabbit
New Features
Documentation
Chores
.gitignore.