Azure AD open BearerStrategy "TypeError: self.success is not a function"
Azure AD open BearerStrategy "TypeError: self.success is not a function"
我在 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});
}
注意 这与 doco 不同,因为他们拥有的东西不起作用。
在线失败:
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)
这里和原来的不一样post
如果我在代码中放置断点,BearerStrategy.js 中的 self Object 错误是:
{
"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) however they are in a closure and never exposed. Nor is the parent Strategy object that they are defined on. The only connection with the outside is through the exposed authenticate method 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 更新 post 来参考这个。
接下来,我将前往 git bisect
存储库,看看是否可以找到一个更改,其中曾经定义了那些缺失的方法或其他突出的内容。
我可以确认我编写的代码永远不会工作。有两个主要问题:
传递参数
根据我对问题的评论,我忽略了在问题中提供信息,因为我认为它不相关。但确实如此。
我正在使用 TSED - TypeScript Express Decorators (https://tsed.io),它取代了 express 中间件代码,例如:
server.get('/api/tasks', passport.authenticate('oauth-bearer', { session: false }), listTasks);
带有注释的中间件 class - 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中间件传递了request对象。所以我真正需要的是:
Passport.authenticate('oauth-bearer', {session: false})(request, response, next); // <-- CORRECT
必须使用Passport.use()
文档具有误导性。鉴于我对 Passport 不是很了解,所以我没有考虑太多。
doco (http://www.passportjs.org/packages/passport-azure-ad/) (at 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 秒的差异(当我第一次看到它时)并得出结论,鉴于登录是由 Azure 使用他们的 msal.js
库完成的,AAD BearerStrategy
处理事情的方式不同。在上面的修复 #1 没有解决问题之前,我没有重新访问它。
我得出结论,TSED 项目需要更新他们的文档/样本(我会为他们做这件事); Passport Azure AD
项目需要更新他们的 doco。
还有一些问题,不知道是谁的错。我在 Passport-Azure-Ad in TSED framework seems to run asynchronously 上写了这些。
我在 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});
}
注意 这与 doco 不同,因为他们拥有的东西不起作用。
在线失败:
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)
这里和原来的不一样post
如果我在代码中放置断点,BearerStrategy.js 中的 self Object 错误是:
{
"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) however they are in a closure and never exposed. Nor is the parent Strategy object that they are defined on. The only connection with the outside is through the exposed authenticate method 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 更新 post 来参考这个。
接下来,我将前往 git bisect
存储库,看看是否可以找到一个更改,其中曾经定义了那些缺失的方法或其他突出的内容。
我可以确认我编写的代码永远不会工作。有两个主要问题:
传递参数
根据我对问题的评论,我忽略了在问题中提供信息,因为我认为它不相关。但确实如此。
我正在使用 TSED - TypeScript Express Decorators (https://tsed.io),它取代了 express 中间件代码,例如:
server.get('/api/tasks', passport.authenticate('oauth-bearer', { session: false }), listTasks);
带有注释的中间件 class - 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中间件传递了request对象。所以我真正需要的是:
Passport.authenticate('oauth-bearer', {session: false})(request, response, next); // <-- CORRECT
必须使用Passport.use()
文档具有误导性。鉴于我对 Passport 不是很了解,所以我没有考虑太多。
doco (http://www.passportjs.org/packages/passport-azure-ad/) (at 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 秒的差异(当我第一次看到它时)并得出结论,鉴于登录是由 Azure 使用他们的 msal.js
库完成的,AAD BearerStrategy
处理事情的方式不同。在上面的修复 #1 没有解决问题之前,我没有重新访问它。
我得出结论,TSED 项目需要更新他们的文档/样本(我会为他们做这件事); Passport Azure AD
项目需要更新他们的 doco。
还有一些问题,不知道是谁的错。我在 Passport-Azure-Ad in TSED framework seems to run asynchronously 上写了这些。