fix(review): harden payment, oauth, and migration paths
This commit is contained in:
@@ -173,20 +173,12 @@ describe('oauth adoption auth api', () => {
|
||||
expect(hasPendingOAuthSuggestedProfile({})).toBe(false)
|
||||
})
|
||||
|
||||
it('prepares an oauth bind access token cookie before redirect binding', async () => {
|
||||
it('requests an HttpOnly oauth bind cookie before redirect binding', async () => {
|
||||
localStorage.setItem('auth_token', 'access-token-value')
|
||||
const setCookie = vi.fn()
|
||||
Object.defineProperty(document, 'cookie', {
|
||||
configurable: true,
|
||||
get: () => '',
|
||||
set: setCookie
|
||||
})
|
||||
|
||||
const { prepareOAuthBindAccessTokenCookie } = await import('@/api/auth')
|
||||
|
||||
prepareOAuthBindAccessTokenCookie()
|
||||
await prepareOAuthBindAccessTokenCookie()
|
||||
|
||||
expect(setCookie).toHaveBeenCalledTimes(1)
|
||||
expect(setCookie.mock.calls[0]?.[0]).toContain('oauth_bind_access_token=access-token-value')
|
||||
expect(post).toHaveBeenCalledWith('/auth/oauth/bind-token')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -278,33 +278,11 @@ export function persistOAuthTokenContext(tokens: Partial<OAuthTokenResponse>): v
|
||||
}
|
||||
}
|
||||
|
||||
export function prepareOAuthBindAccessTokenCookie(): void {
|
||||
if (typeof document === 'undefined' || typeof window === 'undefined') {
|
||||
export async function prepareOAuthBindAccessTokenCookie(): Promise<void> {
|
||||
if (!getAuthToken()) {
|
||||
return
|
||||
}
|
||||
|
||||
const token = getAuthToken()
|
||||
if (!token) {
|
||||
return
|
||||
}
|
||||
|
||||
const secure = window.location.protocol === 'https:' ? '; Secure' : ''
|
||||
const path = resolveOAuthBindCookiePath()
|
||||
document.cookie =
|
||||
`oauth_bind_access_token=${encodeURIComponent(token)}; Path=${path}/auth/oauth; Max-Age=600; SameSite=Lax${secure}`
|
||||
}
|
||||
|
||||
function resolveOAuthBindCookiePath(): string {
|
||||
const apiBase = ((import.meta.env.VITE_API_BASE_URL as string | undefined) || '/api/v1').replace(/\/$/, '')
|
||||
|
||||
try {
|
||||
return new URL(apiBase, window.location.origin).pathname.replace(/\/$/, '') || '/api/v1'
|
||||
} catch {
|
||||
if (apiBase.startsWith('/')) {
|
||||
return apiBase
|
||||
}
|
||||
return '/api/v1'
|
||||
}
|
||||
await apiClient.post('/auth/oauth/bind-token')
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -153,10 +153,10 @@ export function buildOAuthBindingStartURL(
|
||||
return `${normalized}/auth/oauth/${provider}/start?${params.toString()}`
|
||||
}
|
||||
|
||||
export function startOAuthBinding(
|
||||
export async function startOAuthBinding(
|
||||
provider: BindableOAuthProvider,
|
||||
options: BuildOAuthBindingStartURLOptions = {}
|
||||
): void {
|
||||
): Promise<void> {
|
||||
if (typeof window === 'undefined') {
|
||||
return
|
||||
}
|
||||
@@ -164,7 +164,7 @@ export function startOAuthBinding(
|
||||
if (!startURL) {
|
||||
return
|
||||
}
|
||||
prepareOAuthBindAccessTokenCookie()
|
||||
await prepareOAuthBindAccessTokenCookie()
|
||||
window.location.href = startURL
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user