import { inject , injectable } from '@loopback/core' ; import { asSpecEnhancer , HttpErrors , mergeSecuritySchemeToSpec , OASEnhancer , OpenApiSpec , Request , } from '@loopback/rest' ; import { UserProfile } from '@loopback/security' ; import { asAuthStrategy , AuthenticationStrategy } from '../../../types' ; import { JWTAuthenticationStrategyBindings } from '../keys' ; import { JWTService } from '../services/jwt-service' ; @ injectable ( asAuthStrategy , asSpecEnhancer ) export class JWTAuthenticationStrategy implements AuthenticationStrategy , OASEnhancer { name = 'jwt' ; constructor ( @ inject ( JWTAuthenticationStrategyBindings . TOKEN_SERVICE ) public tokenService ) { } async authenticate ( request ) { const token = this . extractCredentials ( request ) ; const userProfile = await this . tokenService . verifyToken ( token ) ; return userProfile ; } extractCredentials ( request ) { if ( ! request . headers . authorization ) { throw new HttpErrors . Unauthorized ( `Authorization header not found.` ) ; } const authHeaderValue = request . headers . authorization ; if ( ! authHeaderValue . startsWith ( 'Bearer' ) ) { throw new HttpErrors . Unauthorized ( `Authorization header is not of type 'Bearer'.` ) ; } const parts = authHeaderValue . split ( ' ' ) ; if ( parts . length !== 2 ) throw new HttpErrors . Unauthorized ( `Authorization header value has too many parts. It must follow the pattern: 'Bearer xx.yy.zz' where xx.yy.zz is a valid JWT token.` ) ; const token = parts [ 1 ] ; return token ; } modifySpec ( spec ) { return mergeSecuritySchemeToSpec ( spec , this . name , { type : 'http' , scheme : 'bearer' , bearerFormat : 'JWT' , } ) ; } }