mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-18 05:25:40 +09:00
feat: use client-provided SSO redirectUri (#1155)
Co-authored-by: Hampus <[email protected]>
This commit is contained in:
1 parent
b80d41a7bf
commit
a45693f581
7 files changed
+92
-19
No files matched your search
@@ -29,6 +29,13 @@ interface SsoStatusResponse {
|
||||
enabled: boolean;
|
||||
enforced: boolean;
|
||||
display_name?: string;
|
||||
redirect_uri: string;
|
||||
}
|
||||
|
||||
function getAuthorizationUrlParam(authorizationUrlString: string, param: string): string | null {
|
||||
const queryStart = authorizationUrlString.indexOf('?');
|
||||
if (queryStart === -1) return null;
|
||||
return new URLSearchParams(authorizationUrlString.slice(queryStart + 1)).get(param);
|
||||
}
|
||||
|
||||
describe('Auth SSO flow', () => {
|
||||
@@ -130,6 +137,7 @@ describe('Auth SSO flow', () => {
|
||||
expect(authUrlString).toContain('code_challenge_method=S256');
|
||||
expect(authUrlString).toContain('code_challenge=');
|
||||
expect(authUrlString).toContain('nonce=');
|
||||
expect(getAuthorizationUrlParam(authUrlString, 'redirect_uri')).toBe(startData.redirect_uri);
|
||||
if (authUrlString.startsWith('http://') || authUrlString.startsWith('https://')) {
|
||||
const authUrl = new URL(authUrlString);
|
||||
const stateParam = authUrl.searchParams.get('state');
|
||||
@@ -151,6 +159,7 @@ describe('Auth SSO flow', () => {
|
||||
.execute();
|
||||
expect(completeData.token).toBeTruthy();
|
||||
expect(completeData.user_id).toBeTruthy();
|
||||
expect(completeData.redirect_to).toBe('/me');
|
||||
const meData = await createBuilder<{
|
||||
email: string | null;
|
||||
}>(harness, completeData.token)
|
||||
@@ -170,6 +179,34 @@ describe('Auth SSO flow', () => {
|
||||
expect(startData.redirect_uri).not.toContain('evil.example');
|
||||
expect(startData.authorization_url).toContain(encodeURIComponent(startData.redirect_uri));
|
||||
});
|
||||
it('uses the requested mobile SSO redirect URI without changing the post-login redirect', async () => {
|
||||
const startData = await createBuilderWithoutAuth<SsoStartResponse>(harness)
|
||||
.post('/auth/sso/start')
|
||||
.body({
|
||||
redirect_to: '/me',
|
||||
redirect_uri: 'fluxer://auth/sso/callback',
|
||||
})
|
||||
.execute();
|
||||
expect(startData.redirect_uri).toBe('fluxer://auth/sso/callback');
|
||||
expect(getAuthorizationUrlParam(startData.authorization_url, 'redirect_uri')).toBe('fluxer://auth/sso/callback');
|
||||
const email = `sso-mobile-redirect-${Date.now()}@example.com`;
|
||||
const completeData = await createBuilderWithoutAuth<SsoCompleteResponse>(harness)
|
||||
.post('/auth/sso/complete')
|
||||
.body({
|
||||
code: email,
|
||||
state: startData.state,
|
||||
})
|
||||
.execute();
|
||||
expect(completeData.token).toBeTruthy();
|
||||
expect(completeData.redirect_to).toBe('/me');
|
||||
});
|
||||
it('rejects unapproved SSO redirect URIs', async () => {
|
||||
await createBuilderWithoutAuth(harness)
|
||||
.post('/auth/sso/start')
|
||||
.body({redirect_uri: 'https://evil.example/auth/sso/callback'})
|
||||
.expect(400, 'INVALID_FORM_BODY')
|
||||
.execute();
|
||||
});
|
||||
});
|
||||
describe('redirect validation', () => {
|
||||
let admin: TestAccount;
|
||||
|
||||
Reference in new issue
Block a user