forked from baron/baron-sso
userfront e2e 전체 테스트
This commit is contained in:
@@ -745,7 +745,7 @@ export type BulkUserItem = {
|
||||
memo?: string;
|
||||
emailDomain?: string;
|
||||
};
|
||||
metadata: Record<string, string>;
|
||||
metadata: Record<string, unknown>;
|
||||
};
|
||||
|
||||
export type BulkUserResult = {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user