Azure AD открыть BearerStrategy «Ошибка типа: self.success не является функцией» - PullRequest
0 голосов
/ 30 мая 2019

Я спросил это в https://github.com/AzureAD/passport-azure-ad/issues/427, но не получил ответа.Я чувствую, что это ошибка, которая мешает мне завершить работу, поэтому я все больше и больше пытаюсь получить ответ.Это что-то, что я делаю, или ошибка?

Я пишу вопрос, отличный от того, который у меня был до того, как я провел еще несколько исследований этой проблемы (я укажу, где начинаются различия).

Passport-Azure-AD версия 4.1.0 - https://www.npmjs.com/package/passport-azure-ad#52-bearerstrategy

Я настроил это из документации:

setup() {
    const findById = (id, fn) => {
        for (let i = 0, len = this.users.length; i < len; i++) {
            const user = this.users[i];
            if (user.sub === id) {
                logger.info('Found user: ', user);
                return fn(null, user);
            }
        }
        return fn(null, null);
    };

    this.bearerStrategy = new BearerStrategy(jwtOptions,
        (token: ITokenPayload, done: VerifyCallback) => {  
            findById(token.oid, (err, user) => {
                if (err) {
                    return done(err);
                }
                if (!user) {
                    // 'Auto-registration'
                    logger.info('User was added automatically as they were new. Their oid is: ', token.oid);
                    this.users.push(token);
                    this.owner = token.oid;
                    return done(null, token);
                }
                this.owner = token.oid;
                return done(null, user, token);
            });
        }
    );
    console.log(`setup bearerStrategy`);
}

jwtOptions Я использую:

Варианты такие:

const jwtOptions = {
    identityMetadata: 'https://login.microsoftonline.com/xyz/v2.0/.well-known/openid-configuration',
    clientID: '0123456789',
    loggingLevel: 'info',
    loggingNoPII: false,
    passReqToCallback: false
};

И запустить аутентификацию (из среднего места), используя следующее:

authenticate(request: express.Request) {
    this.bearerStrategy.authenticate(request, {session: false});
}

ПРИМЕЧАНИЕ Что этоотличается от документа, поскольку то, что у них было, не работает.

В строке не получается:

 return done(null, token);

С:

[2019-05-29T13:49:33.479] [INFO ] [AUTHSERVICE_LOGGER] - User was added automatically as they were new. Their oid is:  123

.../translateboard/node_modules/passport-azure-ad/lib/bearerstrategy.js:565
        return self.success(user, info);
                    ^
TypeError: self.success is not a function
    at verified (/Users/bbos/dev/dhs/translate/translateboard/node_modules/passport-azure-ad/lib/bearerstrategy.js:565:21)
    at findById (/Users/bbos/dev/dhs/translate/translateboard/server/src/services/AuthService.ts:106:32)
    at findById (/Users/bbos/dev/dhs/translate/translateboard/server/src/services/AuthService.ts:87:20)
    at Strategy.bearerStrategy.passport_azure_ad_1.BearerStrategy [as _verify] (/Users/bbos/dev/dhs/translate/translateboard/server/src/services/AuthService.ts:97:17)
    at jwt.verify (/Users/bbos/dev/dhs/translate/translateboard/node_modules/passport-azure-ad/lib/bearerstrategy.js:363:19)
    at /Users/bbos/dev/dhs/translate/translateboard/node_modules/passport-azure-ad/lib/jsonWebToken.js:80:16
    at process._tickCallback (internal/process/next_tick.js:61:11)

Отсюда отличается от исходного поста

Если я поставлю точку останова в коде, самообъект Object в BearerStrategy.js, где ошибка:

