本文介绍了护照-saml - 快递 - 重定向的 url 未提交表单使 SAML 断言尚未生效的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是我今天在控制台上遇到的错误,而不是昨天相同代码运行良好时的错误.

错误:SAML 断言尚未生效在 SAML.checkTimestampsValidityError

我已经确认我收到了 IDP 的成功,因此应用程序被重定向到 URL 中的/home"端点配置文件中提到.

此外,当我提交表单时,在自动重定向后[显示内部服务器错误]

我按下浏览器的刷新按钮,提交表单,达到预期效果.

我的问题是,为什么这不会自动发生,或者我可以如何以及在何处以编程方式进行此提交.

passport.js

const SamlStrategy = require('passport-saml').Strategy;module.exports = 功能(护照,配置){护照.serializeUser(功能(用户,完成){完成(空,用户);});护照.deserializeUser(功能(用户,完成){完成(空,用户);});护照.使用(新的SamlStrategy({入口点:config.passport.saml.entryPoint,发行人:config.passport.saml.issuer,证书:config.passport.saml.cert,路径:config.passport.saml.path,标识符格式:config.passport.saml.identifierFormat},功能(配置文件,完成){调试器;返回完成(空,{sessionIndex: profile.sessionIndex,nameID:profile.nameID,姓氏:profile.lastName,名字:profile.firstName,gid:profile.gid,县:profile.county,邮件:profile.mail,公司单位:profile.companyUnit,首选语言:profile.preferredLanguage,组织代码:profile.orgCode,电子邮件:profile.email});}));};

config.js

module.exports = {护照: {策略:'saml',萨姆:{callbackUrl: '/home',路径:'/家',入口点:'https://.../GetAccess/Saml/IDP/SSO/Unsolicited?GA_SAML_SP=APP',发行人:'...',证书:'...',标识符格式:空}}};

app.js

import express from 'express';从头盔"导入头盔;从 'cookie-parser' 导入 cookieParser;从'body-parser'导入bodyparser;从路径"导入路径;从摩根"导入记录器;从 'cors' 导入 cors;从护照"进口护照;从cookie-session"导入会话;const config = require('./config.js');require('./passport')(passport, config);var app = express();app.use(logger('dev'));app.use(cookieParser());app.use(bodyparser.json());app.use(bodyparser.urlencoded({extended: false }));app.use('/public', express.static(path.join(__dirname, '../public')));app.use('/data', express.static(path.join(__dirname, '../uploads/')));app.use(会话({重新保存:真的,保存未初始化:真,秘密:'秘密价值'}));app.use(passport.initialize());app.use(passport.session());app.use(头盔());app.use(cors());要求('../router/routeConfig')(应用程序,配置,护照);module.exports = 应用程序;

routeConfig.js

module.exports = 功能(应用程序,配置,护照){app.get('/',passport.authenticate(config.passport.strategy,{成功重定向: '/home',failureRedirect: 'https://.../GetAccess/Saml/IDP/SSO/Unsolicited?GA_SAML_SP=APP'}));app.get('/app',passport.authenticate(config.passport.strategy,{成功重定向: '/home',failureRedirect: 'https://.../GetAccess/Saml/IDP/SSO/Unsolicited?GA_SAML_SP=APP'}));app.post(config.passport.saml.path,护照.身份验证(配置.passport.strategy,{failureRedirect: 'https://.../GetAccess/Saml/IDP/SSO/Unsolicited?GA_SAML_SP=APP',失败闪光:真}),功能(请求,资源){调试器;res.sendFile(path.join(__dirname, "../public/index.html"));});};
解决方案

经过一番研究,我终于弄明白了,

据我们了解,SAML 身份验证流程涉及两方,即 IDPSP,因此它们之间存在某些应该满足的条件,作为合同的一部分.其中一种条件是TIME.

这是我从 IDP 收到的 saml 响应中剪下的标记,这里我的(SP 的)服务器的时间应该在 NotBefore 之间>NotOnOrAfter 在身份验证过程中.

因此,我需要将服务器的时钟校准几秒钟,以适应服务器的 NotBeforeNotOnOrAfter 时间片.

当然这不是应该这样做的方式,但是 IDP 方面应该允许 +n 或 -n 分钟(重要的是 SP 和 IDP 都遵循 UTC 时间).

可以在此处找到有关此主题的更多信息,

由于时钟未同步导致的 SAML 断言 NotBefore、NotOnOrAfter 问题:解释

ADFS 不早于时间偏差

奖金

Base 64 到 XML 解码器

XML 修饰符

正如在下面的评论中提到的,可以在任一侧(IdP > 或 SP)或两侧配置偏斜.从护照saml文档:AcceptedClockSkewMs:可接受的偏斜时间(以毫秒为单位)检查 OnBefore 和 NotOnOrAfter 时在客户端和服务器之间断言条件有效性时间戳.设置为 -1 将禁用完全检查这些条件.默认为 0.

