mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-10-31 08:13:50 +00:00
62 lines
2.7 KiB
TypeScript
62 lines
2.7 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import { MOBILE_HANDOFF_REDIRECT_URI, buildMobileHandoffUrl, mobileHandoffTarget, signedInLoginAction } from '@/lib/auth/mobile-handoff';
|
|
|
|
// The login page handed the typed password (and the SSO callback the tokens)
|
|
// to any `bulwarkmobile://` URL named in the query string, with nothing on
|
|
// screen to tell the page apart from a normal sign-in. The target is now the
|
|
// app's one callback link, and the pages confirm with the user before they
|
|
// navigate (components/auth/mobile-handoff-consent.tsx).
|
|
|
|
describe('mobileHandoffTarget', () => {
|
|
it('accepts only the mobile app callback link', () => {
|
|
expect(mobileHandoffTarget('bulwarkmobile://auth/callback')).toBe(MOBILE_HANDOFF_REDIRECT_URI);
|
|
expect(mobileHandoffTarget(' bulwarkmobile://auth/callback/ ')).toBe(MOBILE_HANDOFF_REDIRECT_URI);
|
|
});
|
|
|
|
it.each([
|
|
'bulwarkmobile://x',
|
|
'bulwarkmobile://auth/callback?x=1',
|
|
'bulwarkmobile://auth/callback#frag',
|
|
'bulwarkmobile://evil.example/auth/callback',
|
|
'https://evil.example/',
|
|
'javascript:alert(1)',
|
|
'',
|
|
null,
|
|
undefined,
|
|
])('refuses %s', (raw) => {
|
|
expect(mobileHandoffTarget(raw)).toBe('');
|
|
});
|
|
});
|
|
|
|
describe('buildMobileHandoffUrl', () => {
|
|
it('puts the material in the fragment, encoded', () => {
|
|
const url = buildMobileHandoffUrl(MOBILE_HANDOFF_REDIRECT_URI, { flow: 'password', password: 'p&ss#1', state: 's' });
|
|
expect(url.startsWith('bulwarkmobile://auth/callback#')).toBe(true);
|
|
expect(url).toContain('password=p%26ss%231');
|
|
expect(url.split('#')).toHaveLength(2);
|
|
});
|
|
});
|
|
|
|
// The app's "Sign in via webmail" opens the login page in the system browser.
|
|
// When that browser already had a webmail session (the user reads mail in
|
|
// Safari, or signed out of the app after an earlier hand-off), the page sent
|
|
// the session to the mailbox and the app never got a sign-in: the user was
|
|
// left in the webmail's inbox inside the app's sign-in sheet.
|
|
describe('signedInLoginAction', () => {
|
|
it('keeps the form for a hand-off opened by a signed-in browser', () => {
|
|
expect(signedInLoginAction({ isMobileHandoff: true, isAddAccountMode: false, hasHandoffPayload: false })).toBe('stay');
|
|
});
|
|
|
|
it('hands over a sign-in that just happened on the page', () => {
|
|
expect(signedInLoginAction({ isMobileHandoff: true, isAddAccountMode: false, hasHandoffPayload: true })).toBe('handoff');
|
|
});
|
|
|
|
it('opens the mailbox after a normal sign-in', () => {
|
|
expect(signedInLoginAction({ isMobileHandoff: false, isAddAccountMode: false, hasHandoffPayload: false })).toBe('mailbox');
|
|
});
|
|
|
|
it('leaves add-account mode alone', () => {
|
|
expect(signedInLoginAction({ isMobileHandoff: false, isAddAccountMode: true, hasHandoffPayload: false })).toBe('none');
|
|
});
|
|
});
|