payload-oauth2
Version:
OAuth2 plugin for Payload CMS
125 lines • 6 kB
JavaScript
import { jwtVerify } from "jose";
import { extractJWT, } from "payload";
import { shouldUsePayloadSessions, userHasPayloadSession, } from "./auth-sessions";
const getStringClaim = (jwtUser, claimName) => {
const claim = jwtUser[claimName];
return typeof claim === "string" && claim.length > 0 ? claim : undefined;
};
const getJWTUserID = (jwtUser) => {
const userID = jwtUser.id;
return typeof userID === "string" || typeof userID === "number"
? userID
: undefined;
};
export const createAuthStrategy = (pluginOptions, subFieldName) => {
const authStrategy = {
name: pluginOptions.strategyName,
authenticate: async ({ headers, payload }) => {
try {
const token = extractJWT({ headers, payload });
if (!token)
return { user: null };
let jwtUser = null;
try {
const { payload: verifiedPayload } = await jwtVerify(token, new TextEncoder().encode(payload.secret), { algorithms: ["HS256"] });
jwtUser = verifiedPayload;
}
catch (e) {
// Handle token expiration
if (e.code === "ERR_JWT_EXPIRED")
return { user: null };
throw e;
}
if (!jwtUser)
return { user: null };
// Find the user by email from the verified jwt token
// coerce userCollection to CollectionSlug because it is already checked
// in `modify-auth-collection.ts` that it is a valud collection slug
const userCollection = ((typeof jwtUser.collection === "string" &&
jwtUser.collection) ||
pluginOptions.authCollection ||
"users");
const collectionConfig = payload.collections[userCollection]?.config;
if (!collectionConfig)
return { user: null };
if (shouldUsePayloadSessions(collectionConfig)) {
const sid = getStringClaim(jwtUser, "sid");
const userID = getJWTUserID(jwtUser);
if (!sid || userID === undefined)
return { user: null };
const user = (await payload.findByID({
collection: userCollection,
disableErrors: true,
id: userID,
showHiddenFields: true,
}));
if (!user || !userHasPayloadSession(user, sid)) {
return { user: null };
}
if (typeof collectionConfig.auth === "object" &&
collectionConfig.auth.verify &&
!user._verified) {
return { user: null };
}
user.collection = userCollection;
user._sid = sid;
user._strategy = pluginOptions.strategyName;
return { user };
}
let user = null;
if (pluginOptions.useEmailAsIdentity) {
if (!jwtUser.email || typeof jwtUser.email !== "string") {
payload.logger.warn("Using email as identity but no email is found in jwt token");
return { user: null };
}
const usersQuery = await payload.find({
collection: userCollection,
where: { email: { equals: jwtUser.email } },
});
if (usersQuery.docs.length === 0) {
// coerce to User because `userCollection` is a valid auth collection, checked by `modify-auth-collection.ts` already
user = (await payload.create({
collection: userCollection,
data: jwtUser,
}));
}
else {
// coerce to User because payload warns that some collection may not have property `collection` - i.e. `PayloadMigration;
user = usersQuery.docs[0];
}
}
else {
if (typeof jwtUser[subFieldName] !== "string") {
payload.logger.warn(`No ${subFieldName} found in jwt token. Make sure the jwt token contains the ${subFieldName} field`);
return { user: null };
}
const usersQuery = await payload.find({
collection: userCollection,
where: { [subFieldName]: { equals: jwtUser[subFieldName] } },
});
if (usersQuery.docs.length === 0) {
// coerce to User because payload warns that some collection may not have property `collection` - i.e. `PayloadMigration;
user = (await payload.create({
collection: userCollection,
data: jwtUser,
}));
}
else {
// coerce to User because payload warns that some collection may not have property `collection` - i.e. `PayloadMigration;
user = usersQuery.docs[0];
}
}
user.collection = userCollection;
user._strategy = pluginOptions.strategyName;
// Return the user object
return { user };
}
catch (e) {
payload.logger.error(e);
return { user: null };
}
},
};
return authStrategy;
};
//# sourceMappingURL=auth-strategy.js.map