fix: Fix multiple bugs with new authentication flow

This commit is contained in:
2026-06-07 15:04:21 +02:00
parent 9fc26b1ccf
commit 83456c018c
137 changed files with 4710 additions and 281 deletions

View File

@@ -8,10 +8,88 @@ import {
import { UsersActions } from '../../../../store/users/users.actions';
import type { User } from '../../../../shared-kernel';
export const DEFAULT_POST_AUTH_URL = '/dashboard';
const AUTH_ROUTE_PATHS = new Set(['/login', '/register']);
const MAX_RETURN_URL_DEPTH = 10;
export type AuthenticationOutcome =
| { kind: 'success'; user: User }
| { kind: 'failure'; error: string };
export function isAuthRoutePath(path: string): boolean {
return AUTH_ROUTE_PATHS.has(path);
}
export function getRoutePathFromUrl(url: string): string {
if (!url) {
return '/';
}
const [path] = url.split(/[?#]/, 1);
return path || '/';
}
export function extractReturnUrlParam(url: string): string | null {
const queryStart = url.indexOf('?');
if (queryStart === -1) {
return null;
}
const hashStart = url.indexOf('#', queryStart + 1);
const query = hashStart === -1
? url.slice(queryStart + 1)
: url.slice(queryStart + 1, hashStart);
return new URLSearchParams(query).get('returnUrl');
}
export function resolveSafeReturnUrl(
url: string | null | undefined,
fallback = DEFAULT_POST_AUTH_URL
): string {
let candidate = url?.trim() ?? '';
let depth = 0;
while (candidate && depth < MAX_RETURN_URL_DEPTH) {
if (!candidate.startsWith('/') || candidate.startsWith('//')) {
return fallback;
}
const path = getRoutePathFromUrl(candidate);
if (!isAuthRoutePath(path)) {
return candidate;
}
const nestedReturnUrl = extractReturnUrlParam(candidate)?.trim();
if (!nestedReturnUrl) {
return fallback;
}
candidate = nestedReturnUrl;
depth += 1;
}
return fallback;
}
export function buildLoginReturnQueryParams(
currentUrl: string,
fallback = DEFAULT_POST_AUTH_URL
): { returnUrl?: string } {
const safeReturnUrl = resolveSafeReturnUrl(currentUrl, fallback);
if (safeReturnUrl === fallback) {
return {};
}
return { returnUrl: safeReturnUrl };
}
export function waitForAuthenticationOutcome(
actions$: Observable<{ type: string; user?: User; error?: string }>
): Observable<AuthenticationOutcome> {