0

我有一个使用 passport-azure-ad 的 BearerStrategy 保护的 Node.js API。

我有另一个客户端应用程序,它为我提供了访问 Microsoft Graph 的令牌。我已使用该令牌访问 Microsoft Graph 并使其正常工作。

但是当我使用相同的令牌在我的 API 中进行身份验证时,它会抛出这个错误。

响应正文:未经授权响应状态:401

这是我的护照配置以保护 API

const express = require('express');
const bodyParser = require('body-parser');
const morgan = require('morgan');
const passport = require('passport');
const OIDCBearerStrategy = require('passport-azure-ad').BearerStrategy;

const app = express();

app.use(bodyParser.json({ limit: '50mb' }));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(morgan(':method :url :date :remote-addr :status :response-time'));
app.use(passport.initialize());
app.use(passport.session());

const passportConfiguration = {
  clientID: <<<Application ID>>>,
  identityMetadata: 'https://login.microsoftonline.com/<<<Tenant ID>>>/.well-known/openid-configuration',
  audience: 'https://graph.microsoft.com', // I've even tried setting this to my App ID URI of Application registration
  validateIssuer: true, // if you have validation on, you cannot have users from multiple tenants sign in
  passReqToCallback: false,
  loggingLevel: 'info',
};

const OIDCStrategy = new OIDCBearerStrategy(passportConfiguration, (token, done) => {
  console.log('Verifying the User...');
  console.log('Access Token:', token);

  done(null, token);
});

passport.use(OIDCStrategy);

app.get('/', (req, res) => {
  res.status(200).send('Welcome!');
});

app.get('/users', passport.authenticate('oauth-bearer', {
  session: false,
}), (req, res) => {
  res.status(200).send('Take users...');
});

app.listen(8082, () => {
  console.log('App is running on http://localhost:8082');
});

因此,当我点击主页“/”时,它会显示正确的响应,因为它没有被护照的安全层覆盖。

但是当我用标题点击http://localhost:8082/users 时: Authorization: Bearer <<>>

它返回未经授权,状态为 401。但我尝试使用相同的令牌访问 Microsoft Graph,我得到了响应。

这些是护照日志:

{"name":"AzureAD: Metadata Parser","hostname":"Deadman-INC","pid":5036,"level":30,"msg":"Parsing JSON retreived from the endpoint","time":"2019-01-15T07:54:36.374Z","v":0}
{"name":"AzureAD: Metadata Parser","hostname":"Deadman-INC","pid":5036,"level":30,"msg":"Request to update the Open ID Connect Metadata","time":"2019-01-15T07:54:36.378Z","v":0}
{"name":"AzureAD: Bearer Strategy","hostname":"Deadman-INC","pid":5036,"level":30,"msg":"In Strategy.prototype.authenticate: received metadata","time":"2019-01-15T07:54:36.637Z","v":0}
{"name":"AzureAD: Bearer Strategy","hostname":"Deadman-INC","pid":5036,"level":30,"msg":"In Strategy.prototype.authenticate: we will validate the options","time":"2019-01-15T07:54:36.640Z","v":0}
{"name":"AzureAD: Bearer Strategy","hostname":"Deadman-INC","pid":5036,"level":30,"msg":"In Strategy.prototype.authenticate: access_token is received from request header","time":"2019-01-15T07:54:36.643Z","v":0}
{"name":"AzureAD: Bearer Strategy","hostname":"Deadman-INC","pid":5036,"level":30,"msg":"In Strategy.prototype.jwtVerify: token is decoded","time":"2019-01-15T07:54:36.649Z","v":0}
{"name":"AzureAD: Metadata Parser","hostname":"Deadman-INC","pid":5036,"level":30,"msg":"working on key","time":"2019-01-15T07:54:36.655Z","v":0}
{"name":"AzureAD: Bearer Strategy","hostname":"Deadman-INC","pid":5036,"level":30,"msg":"PEMkey generated","time":"2019-01-15T07:54:36.666Z","v":0}
{"name":"AzureAD: Bearer Strategy","hostname":"Deadman-INC","pid":5036,"level":30,"msg":"authentication failed due to: In Strategy.prototype.jwtVerify: cannot verify token","time":"2019-01-15T07:54:36.675Z","v":0}

谁能帮我解决这个问题?

4

1 回答 1

1

万一这还没有解决,我正在使用 OIDCStrategy 并且它工作正常(在我首先打破了 BearerStrategy 之后)。它在验证回调中返回一个 access_token,您可以将其插入 API 调用。它在文档中,但是如果您筛选模块的代码本身,您可以在评论中找到更好的解释。这是我的代码(正在进行中),HTH,会为我省去很多麻烦。

   const passport = require("passport");
   const OIDCStrategy = require("passport-azure-ad").OIDCStrategy;

var accessToken = "";

app.use(session({
  secret: process.env.SECRET,
  resave: false,
  saveUninitialized: true,
}));

app.use(passport.initialize());
app.use(passport.session());
passport.use(new OIDCStrategy({
      identityMetadata: process.env.OAUTH_ID_METADATA,
      clientID: process.env.OAUTH_APP_ID,
      responseType: "code id_token",
      responseMode: "form_post",
      redirectUrl: process.env.OAUTH_REDIRECT_URI,
      clientSecret: process.env.OAUTH_APP_PASSWORD,
      scope: "https://graph.microsoft.com/.default",
      passReqToCallback: true,
      loggingLevel: "info",
      loggingNoPII: false,
    },
 function(req, iss, sub, profile, jwtClaims, access_token, refresh_token, params, done) {
      accessToken = access_token;
      User.findOrCreate({username_1: sub, token: access_token}, function (err, user) {
        if (err) { return done(err); }
        if (!user) { return done(null, false); }
        return done(null, user, access_token);
      });
    }
  ));

然后对于 API 调用:

 url: "https://graph.microsoft.com/v1.0/me",
    headers : {
        "Authorization" : "Bearer "+accessToken,
        "Content-Type" : "application/json",
        "Host" : "graph.microsoft.com"
    }
于 2019-12-09T10:19:45.783 回答