I am using 'passport-azure-ad-oauth2' npm module, to get an access token, which I could then pass to the MS Graph API.
passport.use(new AzureAdOAuth2Strategy({
clientID: process.env.OUTLOOK_CLIENT_ID,
clientSecret: process.env.OUTLOOK_SECRET,
callbackURL: '/auth/outlook/callback',
},
function (accesstoken: any, refresh_token: any, params: any, profile, done) {
logger.info('Completed azure sign in for : ' + JSON.stringify(profile));
logger.info('Parameters returned: ' + JSON.stringify(params));
const decodedIdToken: any = jwt.decode(params.id_token);
logger.info('Outlook Access Token:' + accesstoken);
logger.info('Decoded Token: ' + JSON.stringify(decodedIdToken, null, 2));
process.env['OUTLOOK_ACCESS_TOKEN'] = accesstoken;
// add new user with token or update user's token here, in the database
}));
And then, using '@microsoft/microsoft-graph-client' npm module, to fetch Calendar events from the Graph API as follows:
try {
const client = this.getAuthenticatedClient(process.env['OUTLOOK_ACCESS_TOKEN']);
const resultSet = await client
.api('users/' + userId + '/calendar/events')
.select('subject,organizer,start,end')
.get();
logger.info(JSON.stringify(resultSet, null, 2));
} catch (err) {
logger.error(err);
}
getAuthenticatedClient(accessToken) {
logger.info('Using accestoken for initialising Graph Client: ' + accessToken);
const client = Client.init({
// Use the provided access token to authenticate requests
authProvider: (done) => {
done(null, accessToken);
}
});
return client;
}
However, however, using the accessToken provided on Successful Login, I get the following error : CompactToken parsing failed with error code: 80049217
Any suggestions what am I doing incorrectly ???
UPDATE : These are the scope I am using : 'openid,profile,offline_access,calendars.read'
UPDATE : After editing the scopes a bit, now I am getting the following error : Invalid Audience.
On decoding the token received at jwt.ms, this is the value for 'aud': "00000002-0000-0000-c000-000000000000"
Is it the case that passport-azure-ad-oauth2 is the wrong library for retrieving tokens for MS Graph API ?
According to my test, we can use the following code to get the access token. app.js
require('dotenv').config();
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var session = require('express-session');
var flash = require('connect-flash');
var passport = require('passport');
var OIDCStrategy = require('passport-azure-ad').OIDCStrategy;
// Configure simple-oauth2
const oauth2 = require('simple-oauth2').create({
client: {
id: process.env.OAUTH_APP_ID,
secret: process.env.OAUTH_APP_PASSWORD
},
auth: {
tokenHost: process.env.OAUTH_AUTHORITY,
authorizePath: process.env.OAUTH_AUTHORIZE_ENDPOINT,
tokenPath: process.env.OAUTH_TOKEN_ENDPOINT
}
});
var users = {};
// Passport calls serializeUser and deserializeUser to
// manage users
passport.serializeUser(function(user, done) {
// Use the OID property of the user as a key
users[user.profile.oid] = user;
done (null, user.profile.oid);
});
passport.deserializeUser(function(id, done) {
done(null, users[id]);
});
// Callback function called once the sign-in is complete
// and an access token has been obtained
async function signInComplete(iss, sub, profile, accessToken, refreshToken, params, done) {
if (!profile.oid) {
return done(new Error("No OID found in user profile."), null);
}
// Create a simple-oauth2 token from raw tokens
let oauthToken = oauth2.accessToken.create(params);
// Save the profile and tokens in user storage
users[profile.oid] = { profile, oauthToken };
return done(null, users[profile.oid]);
}
// Configure OIDC strategy
passport.use(new OIDCStrategy(
{
identityMetadata: `${process.env.OAUTH_AUTHORITY}${process.env.OAUTH_ID_METADATA}`,
clientID: process.env.OAUTH_APP_ID,
responseType: 'code id_token',
responseMode: 'form_post',
redirectUrl: process.env.OAUTH_REDIRECT_URI,
allowHttpForRedirectUrl: true,
clientSecret: process.env.OAUTH_APP_PASSWORD,
validateIssuer: false,
passReqToCallback: false,
scope: process.env.OAUTH_SCOPES.split(' ')
},
signInComplete
));
For more details, please refer to the document and the sample.