UNPKG

@lucidcms/core

Version:

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

1 lines 5.55 kB
{"version":3,"file":"oidc-callback.mjs","names":[],"sources":["../../../../src/services/auth/providers/oidc-callback.ts"],"sourcesContent":["import getAuthProviderAdapter from \"../../../libs/auth-providers/get-adapter.js\";\nimport getAvailableProviders from \"../../../libs/auth-providers/get-available-providers.js\";\nimport buildCallbackRedirectUrl from \"../../../libs/auth-providers/helpers/build-callback-redirect-url.js\";\nimport { copy } from \"../../../libs/i18n/index.js\";\nimport { AuthStatesRepository } from \"../../../libs/repositories/index.js\";\nimport { getBaseUrl } from \"../../../utils/helpers/index.js\";\nimport type { ServiceFn } from \"../../../utils/services/types.js\";\nimport processProviderAuth from \"./helpers/process-provider-auth.js\";\n\n/**\n * The callback endpoint for OIDC auth flow.\n *\n * Verifies the provider and state key, then proceeds to authenticate / link the provider to the user based on the\n * states action type.\n */\nconst oidcCallback: ServiceFn<\n\t[\n\t\t{\n\t\t\tproviderKey: string;\n\t\t\tcode: string;\n\t\t\tstate: string;\n\t\t},\n\t],\n\t{\n\t\tredirectUrl: string;\n\t\tuserId: number;\n\t\tgrantAuthentication: boolean;\n\t}\n> = async (context, data) => {\n\tconst AuthStates = new AuthStatesRepository(\n\t\tcontext.db.client,\n\t\tcontext.config.db,\n\t);\n\n\t//* get provider config\n\tconst availableProviders = getAvailableProviders(context.config);\n\tconst provider = availableProviders.providers.find(\n\t\t(p) => p.key === data.providerKey,\n\t);\n\tif (!provider) {\n\t\treturn {\n\t\t\terror: {\n\t\t\t\ttype: \"basic\",\n\t\t\t\tstatus: 404,\n\t\t\t\tname: copy(\"server:core.auth.providers.not.found.name\"),\n\t\t\t\tmessage: copy(\"server:core.auth.providers.not.found.message\"),\n\t\t\t},\n\t\t\tdata: undefined,\n\t\t};\n\t}\n\n\t//* retrieve and validate auth state\n\tconst authStateRes = await AuthStates.selectSingle({\n\t\tselect: [\n\t\t\t\"id\",\n\t\t\t\"provider_key\",\n\t\t\t\"invitation_token_id\",\n\t\t\t\"redirect_path\",\n\t\t\t\"action_type\",\n\t\t\t\"authenticated_user_id\",\n\t\t],\n\t\twhere: [\n\t\t\t{\n\t\t\t\tkey: \"state\",\n\t\t\t\toperator: \"=\",\n\t\t\t\tvalue: data.state,\n\t\t\t},\n\t\t\t{\n\t\t\t\tkey: \"expiry_date\",\n\t\t\t\toperator: \">\",\n\t\t\t\tvalue: new Date().toISOString(),\n\t\t\t},\n\t\t\t{\n\t\t\t\tkey: \"provider_key\",\n\t\t\t\toperator: \"=\",\n\t\t\t\tvalue: data.providerKey,\n\t\t\t},\n\t\t],\n\t\tvalidation: {\n\t\t\tenabled: true,\n\t\t\tdefaultError: {\n\t\t\t\tstatus: 400,\n\t\t\t\tmessage: copy(\"server:core.invalid.or.expired.state.message\"),\n\t\t\t},\n\t\t},\n\t});\n\tif (authStateRes.error) return authStateRes;\n\n\t//* get provider adapter and use the adapter to handle callback and get user info\n\tconst adapterRes = getAuthProviderAdapter(provider);\n\tif (adapterRes.error) return adapterRes;\n\n\tconst userInfoRes = await adapterRes.data.handleCallback({\n\t\tcode: data.code,\n\t\tstate: data.state,\n\t\tredirectUri: buildCallbackRedirectUrl(\n\t\t\tgetBaseUrl(context),\n\t\t\tdata.providerKey,\n\t\t),\n\t});\n\tif (userInfoRes.error) return userInfoRes;\n\n\t//* process authentication & cleanup\n\tconst [processAuthRes] = await Promise.all([\n\t\tprocessProviderAuth(context, {\n\t\t\tproviderKey: data.providerKey,\n\t\t\tproviderUserId: userInfoRes.data.userId,\n\t\t\tfirstName: userInfoRes.data.firstName,\n\t\t\tlastName: userInfoRes.data.lastName,\n\t\t\tinvitationTokenId: authStateRes.data.invitation_token_id ?? undefined,\n\t\t\tredirectPath: authStateRes.data.redirect_path ?? undefined,\n\t\t\tactionType: authStateRes.data.action_type ?? undefined,\n\t\t\tauthenticatedUserId: authStateRes.data.authenticated_user_id ?? undefined,\n\t\t}),\n\t\tAuthStates.deleteSingle({\n\t\t\twhere: [{ key: \"id\", operator: \"=\", value: authStateRes.data.id }],\n\t\t}),\n\t]);\n\tif (processAuthRes.error) return processAuthRes;\n\n\treturn {\n\t\terror: undefined,\n\t\tdata: {\n\t\t\tuserId: processAuthRes.data.userId,\n\t\t\tredirectUrl: processAuthRes.data.redirectUrl,\n\t\t\tgrantAuthentication: processAuthRes.data.grantAuthentication,\n\t\t},\n\t};\n};\n\nexport default oidcCallback;\n"],"mappings":"+aAeA,MAAM,EAaF,MAAO,EAAS,IAAS,CAC5B,IAAM,EAAa,IAAI,EACtB,EAAQ,GAAG,OACX,EAAQ,OAAO,EAChB,EAIM,EADqB,EAAsB,EAAQ,MACvB,CAAC,CAAC,UAAU,KAC5C,GAAM,EAAE,MAAQ,EAAK,WACvB,EACA,GAAI,CAAC,EACJ,MAAO,CACN,MAAO,CACN,KAAM,QACN,OAAQ,IACR,KAAM,EAAK,2CAA2C,EACtD,QAAS,EAAK,8CAA8C,CAC7D,EACA,KAAM,IAAA,EACP,EAID,IAAM,EAAe,MAAM,EAAW,aAAa,CAClD,OAAQ,CACP,KACA,eACA,sBACA,gBACA,cACA,uBACD,EACA,MAAO,CACN,CACC,IAAK,QACL,SAAU,IACV,MAAO,EAAK,KACb,EACA,CACC,IAAK,cACL,SAAU,IACV,MAAO,IAAI,KAAK,CAAA,CAAE,YAAY,CAC/B,EACA,CACC,IAAK,eACL,SAAU,IACV,MAAO,EAAK,WACb,CACD,EACA,WAAY,CACX,QAAS,GACT,aAAc,CACb,OAAQ,IACR,QAAS,EAAK,8CAA8C,CAC7D,CACD,CACD,CAAC,EACD,GAAI,EAAa,MAAO,OAAO,EAG/B,IAAM,EAAa,EAAuB,CAAQ,EAClD,GAAI,EAAW,MAAO,OAAO,EAE7B,IAAM,EAAc,MAAM,EAAW,KAAK,eAAe,CACxD,KAAM,EAAK,KACX,MAAO,EAAK,MACZ,YAAa,EACZ,EAAW,CAAO,EAClB,EAAK,WACN,CACD,CAAC,EACD,GAAI,EAAY,MAAO,OAAO,EAG9B,GAAM,CAAC,GAAkB,MAAM,QAAQ,IAAI,CAC1C,EAAoB,EAAS,CAC5B,YAAa,EAAK,YAClB,eAAgB,EAAY,KAAK,OACjC,UAAW,EAAY,KAAK,UAC5B,SAAU,EAAY,KAAK,SAC3B,kBAAmB,EAAa,KAAK,qBAAuB,IAAA,GAC5D,aAAc,EAAa,KAAK,eAAiB,IAAA,GACjD,WAAY,EAAa,KAAK,aAAe,IAAA,GAC7C,oBAAqB,EAAa,KAAK,uBAAyB,IAAA,EACjE,CAAC,EACD,EAAW,aAAa,CACvB,MAAO,CAAC,CAAE,IAAK,KAAM,SAAU,IAAK,MAAO,EAAa,KAAK,EAAG,CAAC,CAClE,CAAC,CACF,CAAC,EAGD,OAFI,EAAe,MAAc,EAE1B,CACN,MAAO,IAAA,GACP,KAAM,CACL,OAAQ,EAAe,KAAK,OAC5B,YAAa,EAAe,KAAK,YACjC,oBAAqB,EAAe,KAAK,mBAC1C,CACD,CACD"}