I have a node.js
script, using passport-saml, that simulates an SP. My goal is to connect it to this TestShib IdP but I get the following error: SAML 2 SSO profile is not configured for relying party.
Based on what I read here, I know that I need to provide the SP metadata, but I do not know how. I know that passport-saml has the function: generateServiceProviderMetadata(decryptionCert)
and I while I have the certificates required, I do not know how to make it all work.
Also, I want to avoid having to register my SP if that is possible.
Here is my script:
const https = require('https');
const fs = require('fs');
const express = require('express');
const morgan = require('morgan');
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser');
const session = require('express-session');
const passport = require('passport');
const saml = require('passport-saml');
/*
---------------------------------------------------------------------------------------------------
-- certificates
---------------------------------------------------------------------------------------------------
*/
// for https server
const https_cert = fs.readFileSync('certificate.pem', 'utf-8');
const https_pvk = fs.readFileSync('privatekey.pem', 'utf-8');
// from idp's metadata
const idp_cert_1 = 'MIIDAzCCAeugAwIBAgIVAPX0G6LuoXnKS0Muei006mVSBXbvMA0GCSqGSIb3DQEBCwUAMBsxGTAXBgNVBAMMEGlkcC50ZXN0c2hpYi5vcmcwHhcNMTYwODIzMjEyMDU0WhcNMzYwODIzMjEyMDU0WjAbMRkwFwYDVQQDDBBpZHAudGVzdHNoaWIub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAg9C4J2DiRTEhJAWzPt1S3ryhm3M2P3hPpwJwvt2q948vdTUxhhvNMuc3M3S4WNh6JYBs53R+YmjqJAII4ShMGNEmlGnSVfHorex7IxikpuDPKV3SNf28mCAZbQrX+hWA+ann/uifVzqXktOjs6DdzdBnxoVhniXgC8WCJwKcx6JO/hHsH1rG/0DSDeZFpTTcZHj4S9MlLNUtt5JxRzV/MmmB3ObaX0CMqsSWUOQeE4nylSlp5RWHCnx70cs9kwz5WrflnbnzCeHU2sdbNotBEeTHot6a2cj/pXlRJIgPsrL/4VSicPZcGYMJMPoLTJ8mdy6mpR6nbCmP7dVbCIm/DQIDAQABoz4wPDAdBgNVHQ4EFgQUUfaDa2mPi24x09yWp1OFXmZ2GPswGwYDVR0RBBQwEoIQaWRwLnRlc3RzaGliLm9yZzANBgkqhkiG9w0BAQsFAAOCAQEASKKgqTxhqBzROZ1eVy++si+eTTUQZU4+8UywSKLia2RattaAPMAcXUjO+3cYOQXLVASdlJtt+8QPdRkfp8SiJemHPXC8BES83pogJPYEGJsKo19l4XFJHPnPy+Dsn3mlJyOfAa8RyWBS80u5lrvAcr2TJXt9fXgkYs7BOCigxtZoR8flceGRlAZ4p5FPPxQR6NDYb645jtOTMVr3zgfjP6Wh2dt+2p04LG7ENJn8/gEwtXVuXCsPoSCDx9Y0QmyXTJNdV1aB0AhORkWPlFYwp+zOyOIR+3m1+pqWFpn0eT/HrxpdKa74FA3R2kq4R7dXe4G0kUgXTdqXMLRKhDgdmA==';
const idp_cert_2 = 'MIIDAzCCAeugAwIBAgIVAPX0G6LuoXnKS0Muei006mVSBXbvMA0GCSqGSIb3DQEBCwUAMBsxGTAXBgNVBAMMEGlkcC50ZXN0c2hpYi5vcmcwHhcNMTYwODIzMjEyMDU0WhcNMzYwODIzMjEyMDU0WjAbMRkwFwYDVQQDDBBpZHAudGVzdHNoaWIub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAg9C4J2DiRTEhJAWzPt1S3ryhm3M2P3hPpwJwvt2q948vdTUxhhvNMuc3M3S4WNh6JYBs53R+YmjqJAII4ShMGNEmlGnSVfHorex7IxikpuDPKV3SNf28mCAZbQrX+hWA+ann/uifVzqXktOjs6DdzdBnxoVhniXgC8WCJwKcx6JO/hHsH1rG/0DSDeZFpTTcZHj4S9MlLNUtt5JxRzV/MmmB3ObaX0CMqsSWUOQeE4nylSlp5RWHCnx70cs9kwz5WrflnbnzCeHU2sdbNotBEeTHot6a2cj/pXlRJIgPsrL/4VSicPZcGYMJMPoLTJ8mdy6mpR6nbCmP7dVbCIm/DQIDAQABoz4wPDAdBgNVHQ4EFgQUUfaDa2mPi24x09yWp1OFXmZ2GPswGwYDVR0RBBQwEoIQaWRwLnRlc3RzaGliLm9yZzANBgkqhkiG9w0BAQsFAAOCAQEASKKgqTxhqBzROZ1eVy++si+eTTUQZU4+8UywSKLia2RattaAPMAcXUjO+3cYOQXLVASdlJtt+8QPdRkfp8SiJemHPXC8BES83pogJPYEGJsKo19l4XFJHPnPy+Dsn3mlJyOfAa8RyWBS80u5lrvAcr2TJXt9fXgkYs7BOCigxtZoR8flceGRlAZ4p5FPPxQR6NDYb645jtOTMVr3zgfjP6Wh2dt+2p04LG7ENJn8/gEwtXVuXCsPoSCDx9Y0QmyXTJNdV1aB0AhORkWPlFYwp+zOyOIR+3m1+pqWFpn0eT/HrxpdKa74FA3R2kq4R7dXe4G0kUgXTdqXMLRKhDgdmA==';
/*
---------------------------------------------------------------------------------------------------
-- passport-saml setup
---------------------------------------------------------------------------------------------------
*/
const saml_strategy = new saml.Strategy(
{
'callbackUrl': 'https://localhost:44300/login/callback',
'entryPoint': 'https://idp.testshib.org/idp/profile/SAML2/Redirect/SSO',
'issuer': 'https://localhost:44300',
'decryptionPvk': https_pvk,
'cert': [idp_cert_1, idp_cert_2]
},
function (profile, done)
{
console.log('passport.use() profile: %s \n', JSON.stringify(profile));
return done(
null,
{
'nameIDFormat': profile.nameIDFormat,
'nameID': profile.nameID
}
);
}
);
passport.serializeUser(function (user, done) {
console.log('passport.serializeUser() user: %s \n', JSON.stringify(user));
done(null, user);
});
passport.deserializeUser(function (user, done) {
console.log('passport.deserializeUser() user: %s \n', JSON.stringify(user));
done(null, user);
});
passport.use(saml_strategy);
/*
---------------------------------------------------------------------------------------------------
-- express setup
---------------------------------------------------------------------------------------------------
*/
const app = express();
// configure view engine to render EJS templates
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
// additional settings for logging and parsing
app.use(morgan('dev'));
app.use(cookieParser());
app.use(bodyParser.urlencoded({'extended': true}));
app.use(session({ 'secret': 'this-is-secret', 'resave': false, 'saveUninitialized': false }));
// initialize Passport and restore authentication state, if any, from the session
app.use(passport.initialize());
app.use(passport.session());
/*
---------------------------------------------------------------------------------------------------
-- routes
---------------------------------------------------------------------------------------------------
*/
app.get(
'/',
function (req, res) {
if (req.isAuthenticated()) {
console.log('GET [/] user authenticated! req.user: %s \n', JSON.stringify(req.user));
res.render('home', { 'user': req.user });
} else {
console.log('GET [/] user not authenticated! \n');
res.render('home', { 'user': null });
}
}
);
app.get(
'/login',
passport.authenticate('saml', { 'successRedirect': '/', 'failureRedirect': '/login' })
);
app.post(
'/login/callback',
passport.authenticate('saml', { 'failureRedirect': '/', 'failureFlash': true }),
function(req, res) {
console.log('POST [/login] \n');
res.redirect('/');
}
);
app.get(
'/profile',
function(req, res){
if (req.isAuthenticated()) {
console.log('GET [/profile] user authenticated! req.user: %s \n', JSON.stringify(req.user));
res.render('profile', { 'user': req.user });
} else {
console.log('GET [/profile] user not authenticated! \n');
res.redirect('/login');
}
}
);
app.get(
'/logout',
function(req, res) {
console.log('GET [/logout] \n');
passport._strategy('saml').logout(
req,
function(err, requestUrl) {
req.logout();
res.redirect('/');
}
);
}
);
/*
---------------------------------------------------------------------------------------------------
-- start https server
---------------------------------------------------------------------------------------------------
*/
const server = https.createServer({
'key': https_pvk,
'cert': https_cert
}, app);
server.listen(44300, function() {
console.log('Listening on https://localhost:%d', server.address().port)
});
Thank you in advance for your help and guidance!