node.js - Passport Saml-> SAML 提供程序在身份验证后返回错误
问题描述
我正在尝试使用 passport-saml 进行身份验证,但在通过错误获得授权后Error: SAML provider returned Requester error: An error occurred.
当我点击登录时,它会将我重定向到我提供用户名和密码的 IDP 登录页面,然后它重定向到我的 /login/callback 函数,它会崩溃。
应用程序.js
const express = require('express');
const http = require('http');
const path = require('path');
const passport = require('passport');
const morgan = require('morgan');
const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');
const session = require('express-session');
const errorhandler = require('errorhandler');
var env = process.env.NODE_ENV || 'development';
const config = require('./config/config')[env];
console.log('Using configuration', config);
require('./config/passport')(passport, config);
var app = express();
app.set('port', config.app.port);
app.set('views', __dirname + '/app/views');
app.set('view engine', 'jade');
app.use(morgan('combined'));
app.use(cookieParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use(session(
{
resave: true,
saveUninitialized: true,
secret: 'this shit hits'
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(express.static(path.join(__dirname, 'public')));
require('./config/routes')(app, config, passport);
app.listen(app.get('port'), function () {
console.log('Express server listening on port ' + app.get('port'));
});
路由.js
module.exports = function (app, config, passport) {
app.get('/', function (req, res) {
if (req.isAuthenticated()) {
res.render('home',
{
user: req.user
});
} else {
res.render('home',
{
user: null
});
}
});
app.get('/login',
passport.authenticate(config.passport.strategy,
{
successRedirect: '/',
failureRedirect: '/login'
})
);
app.post(config.passport.saml.path,
passport.authenticate(config.passport.strategy,
{
failureRedirect: '/',
failureFlash: true
}),
function (req, res) {
res.redirect('/');
}
);
app.get('/signup', function (req, res) {
res.render('signup');
});
app.get('/profile', function (req, res) {
if (req.isAuthenticated()) {
res.render('profile',
{
user: req.user
});
} else {
res.redirect('/login');
}
});
app.get('/logout', function (req, res) {
req.logout();
// TODO: invalidate session on IP
res.redirect('/');
});
};
护照.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(
{
path: config.passport.saml.path,
entryPoint: config.passport.saml.entryPoint,
issuer: config.passport.saml.issuer,
cert: config.passport.saml.cert
},
function (profile, done) {
return done(null,
{
id: profile.uid,
email: profile.email,
displayName: profile.cn,
firstName: profile.givenName,
lastName: profile.sn
});
})
);
};
配置.js
module.exports = {
development: {
app: {
name: 'Passport SAML strategy example',
port: process.env.PORT || 3000
},
passport: {
strategy: 'saml',
saml: {
path: process.env.SAML_PATH || '/login/callback',
entryPoint: process.env.SAML_ENTRY_POINT || 'https://idp.example.io/idp/profile/SAML2/Redirect/SSO',
issuer: 'https://sp.example.io/shibboleth',
cert: process.env.SAML_CERT || '/etc/ssl/certs/ssl-sp.crt'
}
}
}
};
这是我在控制台和浏览器上遇到的错误
Error: SAML provider returned Requester error: An error occurred.
at /root/passport-saml-ex1/node_modules/passport-saml/lib/passport-saml/saml.js:677:31
at _fulfilled (/root/passport-saml-ex1/node_modules/q/q.js:854:54)
at /root/passport-saml-ex1/node_modules/q/q.js:883:30
at Promise.promise.promiseDispatch (/root/passport-saml-ex1/node_modules/q/q.js:816:13)
at /root/passport-saml-ex1/node_modules/q/q.js:570:49
at runSingle (/root/passport-saml-ex1/node_modules/q/q.js:137:13)
at flush (/root/passport-saml-ex1/node_modules/q/q.js:125:13)
at process._tickCallback (internal/process/next_tick.js:61:11)
这是我得到的回应
<?xml version="1.0" encoding="UTF-8"?>
<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Destination="http://sp.example.io:3000/login/callback" ID="_a41e13c5b43026d0b854985b77699814" InResponseTo="_0d7bb680083c3aa20048" IssueInstant="2019-01-08T20:26:24.715Z" Version="2.0">
<saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">https://idp.example.io/idp/shibboleth</saml2:Issuer>
<saml2p:Status>
<saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Requester">
<saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:InvalidNameIDPolicy" />
</saml2p:StatusCode>
<saml2p:StatusMessage>An error occurred.</saml2p:StatusMessage>
</saml2p:Status>
</saml2p:Response>
解决方案
就像乔说的那样,您会想查看 IdP 日志的内容,但您可能会发现这个护照-saml 问题很有帮助。基本上,如果您没有在 SamlStrategy 的实例化中指定 identifierFormat,它默认为“urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress”,这总是导致我的请求者错误。将 identifierFormat 设置为 null 会导致来自 IdP 的成功响应。
也就是说,我后来在成功时遇到了一些非常令人沮丧的重定向行为,我不会深入讨论,但是如果您发现自己在 IdP 和 SP 之间被重定向,这个护照问题很好地解释了它并提供了一种解决方法。我还没有开始工作,所以如果你这样做了,请告诉我:)
推荐阅读
- html - 在页面上移动了一个 div 项
- three.js - Three.js:渲染的节流/智能调用是否必要?
- python - Python 在关闭另一个窗口之前不会运行新窗口
- java - KeyAgreement.generateSecret() 中的本机方法错误
- java - Android监听器在活动中工作但不在片段中
- php - 如何使用 preg_replace 从这个字符串中删除最后一个特殊字符?
- javascript - 如何使用用户名从我的数据库中为某个用户调用和回显一个值来识别用户
- angular9 - 角度调查动态问题渲染模板驱动或反应
- java - 布尔默认值 MapStruct
- amazon-web-services - 推荐用于 Adobe ColdFusion 生产环境的 Docker 映像是什么?