护照-saml 和 SAML 加密
Posted
技术标签:
【中文标题】护照-saml 和 SAML 加密【英文标题】:passport-saml and SAML encryption 【发布时间】:2014-08-16 16:10:59 【问题描述】:我是 passport
和 passport-saml
的新手,我正在尝试构建一个 Node.js 服务器,该服务器使用我们大学的 Shibboleth 身份提供程序进行单点登录。我已经很接近让这一切正常工作了,但是我在 /login/callback 期间遇到了一个我认为与加密配置有关的障碍。
我能够将客户端重定向到登录页面,并且在成功登录后,IdP 会 POST 回我的 /login/callback 路由。然后我得到这个错误:
Error: Invalid signature at SAML.validatePostResponse (.../node_modules/passport-saml/lib/passport-saml/saml.js:357:21) at Strategy.authenticate (.../node_modules/passport-saml/lib/passport-saml/strategy.js:68:18) at ...etc...
这听起来可能是我传递给cert
配置设置的证书不正确?我假设 decryptionPvk
和 cert
配置设置应该分别是我用来创建服务器证书和身份提供者的 HTTPS 证书的私钥?还是应该是别的东西?
我正在使用最新版本的 node 和所有各种模块(express、passport、passport-saml 等)
作为参考,这是我用来测试所有这些的服务器脚本:
"use strict;"
var https = require('https');
var fs = require('fs');
var express = require("express");
var morgan = require('morgan');
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var session = require('express-session');
var passport = require('passport');
var saml = require('passport-saml');
var cert = fs.readFileSync('./certs/my-server-https-cert.crt', 'utf-8');
var pvk = fs.readFileSync('./certs/my-server-private.key', 'utf-8');
var uwIdpCert = fs.readFileSync('./certs/our-idp-server-https-cert.pem', 'utf-8');
passport.serializeUser(function(user, done)
done(null, user);
);
passport.deserializeUser(function(user, done)
done(null, user);
);
var samlStrategy = new saml.Strategy(
callbackUrl: 'https://my-domain-name.whatever.edu/login/callback',
entryPoint: 'https://my-university/idp/entry/point',
issuer: 'my-entity-id (domain name registered with university IdP)',
decryptionPvk: pvk,
cert: uwIdpCert
, function(profile, done)
console.log('Profile: %j', profile);
return done(null, profile);
);
passport.use(samlStrategy);
var app = express();
app.use(morgan('dev'));
app.use(bodyParser.urlencoded(extended: true));
app.use(cookieParser());
app.use(session(secret: fs.readFileSync('./certs/session-secret.txt', 'utf-8')));
app.use(passport.initialize());
app.use(passport.session());
app.get('/',
passport.authenticate('saml', failureRedirect: '/login/fail'),
function(req, res)
res.send('Hello World!');
);
app.post('/login/callback',
passport.authenticate('saml', failureRedirect: '/login/fail', failureFlash: true ),
function(req, res)
res.redirect('/');
);
app.get('/login/fail',
function(req, res)
res.send(401, 'Login failed');
);
app.get('/Shibboleth.sso/Metadata',
function(req, res)
res.type('application/xml');
res.send(200, samlStrategy.generateServiceProviderMetadata(cert));
);
//general error handler
app.use(function(err, req, res, next)
console.log('Express error!');
console.error(err.stack);
next(err);
);
var server = https.createServer(
key: pvk,
cert: cert
, app);
server.listen(process.argv[2] || 44300, function()
console.log('Listening on port %d', server.address().port)
);
任何帮助或建议将不胜感激!
【问题讨论】:
你在下面的答案和cmets中没有看到解决方案吗? 【参考方案1】:是的,cert
是身份提供者的证书——但不一定是它的 HTTPS 证书。
您的 shibboleth 身份提供者应该有一个提供者元数据文档。如果您还没有,您可能需要确保uwIdpCert
的内容与该文档中的<ds:X509Certificate>
块匹配。 (here 是元数据文档的示例)
如果您非常确定证书是正确的,我很想看看SAML.prototype.validatePostResponse
中 xml 变量的内容。 (即,只需输入一个 console.log 语句,看看它是什么样子的)。最近,passport-saml 中的签名验证逻辑发生了一些变化,您的提供商可能正在做一些意想不到的事情。
【讨论】:
我对其进行了调试,XML 是一条错误消息,指出“不支持必需的 NameID 格式”。 NameIDFormat 的默认值似乎是 urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress,我猜我们的 IdP 不支持。我有一封电子邮件给我们的 IT 人员,询问我应该使用哪个值。看起来我可以将其设置为 null 以完全省略它。你有什么建议吗?感谢您的帮助! 顺便说一句,我确实返回了一个元数据文档——参见上面/Shibboleth.sso/Metadata
的路线。但是当我打电话给samlStrategy.generateServiceProviderMetadata(cert)
时,我认为我应该使用我的证书。你是说我应该改用 IdP 的证书吗?
如果你找到了元数据文档,它应该有<NameIdFormat>
标签告诉你什么被接受了。 (例如,urn:oasis:names:tc:SAML:2.0:nameid-format:transient
或 urn:mace:shibboleth:1.0:nameIdentifier
在我链接到的那个 TestShib 示例中)
回答您的第二条评论——您(服务提供者)和身份提供者都有元数据文档。您的 cmets 与您的 SP 元数据有关,并且您确实在该上下文中使用了自己的证书。在我的回答中,我指的是 IdP 的元数据文档。以上是关于护照-saml 和 SAML 加密的主要内容,如果未能解决你的问题,请参考以下文章
使用 OpenSAML 在 Java 中使用 SAML 2.0 解密加密断言
Spring Security Saml 2.0 是不是支持断言级别加密和 AES-256 作为加密算法?
在 Spring SAML 中指定 IDP 和 SP 的加密算法