import { Lifecycle , Request , ResponseToolkit } from '@hapi/hapi' ; import { Logger } from '../../logging' ; import { HapiResponseAdapter , OpenSearchDashboardsRequest , IOpenSearchDashboardsResponse , lifecycleResponseFactory , LifecycleResponseFactory , isOpenSearchDashboardsResponse , ResponseHeaders , } from '../router' ; public export enum AuthResultType { authenticated = 'authenticated' , notHandled = 'notHandled' , redirected = 'redirected' } public export interface Authenticated extends AuthResultParams { type : AuthResultType . authenticated ; } public export interface AuthNotHandled { type : AuthResultType . notHandled ; } public export interface AuthRedirected extends AuthRedirectedParams { type : AuthResultType . redirected ; } public export type AuthResult = Authenticated | AuthNotHandled | AuthRedirected ; const authResult = { authenticated ( data = { } ) { return { type : AuthResultType . authenticated , state : data . state , requestHeaders : data . requestHeaders , responseHeaders : data . responseHeaders , } ; } , notHandled ( ) { return { type : AuthResultType . notHandled , } ; } , redirected ( headers ) { return { type : AuthResultType . redirected , headers , } ; } , isAuthenticated ( result ) { return result ?. type === AuthResultType . authenticated ; } , isNotHandled ( result ) { return result ?. type === AuthResultType . notHandled ; } , isRedirected ( result ) { return result ?. type === AuthResultType . redirected ; } , } ; public export type AuthHeaders = Record < string , string | string [ ] > ; public export interface AuthResultParams { /**
     * Data to associate with an incoming request. Any downstream plugin may get access to the data.
     */ state ? : Record < string , any > ; /**
     * Auth specific headers to attach to a request object.
     * Used to perform a request to  on behalf of an authenticated user.
     */ requestHeaders ? : AuthHeaders ; /**
     * Auth specific headers to attach to a response object.
     * Used to send back authentication mechanism related headers to a client when needed.
     */ responseHeaders ? : AuthHeaders ; } public export interface AuthRedirectedParams { /**
     * Headers to attach for auth redirect.
     * Must include "location" header
     */ headers : { location : string ; } & ResponseHeaders ; } public export interface AuthToolkit { /** Authentication is successful with given credentials, allow request to pass through */ authenticated : ( data ? : AuthResultParams ) => AuthResult ; /**
     * User has no credentials.
     * Allows user to access a resource when authRequired: 'optional'
     * Rejects a request when authRequired: true
     * */ notHandled : ( ) => AuthResult ; /**
     * Redirects user to another location to complete authentication when authRequired: true
     * Allows user to access a resource without redirection when authRequired: 'optional'
     * */ redirected : ( headers : { location : string ; } & ResponseHeaders ) => AuthResult ; } const toolkit = { authenticated : authResult . authenticated , notHandled : authResult . notHandled , redirected : authResult . redirected , } ; /**
 * See  AuthToolkit .
 *  public export type AuthenticationHandler = ( request : OpenSearchDashboardsRequest , response : LifecycleResponseFactory , toolkit : AuthToolkit ) => AuthResult | IOpenSearchDashboardsResponse | Promise < AuthResult | IOpenSearchDashboardsResponse > ; public export function adoptToHapiAuthFormat ( fn , log , onAuth = ( ) => undefined ) { return async function interceptAuth ( request , responseToolkit ) : Promise < Lifecycle . ReturnValue > { const hapiResponseAdapter = new HapiResponseAdapter ( responseToolkit ) ; const opensearchDashboardsRequest = OpenSearchDashboardsRequest . from ( request , undefined , false ) ; try { const result = await fn ( opensearchDashboardsRequest , lifecycleResponseFactory , toolkit ) ; if ( isOpenSearchDashboardsResponse ( result ) ) { return hapiResponseAdapter . handle ( result ) ; } if ( authResult . isAuthenticated ( result ) ) { onAuth ( request , { state : result . state , requestHeaders : result . requestHeaders , responseHeaders : result . responseHeaders , } ) ; return responseToolkit . authenticated ( { credentials : result . state || { } } ) ; } if ( authResult . isRedirected ( result ) ) { if ( opensearchDashboardsRequest . route . options . authRequired === 'optional' ) { return responseToolkit . continue ; } return hapiResponseAdapter . handle ( lifecycleResponseFactory . redirected ( { headers : result . headers , } ) ) ; } if ( authResult . isNotHandled ( result ) ) { if ( opensearchDashboardsRequest . route . options . authRequired === 'optional' ) { return responseToolkit . continue ; } return hapiResponseAdapter . handle ( lifecycleResponseFactory . unauthorized ( ) ) ; } throw new Error ( `Unexpected result from Authenticate. Expected AuthResult or OpenSearchDashboardsResponse, but given: ${ result }.` ) ; } catch ( error ) { log . error ( error ) ; return hapiResponseAdapter . toInternalError ( ) ; } } ; }