fix: get env variable dynamically to avoid secret leakage
This commit is contained in:
@@ -1,11 +1,86 @@
|
||||
import type { OidcResolvedOptions } from "./index.js";
|
||||
import type { OidcInjectedOptions } from "./index.js";
|
||||
import { getSecret } from "astro:env/server";
|
||||
|
||||
// This constant is provided via Vite define by the integration during astro:config:setup
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
declare const __RESUELY_OIDC_OPTIONS: OidcResolvedOptions;
|
||||
declare const __RESUELY_OIDC_OPTIONS: OidcInjectedOptions;
|
||||
|
||||
export const options: OidcResolvedOptions = (
|
||||
typeof __RESUELY_OIDC_OPTIONS !== "undefined"
|
||||
? __RESUELY_OIDC_OPTIONS
|
||||
: (undefined as any)
|
||||
) as OidcResolvedOptions;
|
||||
export type OidcRuntimeOptions = {
|
||||
issuer: string;
|
||||
clientId: string;
|
||||
scopes: string;
|
||||
routes: { login: string; callback: string; logout: string };
|
||||
redirectUri: { mode: "infer-from-request" } | { absolute: string };
|
||||
cookie: {
|
||||
name: string;
|
||||
sameSite: "Lax" | "Strict" | "None";
|
||||
secure: boolean;
|
||||
domain?: string;
|
||||
path: string;
|
||||
signingSecret: string;
|
||||
maxAgeSec?: number;
|
||||
};
|
||||
protected: string[];
|
||||
};
|
||||
|
||||
function getInjected(): OidcInjectedOptions {
|
||||
if (typeof __RESUELY_OIDC_OPTIONS === "undefined") {
|
||||
throw new Error(
|
||||
"@resuely/astro-oidc-rp: missing injected options; is the integration configured?",
|
||||
);
|
||||
}
|
||||
return __RESUELY_OIDC_OPTIONS;
|
||||
}
|
||||
|
||||
function readEnv(name: string): string | undefined {
|
||||
const v = getSecret(name);
|
||||
if (typeof v !== "string") return undefined;
|
||||
if (v.trim().length === 0) return undefined;
|
||||
return v;
|
||||
}
|
||||
|
||||
function requireEnv(name: string): string {
|
||||
const v = readEnv(name);
|
||||
if (typeof v === "string") return v;
|
||||
throw new Error(`@resuely/astro-oidc-rp: missing env var ${name}`);
|
||||
}
|
||||
|
||||
let cached: OidcRuntimeOptions | null = null;
|
||||
|
||||
export function getOptions(): OidcRuntimeOptions {
|
||||
if (cached) return cached;
|
||||
|
||||
const injected = getInjected();
|
||||
|
||||
const issuer = readEnv(injected.issuerEnv) ?? injected.issuerFallback;
|
||||
if (!issuer)
|
||||
throw new Error(
|
||||
`@resuely/astro-oidc-rp: missing env var ${injected.issuerEnv}`,
|
||||
);
|
||||
|
||||
const clientId = readEnv(injected.clientIdEnv) ?? injected.clientIdFallback;
|
||||
if (!clientId)
|
||||
throw new Error(
|
||||
`@resuely/astro-oidc-rp: missing env var ${injected.clientIdEnv}`,
|
||||
);
|
||||
|
||||
cached = {
|
||||
issuer,
|
||||
clientId,
|
||||
scopes: injected.scopes,
|
||||
routes: injected.routes,
|
||||
redirectUri: injected.redirectUri,
|
||||
cookie: {
|
||||
name: injected.cookie.name,
|
||||
sameSite: injected.cookie.sameSite,
|
||||
secure: injected.cookie.secure,
|
||||
domain: injected.cookie.domain,
|
||||
path: injected.cookie.path,
|
||||
signingSecret: requireEnv(injected.cookie.signingSecretEnv),
|
||||
maxAgeSec: injected.cookie.maxAgeSec,
|
||||
},
|
||||
protected: injected.protected,
|
||||
};
|
||||
|
||||
return cached;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user