@greenpress/auth
Version:
Express Passport authentication service
94 lines (84 loc) • 3.13 kB
text/typescript
import {
verifyToken,
getUniqueId,
setCookie,
getSignedToken,
} from '../services/tokens';
import { getUserIfTokenExists, updateToken } from '../services/users';
import { cookieTokenExpiration, privilegedRoles, cookieTokenVerificationTime, processedCookieExpiration } from '../../config';
import { NextFunction, RequestHandler, Response } from 'express';
import { AuthRequest } from '../../types';
import { cacheManager } from "../utils/cache-manager";
function oAuthVerify(req: AuthRequest, _res: Response, next: NextFunction): Promise<void> {
// get the last part from a authorization header string like "bearer token-value"
const token = req.headers.authorization!.split(' ')[1];
const tenant = (req.headers.tenant = req.headers.tenant as string || '0');
return verifyToken(token, tenant)
.then((payload) => setUserPayload(payload, req, next))
.catch(() => {
next();
});
}
async function cookieVerify(req: AuthRequest, res: Response, next: NextFunction): Promise<void> {
// get the last part from a authorization header string like "bearer token-value"
const token = req.signedCookies.token || req.cookies.token;
const tenant = (req.headers.tenant = req.headers.tenant as string || '0');
try {
const payload: any = await verifyToken(token, tenant);
const created = Number(payload.tokenIdentifier?.split(':')[0]);
if ((Date.now() - created < cookieTokenVerificationTime) || await isCookieProcessed(payload.tokenIdentifier)) {
setUserPayload(payload, req, next);
return;
}
const newCookieIdentifier = getUniqueId();
const [user] = await Promise.all([
getUserIfTokenExists(
payload.tenant,
payload.sub,
payload.tokenIdentifier
),
setCookieAsProcessed(payload.tokenIdentifier)
]);
await updateToken(
user,
'cookie',
payload.tokenIdentifier,
newCookieIdentifier
);
const { token: newToken, payload: newPayload } = getSignedToken(
user,
newCookieIdentifier,
String(cookieTokenExpiration / 1000)
);
setCookie(res, newToken);
setUserPayload(newPayload, req, next);
} catch (e) {
next();
}
}
async function setCookieAsProcessed(tokenIdentifier: string) {
await cacheManager.setItem(tokenIdentifier, 'tokenIdentifier', {ttl: processedCookieExpiration});
}
async function isCookieProcessed(tokenIdentifier: string) {
const res = await cacheManager.getItem(tokenIdentifier);
return res !== undefined ? true : false;
}
function setUserPayload(payload: any, req: AuthRequest, next: NextFunction) {
req.userPayload = payload;
req.userPayload.isPrivileged = payload.roles.some((role: string) =>
privilegedRoles.includes(role)
);
next();
}
/**
* The Auth Checker middleware function.
*/
export default <RequestHandler>function verifyUser(req: AuthRequest, res: Response, next: NextFunction) {
if (req.cookies.token || req.signedCookies.token) {
cookieVerify(req, res, next).catch(next);
} else if (req.headers.authorization) {
oAuthVerify(req, res, next).catch(next);
} else {
next();
}
};