Skip to content

Commit badcd7c

Browse files
committed
wip gate transit code exchange in the frontend only in embedded context
1 parent f9bba6a commit badcd7c

3 files changed

Lines changed: 29 additions & 4 deletions

File tree

src/frontend/src/features/auth/api/exchangeAccessToken.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import { fetchApi } from '@/api/fetchApi'
22
import { setAccessToken } from '@/stores/accessToken'
3-
import { consumeTransitCodeFromFragment } from '../utils/transitCode'
3+
import {
4+
consumeTransitCodeFromFragment,
5+
isEmbedded,
6+
} from '../utils/transitCode'
47

58
type ApiAccessToken = {
69
access_token: string
@@ -28,6 +31,11 @@ const runInitialization = async (): Promise<void> => {
2831
return
2932
}
3033

34+
if (!isEmbedded()) {
35+
console.warn('Transit code ignored outside an embedded context')
36+
return
37+
}
38+
3139
try {
3240
const { access_token } = await exchangeAccessToken(code)
3341
setAccessToken(access_token)

src/frontend/src/features/auth/components/TransitCodeGate.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,13 @@ export const TransitCodeGate = ({
2323
}) => {
2424
const hash = useHash()
2525

26-
// Latch the decision on the initial hash: the bootstrap scrubs the
27-
// fragment as soon as it starts, and the gate must not flip back to the
28-
// fast path while the exchange is still in flight.
26+
// Note: the exchange only happens in an embedding context. This check lives
27+
// in initializeAccessTokenFromFragment, the single funnel for all bootstrap paths.
28+
// The gate still mounts top-level to scrub the fragment, but bootstrap then resolves
29+
// immediately without exchanging.
30+
//
31+
// Latch the decision on the initial hash: bootstrap scrubs it immediately, and the
32+
// gate must not switch back to the fast path while the exchange is in flight.
2933
const [needsExchange] = useState(() => hasTransitCodeInFragment(hash))
3034

3135
if (!needsExchange) {

src/frontend/src/features/auth/utils/transitCode.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
const TRANSIT_CODE_FRAGMENT_PARAM = 'transit_code'
22

3+
/**
4+
* Whether the app is rendered inside an embedding context (iframe).
5+
*
6+
* Comparing window references never throws, even when the parent is
7+
* cross-origin. Defaults to false outside a browser environment.
8+
*/
9+
export const isEmbedded = (): boolean => {
10+
if (typeof window === 'undefined') {
11+
return false
12+
}
13+
return window.self !== window.top
14+
}
15+
316
/**
417
* Whether a URL fragment carries a transit code. Pure check, does not
518
* consume anything.

0 commit comments

Comments
 (0)