import { afterAll, describe, expect, it } from 'vitest' import { buildOAuthCallbackReturnTo, parseOAuthCallbackHash, sanitizeAuthRedirect, validateOAuthUrl, } from './oauth' describe('oauth auth helpers', () => { it('sanitizes redirect paths to internal routes only', () => { expect(sanitizeAuthRedirect('/users')).toBe('/users') expect(sanitizeAuthRedirect('https://evil.example.com')).toBe('/dashboard') expect(sanitizeAuthRedirect('//evil.example.com')).toBe('/dashboard') expect(sanitizeAuthRedirect('users')).toBe('/dashboard') }) it('builds oauth callback return url on current origin', () => { expect(buildOAuthCallbackReturnTo('/users')).toBe('http://localhost:3000/login/oauth/callback?redirect=%2Fusers') }) it('parses oauth callback hash payload', () => { expect(parseOAuthCallbackHash('#status=success&code=abc&provider=github')).toEqual({ status: 'success', code: 'abc', provider: 'github', message: '', }) }) describe('validateOAuthUrl', () => { const originalOrigin = window.location.origin afterAll(() => { // 恢复原始 origin Object.defineProperty(window, 'location', { value: { origin: originalOrigin }, writable: true, }) }) it('allows same-origin URLs', () => { Object.defineProperty(window, 'location', { value: { origin: 'http://localhost:3000' }, writable: true, }) expect(validateOAuthUrl('http://localhost:3000/api/v1/auth/oauth/authorize')).toBe(true) }) it('allows trusted OAuth provider origins', () => { expect(validateOAuthUrl('https://github.com/login/oauth/authorize')).toBe(true) expect(validateOAuthUrl('https://google.com/oauth/authorize')).toBe(true) expect(validateOAuthUrl('https://facebook.com/v1.0/oauth/authorize')).toBe(true) }) it('rejects untrusted origins', () => { expect(validateOAuthUrl('https://evil.example.com/oauth/authorize')).toBe(false) expect(validateOAuthUrl('https://attacker.com/callback')).toBe(false) }) it('rejects invalid URLs', () => { expect(validateOAuthUrl('not-a-url')).toBe(false) expect(validateOAuthUrl('')).toBe(false) }) }) })