Reputation: 179
I've a Node.js API which is protected using passport-azure-ad's BearerStrategy.
I've another Client App which provides me a token to access Microsoft Graph. I've used that token to access Microsoft Graph and its working properly.
But when I use the same token to authenticate in my API its throwing me this error.
Response body: Unauthorized Response status: 401
This is my configuration of passport to protect the 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');
});
So when I hit the homepage '/' it's showing the proper response as it's not covered with the security layer of passport.
But when I hit http://localhost:8082/users with header: Authorization: Bearer <<>>
It's returning Unauthorized with status 401. But I've tried to access Microsoft Graph using same token and I'm getting the response.
These are the passsport log:
{"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}
Could anyone help me out in this?
Upvotes: 0
Views: 2582
Reputation: 11
In case this isn't solved yet, I'm using the OIDCStrategy and it works fine (after also breaking my head over the BearerStrategy first). It returns an access_token in the verify callback that you can plug into your API call. It's in the docs, but you can find a better explanation in the comments if you sift through the module's code itself. Here's my code (work in progress), HTH, would've saved me a lot of headscratching.
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);
});
}
));
Then for the API call:
url: "https://graph.microsoft.com/v1.0/me",
headers : {
"Authorization" : "Bearer "+accessToken,
"Content-Type" : "application/json",
"Host" : "graph.microsoft.com"
}
Upvotes: 1