Skip to content

Commit 8ac0c92

Browse files
committed
Align Ory proxy auth gate with provider
1 parent 3ec7f17 commit 8ac0c92

2 files changed

Lines changed: 33 additions & 7 deletions

File tree

src/proxy.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,11 @@ async function proxyCore(
4747
}
4848
}
4949

50-
// req.auth is truthy even when the session carries a RefreshTokenError, so we
51-
// must check session.error too — otherwise the auth-route guard treats a
52-
// poisoned session as "logged in" and ping-pongs the user between /dashboard
53-
// (redirects to /sign-in via getAuthContext()) and /sign-in (redirects back to
54-
// /dashboard via the proxy's authenticated-on-auth-route rule).
50+
// Match the Ory auth provider's AuthContext requirements. req.auth can be
51+
// truthy while missing the user id/access token, or while carrying a
52+
// RefreshTokenError; in those cases the server auth context is unauthenticated.
5553
function isSessionAuthenticated(session: Session | null): boolean {
56-
return !!session && !session.error
54+
return !!session?.user?.id && !!session.accessToken && !session.error
5755
}
5856

5957
// In Ory mode the Auth.js middleware wrapper populates req.auth and manages its

tests/unit/ory-proxy.test.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,10 @@ describe('Ory proxy auth routes', () => {
4949
})
5050

5151
it('redirects authenticated users from sign-in to the dashboard', async () => {
52-
authSession.current = { user: { id: 'user-id' } } as Session
52+
authSession.current = {
53+
user: { id: 'user-id' },
54+
accessToken: 'access-token',
55+
} as Session
5356

5457
const response = await proxy(request('/sign-in'), {} as NextFetchEvent)
5558

@@ -69,9 +72,34 @@ describe('Ory proxy auth routes', () => {
6972
expect(location).toContain('returnTo=%2Fdashboard%2Fterminal')
7073
})
7174

75+
it('treats sessions without an access token as unauthenticated on auth routes', async () => {
76+
authSession.current = {
77+
user: { id: 'user-id' },
78+
} as Session
79+
80+
const response = await proxy(request('/sign-in'), {} as NextFetchEvent)
81+
82+
expect(response.headers.get('location')).toContain(
83+
'/api/auth/oauth-start?intent=signin'
84+
)
85+
})
86+
87+
it('treats sessions without a user id as unauthenticated on auth routes', async () => {
88+
authSession.current = {
89+
accessToken: 'access-token',
90+
} as Session
91+
92+
const response = await proxy(request('/sign-in'), {} as NextFetchEvent)
93+
94+
expect(response.headers.get('location')).toContain(
95+
'/api/auth/oauth-start?intent=signin'
96+
)
97+
})
98+
7299
it('treats Auth.js error sessions as unauthenticated on auth routes', async () => {
73100
authSession.current = {
74101
user: { id: 'user-id' },
102+
accessToken: 'access-token',
75103
error: 'RefreshTokenError',
76104
} as Session
77105

0 commit comments

Comments
 (0)