'use strict' const JWT = require('jsonwebtoken') const crypto = require('crypto') const hashToken = async token => { const salt = process.env.APP_SESSION_SALT try { return crypto.createHmac('sha256', salt).update(token).digest('hex') } catch (err) { throw new Error(err.message) } } const createToken = (data, expiration = 600) => { const key = process.env.APP_SECRET const obj = {} Object.assign(obj, { ...data }) return JWT.sign(obj, key, { expiresIn: expiration }) } const validateToken = token => { const key = process.env.APP_SECRET try { return JWT.verify(token, key) } catch (err) { return { payload: null, message: err.message } } } module.exports = options => { return { key: options.jwtKey, verifyOptions: { algorithms: ['HS256'], }, // TODO: Naming conventions need to be reversed again?? validate: async (decoded, request, h) => { const sessionTokenFromHeaders = request.headers.authorization const hashedSessionTokenFromHeaders = await hashToken( sessionTokenFromHeaders, ) const activeSession = request.server.app.activeSessions[hashedSessionTokenFromHeaders] if (!activeSession) throw new Error( `No session found for ${hashedSessionTokenFromHeaders}`, ) const sessionToken = activeSession.sessionToken const accessToken = activeSession.accessToken const validatedSessionToken = validateToken(sessionToken) const validatedAccessToken = validateToken(accessToken) if (!validatedAccessToken.payload) { console.log('accessToken no longer valid, reissuing... ') activeSession.accessToken = createToken( { payload: validatedSessionToken.payload }, // NOTE: Expiration of new sessionToken set for 200 seconds (testing) 100, ) } try { const validatedJwt = JWT.verify( sessionToken, process.env.APP_SECRET, ) return { isValid: true, credentials: validatedJwt.email } } catch (err) { return { isValid: false, error: err.message } } }, } }