saml-idp
Version:
Test Identity Provider (IdP) for SAML 2.0 Web Browser SSO Profile
287 lines (202 loc) • 10.6 kB
Markdown
# 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](http://en.wikipedia.org/wiki/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
``` shell
npm install --global saml-idp
```
### Manual
From inside a local copy of this repo
``` shell
npm install
# or
npm link
```
### Library
``` shell
npm install saml-idp
```
### Docker
1. docker-compose build
2. 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):
``` shell
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.
``` javascript
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)
``` javascript
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: 'saml.jackson@example.com',
},
},
});
```
### Command Line
#### SSO Profile
``` shell
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
``` shell
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
```json
{
"email": "saml.jackson@example.com"
}
```
#### Metadata Entry
```json
{
"id": "email",
"optional": false,
"displayName": "E-Mail Address",
"description": "The e-mail address of the user",
"multiValue": false
}
```
#### SAML Assertion Attribute Statement
```xml
<saml:Attribute Name="email"><saml:AttributeValue xsi:type="xs:anyType">saml.jackson@example.com</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)](developer.okta.com)
### 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`.
1. Add metadata entry for your new attributes. The `id` property must be the name of the SAML Attribute
```json
{
"id": "customAttribute",
"optional": false,
"displayName": "Custom Attribute",
"description": "My custom attribute",
"multiValue": false
}
```
2. 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
``` shell
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
``` shell
openssl x509 -pubkey -noout -in cert.pem > pub.key
```