In loopback4, I have created custom authentication and authorization handlers, and wired them into the application. But the authorization handler is called only if the authentication function returns a UserProfile
object, and skips authorization for an undefined
user.
I want my Authorization handler to be called every time, no matter what the result of authentication is. I want to allow a non-authenticated call (don't know the user) to still flow through the authorization handler to let it judge whether to allow the call based on other factors besides the identity of the end user.
How do I make the Authorization handler be called every time?
export class MySequence implements SequenceHandler {
constructor(
@inject(SequenceActions.FIND_ROUTE) protected findRoute: FindRoute,
@inject(SequenceActions.PARSE_PARAMS) protected parseParams: ParseParams,
@inject(SequenceActions.INVOKE_METHOD) protected invoke: InvokeMethod,
@inject(SequenceActions.SEND) public send: Send,
@inject(SequenceActions.REJECT) public reject: Reject,
@inject(AuthenticationBindings.AUTH_ACTION)
protected authenticateRequest: AuthenticateFn,
) {}
// see: https://loopback.io/doc/en/lb4/Loopback-component-authentication.html#adding-an-authentication-action-to-a-custom-sequence
async handle(context: RequestContext) {
try {
const {request, response} = context;
const route = this.findRoute(request);
//call authentication action
console.log(`request path = ${request.path}`);
await this.authenticateRequest(request); // HOW DO I CONTROL AUTHORIZATION CALL THAT FOLLOWS?
// Authentication step done, proceed to invoke controller
const args = await this.parseParams(request, route);
const result = await this.invoke(route, args);
this.send(response, result);
} catch (error) {
if (
error.code === AUTHENTICATION_STRATEGY_NOT_FOUND ||
error.code === USER_PROFILE_NOT_FOUND
) {
Object.assign(error, {statusCode: 401 /* Unauthorized */});
}
this.reject(context, error);
}
}
}
The full example of code is lengthy, so I have posted it in a gist here.