first commit
This commit is contained in:
112
src/index.ts
Normal file
112
src/index.ts
Normal file
@@ -0,0 +1,112 @@
|
||||
import type { AstroIntegration } from "astro";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
export type OidcIntegrationOptions = {
|
||||
issuer: string;
|
||||
clientId: string;
|
||||
scopes?: string; // default "openid email profile"
|
||||
routes?: { login?: string; callback?: string; logout?: string }; // defaults: /login, /oidc/callback, /logout
|
||||
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[]; // patterns to guard, e.g., ["/app/*", "/me"]
|
||||
};
|
||||
|
||||
export type OidcResolvedOptions = Required<
|
||||
Pick<OidcIntegrationOptions, "issuer" | "clientId">
|
||||
> & {
|
||||
scopes: string;
|
||||
routes: { login: string; callback: string; logout: string };
|
||||
redirectUri: { mode: "infer-from-request" } | { absolute: string };
|
||||
cookie: Required<
|
||||
Pick<
|
||||
NonNullable<OidcIntegrationOptions["cookie"]>,
|
||||
"name" | "sameSite" | "secure" | "path" | "signingSecret"
|
||||
>
|
||||
> & {
|
||||
domain?: string;
|
||||
maxAgeSec?: number;
|
||||
};
|
||||
protected: string[];
|
||||
};
|
||||
|
||||
function resolveOptions(user: OidcIntegrationOptions): OidcResolvedOptions {
|
||||
const routes = {
|
||||
login: user.routes?.login ?? "/login",
|
||||
callback: user.routes?.callback ?? "/oidc/callback",
|
||||
logout: user.routes?.logout ?? "/logout",
|
||||
};
|
||||
const cookie = {
|
||||
name: user.cookie?.name ?? "oidc_session",
|
||||
sameSite: user.cookie?.sameSite ?? "Lax",
|
||||
secure: user.cookie?.secure ?? true,
|
||||
path: user.cookie?.path ?? "/",
|
||||
signingSecret: user.cookie?.signingSecret ?? "",
|
||||
domain: user.cookie?.domain,
|
||||
maxAgeSec: user.cookie?.maxAgeSec,
|
||||
};
|
||||
if (!user.issuer)
|
||||
throw new Error("@resuely/astro-oidc-rp: 'issuer' is required");
|
||||
if (!user.clientId)
|
||||
throw new Error("@resuely/astro-oidc-rp: 'clientId' is required");
|
||||
if (!cookie.signingSecret)
|
||||
throw new Error("@resuely/astro-oidc-rp: cookie.signingSecret is required");
|
||||
return {
|
||||
issuer: user.issuer,
|
||||
clientId: user.clientId,
|
||||
scopes: user.scopes ?? "openid email profile",
|
||||
routes,
|
||||
redirectUri: user.redirectUri ?? { mode: "infer-from-request" },
|
||||
cookie,
|
||||
protected: user.protected ?? [],
|
||||
};
|
||||
}
|
||||
|
||||
export default function resuelyOidc(
|
||||
options: OidcIntegrationOptions,
|
||||
): AstroIntegration {
|
||||
const resolved = resolveOptions(options);
|
||||
return {
|
||||
name: "@resuely/astro-oidc-rp",
|
||||
hooks: {
|
||||
"astro:config:setup": ({ injectRoute, addMiddleware, updateConfig }) => {
|
||||
// Provide runtime options to middleware/routes via Vite define replacement
|
||||
updateConfig({
|
||||
vite: {
|
||||
define: {
|
||||
__RESUELY_OIDC_OPTIONS: JSON.stringify(resolved),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Add middleware (run early to populate locals and guard protected patterns)
|
||||
addMiddleware({
|
||||
entrypoint: fileURLToPath(new URL("./middleware.js", import.meta.url)),
|
||||
order: "pre",
|
||||
});
|
||||
|
||||
// Inject routes
|
||||
injectRoute({
|
||||
pattern: resolved.routes.login,
|
||||
entrypoint: fileURLToPath(new URL("./routes/login.js", import.meta.url)),
|
||||
});
|
||||
injectRoute({
|
||||
pattern: resolved.routes.callback,
|
||||
entrypoint: fileURLToPath(new URL("./routes/callback.js", import.meta.url)),
|
||||
});
|
||||
injectRoute({
|
||||
pattern: resolved.routes.logout,
|
||||
entrypoint: fileURLToPath(new URL("./routes/logout.js", import.meta.url)),
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user