import { TokenService } from '@loopback/authentication' ; import { BindingScope , inject , injectable , uuid } from '@loopback/core' ; import { repository } from '@loopback/repository' ; import { HttpErrors } from '@loopback/rest' ; import { securityId , UserProfile } from '@loopback/security' ; import { promisify } from 'util' ; import { RefreshTokenServiceBindings , TokenServiceBindings , UserServiceBindings , } from '../keys' ; import { RefreshToken , RefreshTokenRelations } from '../models' ; import { RefreshTokenRepository } from '../repositories' ; import { TokenObject } from '../types' ; import { MyUserService } from './user.service' ; const jwt = require ( 'jsonwebtoken' ) ; const signAsync = promisify ( jwt . sign ) ; const verifyAsync = promisify ( jwt . verify ) ; @ injectable ( { scope : BindingScope . TRANSIENT } ) export class RefreshtokenService { constructor ( @ inject ( RefreshTokenServiceBindings . REFRESH_SECRET ) private refreshSecret , @ inject ( RefreshTokenServiceBindings . REFRESH_EXPIRES_IN ) private refreshExpiresIn , @ inject ( RefreshTokenServiceBindings . REFRESH_ISSUER ) private refreshIssure , @ repository ( RefreshTokenRepository ) public refreshTokenRepository , @ inject ( UserServiceBindings . USER_SERVICE ) public userService , @ inject ( TokenServiceBindings . TOKEN_SERVICE ) public jwtService ) { } /**
     * Generate a refresh token, bind it with the given user profile + access
     * token, then store them in backend.
     */ async generateToken ( userProfile , token ) { const data = { token : uuid ( ) , } ; const refreshToken = await signAsync ( data , this . refreshSecret , { expiresIn : Number ( this . refreshExpiresIn ) , issuer : this . refreshIssure , } ) ; const result = { accessToken : token , refreshToken : refreshToken , } ; await this . refreshTokenRepository . create ( { userId : userProfile [ securityId ] , refreshToken : result . refreshToken , } ) ; return result ; } async refreshToken ( refreshToken ) { try { if ( ! refreshToken ) { throw new HttpErrors . Unauthorized ( `Error verifying token : 'refresh token' is null` ) ; } const userRefreshData = await this . verifyToken ( refreshToken ) ; const user = await this . userService . findUserById ( userRefreshData . userId . toString ( ) ) ; const userProfile = this . userService . convertToUserProfile ( user ) ; const token = await this . jwtService . generateToken ( userProfile ) ; return { accessToken : token , } ; } catch ( error ) { throw new HttpErrors . Unauthorized ( `Error verifying token : ${ error . message }` ) ; } } async revokeToken ( refreshToken ) { try { await this . refreshTokenRepository . delete ( new RefreshToken ( { refreshToken : refreshToken } ) ) ; } catch ( e ) { } } param refreshToken async verifyToken ( refreshToken ) { try { await verifyAsync ( refreshToken , this . refreshSecret ) ; const userRefreshData = await this . refreshTokenRepository . findOne ( { where : { refreshToken : refreshToken } , } ) ; if ( ! userRefreshData ) { throw new HttpErrors . Unauthorized ( `Error verifying token : Invalid Token` ) ; } return userRefreshData ; } catch ( error ) { throw new HttpErrors . Unauthorized ( `Error verifying token : ${ error . message }` ) ; } } }