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 8.93 kB
{"version":3,"sources":["../src/exports/express.ts"],"names":["expressOAuthProvider","OAuthProvider","OAuthError","$sharedHandleAuthentication","$sharedHandleCallback","$sharedHandleLogout","$sharedHandleOnBehalfOf","$sharedMiddleware"],"mappings":"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","file":"express.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 Express 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 Express-specific entry point.';\r\n\r\nexport let expressOAuthProvider: OAuthProvider = undefined as unknown as OAuthProvider;\r\n\r\n/**\r\n * Factory that binds a singleton OAuthProvider to every Express 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 (!expressOAuthProvider) {\r\n expressOAuthProvider = new OAuthProvider(config);\r\n }\r\n\r\n req.oauthProvider = expressOAuthProvider;\r\n req.serverType = 'express';\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 function handleAuthentication() {\r\n return async (req: Request, res: Response, next: NextFunction) => {\r\n try {\r\n if (!req.oauthProvider || req.serverType !== 'express') {\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 next(err);\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` - The authorization code received from Microsoft.\r\n * - `state` - The state parameter received from Microsoft, used to prevent CSRF attacks and store session state.\r\n *\r\n * @throws {OAuthError} if there is any issue.\r\n */\r\nexport function handleCallback() {\r\n return async (req: Request, res: Response, next: NextFunction) => {\r\n try {\r\n if (!req.oauthProvider || req.serverType !== 'express') {\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 next(err);\r\n }\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\n * @throws {OAuthError} if there is any issue.\r\n */\r\nexport function handleLogout() {\r\n return async (req: Request, res: Response, next: NextFunction) => {\r\n try {\r\n if (!req.oauthProvider || req.serverType !== 'express') {\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 next(err);\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 function handleOnBehalfOf() {\r\n return async (req: Request, res: Response, next: NextFunction) => {\r\n try {\r\n if (!req.oauthProvider || req.serverType !== 'express') {\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 next(err);\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 *\r\n * @throws {OAuthError} if there is any issue with the configuration or authentication.\r\n */\r\nexport function protectRoute(cb?: CallbackFunction) {\r\n return async (req: Request, res: Response, next: NextFunction) => {\r\n try {\r\n if (!req.oauthProvider || req.serverType !== 'express') {\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 next();\r\n } catch (err) {\r\n next(err);\r\n }\r\n };\r\n}\r\n"]}