

























@@ -27,7 +27,8 @@ export type OAuthCallbackResult = { code: string; state: string };
2727// pass the hosts that may legitimately issue preflights against the redirect
2828// URI; everything else gets a 204 with no `Access-Control-Allow-*` headers,
2929// which is safe for normal browser navigation but blocks cross-origin script
30-// reads. The empty allowlist (default) suppresses CORS echo entirely.
30+// reads. The empty allowlist (default) leaves the legacy permissive SDK
31+// behavior in place for existing callers.
3132export function buildOAuthCallbackOriginResolver(
3233allowedHosts: readonly string[] | undefined,
3334): (originHeader: string | string[] | undefined) => string | undefined {
@@ -101,28 +102,27 @@ export async function waitForLocalOAuthCallback(params: {
101102onProgress?: (message: string) => void;
102103// IdP host allowlist for CORS preflight echo. Pass the canonical authority
103104// host(s) (e.g. `["auth.example.com"]`) that may issue an `OPTIONS` against
104-// the redirect URI. When omitted, no `Access-Control-Allow-*` headers are
105-// echoed.
105+// the redirect URI. When omitted, legacy permissive SDK behavior is
106+// preserved for existing provider login flows.
106107corsOriginAllowlist?: readonly string[];
107108}): Promise<OAuthCallbackResult> {
108109const hostname = params.hostname ?? "localhost";
109110const escapedSuccessTitle = escapeHtmlText(params.successTitle);
110111const resolveOAuthCallbackOrigin = buildOAuthCallbackOriginResolver(params.corsOriginAllowlist);
112+const hasCorsOriginAllowlist =
113+params.corsOriginAllowlist?.some((host) => host.trim().length > 0) ?? false;
111114112115return new Promise<OAuthCallbackResult>((resolve, reject) => {
113116let settled = false;
114117let timeout: NodeJS.Timeout | null = null;
115118const server = createServer((req, res) => {
116119try {
117-applyOAuthCallbackCorsHeaders(req, res);
120+applyOAuthCallbackCorsHeaders(
121+req,
122+res,
123+hasCorsOriginAllowlist ? resolveOAuthCallbackOrigin : undefined,
124+);
118125const requestUrl = new URL(req.url ?? "/", `http://${hostname}:${params.port}`);
119-const requestOrigin = resolveOAuthCallbackOrigin(req.headers.origin);
120-if (requestOrigin) {
121-res.setHeader("Access-Control-Allow-Origin", requestOrigin);
122-res.setHeader("Vary", "Origin");
123-res.setHeader("Access-Control-Allow-Methods", "GET, OPTIONS");
124-res.setHeader("Access-Control-Allow-Headers", "Content-Type");
125-}
126126if (req.method === "OPTIONS") {
127127res.statusCode = 204;
128128res.end();
@@ -223,12 +223,21 @@ export async function waitForLocalOAuthCallback(params: {
223223function applyOAuthCallbackCorsHeaders(
224224req: import("node:http").IncomingMessage,
225225res: import("node:http").ServerResponse,
226+resolveOrigin?: (originHeader: string | string[] | undefined) => string | undefined,
226227): void {
227-const origin = req.headers.origin;
228-if (typeof origin === "string" && isHttpOrigin(origin)) {
228+const origin =
229+resolveOrigin === undefined
230+ ? typeof req.headers.origin === "string" && isHttpOrigin(req.headers.origin)
231+ ? req.headers.origin
232+ : undefined
233+ : resolveOrigin(req.headers.origin);
234+if (origin) {
229235res.setHeader("Access-Control-Allow-Origin", origin);
230236res.setHeader("Vary", "Origin, Access-Control-Request-Method, Access-Control-Request-Headers");
231237}
238+if (resolveOrigin !== undefined && !origin) {
239+return;
240+}
232241233242const requestedHeaders = req.headers["access-control-request-headers"];
234243res.setHeader("Access-Control-Allow-Methods", "GET, OPTIONS");
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。