1
0
forked from baron/baron-sso

userfront e2e 전체 테스트

This commit is contained in:
2026-05-29 08:19:34 +09:00
parent dc16958804
commit da01f63c54
22 changed files with 1439 additions and 103 deletions

View File

@@ -745,7 +745,7 @@ export type BulkUserItem = {
memo?: string;
emailDomain?: string;
};
metadata: Record<string, string>;
metadata: Record<string, unknown>;
};
export type BulkUserResult = {

View File

@@ -1,6 +1,7 @@
import { describe, expect, it } from "vitest";
import {
buildAdminAuthRedirectUris,
canStartBrowserPkceLogin,
resolveAdminPublicOrigin,
} from "./authConfig";
@@ -24,4 +25,39 @@ describe("admin auth config", () => {
"http://localhost:5173",
);
});
it("blocks browser PKCE login when WebCrypto is unavailable", () => {
expect(
canStartBrowserPkceLogin({
isSecureContext: false,
origin: "http://localhost:5173",
cryptoSubtleAvailable: false,
}),
).toBe(false);
expect(
canStartBrowserPkceLogin({
isSecureContext: true,
origin: "https://admin.example.test",
cryptoSubtleAvailable: false,
}),
).toBe(false);
});
it("allows trusted local and private-network origins only when WebCrypto is available", () => {
for (const origin of [
"http://localhost:5173",
"http://127.0.0.1:5173",
"http://host.docker.internal:5173",
"http://172.16.9.189:5173",
"http://192.168.0.20:5173",
]) {
expect(
canStartBrowserPkceLogin({
isSecureContext: false,
origin,
cryptoSubtleAvailable: true,
}),
).toBe(true);
}
});
});

View File

@@ -31,3 +31,58 @@ export function buildAdminAuthRedirectUris(
popupRedirectUri: `${publicOrigin}${ADMIN_AUTH_CALLBACK_PATH}`,
};
}
export type BrowserPkceLoginCheck = {
isSecureContext?: boolean;
origin?: string;
cryptoSubtleAvailable?: boolean;
};
const devTrustedPkceHosts = new Set([
"localhost",
"127.0.0.1",
"::1",
"host.docker.internal",
]);
function isPrivateIPv4(hostname: string) {
const parts = hostname.split(".").map((part) => Number.parseInt(part, 10));
if (
parts.length !== 4 ||
parts.some((part) => Number.isNaN(part) || part < 0 || part > 255)
) {
return false;
}
const [first, second] = parts;
return (
first === 10 ||
(first === 172 && second >= 16 && second <= 31) ||
(first === 192 && second === 168)
);
}
function isDevTrustedPkceOrigin(origin: string) {
try {
const hostname = new URL(origin).hostname;
return devTrustedPkceHosts.has(hostname) || isPrivateIPv4(hostname);
} catch {
return false;
}
}
export function canStartBrowserPkceLogin({
isSecureContext = window.isSecureContext,
origin = window.location.origin,
cryptoSubtleAvailable = Boolean(window.crypto?.subtle),
}: BrowserPkceLoginCheck = {}) {
if (!cryptoSubtleAvailable) {
return false;
}
if (isSecureContext) {
return true;
}
return isDevTrustedPkceOrigin(origin);
}