import { AuthenticationError } from 'apollo-server'; import { User } from '../../entities'; import AccessTokenManager from '../../services/AccessTokenManager'; type GetUserFromToken = { user?: User; authError?: Error; potentiallyRefreshedAccessToken?: string; potentiallyRefreshedRefreshToken?: string; }; type GetUserFromTokenOptions = { accessToken?: string; refreshToken?: string; }; export const getUserFromToken = async ({ accessToken, refreshToken, }: GetUserFromTokenOptions): Promise => { let userId, potentiallyRefreshedRefreshToken; let potentiallyRefreshedAccessToken = accessToken; try { const accessTokenManager = new AccessTokenManager(); if (!accessToken && !refreshToken) { throw new AuthenticationError( 'Must provider access token or refresh token' ); } // attemp to refresh without the token if (!accessToken && refreshToken) { const { accessToken } = await accessTokenManager.refreshAccessTokenWithRefreshTokenOrFail( refreshToken ); potentiallyRefreshedAccessToken = accessToken; } if (!potentiallyRefreshedAccessToken) { throw new AuthenticationError( 'Must provider access token or refresh token' ); } ({ sub: userId, refreshToken: potentiallyRefreshedRefreshToken } = await accessTokenManager.verifyAccessTokenOrFail( potentiallyRefreshedAccessToken, refreshToken )); } catch (error) { return { authError: error && error instanceof Error && error.message ? new AuthenticationError(error.message) : new AuthenticationError('Token is invalid'), }; } if (!userId) { return { authError: new AuthenticationError('Token is invalid') }; } const user = await User.findOne({ where: { id: userId, }, }); if (!user) { return { authError: new AuthenticationError('User does not exist') }; } return { user, potentiallyRefreshedRefreshToken, potentiallyRefreshedAccessToken, }; };