@sidewinder1138/saml-idp
v1.4.0
Published
Test Identity Provider (IdP) for SAML 2.0 Web Browser SSO Profile
Downloads
1,676
Readme
NOTE: THIS IS A FORK
This version of saml-idp is a fork of the original work created by mcguinness (see here: https://github.com/mcguinness/saml-idp).
I took this approach for now just to get the ball rolling on some features I desperately needed. If possible I'd rather share my changes upstream and kill this fork eventually.
Changes so far:
v1.3.1 - No changes by me, I just released the latest version of what mcguinness had in github.
v1.4.0 - Improved the runServer() to work in an asynchronous way (via callback), added a "quiet" mode which silences the noisy console.log calls when running as a library.
Introduction
This app provides a simple SAML Identity Provider (IdP) to test SAML 2.0 Service Providers (SPs) with the SAML 2.0 Web Browser SSO Profile or the Single Logout Profile.
This sample is not intended for use with production systems!
Installation
Global Command Line Tool
npm install --global saml-idp
Manual
From inside a local copy of this repo
npm install
# or
npm link
Library
npm install saml-idp
Docker
- docker-compose build
- docker-compose up
Simply modify Dockerfile to specify your own parameters.
Generating IdP Signing Certificate
You must generate a self-signed certificate for the IdP.
The private key should be unique to your test IdP and not shared!
You can generate a keypair using the following command (requires openssl in your path):
openssl req -x509 -new -newkey rsa:2048 -nodes -subj '/C=US/ST=California/L=San Francisco/O=JankyCo/CN=Test Identity Provider' -keyout idp-private-key.pem -out idp-public-cert.pem -days 7300
Usage
Library
An IdP server can be started using the exported runServer
function. runServer
accepts a config object which matches the interface of the saml-idp
command.
const { runServer } = require("saml-idp");
runServer({
acsUrl: `https://foo.okta.com/auth/saml20/assertion-consumer`,
audience: `https://foo.okta.com/auth/saml20/metadata`,
});
Custom user config (claims)
const { runServer } = require("saml-idp");
runServer({
acsUrl: `https://foo.okta.com/auth/saml20/assertion-consumer`,
audience: `https://foo.okta.com/auth/saml20/metadata`,
config: {
user: userDefaults,
// The auth-service requires at least one AttributeStatement in the SAML assertion.
metadata: [
{
id: "email",
optional: false,
displayName: "E-Mail Address",
description: "The e-mail address of the user",
multiValue: false,
},
{
id: "userType",
optional: true,
displayName: "User Type",
description: "The type of user",
options: ["Admin", "Editor", "Commenter"],
},
],
user: {
email: "[email protected]",
},
},
});
Command Line
SSO Profile
saml-idp --acsUrl {POST URL} --audience {audience}
SSO & SLO Profile
saml-idp --acsUrl {POST URL} --sloUrl {POST URL} --audience {audience}
Open http://localhost:7000
in your browser to start an IdP initiated flow to your SP
Example
saml-idp --acsUrl https://foo.okta.com/auth/saml20/example --audience https://www.okta.com/saml2/service-provider/spf5aFRRXFGIMAYXQPNV
Options
The following options can either be passed as --<option>
or to runServer
in an options object.
| Option (* required) | Description | Default | | -----------------------: | --------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- | | host | IdP Web Server Listender Host | localhost | | port | IdP Web Server Listener Port | 7000 | | cert * | IdP Signature PublicKey Certificate | ./idp-public-cert.pem | | key * | IdP Signature PrivateKey Certificate | ./idp-private-key.pem | | issuer * | IdP Issuer URI | urn:example:idp | | acsUrl * | SP Assertion Consumer URL | | sloUrl | SP Single | | audience * | SP Audience URI | | serviceProviderId | SP Issuer/Entity URI | | relayState | Default SAML RelayState | | disableRequestAcsUrl | Disables ability for SP AuthnRequest to specify Assertion Consumer URL | false | | encryptAssertion | Encrypts assertion with SP Public Key | false | | encryptionCert | SP Certificate (pem) for Assertion Encryption | | encryptionPublicKey | SP RSA Public Key (pem) for Assertion Encryption (e.g. openssl x509 -pubkey -noout -in sp-cert.pem) | | httpsPrivateKey | Web Server TLS/SSL Private Key (pem) | | httpsCert | Web Server TLS/SSL Certificate (pem) | | https * | Enables HTTPS Listener (requires httpsPrivateKey and httpsCert) | false | | configFile * | Path to a SAML attribute config file | saml-idp/config.js | | rollSession | Create a new session for every authn request instead of reusing an existing session | false | | authnContextClassRef | Authentication Context Class Reference | urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport | | authnContextDecl | Authentication Context Declaration (XML FilePath) |
IdP SAML Settings
Issuer
The default IdP issuer is urn:example:idp
. You can change this with the --iss
argument.
Signing Certificate
The signing certificate public key must be specified as a file path or PEM string using the cert
argument.
To generate a self-signed certificate for the IdP run
openssl req -x509 -new -newkey rsa:2048 -nodes \
-subj '/C=US/ST=California/L=San Francisco/O=JankyCo/CN=Test Identity Provider' \
-keyout idp-private-key.pem \
-out idp-public-cert.pem -days 7300
The signing certificate private key must be specified as a file path or PEM string using the key
argument
Passing key/cert pairs from environment variables
Signing certificate key/cert pairs can also be passed from environment variables.
saml-idp --acsUrl {POST URL} --audience {audience} --cert="$SAML_CERT" --key="$SAML_KEY"
Single Sign-On Service Binding
Both SSO POST and Redirect bindings are available on the same endpoint which by default is http://localhost:7000/saml/sso
| Binding | URL |
| ------------- | -------------------------------- |
| HTTP-Redirect | http://localhost:port/saml/sso
|
| HTTP-POST | http://localhost:port/saml/sso
|
Single Logout Service Binding
Both SSO POST and Redirect bindings are available on the same endpoint which by default is http://localhost:7000/saml/slo
| Binding | URL |
| ------------- | -------------------------------- |
| HTTP-Redirect | http://localhost:port/saml/slo
|
| HTTP-POST | http://localhost:port/saml/slo
|
SAML Metadata
IdP SAML metadata is available on http://localhost:port/metadata
Assertion Attributes
The IdP mints the user's profile as a SAML Assertion Attribute Statement using the metadata
property in config.js
. Profile properties that match a metadata entry id
property will be generated as a SAML Attribute with the same name. The IdP UI will automatically render an input for each entry defined via a metadata
entry in config.js
with a default value from the matching profile
property.
Profile Property
{
"email": "[email protected]"
}
Metadata Entry
{
"id": "email",
"optional": false,
"displayName": "E-Mail Address",
"description": "The e-mail address of the user",
"multiValue": false
}
SAML Assertion Attribute Statement
<saml:Attribute Name="email"><saml:AttributeValue xsi:type="xs:anyType">[email protected]</saml:AttributeValue>
Default Attributes
The default profile mappings are defined in config.js
as:
| Profile Property | SAML Attribute Name |
| --------------------- | ------------------------------- |
| userName | Subject NameID |
| nameIdFormat | Subject NameID Format |
| nameIdNameQualifier | Subject NameID Name Qualifer |
| nameIdSPNameQualifier | Subject NameID SP Name Qualifer |
| nameIdSPProvidedID | Subject NameID SP ProvidedID |
| firstName | firstName
|
| lastName | lastName
|
| displayName | displayName
|
| email | email
|
| mobilePhone | mobilePhone
|
| groups | groups
|
SAML attribute mappings currently default to Okta (Inbound SAML)
Custom Attributes
New attributes can be defined at runtime in the IdP UI or statically by modifying the profile
and metadata
objects in config.js
.
Add metadata entry for your new attributes. The
id
property must be the name of the SAML Attribute{ "id": "customAttribute", "optional": false, "displayName": "Custom Attribute", "description": "My custom attribute", "multiValue": false }
Optionally add a default profile attribute value that will be used on startup
Assertion Encryption
Encrypted assertions require both a certificate and public key from the target service provider in the PEM format (base64 encoding of .der
, .cer
, .cert
, .crt
). You can convert certificate formats with openssl
DER to PEM
openssl x509 -inform der -in to-convert.der -out converted.pem
The following formats or extensions should be convertible to the pem format:
.der
,.cer
,.cert
, `.crt
PEM Certificate to Public Key
PEM files that contain the header -----BEGIN CERTIFICATE-----
can also be converted to just the public key which is a file with just the -----BEGIN PUBLIC KEY-----
header
openssl x509 -pubkey -noout -in cert.pem > pub.key