Files
IdP/apps/frontend/lib/oauth-popup-bridge.ts
2026-06-30 09:11:55 +03:00

60 lines
1.6 KiB
TypeScript

export const ONE_TAP_MESSAGE_TYPE = 'lendry-sso-onetap';
export function parsePopupOAuthParams(searchParams: URLSearchParams) {
const display = searchParams.get('display');
const popupOrigin = searchParams.get('popup_origin');
if (display !== 'popup' || !popupOrigin?.trim()) {
return null;
}
try {
return { popupOrigin: new URL(popupOrigin.trim()).origin };
} catch {
return null;
}
}
export function postOneTapResult(popupOrigin: string, payload: Record<string, unknown>): boolean {
if (!window.opener || window.opener.closed) {
return false;
}
try {
window.opener.postMessage({ type: ONE_TAP_MESSAGE_TYPE, ...payload }, popupOrigin);
window.close();
return true;
} catch {
return false;
}
}
export function deliverOAuthPopupResult(
popupContext: { popupOrigin: string } | null,
redirectUrl: string
): 'popup' | 'redirect' {
if (!popupContext) {
return 'redirect';
}
const parsed = parseAuthorizationRedirect(redirectUrl);
const delivered = postOneTapResult(popupContext.popupOrigin, {
code: parsed.code ?? undefined,
state: parsed.state ?? undefined,
token: parsed.code ?? undefined,
error: parsed.error ?? undefined,
errorDescription: parsed.errorDescription ?? undefined
});
return delivered ? 'popup' : 'redirect';
}
export function parseAuthorizationRedirect(redirectUrl: string) {
const url = new URL(redirectUrl);
return {
code: url.searchParams.get('code'),
state: url.searchParams.get('state'),
error: url.searchParams.get('error'),
errorDescription: url.searchParams.get('error_description')
};
}