UNPKG

oauth-entra-id

Version:

🛡️ A Secure, Performant, and Feature-Rich OAuth 2.0 Integration for Microsoft Entra ID — Fully Abstracted and Production-Ready.

1 lines 10.4 kB
{"version":3,"sources":["../src/exports/nestjs.ts"],"names":["nestjsOAuthProvider","OAuthProvider","OAuthError","$sharedHandleAuthentication","$sharedHandleCallback","$sharedHandleLogout","$sharedHandleOnBehalfOf","$sharedMiddleware"],"mappings":"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","file":"nestjs.cjs","sourcesContent":["import '~/shared/types';\r\nimport type { NextFunction, Request, Response } from 'express';\r\nimport { OAuthProvider } from '~/core';\r\nimport { OAuthError } from '~/error';\r\nimport {\r\n $sharedHandleAuthentication,\r\n $sharedHandleCallback,\r\n $sharedHandleLogout,\r\n $sharedHandleOnBehalfOf,\r\n} from '~/shared/endpoints';\r\nimport { $sharedMiddleware } from '~/shared/middleware';\r\nimport type { CallbackFunction } from '~/shared/types';\r\nimport type { OAuthConfig } from '~/types';\r\n\r\nconst ERROR_MSG = 'authConfig not initialized or incorrect usage of NestJS handlers';\r\nconst ERROR_DESC =\r\n 'Ensure you have called `authConfig(config)` during app setup before endpoints, and are importing all functions from the NestJS-specific entry point.';\r\n\r\nexport let nestjsOAuthProvider: OAuthProvider = undefined as unknown as OAuthProvider;\r\n\r\n/**\r\n * Factory that binds a singleton OAuthProvider to every NestJS request.\r\n *\r\n * @param config OAuthConfig for your Microsoft Entra ID app.\r\n */\r\nexport function authConfig(config: OAuthConfig) {\r\n return (req: Request, _res: Response, next: NextFunction) => {\r\n if (!nestjsOAuthProvider) {\r\n nestjsOAuthProvider = new OAuthProvider(config);\r\n }\r\n\r\n req.oauthProvider = nestjsOAuthProvider;\r\n req.serverType = 'nestjs';\r\n\r\n next();\r\n };\r\n}\r\n\r\n/**\r\n * Route handler that begins the OAuth flow by sending back authentication PKCE-based URL.\r\n *\r\n * ### Body:\r\n * - `loginPrompt` (optional) - Overrides the default login prompt behavior, can be `email`, `select_account`, or `sso`.\r\n * - `email` (optional) - Pre-fills the email field in the login form.\r\n * - `frontendUrl` (optional) - Redirects to this URL after successful login.\r\n * - `azureId` (optional) - Azure configuration ID to use, relevant if multiple Azure configurations (Defaults to the first one).\r\n *\r\n * @throws {OAuthError} if there is any issue.\r\n */\r\nexport async function handleAuthentication(req: Request, res: Response) {\r\n try {\r\n if (!req.oauthProvider || req.serverType !== 'nestjs') {\r\n throw new OAuthError({ msg: ERROR_MSG, desc: ERROR_DESC, status: 500 });\r\n }\r\n await $sharedHandleAuthentication(req, res);\r\n } catch (err) {\r\n if (err instanceof OAuthError) throw err;\r\n throw new OAuthError({\r\n msg: 'Something went wrong...',\r\n desc: err instanceof Error ? err.message : typeof err === 'string' ? err : String(err),\r\n status: 500,\r\n });\r\n }\r\n}\r\n\r\n/**\r\n * Route handler that processes the OAuth callback after user authentication.\r\n *\r\n * ### Body:\r\n * - `code` (required) - The authorization code received from the OAuth provider.\r\n * - `state` (required) - The state parameter to validate the request.\r\n *\r\n * @throws {OAuthError} if there is any issue.\r\n */\r\nexport async function handleCallback(req: Request, res: Response) {\r\n try {\r\n if (!req.oauthProvider || req.serverType !== 'nestjs') {\r\n throw new OAuthError({ msg: ERROR_MSG, desc: ERROR_DESC, status: 500 });\r\n }\r\n await $sharedHandleCallback(req, res);\r\n } catch (err) {\r\n if (err instanceof OAuthError) throw err;\r\n if (err instanceof Error) throw new OAuthError({ msg: 'internal', desc: err.message, status: 500 });\r\n throw new OAuthError({ msg: 'internal', desc: 'Something went wrong', status: 500 });\r\n }\r\n}\r\n\r\n/**\r\n * Route handler that clears session cookies and returns the Azure logout URL.\r\n *\r\n * ### Body:\r\n * - `frontendUrl` (optional) - Overrides the default redirect URL after logout.\r\n * - `azureId` (optional) - Azure configuration ID to use, relevant if multiple Azure configurations (Defaults to the first one).\r\n */\r\nexport async function handleLogout(req: Request, res: Response) {\r\n try {\r\n if (!req.oauthProvider || req.serverType !== 'nestjs') {\r\n throw new OAuthError({ msg: ERROR_MSG, desc: ERROR_DESC, status: 500 });\r\n }\r\n await $sharedHandleLogout(req, res);\r\n } catch (err) {\r\n if (err instanceof OAuthError) throw err;\r\n throw new OAuthError({\r\n msg: 'Something went wrong',\r\n desc: err instanceof Error ? err.message : String(err),\r\n status: 500,\r\n });\r\n }\r\n}\r\n\r\n/**\r\n * Route handler that processes on-behalf-of requests to obtain an access token for a service principal.\r\n *\r\n * ### Body:\r\n * - `services` - An array of service names for which the access token is requested.\r\n * - `azureId` (optional) - Azure configuration ID to use, relevant if multiple Azure configurations (Defaults to the first one).\r\n *\r\n * @throws {OAuthError} if there is any issue.\r\n */\r\nexport async function handleOnBehalfOf(req: Request, res: Response) {\r\n try {\r\n if (!req.oauthProvider || req.serverType !== 'nestjs') {\r\n throw new OAuthError({ msg: ERROR_MSG, desc: ERROR_DESC, status: 500 });\r\n }\r\n await $sharedHandleOnBehalfOf(req, res);\r\n } catch (err) {\r\n if (err instanceof OAuthError) throw err;\r\n throw new OAuthError({\r\n msg: 'Something went wrong',\r\n desc: err instanceof Error ? err.message : String(err),\r\n status: 500,\r\n });\r\n }\r\n}\r\n\r\n/**\r\n * Middleware that protects a route by ensuring the user is authenticated.\r\n *\r\n * ### What it does:\r\n * - If `acceptB2BRequests` is enabled:\r\n * - Checks for a Bearer token in the Authorization header.\r\n * - Verifies the token and attaches user info to the request.\r\n * - If not:\r\n * - Validate the users access token cookie.\r\n * - If valid, attaches user info to the request.\r\n * - If invalid, it looks for a refresh token cookie and attempts to refresh the session.\r\n * - If the refresh is successful, it sets new cookies and attaches user info to the request.\r\n * - If the refresh fails, it throws an error.\r\n *\r\n * @param cb (optional) - A callback function that gives access to user info and an inject data function. Fires after the user is authenticated.\r\n * @returns True if the user is authenticated, otherwise throws an error.\r\n *\r\n * @throws {OAuthError} if there is any issue with the configuration or authentication.\r\n */\r\nexport async function isAuthenticated(req: Request, res: Response, cb?: CallbackFunction) {\r\n try {\r\n if (!req.oauthProvider || req.serverType !== 'nestjs') {\r\n throw new OAuthError({ msg: ERROR_MSG, desc: ERROR_DESC, status: 500 });\r\n }\r\n const { userInfo, tryInjectData } = await $sharedMiddleware(req, res);\r\n if (cb) await cb({ userInfo, tryInjectData });\r\n return true;\r\n } catch (err) {\r\n if (err instanceof OAuthError) throw err;\r\n throw new OAuthError({\r\n msg: 'Something went wrong',\r\n desc: err instanceof Error ? err.message : String(err),\r\n status: 500,\r\n });\r\n }\r\n}\r\n"]}