UNPKG

payload-auth-plugin

Version:
131 lines (130 loc) 3.83 kB
// src/core/protocols/oauth/oauth_authentication.ts import * as jose from "jose"; import { APP_COOKIE_SUFFIX } from "../../../constants.js"; import { MissingCollection, UserNotFoundAPIError } from "../../errors/apiErrors.js"; import { createSessionCookies, invalidateOAuthCookies } from "../../utils/cookies.js"; import { v4 as uuid } from "uuid"; import { removeExpiredSessions } from "../../utils/session.js"; async function OAuthAuthentication(pluginType, collections, allowOAuthAutoSignUp, useAdmin, secret, request, successRedirectPath, errorRedirectPath, account) { const { email: _email, sub, name, scope, issuer, picture, access_token } = account; const { payload } = request; const email = _email.toLowerCase(); const userRecords = await payload.find({ collection: collections.usersCollection, where: { email: { equals: email } } }); let userRecord; if (userRecords.docs.length === 1) { userRecord = userRecords.docs[0]; } else if (allowOAuthAutoSignUp) { const data2 = { email, name }; const hasAuthEnabled = Boolean(payload.collections[collections.usersCollection].config.auth); if (hasAuthEnabled) { data2.password = jose.base64url.encode(crypto.getRandomValues(new Uint8Array(16))); } const userRecords2 = await payload.create({ collection: collections.usersCollection, data: data2 }); userRecord = userRecords2; } else { return new UserNotFoundAPIError; } const data = { scope, name, picture, issuerName: issuer, access_token }; const accountRecords = await payload.find({ collection: collections.accountsCollection, where: { sub: { equals: sub } } }); if (accountRecords.docs && accountRecords.docs.length === 1) { await payload.update({ collection: collections.accountsCollection, id: accountRecords.docs[0].id, data }); } else { data.sub = sub; data.user = userRecord.id; await payload.create({ collection: collections.accountsCollection, data }); } let cookies = []; const collectionConfig = payload.config.collections.find((collection) => collection.slug === collections.usersCollection); if (!collectionConfig) { return new MissingCollection; } const sessionID = collectionConfig?.auth.useSessions ? uuid() : null; if (collectionConfig?.auth.useSessions) { const now = new Date; const tokenExpInMs = collectionConfig.auth.tokenExpiration * 1000; const expiresAt = new Date(now.getTime() + tokenExpInMs); const session = { id: sessionID, createdAt: now, expiresAt }; if (!userRecord["sessions"]?.length) { userRecord["sessions"] = [session]; } else { userRecord.sessions = removeExpiredSessions(userRecord.sessions); userRecord.sessions.push(session); } await payload.db.updateOne({ id: userRecord.id, collection: collections.usersCollection, data: userRecord, req: request, returning: false }); } const cookieName = useAdmin ? `${payload.config.cookiePrefix}-token` : `__${pluginType}-${APP_COOKIE_SUFFIX}`; cookies = [ ...await createSessionCookies(cookieName, secret, { id: userRecord.id, email, sid: sessionID, collection: collections.usersCollection }, useAdmin ? collectionConfig?.auth.tokenExpiration : undefined) ]; cookies = invalidateOAuthCookies(cookies); const successRedirectionURL = new URL(`${payload.config.serverURL}${successRedirectPath}`); const res = new Response(null, { status: 302, headers: { Location: successRedirectionURL.href } }); for (const c of cookies) { res.headers.append("Set-Cookie", c); } return res; } export { OAuthAuthentication };