import { config , Getter , inject , injectable , Provider , Setter , } from '@loopback/core' ; import { asMiddleware , Middleware , RedirectRoute , Request , RestMiddlewareGroups , } from '@loopback/rest' ; import { SecurityBindings , UserProfile } from '@loopback/security' ; import { AuthenticationBindings } from '../keys' ; import { AuthenticateFn , AuthenticationOptions , AuthenticationStrategy , AUTHENTICATION_STRATEGY_NOT_FOUND , USER_PROFILE_NOT_FOUND , } from '../types' ; example export class AuthenticateActionProvider implements Provider < AuthenticateFn > { constructor ( @ inject . getter ( AuthenticationBindings . STRATEGY ) readonly getStrategies , @ inject . setter ( SecurityBindings . USER ) readonly setCurrentUser , @ inject . setter ( AuthenticationBindings . AUTHENTICATION_REDIRECT_URL ) readonly setRedirectUrl , @ inject . setter ( AuthenticationBindings . AUTHENTICATION_REDIRECT_STATUS ) readonly setRedirectStatus , @ config ( { fromBinding : AuthenticationBindings . COMPONENT } ) private readonly options = { } ) { } returns value ( ) { return request => this . action ( request ) ; } param request async action ( request ) { let strategies = await this . getStrategies ( ) ; if ( strategies == null ) { return undefined ; } strategies = Array . isArray ( strategies ) ? strategies : [ strategies ] ; const authErrors = [ ] ; for ( const strategy of strategies ) { let authResponse = undefined ; try { authResponse = await strategy . authenticate ( request ) ; } catch ( err ) { if ( this . options . failOnError ) { throw err ; } authErrors . push ( err ) ; } if ( RedirectRoute . isRedirectRoute ( authResponse ) ) { const redirectOptions = authResponse ; this . setRedirectUrl ( redirectOptions . targetLocation ) ; this . setRedirectStatus ( redirectOptions . statusCode ) ; return ; } else if ( authResponse != null ) { const userProfile = authResponse as UserProfile ; this . setCurrentUser ( userProfile ) ; return userProfile ; } } if ( authErrors . length ) { throw authErrors [ 0 ] ; } const error = new Error ( `User profile not returned from strategy's authenticate function` ) ; Object . assign ( error , { code : USER_PROFILE_NOT_FOUND , } ) ; throw error ; } } @ injectable ( asMiddleware ( { group : RestMiddlewareGroups . AUTHENTICATION , upstreamGroups : [ RestMiddlewareGroups . FIND_ROUTE ] , } ) ) export class AuthenticationMiddlewareProvider implements Provider < Middleware > { constructor ( @ inject ( AuthenticationBindings . AUTH_ACTION ) private authenticate ) { } value ( ) { return async ( ctx , next ) => { try { await this . authenticate ( ctx . request ) ; } catch ( error ) { if ( error . code === AUTHENTICATION_STRATEGY_NOT_FOUND || error . code === USER_PROFILE_NOT_FOUND ) { error . statusCode = 401 ; } throw error ; } return next ( ) ; } ; } }