Node authentication with Passport.js and OpenID Connect

Node authentication with Passport.js and OpenID Connect

This post demonstrates how to set up OpenID Connect authentication in Node with Passport.js.

sachin saxena

If I need the access token returned after authentication, how can I get that ?

Randall Degges

When you first create the passport strategy, there’s a callback function that in the example above isn’t using, eg:

// set up passport
passport.use(‘oidc’, new OidcStrategy({
issuer: ‘https://dev-846291.oktapreview.com/oauth2/default’,
authorizationURL: ‘https://dev-846291.oktapreview.com/oauth2/default/v1/authorize’,
tokenURL: ‘https://dev-846291.oktapreview.com/oauth2/default/v1/token’,
userInfoURL: ‘https://dev-846291.oktapreview.com/oauth2/default/v1/userinfo’,
clientID: ‘{ClientID}’,
clientSecret: ‘{ClientSecret}’,
callbackURL: ‘http://localhost:3000/authorization-code/callback’,
scope: ‘openid profile’
}, (issuer, sub, profile, accessToken, refreshToken, done) => {
return done(null, profile);
}));

What you can do is take the accessToken variable from there and store it someplace for later usage =)

Brian McBride

I’m always looking for more articles on how people implemented passport and Okta is a great product.

it might be great to see an example with Okta using JWTs & Authentication Headers over cookies. When I saw express-session there, I had to check the date of this blog post as I was thinking I might be seeing something from a couple years ago :slight_smile:

Sathish Balasubramaniyan

How can I get the OIDC ID Token if I need it?

Randall Degges

I believe it’s in the session cookie already.

Adam

Thanks for the article! Got me on the right path, but the passport-openidconnect package did not work for other oidc provider implementations like IdentityServer4. The auth redirect url is not formed correctly, so the provider rejects the request. There are a number of parameters missing such as a nonce value. I was able to use the following package’s strategy and it worked like a champ. https://github.com/panva/no…

Joao Reis

should the secret be hardcoded? seems like a security flaw to me…

Lee Brandt

Never. This is just for demonstration purposes. Secrets can be stored and used in lots of secure ways. This is more about demonstrating how passport works with OIDC,

Vadym Rybak

no, you can find ID Token in params object which is missing in example callback above:
(issuer, sub, profile, accessToken, refreshToken, params, done)

Vishnu Karthik Reddy Aleti

Hi Team, Thank you for this great article. In my case, we have Loopback framework with Node.Js. So, how shall i implement this Okta with my application. This article is purely for NodeJs & ExpressJs. kindly advise me. Thank you in advance.

pragmaticivan

FYI, req.session.destroy() performs race condition. express-session only performs .save on res.end, it doesn’t wait for redirects.

If you are connected to a store that has some latency, it will redirect before it destroys the session.

Greg Steven

Is this the recommended approach, or is using @okta/oidc-middleware, as described in https://developer.okta.com/…, the standard approach?

leebrandt

The Okta oidc-middleware is probably the more common approach. But if your developers are already familiar with setting up and configuring Passport for authentication, then that might be the right approach for your organization.

Roman Soulman

Thank you for the article, @leebrandt ! Any reason you picked ‘passport-openidconnect’ vs. ‘openid-client’ (http://www.passportjs.org/p… - an OIDC client despite the name) which has many more downloads?

Frédéric Mériot

Hi,
personally, I preferred to use the official library openid-client. The one used in this example no longer seems to be maintained.

Nomi

Great article, got a question though. Where is the user? You have a login link which invokes login flow and calls call back method to redirect to a page printing user.displayName but which user? no user singed in yet. I am confused.

I’m stuck…
I followed this and other posts to add the ‘groups’ claim to the example app.
I verified in the Okta admin UI → Token preview, that I see the groups list.
But, the profile page does not list the groups claim. Nor does it appear in the ‘req.user’ object when I dump it to the console.

I was quite surprised to not be able to find a step-by-step that covers this.

Is there such a guide or post?
Otherwise can the steps to accomplish that be shared here?

Thanks.

Hi @Opher

I can think of a couple of quick things you can check, but if these don’t work let us know!

  1. Check to see if your groups claim is added to your access token or ID token, for debugging purposes you can enable it for to both token types.
  2. Make sure the Issuer you are using is in the format of https://<your-okta-domain>/oauth2/<id>, typically it would look like https://dev-133337.okta.com/oauth2/default
    If you are NOT using an issuer formatted like this, take a look at this doc for guidance: Customize tokens returned from Okta with a Groups claim | Okta Developer

If that doesn’t help, can you include the data you are getting from req.user (sanitize the data before posting).

Keep us posted!

Not sure if this topic is still active, but I am attempting to follow the original guide.
I have Passport configured as follows:

const oktaDomain = 'dev-XXXXXXXX.okta.com';
const clientID = 'XXXXXXXXXXXXXXX';

const issuer = `https://${oktaDomain}/oauth2/default`;

passport.use('oidc', new Strategy({
  issuer,
  authorizationURL: `https://${oktaDomain}/oauth2/default/v1/authorize`,
  tokenURL: `https://${oktaDomain}/oauth2/default/v1/token`,
  userInfoURL: `https://${oktaDomain}/oauth2/default/v1/userinfo`,
  clientID: `${clientID}`,
  callbackURL: 'http://localhost:3000/authorization-code/callback',
  scope: 'openid profile'
}, (issuer, profile, done) => {
  return done(null, profile);
}));

where callbackURL is equal to the Sign In Redirect URI I set for my SPA.

However, when I click the Log In link I get the following error:

PKCE code challenge is required by the application.
500
AuthorizationError: PKCE code challenge is required by the application.
    at Strategy.authenticate (/home/rlowles/Documents/OktaTesting/okta-node-passport-oidc-example/node_modules/passport-openidconnect/lib/strategy.js:99:25)
[...]

Is there a step or setting in Okta that I missed which would be causing this error?