{
  "name": "oauth-bearer",
  "_options": {
    "identityMetadata": "https://login.microsoftonline.com/xyz/v2.0/.well-known/openid-configuration",
    "clientID": "0123456789",
    "loggingLevel": "info",
    "loggingNoPII": false,
    "passReqToCallback": false,
    "clockSkew": 300,
    "validateIssuer": true,
    "allowMultiAudiencesInToken": false,
    "audience": [
      "1234",
      "spn:1234"
    ],
    "isB2C": false,
    "_isCommonEndpoint": false,
    "_verify" = (token, done) => {...},
    "__proto__" = Strategy(...,
  }
}

И ниже__proto__:

 authenticate = function authenticateStrategy(req, options) {
 constructor = function Strategy(options, verifyFn) {
 failWithLog = function(message) {
 jwtVerify = function jwtVerifyFunc(req, token, metadata, optionsToValidate, done) {
 loadMetadata = function(params, next) {

Вы можете видеть, что в Passport-Azure-Ad нет success.Он определяет failWithLog https://github.com/AzureAD/passport-azure-ad/blob/e9684341920ac8ac41c55a1e7150d1765dced809/lib/bearerstrategy.js#L600 - они забыли добавить другие?

Паспорт определяет эти другие (https://github.com/jaredhanson/passport/blob/1c8ede35a334d672024e14234f023a87bdccaac2/lib/middleware/authenticate.js#L230), однако они находятся в закрытии и никогда не выставляются. Ниявляется родительским объектом Стратегии, для которого они определены. Единственное соединение с внешним миром - через открытый метод аутентификации https://github.com/jaredhanson/passport/blob/1c8ede35a334d672024e14234f023a87bdccaac2/lib/middleware/authenticate.js#L70

Однако, как видно, Passport-Azure-Ad определяет свой собственный метод аутентификации (https://github.com/AzureAD/passport-azure-ad/blob/e9684341920ac8ac41c55a1e7150d1765dced809/lib/bearerstrategy.js#L372) и никогда не вызывает passsport.

Мне кажется, это никогда не работало.

Может кто-нибудь подтвердить или не согласиться?

Я обновлю сообщение на https://github.com/AzureAD/passport-azure-ad/issues/427, чтобы сослаться на это.

Далее я собираюсь git bisect в хранилище, чтобы посмотреть, смогу ли я найти изменение, где раньше использовались эти отсутствующие методы или что-то еще, что выделяется.

1 Ответ

0 голосов
/ 31 мая 2019

Я могу подтвердить, что, поскольку мой код был написан, он никогда не будет работать.Было две основные проблемы:

Параметры передачи

В соответствии с моим комментарием к вопросу, я не предоставил информацию в вопросе, так как не думал, что она актуальна.Но это так.

Я использую TSED - TypeScript Express Decorators (https://tsed.io), и он заменяет экспресс-код промежуточного программного обеспечения, например:

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

На аннотированный класс промежуточного программного обеспечения - https://tsed.io/docs/middlewares.html

Так что теперь вызов passport.authenticate() осуществляется в методе use(), подобном этому, как я показал ранее ( ЭТО НЕПРАВИЛЬНО ):

@OverrideMiddleware(AuthenticatedMiddleware)
export class UserAuthMiddleware implements IMiddleware {
    constructor(@Inject() private authService: AuthService) {
    }

    public use(
        @EndpointInfo() endpoint: EndpointMetadata,
        @Request() request: express.Request,
        @Response() response: express.Response,
        @Next() next: express.NextFunction
    ) {
        const options = endpoint.get(AuthenticatedMiddleware) || {};
        Passport.authenticate('oauth-bearer', {session: false});  // <-- WRONG
        if (!request.isAuthenticated()) {
            throw new Forbidden('Forbidden');
        }
        next();
    }
}

ЧтоЯ не учел, что промежуточному программному обеспечению Express передается объект запроса. Так что мне действительно нужно было:

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

Необходимо использовать Passport.use()

Документация вводит в заблуждение.Я не слишком разбираюсь в паспорте. Я не особо задумывался об этом.

Доко (http://www.passportjs.org/packages/passport-azure-ad/) (на 5.2.1.1 Sample using the BearerStrategy) говорит использовать:

var bearerStrategy = new BearerStrategy(options,
  function(token, done) {
    log.info('verifying the user');
    log.info(token, 'was the token retreived');
    findById(token.oid, function(err, user) {
      if (err) {
        return done(err);
      }
      if (!user) {
        // "Auto-registration"
        log.info('User was added automatically as they were new. Their oid is: ', token.oid);
        users.push(token);
        owner = token.oid;
        return done(null, token);
      }
      owner = token.oid;
      return done(null, user, token);
    });
  }
);

Я знаю, что когда описываются другие стратегии (такие как 5.1 OIDCStrategy на той же странице):

passport.use(new OIDCStrategy({
    identityMetadata: config.creds.identityMetadata,
    clientID: config.creds.clientID,
    ...
  },
  function(iss, sub, profile, accessToken, refreshToken, done) {
    ...
  }
));

Они используют passport.use. Я думал о разнице (когда я впервые увидел ее) для1/2 секунды и пришел к выводу, что AAD BearerStrategy обрабатывает вещи по-разному, поскольку Azure выполняет вход в систему с использованием их msal.js library.И я не возвращался к этому, пока исправление № 1 выше не решило проблему.

Я пришел к выводу, что проекту TSED необходимо обновить их документацию / образцы (я сделаю это для них);и проекту Passport Azure AD необходимо обновить документацию.

Все еще есть некоторые проблемы, и я не знаю, кто виноват.Я писал об этом в Passport-Azure-Ad в среде TSED, кажется, работает асинхронно .

...