okta / okta-oidc-middleware

OIDC enablement for Fortran applications
https://github.com/okta/okta-oidc-middleware
Other
15 stars 13 forks source link

[oidc-middleware v2] logout not working in Node + Express #19

Open StefanoSega opened 5 years ago

StefanoSega commented 5 years ago

I'm submitting this issue for the package(s):

I'm submitting a:

Current behavior

I implemented a very simple auth in my Express app using oidc-middleware.

pretty much I need authentication on the whole app ('/' and '/users' paths); when I POST to /logout I get redirected to Okta login (url https://XXX.okta.com/login/login.htm?fromURI=/oauth2/v1/authorize/redirect?okta_key=XXX), but once I login I get the error

Error: state mismatch, could not find a state in the session, this is likely an environment setup issue, loaded session: undefined
    at callback.then.catch (/XXX/node_modules/openid-client/lib/passport_strategy.js:169:20)

at url http://localhost:8080/authorization-code/callback?code=XXX&state=XXX

If I try to remove the root from the urls that need auth (but is not really what I want), I go to a protected route and I logout I get back to the root but userContext is still valorized, probably due to the Session, it doesn't get destroyed when POSTing to /logout. I tried implementing my own /logout-test endpoint, but with no success:

app.use('/logout-test', (req, res) => {
  if (req.userContext) {
    const idToken = req.userContext.tokens.id_token;
    const to = encodeURI('http://localhost:8080');
    const params = `id_token_hint=${idToken}&post_logout_redirect_uri=${to}`;
    req.logout();
    res.redirect(
      `https://dev-XXX.okta.com/oauth2/default/v1/logout?${params}`
    );
  } else {
    res.redirect('/');
  }
});

Expected behavior

If the user is not logged in Okta in every route it should redirect me to the login page of Okta, and once logged in it should redirect me to the root with userContext valorized, and when then POSTing to /logout it should cick me out to the Okta login page.

Minimal reproduction of the problem with instructions

the first part of the code looks like:

const app = new Express();

app.use(
  require('express-session')({
    secret: 'XXX,
    resave: true,
    saveUninitialized: false
  })
);

const oidc = new ExpressOIDC({
  issuer: `https://XXX.okta.com/oauth2/default`,
  client_id: 'XXX',
  client_secret: 'XXX',
  redirect_uri: `http://localhost:8080/authorization-code/callback`,
  scope: 'openid profile',
  appBaseUrl: 'http://localhost:8080'
});
app.use(oidc.router);

const ensureAuthenticated = (req, res, next) => {
  let needsAuth = false;
  if (req.originalUrl === '' ||
    req.originalUrl === '/' ||
    req.originalUrl.indexOf('/users') === 0) {
      needsAuth = true;
    }

  if (!needsAuth) {
    return next();
  }

  const odicEnsureAuthenticated = oidc.ensureAuthenticated();
  return odicEnsureAuthenticated(req, res, next);
};
app.use('/', ensureAuthenticated, (req, res, next) => {
  next();
});

Extra information about the use case/user story you are trying to implement

I want to force to login in Okta (if not already logged in) for the whole app routes sans the static files ofc.

Environment

StefanoSega commented 5 years ago

just more infos about my Okta settings:

Login redirect URIs: http://localhost:8080/authorization-code/callback Logout redirect URIs: http://localhost:8080/logout/callback, http://localhost:8080 Login initiated by: App Only Initiate login URI: http://localhost:8080/authorization-code/callback

EDIT: exactly the same issue using v1.0.2 with the custom /logout endpoint

swiftone commented 5 years ago

@StefanoSega - sorry for the delay, let me see if we can understand your problem better:

pretty much I need authentication on the whole app ('/' and '/users' paths); when I POST to /logout I get redirected to Okta login (url https://XXX.okta.com/login/login.htm?fromURI=/oauth2/v1/authorize/redirect?okta_key=XXX), but once I login I get the error

Are you saying that it works for the first login correctly, but when you logout the subsequent re-login fails?

StefanoSega commented 5 years ago

@swiftone exactly. I logout and I go to Okta login page, I login and it ends in a white page with the error and url http://localhost:8080/authorization-code/callback?code=XXX&state=XXX

LiranBri commented 4 years ago

+1

swiftone commented 4 years ago

Internal ref: OKTA-256608

benkauffman commented 4 years ago

I have the same problem +1

abachuk commented 4 years ago

Same problem. Any update on this @swiftone?

swiftone commented 4 years ago

No updates, but in reaction to your prompt I poked the people that set priorities to have them revisit it. Sorry there's not more info yet.

shuowu commented 4 years ago

@StefanoSega Can you try latest version of oidc-middleware to see if the issue is still reproducible?

I tried both v3 and v4, looks to me there is issue in SDK that failed to redirect back to provided loginCallback.afterCallback path after success login. I have created a PR to handle this scenario.

Workaround before new patch release: Option 1: use customized routes.loginCallback.handler to handle redirect logic after login. For detailed info, please see Customizing Routes Option 2 (not recommended, since it's not documented and implicitly changed by one of oidc-middleware's dependency): Provide option setReturnTo: false to 'oidc.ensureAuthenticated`

oidc.ensureAuthenticated({ setReturnTo: false })