Passport-Azure-Ad seems to run asynchronously (sti

2019-08-20 07:26发布

问题:

The traditional way of running Passport strategies in nodejs express middleware is:

server.get('/api/tasks', passport.authenticate('oauth-bearer', { session: false }));

I am using https://tsed.io, ("typescript express decorators") and referencing this passport strategy it is done like:

class MyCtrl {
    @Get('/api/tasks')
    @UseBefore(passport.authenticate('oauth-bearer', { session: false }))
    get() {
         ...
    } 
}

This works perfectly.

you can also run it as a detached middleware. Something like:

@Post('/search')
@CustomAuth({role: 'admin', scope: ['admin']})
async search(@Req() request: Req, @BodyParams() query: TranslationApiQuery): Promise<TranslationApiModel[]> {
     ...

export function CustomAuth(options = {}): Function {
    return applyDecorators(
        UseAuth(CustomAuthMiddleware), 
         ...

@Middleware()
export class CustomAuthMiddleware implements IMiddleware {
    public use(
        @Req() request: Express.Request, @Res() response: Express.Response, @EndpointInfo() endpoint: EndpointInfo,
        @Next() next: Express.NextFunction) {
              // retrieve options given to the decorator
              const options = endpoint.get(CustomAuthMiddleware) || {};

              Passport.authenticate('oauth-bearer', {session: false}})(request, response, next);
              ...

Which I was trying to use so-as to have access to the roles and scopes defined on the endpoint. But this use of passport.authenticate doesn't work. The https://github.com/AzureAD/passport-azure-ad/blob/dev/lib/bearerstrategy.js uses async.waterfall() and this forces async behaviour. But doesn't return a promise so cannot be waited upon.

I don't understand why the traditional uses of passport.authenticate works. Can someone explain why? Is there an easy way around this (without rewriting bearerstrategy.js)? Could bearerstrategy.js be easily rewritten to allow for both uses?


I originally had this question at Passport-Azure-Ad seems to run asynchronously but I needed to simplify the question. Plus I wrote an answer that proved to be not fully correct but wanted to keep it by adding to the question. Overall it was becoming a mess so it seemed that it was easier to closes that old one and start this one a-new.