护照-saml 和 SAML 加密

Posted

技术标签:

【中文标题】护照-saml 和 SAML 加密【英文标题】:passport-saml and SAML encryption 【发布时间】:2014-08-16 16:10:59 【问题描述】:

我是 passportpassport-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 配置设置的证书不正确?我假设 decryptionPvkcert 配置设置应该分别是我用来创建服务器证书和身份提供者的 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:transienturn: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 的加密算法

如何读取加密的断言?

Spring SAML:解密加密密钥时出错,没有安装的提供程序支持此密钥

SSO:SAML与LDAP?