UNPKG

@lucidcms/core

Version:

The core of the Lucid CMS. It's responsible for spinning up the API and serving the CMS.

1 lines 9.27 kB
{"version":3,"file":"oidc-adapter.mjs","names":["constants"],"sources":["../../../../src/libs/auth-providers/adapters/oidc-adapter.ts"],"sourcesContent":["import constants from \"../../../constants/constants.js\";\nimport logger from \"../../../libs/logger/index.js\";\nimport { copy } from \"../../i18n/index.js\";\nimport mapStandardUserInfo from \"../helpers/default-user-info-mapper.js\";\nimport type { OIDCAdapter, OIDCAuthConfig } from \"../types.js\";\n\nconst createOIDCAdapter = (config: OIDCAuthConfig): OIDCAdapter => {\n\treturn {\n\t\tconfig,\n\t\tgetAuthUrl: async (params) => {\n\t\t\ttry {\n\t\t\t\tconst scopes = config.scopes\n\t\t\t\t\t? config.scopes.join(\" \")\n\t\t\t\t\t: \"openid profile email\";\n\n\t\t\t\tconst url = new URL(config.authorizationEndpoint);\n\t\t\t\turl.searchParams.set(\"client_id\", config.clientId);\n\t\t\t\turl.searchParams.set(\"response_type\", \"code\");\n\t\t\t\turl.searchParams.set(\"redirect_uri\", params.redirectUri);\n\t\t\t\turl.searchParams.set(\"state\", params.state);\n\t\t\t\turl.searchParams.set(\"scope\", scopes);\n\n\t\t\t\tif (config.additionalAuthParams) {\n\t\t\t\t\tfor (const [key, value] of Object.entries(\n\t\t\t\t\t\tconfig.additionalAuthParams,\n\t\t\t\t\t)) {\n\t\t\t\t\t\turl.searchParams.set(key, value);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tlogger.debug({\n\t\t\t\t\tscope: constants.logScopes.oidcAuth,\n\t\t\t\t\tevent: \"oidc.authorization-url.generated\",\n\t\t\t\t\tmessage: `Generating OIDC auth URL for ${config.clientId}`,\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tauthEndpoint: config.authorizationEndpoint,\n\t\t\t\t\t\tscopes,\n\t\t\t\t\t\tredirectUri: params.redirectUri,\n\t\t\t\t\t},\n\t\t\t\t});\n\n\t\t\t\treturn {\n\t\t\t\t\terror: undefined,\n\t\t\t\t\tdata: url.toString(),\n\t\t\t\t};\n\t\t\t} catch (err) {\n\t\t\t\tlogger.error({\n\t\t\t\t\terror: err,\n\t\t\t\t\tevent: \"oidc.authorization-url.failed\",\n\t\t\t\t\tscope: constants.logScopes.oidcAuth,\n\t\t\t\t\tmessage: `Failed to generate OIDC auth URL for ${config.clientId}`,\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tredirectUri: params.redirectUri,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\treturn {\n\t\t\t\t\terror: {\n\t\t\t\t\t\ttype: \"basic\",\n\t\t\t\t\t\tstatus: 500,\n\t\t\t\t\t\tname: copy(\n\t\t\t\t\t\t\t\"server:core.auth.oidc.failed.to.generate.auth.url.name\",\n\t\t\t\t\t\t),\n\t\t\t\t\t\tmessage: copy(\n\t\t\t\t\t\t\t\"server:core.auth.oidc.failed.to.generate.auth.url.message\",\n\t\t\t\t\t\t\terr instanceof Error\n\t\t\t\t\t\t\t\t? { defaultMessage: err.message }\n\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t),\n\t\t\t\t\t},\n\t\t\t\t\tdata: undefined,\n\t\t\t\t};\n\t\t\t}\n\t\t},\n\t\thandleCallback: async (params) => {\n\t\t\ttry {\n\t\t\t\tconst tokenEndpoint =\n\t\t\t\t\tconfig.tokenEndpoint || `${config.issuer}/oauth2/token`;\n\n\t\t\t\tconst tokenResponse = await fetch(tokenEndpoint, {\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\t\t\t\tAccept: \"application/json\",\n\t\t\t\t\t},\n\t\t\t\t\tbody: new URLSearchParams({\n\t\t\t\t\t\tclient_id: config.clientId,\n\t\t\t\t\t\tclient_secret: config.clientSecret,\n\t\t\t\t\t\tcode: params.code,\n\t\t\t\t\t\tgrant_type: \"authorization_code\",\n\t\t\t\t\t\tredirect_uri: params.redirectUri,\n\t\t\t\t\t}),\n\t\t\t\t});\n\t\t\t\tif (!tokenResponse.ok) {\n\t\t\t\t\tconst errorText = await tokenResponse.text();\n\t\t\t\t\treturn {\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\ttype: \"basic\",\n\t\t\t\t\t\t\tstatus: tokenResponse.status,\n\t\t\t\t\t\t\tname: copy(\"server:core.auth.oidc.token.exchange.failed.name\"),\n\t\t\t\t\t\t\tmessage: copy(\n\t\t\t\t\t\t\t\t\"server:core.auth.oidc.token.exchange.failed.message\",\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\t\t\tmessage: errorText,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdata: undefined,\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tconst tokenData = await tokenResponse.json();\n\n\t\t\t\tconst accessToken = tokenData.access_token;\n\t\t\t\tif (!accessToken) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\ttype: \"basic\",\n\t\t\t\t\t\t\tstatus: 500,\n\t\t\t\t\t\t\tname: copy(\"server:core.auth.oidc.access.token.missing.name\"),\n\t\t\t\t\t\t\tmessage: copy(\n\t\t\t\t\t\t\t\t\"server:core.auth.oidc.access.token.missing.message\",\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdata: undefined,\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tconst userinfoEndpoint =\n\t\t\t\t\tconfig.userinfoEndpoint || `${config.issuer}/oauth2/userinfo`;\n\n\t\t\t\tconst userInfoResponse = await fetch(userinfoEndpoint, {\n\t\t\t\t\theaders: {\n\t\t\t\t\t\tAuthorization: `Bearer ${accessToken}`,\n\t\t\t\t\t\tAccept: \"application/json\",\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\tif (!userInfoResponse.ok) {\n\t\t\t\t\tconst errorText = await userInfoResponse.text();\n\t\t\t\t\treturn {\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\ttype: \"basic\",\n\t\t\t\t\t\t\tstatus: userInfoResponse.status,\n\t\t\t\t\t\t\tname: copy(\"server:core.auth.oidc.user.info.fetch.failed.name\"),\n\t\t\t\t\t\t\tmessage: copy(\n\t\t\t\t\t\t\t\t\"server:core.auth.oidc.user.info.fetch.failed.message\",\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\t\t\tmessage: errorText,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdata: undefined,\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tconst rawUserInfo = await userInfoResponse.json();\n\n\t\t\t\tconst userInfoRes = await (config.mappers?.userInfo\n\t\t\t\t\t? config.mappers.userInfo(rawUserInfo)\n\t\t\t\t\t: mapStandardUserInfo(rawUserInfo));\n\t\t\t\tif (userInfoRes.error) return userInfoRes;\n\n\t\t\t\tif (!userInfoRes.data.userId) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\tstatus: 500,\n\t\t\t\t\t\t\tname: copy(\"server:core.auth.oidc.user.info.incomplete.name\"),\n\t\t\t\t\t\t\tmessage: copy(\n\t\t\t\t\t\t\t\t\"server:core.auth.oidc.user.info.incomplete.message\",\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdata: undefined,\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\terror: undefined,\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tuserId: String(userInfoRes.data.userId),\n\t\t\t\t\t\tfirstName: userInfoRes.data.firstName,\n\t\t\t\t\t\tlastName: userInfoRes.data.lastName,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t} catch (err) {\n\t\t\t\treturn {\n\t\t\t\t\terror: {\n\t\t\t\t\t\ttype: \"basic\",\n\t\t\t\t\t\tstatus: 500,\n\t\t\t\t\t\tname: copy(\"server:core.auth.oidc.callback.failed.name\"),\n\t\t\t\t\t\tmessage: copy(\n\t\t\t\t\t\t\t\"server:core.auth.oidc.callback.failed.message\",\n\t\t\t\t\t\t\terr instanceof Error\n\t\t\t\t\t\t\t\t? { defaultMessage: err.message }\n\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t),\n\t\t\t\t\t},\n\t\t\t\t\tdata: undefined,\n\t\t\t\t};\n\t\t\t}\n\t\t},\n\t};\n};\n\nexport default createOIDCAdapter;\n"],"mappings":"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"}