feat: returns queried user alongside refreshed token (#2813)
Co-authored-by: Dan Ribbens <dan.ribbens@gmail.com>
This commit is contained in:
39
src/auth/operations/getFieldsToSign.ts
Normal file
39
src/auth/operations/getFieldsToSign.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { User } from '..';
|
||||
import { CollectionConfig } from '../../collections/config/types';
|
||||
import { Field, fieldAffectsData, fieldHasSubFields } from '../../fields/config/types';
|
||||
|
||||
export const getFieldsToSign = (args: {
|
||||
collectionConfig: CollectionConfig,
|
||||
user: User
|
||||
email: string
|
||||
}): Record<string, unknown> => {
|
||||
const {
|
||||
collectionConfig,
|
||||
user,
|
||||
email,
|
||||
} = args;
|
||||
|
||||
return collectionConfig.fields.reduce((signedFields, field: Field) => {
|
||||
const result = {
|
||||
...signedFields,
|
||||
};
|
||||
|
||||
if (!fieldAffectsData(field) && fieldHasSubFields(field)) {
|
||||
field.fields.forEach((subField) => {
|
||||
if (fieldAffectsData(subField) && subField.saveToJWT) {
|
||||
result[subField.name] = user[subField.name];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (fieldAffectsData(field) && field.saveToJWT) {
|
||||
result[field.name] = user[field.name];
|
||||
}
|
||||
|
||||
return result;
|
||||
}, {
|
||||
email,
|
||||
id: user.id,
|
||||
collection: collectionConfig.slug,
|
||||
});
|
||||
};
|
||||
@@ -6,13 +6,13 @@ import { PayloadRequest } from '../../express/types';
|
||||
import getCookieExpiration from '../../utilities/getCookieExpiration';
|
||||
import isLocked from '../isLocked';
|
||||
import sanitizeInternalFields from '../../utilities/sanitizeInternalFields';
|
||||
import { Field, fieldHasSubFields, fieldAffectsData } from '../../fields/config/types';
|
||||
import { User } from '../types';
|
||||
import { Collection } from '../../collections/config/types';
|
||||
import { afterRead } from '../../fields/hooks/afterRead';
|
||||
import unlock from './unlock';
|
||||
import { incrementLoginAttempts } from '../strategies/local/incrementLoginAttempts';
|
||||
import { authenticateLocalStrategy } from '../strategies/local/authenticate';
|
||||
import { getFieldsToSign } from './getFieldsToSign';
|
||||
|
||||
export type Result = {
|
||||
user?: User,
|
||||
@@ -121,28 +121,10 @@ async function login<TSlug extends keyof GeneratedTypes['collections']>(
|
||||
});
|
||||
}
|
||||
|
||||
const fieldsToSign = collectionConfig.fields.reduce((signedFields, field: Field) => {
|
||||
const result = {
|
||||
...signedFields,
|
||||
};
|
||||
|
||||
if (!fieldAffectsData(field) && fieldHasSubFields(field)) {
|
||||
field.fields.forEach((subField) => {
|
||||
if (fieldAffectsData(subField) && subField.saveToJWT) {
|
||||
result[subField.name] = user[subField.name];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (fieldAffectsData(field) && field.saveToJWT) {
|
||||
result[field.name] = user[field.name];
|
||||
}
|
||||
|
||||
return result;
|
||||
}, {
|
||||
const fieldsToSign = getFieldsToSign({
|
||||
collectionConfig,
|
||||
user,
|
||||
email,
|
||||
id: user.id,
|
||||
collection: collectionConfig.slug,
|
||||
});
|
||||
|
||||
await collectionConfig.hooks.beforeLogin.reduce(async (priorHook, hook) => {
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import jwt from 'jsonwebtoken';
|
||||
import { Response } from 'express';
|
||||
import url from 'url';
|
||||
import { Collection, BeforeOperationHook } from '../../collections/config/types';
|
||||
import { Forbidden } from '../../errors';
|
||||
import getCookieExpiration from '../../utilities/getCookieExpiration';
|
||||
import { Document } from '../../types';
|
||||
import { PayloadRequest } from '../../express/types';
|
||||
import { getFieldsToSign } from './getFieldsToSign';
|
||||
|
||||
export type Result = {
|
||||
exp: number,
|
||||
@@ -51,16 +53,32 @@ async function refresh(incomingArgs: Arguments): Promise<Result> {
|
||||
},
|
||||
} = args;
|
||||
|
||||
const opts = {
|
||||
expiresIn: args.collection.config.auth.tokenExpiration,
|
||||
};
|
||||
|
||||
if (typeof args.token !== 'string') throw new Forbidden(args.req.t);
|
||||
|
||||
const payload = jwt.verify(args.token, secret, {}) as Record<string, unknown>;
|
||||
delete payload.iat;
|
||||
delete payload.exp;
|
||||
const refreshedToken = jwt.sign(payload, secret, opts);
|
||||
const parsedURL = url.parse(args.req.url);
|
||||
const isGraphQL = parsedURL.pathname === config.routes.graphQL;
|
||||
|
||||
const user = await args.req.payload.findByID({
|
||||
id: args.req.user.id,
|
||||
collection: args.req.user.collection,
|
||||
req: args.req,
|
||||
depth: isGraphQL ? 0 : args.collection.config.auth.depth,
|
||||
});
|
||||
|
||||
const fieldsToSign = getFieldsToSign({
|
||||
collectionConfig,
|
||||
user: args?.req?.user,
|
||||
email: user?.email as string,
|
||||
});
|
||||
|
||||
const refreshedToken = jwt.sign(
|
||||
fieldsToSign,
|
||||
secret,
|
||||
{
|
||||
expiresIn: collectionConfig.auth.tokenExpiration,
|
||||
},
|
||||
);
|
||||
|
||||
const exp = (jwt.decode(refreshedToken) as Record<string, unknown>).exp as number;
|
||||
|
||||
if (args.res) {
|
||||
@@ -78,6 +96,12 @@ async function refresh(incomingArgs: Arguments): Promise<Result> {
|
||||
args.res.cookie(`${config.cookiePrefix}-token`, refreshedToken, cookieOptions);
|
||||
}
|
||||
|
||||
let response: Result = {
|
||||
user,
|
||||
refreshedToken,
|
||||
exp,
|
||||
};
|
||||
|
||||
// /////////////////////////////////////
|
||||
// After Refresh - Collection
|
||||
// /////////////////////////////////////
|
||||
@@ -85,23 +109,19 @@ async function refresh(incomingArgs: Arguments): Promise<Result> {
|
||||
await collectionConfig.hooks.afterRefresh.reduce(async (priorHook, hook) => {
|
||||
await priorHook;
|
||||
|
||||
args = (await hook({
|
||||
response = (await hook({
|
||||
req: args.req,
|
||||
res: args.res,
|
||||
exp,
|
||||
token: refreshedToken,
|
||||
})) || args;
|
||||
})) || response;
|
||||
}, Promise.resolve());
|
||||
|
||||
// /////////////////////////////////////
|
||||
// Return results
|
||||
// /////////////////////////////////////
|
||||
|
||||
return {
|
||||
refreshedToken,
|
||||
exp,
|
||||
user: payload,
|
||||
};
|
||||
return response;
|
||||
}
|
||||
|
||||
export default refresh;
|
||||
|
||||
Reference in New Issue
Block a user