- Notifications
You must be signed in to change notification settings - Fork 478
How to use with ADFS
This document attempts to describe a complete solution for integrating with AD FS.
Create a folder to contain your keys and certificates.
Download mellon_create_metadata.sh
Create a new key, certificate and relying party XML as follows:
./mellon_create_metadata.sh acme_tools_com https://acme_tools.com/adfs/postResponseUse retrieve_adfs_certificate.sh to get your AD FS server's signing certificate:
#!/bin/sh # Author: Tim Brody <T.D.Brody@soton.ac.uk> # Date: 2015-02-11 # # Retrieve the signing certificate from an ADFS instance in PEM format. ADFS_SERVER=$1 if [ "$#" -ne "1" ]; then echo "Usage: $0 <adfs server URL>" exit 1 fi URL=$ADFS_SERVER/FederationMetadata/2007-06/FederationMetadata.xml TEMPFILE=$(mktemp) if [[ $(command -v wget) ]]; then wget --no-check-certificate -q -O $TEMPFILE $URL elif [[ $(command -v curl) ]]; then curl -sk $URL -o $TEMPFILE else echo "Neither curl or wget was found" exit 127 fi if [ $? -ne 0 ]; then echo "Error requesting $URL" exit 1 fi echo "-----BEGIN CERTIFICATE-----" (xmllint --shell $TEMPFILE | grep -v '^/ >' | grep -v '^ ----' | fold -w 64) << EndOfScript setns a=urn:oasis:names:tc:SAML:2.0:metadata setns b=http://www.w3.org/2000/09/xmldsig# cat /a:EntityDescriptor/b:Signature/b:KeyInfo/b:X509Data/b:X509Certificate/text() EndOfScript echo "-----END CERTIFICATE-----" unlink $TEMPFILE./retrieve_adfs_certificate.sh https://adfs.acme_tools.com/ > adfs.acme_tools.com.crtCopy the acme_tools_com.xml to your AD FS server. Use the AD FS management relying party wizard to import this XML, creating a relying party. Create claim rules to pass authentication information to your application.
This example assumes you will pass in the UPN.
Set-AdfsRelyingPartyTrust -TargetIdentifier "acme_tools_com" -SamlResponseSignature "MessageAndAssertion"Create a separate file for passport configuration (assumed to be config/passport.js).
var fs = require("fs"), passport = require("passport"), SamlStrategy = require("passport-saml").Strategy; passport.serializeUser(function (user, done) { done(null, user); }); passport.deserializeUser(function (user, done) { done(null, user); }); passport.use( new SamlStrategy( { entryPoint: "https://adfs.acme_tools.com/adfs/ls/", issuer: "acme_tools_com", callbackUrl: "https://acme_tools.com/adfs/postResponse", privateKey: fs.readFileSync("/path/to/acme_tools_com.key", "utf-8"), cert: fs.readFileSync("/path/to/adfs.acme_tools.com.crt", "utf-8"), // other authn contexts are available e.g. windows single sign-on // see: https://learn.microsoft.com/en-us/dotnet/api/system.identitymodel.tokens.authenticationmethods?view=netframework-4.8#fields authnContext: [ "http://schemas.microsoft.com/ws/2008/06/identity/authenticationmethod/password", ], identifierFormat: null, // this is configured under the Advanced tab in AD FS relying party signatureAlgorithm: "sha256", racComparison: "exact", // default to exact RequestedAuthnContext Comparison Type // From the metadata document audience: "https://adfs.acme_tools.com/FederationMetadata/2007-06/FederationMetadata.xml", }, function (profile, done) { return done(null, { upn: profile["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn"], // e.g. if you added a Group claim group: profile["http://schemas.xmlsoap.org/claims/Group"], }); } ) ); module.exports = passport; var passport = require('passport'); var express = require('express'); ... etc. var app = express(); require('./config/passport.js'); ... add the usual express pro-forma app.use(passport.initialize()); app.use(passport.session()); app.get('/login', passport.authenticate('saml', { failureRedirect: '/', failureFlash: true }), function(req, res) { res.redirect('https://acme_tools.com'); } ); app.post('/adfs/postResponse', passport.authenticate('saml', { failureRedirect: '/', failureFlash: true }), function(req, res) { res.redirect('https://acme_tools.com'); } ); app.get('/secure', validUser, routes.secure); function validUser(req, res, next) { if (!req.user) { res.redirect('https://acme_tools.com/login'); } next(); } var server = http.createServer(app);If you are setting up an ADFS 2016 server, you might run into the following issue with the previous settings:
An error occurred during an attempt to read the federation metadata. Verify that the specified URL or host name is a valid federation metadata endpoint. Verify your proxy server setting. For more information about how to verify you proxy sever setting, see the AD FS Troubleshooting Guide http://go.microsoft.com/fwlink/?LinkId=182180). Error message: EntityDescriptor 'acme_tools_com'. ID0014: The value 'NameIDFormat' must be an absolute URI.
If you remove the identifierFormat, it works as expected.