An open API service indexing awesome lists of open source software.

https://github.com/mcguinness/saml-idp

Simple SAML Identity Provider (IdP) for Node
https://github.com/mcguinness/saml-idp

identity-provider idp saml saml2

Last synced: 7 months ago
JSON representation

Simple SAML Identity Provider (IdP) for Node

Awesome Lists containing this project

README

          

# 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 `--` or to `runServer` in an options object.

Option (* required) | Description | Default
-----------------------: | --------------------------------------------------------------------------------------------------- | ----------
**host** | IdP Web Server Listener 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.jackson@example.com
```

### 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
```