UNPKG

alepha

Version:

Easy-to-use modern TypeScript framework for building many kind of applications.

89 lines (80 loc) 2.77 kB
import { $context, AlephaError, z } from "alepha"; import type { IssuerPrimitive } from "alepha/security"; import { $auth, type LinkAccountFn, type OidcOptions, type WithLinkFn, } from "./$auth.ts"; /** * Already configured Microsoft Entra ID (Azure AD) authentication primitive. * * Uses OpenID Connect (OIDC) to authenticate users via their Microsoft accounts. * Supports personal Microsoft accounts, work/school (Azure AD) accounts, and * multi-tenant applications. * * The tenant ID defaults to `"common"`, which allows all Microsoft account types * (personal, work, school). To restrict to a specific Azure AD tenant, set * `MICROSOFT_TENANT_ID` to your tenant's GUID or domain. * * **Note on multi-tenant issuer validation**: Microsoft's OIDC discovery document * for the `common` endpoint returns `{tenantid}` as a literal placeholder in the * `issuer` field. This is expected behavior for multi-tenant endpoints. The * openid-client library handles this during token validation automatically. * * Environment Variables: * - `MICROSOFT_CLIENT_ID`: The application (client) ID from the Azure Portal. * - `MICROSOFT_CLIENT_SECRET`: The client secret value from the Azure Portal. * - `MICROSOFT_TENANT_ID`: (Optional) Azure AD tenant ID or `"common"` for * multi-tenant. Defaults to `"common"`. */ export const $authMicrosoft = ( realm: IssuerPrimitive & WithLinkFn, options: Partial<OidcOptions> = {}, ) => { const { alepha } = $context(); const env = alepha.parseEnv( z.object({ MICROSOFT_CLIENT_ID: z .text({ description: "The application (client) ID obtained from the Azure Portal.", }) .optional(), MICROSOFT_CLIENT_SECRET: z .text({ description: "The client secret value obtained from the Azure Portal.", }) .optional(), MICROSOFT_TENANT_ID: z .text({ description: "The Azure AD tenant ID or 'common' for multi-tenant. Defaults to 'common'.", }) .optional(), }), ); const disabled = !env.MICROSOFT_CLIENT_ID || !env.MICROSOFT_CLIENT_SECRET; const tenantId = env.MICROSOFT_TENANT_ID ?? "common"; const name = "microsoft"; const account: LinkAccountFn | undefined = options.account ?? (realm.link ? realm.link(name) : undefined); if (!account) { throw new AlephaError( "Authentication requires a link function in the realm primitive.", ); } return $auth({ issuer: realm, name, oidc: { issuer: `https://login.microsoftonline.com/${tenantId}/v2.0`, clientId: env.MICROSOFT_CLIENT_ID!, clientSecret: env.MICROSOFT_CLIENT_SECRET, ...options, account, }, disabled, }); };