You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Okta OIDC跳转模式下分步认证异常问题求助

问题:Okta跳转模式下分步认证触发全量认证而非仅Okta Verify 2FA

我使用Okta的redirect model(跳转模式)实现用户登录,登录流程中用户需输入登录凭证并通过Okta Verify完成2FA认证。用户成功登录并建立认证会话后,在访问受限资源前调用/auth/2fa端点,期望仅触发Okta Verify的分步认证(Step-Up authentication),但实际却被要求输入密码+Okta Verify,等同于重新认证而非分步认证。我不确定是否是认证策略配置问题,若为配置问题,请告知正确的策略设置方式,当前我已在此处受阻无法推进。

相关代码

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 passport = require('passport');
var qs = require('querystring');
var { Strategy } = require('passport-openidconnect');
const axios = require('axios');
const crypto = require('crypto');

// source and import environment variables
require('dotenv').config({ path: '.okta.env' })
//require('dotenv').config({ path: '.entra.env' })
const { ORG_URL, CLIENT_ID, CLIENT_SECRET, CALLBACK_URL } = process.env;

var indexRouter = require('./routes/index');
const { profile } = require('console');


var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use(session({
  secret: 'CanYouLookTheOtherWay',
  resave: false,
  saveUninitialized: true,
  // cookie: { secure: true, sameSite: false }
}));

// app.set("trust proxy", 1);

app.use(passport.initialize());
app.use(passport.session());

// https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationRequest
let logout_url, id_token;
let _base = ORG_URL.slice(-1) == '/' ? ORG_URL.slice(0, -1) : ORG_URL;
console.log ('Base URL - ' + _base);
axios
  .get(`${_base}/.well-known/openid-configuration`)
  .then(res => {
    if (res.status == 200) {
      let { issuer, authorization_endpoint, token_endpoint, userinfo_endpoint, end_session_endpoint } = res.data;
      logout_url = end_session_endpoint;

      console.log ('Authorization Endpoint - ' +authorization_endpoint);

      const riskyActionInfo = {
        action: 'Login Button',
        referURL: '/',
        targetURL: '/profile'
     };
     
     //const state = JSON.stringify(riskyActionInfo);
     const state = JSON.stringify(riskyActionInfo);

      // Set up passport
      passport.use('oidc', new Strategy({
        issuer,
        authorizationURL: authorization_endpoint,
        tokenURL: token_endpoint,
        userInfoURL: userinfo_endpoint,
        clientID: CLIENT_ID,
        clientSecret: CLIENT_SECRET,
        callbackURL: CALLBACK_URL,
        scope: ['openid', 'profile', 'email'],
        state: true,
        nonce: true,
        maxAge: 5,
      }, (issuer, profile, context, idToken, accessToken, refreshToken, params, done) => {
        console.log(`OIDC response: ${JSON.stringify({
          issuer, profile, context, idToken,
          accessToken, refreshToken, params
        }, null, 2)}\n*****`);
        id_token = idToken;
        return done(null, profile);
      }));
    }
    else {
      console.log(`Unable to reach the well-known endpoint. Are you sure that the ORG_URL you provided (${ORG_URL}) is correct?`);
    }
  })
  .catch(error => {
    console.error(error);
});

passport.serializeUser((user, next) => {
  next(null, user);
});

passport.deserializeUser((obj, next) => {
  next(null, obj);
});

function ensureLoggedIn(req, res, next) {
  if (req.isAuthenticated()) {
    return next();
  }
  res.redirect('/login')
}

app.use('/', indexRouter);

app.use('/login', passport.authenticate('oidc'));

app.use('/authorization-code/callback',
  // https://github.com/jaredhanson/passport/issues/458

  passport.authenticate('oidc', { failureMessage: true, failWithError: true }),
  (req, res) => {
    console.log ("IN Callback Handler");
    const returnedState = req.query.state;
    let st = req.authInfo.state;
    console.log("State :" + st);

    if (st === undefined) {
      console.log("state is null or undefined");
      res.redirect('/profile');
    }
    else {
      console.log(JSON.parse(st).targetURL);
      var url = JSON.parse(st).targetURL;
      res.redirect(url);
    }
    
  }
);

app.use('/profile', ensureLoggedIn, (req, res) => {
  res.render('profile', { authenticated: req.isAuthenticated(), user: req.user, title: 'Profile' });
});

app.use('/secure_page', ensureLoggedIn, (req, res) => {
  res.render('secure_page', { authenticated: req.isAuthenticated(), user: req.user, title: 'Secure Page' });
});

app.use('/auth/2fa', ensureLoggedIn, (req,res) =>{
    console.log ("******In MFA Page******");
    const state = JSON.stringify({ action: 'secure_page', targetURL: '/secure_page' });
    const nonce = crypto.randomBytes(16).toString('hex');
    
    passport.authenticate('oidc', {
      scope: ['openid', 'profile', 'email','offline_access'],
      state:  state,
      nonce: nonce,
      acrValues: 'phrh',
      maxAge:'0',
  })(req, res);
});


app.get('/logout', (req, res) => {
  req.logout();
  req.session.destroy();
  res.redirect('/');
});



// catch 404 and forward to error handler
app.use(function (req, res, next) {
  next(createError(404));
});

// error handler
app.use(function (err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message + (err.code && ' (' + err.code + ')' || '') +
    (req.session.messages && ": " + req.session.messages.join("\n. ") || '');
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

内容的提问来源于stack exchange,提问作者Pawan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 11:22:05