dify/web/service/__tests__/base.spec.ts
Coding On Star c68e5e5ed3
fix(auth): prevent open redirects in post-login flows (#38864)
Co-authored-by: CodingOnStar <hanxujiang@dify.com>
2026-07-13 10:11:36 +00:00

104 lines
2.9 KiB
TypeScript

import {
buildSigninUrlWithRedirect,
buildWebAppSigninUrlWithRedirect,
isWebAppSigninPath,
} from '../base'
vi.mock('@/utils/var', () => ({
basePath: '/app',
API_PREFIX: '/console/api',
PUBLIC_API_PREFIX: '/api',
IS_CE_EDITION: false,
}))
describe('buildSigninUrlWithRedirect', () => {
const originalLocation = globalThis.location
beforeEach(() => {
Object.defineProperty(globalThis, 'location', {
value: {
origin: 'https://example.com',
pathname: '/apps',
href: 'https://example.com/apps',
},
writable: true,
configurable: true,
})
})
afterEach(() => {
Object.defineProperty(globalThis, 'location', {
value: originalLocation,
writable: true,
configurable: true,
})
})
it('should return plain signin URL for non-OAuth pages', () => {
const url = buildSigninUrlWithRedirect()
expect(url).toBe('https://example.com/app/signin')
})
it('should append redirect_url for OAuth authorize pages', () => {
const oauthHref = 'https://example.com/account/oauth/authorize?client_id=abc&state=xyz'
Object.defineProperty(globalThis, 'location', {
value: {
origin: 'https://example.com',
pathname: '/account/oauth/authorize',
href: oauthHref,
},
writable: true,
configurable: true,
})
const url = buildSigninUrlWithRedirect()
expect(url).toBe(`https://example.com/app/signin?redirect_url=${encodeURIComponent(oauthHref)}`)
})
it('should not include redirect_url for other paths containing partial match', () => {
Object.defineProperty(globalThis, 'location', {
value: {
origin: 'https://example.com',
pathname: '/settings/oauth',
href: 'https://example.com/settings/oauth',
},
writable: true,
configurable: true,
})
const url = buildSigninUrlWithRedirect()
expect(url).toBe('https://example.com/app/signin')
})
})
describe('buildWebAppSigninUrlWithRedirect', () => {
it('should encode the internal redirect target exactly once', () => {
const url = buildWebAppSigninUrlWithRedirect(
'https://example.com',
'/chatbot/share-app',
'?foo=bar',
)
expect(url).toBe(
'https://example.com/app/webapp-signin?redirect_url=%2Fchatbot%2Fshare-app%3Ffoo%3Dbar',
)
expect(new URL(url).searchParams.get('redirect_url')).toBe('/chatbot/share-app?foo=bar')
})
})
describe('isWebAppSigninPath', () => {
it.each(['/app/webapp-signin', '/app/webapp-signin/'])(
'should recognize the web app signin route behind basePath: %s',
(pathname) => {
expect(isWebAppSigninPath(pathname)).toBe(true)
},
)
it.each(['/webapp-signin', '/app/webapp-signin-extra', '/app/webapp-signin/check-code'])(
'should not match a different path: %s',
(pathname) => {
expect(isWebAppSigninPath(pathname)).toBe(false)
},
)
})