Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passport azure-ad Verify Callback not Called

I have encountered a problem when using passport (with the passport-azure-ad strategy) to authenticate requests. The request to Azure Active Directory works fine. I can login with my credentials. After that, I expect the verify callback to be called, setting the user object based on the accessToken etc. Then I expect the redirect route function to be called where the user object will be available. This is my setup:

passport.serializeUser((accessToken, done) => {
    done(null, accessToken);
});

passport.deserializeUser((accessToken, done) => {
    done(null, accessToken);
});

passport.use(new OIDCStrategy({
    // options for the azure AD strategy
    identityMetadata: config.auth.identityMetadata,
    clientID: config.auth.clientID,
    clientSecret: config.auth.clientSecret,
    redirectUrl: config.auth.redirectUrl,
    responseType: 'code id_token',
    responseMode: 'query',
    allowHttpForRedirectUrl: config.auth.allowHttpForRedirectUrl,
    isB2C: true,
    passReqToCallback: false,
    scope: config.auth.scope,
    loggingLevel: 'error'
}, (iss, sub, profile, jwtClaims, accessToken, refreshToken, params, done) => {
    console.log('1. VERIFY CALLBACK');
    if (!accessToken) {
        return done(new Error('No accessToken was given'), null);
    }
    return done(null, { accessToken, expires: params.expires_on, refreshToken });
}));

My routes:

router.get('/auth/login', (req, res, next) => {
    passport.authenticate('azuread-openidconnect', { failureRedirect: '/' })(req, res, next);
});

router.get('/auth/openid/redirect', (req, res, next) => {
    passport.authenticate('azuread-openidconnect', { failureRedirect: '/' }, (err, user) => {
        console.log('2. ROUTE REDIRECT');
        return res.send('...then redirect existing user to profile page');
    })(req, res, next);
});

2 out of 10 times, my expectations are right and everything works fine. The rest of the times the verify callback is never called, or the redirect route function is called before it, and therefor the user object is never set (user is 'false').

Anyone have a clue how I can get through this?

like image 664
yrstyre Avatar asked Nov 07 '22 10:11

yrstyre


1 Answers

To my understanding the passport-azure-ad authentication process works as follows:

  1. User navigates to /auth/login route
  2. User follows onscreen instructions to authenticate with application configured on Azure Active Directory (AAD)
  3. Upon successful authentication. The replyURL for your specific application is called. In your case /auth/openid/redirect.
  4. Reply URL receives HTTP post request from AAD with details of the authentication (token etc.) with the body urlEncoded
  5. Passport strategy is then invoked and callback function executed to authenticate user onto your application

I had a similar issue to you whereby I could log on with azure, then the replyURL would be called, but my browser would then enter an infinite loop of calling the replyURL and never initiate the strategy verify callback.

I managed to identify that I had not configured my express server to parse urlEncoded bodies correctly which was causing the infinite loop with the following line of code...

app.use(bodyParser.urlencoded({ extended : true }));

I suspect that you may be having the same issue.

Hope that helps.

like image 74
Josh Avatar answered Nov 14 '22 20:11

Josh