此处提到

Below is the error that I am getting on my console today as opposed to yesterday when the same code was working fine.

Error: SAML assertion not yet valid
        at SAML.checkTimestampsValidityError

Additionally, when I submit the form, after an auto redirection [which shows me Internal Server Error]

I press refresh button of the browser and a form submission happens and the expected result is achieved.

My problem is, why doesn't this happens automatically or how and where can I do this submission programatically.

passport.js

const SamlStrategy = require('passport-saml').Strategy;

module.exports = function (passport, config) {

  passport.serializeUser(function (user, done) {
    done(null, user);
  });

  passport.deserializeUser(function (user, done) {
    done(null, user);
  });

  passport.use(new SamlStrategy(
    {
      entryPoint: config.passport.saml.entryPoint,
      issuer: config.passport.saml.issuer,
      cert: config.passport.saml.cert,
      path: config.passport.saml.path,
      identifierFormat: config.passport.saml.identifierFormat
    },
    function (profile, done) {

      debugger;
      return done(null,
        {
          sessionIndex: profile.sessionIndex,
          nameID: profile.nameID,
          lastName: profile.lastName,
          firstName: profile.firstName,
          gid: profile.gid,
          county: profile.county,
          mail: profile.mail,
          companyUnit: profile.companyUnit,
          preferredLanguage: profile.preferredLanguage,
          orgCode: profile.orgCode,
          email: profile.email
        });
    })
  );

};

config.js

module.exports = {
      passport: {
        strategy: 'saml',
        saml: {
          callbackUrl: '/home',
          path: '/home',
          entryPoint: 'https://.../GetAccess/Saml/IDP/SSO/Unsolicited?GA_SAML_SP=APP',
          issuer: '...',
          cert: '...',
          identifierFormat: null
        }
      }
  };

app.js

import express from 'express';
import helmet from 'helmet';
import cookieParser from 'cookie-parser';
import bodyparser from 'body-parser';
import path from 'path';
import logger from 'morgan';
import cors from 'cors';
import passport from 'passport';
import session from 'cookie-session';

const config = require('./config.js');
require('./passport')(passport, config);
var app = express();
app.use(logger('dev'));
app.use(cookieParser());
app.use(bodyparser.json());
app.use(bodyparser.urlencoded({ extended: false }));
app.use('/public', express.static(path.join(__dirname, '../public')));
app.use('/data', express.static(path.join(__dirname, '../uploads/')));
app.use(session(
  {
    resave: true,
    saveUninitialized: true,
    secret: 'secret value'
  }));
app.use(passport.initialize());
app.use(passport.session());
app.use(helmet());
app.use(cors());

require('../router/routeConfig')(app, config, passport);

module.exports = app;

routeConfig.js

module.exports = function (app, config, passport) {


  app.get('/', passport.authenticate(config.passport.strategy, {
    successRedirect: '/home',
    failureRedirect: 'https://.../GetAccess/Saml/IDP/SSO/Unsolicited?GA_SAML_SP=APP'
  }));

  app.get('/app', passport.authenticate(config.passport.strategy, {
    successRedirect: '/home',
    failureRedirect: 'https://.../GetAccess/Saml/IDP/SSO/Unsolicited?GA_SAML_SP=APP'
  }));

  app.post(config.passport.saml.path,
    passport.authenticate(config.passport.strategy,
      {
        failureRedirect: 'https://.../GetAccess/Saml/IDP/SSO/Unsolicited?GA_SAML_SP=APP',
        failureFlash: true
      }),
    function (req, res) {
      debugger;
      res.sendFile(path.join(__dirname, "../public/index.html"));
    });

};
解决方案

Finally I have figured this out after some research,

As we understand that there are two parties involved in the SAML Authentication Process i.e. IDP and SP, therefore there are certain conditions between these which are supposed to be met, as part of the contract. One such condition is the TIME.

<saml:Conditions NotBefore="2019-08-01T11:02:49Z" NotOnOrAfter="2019-08-01T11:03:59Z">

This is a tag that I have clipped from the saml response received from the IDP, here the time of my(SP's) server should be between NotBefore and NotOnOrAfter during the process of authentication.

Therefore, I need to calibrate the clock of my server by a few seconds so that I fit in the time-slice of NotBefore and NotOnOrAfter of the server.

Of course that is not the way this should be done, but some +n or -n minutes should be allowed from the IDP side (importantly both SP and IDP to follow UTC times).

More on this topic can be found here,

SAML Assertion NotBefore,NotOnOrAfter problem due to unsynced clocks : Explained

ADFS Not Before Time Skew

Base 64 to XML Decoder

XML Prettifier

Mentioned Here

这篇关于护照-saml - 快递 - 重定向的 url 未提交表单使 SAML 断言尚未生效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-12 21:53