├── .editorconfig
├── .github
└── FUNDING.yml
├── .gitignore
├── .npmignore
├── .pre-commit.sh
├── .snyk
├── .travis.yml
├── @types
└── xml-encryption.d.ts
├── LICENSE
├── Makefile
├── README.md
├── docs
├── .nojekyll
├── CNAME
├── README.md
├── _coverpage.md
├── _media
│ ├── bg.jpg
│ ├── favicon.ico
│ └── lock.png
├── _sidebar.md
├── advance.md
├── basic.md
├── configuration.md
├── encrypted-saml-response.md
├── examples.md
├── gitlab.md
├── guide.md
├── idp-configuration.md
├── idp.md
├── index.html
├── key-generation.md
├── metadata-distribution.md
├── multi-entities.md
├── okta-inbound.md
├── okta.md
├── onelogin.md
├── prerequistite.md
├── saml-request.md
├── saml-response.md
├── signed-saml-request.md
├── signed-saml-response.md
├── sp-configuration.md
├── sp.md
└── template.md
├── index.ts
├── package.json
├── src
├── api.ts
├── binding-post.ts
├── binding-redirect.ts
├── entity-idp.ts
├── entity-sp.ts
├── entity.ts
├── extractor.ts
├── flow.ts
├── libsaml.ts
├── metadata-idp.ts
├── metadata-sp.ts
├── metadata.ts
├── types.ts
├── urn.ts
├── utility.ts
└── validator.ts
├── test
├── README.md
├── extractor.ts
├── flow.ts
├── index.ts
├── issues.ts
├── key
│ ├── idp
│ │ ├── README.md
│ │ ├── cert.cer
│ │ ├── cert2.cer
│ │ ├── encryptKey.pem
│ │ ├── encryptionCert.cer
│ │ ├── nocrypt.pem
│ │ ├── privkey.pem
│ │ └── privkey2.pem
│ ├── keypass.txt
│ └── sp
│ │ ├── cert.cer
│ │ ├── encryptKey.pem
│ │ ├── encryptionCert.cer
│ │ ├── knownGoodCert.cer
│ │ ├── knownGoodEncryptKey.pem
│ │ └── privkey.pem
└── misc
│ ├── attack_response_signed.xml
│ ├── dumpes_issuer_response.xml
│ ├── failed_response.xml
│ ├── false_signed_request_sha1.xml
│ ├── false_signed_request_sha256.xml
│ ├── false_signed_request_sha512.xml
│ ├── idpmeta.xml
│ ├── idpmeta_nosign.xml
│ ├── idpmeta_onelogoutservice.xml
│ ├── idpmeta_rollingcert.xml
│ ├── idpmeta_share_cert.xml
│ ├── invalid_response.xml
│ ├── logout_request.xml
│ ├── multiple_entitydescriptor.xml
│ ├── request.xml
│ ├── response.xml
│ ├── response_signed.xml
│ ├── response_signed_cert1.xml
│ ├── response_signed_cert2.xml
│ ├── signed_request_sha1.xml
│ ├── signed_request_sha256.xml
│ ├── signed_request_sha512.xml
│ ├── signed_response_sha1.xml
│ ├── signed_response_sha256.xml
│ ├── signed_response_sha512.xml
│ ├── sp_metadata_98.xml
│ ├── spmeta.xml
│ ├── spmeta_noassertsign.xml
│ └── spmeta_noauthnsign.xml
├── tsconfig.json
├── tslint.json
├── types.d.ts
└── yarn.lock
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = tab
5 | end_of_line = lf
6 | charset = utf-8
7 | trim_trailing_whitespace = true
8 | insert_final_newline = true
9 |
10 | [*.{json,js,ts,jsx,html,css}]
11 | indent_style = space
12 | indent_size = 2
13 |
14 | [.eslintrc]
15 | indent_style = space
16 | indent_size = 2
17 |
18 | [*.md]
19 | trim_trailing_whitespace = false
20 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: [tngan]
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 |
5 | # Runtime data
6 | pids
7 | *.pid
8 | *.seed
9 |
10 | # Directory for instrumented libs generated by jscoverage/JSCover
11 | lib-cov
12 |
13 | # Coverage directory used by tools like istanbul
14 | coverage
15 |
16 | # Dependency directory
17 | # Commenting this out is preferred by some people, see
18 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git-
19 | node_modules
20 |
21 | build
22 | types/
23 |
24 | .yarnclean
25 |
26 | .nyc_output
27 |
28 | #jetbrains IDEs
29 | .idea
30 |
31 | #vscode
32 | .vscode
33 |
34 | *.tgz
35 |
36 | package-lock.json
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | examples
3 | test
4 | @types
5 | docs
6 | yarn*
7 | .nyc_output
--------------------------------------------------------------------------------
/.pre-commit.sh:
--------------------------------------------------------------------------------
1 | echo "Linting"
2 | npm run lint
3 | LINTRESULT=$?
4 |
5 | echo "Compiling"
6 | $(npm bin)/tsc
7 | BUILDRESULT=$?
8 |
9 | if [[ $LINTRESULT -ne 0 || $BUILDRESULT -ne 0 ]]; then
10 | echo "Fix errors before commit"
11 | exit 1
12 | else
13 | echo "Ok to commit"
14 | exit 0
15 | fi
16 |
--------------------------------------------------------------------------------
/.snyk:
--------------------------------------------------------------------------------
1 | # Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities.
2 | version: v1.14.0
3 | ignore: {}
4 | # patches apply the minimum changes required to fix a vulnerability
5 | patch:
6 | SNYK-JS-LODASH-450202:
7 | - '@authenio/xml-encryption > async > lodash':
8 | patched: '2019-12-11T18:53:51.541Z'
9 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 |
3 | node_js:
4 | - "10"
5 | - "12"
6 | - "14"
7 |
8 | env:
9 | - INSTALL_JDK=1
10 | - INSTALL_JDK=0
11 |
12 | before_install:
13 | - if [[ "$INSTALL_JDK" == "1" ]] ; then make install_jdk ; fi
14 |
15 | install:
16 | - yarn install --production=true
17 |
18 | script:
19 | - yarn add @authenio/samlify-xsd-schema-validator
20 | - yarn test --timeout=30s
21 |
22 | branches:
23 | only:
24 | - master
25 | - /^.*-alpha$/
26 | - /^.*-rc.*$/
27 | - /^feature\/.*$/
28 |
29 | after_success: npm run coverage
--------------------------------------------------------------------------------
/@types/xml-encryption.d.ts:
--------------------------------------------------------------------------------
1 | declare module "xml-encryption" {
2 | export interface EncryptOptions {
3 | rsa_pub: string | Buffer;
4 | pem: string | Buffer;
5 | encryptionAlgorithm: string;
6 | keyEncryptionAlgorithm: string;
7 | input_encoding?: string;
8 | }
9 | export interface DecryptOptions {
10 | key: string | Buffer;
11 | }
12 | export interface Callback {
13 | (err:Error, result): void;
14 | }
15 | export function encrypt(content: string, options: EncryptOptions, callback: Callback): string;
16 | export function encryptKeyInfo(symmetricKey: string, options: EncryptOptions, callback: Callback): string;
17 | export function decrypt(xml: string | Document, options: DecryptOptions, callback: Callback): string;
18 | export function decryptKeyInfo(doc: string | Document, options: DecryptOptions): string;
19 | const _default: { decrypt, encrypt, decryptKeyInfo, encryptKeyInfo };
20 | export default _default;
21 | }
22 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016-present Tony Ngan
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | PROJECT = "samlify"
2 |
3 | install: ;@echo "install ${PROJECT}"; \
4 | npm install;
5 |
6 | clean: ;
7 | rm -rf node_modules
8 |
9 | rebuild: ;
10 | rm -rf build; \
11 | tsc; \
12 |
13 | pretest: ;
14 | mkdir -p build/test; \
15 | cp -a test/key test/misc build/test;
16 |
17 | install_jdk:
18 | sudo add-apt-repository ppa:openjdk-r/ppa -y
19 | sudo apt-get -qq update
20 | sudo apt-get install -y openjdk-9-jdk
21 |
22 | doc: ;@echo "prepare and serve the docs"; \
23 | docsify serve ./docs
24 |
25 | .PHONY: rebuild pretest doc install_jdk
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # samlify ·
2 |
3 | [](https://travis-ci.org/tngan/samlify)
4 | [](https://www.npmjs.com/package/samlify)
5 | [](https://coveralls.io/github/tngan/samlify?branch=master)
6 | [](https://spectrum.chat/samlify)
7 |
8 | Highly configuarable Node.js SAML 2.0 library for Single Sign On
9 |
10 | ## Welcome PRs
11 |
12 | Welcome all PRs for maintaining this project, or provide a link to the repositories especially for use cases alongside with different frameworks.
13 |
14 | ### Sponsor
15 |
16 | | |
If you want to quickly implement SAML SSO, feel free to check out Auth0's NodeJS SDK and free plan at [auth0.com/overview](https://auth0.com/overview?utm_source=GHsponsor&utm_medium=GHsponsor&utm_campaign=samlify&utm_content=auth).
|
17 | | :----------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
18 |
19 |
20 | ### Installation
21 |
22 | To install the stable version
23 |
24 | Starting from v2.6, multiple schema validators are now supported. You can simply set the validator via the following global method. We have four validator modules right now, and you can write your own. The `setSchemaValidator` is required since v2.6, it will throw error if you don't set at the beginning.
25 |
26 | ```js
27 | import * as samlify from 'samlify';
28 | import * as validator from '@authenio/samlify-xsd-schema-validator';
29 | // import * as validator from '@authenio/samlify-validate-with-xmllint';
30 | // import * as validator from '@authenio/samlify-node-xmllint';
31 | // import * as validator from '@authenio/samlify-libxml-xsd'; // only support for version of nodejs <= 8
32 |
33 | // const validator = require('@authenio/samlify-xsd-schema-validator');
34 | // const validator = require('@authenio/samlify-validate-with-xmllint');
35 | // const validator = require('@authenio/samlify-node-xmllint');
36 | // const validator = require('@authenio/samlify-libxml-xsd');
37 |
38 | samlify.setSchemaValidator(validator);
39 | ```
40 |
41 | Now you can create your own schema validator and even suppress it but you have to take the risk for accepting malicious response.
42 |
43 | ```typescript
44 | samlify.setSchemaValidator({
45 | validate: (response: string) => {
46 | /* implment your own or always returns a resolved promise to skip */
47 | return Promise.resolve('skipped');
48 | }
49 | });
50 | ```
51 |
52 | For those using Windows, `windows-build-tools` should be installed globally before installing samlify if you are using `libxml` validator.
53 |
54 | ```console
55 | yarn global add windows-build-tools
56 | ```
57 |
58 | ### Development
59 |
60 | This project is now developed using TypeScript, also support Yarn which is a new package manager.
61 |
62 | ```console
63 | yarn global add typescript
64 | yarn
65 | ```
66 |
67 | ### Get Started
68 |
69 | ```javascript
70 | const saml = require('samlify');
71 | ```
72 |
73 | See full documentation [here](https://samlify.js.org/)
74 |
75 | ### Example
76 |
77 | [react-samlify](https://github.com/passify/react-samlify) SP example powered by React, TypeScript and Webpack
78 |
79 | ### Talks
80 |
81 | [An introduction to Single Sign On](http://www.slideshare.net/TonyNgan/an-introduction-of-single-sign-on)
82 |
83 | ### License
84 |
85 | [MIT](LICENSE)
86 |
87 | ### Copyright
88 |
89 | Copyright (C) 2016-present Tony Ngan, released under the MIT License.
90 |
--------------------------------------------------------------------------------
/docs/.nojekyll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tryretool/samlify/c960ef6d64382d4a021590a69b1e10ce17bb9cf8/docs/.nojekyll
--------------------------------------------------------------------------------
/docs/CNAME:
--------------------------------------------------------------------------------
1 | samlify.js.org
2 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | ## samlify
2 |
3 | > High-level API library for Single Sign On with SAML 2.0
4 |
5 | This module provides a library for scaling Single Sign On implementation. Developers can easily configure the entities by importing the metadata.
6 |
7 | We provide a simple interface that's highly configurable.
8 |
9 | ### Thanks
10 |
11 |
12 |
13 |
14 | ### Installation
15 | To install the stable version
16 |
17 | ```console
18 | $ npm install samlify
19 | ```
20 |
21 | or
22 |
23 | ```console
24 | $ yarn add samlify
25 | ```
26 |
27 | ### Use cases
28 |
29 | + IdP-initiated Single Sign On
30 | + IdP-initiated Single Log-out
31 | + SP-initiated Single Sign On
32 | + SP-initiated Single Log-out (in development)
33 |
34 | Simple solution of Identity Provider is provided in this module for test and educational use. Work with other 3rd party Identity Provider is also supported.
35 |
36 | ### Glimpse of code
37 |
38 | !> **API is changed since v2. All file attributes like metadata and keyFile, it's expected to be normalized as string. It allows easy integration with database storage and import from local file system.**
39 |
40 | !> **The constructor of entity is also modified to accept a single configuration object instead of putting metadata and advanced configurations in separate arguments.**
41 |
42 | ```javascript
43 | const saml = require('samlify');
44 | // configure a service provider
45 | const sp = saml.ServiceProvider({
46 | metadata: fs.readFileSync('./metadata_sp.xml')
47 | });
48 | // configure the corresponding identity provider
49 | const idp = saml.IdentityProvider({
50 | metadata: fs.readFileSync('./metadata_idp.xml')
51 | });
52 | // parse when receive a SAML Response from IdP
53 | router.post('/acs', (req, res) => {
54 | sp.parseLoginResponse(idp, 'post', req)
55 | .then(parseResult => {
56 | // Write your own validation and render function here
57 | })
58 | .catch(console.error);
59 | });
60 | ```
61 |
62 | Our default validation is to validate signature and the issuer name of Identity Provider. The code base is self explained. More use cases are provided in this documentation to fit in the real world application.
63 |
64 | ### License
65 |
66 | MIT
67 |
--------------------------------------------------------------------------------
/docs/_coverpage.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | # samlify 2.7.0
4 |
5 | > Node.js SAML2 API
6 |
7 | - Simple and active maintenance
8 | - Includes Identity and Service Provider
9 | - Highly configurable
10 |
11 | [GitHub](https://github.com/tngan/samlify)
12 | [Get Started](#samlify)
13 |
14 |
15 | 
16 |
--------------------------------------------------------------------------------
/docs/_media/bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tryretool/samlify/c960ef6d64382d4a021590a69b1e10ce17bb9cf8/docs/_media/bg.jpg
--------------------------------------------------------------------------------
/docs/_media/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tryretool/samlify/c960ef6d64382d4a021590a69b1e10ce17bb9cf8/docs/_media/favicon.ico
--------------------------------------------------------------------------------
/docs/_media/lock.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tryretool/samlify/c960ef6d64382d4a021590a69b1e10ce17bb9cf8/docs/_media/lock.png
--------------------------------------------------------------------------------
/docs/_sidebar.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | - **Get Started**
4 | - [Prerequisite](/prerequistite)
5 | - **Basic**
6 | - [Introduction](/basic)
7 | - [Identity Provider](/idp)
8 | - [Service Provider](/sp)
9 | - [SAML Request](/saml-request)
10 | - [Signed](/signed-saml-request)
11 | - [SAML Response](/saml-response)
12 | - [Signed](/signed-saml-response)
13 | - [Encrypted](/encrypted-saml-response)
14 | - [Key Generation](/key-generation)
15 | - **Advanced**
16 | - [Introduction](/advance)
17 | - [Metadata Distribution](/metadata-distribution)
18 | - [IDP/SP Configuration](/configuration)
19 | - [Identity Provider](/idp-configuration)
20 | - [Service Provider](/sp-configuration)
21 | - [Attributes & Template](/template)
22 | - [Helper Functions](/helpers)
23 | - [Multiple Entities](/multi-entities)
24 | - **Examples**
25 | - [Gitlab](/gitlab)
26 | - [OneLogin](/onelogin)
27 | - [Okta](/okta)
28 | - [Inbound SAML](/okta-inbound)
29 |
--------------------------------------------------------------------------------
/docs/advance.md:
--------------------------------------------------------------------------------
1 | # Advanced
2 |
3 | Thanks for your patience. Reading documentation is a tough job, so that we keep as simple as possible. This chapter is about the advanced level tutorial. In real-world application, things become complicated and developers may need to do customizations. We hope to maintain a simple but highly configurable interface. Like in basic tutorial, we will go through step by step again.
4 |
5 | + Custom templates for SAML Request/Response
6 | + Scale with multiple Identity/Service Providers
7 | + Additional assertion validations
8 | + Metadata distribution
9 | + Configuration of Identity/Service Provider w/o metadata
10 |
11 | If you have ideas and want more examples, please don't hesitate to create an issue in our Github repository.
12 |
--------------------------------------------------------------------------------
/docs/basic.md:
--------------------------------------------------------------------------------
1 | # Basics
2 |
3 | Don't be scared off. Even through SAML leaves a lot of options to developers, and this documentation will go through step by step on:
4 |
5 | + Basic knowledge on SSO for newbie
6 | + Default environment settings
7 | + How to configure a service provider
8 | + How to configure a identity provider
9 | + How to send a SAML Request
10 | + How to parse a SAML Response
11 | + How to integrate with different idp and sp (Examples)
12 |
13 | In this basic tutorial, we provide the simplest solution (without signature and encryption). The real world application is complicated, those topics are covered in the advanced part.
14 |
--------------------------------------------------------------------------------
/docs/configuration.md:
--------------------------------------------------------------------------------
1 | # Configuration
2 |
3 | The easiest way to get SP and iDP ready is to import the metadata file directly.
4 |
5 | ```js
6 | // service provider
7 | const sp = saml.ServiceProvider({
8 | metadata: fs.readFileSync('./metadata/sp.xml')
9 | });
10 |
11 | // identity provider
12 | const idp = saml.IdentityProvider({
13 | metadata: fs.readFileSync('./metadata/idp.xml')
14 | });
15 | ```
16 |
17 | Without importing a defined metadata, we provide an advanced way to configure the entities. The metadata can be created according to the parameters later on.
18 |
19 | ```js
20 | // service provider
21 | const sp = saml.ServiceProvider({
22 | privateKey: readFileSync('./test/key/sp/privkey.pem'),
23 | privateKeyPass: 'q9ALNhGT5EhfcRmp8Pg7e9zTQeP2x1bW',
24 | isAssertionEncrypted: false,
25 | encPrivateKey: readFileSync('./test/key/sp/encryptKey.pem'),
26 | encPrivateKeyPass: 'g7hGcRmp8PxT5QeP2q9Ehf1bWe9zTALN',
27 | // ....
28 | });
29 |
30 | // identity provider
31 | const idp = saml.ServiceProvider({
32 | privateKey: readFileSync('./test/key/idp/privkey.pem'),
33 | privateKeyPass: 'q9ALNhGT5EhfcRmp8Pg7e9zTQeP2x1bW',
34 | isAssertionEncrypted: false,
35 | encPrivateKey: readFileSync('./test/key/idp/encryptKey.pem'),
36 | encPrivateKeyPass: 'g7hGcRmp8PxT5QeP2q9Ehf1bWe9zTALN',
37 | // ....
38 | });
39 | ```
40 |
41 | We will also generate the metadata for you if you use this advanced method to create your entity. See more [here](/metadata-distribution).
42 |
43 | ```js
44 | sp.getMetadata();
45 | idp.getMetadata();
46 |
47 | // or expose it to public (e.g. express.js)
48 | router.get('/metadata', (req, res) => {
49 | const metadata = sp.getMetadata();
50 | return res.header('Content-Type','text/xml').send(metadata);
51 | });
52 | ```
53 |
54 | ## References
55 |
56 | + [Metadata for the OASIS Security Assertion Markup Language](https://www.oasis-open.org/committees/download.php/35391/sstc-saml-metadata-errata-2.0-wd-04-diff.pdf)
57 | + [SAML specification](http://saml.xml.org/saml-specifications)
58 |
--------------------------------------------------------------------------------
/docs/encrypted-saml-response.md:
--------------------------------------------------------------------------------
1 | # Encrypted Assertion
2 |
3 | According to the guideline of SAML, our module leaves some security options for developers. If the assertion contains some sensitive information, Identity Provider may want to do encryption. In IdP's construction, add the following settings as follow:
4 |
5 | ```javascript
6 | const idp = IdentityProvider({
7 | isAssertionEncrypted: true,
8 | metadata: fs.readFileSync('./metadata_idp.xml'),
9 | dataEncryptionAlgorithm: 'http://www.w3.org/2001/04/xmlenc#aes128-cbc',
10 | keyEncryptionAlgorithm: 'http://www.w3.org/2001/04/xmlenc#rsa-1_5'
11 | });
12 | ```
13 |
14 | If you remember SP configuration for signing a request, there are two parameters in the setting object. They are `privateKey` and `privateKeyPass`. **Warning:** If you are applying our solution instead of another 3rd party IdP, it's suggested not to use same key for both signing and encryption.
15 |
16 | In SP's metadata, the certificate must be included in order to allow idp to encrypt the assertion.
17 |
18 | ```xml
19 |
20 |
21 |
22 | MIID6TCCAtGg...
23 |
24 |
25 |
26 | ```
27 |
28 | Now all you need to do is to use `sp.parseLoginResponse` again to parse and verify the response.
29 |
30 | ```javascript
31 | router.post('/acs', (req, res) => {
32 | sp.parseLoginResponse(idp, 'post', req)
33 | .then(parseResult => {
34 | // Use the parseResult to do customized action
35 | })
36 | .catch(console.error);
37 | });
38 | ```
39 |
40 | Currently, we support the following encrpytion algorithms:
41 |
42 | **Data encryption algorithms**
43 | * http://www.w3.org/2001/04/xmlenc#tripledes-cbc
44 | * http://www.w3.org/2001/04/xmlenc#aes128-cbc
45 | * http://www.w3.org/2001/04/xmlenc#aes256-cbc
46 |
47 | **Key encryption algorithms**
48 | * http://www.w3.org/2001/04/xmlenc#rsa-1_5
49 | * http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p
50 |
51 | Credits to [auth0/node-xml-encryption](https://github.com/auth0/node-xml-encryption)
52 |
--------------------------------------------------------------------------------
/docs/examples.md:
--------------------------------------------------------------------------------
1 | # Examples
2 |
3 | ?> A tutorial is not only including text-book knowledge and guideline. Therefore, a number of examples are provided in this chapter. Different use cases for real application are covered in each example.
4 |
5 | **Entities**
6 |
7 | - [OneLogin](/onelogin)
8 | - [Gitlab](/gitlab)
9 | - [Okta](/okta)
10 |
--------------------------------------------------------------------------------
/docs/gitlab.md:
--------------------------------------------------------------------------------
1 | # Work with Gitlab (samlify as idp)
2 |
3 | In this tutorial, we will walk through step by step to configure self-hosted and dockerized Gitlab CE, also integrates with samlify.
4 |
5 | ### Setup postgresql
6 |
7 | ```
8 | docker run --name gitlab-postgresql -d \
9 | --env 'DB_NAME=gitlabhq_production' \
10 | --env 'DB_USER=gitlab' --env 'DB_PASS=password' \
11 | --env 'DB_EXTENSION=pg_trgm' \
12 | --volume /esaml2/postgresql:/var/lib/postgresql \
13 | sameersbn/postgresql:9.6-2
14 | ```
15 | !> Remember to configure file sharing when work with volume mount
16 |
17 | ### Setup redis
18 |
19 | ```
20 | docker run --name gitlab-redis -d \
21 | --volume /esaml2/redis:/var/lib/redis \
22 | sameersbn/redis:latest
23 | ```
24 |
25 | ### Running gitlab in container
26 |
27 | ```
28 | docker run --name gitlab -d \
29 | --link gitlab-postgresql:postgresql --link gitlab-redis:redisio \
30 | --publish 10022:22 --publish 10080:80 \
31 | --env 'GITLAB_PORT=10080' --env 'GITLAB_SSH_PORT=10022' \
32 | --env 'GITLAB_SECRETS_DB_KEY_BASE=long-and-random-alpha-numeric-string' \
33 | --env 'GITLAB_SECRETS_SECRET_KEY_BASE=long-and-random-alpha-numeric-string' \
34 | --env 'GITLAB_SECRETS_OTP_KEY_BASE=long-and-random-alpha-numeric-string' \
35 | --env 'OAUTH_SAML_ASSERTION_CONSUMER_SERVICE_URL=http://localhost:10080/users/auth/saml/callback' \
36 | --env 'OAUTH_SAML_IDP_CERT_FINGERPRINT=77:36:12:0B:32:9A:6D:61:29:E1:0D:13:C0:FF:63:1A:B9:22:FC:3C' \
37 | --env 'OAUTH_SAML_IDP_SSO_TARGET_URL=http://localhost:3001/sso/SingleSignOnService/gitlab' \
38 | --env 'OAUTH_SAML_ISSUER=https://gitlab' \
39 | --env 'OAUTH_SAML_NAME_IDENTIFIER_FORMAT=urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress' \
40 | --volume /esaml2/gitlab:/home/git/data \
41 | sameersbn/gitlab:9.1.2
42 | ```
43 |
44 | ### Get fingerprint (This is another way I found)
45 |
46 | ```console
47 | $ openssl x509 -in ./key/idp/cert.cer -sha1 -noout -fingerprint
48 | ```
49 |
50 | ### Get metadata from gitlab
51 |
52 | `http://localhost:10080/users/auth/saml/metadata`
53 |
54 | remember to modify the acs endpoint to http://localhost:10080/users/auth/saml/callback
55 |
56 | ### The step-by-step configuration of IDP with samlify
57 |
58 | After setting up the gitlab, we need to set up the IDP with samlify. Beside, the identity provider is an experimental feature in this module.
59 |
60 | Since there are some required attributes are required and specified in the Gitlab metadata, so we need to add attributes to the response, so we need to customize response template when we construct the Identity provider.
61 |
62 | `email`, `name`, `first_name` and `last_name` (default email and name are `admin@example.com` and `Administrator` in docker-gitlab)
63 |
64 | And we need to change our metadata by setting `WantAuthnRequestsSigned` to false since the request from SP is not signed.
65 |
66 | Signed response is highly RECOMMENDED (compulsory in Gitlab's implementation), including assertion signature or/and entire message signature, so a new property `signatureConfig` is introduced into constructor of identity provider to specify the location, prefix of messsage signature, this configuration is exactly the same as [xml-crypto](https://github.com/yaronn/xml-crypto#examples).
67 |
68 | ```javascript
69 | const idp = require('samlify').IdentityProvider({
70 | metadata: readFileSync('./misc/metadata_idp1.xml'),
71 | privateKey: './misc/privkey.pem',
72 | isAssertionEncrypted: false,
73 | privateKeyPass: 'q9ALNhGT5EhfcRmp8Pg7e9zTQeP2x1bW',
74 | loginResponseTemplate: {
75 | context: '{Issuer}{Issuer}{NameID}{Audience}AuthnContextClassRef',
76 | attributes: [
77 | { name: "mail", valueTag: "user.email", nameFormat: "urn:oasis:names:tc:SAML:2.0:attrname-format:basic", valueXsiType: "xs:string" },
78 | { name: "name", valueTag: "user.name", nameFormat: "urn:oasis:names:tc:SAML:2.0:attrname-format:basic", valueXsiType: "xs:string" },
79 | { name: "first_name", valueTag: "user.first", nameFormat: "urn:oasis:names:tc:SAML:2.0:attrname-format:basic", valueXsiType: "xs:string" },
80 | { name: "last_name", valueTag: "user.last", nameFormat: "urn:oasis:names:tc:SAML:2.0:attrname-format:basic", valueXsiType: "xs:string" },
81 | ]
82 | },
83 | signatureConfig: {
84 | prefix: 'ds',
85 | location: { reference: "/*[local-name(.)='Response']/*[local-name(.)='Issuer']", action: 'after' }
86 | }
87 | });
88 | ```
89 |
90 | ### The step-by-step configuration of SP with samlify
91 |
92 | ```javascript
93 | const sp = require('samlify').ServiceProvider({
94 | metadata: readFileSync('./misc/metadata_sp1.xml')
95 | });
96 | ```
97 |
98 | the metadata is obtained from `http://localhost:10080/users/auth/saml/metadata`
99 |
--------------------------------------------------------------------------------
/docs/guide.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tryretool/samlify/c960ef6d64382d4a021590a69b1e10ce17bb9cf8/docs/guide.md
--------------------------------------------------------------------------------
/docs/idp-configuration.md:
--------------------------------------------------------------------------------
1 | # IDP Configuration
2 |
3 | You can use samlify as identity provider for testing/production purpose but you can also easily integrate samlify with the current identity provider setup.
4 |
5 | #### Required Parameters
6 |
7 | ?> You can either choose to import from metadata plus optional paramters, or defined properties plus optional parameters.
8 |
9 | - **metadata: String**
10 | IDP issued metadata to declare the structure and scope of the entity, as a common contract on how sso/slo should be proceeded.
11 |
12 | ```js
13 | const idp = new IdentityProvider({
14 | // required
15 | metadata: readFileSync('./test/misc/idpmeta.xml'),
16 | // optional
17 | privateKey: readFileSync('./test/key/idp/privkey.pem'),
18 | privateKeyPass: 'q9ALNhGT5EhfcRmp8Pg7e9zTQeP2x1bW',
19 | encPrivateKey: readFileSync('./test/key/idp/encryptKey.pem'),
20 | encPrivateKeyPass: 'g7hGcRmp8PxT5QeP2q9Ehf1bWe9zTALN',
21 | isAssertionEncrypted: true,
22 | });
23 | ```
24 |
25 | OR
26 |
27 | - **entityID: String** Entity identifier. It is used to identify your entity, and match the equivalence in each saml request/response.
28 |
29 | - **signingCert: String**
30 | _Optional_: Specify the certificate used for signing purpose if you construct the idp without a metadata.
31 |
32 | - **encryptCert: String**
33 | _Optional_: Specify the certificate used for encryption purpose if you construct the idp without a metadata.
34 |
35 | - **singleSignOnService: SignOnService[]**
36 | _Optional_: Declare the single sign on service if you construct the idp without a metadata.
37 |
38 | - **singleLogoutService: SignLogoutService[]**
39 | _Optional_: Declare the single logout service if you construct the idp without a metadata.
40 |
41 | - **nameIDFormat: NameIDFormat[]**
42 | _Optional_: Declare the name id format that would respond if you construct the idp without a metadata.
43 |
44 | ```js
45 | const idp = new IdentityProvider({
46 | // required
47 | entityID: 'http://hello-saml-idp.com/metadata',
48 | // optional parameters listed below
49 | });
50 | ```
51 |
52 | #### Optional Parameters
53 |
54 | - **wantAuthnRequestsSigned: Boolean**
55 | Declare if idp guarantees the authn request sent from sp is signed, reflects to the `WantAuthnRequestsSigned` in idp metadata, default to `false`.
56 |
57 | - **tagPrefix: {[key: TagPrefixKey]: string}**
58 | Declare the tag of specific xml document node. `TagPrefixKey` currently supports `encryptedAssertion` only. (See more [#220](https://github.com/tngan/samlify/issues/220))
59 |
60 | - **loginResponseTemplate: {context: String, attributes: Attributes}**
61 | Customize the login response template, and user can reuse it in the callback function to do runtime interpolation. (See [more](/template))
62 |
63 | - **wantLogoutResponseSigned: Boolean**
64 | Declare if idp guarantees the logout response from sp is signed.
65 |
66 | - **messageSigningOrder: SigningOrder**
67 | Declare the message signing order, either `sign-then-encrypt` (default) or `encrypt-then-sign`.
68 |
69 | - **relayState: String**
70 | Specify the relayState of the request.
71 |
72 | !> It will be deprecated soon and put into request level instead of entity level.
73 |
74 | - **isAssertionEncrypted: Boolean**
75 | Decalre if idp would encrypt the assertion in the response.
76 |
77 | !> It will be deprecated soon, then samlify will automatically detect if the document is encrypted.
78 |
79 | - **requestSignatureAlgorithm: SigningAlgorithm**
80 | The signature algorithm used in request. Default to `http://www.w3.org/2001/04/xmldsig-more#rsa-sha256`. We also support rsa-sha1 (not recommended) `http://www.w3.org/2000/09/xmldsig#rsa-sha1` and rsa-sha2 `http://www.w3.org/2001/04/xmldsig-more#rsa-sha512`.
81 |
82 | - **dataEncryptionAlgorithm: EncryptionAlgorithm**
83 | The encryption algorithm used in response. Default to `http://www.w3.org/2001/04/xmldsig-more#rsa-sha256`. We also support aes256 `http://www.w3.org/2001/04/xmlenc#aes256-cbc` and tripledes `http://www.w3.org/2001/04/xmlenc#tripledes-cbc`.
84 |
85 | - **keyEncryptionAlgorithm: KeyEncryptionAlgorithm**
86 | The key encryption algorithm. Default to rsa-1_5 `http://www.w3.org/2001/04/xmlenc#rsa-1_5`. We also support rsa-oaep-mgf1p `http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p`.
87 |
88 | - **generateID: (): String**
89 | A function to generate the document identifier in root node. Default to `_${UUID_V4}`.
90 |
--------------------------------------------------------------------------------
/docs/idp.md:
--------------------------------------------------------------------------------
1 | # Identity Provider
2 |
3 | Let's get started with entry point:
4 | ```javascript
5 | const saml = require('samlify');
6 | ```
7 |
8 | The following metadata is provided by the target identity provider.
9 |
10 | ```xml
11 |
12 |
13 |
14 |
15 |
16 | MIIEF...
17 |
18 |
19 |
20 | urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
21 |
22 |
23 |
24 |
25 |
26 | Support
27 | support@onelogin.com
28 |
29 |
30 | ```
31 |
32 | Import the above metadata and get the identity provider ready. Previously, we only allow user to enter path to file and the module will read for users. Starting from v2, we have relaxed the configuration to accept string, it allows user importing their metadata, key and certificate files from different sources. For examples, read from database, file systems, online resources (public url for metadata) and even in-memory storage.
33 |
34 | !> **API is changed since v2**
35 |
36 | ```javascript
37 | // after v2
38 | const idp = saml.IdentityProvider({
39 | metadata: fs.readFileSync('./metadata/onelogin_metadata_486670.xml')
40 | });
41 | // before v2 (deprecated)
42 | // const idp = saml.IdentityProvider('./metadata/onelogin_metadata_486670.xml');
43 | ```
44 |
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | samlify - High-level API for Single Sign On (SAML 2.0)
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/docs/key-generation.md:
--------------------------------------------------------------------------------
1 | # Key generation
2 |
3 | We use openssl to generate the keys and certificate for testing purpose. It is optional to use password protection for private key. The following is the commands to generate private key and self-signed certificate.
4 |
5 | ```console
6 | > openssl genrsa -passout pass:foobar -out encryptKey.pem 4096
7 | > openssl req -new -x509 -key encryptKey.pem -out encryptionCert.cer -days 3650
8 | ```
--------------------------------------------------------------------------------
/docs/metadata-distribution.md:
--------------------------------------------------------------------------------
1 | # Metadata distribution
2 |
3 | ?> Metadata is used to exchange information between Identity Provider and Service Provider. Simply there are two major ways to exchange Metadata.
4 |
5 | **Release in public **
6 |
7 | Display the Metadata in a specific URL. Everyone has the URL can watch the Metadata. Therefore, the Metadata is distributed publicly. We provide an API to do it once you've configure your SP.
8 |
9 | ```javascript
10 | const saml = require('samlify');
11 | const sp = saml.ServiceProvider({
12 | metadata: fs.readFileSync('./metadata_sp.xml')
13 | });
14 | router.get('/metadata', (req, res) => {
15 | res.header('Content-Type', 'text/xml').send(sp.getMetadata());
16 | });
17 | ```
18 |
19 | If you use our IdP solution, you can also release the Metadata same as above.
20 |
21 | ```javascript
22 | const idp = saml.IdentityProvider({
23 | metadata: fs.readFileSync('./metadata_idp.xml')
24 | });
25 | router.get('/metadata', (req, res) => {
26 | res.header('Content-Type', 'text/xml').send(idp.getMetadata());
27 | });
28 | ```
29 |
30 | **Export and distribute it privately**
31 |
32 | Some properties may not want their metadata to release publicly. If IdP or SP is configured explicitly, a helper method is provided to export the auto-generated metadata.
33 |
34 | ```javascript
35 | // Configure the entities without metadata
36 | const sp = saml.ServiceProvider(spSetting);
37 | const idp = saml.IdentityProvider(idpSetting);
38 | // Export the auto-generated Metadata to a specific file
39 | sp.exportMetadata('./distributed_sp_md.xml');
40 | idp.exportMetadata('./distributed_idp_md.xml');
41 | ```
42 |
43 |
44 |
--------------------------------------------------------------------------------
/docs/multi-entities.md:
--------------------------------------------------------------------------------
1 | # Multiple entities
2 |
3 | For those applications with many clients, each client may have its own Identity Provider. Developers just need to configure multiple IdPs. Different configuration of SP is required for different IdP, therefore multiple SPs are allowed.
4 |
5 | **Multiple IdPs - Single SP**
6 |
7 | ```javascript
8 | // define SP
9 | const sp = saml.ServiceProvider({
10 | metadata: fs.readFileSync('./metadata_sp.xml')
11 | });
12 | // define multiple IdPs
13 | const defaultIdP = saml.IdentityProvider({
14 | metadata: fs.readFileSync('./metadata_idp_default.xml')
15 | });
16 | const oneloginIdP = saml.IdentityProvider({
17 | metadata: fs.readFileSync('./metadata_onelogin.xml')
18 | });
19 | // URL routing for SP-initiated SSO
20 | router.get('/spinitsso-post/:idp', (req, res) => {
21 | let targetIdP = undefined;
22 | switch(req.params.idp) {
23 | case 'onelogin': {
24 | targetIdP = oneloginIdP;
25 | break;
26 | }
27 | default: {
28 | targetIdP = idp;
29 | break;
30 | }
31 | }
32 | return sp.createLoginRequest(targetIdP, 'post', (req, res) => res.render('actions', req));
33 | });
34 | ```
35 |
36 | Using the same SP configuration, it can apply to different IdPs. We've played a trick here, the initiated URL for SP-inititated SSO is controlled by a parameter. When user accesses `/spinitsso-post/onelogin`, the OneLogin IdP is used. When user accesses `/spinitsso-post/default`, the default IdP is then used for authentication.
37 |
38 | **Multiple IdPs - Mutiple SPs**
39 |
40 | Different IdPs may have different preference, so single SP configuration may not be suitable. For example, OneLogin IdP requires a request with signature but our default IdP does not. Here we come up with another solution which is very similar to the previous one.
41 |
42 | ```javascript
43 | // define a default SP
44 | const defaultSP = saml.ServiceProvider({
45 | metadata: fs.readFileSync('./metadata_sp.xml')
46 | });
47 | // define SP for OneLogin with different metadta
48 | const oneloginSP = saml.ServiceProvider({
49 | metadata: fs.readFileSync('./metadata_sp_for_oneLogin.xml')
50 | });
51 | // define a default IdP
52 | const defaultIdP = saml.IdentityProvider({
53 | metadata: fs.readFileSync('./metadata_idp_default.xml')
54 | });
55 | // define OneLogin IdP
56 | const oneloginIdP = saml.IdentityProvider({
57 | metadata: fs.readFileSync('./metadata_idp_onelogin.xml')
58 | });
59 | // URL routing for SP-initiated SSO
60 | router.get('/spinitsso-post/:idp', function(req, res) {
61 | let targetIdP = undefined;
62 | let sourceSP = undefined;
63 | switch(req.params.idp || '') {
64 | case 'onelogin': {
65 | targetIdP = oneloginIdP;
66 | sourceSP = oneloginSP;
67 | break;
68 | }
69 | default: {
70 | targetIdP = idp;
71 | sourceSP = defaultSP;
72 | break;
73 | }
74 | }
75 | return sourceSP.createLoginRequest(targetIdP, 'post', (req, res) => res.render('actions', request));
76 | });
77 | ```
78 |
--------------------------------------------------------------------------------
/docs/okta-inbound.md:
--------------------------------------------------------------------------------
1 | In progress ...
--------------------------------------------------------------------------------
/docs/okta.md:
--------------------------------------------------------------------------------
1 | ## Work with Okta (Credit to [@fas3r](https://github.com/fas3r))
2 |
3 | ?> In this chapter, we will make an sample application that implements SP-initiated SSO.
4 |
5 | ### Pre-requirement:
6 |
7 | samlify, express (or other), body-parser.
8 |
9 | ### Step-by-step tutorial:
10 |
11 | 1. Create a new web app with SAML2.0 in okta :
12 |
13 | 
14 |
15 |
16 | 2. Configure SAML_integration:
17 |
18 | - General setting:
19 |
20 | 
21 |
22 | - Configure SAML :
23 |
24 | !> Never upload your private key online
25 |
26 | 
27 |
28 | * "Single Sign on URL": the uri where to "POST" the auth request
29 | * "Audience URI": The uri where the metadata are accessible. This is not mandatory if you don't want to share the metadata file. See [here](https://samlify.js.org/#/metadata-distribution)
30 | * "Assertion Encryption": We set to "Encrypted". Indicates whether the SAML assertion is encrypted.
31 | * "Encryption Certificate" : Upload the path to the certificate `*.cer` to use to encrypt the assertion.
32 |
33 | 
34 |
35 | * and the attributes statement/groups to return in the assertion section
36 |
37 | - Feedback:
38 |
39 | 
40 |
41 | * Choose your desired one.
42 |
43 | 3. Next you will see in the "Sign On" tab the following :
44 |
45 | 
46 |
47 | - Red Arrow: The SAML 2.0 Certificate
48 | - Green Arrow: Get the idp XML file of your application with all the information
49 | - Blue Arrow: Direct link to the metadata file of the application.
50 | - In the "General" tab you should see something like :
51 |
52 | 
53 |
54 |
55 | 4. Example code snippet
56 |
57 | ```js
58 | const express = require('express');
59 | const fs = require('fs');
60 | const saml = require('samlify');
61 | const axios = require('axios');
62 | const bodyParser = require("body-parser");
63 | const app = express();
64 | app.use(bodyParser.urlencoded({ extended: true }));
65 | app.use(bodyParser.json());
66 | app.use(serveStatic(path.resolve(__dirname, 'public')));
67 |
68 | // URL to the okta metadata
69 | const uri_okta_metadata = 'https://dev-xxxxxxx.oktapreview.com/app/APP_ID/sso/saml/metadata';
70 |
71 | axios.get(uri_okta_metadata)
72 | .then(response => {
73 |
74 | const idp = saml.IdentityProvider({
75 | metadata: response.data,
76 | isAssertionEncrypted: true,
77 | messageSigningOrder: 'encrypt-then-sign',
78 | wantLogoutRequestSigned: true
79 | });
80 |
81 | const sp = saml.ServiceProvider({
82 | entityID: 'http://localhost:8080/sp/metadata?encrypted=true',
83 | authnRequestsSigned: false,
84 | wantAssertionsSigned: true,
85 | wantMessageSigned: true,
86 | wantLogoutResponseSigned: true,
87 | wantLogoutRequestSigned: true,
88 | // the private key (.pem) use to sign the assertion;
89 | privateKey: fs.readFileSync(__dirname + '/ssl/sign/privkey.pem'),
90 | // the private key pass;
91 | privateKeyPass: 'VHOSp5RUiBcrsjrcAuXFwU1NKCkGA8px',
92 | // the private key (.pem) use to encrypt the assertion;
93 | encPrivateKey: fs.readFileSync(__dirname + '/ssl/encrypt/privkey.pem'),
94 | isAssertionEncrypted: true,
95 | assertionConsumerService: [{
96 | Binding: saml.Constants.namespace.post,
97 | Location: 'http://localhost:8080/sp/acs?encrypted=true',
98 | }]
99 | });
100 |
101 | app.post('/sp/acs', async (req, res) => {
102 | try {
103 | const { extract } = await sp.parseLoginResponse(idp, 'post', req);
104 | console.log(extract.attributes);
105 | /**
106 | *
107 | * Implement your logic here.
108 | * extract.attributes, should contains : firstName, lastName, email, uid, groups
109 | *
110 | **/
111 | } catch (e) {
112 | console.error('[FATAL] when parsing login response sent from okta', e);
113 | return res.redirect('/');
114 | }
115 | });
116 |
117 | app.get('/login', async (req, res) => {
118 | const { id, context } = await sp.createLoginRequest(idp, 'redirect');
119 | console.log(context);
120 | return res.redirect(context);
121 | });
122 |
123 | app.get('/sp/metadata', (req, res) => {
124 | console.log("here");
125 | res.header('Content-Type', 'text/xml').send(idp.getMetadata());
126 | });
127 |
128 | });
129 | ```
--------------------------------------------------------------------------------
/docs/prerequistite.md:
--------------------------------------------------------------------------------
1 | # Knowledge
2 |
3 | There is no prerequisite for using this module. You can skip this chapter in case you are familiar with Single Sign On and have worked before. Otherwise, it's recommended to go through this chapter once and get some insights.
4 |
5 | ## What is Single Sign On (SSO) ?
6 |
7 | SSO is an access control strategy for multiple applications. Just imagine that you have to log-in different internal systems in a company every morning. It's really annoying when you type your account name and password. Also you imagine if you were the guy in IT department. Every time a new employee is hired, you have to create an account information for each internal systems. It turns out that really difficult to manage the credentials.
8 |
9 | By using SSO, user can memorize one set of credential to log-in an **Identity Provider** for authentication. User can access those systems because of the trust-worthy relationship among IdP and those systems.
10 |
--------------------------------------------------------------------------------
/docs/saml-request.md:
--------------------------------------------------------------------------------
1 | # SAML Request
2 |
3 | When we apply SP-initiated SSO, our Service Provider have to send a SAML Request to Identity Provider.
4 |
5 | SAML Request is in XML format, asking if identity provider can authenticate this user. The following is a sample request without signature.
6 |
7 | ```xml
8 |
17 | https://sp.example.org/metadata
18 |
19 |
20 | urn:oasis:names:tc:SAML:2.0:ac:classes:Password
21 |
22 |
23 | ```
24 |
25 | Different bindings can be used to send this request, we support Redirect-Binding and Post-Binding.
26 |
27 | **Redirect-Binding**
28 |
29 | It means that the XML is embedded as an URL parameter and redirect to the SSO endpoint of IdP. Because of different length limitation in different browsers, it's required to deflate Request.
30 |
31 | ```javascript
32 | const saml = require('samlify');
33 | const sp = saml.ServiceProvider({
34 | metadata: fs.readFileSync('./metadata_sp.xml')
35 | });
36 | const idp = saml.IdentityProvider({
37 | metadata: fs.readFileSync('./metadata_idp.xml')
38 | });
39 | ```
40 |
41 | The SSO endpoint of IdP is specified in their metadata. For example:
42 |
43 | ```xml
44 |
45 |
46 | ```
47 |
48 | There may be more than one SSO endpoint, to support different bindings. By using our entity level API, you can just write your initiation point in any route you want as follow:
49 |
50 | ```javascript
51 | router.get('/spinitsso-redirect', (req, res) => {
52 | const { id, context } = sp.createLoginRequest(idp, 'redirect');
53 | return res.redirect(context);
54 | });
55 | ```
56 | By applying the preference of SP and IdP, `sp.createLoginRequest`returns an URL which is in following general format:
57 |
58 | https://idp.example.org/sso/SingleSignOnService?SAMLRequest=www&SigAlg=xxx&RelayState=yyy&Signature=zzz
59 |
60 | The parameters **SigAlg** and **Signature** is optional in case IdP requests your SAML Request should be signed. **relayState** is also optional if the application needs a deep link to access.
61 |
62 | All the corresponding values are URL-encoded. **Signature** is already Base64-encoded and the deflated **SAMLRequest** should be Base64-encoded.
63 |
64 | **Post-Binding**
65 |
66 | The Request XML is sent via a form post instead of embedding in URL parameters. By using the same method as in Redirect-Binding:
67 |
68 | ```javascript
69 | router.get('/spinitsso-redirect', (req, res) => {
70 | res.render('actions', sp.createLoginRequest(idp, 'post'));
71 | });
72 | ```
73 |
74 | You can simply change the second argument from 'redirect' to 'post'. This time the callback function returns an object instead of a string. It is then fed to a generic form post template as follow:
75 |
76 | ```html
77 |
83 |
89 | ```
90 |
91 | Handlebar view engine is used in this example, you may choose your own and configure in your `app.js`.
92 |
93 | ```javascript
94 | app.engine('handlebars', exphbs({defaultLayout: 'main'}));
95 | app.set('view engine', 'handlebars');
96 | ```
97 |
98 | After those values are filled into the tags, the form will be automatically submit.
99 |
100 | ?> **What's the next ?**
101 | Identity Provider parses SP's request, then a SAML Response is sent back to SP. The response includes the authentication result. SP can then take action to create session for authenticated user if the result is successful.
102 |
--------------------------------------------------------------------------------
/docs/signed-saml-request.md:
--------------------------------------------------------------------------------
1 | # Signed SAML Request
2 |
3 | We follow the preference in metadata files. If it doesn't state in the metadata, default is not to sign the SAML Request.
4 |
5 | In IdP's metadata, there is an attribute called `WantAuthnRequestsSigned`. Default value is `false`.
6 |
7 | ```xml
8 |
12 | ```
13 | In SP's metadata, there is an attribute called `AuthnRequestsSigned`. Default value is `false`.
14 |
15 | ```xml
16 |
19 | ```
20 |
21 | and include the X.509 certificate in SP's metadata.
22 |
23 | ```xml
24 |
28 |
29 |
30 |
31 |
32 | MIIDozCCAougAwIBAgIJAKN...
33 |
34 |
35 |
36 | ...
37 | ```
38 |
39 | If both two attributes are not matched, an error will be thrown out during run-time. Developers can easily locate the error.
40 |
41 | If IdP doesn't provide the metadata for you, 1) you may ask them 2) import an object setting, see advanced topics [here]().
42 |
43 | Metadata stores the preferences only. To sign a XML document, we still need our **private key** and **signature algorithm**. We can configure our SP here:
44 |
45 | ```javascript
46 | const saml = require('samlify');
47 | // Define the setting
48 | const setting = {
49 | privateKey: fs.readFileSync('./key/sp_key.pem'),
50 | privateKeyPass: 'KCkGOSjrcAuXFwU1pVH5RUiBcrsNA8px',
51 | requestSignatureAlgorithm: 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha512',
52 | metadata: fs.readFileSync('./metadata_sp.xml')
53 | };
54 | // Construct our service provider
55 | const sp = saml.ServiceProvider(setting);
56 | ```
57 |
58 | The property `privateKeyPass` is optional in case you have set a passphrase when the private key is created. Also the default value of `requestSignatureAlgorithm` is RSA-SHA1.
59 |
60 | All support signature algorithms:
61 | ```javascript
62 | 'http://www.w3.org/2000/09/xmldsig#rsa-sha1',
63 | 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256',
64 | 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha512'
65 | ```
66 | Once you have configured the SP correctly, all you need to send a signed SAML Request is to do as follow:
67 |
68 | ```javascript
69 | router.get('/spinitsso-redirect', (req, res) => {
70 | const { id, context } = sp.createLoginRequest(idp, 'redirect');
71 | return res.redirect(context);
72 | });
73 | ```
74 |
75 | Yes, it's the same method we used to send a SAML Request without signature.
76 |
77 | **How to generate a signature**
78 |
79 | For those who are not interested in how the signature generates, you can skip this section. The signature is generated by two different formats.
80 |
81 | In **Redirect-Binding**, the URL-encoded message should be assigned as follow:
82 |
83 | + Octet string is a concatenation of SAMLRequest, RelayState and SigAlg.`SAMLRequest=xxx&RelayState=yyy&SigAlg=zzz`
84 | + Signature MUST be encoded by base64 encoding.
85 | + RelayState is an optional parameter. If there is no RelayState value, this parameter should be ignored from computing signature. e.g. `SAMLRequest=xxx&SigAlg=zzz`
86 |
87 |
88 | In **Post-Binding**, XML digital signature is used and embedded inside the Request XML.
89 |
90 | ```xml
91 |
101 |
102 | https://sp.example.org/metadata
103 |
104 |
105 | urn:oasis:names:tc:SAML:2.0:ac:classes:Password
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 | tQDisBXKTQ+9OXJO5r7KuJga+KI=
118 |
119 |
120 | oxRkvau7UvYgFEZ7YNAUNf3067V7Tn5C9XSIiet1aZw2FYevNW5bUy/0mxp3aj6AvfFjnmpzAb88BjdwAz2BErDTomRcuZB7Lb0fYTf31N2oZOX0MiPiQOH54I63qJW4Xo3VqdF7GBuFZZHyllfSBv7gfCtjJDwFSCzWK70B9r3cFMRJZLhCJ9oPen+4U9scSYO6g+szBZLl6AiJ06PHc8jzEKGwfQrcZk8kDKUlvNfJMULyq8dpx2VvUAx4p5ewfMOwB9W3Hl3PPa0dO77zZif3CglpcN06f+m6UYG/wnoTQEyKW9hOe+2vGM80W77eWu0dmiaPuqT1ok8LXPuq1A==
121 |
122 |
123 | ```
124 |
--------------------------------------------------------------------------------
/docs/signed-saml-response.md:
--------------------------------------------------------------------------------
1 | # Signed SAML Response
2 |
3 | The configuration for the use case receiving signed SAML Response is very simple. First, developers have to make sure that Identity Provider would sign the response. Second, define the property `WantAssertionsSigned` in SP's metadata inside the `SPSSODescriptor` tag.
4 |
5 | ```xml
6 |
10 | ```
11 | Currently, we support the following algorithms:
12 |
13 | **Signature algorithms**
14 | * http://www.w3.org/2000/09/xmldsig#rsa-sha1 (Default)
15 | * http://www.w3.org/2001/04/xmldsig-more#rsa-sha256
16 | * http://www.w3.org/2001/04/xmldsig-more#rsa-sha512
17 | * http://www.w3.org/2000/09/xmldsig#hmac-sha1
18 |
19 | **Hashing Algorithms**
20 | * http://www.w3.org/2000/09/xmldsig#sha1 (Default)
21 | * http://www.w3.org/2001/04/xmlenc#sha256
22 | * http://www.w3.org/2001/04/xmlenc#sha512
23 |
24 | **Canonicalization and Transformation Algorithms**
25 | * http://www.w3.org/2001/10/xml-exc-c14n#
26 | * http://www.w3.org/2001/10/xml-exc-c14n#WithComments
27 | * http://www.w3.org/2000/09/xmldsig#enveloped-signature
28 |
29 | Credits to [yaronn/xml-crypto](https://github.com/yaronn/xml-crypto).
30 |
31 | !> SAML Response must be signed if you use our API for creating identity providers.
32 |
33 | We recommend user to accept signed response in their service provider. Therefore, our identity provider is RECOMMENDED to sign the response in order to maintain the confidentiality and message integrity [Section 4.1.3.5](http://docs.oasis-open.org/security/saml/v2.0/saml-profiles-2.0-os.pdf).
34 |
35 | There are different examples of signing scheme supported in samlify.
36 |
37 | + **Unsigned message, Signed assertion (wo/ encryption)**
38 |
39 | To guarantee the setting in between idp-sp pair is synchronized, determination of assertion signature depends on the sp setting. Set `WantAssertionsSigned` to true in corresponding sp's metadata or `wantAssertionsSigned` in constructor if metadata is not set.
40 |
41 | ```javascript
42 | const sp = ServiceProvider({
43 | // ...
44 | metadata: readFileSync('./sp-metadata.xml'),
45 | // must have if assertion signature fails validation
46 | // transformationAlgorithms: [
47 | // 'http://www.w3.org/2000/09/xmldsig#enveloped-signature',
48 | // 'http://www.w3.org/2001/10/xml-exc-c14n#',
49 | // ],
50 | });
51 |
52 | const idp = IdentityProvider({
53 | // ...
54 | metadata: readFileSync('./idp-metatadata.xml'),
55 | privateKey: readFileSync('./mysecret.pem'),
56 | privateKeyPass: 'zzz', // if has
57 | // must have if metadata is not provided
58 | // signingCert: readFileSync('./signing.cer')
59 | });
60 | ```
61 |
62 | The certificate of identity provider will be included in its metadata, or specify in constructor as `signingCert`.
63 |
64 | + **Unsigned message, Signed & Encrypted assertion**
65 |
66 | SP's preparation is same as the first case. For encrpytion part, identity provider encrypts the assertion with sp's certificate (public key) and sp can decrypt the response using sp's private key.
67 |
68 | IdP controls whether the response is encrypted or not.
69 |
70 | ```javascript
71 | // create in sp side, private key for decryption is owned by sp only
72 |
73 | const sp = ServiceProvider({
74 | // ...
75 | metadata: readFileSync('./sp-metadata.xml'),
76 | encPrivateKey: fs.readFileSync('./encryptKey.pem'),
77 | encPrivateKeyPass: 'yyy',
78 | // must have if metadata is not provided
79 | // signingCert: readFileSync('./signing.cer')
80 | // encryptCert: readFileSync('./encrypt.cer')
81 | });
82 | ```
83 |
84 | ```javascript
85 | // create in idp side
86 |
87 | const sp = ServiceProvider({
88 | // ...
89 | metadata: readFileSync('./sp-metadata.xml'),
90 | });
91 |
92 | const idp = IdentityProvider({
93 | // ...
94 | isAssertionEncrypted: true,
95 | metadata: readFileSync('./idp-metatadata.xml'),
96 | privateKey: readFileSync('./mysecret.pem'),
97 | privateKeyPass: 'xxx', // if has
98 | // must have if metadata is not provided
99 | // signingCert: readFileSync('./signing.cer')
100 | });
101 | ```
102 |
103 | + **Signed message, Unsigned assertion (w/wo encryption)**
104 |
105 | There are two new properties added into the constructor method for idp starting from v2. `wantMessageSigned` and `signatureConfig` are used to enrich our signature scheme whereas `signatureConfig` is same as the configuration in [xml-crypto](https://
106 | github.com/yaronn/xml-crypto#examples).
107 |
108 | ```javascript
109 | const idp = IdentityProvider({
110 | // ...
111 | wantMessageSigned: true,
112 | signatureConfig: {
113 | prefix: 'ds',
114 | location: {
115 | reference: '/samlp:Response/saml:Issuer',
116 | action: 'after'
117 | }
118 | }
119 | });
120 | ```
121 |
122 | + **Signed message, Signed assertion (wo/ encryption)**
123 |
124 | See above signed message and signed assertion setting.
125 |
126 | + **Signed message, Signed & Encrypted assertion**
127 |
128 | The most complex case, see above all.
--------------------------------------------------------------------------------
/docs/sp-configuration.md:
--------------------------------------------------------------------------------
1 | # SP Configuration
2 |
3 | #### Required Parameters
4 |
5 | ?> You can either choose to import from metadata plus optional paramters, or defined properties plus optional parameters.
6 |
7 | - **metadata: String**
8 | SP issued metadata to declare the structure and scope of the entity, as a common contract on how sso/slo should be proceeded.
9 |
10 | ```js
11 | const sp = new ServiceProvider({
12 | // required
13 | metadata: readFileSync('./test/misc/spmeta.xml'),
14 | // optional
15 | privateKey: readFileSync('./test/key/sp/privkey.pem'),
16 | privateKeyPass: 'q9ALNhGT5EhfcRmp8Pg7e9zTQeP2x1bW',
17 | encPrivateKey: readFileSync('./test/key/sp/encryptKey.pem'),
18 | encPrivateKeyPass: 'g7hGcRmp8PxT5QeP2q9Ehf1bWe9zTALN'
19 | });
20 | ```
21 |
22 | OR
23 |
24 | - **entityID: String** Entity identifier. It is used to identify your entity, and match the equivalence in each saml request/response.
25 |
26 | - **authnRequestsSigned: Boolean**
27 | _Optional_: Declare if sp signs the authn request, reflects to the `AuthnRequestsSigned` in sp metadata, default to `false`.
28 |
29 | - **wantAssertionsSigned: Boolean**
30 | _Optional_: Declare if sp wants the signed assertion, reflects to the `WantAssertionsSigned` in sp metadata, default to `false`.
31 |
32 | - **wantMessageSigned: Boolean**
33 | _Optional_: Declare if sp wants the signed message, default to `false`.
34 |
35 | - **signingCert: String**
36 | _Optional_: Specify the certificate used for signing purpose if you construct the sp without a metadata.
37 |
38 | - **encryptCert: String**
39 | _Optional_: Specify the certificate used for encryption purpose if you construct the sp without a metadata.
40 |
41 | - **elementsOrder: String[]**
42 | _Optional_: Define the DOM structure of xml document, default to `['KeyDescriptor', 'NameIDFormat', 'SingleLogoutService', 'AssertionConsumerService']`. (See more [#89](https://github.com/tngan/samlify/issues/89))
43 |
44 | - **nameIDFormat: NameIDFormat[]**
45 | _Optional_: Declare the name id format that would respond if you construct the sp without a metadata. The request will always pick the first one if multiple formats are specified.
46 |
47 | - **singleLogoutService: Service[]**
48 | _Optional_: Declare the single logout service if you construct the sp without a metadata.
49 |
50 | - **assertionConsumerService: Service[]**
51 | _Optional_: Declare the asssertion consumer service where the saml response redirects to if you construct the sp without a metadata.
52 |
53 | - **signatureConfig: SignatureConfig**
54 | _Optional_: Configure how the signature is being constructed. (See [more](/signed-saml-response))
55 |
56 | ```js
57 | const sp = new ServiceProvider({
58 | // required
59 | entityID: 'http://hello-saml-sp.com/metadata',
60 | // optional parameters listed below
61 | });
62 | ```
63 |
64 | #### Optional Parameters
65 |
66 | - **loginRequestTemplate: {context: String, attributes: Attributes}**
67 | Customize the login request template, and user can reuse it in the callback function to do runtime interpolation. (See [more](/template))
68 |
69 | - **wantLogoutRequestSigned: Boolean**
70 | Declare if sp guarantees the logout request from idp is signed.
71 |
72 | - **relayState: String**
73 | Specify the relayState of the request.
74 |
75 | !> It will be deprecated soon and put into request level instead g of entity level.
76 |
77 | - **generateID: (): String**
78 | A function to generate the document identifier in root node. Default to `_${UUID_V4}`.
79 |
80 | - **clockDrifts: [Number, Number]**
81 | A time range allowing for drifting the range that specified in the SAML document. The first one is for the `notBefore` time and the second one is for `notOnOrAfter`. Default value of both drift value is `0`. The unit is in `ms`.
82 |
83 | For example, if you set `[-5000, 3000]`. The value can be either positive or negative in order to take care of the flexibility.
84 |
85 | ```console
86 | # tolerated timeline
87 | notBefore - 5s >>>>>>> notBefore >>>>>>> notAfter ---- notAfter + 3s
88 |
89 | # new valid time
90 | notBefore - 5s >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> notAfter + 3s
91 | ```
92 |
93 | Another example, if you don't set, the default drift tolerance is `[0, 0]`. The valid range is trivial.
94 |
95 | ```console
96 | # valid time
97 | notBefore >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> notAfter
98 | ```
99 |
100 | ?> The flow will skip the validation when there is no `notBefore` and `notOnOrAfter` at the same time.
101 |
102 | ?> See [SAML Core P.19](https://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf) for more detail.
103 |
--------------------------------------------------------------------------------
/docs/sp.md:
--------------------------------------------------------------------------------
1 | # Service Provider
2 |
3 | Let's get started to get the entry point.
4 |
5 | ```javascript
6 | const saml = require('samlify');
7 | ```
8 |
9 | You should have prepared the metadata of service provider.
10 |
11 | ```xml
12 |
17 |
18 |
19 |
20 |
21 | MIID...
22 |
23 |
24 |
25 | urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
26 |
27 |
28 |
29 | ```
30 |
31 | Import the above metadata and get the service provider ready. Previously, we only allow user to enter path to file and the module will read for users. Starting from v2, we have relaxed the configuration to accept string, it allows user importing their metadata, key and certificate files from different sources. For examples, read from database, file systems, online resources (public url for metadata) and even in-memory storage.
32 |
33 | !> **API is changed since v2**
34 |
35 | ```javascript
36 | // after v2
37 | const sp = saml.ServiceProvider({
38 | metadata: fs.readFileSync('./metadata/sp.xml')
39 | });
40 | // before v2 (deprecated)
41 | // const sp = saml.ServiceProvider('./metadata/sp.xml');
42 | ```
43 |
--------------------------------------------------------------------------------
/docs/template.md:
--------------------------------------------------------------------------------
1 | # Attributes in response
2 |
3 | ?> **Starting from v2, we provide a shortcut for user to construct the attributes section efficiently instead of hard code the attribute information in template string.**
4 |
5 | ```javascript
6 | const idp = require('samlify').IdentityProvider({
7 | // ...
8 | loginResponseTemplate: {
9 | context: ',
10 | attributes: [
11 | { name: "mail", valueTag: "user.email", nameFormat: "urn:oasis:names:tc:SAML:2.0:attrname-format:basic", valueXsiType: "xs:string" },
12 | { name: "name", valueTag: "user.name", nameFormat: "urn:oasis:names:tc:SAML:2.0:attrname-format:basic", valueXsiType: "xs:string" }
13 | ]
14 | }
15 | });
16 | ```
17 |
18 | then the attributes part will be included in the template string:
19 |
20 | ```xml
21 |
22 |
25 |
26 | {attrUserEmail}
27 |
28 |
29 |
32 |
33 | {attrUserName}
34 |
35 |
36 |
37 | ```
38 |
39 | the tag name is auto-generated with prefix `attr` and the suffix is formatted as camel case of `valueTag` specified in the config.
40 |
41 | # Custom templates
42 |
43 | Developer can design their own request and response template for log-in and log-out respectively. There are optional parameters in setting object.
44 |
45 | ```javascript
46 | const saml = require('samlify');
47 |
48 | // load the template every time before each request/response is sent
49 | const sp = saml.ServiceProvider({
50 | //...
51 | loginRequestTemplate: {
52 | context: readFileSync('./loginResponseTemplate.xml'),
53 | }
54 | });
55 | ```
56 |
57 | In SP configuration, `loginRequestTemplate` is the template of SAML Request, it can be either file name or XML string. This is the default template we've used in our module.
58 |
59 | ```xml
60 |
69 |
70 | {Issuer}
71 |
74 |
75 |
76 | ```
77 |
78 | When you apply your own template, remember to do custom tag replacement when you send out the request. `replaceTagFromTemplate` is just the name here to illustrate but it's not fixed.
79 |
80 | ```javascript
81 | router.get('/spinitsso-redirect', (req, res) => {
82 |
83 | const { id, context } = sp.createLoginRequest(idp, 'redirect', loginRequestTemplate => {
84 | // Here is the callback function for custom template
85 | // the input parameter is the value of loginRequestTemplate
86 | // The following is the input parameter of rcallback in different actions
87 | // sp.createLoginRequest -> loginRequestTemplate
88 | // sp.createLogoutResponse -> logoutResponseTemplate
89 | // idp.createLoginResponse -> loginResponseTemplate
90 | // idp.createLogoutRequest -> logoutRequestTemplate
91 | // replaceTagFromTemplate is a function to do dynamically substitution of tags
92 | return replaceTagFromTemplate(loginRequestTemplate);
93 | });
94 |
95 | return res.redirect(context);
96 |
97 | });
98 | ```
99 |
100 | !> `replaceTagFromTemplate` must return the object containing `id` (response id) and `context` (string)
101 |
--------------------------------------------------------------------------------
/index.ts:
--------------------------------------------------------------------------------
1 | // version <= 1.25
2 | import IdentityProvider, { IdentityProvider as IdentityProviderInstance } from './src/entity-idp';
3 | import ServiceProvider, { ServiceProvider as ServiceProviderInstance } from './src/entity-sp';
4 |
5 | export { default as IdPMetadata } from './src/metadata-idp';
6 | export { default as SPMetadata } from './src/metadata-sp';
7 | export { default as Utility } from './src/utility';
8 | export { default as SamlLib } from './src/libsaml';
9 | // roadmap
10 | // new name convention in version >= 3.0
11 | import * as Constants from './src/urn';
12 | import * as Extractor from './src/extractor';
13 |
14 | // exposed methods for customising samlify
15 | import { setSchemaValidator } from './src/api';
16 |
17 | export {
18 | Constants,
19 | Extractor,
20 | // temp: resolve the conflict after version >= 3.0
21 | IdentityProvider,
22 | IdentityProviderInstance,
23 | ServiceProvider,
24 | ServiceProviderInstance,
25 | // set context
26 | setSchemaValidator
27 | };
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "samlify",
3 | "version": "2.7.4",
4 | "description": "High-level API for Single Sign On (SAML 2.0)",
5 | "main": "build/index.js",
6 | "keywords": [
7 | "nodejs",
8 | "saml2",
9 | "sso",
10 | "slo",
11 | "metadata"
12 | ],
13 | "typings": "types/index.d.ts",
14 | "scripts": {
15 | "build": "yarn audit;make rebuild",
16 | "docs": "docsify serve -o docs",
17 | "lint": "tslint -p .",
18 | "lint:fix": "tslint -p . --fix",
19 | "pretest": "make pretest",
20 | "test": "NODE_ENV=test nyc ava",
21 | "coverage": "nyc report --reporter=text-lcov | coveralls",
22 | "hooks:postinstall": "ln -sf $PWD/.pre-commit.sh $PWD/.git/hooks/pre-commit"
23 | },
24 | "contributors": [
25 | "Tony Ngan "
26 | ],
27 | "author": "tngan",
28 | "repository": {
29 | "url": "https://github.com/tngan/samlify",
30 | "type": "git"
31 | },
32 | "license": "MIT",
33 | "dependencies": {
34 | "camelcase": "^5.3.1",
35 | "node-forge": "^0.8.5",
36 | "node-rsa": "^1.0.5",
37 | "pako": "^1.0.10",
38 | "uuid": "^3.3.2",
39 | "xml": "^1.0.1",
40 | "xml-crypto": "^1.5.3",
41 | "xml-encryption": "^1.1.1",
42 | "xmldom": "^0.1.27",
43 | "xpath": "^0.0.27"
44 | },
45 | "devDependencies": {
46 | "@ava/typescript": "^1.1.1",
47 | "@types/node": "^11.11.3",
48 | "@types/node-forge": "^0.7.4",
49 | "@types/pako": "^1.0.1",
50 | "@types/uuid": "3.0.0",
51 | "@types/xmldom": "^0.1.28",
52 | "ava": "^3.8.2",
53 | "coveralls": "^3.1.0",
54 | "nyc": "^15.0.1",
55 | "timekeeper": "^2.2.0",
56 | "ts-node": "^8.3.0",
57 | "tslint": "^6.1.2",
58 | "typescript": "^3.8.3"
59 | },
60 | "ava": {
61 | "extensions": [
62 | "ts"
63 | ],
64 | "require": [
65 | "ts-node/register"
66 | ],
67 | "files": [
68 | "!**/*.d.ts"
69 | ]
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/api.ts:
--------------------------------------------------------------------------------
1 | // global module configuration
2 | interface Context extends ValidatorContext {}
3 |
4 | interface ValidatorContext {
5 | validate?: (xml: string) => Promise;
6 | }
7 |
8 | const context: Context = {
9 | validate: undefined
10 | };
11 |
12 | export function getContext() {
13 | return context;
14 | }
15 |
16 | export function setSchemaValidator(params: ValidatorContext) {
17 |
18 | if (typeof params.validate !== 'function') {
19 | throw new Error('validate must be a callback function having one arguemnt as xml input');
20 | }
21 |
22 | // assign the validate function to the context
23 | context.validate = params.validate;
24 |
25 | }
--------------------------------------------------------------------------------
/src/entity-idp.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @file entity-idp.ts
3 | * @author tngan
4 | * @desc Declares the actions taken by identity provider
5 | */
6 | import Entity, { ESamlHttpRequest } from './entity';
7 | import {
8 | ServiceProviderConstructor as ServiceProvider,
9 | ServiceProviderMetadata,
10 | IdentityProviderMetadata,
11 | IdentityProviderSettings,
12 | } from './types';
13 | import libsaml from './libsaml';
14 | import { namespace } from './urn';
15 | import postBinding from './binding-post';
16 | import { flow, FlowResult } from './flow';
17 | import { isString } from './utility';
18 | import { BindingContext } from './entity';
19 |
20 | /**
21 | * Identity prvider can be configured using either metadata importing or idpSetting
22 | */
23 | export default function(props: IdentityProviderSettings) {
24 | return new IdentityProvider(props);
25 | }
26 |
27 | /**
28 | * Identity prvider can be configured using either metadata importing or idpSetting
29 | */
30 | export class IdentityProvider extends Entity {
31 |
32 | entityMeta: IdentityProviderMetadata;
33 |
34 | constructor(idpSetting: IdentityProviderSettings) {
35 | const defaultIdpEntitySetting = {
36 | wantAuthnRequestsSigned: false,
37 | tagPrefix: {
38 | encryptedAssertion: 'saml',
39 | },
40 | };
41 | const entitySetting = Object.assign(defaultIdpEntitySetting, idpSetting);
42 | // build attribute part
43 | if (idpSetting.loginResponseTemplate) {
44 | if (isString(idpSetting.loginResponseTemplate.context) && Array.isArray(idpSetting.loginResponseTemplate.attributes)) {
45 | const replacement = {
46 | AttributeStatement: libsaml.attributeStatementBuilder(idpSetting.loginResponseTemplate.attributes),
47 | };
48 | entitySetting.loginResponseTemplate = {
49 | ...entitySetting.loginResponseTemplate,
50 | context: libsaml.replaceTagsByValue(entitySetting.loginResponseTemplate!.context, replacement),
51 | };
52 | } else {
53 | console.warn('Invalid login response template');
54 | }
55 | }
56 | super(entitySetting, 'idp');
57 | }
58 |
59 | /**
60 | * @desc Generates the login response for developers to design their own method
61 | * @param sp object of service provider
62 | * @param requestInfo corresponding request, used to obtain the id
63 | * @param binding protocol binding
64 | * @param user current logged user (e.g. req.user)
65 | * @param customTagReplacement used when developers have their own login response template
66 | * @param encryptThenSign whether or not to encrypt then sign first (if signing)
67 | */
68 | public async createLoginResponse(
69 | sp: ServiceProvider,
70 | requestInfo: { [key: string]: any },
71 | binding: string,
72 | user: { [key: string]: any },
73 | customTagReplacement?: (template: string) => BindingContext,
74 | encryptThenSign?: boolean,
75 | ) {
76 | const protocol = namespace.binding[binding];
77 | // can only support post binding for login response
78 | if (protocol === namespace.binding.post) {
79 | const context = await postBinding.base64LoginResponse(requestInfo, {
80 | idp: this,
81 | sp,
82 | }, user, customTagReplacement, encryptThenSign);
83 | return {
84 | ...context,
85 | entityEndpoint: (sp.entityMeta as ServiceProviderMetadata).getAssertionConsumerService(binding),
86 | type: 'SAMLResponse'
87 | };
88 | }
89 | throw new Error('ERR_CREATE_RESPONSE_UNDEFINED_BINDING');
90 | }
91 |
92 | /**
93 | * Validation of the parsed URL parameters
94 | * @param sp ServiceProvider instance
95 | * @param binding Protocol binding
96 | * @param req RequesmessageSigningOrderst
97 | */
98 | parseLoginRequest(sp: ServiceProvider, binding: string, req: ESamlHttpRequest) {
99 | const self = this;
100 | return flow({
101 | from: sp,
102 | self: self,
103 | checkSignature: self.entityMeta.isWantAuthnRequestsSigned(),
104 | parserType: 'SAMLRequest',
105 | type: 'login',
106 | binding: binding,
107 | request: req
108 | });
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/src/entity-sp.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @file entity-sp.ts
3 | * @author tngan
4 | * @desc Declares the actions taken by service provider
5 | */
6 | import Entity, {
7 | BindingContext,
8 | PostBindingContext,
9 | ESamlHttpRequest,
10 | } from './entity';
11 | import {
12 | IdentityProviderConstructor as IdentityProvider,
13 | ServiceProviderMetadata,
14 | ServiceProviderSettings,
15 | } from './types';
16 | import { namespace } from './urn';
17 | import redirectBinding from './binding-redirect';
18 | import postBinding from './binding-post';
19 | import { flow, FlowResult } from './flow';
20 |
21 | /*
22 | * @desc interface function
23 | */
24 | export default function(props: ServiceProviderSettings) {
25 | return new ServiceProvider(props);
26 | }
27 |
28 | /**
29 | * @desc Service provider can be configured using either metadata importing or spSetting
30 | * @param {object} spSettingimport { FlowResult } from '../types/src/flow.d';
31 |
32 | */
33 | export class ServiceProvider extends Entity {
34 | entityMeta: ServiceProviderMetadata;
35 |
36 | /**
37 | * @desc Inherited from Entity
38 | * @param {object} spSetting setting of service provider
39 | */
40 | constructor(spSetting: ServiceProviderSettings) {
41 | const entitySetting = Object.assign({
42 | authnRequestsSigned: false,
43 | wantAssertionsSigned: false,
44 | wantMessageSigned: false,
45 | }, spSetting);
46 | super(entitySetting, 'sp');
47 | }
48 |
49 | /**
50 | * @desc Generates the login request for developers to design their own method
51 | * @param {IdentityProvider} idp object of identity provider
52 | * @param {string} binding protocol binding
53 | * @param {function} customTagReplacement used when developers have their own login response template
54 | */
55 | public createLoginRequest(
56 | idp: IdentityProvider,
57 | binding = 'redirect',
58 | customTagReplacement?: (template: string) => BindingContext,
59 | ): BindingContext | PostBindingContext {
60 | const nsBinding = namespace.binding;
61 | const protocol = nsBinding[binding];
62 | if (this.entityMeta.isAuthnRequestSigned() !== idp.entityMeta.isWantAuthnRequestsSigned()) {
63 | throw new Error('ERR_METADATA_CONFLICT_REQUEST_SIGNED_FLAG');
64 | }
65 |
66 | if (protocol === nsBinding.redirect) {
67 | return redirectBinding.loginRequestRedirectURL({ idp, sp: this }, customTagReplacement);
68 | }
69 |
70 | if (protocol === nsBinding.post) {
71 | const context = postBinding.base64LoginRequest("/*[local-name(.)='AuthnRequest']", { idp, sp: this }, customTagReplacement);
72 | return {
73 | ...context,
74 | relayState: this.entitySetting.relayState,
75 | entityEndpoint: idp.entityMeta.getSingleSignOnService(binding) as string,
76 | type: 'SAMLRequest',
77 | };
78 | }
79 | // Will support artifact in the next release
80 | throw new Error('ERR_SP_LOGIN_REQUEST_UNDEFINED_BINDING');
81 | }
82 |
83 | /**
84 | * @desc Validation of the parsed the URL parameters
85 | * @param {IdentityProvider} idp object of identity provider
86 | * @param {string} binding protocol binding
87 | * @param {request} req request
88 | */
89 | public parseLoginResponse(idp, binding, request: ESamlHttpRequest) {
90 | const self = this;
91 | return flow({
92 | from: idp,
93 | self: self,
94 | checkSignature: true, // saml response must have signature
95 | parserType: 'SAMLResponse',
96 | type: 'login',
97 | binding: binding,
98 | request: request
99 | });
100 | }
101 |
102 | }
103 |
--------------------------------------------------------------------------------
/src/metadata-idp.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @file metadata-idp.ts
3 | * @author tngan
4 | * @desc Metadata of identity provider
5 | */
6 | import Metadata, { MetadataInterface } from './metadata';
7 | import { MetadataIdpOptions, MetadataIdpConstructor } from './types';
8 | import { namespace } from './urn';
9 | import libsaml from './libsaml';
10 | import { isNonEmptyArray, isString } from './utility';
11 | import * as xml from 'xml';
12 |
13 | export interface IdpMetadataInterface extends MetadataInterface {
14 |
15 | }
16 |
17 | /*
18 | * @desc interface function
19 | */
20 | export default function(meta: MetadataIdpConstructor) {
21 | return new IdpMetadata(meta);
22 | }
23 |
24 | export class IdpMetadata extends Metadata {
25 |
26 | constructor(meta: MetadataIdpConstructor) {
27 |
28 | const isFile = isString(meta) || meta instanceof Buffer;
29 |
30 | if (!isFile) {
31 |
32 | const {
33 | entityID,
34 | signingCert,
35 | encryptCert,
36 | wantAuthnRequestsSigned = false,
37 | nameIDFormat = [],
38 | singleSignOnService = [],
39 | singleLogoutService = [],
40 | } = meta as MetadataIdpOptions;
41 |
42 | const IDPSSODescriptor: any[] = [{
43 | _attr: {
44 | WantAuthnRequestsSigned: String(wantAuthnRequestsSigned),
45 | protocolSupportEnumeration: namespace.names.protocol,
46 | },
47 | }];
48 |
49 | if (signingCert) {
50 | IDPSSODescriptor.push(libsaml.createKeySection('signing', signingCert));
51 | } else {
52 | //console.warn('Construct identity provider - missing signing certificate');
53 | }
54 |
55 | if (encryptCert) {
56 | IDPSSODescriptor.push(libsaml.createKeySection('encryption', encryptCert));
57 | } else {
58 | //console.warn('Construct identity provider - missing encrypt certificate');
59 | }
60 |
61 | if (isNonEmptyArray(nameIDFormat)) {
62 | nameIDFormat.forEach(f => IDPSSODescriptor.push({ NameIDFormat: f }));
63 | }
64 |
65 | if (isNonEmptyArray(singleSignOnService)) {
66 | singleSignOnService.forEach((a, indexCount) => {
67 | const attr: any = {
68 | Binding: a.Binding,
69 | Location: a.Location,
70 | };
71 | if (a.isDefault) {
72 | attr.isDefault = true;
73 | }
74 | IDPSSODescriptor.push({ SingleSignOnService: [{ _attr: attr }] });
75 | });
76 | } else {
77 | throw new Error('ERR_IDP_METADATA_MISSING_SINGLE_SIGN_ON_SERVICE');
78 | }
79 |
80 | if (isNonEmptyArray(singleLogoutService)) {
81 | singleLogoutService.forEach((a, indexCount) => {
82 | const attr: any = {};
83 | if (a.isDefault) {
84 | attr.isDefault = true;
85 | }
86 | attr.Binding = a.Binding;
87 | attr.Location = a.Location;
88 | IDPSSODescriptor.push({ SingleLogoutService: [{ _attr: attr }] });
89 | });
90 | } else {
91 | console.warn('Construct identity provider - missing endpoint of SingleLogoutService');
92 | }
93 | // Create a new metadata by setting
94 | meta = xml([{
95 | EntityDescriptor: [{
96 | _attr: {
97 | 'xmlns': namespace.names.metadata,
98 | 'xmlns:assertion': namespace.names.assertion,
99 | 'xmlns:ds': 'http://www.w3.org/2000/09/xmldsig#',
100 | entityID,
101 | },
102 | }, { IDPSSODescriptor }],
103 | }]);
104 | }
105 |
106 | super(meta as string | Buffer, [
107 | {
108 | key: 'wantAuthnRequestsSigned',
109 | localPath: ['EntityDescriptor', 'IDPSSODescriptor'],
110 | attributes: ['WantAuthnRequestsSigned'],
111 | },
112 | {
113 | key: 'singleSignOnService',
114 | localPath: ['EntityDescriptor', 'IDPSSODescriptor', 'SingleSignOnService'],
115 | index: ['Binding'],
116 | attributePath: [],
117 | attributes: ['Location']
118 | },
119 | ]);
120 |
121 | }
122 |
123 | /**
124 | * @desc Get the preference whether it wants a signed request
125 | * @return {boolean} WantAuthnRequestsSigned
126 | */
127 | isWantAuthnRequestsSigned(): boolean {
128 | const was = this.meta.wantAuthnRequestsSigned;
129 | if (was === undefined) {
130 | return false;
131 | }
132 | return String(was) === 'true';
133 | }
134 |
135 | /**
136 | * @desc Get the entity endpoint for single sign on service
137 | * @param {string} binding protocol binding (e.g. redirect, post)
138 | * @return {string/object} location
139 | */
140 | getSingleSignOnService(binding: string): string | object {
141 | if (isString(binding)) {
142 | const bindName = namespace.binding[binding];
143 | const service = this.meta.singleSignOnService[bindName];
144 | if (service) {
145 | return service;
146 | }
147 | }
148 | return this.meta.singleSignOnService;
149 | }
150 | }
151 |
--------------------------------------------------------------------------------
/src/metadata.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @file metadata.ts
3 | * @author tngan
4 | * @desc An abstraction for metadata of identity provider and service provider
5 | */
6 | import * as fs from 'fs';
7 | import { namespace } from './urn';
8 | import { extract } from './extractor';
9 | import { isString } from './utility';
10 |
11 | export interface MetadataInterface {
12 | xmlString: string;
13 | getMetadata: () => string;
14 | exportMetadata: (exportFile: string) => void;
15 | getEntityID: () => string;
16 | getX509Certificate: (certType: string) => string | string[];
17 | getNameIDFormat: () => any[];
18 | getSingleLogoutService: (binding: string | undefined) => string | object;
19 | getSupportBindings: (services: string[]) => string[];
20 | }
21 |
22 | export default class Metadata implements MetadataInterface {
23 |
24 | xmlString: string;
25 | meta: any;
26 |
27 | /**
28 | * @param {string | Buffer} metadata xml
29 | * @param {object} extraParse for custom metadata extractor
30 | */
31 | constructor(xml: string | Buffer, extraParse: any = []) {
32 | this.xmlString = xml.toString();
33 | this.meta = extract(this.xmlString, extraParse.concat([
34 | {
35 | key: 'entityDescriptor',
36 | localPath: ['EntityDescriptor'],
37 | attributes: [],
38 | context: true
39 | },
40 | {
41 | key: 'entityID',
42 | localPath: ['EntityDescriptor'],
43 | attributes: ['entityID']
44 | },
45 | {
46 | // shared certificate for both encryption and signing
47 | key: 'sharedCertificate',
48 | localPath: ['EntityDescriptor', '~SSODescriptor', 'KeyDescriptor', 'KeyInfo', 'X509Data', 'X509Certificate'],
49 | attributes: []
50 | },
51 | {
52 | // explicit certificate declaration for encryption and signing
53 | key: 'certificate',
54 | localPath: ['EntityDescriptor', '~SSODescriptor', 'KeyDescriptor'],
55 | index: ['use'],
56 | attributePath: ['KeyInfo', 'X509Data', 'X509Certificate'],
57 | attributes: []
58 | },
59 | {
60 | key: 'singleLogoutService',
61 | localPath: ['EntityDescriptor', '~SSODescriptor', 'SingleLogoutService'],
62 | attributes: ['Binding', 'Location']
63 | },
64 | {
65 | key: 'nameIDFormat',
66 | localPath: ['EntityDescriptor', '~SSODescriptor', 'NameIDFormat'],
67 | attributes: [],
68 | }
69 | ]));
70 |
71 | // get shared certificate
72 | const sharedCertificate = this.meta.sharedCertificate;
73 | if (typeof sharedCertificate === 'string') {
74 | this.meta.certificate = {
75 | signing: sharedCertificate,
76 | encryption: sharedCertificate
77 | };
78 | delete this.meta.sharedCertificate;
79 | }
80 |
81 | if (
82 | Array.isArray(this.meta.entityDescriptor) &&
83 | this.meta.entityDescriptor.length > 1
84 | ) {
85 | throw new Error('ERR_MULTIPLE_METADATA_ENTITYDESCRIPTOR');
86 | }
87 |
88 | }
89 |
90 | /**
91 | * @desc Get the metadata in xml format
92 | * @return {string} metadata in xml format
93 | */
94 | public getMetadata(): string {
95 | return this.xmlString;
96 | }
97 |
98 | /**
99 | * @desc Export the metadata to specific file
100 | * @param {string} exportFile is the output file path
101 | */
102 | public exportMetadata(exportFile: string): void {
103 | fs.writeFileSync(exportFile, this.xmlString);
104 | }
105 |
106 | /**
107 | * @desc Get the entityID in metadata
108 | * @return {string} entityID
109 | */
110 | public getEntityID(): string {
111 | return this.meta.entityID;
112 | }
113 |
114 | /**
115 | * @desc Get the x509 certificate declared in entity metadata
116 | * @param {string} use declares the type of certificate
117 | * @return {string} certificate in string format
118 | */
119 | public getX509Certificate(use: string): string | string[] {
120 | return this.meta.certificate[use] || null;
121 | }
122 |
123 | /**
124 | * @desc Get the support NameID format declared in entity metadata
125 | * @return {array} support NameID format
126 | */
127 | public getNameIDFormat(): any {
128 | return this.meta.nameIDFormat;
129 | }
130 |
131 | /**
132 | * @desc Get the entity endpoint for single logout service
133 | * @param {string} binding e.g. redirect, post
134 | * @return {string/object} location
135 | */
136 | public getSingleLogoutService(binding: string | undefined): string | object {
137 | if (binding && isString(binding)) {
138 | const bindType = namespace.binding[binding];
139 | let singleLogoutService = this.meta.singleLogoutService;
140 | if (!(singleLogoutService instanceof Array)) {
141 | singleLogoutService = [singleLogoutService];
142 | }
143 | const service = singleLogoutService.find(obj => obj.binding === bindType);
144 | if (service) {
145 | return service.location;
146 | }
147 | }
148 | return this.meta.singleLogoutService;
149 | }
150 |
151 | /**
152 | * @desc Get the support bindings
153 | * @param {[string]} services
154 | * @return {[string]} support bindings
155 | */
156 | public getSupportBindings(services: string[]): string[] {
157 | let supportBindings = [];
158 | if (services) {
159 | supportBindings = services.reduce((acc: any, service) => {
160 | const supportBinding = Object.keys(service)[0];
161 | return acc.push(supportBinding);
162 | }, []);
163 | }
164 | return supportBindings;
165 | }
166 | }
167 |
--------------------------------------------------------------------------------
/src/types.ts:
--------------------------------------------------------------------------------
1 | import { LoginResponseTemplate } from './libsaml';
2 |
3 | export { IdentityProvider as IdentityProviderConstructor } from './entity-idp';
4 | export { IdpMetadata as IdentityProviderMetadata } from './metadata-idp';
5 |
6 | export { ServiceProvider as ServiceProviderConstructor } from './entity-sp';
7 | export { SpMetadata as ServiceProviderMetadata } from './metadata-sp';
8 |
9 | export type MetadataFile = string | Buffer;
10 |
11 | type SSOService = {
12 | isDefault?: boolean;
13 | Binding: string;
14 | Location: string;
15 | };
16 |
17 | export interface MetadataIdpOptions {
18 | entityID?: string;
19 | signingCert?: string | Buffer;
20 | encryptCert?: string | Buffer;
21 | wantAuthnRequestsSigned?: boolean;
22 | nameIDFormat?: string[];
23 | singleSignOnService?: SSOService[];
24 | singleLogoutService?: SSOService[];
25 | requestSignatureAlgorithm?: string;
26 | }
27 |
28 | export type MetadataIdpConstructor =
29 | | MetadataIdpOptions
30 | | MetadataFile;
31 |
32 | export interface MetadataSpOptions {
33 | entityID?: string;
34 | signingCert?: string | Buffer;
35 | encryptCert?: string | Buffer;
36 | authnRequestsSigned?: boolean;
37 | wantAssertionsSigned?: boolean;
38 | wantMessageSigned?: boolean;
39 | signatureConfig?: { [key: string]: any };
40 | nameIDFormat?: string[];
41 | singleSignOnService?: SSOService[];
42 | singleLogoutService?: SSOService[];
43 | assertionConsumerService?: SSOService[];
44 | elementsOrder?: string[];
45 | }
46 |
47 | export type MetadataSpConstructor =
48 | | MetadataSpOptions
49 | | MetadataFile;
50 |
51 | export type EntitySetting = ServiceProviderSettings & IdentityProviderSettings;
52 |
53 | export interface SignatureConfig {
54 | prefix?: string;
55 | location?: {
56 | reference?: string;
57 | action?: 'append' | 'prepend' | 'before' | 'after';
58 | };
59 | }
60 |
61 | export interface SAMLDocumentTemplate {
62 | context?: string;
63 | }
64 |
65 | export type ServiceProviderSettings = {
66 | metadata?: string | Buffer;
67 | entityID?: string;
68 | authnRequestsSigned?: boolean;
69 | wantAssertionsSigned?: boolean;
70 | wantMessageSigned?: boolean;
71 | wantLogoutResponseSigned?: boolean;
72 | wantLogoutRequestSigned?: boolean;
73 | privateKey?: string | Buffer;
74 | privateKeyPass?: string;
75 | isAssertionEncrypted?: boolean;
76 | requestSignatureAlgorithm?: string;
77 | encPrivateKey?: string | Buffer;
78 | encPrivateKeyPass?: string | Buffer;
79 | assertionConsumerService?: SSOService[];
80 | singleLogoutService?: SSOService[];
81 | signatureConfig?: SignatureConfig;
82 | loginRequestTemplate?: SAMLDocumentTemplate;
83 | logoutRequestTemplate?: SAMLDocumentTemplate;
84 | signingCert?: string | Buffer;
85 | encryptCert?: string | Buffer;
86 | transformationAlgorithms?: string[];
87 | nameIDFormat?: string[];
88 | allowCreate?: boolean;
89 | // will be deprecated soon
90 | relayState?: string;
91 | // https://github.com/tngan/samlify/issues/337
92 | clockDrifts?: [number, number];
93 | };
94 |
95 | export type IdentityProviderSettings = {
96 | metadata?: string | Buffer;
97 |
98 | /** signature algorithm */
99 | requestSignatureAlgorithm?: string;
100 |
101 | /** template of login response */
102 | loginResponseTemplate?: LoginResponseTemplate;
103 |
104 | /** template of logout request */
105 | logoutRequestTemplate?: SAMLDocumentTemplate;
106 |
107 | /** customized function used for generating request ID */
108 | generateID?: () => string;
109 |
110 | entityID?: string;
111 | privateKey?: string | Buffer;
112 | privateKeyPass?: string;
113 | signingCert?: string | Buffer;
114 | encryptCert?: string | Buffer; /** todo */
115 | nameIDFormat?: string[];
116 | singleSignOnService?: SSOService[];
117 | singleLogoutService?: SSOService[];
118 | isAssertionEncrypted?: boolean;
119 | encPrivateKey?: string | Buffer;
120 | encPrivateKeyPass?: string;
121 | messageSigningOrder?: string;
122 | wantLogoutRequestSigned?: boolean;
123 | wantLogoutResponseSigned?: boolean;
124 | wantAuthnRequestsSigned?: boolean;
125 | wantLogoutRequestSignedResponseSigned?: boolean;
126 | tagPrefix?: { [key: string]: string };
127 | };
128 |
--------------------------------------------------------------------------------
/src/validator.ts:
--------------------------------------------------------------------------------
1 | // unit is ms
2 | type DriftTolerance = [number, number];
3 |
4 | function verifyTime(
5 | utcNotBefore: string | undefined,
6 | utcNotOnOrAfter: string | undefined,
7 | drift: DriftTolerance = [0, 0]
8 | ): boolean {
9 |
10 | const now = new Date();
11 |
12 | if (!utcNotBefore && !utcNotOnOrAfter) {
13 | // show warning because user intends to have time check but the document doesn't include corresponding information
14 | console.warn('You intend to have time validation however the document doesn\'t include the valid range.');
15 | return true;
16 | }
17 |
18 | let notBeforeLocal: Date | null = null;
19 | let notOnOrAfterLocal: Date | null = null;
20 |
21 | const [notBeforeDrift, notOnOrAfterDrift] = drift;
22 |
23 | if (utcNotBefore && !utcNotOnOrAfter) {
24 | notBeforeLocal = new Date(utcNotBefore);
25 | return +notBeforeLocal + notBeforeDrift <= +now;
26 | }
27 | if (!utcNotBefore && utcNotOnOrAfter) {
28 | notOnOrAfterLocal = new Date(utcNotOnOrAfter);
29 | return +now < +notOnOrAfterLocal + notOnOrAfterDrift;
30 | }
31 |
32 | notBeforeLocal = new Date(utcNotBefore!);
33 | notOnOrAfterLocal = new Date(utcNotOnOrAfter!);
34 |
35 | return (
36 | +notBeforeLocal + notBeforeDrift <= +now &&
37 | +now < +notOnOrAfterLocal + notOnOrAfterDrift
38 | );
39 |
40 | }
41 |
42 | export {
43 | verifyTime
44 | };
--------------------------------------------------------------------------------
/test/README.md:
--------------------------------------------------------------------------------
1 | ## Standalone code for running directly with Node.js REPL
2 |
3 | ```javascript
4 | // playground setup for extractor
5 | var samlify = require('./build/index');
6 | var fs = require('fs');
7 | var idpconfig = {
8 | privateKey: fs.readFileSync('./test/key/idp/privkey.pem'),
9 | privateKeyPass: 'q9ALNhGT5EhfcRmp8Pg7e9zTQeP2x1bW',
10 | isAssertionEncrypted: false,
11 | metadata: fs.readFileSync('./test/misc/idpmeta_rollingcert.xml')
12 | };
13 | var idp = samlify.IdentityProvider(idpconfig);
14 |
15 | samlify.Extractor.extract(idp.entityMeta.xmlString, [
16 | {
17 | key: 'certificate',
18 | localPath: ['EntityDescriptor', '~SSODescriptor', 'KeyDescriptor'],
19 | index: ['use'],
20 | attributePath: ['KeyInfo', 'X509Data', 'X509Certificate'],
21 | attributes: []
22 | }
23 | ])
24 |
25 | // construct response signature
26 | const {
27 | IdPMetadata: idpMetadata,
28 | Utility: utility,
29 | SamlLib: libsaml,
30 | } = require('./');
31 | const fs = require('fs');
32 | const metadata = idpMetadata(fs.readFileSync('./test/misc/idpmeta_rollingcert.xml'));
33 | const _idpKeyFolder = './test/key/idp/';
34 | const _idpPrivPem1 = String(fs.readFileSync(_idpKeyFolder + 'privkey.pem'));
35 | const _idpPrivPem2 = String(fs.readFileSync(_idpKeyFolder + 'privkey2.pem'));
36 | function writer(str) {
37 | fs.writeFileSync('nogit.xml', str);
38 | }
39 | writer(utility.base64Decode(libsaml.constructSAMLSignature({
40 | rawSamlMessage: String(fs.readFileSync('./test/misc/response.xml')),
41 | referenceTagXPath: libsaml.createXPath('Issuer'),
42 | signingCert: metadata.getX509Certificate('signing')[0],
43 | privateKey: _idpPrivPem1,
44 | privateKeyPass: 'q9ALNhGT5EhfcRmp8Pg7e9zTQeP2x1bW',
45 | signatureAlgorithm: 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256',
46 | signatureConfig: {
47 | prefix: 'ds',
48 | location: { reference: "/*[local-name(.)='Response']/*[local-name(.)='Issuer']", action: 'after' },
49 | },
50 | })));
51 | ```
--------------------------------------------------------------------------------
/test/extractor.ts:
--------------------------------------------------------------------------------
1 | // This test file includes all the units related to the extractor
2 | import test from 'ava';
3 | import { readFileSync } from 'fs';
4 | import { extract } from '../src/extractor';
5 |
6 | const _decodedResponse: string = String(readFileSync('./test/misc/response_signed.xml'));
7 | const _spmeta: string = String(readFileSync('./test/misc/spmeta.xml'));
8 |
9 | (() => {
10 |
11 | test('fetch multiple attributes', t => {
12 | const result = extract(_decodedResponse, [
13 | {
14 | key: 'response',
15 | localPath: ['Response'],
16 | attributes: ['ID', 'Destination']
17 | }
18 | ]);
19 | t.is(result.response.id, '_8e8dc5f69a98cc4c1ff3427e5ce34606fd672f91e6');
20 | t.is(result.response.destination, 'http://sp.example.com/demo1/index.php?acs');
21 | });
22 |
23 | test('fetch single attributes', t => {
24 | const result = extract(_decodedResponse, [
25 | {
26 | key: 'statusCode',
27 | localPath: ['Response', 'Status', 'StatusCode'],
28 | attributes: ['Value'],
29 | }
30 | ]);
31 | t.is(result.statusCode, 'urn:oasis:names:tc:SAML:2.0:status:Success');
32 | });
33 |
34 | test('fetch the inner context of leaf node', t => {
35 | const result = extract(_decodedResponse, [
36 | {
37 | key: 'audience',
38 | localPath: ['Response', 'Assertion', 'Conditions', 'AudienceRestriction', 'Audience'],
39 | attributes: []
40 | }
41 | ]);
42 | t.is(result.audience, 'https://sp.example.com/metadata');
43 | });
44 |
45 | test('fetch the entire context of a non-existing node ', t => {
46 | const result = extract(_decodedResponse, [
47 | {
48 | key: 'assertionSignature',
49 | localPath: ['Response', 'Assertion', 'Signature'],
50 | attributes: [],
51 | context: true
52 | }
53 | ]);
54 | t.is(result.assertionSignature, null);
55 | });
56 |
57 | test('fetch the entire context of an existed node', t => {
58 | const result = extract(_decodedResponse, [
59 | {
60 | key: 'messageSignature',
61 | localPath: ['Response', 'Signature'],
62 | attributes: [],
63 | context: true
64 | }
65 | ]);
66 | t.not(result.messageSignature, null);
67 | });
68 |
69 | test('fetch the unique inner context of multiple nodes', t => {
70 | const result = extract(_decodedResponse, [
71 | {
72 | key: 'issuer',
73 | localPath: [
74 | ['Response', 'Issuer'],
75 | ['Response', 'Assertion', 'Issuer']
76 | ],
77 | attributes: []
78 | }
79 | ]);
80 | t.is(result.issuer.length, 1);
81 | t.is(result.issuer.every(i => i === 'https://idp.example.com/metadata'), true);
82 | });
83 |
84 | test('fetch the attribute with wildcard local path', t => {
85 | const result = extract(_spmeta, [
86 | {
87 | key: 'certificate',
88 | localPath: ['EntityDescriptor', '~SSODescriptor', 'KeyDescriptor'],
89 | index: ['use'],
90 | attributePath: ['KeyInfo', 'X509Data', 'X509Certificate'],
91 | attributes: []
92 | }
93 | ]);
94 | t.not(result.certificate.signing, null);
95 | t.not(result.certificate.encryption, null);
96 | });
97 |
98 | test('fetch the attribute with non-wildcard local path', t => {
99 | const result = extract(_decodedResponse, [
100 | {
101 | key: 'attributes',
102 | localPath: ['Response', 'Assertion', 'AttributeStatement', 'Attribute'],
103 | index: ['Name'],
104 | attributePath: ['AttributeValue'],
105 | attributes: []
106 | }
107 | ]);
108 | t.is(result.attributes.uid, 'test');
109 | t.is(result.attributes.mail, 'test@example.com');
110 | t.is(result.attributes.eduPersonAffiliation.length, 2);
111 | });
112 |
113 | test('fetch with one attribute as key, another as value', t => {
114 | const result = extract(_spmeta, [
115 | {
116 | key: 'singleSignOnService',
117 | localPath: ['EntityDescriptor', '~SSODescriptor', 'AssertionConsumerService'],
118 | index: ['Binding'],
119 | attributePath: [],
120 | attributes: ['Location']
121 | }
122 | ]);
123 | const postEndpoint = result.singleSignOnService['urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST'];
124 | const artifactEndpoint = result.singleSignOnService['urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact'];
125 |
126 | t.is(postEndpoint, 'https://sp.example.org/sp/sso');
127 | t.is(artifactEndpoint, 'https://sp.example.org/sp/sso');
128 | });
129 |
130 | })();
131 |
--------------------------------------------------------------------------------
/test/key/idp/README.md:
--------------------------------------------------------------------------------
1 | ## Support the use case of rolling certificate
2 |
3 | * `privkey1.pem` - password protected `q9ALNhGT5EhfcRmp8Pg7e9zTQeP2x1bW`, it generates `cert.cer`
4 | * `privkey2.pem` - no password protected, it generates `cert2.cer`
--------------------------------------------------------------------------------
/test/key/idp/cert.cer:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIDlzCCAn+gAwIBAgIJAO1ymQc33+bWMA0GCSqGSIb3DQEBCwUAMGIxCzAJBgNV
3 | BAYTAkhLMRMwEQYDVQQIDApTb21lLVN0YXRlMRowGAYDVQQKDBFJZGVudGl0eSBQ
4 | cm92aWRlcjEUMBIGA1UECwwLRGV2ZWxvcG1lbnQxDDAKBgNVBAMMA0lEUDAeFw0x
5 | NTA3MDUxODAyMjdaFw0xODA3MDQxODAyMjdaMGIxCzAJBgNVBAYTAkhLMRMwEQYD
6 | VQQIDApTb21lLVN0YXRlMRowGAYDVQQKDBFJZGVudGl0eSBQcm92aWRlcjEUMBIG
7 | A1UECwwLRGV2ZWxvcG1lbnQxDDAKBgNVBAMMA0lEUDCCASIwDQYJKoZIhvcNAQEB
8 | BQADggEPADCCAQoCggEBAODZsWhCe+yG0PalQPTUoD7yko5MTWMCRxJ8hSm2k7mG
9 | 3Eg/Y2v0EBdCmTw7iDCevRqUmbmFnq7MROyV4eriJzh0KabAdZf7/k6koghst3ZU
10 | tWOwzshyxkBtWDwGmBpQGTGsKxJ8M1js3aSqNRXBT4OBWM9w2Glt1+8ty30RhYv3
11 | pSF+/HHLH7Ac+vLSIAlokaFW34RWTcJ/8rADuRWlXih4GfnIu0W/ncm5nTSaJiRA
12 | vr3dGDRO/khiXoJdbbOj7dHPULxVGbH9IbPK76TCwLbF7ikIMsPovVbTrpyL6vsb
13 | VUKeEl/5GKppTwp9DLAOeoSYpCYkkDkYKu9TRQjF02MCAwEAAaNQME4wHQYDVR0O
14 | BBYEFP2ut2AQdy6D1dwdwK740IHmbh38MB8GA1UdIwQYMBaAFP2ut2AQdy6D1dwd
15 | wK740IHmbh38MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBANMZUoPN
16 | mHzgja2PYkbvBYMHmpvUkVoiuvQ9cJPlqGTB2CRfG68BNNs/Clz8P7cIrAdkhCUw
17 | i1rSBhDuslGFNrSaIpv6B10FpBuKwef3G7YrPWFNEN6khY7aHNWSTHqKgs1DrGef
18 | 2B9hvkrnHWbQVSVXrBFKe1wTCqcgGcOpYoSK7L8C6iX6uIA/uZYnVQ4NgBrizJ0a
19 | zkjdegz3hwO/gt4malEURy8D85/AAVt6PAzhpb9VJUGxSXr/EfntVUEz3L2gUFWW
20 | k1CnZFyz0rIOEt/zPmeAY8BLyd/Tjxm4Y+gwNazKq5y9AJS+m858b/nM4QdCnUE4
21 | yyoWAJDUHiAmvFA=
22 | -----END CERTIFICATE-----
23 |
--------------------------------------------------------------------------------
/test/key/idp/cert2.cer:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIFLjCCAxYCCQCqGHhTssya9jANBgkqhkiG9w0BAQsFADBZMQswCQYDVQQGEwJI
3 | SzESMBAGA1UECAwJSG9uZyBLb25nMRIwEAYDVQQHDAlIb25nIEtvbmcxEDAOBgNV
4 | BAoMB3NhbWxpZnkxEDAOBgNVBAMMB3NhbWxpZnkwHhcNMjAwNTEwMTUyNjIzWhcN
5 | MzAwNTA4MTUyNjIzWjBZMQswCQYDVQQGEwJISzESMBAGA1UECAwJSG9uZyBLb25n
6 | MRIwEAYDVQQHDAlIb25nIEtvbmcxEDAOBgNVBAoMB3NhbWxpZnkxEDAOBgNVBAMM
7 | B3NhbWxpZnkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDQG+abAeeW
8 | jwsOZt5SkcNcw/XSJcjSyJykEbEU2iguErRuOIyBfgj0p1UVBv33uL2igeYJT3OS
9 | XmSjvMO8KvqtYN2tJAjoFjghGr8NbIEZjYS4ukMZUbwxd2bRycD9OMI9g44AUB1s
10 | fQ0UyFwzEOseW3lcW1FnhcizA8TgI0GN4NpdVruNlpgoWdP3w+Syhtq0rWebY8g/
11 | HGFruEKn8VwbUblOZdP7jNVXsd1aUMScpuMa0khzzXPDN+Q0rwl79fO4ychSeKAA
12 | ERdPXA1UfDfbh9W7pcYBP0ABXd91Bf9akplmbbVOIsNbuRIcVS7WvLwCr613JuJ+
13 | EtGDcUkrSpbuRvDW85DQRHBGuoKlcSG+imHQtHqRwMwMc8P54hIEBvaFW0RfwPfz
14 | dFNe8wARtmvIeX84iwq5Yey15Ly1rdopi7t2g7qyF7C/B9gZ3tJ/gPKp2NrdCGFB
15 | cahl93Lj56WWmI0jNHn7+7Y3x6isJ3KTRXIliSrAwiK7/7UezOlWzs1k8mGQWZTD
16 | 3AGGKu1cBVwuC+rh4wkLsDeHfzxavbXxVEok9p/1P28M4GiHfS0POE3Hl4RT3Q6A
17 | iYWnmFYyZ+smY97SgPwB4tTNYFjC6+9d/BllNoQb8wsPjqp6ZDn1OeY668hp+ZAc
18 | E13AFdiTBMVrcdEECCPLxg1kFk5wZdHrGwIDAQABMA0GCSqGSIb3DQEBCwUAA4IC
19 | AQCyA/14hKTqfdeOVl+MQ2SLPWi7pC/t/Zv4kc361xP26FAVSSrxgXq9kVLZeJIA
20 | qCwjGHkl/DTUlA8hfLfuZx5z+NI/qIodsXAjCzsCe7paEbjvR6OQjYkR0UY4u/AO
21 | O7x2op2KDFKNuWT9KZNm8bh1mxwNKep1fJP2O5M0nMYAGYbPsLAOn7mzZyufQl8h
22 | sJwIV2s8sbft7s8vmEYZbuueQDOJCMTt+eC08LONrovYChyYmj3i5RIk8kcaodeS
23 | Do811F1B1gDvO/dmVxgrHEgoai7X6LUoiAiLkigP7udNEZxbXsRlOhBRv9w+rRXF
24 | urVFlUPkQ9UF+QB0BoyIcUxo+fZ8vCA4xEVBenVBadpFbwum6+XeTkvDoRc4sSCp
25 | m8v2qtprc8aU/0F82EzxSybYvstc5lDv7wuwCwNwfoAQ+/16kTpJvoYbOXUPv5yC
26 | A3mIuqYeA1woaWPXsE4jNOzTqv1qOZQTvXProEgK5B0FR5ILc4mfNrD2p9VGbiYf
27 | 2GjCfeEzDFg174dvSn2MMp1yK5pvZEp7yFE8z1eduYN6W/7qdtss9BGpnyS5X7Lu
28 | YfDvd1dHP6/JuqJDbfSVG9prYWcaMRd3FzSC7jBeetJgMyj4dunfqw8R16aONhwv
29 | ICtzdFa93hYrDvTyo3ae80KFi0WGgApKeoqO5t3l1PAcaA==
30 | -----END CERTIFICATE-----
31 |
--------------------------------------------------------------------------------
/test/key/idp/encryptKey.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | Proc-Type: 4,ENCRYPTED
3 | DEK-Info: DES-EDE3-CBC,FACBF89A697AB50A
4 |
5 | i0RiFM9TTHzN/atuOBWhAfoty7rMEgNVVsyeoAPqQZoGwBTmOSbMZ+3vLR3jc7Xi
6 | GJ4NtXOux2IcNy5rcYnL3SgZIANVakfEUwF6qwBLCGYbOaqWqEv4eHvz9JHIH9iC
7 | 0w4PPMzA2Q4daWiRw1UGr4Kik2iqfkDGv4JPdUDY7/KNlD4hpthRk6axUg+XbJat
8 | swCijv0NGrU//MRGCpqnt4q5ApoZ5Yg4jIbc9JG95ZoZ9+eVZJa1l9ZyYyw6bJ6+
9 | 0iinwWC59qX4soWzvBPvXMzJpgSPAtDrhNKMU4mLPD6+1fLVsc5POzjAuGqDRNcV
10 | bJb/nftu3/MNasXI0PI37RM5krOitBfona8YD4T3B5fIa80XBUrPfSpFXqOqCHZQ
11 | H4rHbnletX8mnAAlzBIEzELO5Dspwnd9OvEkHsKdN5BSZ8cKJh6/qIHwejn4DP21
12 | hvFAkUYrZWpNZsCi7CKZTJBYkwogW7u0u7ki3XiyPxeDJaYSyTxcdiZD2eVmsWdh
13 | wOWU7mfprfcYIJJnslyJ104z5C0Ioj2xp7VHcX4It8DrwzizfPHkvasv9JarILIX
14 | yeST80i7mcxFyAwmuKIVdD+vvNhZeu0OYs15uhcoKH/oIz2dBLk5U+d/hVwV6TlX
15 | v41nDLuXfvqjAh83rz+a+QkjEdtaMDXKkM3ob6u13F+7JZPQ/32VMeiu0hMWwFff
16 | nijXoWZ+gv3hxbI2oy3Gc2Kjj4H8sYBx/Jd+LTtEZzH01wq0oR/2BR2r74ErB2lF
17 | ByD9d9/SJ/+WrIuseJTcLIWARP5t0QDe8NAWEY5KPk6YjvB84jHIAHf+K+fQMKJL
18 | n6ehvRlVZo4a4cP9PPGMEupfSHCNjioRzT92/AAc3+vplZghMd8lNOpCKSs2NlYX
19 | rf1gKanBPwjcH034SbiP3gN8r4j0Pep6RIWBra2FGZtZcNUhLSXZG87Lmf4RGnsJ
20 | TRwbCUPAx21vhkoQPg5/sLh9IQ+7nzCZfs82ke/yXVNNW7KIxchQ8mz54Ji/k2ix
21 | l0q3jRgH3u8LGPOyLwl1h2fusfZjKYZQnjTZw69Xv8kz1dt5iigNlSspwoMm9NI1
22 | Hj2TEXQJuBi2/Z+J+aDnY8HLPTM1VtXpuJiPmbxcS0kAJIveg9HQDAei26i+l5OM
23 | b4tXGjGCH/HYJxNIFWtAkrRJZjwrKmVF/GWESGvOtpEsm5YiuC5pUt7+fs6eZ+F+
24 | nzUV2d/2EkA3FKEjAvoQb6QICCFE0SRUGutYYuUZm4AYG3JEeI4JGYpE1h9pGXMz
25 | m1hlV8N9EIJiFdEtGifjAcfHSVHm7m4us5qOG0TiVfSDC3RZCJSxm8pAUJXLaemp
26 | BvoHL8MuJX8bNMMB3JpWW3e3HxrmR8nLk+xZiviggfWBVRxM9YAyb6NPezVFAV0H
27 | YTULqiXGZbpe+Bm6MmJ6LryicIf8E3pyGbQEYtO9iLYfXnJDHud4dKZnXqjo68oc
28 | 80EeEm149eVGtYFRiWhjnRGyb6Hdql4u5iLZdaBRIm3Jm0qsHioYBi6SH5ucPM+q
29 | 8hSEfoIZiRlSsrjzvko+19lM4/JnHpk/7cihRNpgXBQysGLwSSA626cvgjwEJSJB
30 | -----END RSA PRIVATE KEY-----
31 |
--------------------------------------------------------------------------------
/test/key/idp/encryptionCert.cer:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIID6TCCAtGgAwIBAgIJAPQQPsolUypeMA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNV
3 | BAYTAkhLMRIwEAYDVQQIEwlIb25nIEtvbmcxFTATBgNVBAoTDGV4cHJlc3Mtc2Ft
4 | bDEMMAoGA1UECxMDZGV2MQ4wDAYDVQQDEwVlc2FtbDAeFw0xNTEwMDMwMzU3MzRa
5 | Fw0xODEwMDIwMzU3MzRaMFYxCzAJBgNVBAYTAkhLMRIwEAYDVQQIEwlIb25nIEtv
6 | bmcxFTATBgNVBAoTDGV4cHJlc3Mtc2FtbDEMMAoGA1UECxMDZGV2MQ4wDAYDVQQD
7 | EwVlc2FtbDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL7dF1gUNu8e
8 | n0fHMSbzf192uB8m2CTeHeEeYrmq5rau6t1WzaHwbSStd9tJ/11Arm8f8zfefFqE
9 | BA0EYbp/DMqHb9ZiLGgIff08679NOYeK/d9EAs5DzvTMTR6QqG7a4vH3jKOksIbj
10 | M35h5RVitVDxo+xWDKyvOpuNE64bJlWHOEiNxvwmcHfJ2hAd1EozaRLcJOojFHg5
11 | 1alUqiNIZ+vpkMAM8s3lUlcYETKqTpcnsE7c1QX60cCrFN4m3SNS98HGBEdotch8
12 | +2Myzz957cBiwg9CR05PtEfjH0gGXJbL56JmpPyY+TkEiNMtMqJ7RNkK92gZfoY2
13 | i3RdjLKOHDUCAwEAAaOBuTCBtjAdBgNVHQ4EFgQUm4zK2qBtDMICekupt3LnRBdb
14 | P9UwgYYGA1UdIwR/MH2AFJuMytqgbQzCAnpLqbdy50QXWz/VoVqkWDBWMQswCQYD
15 | VQQGEwJISzESMBAGA1UECBMJSG9uZyBLb25nMRUwEwYDVQQKEwxleHByZXNzLXNh
16 | bWwxDDAKBgNVBAsTA2RldjEOMAwGA1UEAxMFZXNhbWyCCQD0ED7KJVMqXjAMBgNV
17 | HRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQA9t7VMtX93yIYIGFC20GCsMYZe
18 | ZpTedxpxpjqom2dOuOUaDQgrZcGF3FVbFqTEpPtOnsKXYaCg7FJvUjxv7FIuix5H
19 | 7JO6DALoJ792pfG2wwS2PvDiGFxMfGnNvb3aLnB/s6wTyWBpDYRdwlB5nj37KPk6
20 | kpFJj3N9x5BD1oTdmQqeVuacjoiemIulkc33P28tGl6Datth4WpE0LwmrwREQ1NW
21 | ixi2j1Ti3mjYkyqGVY8XphWKEIIWmheqLnYCXRXhbxZ4E+FGg81ZYG8TKYC/IjzV
22 | 8p0rLnAI1qS7wdwv5UJ9vQJt6KcxdHHZsUlpIfaJC6N5DvAL/qUY8DoIymgz
23 | -----END CERTIFICATE-----
24 |
--------------------------------------------------------------------------------
/test/key/idp/nocrypt.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIIEpQIBAAKCAQEA4NmxaEJ77IbQ9qVA9NSgPvKSjkxNYwJHEnyFKbaTuYbcSD9j
3 | a/QQF0KZPDuIMJ69GpSZuYWersxE7JXh6uInOHQppsB1l/v+TqSiCGy3dlS1Y7DO
4 | yHLGQG1YPAaYGlAZMawrEnwzWOzdpKo1FcFPg4FYz3DYaW3X7y3LfRGFi/elIX78
5 | ccsfsBz68tIgCWiRoVbfhFZNwn/ysAO5FaVeKHgZ+ci7Rb+dybmdNJomJEC+vd0Y
6 | NE7+SGJegl1ts6Pt0c9QvFUZsf0hs8rvpMLAtsXuKQgyw+i9VtOunIvq+xtVQp4S
7 | X/kYqmlPCn0MsA56hJikJiSQORgq71NFCMXTYwIDAQABAoIBADOGbzr/ETrQYg5D
8 | LDFukBIcsCzfm1Q272ZzFmjKp+t51fzQWc4hLZbG8ip1Ue4iUh9HMjrrPcO8l4bH
9 | ie+zR12OcQT/UXM0kcAfxem8UAZTvwVLPPd+JaQZ6oBG2pAdDsjtNSmVQIb+MIRN
10 | ZMDJfZkbCOjwaQcv3q22hszwOPQrq5nW82ScuZ8k9oAyz5igomGX0jQBkQM8KMzm
11 | cXTJXBVCc/wEjHEjV8Gx1hBaDuIqY0rt6/5R4zLtwgSvT5LvUOIlzFMKACs7RFA2
12 | pkhfUx786IRbDXnGRPIqlJgYglcQjEh/815jTdsjJ6VDBBtYcEiF4vn0eWl9tp4S
13 | NxzwWoECgYEA/BG+bAMnMuvjtlOnrZF7l7mCMmKvQzhPr8+8zPtuiQKgn0vHtw4z
14 | 7u0TcaP35sa7WwZjcwUtSX4Vs1VrlBfNaHUAEgJ6PAxVPMIB537ttxbPER1l4vE8
15 | ZvGRGYsps+VNfu7XJnaFtq81mbpGsr1qRmaN+OjDs51UbkKd5esPDCECgYEA5FtK
16 | ps3kfe8rkaacFKfbD3tyj9CeZf8A1ovgiWJFi7PCY46Yg+66Vx/aKkzj2rh993Nn
17 | 74BgPWszDJHwG15sHyDlxaZHxUAAeWRJClirsS8MuaLOooReA9D3U82w/s5MDviT
18 | aP3CIc/RtpoLk31arCyqF/aT6K2B79EjmzOKzwMCgYEAjpY68T6XXeax2OFZaIVz
19 | NFBrpbTND2k7KmiIlCtmS3qBAZsMTjBqkCzrYs0t3g1szgC/IME87OW1wMwBHrSY
20 | LQ6CC637Fxyi2suj6B+UuIzedP/8MnPjhxf+zEQ8QtbjD3prmgZRfRV/bIZCl7kt
21 | 9MTuam7AxUmqCPUF/JkK2gECgYEA4Y8DF+w7i+EYag/mD8kVah+Hs2Jfc2QEkecs
22 | bMdy5mEy21/Yakj+Kly+BBZa4oplcmy99yYY6dHfZMUqI/6KUd0O2MI8Fiv3y/Aw
23 | 7VVUkfllWl/kN0cEDkT0aAS+lZF0Mz15bbVpcjhybymN0at6SqL7iBv5UVVBCX7M
24 | 6tpoe70CgYEA5TAEHT77eF8falYD7nYKnPUinfx2p6a3J0UAWI33W3CE6K4MTMSN
25 | Q2AxLj1ImFrmDMiPIFa9GeP9DrE/6eeKVI4q0u7kF58XkCammgIJ9GzyCBWfNpVR
26 | rR2ZD+OyCGiqsrL4PqtHxTwRiYymLOuVKvXxZYlDDPN/RlkBINUX0qk=
27 | -----END RSA PRIVATE KEY-----
28 |
--------------------------------------------------------------------------------
/test/key/idp/privkey.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | Proc-Type: 4,ENCRYPTED
3 | DEK-Info: DES-EDE3-CBC,116B0EBB2F2F0A9D
4 |
5 | HMmUsJPVPTsq1e06yrrskfinY21OOHosfRzibLueBg9ByFFZ7+/oW/DKy1GcDeBc
6 | ycL+3gylIoGUYuZ+DPC11ArjdxFqLFnHJb96rwy5h4sTP0lE+qHy+06AwsowUgp3
7 | pdD2unPFeydpu5h/dqgoDzkGSucz0Ty/spHXNBvns0vJO18B7XlzXUtfH5aHco22
8 | DyVY6FrJwMts9E4Rzs9JsxJJ7mi/6+Qsc0rOr8/6KKsRo1sKD6cvQIQ05dEvGrE9
9 | /2fubHkRTl+zBqOVyQvC6iUtocwxlMP4KfmyYrD1wlQAnP/+smq2G+xf7uGc4X4P
10 | 8q0jEy2P9n5ASlwZ3XCS9hZgp8VRAcXWOYjzzNouQp3NEP9d5D3wN4aFKa/JW6pk
11 | a6VwraEweuyJqvZ7nnam1emW0ge0z7hJabR0+j0PnUxFIwkI5jO3HI5UiuUzuQFe
12 | 2bTLA3XnJ7QD08ZKom0rmApbFrmm9BWBRTmt46NlQDy49VODPY4gFuQ/mpaFjaBy
13 | fSNJaOSS/MDuAdPabNEh3l+yCGKtHIbPVIms76PxYf6o0VVxW96/Q25hrvyOJCxn
14 | dVQyyJbQ1jGenu4ViDNrW9ZQfw4aJCPpY7lUQd09BGz2NMKgkrSl8bKSan4lvlF3
15 | ok8BjfIw+pIrTyesPU5tF0YudDxwi8fbIG70iwrpsSt2wVIMa+Nz2lwFT1dV8be7
16 | NARkkkhLWJYAsxsyVfdl+ucNSqhvo8xLITuG8CZnzKf0T2HMKnMNegFx/ipfM7ff
17 | Mx5CjayN5Oy99MWsagYEutUGzCGPAuVpqYpJuuYa3lWbFk2XWihWkAiUwgRqIluE
18 | M6LpO8l3LVXVjN1+6bK1GZpbfLay+E6vy4W38XMuXZSNpyhy6e+XggTPH2xbbwoi
19 | OcAzcojhMaxVGpxm/aXyRxg9zBdrQjtqM/aCN91ri55bvOKxELVi+D/VcZKpd2CR
20 | X/vWcqoGaK/6+vlPWMZSHCJkPa4KBT0aUcnEdeFWx2nmrwdrHvETzCYLAzVBSECV
21 | ZoYH0xTkFr/RI2AOAzx701LSuYbnPoCq+w7TXtjPaooZdYVVgrYuI+j4JOlseFS7
22 | 1c9iRiJVPBfnpUNIZdHLw19+k81IJ/FmumiuDhfLS5pwQmtuXkO3DWZDa3UPlV8e
23 | 6dmZeP1XGwRLL9VpOKx7NCqZM+CdEt87CXpFFWXdw8tL+3K/2r8w4lHIzBKaVPSS
24 | 5uFqXc1vzfP6Qeov31IjeLPE1pWTHNqRPdmvt9Scq9tKS3o18wmLBxOVinOE0cxQ
25 | oddzPd0z5NxNYVayqZORwDdVv6CVXKnrvBSnOFFslZqv1G8/diE5BXxeaAPEMcZE
26 | 3lD7MzdoEHK5oL2MXofLWZbNtMkOZLaLqY80zKT1UG3Gs8U44d44aLXO1dBL0HGX
27 | dNfNUaH+IGZf2ccS6OR1RhwIazDZ8qk0XeUwQV588adwC3FUvscVA3eHZa95z4kX
28 | xvHg+ylzRtKRfpSPzB2IVwgV9/rsOg0OmvwhV8+5IQpdcFr+hf2Bn6AVn6H9aX8A
29 | JjycN6KMcHaFa0EUqagGm9tsQLmf/MGCj8sy9am1IbRmFCz5lB5A7P/YLPM2Csjg
30 | -----END RSA PRIVATE KEY-----
31 |
--------------------------------------------------------------------------------
/test/key/idp/privkey2.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIIJKQIBAAKCAgEA0BvmmwHnlo8LDmbeUpHDXMP10iXI0sicpBGxFNooLhK0bjiM
3 | gX4I9KdVFQb997i9ooHmCU9zkl5ko7zDvCr6rWDdrSQI6BY4IRq/DWyBGY2EuLpD
4 | GVG8MXdm0cnA/TjCPYOOAFAdbH0NFMhcMxDrHlt5XFtRZ4XIswPE4CNBjeDaXVa7
5 | jZaYKFnT98PksobatK1nm2PIPxxha7hCp/FcG1G5TmXT+4zVV7HdWlDEnKbjGtJI
6 | c81zwzfkNK8Je/XzuMnIUnigABEXT1wNVHw324fVu6XGAT9AAV3fdQX/WpKZZm21
7 | TiLDW7kSHFUu1ry8Aq+tdybifhLRg3FJK0qW7kbw1vOQ0ERwRrqCpXEhvoph0LR6
8 | kcDMDHPD+eISBAb2hVtEX8D383RTXvMAEbZryHl/OIsKuWHsteS8ta3aKYu7doO6
9 | shewvwfYGd7Sf4Dyqdja3QhhQXGoZfdy4+ellpiNIzR5+/u2N8eorCdyk0VyJYkq
10 | wMIiu/+1HszpVs7NZPJhkFmUw9wBhirtXAVcLgvq4eMJC7A3h388Wr218VRKJPaf
11 | 9T9vDOBoh30tDzhNx5eEU90OgImFp5hWMmfrJmPe0oD8AeLUzWBYwuvvXfwZZTaE
12 | G/MLD46qemQ59TnmOuvIafmQHBNdwBXYkwTFa3HRBAgjy8YNZBZOcGXR6xsCAwEA
13 | AQKCAgBLkOYCgQWLuPMlzpqJ1t3ecFVxckDisO+X78iiLrkKScZ0g1oZpx8vXxdY
14 | 5EoRymYpfQt/c/cePeJDRka4q86MaDD2LrCBPZgyBRk8kZqrIaUAwrmclv5D4/xU
15 | zvKhwBtf5MYKPQ0CGMJIOpyn+ku1oTeHHq2Hbp+6yPKTBJpIH06LN/QwbG9hr4R1
16 | Yg9H+AmwM4r8dJYAvJhvWd/yRYTRcrJb0kPQAopxJmee5NcPntW2JocibYbMax4V
17 | Nz21YlCWV8bCk4RdodcZ/O3mMJjDwSYN1hr41vOxy1lZj8zyIWtMMyfzcFIJm0EF
18 | QrUYSj3mp83QBzGU39Zt6RPNgW8d/CMrBRoGK4PnBqOaL8vxlc3zFh9imveXEhk+
19 | bYhvC15w3+i94IX/7zEv8Bkx7iPUTvKh1RjEEDqYikuLmW9KEmF01u26BSg1Y2uM
20 | 6ZLlzhw9cKf8xok63jdE0o8XT+VRd8UzcdCnQ7k5NUkm4dLYhpNxMTCsSptBwpTV
21 | c7XwHOdMFopkQi8XMkZlJqNsXQy57BcDgEEfLPRsfd93jGOn5zIKwj5zC1DXDrDX
22 | uker1yDxkLxeQdFPQwvE3m1Xpb2lvR1a29474qE6bxsrp0ADajLaebnB+QprWRX3
23 | iBLMJau1YcI0HHpncGtTTzmmkuTNbwd7CgLODMQ35V2kkIbPGQKCAQEA/B+1oPhb
24 | bh0jZGTL3MoHQTjJNwmd2frv4ijxB683VJbhw0kbHbitnYsv/cCdgCTsHcxOGYQu
25 | D6feVTPtNoJxYZziXwFI0xvrgAMQHWPHDfESs3vCZtJfyWSVqNf7FGfbasxxe0D1
26 | 3qbKLVJSctdMezc1+o7grJmfd+mBNU3p9iGUmWNc/qBClsB4tlrsNfoyRiJwcOsY
27 | HZKXNeudawIBlq+Lysf1r7waLtjMg9flshzrkvOlls6xfV0z9MT6XvSnqKqUNiMI
28 | sgJGnc2SWbuYa/pVWNMyFdt40aq7i+ybkm+ddFJFEYD7X37yI9gZZQLsltik8D1/
29 | fICX37mGrbk5vwKCAQEA007192RB31QA6rSTzQ48rvcKIreBH9dRf/LrQtrkUp1M
30 | oAAGeiH5iypCdWREL6yXVCXMmAgTUdpgP6hj5J7B7N7TkQP5HBvL+NIN/iaY2pob
31 | SI4hwf4OuiHD6oRMWuuzOlT8enNk4mo+ue29uv/g3gvR2S6zkOCDc2G3gycSfpfF
32 | vgjU0lF9dVhhn3emcXInDXkDU9aXXjy+8tXDo6xvbMV9Vo9nCrFMT1hYbrdIETxl
33 | GyrvVbDvel6xV765FT60v37Q0e4zbyPoS8iN0yDXg+XS8GrqrEnCDc6hUJG5OFwb
34 | kBnbCX0Eo0YXd85YuKYfwmwRwFK8Ct98FXl+EL8NpQKCAQA4o9sG7aSEqVEhJa/S
35 | yyQ0F9DEZ4mpxcEMWsxDQK66dycC2zKXS7zdLr66UAJSHnlY/GPzQYmjhL/i/kZl
36 | P4q/NiJ4224D1zrhyE5fe+HlFOpxnfT/anWQZeNlShgi7m4RoRpBaUeTHH9BDURu
37 | fkW1TKL4xg5dWCnGI5QeaIGOBN9AUl066r/q5BR6SxTTz4Bp1yTRiU8inaMQvvzf
38 | ZFT9CDTsel2MfEKZkaToXaFBkVOu8MObjJW9Jyob7ACfQnFD6AZh3x799prsqpkd
39 | RZKpd1SjHtcap/KNj8CQX7hXfnGuBylzFDnkqz00pkCWO8Dw5nyvZ/FzA+SaozBJ
40 | aNo7AoIBAQCGlyGlzK8EX44h8Ji/oFTYoLNM/5L4Q/4+P+zHbYLGeDiJJNr7Sc6X
41 | bHheK1oe/5B34YeaQnKDzVNG2Kufv9sHU7pwAJbX54CY4LpW6iCsBEJiiV1JIdgh
42 | iEYwhsnXk49aFS2nlP5qFIAVjy8s/7Qr2l10NwHawpYXlOL9X5KxHVyvORLNT2hY
43 | qM2tc9mJIstrEmwjJ2jMdmatZ6iwBLIIFxZJXxejwOA5Ha1d/9GgYNaJYmSFMSin
44 | yc6tc+aReJpJ6q15OX57SOS5+GkVVDLRaT5dMcx9ppE6mCU5m0fddRV9SGqydXXR
45 | xWBHSCBMpEtQW+NGm6v4RPbU+shoRDidAoIBAQCfNnCjLvLNTfeJ4blQOdGMOiDr
46 | TEyxtF9tAgkzbQefBr6HBVwzfPdywUtf3ZxVxKIsnpYmbGJIKp525/Wtvme7qjp4
47 | CsdyFO6ZFLEeI8KGKiewGEv5YzvQIpVqoMZ6ucY/WiSvwHSvZuyLZVLHOLGcZRLJ
48 | 49jbfhsvrJqWVDC2CmX2oAuH3GF+LUFhkM36zD1d0FrpaZwL2acWErk/N0CNhnNp
49 | H/08579O5MmSjlWh8Eco2wVD1z/A+LSC0YN+04ZrurB7wAebGCsOoEO7M53aan77
50 | gP2nLQ/cnYHiPrmUlL5s7EDhKnvpNY1W2ViEydwywvg9m4mxOA1sjrYpoNRg
51 | -----END RSA PRIVATE KEY-----
52 |
--------------------------------------------------------------------------------
/test/key/keypass.txt:
--------------------------------------------------------------------------------
1 | Private Key Phrase (SP) - signature
2 | VHOSp5RUiBcrsjrcAuXFwU1NKCkGA8px
3 |
4 | Private Key Phrase (SP) - encryption
5 | BXFNKpxrsjrCkGA8cAu5wUVHOSpci1RU
6 |
7 | Private Key Phrase (IDP) - signature
8 | q9ALNhGT5EhfcRmp8Pg7e9zTQeP2x1bW
9 |
10 | Private Key Phrase (IDP) - encryption
11 | g7hGcRmp8PxT5QeP2q9Ehf1bWe9zTALN
12 |
--------------------------------------------------------------------------------
/test/key/sp/cert.cer:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIDozCCAougAwIBAgIJAKNsmL8QbfpwMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNV
3 | BAYTAkhLMRIwEAYDVQQIDAlIb25nIEtvbmcxCzAJBgNVBAcMAkhLMRMwEQYDVQQK
4 | DApub2RlLXNhbWwyMSMwIQYJKoZIhvcNAQkBFhRub2RlLnNhbWwyQGdtYWlsLmNv
5 | bTAeFw0xNTA3MDUxNzU2NDdaFw0xODA3MDQxNzU2NDdaMGgxCzAJBgNVBAYTAkhL
6 | MRIwEAYDVQQIDAlIb25nIEtvbmcxCzAJBgNVBAcMAkhLMRMwEQYDVQQKDApub2Rl
7 | LXNhbWwyMSMwIQYJKoZIhvcNAQkBFhRub2RlLnNhbWwyQGdtYWlsLmNvbTCCASIw
8 | DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMQJAB8JrsLQbUuJa8akzLqO1EZq
9 | ClS0tQp+w+5wgufp07WwGn/shma8dcQNj1dbjszI5HBeVFjOKIxlfjmNB9ovhQPs
10 | tBjP/UPQYp1Ip2IoHCYX9HDgMz3xyXKbHthUzZaECz+p+7WtgwhczRkBLDOm2k15
11 | qhPYGPw0vH2zbVRGWUBS9dy2Mp3tqlVbP0xZ9CDNkhCJkV9SMNfoCVW/VYPqK2QB
12 | o7ki4obm5x5ixFQSSHsKbVARVzyQH5iNjFe1TdAp3rDwrE5Lc1NQlQaxR5Gnb2NZ
13 | ApDORRZIVlNv2WUdi9QvM0yCzjQ90jP0OAogHhRYaxg0/vgNEye46h+PiY0CAwEA
14 | AaNQME4wHQYDVR0OBBYEFEVkjcLAITndky090Ay74QqCmQKIMB8GA1UdIwQYMBaA
15 | FEVkjcLAITndky090Ay74QqCmQKIMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEL
16 | BQADggEBAG4lYX3KQXenez4LpDnZhcFBEZi9YstUKPF5EKd+WplpVbcTQc1A3/Z+
17 | uHRmyV8h+pQzeF6Liob37G87YpacPplJI66cf2Rj7j8hSBNbdr+66E2qpcEhAF1i
18 | JmzBNyhb/ydlEuVpn8/EsoP+HvBeiDl5gon3562MzZIgV/pLdTfxHyW6hzAQhjGq
19 | 2UhcvR+gXNVJvHP2eS4jlHnJkB9bfo0kvf87Q+D6XKX3q5c3mO8tqW6UpqHSC+uL
20 | EpzZiNLeuFa4TUIhgBgjDjlRrNDKu8ndancSn3yBHYnqJ2t9cR+coFnnjYABQpNr
21 | vk4mtmXY8SXoBzYG9Y+lqeAun6+0YyE=
22 | -----END CERTIFICATE-----
23 |
--------------------------------------------------------------------------------
/test/key/sp/encryptKey.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | Proc-Type: 4,ENCRYPTED
3 | DEK-Info: DES-EDE3-CBC,860FDB9F3BE14699
4 |
5 | bMpTdWaAEqNciUFQhHYNv1F9N12aqOQd6cFbMozfRnNR19HW6QIPDmEOPSSCaaRy
6 | QCnJhbpcSnaz9pvI7EzeJzdykDmR8Boos+0NSK9qIX0buBO55mfPr7hjx7bLFEVl
7 | kkHk+k9F1rLyjyAGJrVoTNoWjyuMOFUCWR7ZxoYticwM/sL+Rbhn1FsfdkdfhFW0
8 | 08OHTouRK33Aifx0A3MWxR0ILvw49E6urtbbIrskEzKzfWQug8gY1TJhI3sbsMsI
9 | 1bS5Vg88TvilFFBGn0Yv6GEJjgOrsrKDGKtYGhuBfK4fd4rwnQKKvC6gTKeNXIfV
10 | 7Qm1R20LUJXC8zv35pdKoVk+NdS/MGNXJRFgO3Kkp01aVf3n1oo2+AllS02AYyWt
11 | 1svHecsRwbibXip8gSQsOtDdpqQrEDyqZlFHXEw/IcJE9vQWEJmpHD5GFhbKtttp
12 | E0B3ZtNl6YcyUz0rSf9zjuMx/wReWdRb6H2WoIqoRS7vAUONDRPt7wvfjtLlDRVi
13 | bc2RTN8yce/57lGnA1n8bxPV5+9VxCJOEipV3io/nrj+uNO8i/0rUpkKdZy8wy2C
14 | Rksoxq4TxwegONz1HQcJVpJu0iBdu7B+BXVjxQQScvMQlOTbua8k+YdaCeZAb83j
15 | JVX89/PFy+Xj7eGyzzBTqz7dV0Xkxq9mpiMYUCoyNL5Iq1jD9Xb5TzVW1Gbh8zCZ
16 | YXjcZEQKeartaBC4/fRWyxqK3gJRX4SJkl4gYMQrPS2pbTzVCO+WLxSwIh3dOZpo
17 | eErXLSrylIv9cE2Xrs0McXAR+hfGrqgtILBWwgbh2NhmUiFfLwUTUxU51eu7QZ2T
18 | V1VFBX0QTmn2kM0JLSSC96mDUzbs6qfURUaXbuffF5cqdUjXgtzZj5SFEbIv4UFS
19 | 0DAS+6i/jTGSz7aAp/uofOxhYkCqK/s2Cex2jQbDpcKXKiWzPdULOCjAh3fdCAp0
20 | 3ua3fdAI7H8PslSDiPFrcY78OxZaWXzazEiun77WKbzrMloLMP5dpCPlUCOqxbZ0
21 | ykSuo0M7p/UPY34yi3AMHS9grvQQ1DykMPoqKKEheI6nUGcQ1AFcdr307ILWRsPO
22 | T6gHOLXZaR4+UEeYfkTKsjrMUhozx7JIyuLgTXA9TWC+tZ9WZpbJ7i3bpQ+RNwX2
23 | AxQSwc9ZOcNxg8YCbGlJgJHnRVhA202kNT5ORplcRKqaOaO9LK7491gaaShjaspg
24 | 4THDnH+HHFORmbgwyO9P74wuw+n6tI40Ia3qzRLVz6sJBQMtLEN+cvNoNi3KYkNj
25 | GJM1iWfSz6PjrEGxbzQZKoFPPiZrVRnVfPhBNyT2OZj+TJii9CaukhmkkA2/AJmS
26 | 5XoO3GNIaqOGYV9HLyh1++cn3NhjgFYe/Q3ORCTIg2Ltd8Qr6mYe0LcONQFgiv4c
27 | AUOZtOq05fJDXE74R1JjYHPaQF6uZEbTF98jN9QZIfCEvDdv1nC83MvSwATi0j5S
28 | LvdU/MSPaZ0VKzPc4JPwv72dveEPME6QyswKx9izioJVrQJr36YtmrhDlKR1WBny
29 | ISbutnQPUN5fsaIsgKDIV3T7n6519t6brobcW5bdigmf5ebFeZJ16/lYy6V77UM5
30 | -----END RSA PRIVATE KEY-----
31 |
--------------------------------------------------------------------------------
/test/key/sp/encryptionCert.cer:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIID7TCCAtWgAwIBAgIJANSq1uUtXl4DMA0GCSqGSIb3DQEBCwUAMFcxCzAJBgNV
3 | BAYTAkhLMRIwEAYDVQQIEwlIb25nIEtvbmcxFjAUBgNVBAoTDWV4cHJlc3Mtc2Ft
4 | bDIxDDAKBgNVBAsTA2RldjEOMAwGA1UEAxMFZXNhbWwwHhcNMTUxMDAzMDM0ODA2
5 | WhcNMTgxMDAyMDM0ODA2WjBXMQswCQYDVQQGEwJISzESMBAGA1UECBMJSG9uZyBL
6 | b25nMRYwFAYDVQQKEw1leHByZXNzLXNhbWwyMQwwCgYDVQQLEwNkZXYxDjAMBgNV
7 | BAMTBWVzYW1sMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyx/yIgvJ
8 | wfOCwMTNjL4Fslr21ky4O/uzxp0Y8wpHk9jk8Afcj3plQCr5X8dPKG2Rz4EIh//n
9 | QQL9tq2InaUdRwJkS9SeuuAcJG7DN/KDUtfrh4+cO2lZ4h7cQIdjpbBgpGEMhGy1
10 | wwpwHJsadoBuX0PKyT4O4oHkj1gwWO14qYnK4biviNBqmjGjmN+py+lUcACsQt22
11 | abA4s8Xjm/tlvnkgNRE3H44ICvSr8m5MVhyYGoAUe7Qprn2BcsMXd9mrlZ5hEdal
12 | NUDRbKb+W7mrKEkKFCbE3wi/Ns2bc4fbNXvwcZoF3/TPzl936u2eivTQESjCLsym
13 | IqdYHwRiVLifWQIDAQABo4G7MIG4MB0GA1UdDgQWBBSdBiMAVhKrjzd72sncR13i
14 | mevq/DCBiAYDVR0jBIGAMH6AFJ0GIwBWEquPN3vaydxHXeKZ6+r8oVukWTBXMQsw
15 | CQYDVQQGEwJISzESMBAGA1UECBMJSG9uZyBLb25nMRYwFAYDVQQKEw1leHByZXNz
16 | LXNhbWwyMQwwCgYDVQQLEwNkZXYxDjAMBgNVBAMTBWVzYW1sggkA1KrW5S1eXgMw
17 | DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEARi25PJOR+x0ytYCmfXwG
18 | 5LSXKNHx5BD6G+nBgXm1/DMMJ9ZY34FYMF3gDUu+NmQoVegqARTxetQcCICpAPdK
19 | nK0yQb6MXdj3VfQnEA+4hVGFmqnHTK90g0BudEmp1fWKBjJYpLd0oncVwJQJDK5O
20 | fS7fMUftN6/Kg6/fDuJMCNIECfKRE8tiXz2Ht924MjedKlH0+qoV1F2Fy5as+QRb
21 | j/QfrPTrZrfqhP04mavTPL2bdW6+ykeQWN3zMQtJA8kt2LI0y0CIGhFjLbqAceq+
22 | gDkp4drj7/Yw8qaqmxl6GP8w3GbfLu6mXCjCLCGgsATktvWq9dRfBuapaIpNDrv0
23 | NA==
24 | -----END CERTIFICATE-----
25 |
--------------------------------------------------------------------------------
/test/key/sp/knownGoodCert.cer:
--------------------------------------------------------------------------------
1 | MIIDozCCAougAwIBAgIJAKNsmL8QbfpwMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNVBAYTAkhLMRIwEAYDVQQIDAlIb25nIEtvbmcxCzAJBgNVBAcMAkhLMRMwEQYDVQQKDApub2RlLXNhbWwyMSMwIQYJKoZIhvcNAQkBFhRub2RlLnNhbWwyQGdtYWlsLmNvbTAeFw0xNTA3MDUxNzU2NDdaFw0xODA3MDQxNzU2NDdaMGgxCzAJBgNVBAYTAkhLMRIwEAYDVQQIDAlIb25nIEtvbmcxCzAJBgNVBAcMAkhLMRMwEQYDVQQKDApub2RlLXNhbWwyMSMwIQYJKoZIhvcNAQkBFhRub2RlLnNhbWwyQGdtYWlsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMQJAB8JrsLQbUuJa8akzLqO1EZqClS0tQp+w+5wgufp07WwGn/shma8dcQNj1dbjszI5HBeVFjOKIxlfjmNB9ovhQPstBjP/UPQYp1Ip2IoHCYX9HDgMz3xyXKbHthUzZaECz+p+7WtgwhczRkBLDOm2k15qhPYGPw0vH2zbVRGWUBS9dy2Mp3tqlVbP0xZ9CDNkhCJkV9SMNfoCVW/VYPqK2QBo7ki4obm5x5ixFQSSHsKbVARVzyQH5iNjFe1TdAp3rDwrE5Lc1NQlQaxR5Gnb2NZApDORRZIVlNv2WUdi9QvM0yCzjQ90jP0OAogHhRYaxg0/vgNEye46h+PiY0CAwEAAaNQME4wHQYDVR0OBBYEFEVkjcLAITndky090Ay74QqCmQKIMB8GA1UdIwQYMBaAFEVkjcLAITndky090Ay74QqCmQKIMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAG4lYX3KQXenez4LpDnZhcFBEZi9YstUKPF5EKd+WplpVbcTQc1A3/Z+uHRmyV8h+pQzeF6Liob37G87YpacPplJI66cf2Rj7j8hSBNbdr+66E2qpcEhAF1iJmzBNyhb/ydlEuVpn8/EsoP+HvBeiDl5gon3562MzZIgV/pLdTfxHyW6hzAQhjGq2UhcvR+gXNVJvHP2eS4jlHnJkB9bfo0kvf87Q+D6XKX3q5c3mO8tqW6UpqHSC+uLEpzZiNLeuFa4TUIhgBgjDjlRrNDKu8ndancSn3yBHYnqJ2t9cR+coFnnjYABQpNrvk4mtmXY8SXoBzYG9Y+lqeAun6+0YyE=
2 |
--------------------------------------------------------------------------------
/test/key/sp/knownGoodEncryptKey.pem:
--------------------------------------------------------------------------------
1 | Proc-Type:4,ENCRYPTEDDEK-Info:DES-EDE3-CBC,860FDB9F3BE14699bMpTdWaAEqNciUFQhHYNv1F9N12aqOQd6cFbMozfRnNR19HW6QIPDmEOPSSCaaRyQCnJhbpcSnaz9pvI7EzeJzdykDmR8Boos+0NSK9qIX0buBO55mfPr7hjx7bLFEVlkkHk+k9F1rLyjyAGJrVoTNoWjyuMOFUCWR7ZxoYticwM/sL+Rbhn1FsfdkdfhFW008OHTouRK33Aifx0A3MWxR0ILvw49E6urtbbIrskEzKzfWQug8gY1TJhI3sbsMsI1bS5Vg88TvilFFBGn0Yv6GEJjgOrsrKDGKtYGhuBfK4fd4rwnQKKvC6gTKeNXIfV7Qm1R20LUJXC8zv35pdKoVk+NdS/MGNXJRFgO3Kkp01aVf3n1oo2+AllS02AYyWt1svHecsRwbibXip8gSQsOtDdpqQrEDyqZlFHXEw/IcJE9vQWEJmpHD5GFhbKtttpE0B3ZtNl6YcyUz0rSf9zjuMx/wReWdRb6H2WoIqoRS7vAUONDRPt7wvfjtLlDRVibc2RTN8yce/57lGnA1n8bxPV5+9VxCJOEipV3io/nrj+uNO8i/0rUpkKdZy8wy2CRksoxq4TxwegONz1HQcJVpJu0iBdu7B+BXVjxQQScvMQlOTbua8k+YdaCeZAb83jJVX89/PFy+Xj7eGyzzBTqz7dV0Xkxq9mpiMYUCoyNL5Iq1jD9Xb5TzVW1Gbh8zCZYXjcZEQKeartaBC4/fRWyxqK3gJRX4SJkl4gYMQrPS2pbTzVCO+WLxSwIh3dOZpoeErXLSrylIv9cE2Xrs0McXAR+hfGrqgtILBWwgbh2NhmUiFfLwUTUxU51eu7QZ2TV1VFBX0QTmn2kM0JLSSC96mDUzbs6qfURUaXbuffF5cqdUjXgtzZj5SFEbIv4UFS0DAS+6i/jTGSz7aAp/uofOxhYkCqK/s2Cex2jQbDpcKXKiWzPdULOCjAh3fdCAp03ua3fdAI7H8PslSDiPFrcY78OxZaWXzazEiun77WKbzrMloLMP5dpCPlUCOqxbZ0ykSuo0M7p/UPY34yi3AMHS9grvQQ1DykMPoqKKEheI6nUGcQ1AFcdr307ILWRsPOT6gHOLXZaR4+UEeYfkTKsjrMUhozx7JIyuLgTXA9TWC+tZ9WZpbJ7i3bpQ+RNwX2AxQSwc9ZOcNxg8YCbGlJgJHnRVhA202kNT5ORplcRKqaOaO9LK7491gaaShjaspg4THDnH+HHFORmbgwyO9P74wuw+n6tI40Ia3qzRLVz6sJBQMtLEN+cvNoNi3KYkNjGJM1iWfSz6PjrEGxbzQZKoFPPiZrVRnVfPhBNyT2OZj+TJii9CaukhmkkA2/AJmS5XoO3GNIaqOGYV9HLyh1++cn3NhjgFYe/Q3ORCTIg2Ltd8Qr6mYe0LcONQFgiv4cAUOZtOq05fJDXE74R1JjYHPaQF6uZEbTF98jN9QZIfCEvDdv1nC83MvSwATi0j5SLvdU/MSPaZ0VKzPc4JPwv72dveEPME6QyswKx9izioJVrQJr36YtmrhDlKR1WBnyISbutnQPUN5fsaIsgKDIV3T7n6519t6brobcW5bdigmf5ebFeZJ16/lYy6V77UM5
2 |
--------------------------------------------------------------------------------
/test/key/sp/privkey.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | Proc-Type: 4,ENCRYPTED
3 | DEK-Info: DES-EDE3-CBC,9C86371F0420A091
4 |
5 | 77TqgiK/IYRgO5w3ZMyV81/gk0zN5wPTGWxoztNFjQKXCySFnrL30kUqlGituBxX
6 | VgxwXbkoYMrd5MoDZKL5EJuf0H59hq92O0+3uwJA8QyZjOm4brQcjXKmIrkvihgs
7 | FvpaJiGzp6kS/O7vFBDNTQWr9yY9Y3FBPcmOUWufpRp4Q5nhpSlqnMmIqZyWQUL/
8 | YJSJETtzJVsk38lCqIxxDT3LtbGySahj0jRuRqspAZQeLTpnJqzNMC4vnJew9luC
9 | R+UffrX7gVsnwOhNtyRzYaMsLnbRfXT8Jqx2gRHg36GxkOVgyU7e62nk9CzeC0WA
10 | kHHCNVqqivRx9/EC0mQkkRgRzo3BZWp0o671sUsGTy57JhktiGfTnWMrl7ZfhAza
11 | SZnjyTwuI1bTQipIkNI3aJBTP/o/gNUE1sj5D5FZlFdpq5ks2Vxww3GNx1FRrvWd
12 | 98z5CNt78ZR0ihLmdz/EakEBKBUteQu/5zPLUlwmGuou4wPuEHG2BsjGzb/d5Zfc
13 | ElIjUV+yrMmGHvBfPyPnDUrCUyLn18S1NZiCMCdN5PqCybjhk8oMPYZhWBqp8Ymr
14 | yHIC7BCnTJhIvgQZR6M68NwVv0aBBgH/I/DB0jADo6/B5Eajwus9i6zSv8QIbqhw
15 | fusKtI04vxc91aP0GWRr0J/O4mkxXYNPfa3a/I7sGTXGl0k0CygckE3fLXRy/WEk
16 | ikZt4UHqg5ZQ8vc5NSAM5f5Yx/72CU1I6ehFtxHsyE5yndpZXWp2X2S4l31e8fLs
17 | ddOoybroJgbyLrh7JT3Yac3XOEsKATWIvqU+hNYq6KwqLWev9jInHVgjzfyOKbmF
18 | hkrzDDHaKULYZuTsUq5mLc1SzSu98lXYfXp1WE4XsH0X0VicPzf8ZH4Kutuig0VG
19 | 5Kg9HB/Cin65VMm0ffEiTraO6johIlwFGRrtAs38ONKgsPCQUv7ee9SEGOHViNZq
20 | NpWPr1KOzbI4wEB1ueKoZuEQ0a+tzfJgszJrM48bM82J6iEjN/PSOTsdTKJq9e47
21 | dlUp+tqQsvGkbBOIOt5OOpkr8Z+8qbEd21ojF9Q0p0T4WMThRP6YBRKvt8mmFwRs
22 | DjEhMiPa4L70Eqldfu2lWdI6ietfHrK97WXwQO1gF73LOnA+EdMXNxr1iLd0Tdke
23 | z6fUSw3hKZL+I7nX6O40+KgkhXVSZOsRz5CEvo2iChIUrYGEGDl94K/ofqGu71Y+
24 | G8KBvbha6EC7xcUrTYP5Gek5wsrw7cGgDZJjMsyXYFBZjQO1N6g9fncLmc5pB5Ix
25 | W3gLfQS/My4daWNTvrYOgfA08J4M4ZWd0v5TglxOSV78psG4J4slppDySNFB2d/3
26 | 7JiwWVm5SMk0StLWwb2azmTvBoinnrZJzPnPlOytxvE5uGJ/i0WAik7C99YgVJkS
27 | 9hO3FJGasrOnHeiOvMZEdRuIVspKz9iMFx7hWHpVHTTyjwceEpaiEkhmqLM9QkKh
28 | kCZqeWyVsKBIc0sse+CKNK8ik9eTeUlCklGMV1Q4kKjR6uuHUOLyjk/xhqslV4TS
29 | jnnjCjsK5YzTa4hmbHhPZIW262KoFV9TqxYKkhP5ab7AXRSakrdrY2cwACWN4AMT
30 | -----END RSA PRIVATE KEY-----
31 |
--------------------------------------------------------------------------------
/test/misc/attack_response_signed.xml:
--------------------------------------------------------------------------------
1 | evil@evil.comhttps://idp.example.com/metadatahttps://idp.example.com/metadata_ce3d2948b4cf20146dee0a0b3dd6f69b6cf86f62d7https://sp.example.com/metadataurn:oasis:names:tc:SAML:2.0:ac:classes:Passwordtesttest@example.comusersexamplerole1sZOR3aMpVBn1CoSmP674OQfCcyg=h7Dk6GTh4MrNNx8b8Or12SeGsAGBM/ILd7Jgz/RuqR6ixMHrmkRAotou8LvKOzH9I9BfLthqgwcNJGm4hMPHcxoiyVlkqWqnpIMxlWc/vb1E/lXjwo86mZ/hBUJdRhgIfrgIDKCMBf98ftWtUF8I1Hd5qBvY7pTMk3ErQYOtqBfvCCFGwejAfOUKwtY4itQ7AILi4Er2IgALH0zJO7alPugTOwmICd998rafB2wAHWREJkaOfCgCasRkB8tqcWjpLx2oMqiYSTVq2d6PBgAFSmoN9ltO2neTz9pqd0BA1BKIi7PjQYN+F7dB/ffG7V8VjNoPMROrHzq6sY3Ondtv7w==MIIDlzCCAn+gAwIBAgIJAO1ymQc33+bWMA0GCSqGSIb3DQEBCwUAMGIxCzAJBgNVBAYTAkhLMRMwEQYDVQQIDApTb21lLVN0YXRlMRowGAYDVQQKDBFJZGVudGl0eSBQcm92aWRlcjEUMBIGA1UECwwLRGV2ZWxvcG1lbnQxDDAKBgNVBAMMA0lEUDAeFw0xNTA3MDUxODAyMjdaFw0xODA3MDQxODAyMjdaMGIxCzAJBgNVBAYTAkhLMRMwEQYDVQQIDApTb21lLVN0YXRlMRowGAYDVQQKDBFJZGVudGl0eSBQcm92aWRlcjEUMBIGA1UECwwLRGV2ZWxvcG1lbnQxDDAKBgNVBAMMA0lEUDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAODZsWhCe+yG0PalQPTUoD7yko5MTWMCRxJ8hSm2k7mG3Eg/Y2v0EBdCmTw7iDCevRqUmbmFnq7MROyV4eriJzh0KabAdZf7/k6koghst3ZUtWOwzshyxkBtWDwGmBpQGTGsKxJ8M1js3aSqNRXBT4OBWM9w2Glt1+8ty30RhYv3pSF+/HHLH7Ac+vLSIAlokaFW34RWTcJ/8rADuRWlXih4GfnIu0W/ncm5nTSaJiRAvr3dGDRO/khiXoJdbbOj7dHPULxVGbH9IbPK76TCwLbF7ikIMsPovVbTrpyL6vsbVUKeEl/5GKppTwp9DLAOeoSYpCYkkDkYKu9TRQjF02MCAwEAAaNQME4wHQYDVR0OBBYEFP2ut2AQdy6D1dwdwK740IHmbh38MB8GA1UdIwQYMBaAFP2ut2AQdy6D1dwdwK740IHmbh38MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBANMZUoPNmHzgja2PYkbvBYMHmpvUkVoiuvQ9cJPlqGTB2CRfG68BNNs/Clz8P7cIrAdkhCUwi1rSBhDuslGFNrSaIpv6B10FpBuKwef3G7YrPWFNEN6khY7aHNWSTHqKgs1DrGef2B9hvkrnHWbQVSVXrBFKe1wTCqcgGcOpYoSK7L8C6iX6uIA/uZYnVQ4NgBrizJ0azkjdegz3hwO/gt4malEURy8D85/AAVt6PAzhpb9VJUGxSXr/EfntVUEz3L2gUFWWk1CnZFyz0rIOEt/zPmeAY8BLyd/Tjxm4Y+gwNazKq5y9AJS+m858b/nM4QdCnUE4yyoWAJDUHiAmvFA=
2 |
--------------------------------------------------------------------------------
/test/misc/dumpes_issuer_response.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | http://www.okta.com/dummyIssuer
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | Spr+5HzbZxSt8I3vCY4rTBu+glE=
19 |
20 |
21 |
22 | signatureValue
23 |
24 |
25 |
26 | stuff
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
36 | http://www.okta.com/dummyIssuer
37 |
38 | email@email.com
39 |
40 |
41 |
43 |
44 |
45 |
46 |
47 | api.com
48 |
49 |
50 |
51 |
52 | urn:oasis:names:tc:SAML:2.0:ac:classes:TLSClient
53 |
54 |
55 |
56 |
57 |
58 |
60 | email@email.com
61 |
62 |
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/test/misc/failed_response.xml:
--------------------------------------------------------------------------------
1 | https://idp.example.com/metadata
--------------------------------------------------------------------------------
/test/misc/false_signed_request_sha1.xml:
--------------------------------------------------------------------------------
1 | https://sp.example.org/metadataurn:oasis:names:tc:SAML:2.0:ac:classes:PasswordtQDisBXKTQ+9OXJO5r7KuJga+KI=oxRkvau7UvYgFEZ7YNAUNf3067V7Tn5C9XSIiet1aZw2FYevNW5bUy/0mxp3aj6AvfFjnmpzAb88BjdwAz2BErDTomRcuZB7Lb0fYTf31N2oZOX0MiPiQOH54I63qJW4Xo3VqdF7GBuFZZHyllfSBv7gfCtjJDwFSCzWK70B9r3cFMRJZLhCJ9oPen+4U9scSYO6g+szBZLl6AiJ06PHc8jzEKGwfQrcZk8kDKUlvNfJMULyq8dpx2VvUAx4p5ewfMOwB9W3Hl3PPa0dO77zZif3CglpcN06f+m6UYG/wnoTQEyKW9hOe+2vGM80W77eWu0dmiaPuqTok8LXPuq1A==MIIDozCCAougAwIBAgIJAKNsmL8QbfpwMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNVBAYTAkhLMRIwEAYDVQQIDAlIb25nIEtvbmcxCzAJBgNVBAcMAkhLMRMwEQYDVQQKDApub2RlLXNhbWwyMSMwIQYJKoZIhvcNAQkBFhRub2RlLnNhbWwyQGdtYWlsLmNvbTAeFw0xNTA3MDUxNzU2NDdaFw0xODA3MDQxNzU2NDdaMGgxCzAJBgNVBAYTAkhLMRIwEAYDVQQIDAlIb25nIEtvbmcxCzAJBgNVBAcMAkhLMRMwEQYDVQQKDApub2RlLXNhbWwyMSMwIQYJKoZIhvcNAQkBFhRub2RlLnNhbWwyQGdtYWlsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMQJAB8JrsLQbUuJa8akzLqO1EZqClS0tQp+w+5wgufp07WwGn/shma8dcQNj1dbjszI5HBeVFjOKIxlfjmNB9ovhQPstBjP/UPQYp1Ip2IoHCYX9HDgMz3xyXKbHthUzZaECz+p+7WtgwhczRkBLDOm2k15qhPYGPw0vH2zbVRGWUBS9dy2Mp3tqlVbP0xZ9CDNkhCJkV9SMNfoCVW/VYPqK2QBo7ki4obm5x5ixFQSSHsKbVARVzyQH5iNjFe1TdAp3rDwrE5Lc1NQlQaxR5Gnb2NZApDORRZIVlNv2WUdi9QvM0yCzjQ90jP0OAogHhRYaxg0/vgNEye46h+PiY0CAwEAAaNQME4wHQYDVR0OBBYEFEVkjcLAITndky090Ay74QqCmQKIMB8GA1UdIwQYMBaAFEVkjcLAITndky090Ay74QqCmQKIMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAG4lYX3KQXenez4LpDnZhcFBEZi9YstUKPF5EKd+WplpVbcTQc1A3/Z+uHRmyV8h+pQzeF6Liob37G87YpacPplJI66cf2Rj7j8hSBNbdr+66E2qpcEhAF1iJmzBNyhb/ydlEuVpn8/EsoP+HvBeiDl5gon3562MzZIgV/pLdTfxHyW6hzAQhjGq2UhcvR+gXNVJvHP2eS4jlHnJkB9bfo0kvf87Q+D6XKX3q5c3mO8tqW6UpqHSC+uLEpzZiNLeuFa4TUIhgBgjDjlRrNDKu8ndancSn3yBHYnqJ2t9cR+coFnnjYABQpNrvk4mtmXY8SXoBzYG9Y+lqeAun6+0YyE=
2 |
--------------------------------------------------------------------------------
/test/misc/false_signed_request_sha256.xml:
--------------------------------------------------------------------------------
1 | http://localhost:4002/sso/metadata9Ftynct5x7o+SdQM9iie2Z8VzZW95OTtXh4BD4O/HP8=EjY0qRy8tJeSANz3uINpdyFmCISiid4vl3KtszPa1mLvx1wGO2RJiFW8Sa18JOS0l8rYP2gwoUYmxU5WS/Cl1QEMlDj46fPpOjEBELGXdKW69zpAHa5jM/FtS8RCixhiMI1dmbL3+zgziEVdx5xrkaakqvpdDD601Eyn0gy1oO+VUmCMPFE6YjsPeFDhw5ZXf7MmJ/fXLeqWmH5Pn+mkyTCZWxi/L+2nG9iayZ41Z3wBl67XTdBL6rwHMcEY7oxwFSZtKTbtTOV6aW11KdAd9peLIsHeqoaMCY/VypS2bTr9FubQCbHhho2vbhX8cuUfpE21OefA7o1rA==MIIDozCCAougAwIBAgIJAKNsmL8QbfpwMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNVBAYTAkhLMRIwEAYDVQQIDAlIb25nIEtvbmcxCzAJBgNVBAcMAkhLMRMwEQYDVQQKDApub2RlLXNhbWwyMSMwIQYJKoZIhvcNAQkBFhRub2RlLnNhbWwyQGdtYWlsLmNvbTAeFw0xNTA3MDUxNzU2NDdaFw0xODA3MDQxNzU2NDdaMGgxCzAJBgNVBAYTAkhLMRIwEAYDVQQIDAlIb25nIEtvbmcxCzAJBgNVBAcMAkhLMRMwEQYDVQQKDApub2RlLXNhbWwyMSMwIQYJKoZIhvcNAQkBFhRub2RlLnNhbWwyQGdtYWlsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMQJAB8JrsLQbUuJa8akzLqO1EZqClS0tQp+w+5wgufp07WwGn/shma8dcQNj1dbjszI5HBeVFjOKIxlfjmNB9ovhQPstBjP/UPQYp1Ip2IoHCYX9HDgMz3xyXKbHthUzZaECz+p+7WtgwhczRkBLDOm2k15qhPYGPw0vH2zbVRGWUBS9dy2Mp3tqlVbP0xZ9CDNkhCJkV9SMNfoCVW/VYPqK2QBo7ki4obm5x5ixFQSSHsKbVARVzyQH5iNjFe1TdAp3rDwrE5Lc1NQlQaxR5Gnb2NZApDORRZIVlNv2WUdi9QvM0yCzjQ90jP0OAogHhRYaxg0/vgNEye46h+PiY0CAwEAAaNQME4wHQYDVR0OBBYEFEVkjcLAITndky090Ay74QqCmQKIMB8GA1UdIwQYMBaAFEVkjcLAITndky090Ay74QqCmQKIMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAG4lYX3KQXenez4LpDnZhcFBEZi9YstUKPF5EKd+WplpVbcTQc1A3/Z+uHRmyV8h+pQzeF6Liob37G87YpacPplJI66cf2Rj7j8hSBNbdr+66E2qpcEhAF1iJmzBNyhb/ydlEuVpn8/EsoP+HvBeiDl5gon3562MzZIgV/pLdTfxHyW6hzAQhjGq2UhcvR+gXNVJvHP2eS4jlHnJkB9bfo0kvf87Q+D6XKX3q5c3mO8tqW6UpqHSC+uLEpzZiNLeuFa4TUIhgBgjDjlRrNDKu8ndancSn3yBHYnqJ2t9cR+coFnnjYABQpNrvk4mtmXY8SXoBzYG9Y+lqeAun6+0YyE=
2 |
--------------------------------------------------------------------------------
/test/misc/false_signed_request_sha512.xml:
--------------------------------------------------------------------------------
1 | http://localhost:4002/sso/metadata9Ftynct5x7o+SdQM9iie2Z8VzZW95OTtXh4BD4O/HP8=dk+CI6UvXgsM0cHAGAz/Y3gbvehbab92i1jEmDH0QB7d6/3l7j7TuOEvUFnmtwa0kwpigwpySwXybfiuvgdSBmhejwng5m28bYqaIA8FgCWe/BkBVL5BYeQH03gPbnqhBpC5EXUe52FtOlGAoTGNqaD0pyrshoGiOj/OzqVZC7RSBvvYt5iwpLyqj4KIFFao4yNAfIs2n7RwfcbGg3I2m2b5nuhVppRdzzukdQiLdDCuATPDxKJ3KdETbHb3yss+8L2iDPcAoqsZ+UTZ8VI5DhrQBcarcIe8Xp2FUKQnC4n0AEqCpb87l6txPz7GYDaw9yMqe2xD5LPWQ6/2guvqw==MIIDozCCAougAwIBAgIJAKNsmL8QbfpwMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNVBAYTAkhLMRIwEAYDVQQIDAlIb25nIEtvbmcxCzAJBgNVBAcMAkhLMRMwEQYDVQQKDApub2RlLXNhbWwyMSMwIQYJKoZIhvcNAQkBFhRub2RlLnNhbWwyQGdtYWlsLmNvbTAeFw0xNTA3MDUxNzU2NDdaFw0xODA3MDQxNzU2NDdaMGgxCzAJBgNVBAYTAkhLMRIwEAYDVQQIDAlIb25nIEtvbmcxCzAJBgNVBAcMAkhLMRMwEQYDVQQKDApub2RlLXNhbWwyMSMwIQYJKoZIhvcNAQkBFhRub2RlLnNhbWwyQGdtYWlsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMQJAB8JrsLQbUuJa8akzLqO1EZqClS0tQp+w+5wgufp07WwGn/shma8dcQNj1dbjszI5HBeVFjOKIxlfjmNB9ovhQPstBjP/UPQYp1Ip2IoHCYX9HDgMz3xyXKbHthUzZaECz+p+7WtgwhczRkBLDOm2k15qhPYGPw0vH2zbVRGWUBS9dy2Mp3tqlVbP0xZ9CDNkhCJkV9SMNfoCVW/VYPqK2QBo7ki4obm5x5ixFQSSHsKbVARVzyQH5iNjFe1TdAp3rDwrE5Lc1NQlQaxR5Gnb2NZApDORRZIVlNv2WUdi9QvM0yCzjQ90jP0OAogHhRYaxg0/vgNEye46h+PiY0CAwEAAaNQME4wHQYDVR0OBBYEFEVkjcLAITndky090Ay74QqCmQKIMB8GA1UdIwQYMBaAFEVkjcLAITndky090Ay74QqCmQKIMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAG4lYX3KQXenez4LpDnZhcFBEZi9YstUKPF5EKd+WplpVbcTQc1A3/Z+uHRmyV8h+pQzeF6Liob37G87YpacPplJI66cf2Rj7j8hSBNbdr+66E2qpcEhAF1iJmzBNyhb/ydlEuVpn8/EsoP+HvBeiDl5gon3562MzZIgV/pLdTfxHyW6hzAQhjGq2UhcvR+gXNVJvHP2eS4jlHnJkB9bfo0kvf87Q+D6XKX3q5c3mO8tqW6UpqHSC+uLEpzZiNLeuFa4TUIhgBgjDjlRrNDKu8ndancSn3yBHYnqJ2t9cR+coFnnjYABQpNrvk4mtmXY8SXoBzYG9Y+lqeAun6+0YyE=
2 |
--------------------------------------------------------------------------------
/test/misc/idpmeta.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
9 |
10 | MIIDlzCCAn+gAwIBAgIJAO1ymQc33+bWMA0GCSqGSIb3DQEBCwUAMGIxCzAJBgNVBAYTAkhLMRMwEQYDVQQIDApTb21lLVN0YXRlMRowGAYDVQQKDBFJZGVudGl0eSBQcm92aWRlcjEUMBIGA1UECwwLRGV2ZWxvcG1lbnQxDDAKBgNVBAMMA0lEUDAeFw0xNTA3MDUxODAyMjdaFw0xODA3MDQxODAyMjdaMGIxCzAJBgNVBAYTAkhLMRMwEQYDVQQIDApTb21lLVN0YXRlMRowGAYDVQQKDBFJZGVudGl0eSBQcm92aWRlcjEUMBIGA1UECwwLRGV2ZWxvcG1lbnQxDDAKBgNVBAMMA0lEUDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAODZsWhCe+yG0PalQPTUoD7yko5MTWMCRxJ8hSm2k7mG3Eg/Y2v0EBdCmTw7iDCevRqUmbmFnq7MROyV4eriJzh0KabAdZf7/k6koghst3ZUtWOwzshyxkBtWDwGmBpQGTGsKxJ8M1js3aSqNRXBT4OBWM9w2Glt1+8ty30RhYv3pSF+/HHLH7Ac+vLSIAlokaFW34RWTcJ/8rADuRWlXih4GfnIu0W/ncm5nTSaJiRAvr3dGDRO/khiXoJdbbOj7dHPULxVGbH9IbPK76TCwLbF7ikIMsPovVbTrpyL6vsbVUKeEl/5GKppTwp9DLAOeoSYpCYkkDkYKu9TRQjF02MCAwEAAaNQME4wHQYDVR0OBBYEFP2ut2AQdy6D1dwdwK740IHmbh38MB8GA1UdIwQYMBaAFP2ut2AQdy6D1dwdwK740IHmbh38MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBANMZUoPNmHzgja2PYkbvBYMHmpvUkVoiuvQ9cJPlqGTB2CRfG68BNNs/Clz8P7cIrAdkhCUwi1rSBhDuslGFNrSaIpv6B10FpBuKwef3G7YrPWFNEN6khY7aHNWSTHqKgs1DrGef2B9hvkrnHWbQVSVXrBFKe1wTCqcgGcOpYoSK7L8C6iX6uIA/uZYnVQ4NgBrizJ0azkjdegz3hwO/gt4malEURy8D85/AAVt6PAzhpb9VJUGxSXr/EfntVUEz3L2gUFWWk1CnZFyz0rIOEt/zPmeAY8BLyd/Tjxm4Y+gwNazKq5y9AJS+m858b/nM4QdCnUE4yyoWAJDUHiAmvFA=
11 |
12 |
13 |
14 |
15 |
16 |
17 | MIID6TCCAtGgAwIBAgIJAPQQPsolUypeMA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNVBAYTAkhLMRIwEAYDVQQIEwlIb25nIEtvbmcxFTATBgNVBAoTDGV4cHJlc3Mtc2FtbDEMMAoGA1UECxMDZGV2MQ4wDAYDVQQDEwVlc2FtbDAeFw0xNTEwMDMwMzU3MzRaFw0xODEwMDIwMzU3MzRaMFYxCzAJBgNVBAYTAkhLMRIwEAYDVQQIEwlIb25nIEtvbmcxFTATBgNVBAoTDGV4cHJlc3Mtc2FtbDEMMAoGA1UECxMDZGV2MQ4wDAYDVQQDEwVlc2FtbDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL7dF1gUNu8en0fHMSbzf192uB8m2CTeHeEeYrmq5rau6t1WzaHwbSStd9tJ/11Arm8f8zfefFqEBA0EYbp/DMqHb9ZiLGgIff08679NOYeK/d9EAs5DzvTMTR6QqG7a4vH3jKOksIbjM35h5RVitVDxo+xWDKyvOpuNE64bJlWHOEiNxvwmcHfJ2hAd1EozaRLcJOojFHg51alUqiNIZ+vpkMAM8s3lUlcYETKqTpcnsE7c1QX60cCrFN4m3SNS98HGBEdotch8+2Myzz957cBiwg9CR05PtEfjH0gGXJbL56JmpPyY+TkEiNMtMqJ7RNkK92gZfoY2i3RdjLKOHDUCAwEAAaOBuTCBtjAdBgNVHQ4EFgQUm4zK2qBtDMICekupt3LnRBdbP9UwgYYGA1UdIwR/MH2AFJuMytqgbQzCAnpLqbdy50QXWz/VoVqkWDBWMQswCQYDVQQGEwJISzESMBAGA1UECBMJSG9uZyBLb25nMRUwEwYDVQQKEwxleHByZXNzLXNhbWwxDDAKBgNVBAsTA2RldjEOMAwGA1UEAxMFZXNhbWyCCQD0ED7KJVMqXjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQA9t7VMtX93yIYIGFC20GCsMYZeZpTedxpxpjqom2dOuOUaDQgrZcGF3FVbFqTEpPtOnsKXYaCg7FJvUjxv7FIuix5H7JO6DALoJ792pfG2wwS2PvDiGFxMfGnNvb3aLnB/s6wTyWBpDYRdwlB5nj37KPk6kpFJj3N9x5BD1oTdmQqeVuacjoiemIulkc33P28tGl6Datth4WpE0LwmrwREQ1NWixi2j1Ti3mjYkyqGVY8XphWKEIIWmheqLnYCXRXhbxZ4E+FGg81ZYG8TKYC/IjzV8p0rLnAI1qS7wdwv5UJ9vQJt6KcxdHHZsUlpIfaJC6N5DvAL/qUY8DoIymgz
18 |
19 |
20 |
21 | urn:oasis:names:tc:SAML:2.0:nameid-format:persistent
22 | urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
23 | urn:oasis:names:tc:SAML:2.0:nameid-format:transient
24 | urn:oasis:names:tc:SAML:2.0:nameid-format:entity
25 | urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified
26 | urn:oasis:names:tc:SAML:2.0:nameid-format:kerberos
27 | urn:oasis:names:tc:SAML:1.1:nameid-format:WindowsDomainQualifiedName
28 | urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/test/misc/idpmeta_nosign.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
9 |
10 | MIIDlzCCAn+gAwIBAgIJAO1ymQc33+bWMA0GCSqGSIb3DQEBCwUAMGIxCzAJBgNVBAYTAkhLMRMwEQYDVQQIDApTb21lLVN0YXRlMRowGAYDVQQKDBFJZGVudGl0eSBQcm92aWRlcjEUMBIGA1UECwwLRGV2ZWxvcG1lbnQxDDAKBgNVBAMMA0lEUDAeFw0xNTA3MDUxODAyMjdaFw0xODA3MDQxODAyMjdaMGIxCzAJBgNVBAYTAkhLMRMwEQYDVQQIDApTb21lLVN0YXRlMRowGAYDVQQKDBFJZGVudGl0eSBQcm92aWRlcjEUMBIGA1UECwwLRGV2ZWxvcG1lbnQxDDAKBgNVBAMMA0lEUDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAODZsWhCe+yG0PalQPTUoD7yko5MTWMCRxJ8hSm2k7mG3Eg/Y2v0EBdCmTw7iDCevRqUmbmFnq7MROyV4eriJzh0KabAdZf7/k6koghst3ZUtWOwzshyxkBtWDwGmBpQGTGsKxJ8M1js3aSqNRXBT4OBWM9w2Glt1+8ty30RhYv3pSF+/HHLH7Ac+vLSIAlokaFW34RWTcJ/8rADuRWlXih4GfnIu0W/ncm5nTSaJiRAvr3dGDRO/khiXoJdbbOj7dHPULxVGbH9IbPK76TCwLbF7ikIMsPovVbTrpyL6vsbVUKeEl/5GKppTwp9DLAOeoSYpCYkkDkYKu9TRQjF02MCAwEAAaNQME4wHQYDVR0OBBYEFP2ut2AQdy6D1dwdwK740IHmbh38MB8GA1UdIwQYMBaAFP2ut2AQdy6D1dwdwK740IHmbh38MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBANMZUoPNmHzgja2PYkbvBYMHmpvUkVoiuvQ9cJPlqGTB2CRfG68BNNs/Clz8P7cIrAdkhCUwi1rSBhDuslGFNrSaIpv6B10FpBuKwef3G7YrPWFNEN6khY7aHNWSTHqKgs1DrGef2B9hvkrnHWbQVSVXrBFKe1wTCqcgGcOpYoSK7L8C6iX6uIA/uZYnVQ4NgBrizJ0azkjdegz3hwO/gt4malEURy8D85/AAVt6PAzhpb9VJUGxSXr/EfntVUEz3L2gUFWWk1CnZFyz0rIOEt/zPmeAY8BLyd/Tjxm4Y+gwNazKq5y9AJS+m858b/nM4QdCnUE4yyoWAJDUHiAmvFA=
11 |
12 |
13 |
14 | urn:oasis:names:tc:SAML:2.0:nameid-format:persistent
15 | urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
16 | urn:oasis:names:tc:SAML:2.0:nameid-format:transient
17 | urn:oasis:names:tc:SAML:2.0:nameid-format:entity
18 | urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified
19 | urn:oasis:names:tc:SAML:2.0:nameid-format:kerberos
20 | urn:oasis:names:tc:SAML:1.1:nameid-format:WindowsDomainQualifiedName
21 | urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/test/misc/idpmeta_onelogoutservice.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
9 |
10 | MIIDlzCCAn+gAwIBAgIJAO1ymQc33+bWMA0GCSqGSIb3DQEBCwUAMGIxCzAJBgNVBAYTAkhLMRMwEQYDVQQIDApTb21lLVN0YXRlMRowGAYDVQQKDBFJZGVudGl0eSBQcm92aWRlcjEUMBIGA1UECwwLRGV2ZWxvcG1lbnQxDDAKBgNVBAMMA0lEUDAeFw0xNTA3MDUxODAyMjdaFw0xODA3MDQxODAyMjdaMGIxCzAJBgNVBAYTAkhLMRMwEQYDVQQIDApTb21lLVN0YXRlMRowGAYDVQQKDBFJZGVudGl0eSBQcm92aWRlcjEUMBIGA1UECwwLRGV2ZWxvcG1lbnQxDDAKBgNVBAMMA0lEUDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAODZsWhCe+yG0PalQPTUoD7yko5MTWMCRxJ8hSm2k7mG3Eg/Y2v0EBdCmTw7iDCevRqUmbmFnq7MROyV4eriJzh0KabAdZf7/k6koghst3ZUtWOwzshyxkBtWDwGmBpQGTGsKxJ8M1js3aSqNRXBT4OBWM9w2Glt1+8ty30RhYv3pSF+/HHLH7Ac+vLSIAlokaFW34RWTcJ/8rADuRWlXih4GfnIu0W/ncm5nTSaJiRAvr3dGDRO/khiXoJdbbOj7dHPULxVGbH9IbPK76TCwLbF7ikIMsPovVbTrpyL6vsbVUKeEl/5GKppTwp9DLAOeoSYpCYkkDkYKu9TRQjF02MCAwEAAaNQME4wHQYDVR0OBBYEFP2ut2AQdy6D1dwdwK740IHmbh38MB8GA1UdIwQYMBaAFP2ut2AQdy6D1dwdwK740IHmbh38MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBANMZUoPNmHzgja2PYkbvBYMHmpvUkVoiuvQ9cJPlqGTB2CRfG68BNNs/Clz8P7cIrAdkhCUwi1rSBhDuslGFNrSaIpv6B10FpBuKwef3G7YrPWFNEN6khY7aHNWSTHqKgs1DrGef2B9hvkrnHWbQVSVXrBFKe1wTCqcgGcOpYoSK7L8C6iX6uIA/uZYnVQ4NgBrizJ0azkjdegz3hwO/gt4malEURy8D85/AAVt6PAzhpb9VJUGxSXr/EfntVUEz3L2gUFWWk1CnZFyz0rIOEt/zPmeAY8BLyd/Tjxm4Y+gwNazKq5y9AJS+m858b/nM4QdCnUE4yyoWAJDUHiAmvFA=
11 |
12 |
13 |
14 |
15 |
16 |
17 | MIID6TCCAtGgAwIBAgIJAPQQPsolUypeMA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNVBAYTAkhLMRIwEAYDVQQIEwlIb25nIEtvbmcxFTATBgNVBAoTDGV4cHJlc3Mtc2FtbDEMMAoGA1UECxMDZGV2MQ4wDAYDVQQDEwVlc2FtbDAeFw0xNTEwMDMwMzU3MzRaFw0xODEwMDIwMzU3MzRaMFYxCzAJBgNVBAYTAkhLMRIwEAYDVQQIEwlIb25nIEtvbmcxFTATBgNVBAoTDGV4cHJlc3Mtc2FtbDEMMAoGA1UECxMDZGV2MQ4wDAYDVQQDEwVlc2FtbDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL7dF1gUNu8en0fHMSbzf192uB8m2CTeHeEeYrmq5rau6t1WzaHwbSStd9tJ/11Arm8f8zfefFqEBA0EYbp/DMqHb9ZiLGgIff08679NOYeK/d9EAs5DzvTMTR6QqG7a4vH3jKOksIbjM35h5RVitVDxo+xWDKyvOpuNE64bJlWHOEiNxvwmcHfJ2hAd1EozaRLcJOojFHg51alUqiNIZ+vpkMAM8s3lUlcYETKqTpcnsE7c1QX60cCrFN4m3SNS98HGBEdotch8+2Myzz957cBiwg9CR05PtEfjH0gGXJbL56JmpPyY+TkEiNMtMqJ7RNkK92gZfoY2i3RdjLKOHDUCAwEAAaOBuTCBtjAdBgNVHQ4EFgQUm4zK2qBtDMICekupt3LnRBdbP9UwgYYGA1UdIwR/MH2AFJuMytqgbQzCAnpLqbdy50QXWz/VoVqkWDBWMQswCQYDVQQGEwJISzESMBAGA1UECBMJSG9uZyBLb25nMRUwEwYDVQQKEwxleHByZXNzLXNhbWwxDDAKBgNVBAsTA2RldjEOMAwGA1UEAxMFZXNhbWyCCQD0ED7KJVMqXjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQA9t7VMtX93yIYIGFC20GCsMYZeZpTedxpxpjqom2dOuOUaDQgrZcGF3FVbFqTEpPtOnsKXYaCg7FJvUjxv7FIuix5H7JO6DALoJ792pfG2wwS2PvDiGFxMfGnNvb3aLnB/s6wTyWBpDYRdwlB5nj37KPk6kpFJj3N9x5BD1oTdmQqeVuacjoiemIulkc33P28tGl6Datth4WpE0LwmrwREQ1NWixi2j1Ti3mjYkyqGVY8XphWKEIIWmheqLnYCXRXhbxZ4E+FGg81ZYG8TKYC/IjzV8p0rLnAI1qS7wdwv5UJ9vQJt6KcxdHHZsUlpIfaJC6N5DvAL/qUY8DoIymgz
18 |
19 |
20 |
21 | urn:oasis:names:tc:SAML:2.0:nameid-format:persistent
22 | urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
23 | urn:oasis:names:tc:SAML:2.0:nameid-format:transient
24 | urn:oasis:names:tc:SAML:2.0:nameid-format:entity
25 | urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified
26 | urn:oasis:names:tc:SAML:2.0:nameid-format:kerberos
27 | urn:oasis:names:tc:SAML:1.1:nameid-format:WindowsDomainQualifiedName
28 | urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/test/misc/idpmeta_share_cert.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
9 |
10 | MIIDlzCCAn+gAwIBAgIJAO1ymQc33+bWMA0GCSqGSIb3DQEBCwUAMGIxCzAJBgNVBAYTAkhLMRMwEQYDVQQIDApTb21lLVN0YXRlMRowGAYDVQQKDBFJZGVudGl0eSBQcm92aWRlcjEUMBIGA1UECwwLRGV2ZWxvcG1lbnQxDDAKBgNVBAMMA0lEUDAeFw0xNTA3MDUxODAyMjdaFw0xODA3MDQxODAyMjdaMGIxCzAJBgNVBAYTAkhLMRMwEQYDVQQIDApTb21lLVN0YXRlMRowGAYDVQQKDBFJZGVudGl0eSBQcm92aWRlcjEUMBIGA1UECwwLRGV2ZWxvcG1lbnQxDDAKBgNVBAMMA0lEUDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAODZsWhCe+yG0PalQPTUoD7yko5MTWMCRxJ8hSm2k7mG3Eg/Y2v0EBdCmTw7iDCevRqUmbmFnq7MROyV4eriJzh0KabAdZf7/k6koghst3ZUtWOwzshyxkBtWDwGmBpQGTGsKxJ8M1js3aSqNRXBT4OBWM9w2Glt1+8ty30RhYv3pSF+/HHLH7Ac+vLSIAlokaFW34RWTcJ/8rADuRWlXih4GfnIu0W/ncm5nTSaJiRAvr3dGDRO/khiXoJdbbOj7dHPULxVGbH9IbPK76TCwLbF7ikIMsPovVbTrpyL6vsbVUKeEl/5GKppTwp9DLAOeoSYpCYkkDkYKu9TRQjF02MCAwEAAaNQME4wHQYDVR0OBBYEFP2ut2AQdy6D1dwdwK740IHmbh38MB8GA1UdIwQYMBaAFP2ut2AQdy6D1dwdwK740IHmbh38MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBANMZUoPNmHzgja2PYkbvBYMHmpvUkVoiuvQ9cJPlqGTB2CRfG68BNNs/Clz8P7cIrAdkhCUwi1rSBhDuslGFNrSaIpv6B10FpBuKwef3G7YrPWFNEN6khY7aHNWSTHqKgs1DrGef2B9hvkrnHWbQVSVXrBFKe1wTCqcgGcOpYoSK7L8C6iX6uIA/uZYnVQ4NgBrizJ0azkjdegz3hwO/gt4malEURy8D85/AAVt6PAzhpb9VJUGxSXr/EfntVUEz3L2gUFWWk1CnZFyz0rIOEt/zPmeAY8BLyd/Tjxm4Y+gwNazKq5y9AJS+m858b/nM4QdCnUE4yyoWAJDUHiAmvFA=
11 |
12 |
13 |
14 | urn:oasis:names:tc:SAML:2.0:nameid-format:persistent
15 | urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
16 | urn:oasis:names:tc:SAML:2.0:nameid-format:transient
17 | urn:oasis:names:tc:SAML:2.0:nameid-format:entity
18 | urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified
19 | urn:oasis:names:tc:SAML:2.0:nameid-format:kerberos
20 | urn:oasis:names:tc:SAML:1.1:nameid-format:WindowsDomainQualifiedName
21 | urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/test/misc/invalid_response.xml:
--------------------------------------------------------------------------------
1 |
2 | https://idp.example.com/metadata
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/test/misc/logout_request.xml:
--------------------------------------------------------------------------------
1 |
2 | http://sp.example.com/metadata
3 | f92cc1834efc0f73e9c09f482fce80037a6251e7
4 |
5 |
--------------------------------------------------------------------------------
/test/misc/multiple_entitydescriptor.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
9 |
10 | MIIDlzCCAn+gAwIBAgIJAO1ymQc33+bWMA0GCSqGSIb3DQEBCwUAMGIxCzAJBgNVBAYTAkhLMRMwEQYDVQQIDApTb21lLVN0YXRlMRowGAYDVQQKDBFJZGVudGl0eSBQcm92aWRlcjEUMBIGA1UECwwLRGV2ZWxvcG1lbnQxDDAKBgNVBAMMA0lEUDAeFw0xNTA3MDUxODAyMjdaFw0xODA3MDQxODAyMjdaMGIxCzAJBgNVBAYTAkhLMRMwEQYDVQQIDApTb21lLVN0YXRlMRowGAYDVQQKDBFJZGVudGl0eSBQcm92aWRlcjEUMBIGA1UECwwLRGV2ZWxvcG1lbnQxDDAKBgNVBAMMA0lEUDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAODZsWhCe+yG0PalQPTUoD7yko5MTWMCRxJ8hSm2k7mG3Eg/Y2v0EBdCmTw7iDCevRqUmbmFnq7MROyV4eriJzh0KabAdZf7/k6koghst3ZUtWOwzshyxkBtWDwGmBpQGTGsKxJ8M1js3aSqNRXBT4OBWM9w2Glt1+8ty30RhYv3pSF+/HHLH7Ac+vLSIAlokaFW34RWTcJ/8rADuRWlXih4GfnIu0W/ncm5nTSaJiRAvr3dGDRO/khiXoJdbbOj7dHPULxVGbH9IbPK76TCwLbF7ikIMsPovVbTrpyL6vsbVUKeEl/5GKppTwp9DLAOeoSYpCYkkDkYKu9TRQjF02MCAwEAAaNQME4wHQYDVR0OBBYEFP2ut2AQdy6D1dwdwK740IHmbh38MB8GA1UdIwQYMBaAFP2ut2AQdy6D1dwdwK740IHmbh38MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBANMZUoPNmHzgja2PYkbvBYMHmpvUkVoiuvQ9cJPlqGTB2CRfG68BNNs/Clz8P7cIrAdkhCUwi1rSBhDuslGFNrSaIpv6B10FpBuKwef3G7YrPWFNEN6khY7aHNWSTHqKgs1DrGef2B9hvkrnHWbQVSVXrBFKe1wTCqcgGcOpYoSK7L8C6iX6uIA/uZYnVQ4NgBrizJ0azkjdegz3hwO/gt4malEURy8D85/AAVt6PAzhpb9VJUGxSXr/EfntVUEz3L2gUFWWk1CnZFyz0rIOEt/zPmeAY8BLyd/Tjxm4Y+gwNazKq5y9AJS+m858b/nM4QdCnUE4yyoWAJDUHiAmvFA=
11 |
12 |
13 |
14 | urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
15 |
16 |
17 |
18 |
19 |
20 |
25 |
26 |
27 |
28 |
29 | MIIDozCCAougAwIBAgIJAKNsmL8QbfpwMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNVBAYTAkhLMRIwEAYDVQQIDAlIb25nIEtvbmcxCzAJBgNVBAcMAkhLMRMwEQYDVQQKDApub2RlLXNhbWwyMSMwIQYJKoZIhvcNAQkBFhRub2RlLnNhbWwyQGdtYWlsLmNvbTAeFw0xNTA3MDUxNzU2NDdaFw0xODA3MDQxNzU2NDdaMGgxCzAJBgNVBAYTAkhLMRIwEAYDVQQIDAlIb25nIEtvbmcxCzAJBgNVBAcMAkhLMRMwEQYDVQQKDApub2RlLXNhbWwyMSMwIQYJKoZIhvcNAQkBFhRub2RlLnNhbWwyQGdtYWlsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMQJAB8JrsLQbUuJa8akzLqO1EZqClS0tQp+w+5wgufp07WwGn/shma8dcQNj1dbjszI5HBeVFjOKIxlfjmNB9ovhQPstBjP/UPQYp1Ip2IoHCYX9HDgMz3xyXKbHthUzZaECz+p+7WtgwhczRkBLDOm2k15qhPYGPw0vH2zbVRGWUBS9dy2Mp3tqlVbP0xZ9CDNkhCJkV9SMNfoCVW/VYPqK2QBo7ki4obm5x5ixFQSSHsKbVARVzyQH5iNjFe1TdAp3rDwrE5Lc1NQlQaxR5Gnb2NZApDORRZIVlNv2WUdi9QvM0yCzjQ90jP0OAogHhRYaxg0/vgNEye46h+PiY0CAwEAAaNQME4wHQYDVR0OBBYEFEVkjcLAITndky090Ay74QqCmQKIMB8GA1UdIwQYMBaAFEVkjcLAITndky090Ay74QqCmQKIMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAG4lYX3KQXenez4LpDnZhcFBEZi9YstUKPF5EKd+WplpVbcTQc1A3/Z+uHRmyV8h+pQzeF6Liob37G87YpacPplJI66cf2Rj7j8hSBNbdr+66E2qpcEhAF1iJmzBNyhb/ydlEuVpn8/EsoP+HvBeiDl5gon3562MzZIgV/pLdTfxHyW6hzAQhjGq2UhcvR+gXNVJvHP2eS4jlHnJkB9bfo0kvf87Q+D6XKX3q5c3mO8tqW6UpqHSC+uLEpzZiNLeuFa4TUIhgBgjDjlRrNDKu8ndancSn3yBHYnqJ2t9cR+coFnnjYABQpNrvk4mtmXY8SXoBzYG9Y+lqeAun6+0YyE=
30 |
31 |
32 |
33 | urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/test/misc/request.xml:
--------------------------------------------------------------------------------
1 | https://sp.example.org/metadataurn:oasis:names:tc:SAML:2.0:ac:classes:Password
2 |
--------------------------------------------------------------------------------
/test/misc/response.xml:
--------------------------------------------------------------------------------
1 | https://idp.example.com/metadatahttps://idp.example.com/metadata_ce3d2948b4cf20146dee0a0b3dd6f69b6cf86f62d7https://sp.example.com/metadataurn:oasis:names:tc:SAML:2.0:ac:classes:Passwordtesttest@example.comusersexamplerole1
2 |
--------------------------------------------------------------------------------
/test/misc/response_signed.xml:
--------------------------------------------------------------------------------
1 | https://idp.example.com/metadatahttps://idp.example.com/metadata_ce3d2948b4cf20146dee0a0b3dd6f69b6cf86f62d7https://sp.example.com/metadataurn:oasis:names:tc:SAML:2.0:ac:classes:Passwordtesttest@example.comusersexamplerole1sZOR3aMpVBn1CoSmP674OQfCcyg=h7Dk6GTh4MrNNx8b8Or12SeGsAGBM/ILd7Jgz/RuqR6ixMHrmkRAotou8LvKOzH9I9BfLthqgwcNJGm4hMPHcxoiyVlkqWqnpIMxlWc/vb1E/lXjwo86mZ/hBUJdRhgIfrgIDKCMBf98ftWtUF8I1Hd5qBvY7pTMk3ErQYOtqBfvCCFGwejAfOUKwtY4itQ7AILi4Er2IgALH0zJO7alPugTOwmICd998rafB2wAHWREJkaOfCgCasRkB8tqcWjpLx2oMqiYSTVq2d6PBgAFSmoN9ltO2neTz9pqd0BA1BKIi7PjQYN+F7dB/ffG7V8VjNoPMROrHzq6sY3Ondtv7w==MIIDlzCCAn+gAwIBAgIJAO1ymQc33+bWMA0GCSqGSIb3DQEBCwUAMGIxCzAJBgNVBAYTAkhLMRMwEQYDVQQIDApTb21lLVN0YXRlMRowGAYDVQQKDBFJZGVudGl0eSBQcm92aWRlcjEUMBIGA1UECwwLRGV2ZWxvcG1lbnQxDDAKBgNVBAMMA0lEUDAeFw0xNTA3MDUxODAyMjdaFw0xODA3MDQxODAyMjdaMGIxCzAJBgNVBAYTAkhLMRMwEQYDVQQIDApTb21lLVN0YXRlMRowGAYDVQQKDBFJZGVudGl0eSBQcm92aWRlcjEUMBIGA1UECwwLRGV2ZWxvcG1lbnQxDDAKBgNVBAMMA0lEUDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAODZsWhCe+yG0PalQPTUoD7yko5MTWMCRxJ8hSm2k7mG3Eg/Y2v0EBdCmTw7iDCevRqUmbmFnq7MROyV4eriJzh0KabAdZf7/k6koghst3ZUtWOwzshyxkBtWDwGmBpQGTGsKxJ8M1js3aSqNRXBT4OBWM9w2Glt1+8ty30RhYv3pSF+/HHLH7Ac+vLSIAlokaFW34RWTcJ/8rADuRWlXih4GfnIu0W/ncm5nTSaJiRAvr3dGDRO/khiXoJdbbOj7dHPULxVGbH9IbPK76TCwLbF7ikIMsPovVbTrpyL6vsbVUKeEl/5GKppTwp9DLAOeoSYpCYkkDkYKu9TRQjF02MCAwEAAaNQME4wHQYDVR0OBBYEFP2ut2AQdy6D1dwdwK740IHmbh38MB8GA1UdIwQYMBaAFP2ut2AQdy6D1dwdwK740IHmbh38MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBANMZUoPNmHzgja2PYkbvBYMHmpvUkVoiuvQ9cJPlqGTB2CRfG68BNNs/Clz8P7cIrAdkhCUwi1rSBhDuslGFNrSaIpv6B10FpBuKwef3G7YrPWFNEN6khY7aHNWSTHqKgs1DrGef2B9hvkrnHWbQVSVXrBFKe1wTCqcgGcOpYoSK7L8C6iX6uIA/uZYnVQ4NgBrizJ0azkjdegz3hwO/gt4malEURy8D85/AAVt6PAzhpb9VJUGxSXr/EfntVUEz3L2gUFWWk1CnZFyz0rIOEt/zPmeAY8BLyd/Tjxm4Y+gwNazKq5y9AJS+m858b/nM4QdCnUE4yyoWAJDUHiAmvFA=
2 |
--------------------------------------------------------------------------------
/test/misc/response_signed_cert1.xml:
--------------------------------------------------------------------------------
1 | https://idp.example.com/metadataiPlh1ZRFuCBV07ayPRWVk7xU9SB5JN8mu6xAab3lEo0=ECKTz4y6czJx+KGlZNb8E6mBnFrMQC8hL7YDlAi8dko=GZSDF9T0TMTe5nkZspOBlc6+j+lon0eHjViy765ty0tM7F47qgDVWTiC2x326Iz8One12XKKbUHxMvqABnI77aNSJ0/BADFJLoH+mgPuSsgcZygTAWmKdn1bR/3zydMtkMIbP9JXB2VEF7a7KnnnjGcM2OXmdxanhe5J2vtrBWCrxt0QZOLaEsxQmCHosKizVhOnO5JehNqqkf9M4yp7acIsIVhCg21YYqnuAWMsve8qReryF31189TdsV9KO8uB0rufBsxl/dzNnMG74Rgq4mS3QjPI7N/WpXzZZk8vPe38FYEsFA5lmeIsdMxnlbbUEPJFwzWM72xEmMgo12+y4A==MIIDlzCCAn+gAwIBAgIJAO1ymQc33+bWMA0GCSqGSIb3DQEBCwUAMGIxCzAJBgNVBAYTAkhLMRMwEQYDVQQIDApTb21lLVN0YXRlMRowGAYDVQQKDBFJZGVudGl0eSBQcm92aWRlcjEUMBIGA1UECwwLRGV2ZWxvcG1lbnQxDDAKBgNVBAMMA0lEUDAeFw0xNTA3MDUxODAyMjdaFw0xODA3MDQxODAyMjdaMGIxCzAJBgNVBAYTAkhLMRMwEQYDVQQIDApTb21lLVN0YXRlMRowGAYDVQQKDBFJZGVudGl0eSBQcm92aWRlcjEUMBIGA1UECwwLRGV2ZWxvcG1lbnQxDDAKBgNVBAMMA0lEUDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAODZsWhCe+yG0PalQPTUoD7yko5MTWMCRxJ8hSm2k7mG3Eg/Y2v0EBdCmTw7iDCevRqUmbmFnq7MROyV4eriJzh0KabAdZf7/k6koghst3ZUtWOwzshyxkBtWDwGmBpQGTGsKxJ8M1js3aSqNRXBT4OBWM9w2Glt1+8ty30RhYv3pSF+/HHLH7Ac+vLSIAlokaFW34RWTcJ/8rADuRWlXih4GfnIu0W/ncm5nTSaJiRAvr3dGDRO/khiXoJdbbOj7dHPULxVGbH9IbPK76TCwLbF7ikIMsPovVbTrpyL6vsbVUKeEl/5GKppTwp9DLAOeoSYpCYkkDkYKu9TRQjF02MCAwEAAaNQME4wHQYDVR0OBBYEFP2ut2AQdy6D1dwdwK740IHmbh38MB8GA1UdIwQYMBaAFP2ut2AQdy6D1dwdwK740IHmbh38MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBANMZUoPNmHzgja2PYkbvBYMHmpvUkVoiuvQ9cJPlqGTB2CRfG68BNNs/Clz8P7cIrAdkhCUwi1rSBhDuslGFNrSaIpv6B10FpBuKwef3G7YrPWFNEN6khY7aHNWSTHqKgs1DrGef2B9hvkrnHWbQVSVXrBFKe1wTCqcgGcOpYoSK7L8C6iX6uIA/uZYnVQ4NgBrizJ0azkjdegz3hwO/gt4malEURy8D85/AAVt6PAzhpb9VJUGxSXr/EfntVUEz3L2gUFWWk1CnZFyz0rIOEt/zPmeAY8BLyd/Tjxm4Y+gwNazKq5y9AJS+m858b/nM4QdCnUE4yyoWAJDUHiAmvFA=https://idp.example.com/metadata_ce3d2948b4cf20146dee0a0b3dd6f69b6cf86f62d7https://sp.example.com/metadataurn:oasis:names:tc:SAML:2.0:ac:classes:Passwordtesttest@example.comusersexamplerole1
--------------------------------------------------------------------------------
/test/misc/response_signed_cert2.xml:
--------------------------------------------------------------------------------
1 | https://idp.example.com/metadataiPlh1ZRFuCBV07ayPRWVk7xU9SB5JN8mu6xAab3lEo0=ECKTz4y6czJx+KGlZNb8E6mBnFrMQC8hL7YDlAi8dko=JgrKOwRaj4swHYgLra3MOG92BeekCyRgbDfxAk5KLmzeRk1u0w6AmB/qW32mrlM4bn8LtwTq33PiHk6NMbkOfg5X2jQ8vjRyog+tgxDmwdiVkMMHfTWHcOqI5Gou572GayDLC0M9rOv4iHXUoDaul4ozhkeRolS9peLxydulSLzyXJiMGQ9ChnmxsR1P7y1rU/DOJ4O/zWzY2M9GoKBXWwG5C9RuoiO7FfOQn4za7InoQ+pBAtGWeh3mXwKLYpd+dhWL73vLa2sr5OmOQUlnFDSuFoAzhnT9eJEJCcedfmtjTUi724iAcYtFeXYahcCe/n4H2JjQYhE0ovG4JpEaThRA/sM3C6h3j7t9b+fX86VhH71+0f79VuX9TNeQkSiuYxqbUYvJjNgx3z8W7ixv5WGpHCjq6zd5KKbIwGk2+bWp7xs6ZD8sh9uyqWHNX/7YE096Ovxn4ki9O370MnK/3henA3m/+lwwWaL3Bn6+TmYC5DOWM7WVhy+dokSW6/2ZhgzoehpbDVZfYkKP+SH1w2PEqwtyB60fJpcTHZFANbCzfLJuyuRjiaWl9lzc3sKsRlK8W76ro/lXeIX2Jal1pQpkctZRUc0RyL+l9EnqzRnPc1K9nGUI+a8PNS54clILe0silqt339ZaE+wkslvhZ1M8oLzsWcXFWD+x2JZkvbo=MIIFLjCCAxYCCQCqGHhTssya9jANBgkqhkiG9w0BAQsFADBZMQswCQYDVQQGEwJISzESMBAGA1UECAwJSG9uZyBLb25nMRIwEAYDVQQHDAlIb25nIEtvbmcxEDAOBgNVBAoMB3NhbWxpZnkxEDAOBgNVBAMMB3NhbWxpZnkwHhcNMjAwNTEwMTUyNjIzWhcNMzAwNTA4MTUyNjIzWjBZMQswCQYDVQQGEwJISzESMBAGA1UECAwJSG9uZyBLb25nMRIwEAYDVQQHDAlIb25nIEtvbmcxEDAOBgNVBAoMB3NhbWxpZnkxEDAOBgNVBAMMB3NhbWxpZnkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDQG+abAeeWjwsOZt5SkcNcw/XSJcjSyJykEbEU2iguErRuOIyBfgj0p1UVBv33uL2igeYJT3OSXmSjvMO8KvqtYN2tJAjoFjghGr8NbIEZjYS4ukMZUbwxd2bRycD9OMI9g44AUB1sfQ0UyFwzEOseW3lcW1FnhcizA8TgI0GN4NpdVruNlpgoWdP3w+Syhtq0rWebY8g/HGFruEKn8VwbUblOZdP7jNVXsd1aUMScpuMa0khzzXPDN+Q0rwl79fO4ychSeKAAERdPXA1UfDfbh9W7pcYBP0ABXd91Bf9akplmbbVOIsNbuRIcVS7WvLwCr613JuJ+EtGDcUkrSpbuRvDW85DQRHBGuoKlcSG+imHQtHqRwMwMc8P54hIEBvaFW0RfwPfzdFNe8wARtmvIeX84iwq5Yey15Ly1rdopi7t2g7qyF7C/B9gZ3tJ/gPKp2NrdCGFBcahl93Lj56WWmI0jNHn7+7Y3x6isJ3KTRXIliSrAwiK7/7UezOlWzs1k8mGQWZTD3AGGKu1cBVwuC+rh4wkLsDeHfzxavbXxVEok9p/1P28M4GiHfS0POE3Hl4RT3Q6AiYWnmFYyZ+smY97SgPwB4tTNYFjC6+9d/BllNoQb8wsPjqp6ZDn1OeY668hp+ZAcE13AFdiTBMVrcdEECCPLxg1kFk5wZdHrGwIDAQABMA0GCSqGSIb3DQEBCwUAA4ICAQCyA/14hKTqfdeOVl+MQ2SLPWi7pC/t/Zv4kc361xP26FAVSSrxgXq9kVLZeJIAqCwjGHkl/DTUlA8hfLfuZx5z+NI/qIodsXAjCzsCe7paEbjvR6OQjYkR0UY4u/AOO7x2op2KDFKNuWT9KZNm8bh1mxwNKep1fJP2O5M0nMYAGYbPsLAOn7mzZyufQl8hsJwIV2s8sbft7s8vmEYZbuueQDOJCMTt+eC08LONrovYChyYmj3i5RIk8kcaodeSDo811F1B1gDvO/dmVxgrHEgoai7X6LUoiAiLkigP7udNEZxbXsRlOhBRv9w+rRXFurVFlUPkQ9UF+QB0BoyIcUxo+fZ8vCA4xEVBenVBadpFbwum6+XeTkvDoRc4sSCpm8v2qtprc8aU/0F82EzxSybYvstc5lDv7wuwCwNwfoAQ+/16kTpJvoYbOXUPv5yCA3mIuqYeA1woaWPXsE4jNOzTqv1qOZQTvXProEgK5B0FR5ILc4mfNrD2p9VGbiYf2GjCfeEzDFg174dvSn2MMp1yK5pvZEp7yFE8z1eduYN6W/7qdtss9BGpnyS5X7LuYfDvd1dHP6/JuqJDbfSVG9prYWcaMRd3FzSC7jBeetJgMyj4dunfqw8R16aONhwvICtzdFa93hYrDvTyo3ae80KFi0WGgApKeoqO5t3l1PAcaA==https://idp.example.com/metadata_ce3d2948b4cf20146dee0a0b3dd6f69b6cf86f62d7https://sp.example.com/metadataurn:oasis:names:tc:SAML:2.0:ac:classes:Passwordtesttest@example.comusersexamplerole1
--------------------------------------------------------------------------------
/test/misc/signed_request_sha1.xml:
--------------------------------------------------------------------------------
1 | https://sp.example.org/metadataurn:oasis:names:tc:SAML:2.0:ac:classes:PasswordtQDisBXKTQ+9OXJO5r7KuJga+KI=oxRkvau7UvYgFEZ7YNAUNf3067V7Tn5C9XSIiet1aZw2FYevNW5bUy/0mxp3aj6AvfFjnmpzAb88BjdwAz2BErDTomRcuZB7Lb0fYTf31N2oZOX0MiPiQOH54I63qJW4Xo3VqdF7GBuFZZHyllfSBv7gfCtjJDwFSCzWK70B9r3cFMRJZLhCJ9oPen+4U9scSYO6g+szBZLl6AiJ06PHc8jzEKGwfQrcZk8kDKUlvNfJMULyq8dpx2VvUAx4p5ewfMOwB9W3Hl3PPa0dO77zZif3CglpcN06f+m6UYG/wnoTQEyKW9hOe+2vGM80W77eWu0dmiaPuqT1ok8LXPuq1A==
2 |
--------------------------------------------------------------------------------
/test/misc/signed_request_sha256.xml:
--------------------------------------------------------------------------------
1 | http://localhost:4002/sso/metadata9Ftynct5x7o+SdQM9iie2Z8VzZW95OTtXh4BD4O/HP8=EjCY0hdmiULo0qRy8tJeSANz3uINpdyFmCISiid4vl3KtszPa1mLvx1wGO2RJiFW8Sa18JOS0l8rYP2gwoUYmxU5WS/Cl1QEMlDj46fPpOjEBELGXdKW69zpAHa5jM/FtS8RCixhiMI1dmbL3+zgziEVdx5xrkaakqvpdDD601Eyn0gy1oO+VUmCMPFE6YjsPeFDhw5ZXf7MmJ/fXLeqWmH5Pn+mkyTCZWxi/L+2nG9iayZ41Z3wBl67XTdBL6rwHMcEY7oxwFSZtKTbtTOV6aW11KdAd9peLIsHeqoaMCY/VypS2bTr9FubQCbHhho2vbhX8cuUfpE21OefA7o1rA==MIIDozCCAougAwIBAgIJAKNsmL8QbfpwMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNVBAYTAkhLMRIwEAYDVQQIDAlIb25nIEtvbmcxCzAJBgNVBAcMAkhLMRMwEQYDVQQKDApub2RlLXNhbWwyMSMwIQYJKoZIhvcNAQkBFhRub2RlLnNhbWwyQGdtYWlsLmNvbTAeFw0xNTA3MDUxNzU2NDdaFw0xODA3MDQxNzU2NDdaMGgxCzAJBgNVBAYTAkhLMRIwEAYDVQQIDAlIb25nIEtvbmcxCzAJBgNVBAcMAkhLMRMwEQYDVQQKDApub2RlLXNhbWwyMSMwIQYJKoZIhvcNAQkBFhRub2RlLnNhbWwyQGdtYWlsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMQJAB8JrsLQbUuJa8akzLqO1EZqClS0tQp+w+5wgufp07WwGn/shma8dcQNj1dbjszI5HBeVFjOKIxlfjmNB9ovhQPstBjP/UPQYp1Ip2IoHCYX9HDgMz3xyXKbHthUzZaECz+p+7WtgwhczRkBLDOm2k15qhPYGPw0vH2zbVRGWUBS9dy2Mp3tqlVbP0xZ9CDNkhCJkV9SMNfoCVW/VYPqK2QBo7ki4obm5x5ixFQSSHsKbVARVzyQH5iNjFe1TdAp3rDwrE5Lc1NQlQaxR5Gnb2NZApDORRZIVlNv2WUdi9QvM0yCzjQ90jP0OAogHhRYaxg0/vgNEye46h+PiY0CAwEAAaNQME4wHQYDVR0OBBYEFEVkjcLAITndky090Ay74QqCmQKIMB8GA1UdIwQYMBaAFEVkjcLAITndky090Ay74QqCmQKIMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAG4lYX3KQXenez4LpDnZhcFBEZi9YstUKPF5EKd+WplpVbcTQc1A3/Z+uHRmyV8h+pQzeF6Liob37G87YpacPplJI66cf2Rj7j8hSBNbdr+66E2qpcEhAF1iJmzBNyhb/ydlEuVpn8/EsoP+HvBeiDl5gon3562MzZIgV/pLdTfxHyW6hzAQhjGq2UhcvR+gXNVJvHP2eS4jlHnJkB9bfo0kvf87Q+D6XKX3q5c3mO8tqW6UpqHSC+uLEpzZiNLeuFa4TUIhgBgjDjlRrNDKu8ndancSn3yBHYnqJ2t9cR+coFnnjYABQpNrvk4mtmXY8SXoBzYG9Y+lqeAun6+0YyE=
2 |
--------------------------------------------------------------------------------
/test/misc/signed_request_sha512.xml:
--------------------------------------------------------------------------------
1 | http://localhost:4002/sso/metadata9Ftynct5x7o+SdQM9iie2Z8VzZW95OTtXh4BD4O/HP8=dk+CI6UvXgsM0cHAGAz/Y3gbvehbab92i1jEUmDH0QB7d6/3l7j7TuOEvUFnmtwa0kwpigwpySwXybfiuvgdSBmhejwng5m28bYqaIA8FgCWe/BkBVL5BYeQH03gPbnqhBpC5EXUe52FtOlGAoTGNqaD0pyrshoGiOj/OzqVZC7RSBvvYt5iwpLyqj4KIFFao4yNAfIs2n7RwfcbGg3I2m2b5nuhVppRdzzukdQiLdDCuATPDxKJ3KdETbHb3yss+8L2iDPcAoqsZ+UTZ8VI5DhrQBcarcIe8Xp2FUKQnC4n0AEqCpb87l6txPz7GYDaw9yMqe2xD5LPWQ6/2guvqw==MIIDozCCAougAwIBAgIJAKNsmL8QbfpwMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNVBAYTAkhLMRIwEAYDVQQIDAlIb25nIEtvbmcxCzAJBgNVBAcMAkhLMRMwEQYDVQQKDApub2RlLXNhbWwyMSMwIQYJKoZIhvcNAQkBFhRub2RlLnNhbWwyQGdtYWlsLmNvbTAeFw0xNTA3MDUxNzU2NDdaFw0xODA3MDQxNzU2NDdaMGgxCzAJBgNVBAYTAkhLMRIwEAYDVQQIDAlIb25nIEtvbmcxCzAJBgNVBAcMAkhLMRMwEQYDVQQKDApub2RlLXNhbWwyMSMwIQYJKoZIhvcNAQkBFhRub2RlLnNhbWwyQGdtYWlsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMQJAB8JrsLQbUuJa8akzLqO1EZqClS0tQp+w+5wgufp07WwGn/shma8dcQNj1dbjszI5HBeVFjOKIxlfjmNB9ovhQPstBjP/UPQYp1Ip2IoHCYX9HDgMz3xyXKbHthUzZaECz+p+7WtgwhczRkBLDOm2k15qhPYGPw0vH2zbVRGWUBS9dy2Mp3tqlVbP0xZ9CDNkhCJkV9SMNfoCVW/VYPqK2QBo7ki4obm5x5ixFQSSHsKbVARVzyQH5iNjFe1TdAp3rDwrE5Lc1NQlQaxR5Gnb2NZApDORRZIVlNv2WUdi9QvM0yCzjQ90jP0OAogHhRYaxg0/vgNEye46h+PiY0CAwEAAaNQME4wHQYDVR0OBBYEFEVkjcLAITndky090Ay74QqCmQKIMB8GA1UdIwQYMBaAFEVkjcLAITndky090Ay74QqCmQKIMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAG4lYX3KQXenez4LpDnZhcFBEZi9YstUKPF5EKd+WplpVbcTQc1A3/Z+uHRmyV8h+pQzeF6Liob37G87YpacPplJI66cf2Rj7j8hSBNbdr+66E2qpcEhAF1iJmzBNyhb/ydlEuVpn8/EsoP+HvBeiDl5gon3562MzZIgV/pLdTfxHyW6hzAQhjGq2UhcvR+gXNVJvHP2eS4jlHnJkB9bfo0kvf87Q+D6XKX3q5c3mO8tqW6UpqHSC+uLEpzZiNLeuFa4TUIhgBgjDjlRrNDKu8ndancSn3yBHYnqJ2t9cR+coFnnjYABQpNrvk4mtmXY8SXoBzYG9Y+lqeAun6+0YyE=
2 |
--------------------------------------------------------------------------------
/test/misc/signed_response_sha1.xml:
--------------------------------------------------------------------------------
1 | https://idp.example.com/metadataCocGj4j5psQ0OfZ1mOlAdQkfwjTqCb95tNqpiFtt6qhTlnn+1IIp9pDpMLubomf9LWwX176PPLWFYxsRmqyEBYlhT53hgAF+z2fEgJdlxXF7FYKsnsn+ujC0ZJP3QkUlWGT9eo74i67JrkAwmiOXPHBJAAN040L/uqmYgjqdnGIFZAyTk4SwplECf1yzVxh4wkETpkf1na1VgTpFC3QDHpXVmCdTbq4FgtgNyfcZmr10d81rmSLjwfHJswV8Qg+cuxXODcn0rxDA5ZA3abpIxGwHUMtKP8ak4amY1urWQTXkhaFjZIChA6E4p870MzfmzVExG6p8/svKf2vDHTAH0w==MIIDlzCCAn+gAwIBAgIJAO1ymQc33+bWMA0GCSqGSIb3DQEBCwUAMGIxCzAJBgNVBAYTAkhLMRMwEQYDVQQIDApTb21lLVN0YXRlMRowGAYDVQQKDBFJZGVudGl0eSBQcm92aWRlcjEUMBIGA1UECwwLRGV2ZWxvcG1lbnQxDDAKBgNVBAMMA0lEUDAeFw0xNTA3MDUxODAyMjdaFw0xODA3MDQxODAyMjdaMGIxCzAJBgNVBAYTAkhLMRMwEQYDVQQIDApTb21lLVN0YXRlMRowGAYDVQQKDBFJZGVudGl0eSBQcm92aWRlcjEUMBIGA1UECwwLRGV2ZWxvcG1lbnQxDDAKBgNVBAMMA0lEUDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAODZsWhCe+yG0PalQPTUoD7yko5MTWMCRxJ8hSm2k7mG3Eg/Y2v0EBdCmTw7iDCevRqUmbmFnq7MROyV4eriJzh0KabAdZf7/k6koghst3ZUtWOwzshyxkBtWDwGmBpQGTGsKxJ8M1js3aSqNRXBT4OBWM9w2Glt1+8ty30RhYv3pSF+/HHLH7Ac+vLSIAlokaFW34RWTcJ/8rADuRWlXih4GfnIu0W/ncm5nTSaJiRAvr3dGDRO/khiXoJdbbOj7dHPULxVGbH9IbPK76TCwLbF7ikIMsPovVbTrpyL6vsbVUKeEl/5GKppTwp9DLAOeoSYpCYkkDkYKu9TRQjF02MCAwEAAaNQME4wHQYDVR0OBBYEFP2ut2AQdy6D1dwdwK740IHmbh38MB8GA1UdIwQYMBaAFP2ut2AQdy6D1dwdwK740IHmbh38MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBANMZUoPNmHzgja2PYkbvBYMHmpvUkVoiuvQ9cJPlqGTB2CRfG68BNNs/Clz8P7cIrAdkhCUwi1rSBhDuslGFNrSaIpv6B10FpBuKwef3G7YrPWFNEN6khY7aHNWSTHqKgs1DrGef2B9hvkrnHWbQVSVXrBFKe1wTCqcgGcOpYoSK7L8C6iX6uIA/uZYnVQ4NgBrizJ0azkjdegz3hwO/gt4malEURy8D85/AAVt6PAzhpb9VJUGxSXr/EfntVUEz3L2gUFWWk1CnZFyz0rIOEt/zPmeAY8BLyd/Tjxm4Y+gwNazKq5y9AJS+m858b/nM4QdCnUE4yyoWAJDUHiAmvFA=https://idp.example.com/metadata_ce3d2948b4cf20146dee0a0b3dd6f69b6cf86f62d7https://sp.example.com/metadataurn:oasis:names:tc:SAML:2.0:ac:classes:Passwordtesttest@example.comusersexamplerole1
--------------------------------------------------------------------------------
/test/misc/signed_response_sha256.xml:
--------------------------------------------------------------------------------
1 | https://idp.example.com/metadata0TJreH5fvSPwTL8cMGtvYkc8mDQDirHL/0KAU0PPjWXKUqyWSVi7FtDhnAuUakJpfPaYowrHBaUkX+SoJC9uQjXNCgvx5Z7DJfNq+h/vFxoSoxMT/1qeKMKWoNQFVmUErIPMCl0Wou/MfDR8qd+0ofUyLF4pEglczqNBVGi23RirDMZGSgS9M6QDlgpTx/CDnWRL6+0T1lNrTLuX6n0VaEziUeHOHY0lK5T0hmT/tVlufZ7LRO10FN7MUrxzIZvIIWVNuPVOmn0hm/4Z33JEK7rT35+MZLq8f7fbA3SS4+4InJOvZZgBRR9BcPjeEXG1n1el7uyf2AfE9+gr3vu6eg==MIIDlzCCAn+gAwIBAgIJAO1ymQc33+bWMA0GCSqGSIb3DQEBCwUAMGIxCzAJBgNVBAYTAkhLMRMwEQYDVQQIDApTb21lLVN0YXRlMRowGAYDVQQKDBFJZGVudGl0eSBQcm92aWRlcjEUMBIGA1UECwwLRGV2ZWxvcG1lbnQxDDAKBgNVBAMMA0lEUDAeFw0xNTA3MDUxODAyMjdaFw0xODA3MDQxODAyMjdaMGIxCzAJBgNVBAYTAkhLMRMwEQYDVQQIDApTb21lLVN0YXRlMRowGAYDVQQKDBFJZGVudGl0eSBQcm92aWRlcjEUMBIGA1UECwwLRGV2ZWxvcG1lbnQxDDAKBgNVBAMMA0lEUDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAODZsWhCe+yG0PalQPTUoD7yko5MTWMCRxJ8hSm2k7mG3Eg/Y2v0EBdCmTw7iDCevRqUmbmFnq7MROyV4eriJzh0KabAdZf7/k6koghst3ZUtWOwzshyxkBtWDwGmBpQGTGsKxJ8M1js3aSqNRXBT4OBWM9w2Glt1+8ty30RhYv3pSF+/HHLH7Ac+vLSIAlokaFW34RWTcJ/8rADuRWlXih4GfnIu0W/ncm5nTSaJiRAvr3dGDRO/khiXoJdbbOj7dHPULxVGbH9IbPK76TCwLbF7ikIMsPovVbTrpyL6vsbVUKeEl/5GKppTwp9DLAOeoSYpCYkkDkYKu9TRQjF02MCAwEAAaNQME4wHQYDVR0OBBYEFP2ut2AQdy6D1dwdwK740IHmbh38MB8GA1UdIwQYMBaAFP2ut2AQdy6D1dwdwK740IHmbh38MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBANMZUoPNmHzgja2PYkbvBYMHmpvUkVoiuvQ9cJPlqGTB2CRfG68BNNs/Clz8P7cIrAdkhCUwi1rSBhDuslGFNrSaIpv6B10FpBuKwef3G7YrPWFNEN6khY7aHNWSTHqKgs1DrGef2B9hvkrnHWbQVSVXrBFKe1wTCqcgGcOpYoSK7L8C6iX6uIA/uZYnVQ4NgBrizJ0azkjdegz3hwO/gt4malEURy8D85/AAVt6PAzhpb9VJUGxSXr/EfntVUEz3L2gUFWWk1CnZFyz0rIOEt/zPmeAY8BLyd/Tjxm4Y+gwNazKq5y9AJS+m858b/nM4QdCnUE4yyoWAJDUHiAmvFA=https://idp.example.com/metadata_ce3d2948b4cf20146dee0a0b3dd6f69b6cf86f62d7https://sp.example.com/metadataurn:oasis:names:tc:SAML:2.0:ac:classes:Passwordtesttest@example.comusersexamplerole1
--------------------------------------------------------------------------------
/test/misc/signed_response_sha512.xml:
--------------------------------------------------------------------------------
1 | https://idp.example.com/metadataRkgzPlU7snHmrHTA6tCt0DRqQFyQeNypGIFzaY+2/6OLsNNH0B4gdBWYUWrwMpOGNqHr9Wo+th248ABVoUBtbdQ2pT8M49D0JDGwvl6L8CscTK0xzLGaqaAhHwszmk61WGVOxrbkiZQqOQA8VDiua5bDoXOqiCqEIB6TlSuJ+HH4Lc6u10WSXChI5iC9YwsHoWS8tqFLw6rsx4qPx4hFkZfBUh6JFZNT8hsWiSr4y6d359SIkRgkPUd85+I/3Od//al4HLnIjXaDsahO/YZ9AlvOnBxjUEuk/7kuxZ91LDeI6I8ekno83+ndhk34tnaBc3l1uGeHNhJhpY3eK+LiCw==MIIDlzCCAn+gAwIBAgIJAO1ymQc33+bWMA0GCSqGSIb3DQEBCwUAMGIxCzAJBgNVBAYTAkhLMRMwEQYDVQQIDApTb21lLVN0YXRlMRowGAYDVQQKDBFJZGVudGl0eSBQcm92aWRlcjEUMBIGA1UECwwLRGV2ZWxvcG1lbnQxDDAKBgNVBAMMA0lEUDAeFw0xNTA3MDUxODAyMjdaFw0xODA3MDQxODAyMjdaMGIxCzAJBgNVBAYTAkhLMRMwEQYDVQQIDApTb21lLVN0YXRlMRowGAYDVQQKDBFJZGVudGl0eSBQcm92aWRlcjEUMBIGA1UECwwLRGV2ZWxvcG1lbnQxDDAKBgNVBAMMA0lEUDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAODZsWhCe+yG0PalQPTUoD7yko5MTWMCRxJ8hSm2k7mG3Eg/Y2v0EBdCmTw7iDCevRqUmbmFnq7MROyV4eriJzh0KabAdZf7/k6koghst3ZUtWOwzshyxkBtWDwGmBpQGTGsKxJ8M1js3aSqNRXBT4OBWM9w2Glt1+8ty30RhYv3pSF+/HHLH7Ac+vLSIAlokaFW34RWTcJ/8rADuRWlXih4GfnIu0W/ncm5nTSaJiRAvr3dGDRO/khiXoJdbbOj7dHPULxVGbH9IbPK76TCwLbF7ikIMsPovVbTrpyL6vsbVUKeEl/5GKppTwp9DLAOeoSYpCYkkDkYKu9TRQjF02MCAwEAAaNQME4wHQYDVR0OBBYEFP2ut2AQdy6D1dwdwK740IHmbh38MB8GA1UdIwQYMBaAFP2ut2AQdy6D1dwdwK740IHmbh38MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBANMZUoPNmHzgja2PYkbvBYMHmpvUkVoiuvQ9cJPlqGTB2CRfG68BNNs/Clz8P7cIrAdkhCUwi1rSBhDuslGFNrSaIpv6B10FpBuKwef3G7YrPWFNEN6khY7aHNWSTHqKgs1DrGef2B9hvkrnHWbQVSVXrBFKe1wTCqcgGcOpYoSK7L8C6iX6uIA/uZYnVQ4NgBrizJ0azkjdegz3hwO/gt4malEURy8D85/AAVt6PAzhpb9VJUGxSXr/EfntVUEz3L2gUFWWk1CnZFyz0rIOEt/zPmeAY8BLyd/Tjxm4Y+gwNazKq5y9AJS+m858b/nM4QdCnUE4yyoWAJDUHiAmvFA=https://idp.example.com/metadata_ce3d2948b4cf20146dee0a0b3dd6f69b6cf86f62d7https://sp.example.com/metadataurn:oasis:names:tc:SAML:2.0:ac:classes:Passwordtesttest@example.comusersexamplerole1
--------------------------------------------------------------------------------
/test/misc/sp_metadata_98.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | urn:oasis:names:tc:SAML:2.0:nameid-format:transient
4 |
5 |
6 |
--------------------------------------------------------------------------------
/test/misc/spmeta.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 | MIIDozCCAougAwIBAgIJAKNsmL8QbfpwMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNVBAYTAkhLMRIwEAYDVQQIDAlIb25nIEtvbmcxCzAJBgNVBAcMAkhLMRMwEQYDVQQKDApub2RlLXNhbWwyMSMwIQYJKoZIhvcNAQkBFhRub2RlLnNhbWwyQGdtYWlsLmNvbTAeFw0xNTA3MDUxNzU2NDdaFw0xODA3MDQxNzU2NDdaMGgxCzAJBgNVBAYTAkhLMRIwEAYDVQQIDAlIb25nIEtvbmcxCzAJBgNVBAcMAkhLMRMwEQYDVQQKDApub2RlLXNhbWwyMSMwIQYJKoZIhvcNAQkBFhRub2RlLnNhbWwyQGdtYWlsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMQJAB8JrsLQbUuJa8akzLqO1EZqClS0tQp+w+5wgufp07WwGn/shma8dcQNj1dbjszI5HBeVFjOKIxlfjmNB9ovhQPstBjP/UPQYp1Ip2IoHCYX9HDgMz3xyXKbHthUzZaECz+p+7WtgwhczRkBLDOm2k15qhPYGPw0vH2zbVRGWUBS9dy2Mp3tqlVbP0xZ9CDNkhCJkV9SMNfoCVW/VYPqK2QBo7ki4obm5x5ixFQSSHsKbVARVzyQH5iNjFe1TdAp3rDwrE5Lc1NQlQaxR5Gnb2NZApDORRZIVlNv2WUdi9QvM0yCzjQ90jP0OAogHhRYaxg0/vgNEye46h+PiY0CAwEAAaNQME4wHQYDVR0OBBYEFEVkjcLAITndky090Ay74QqCmQKIMB8GA1UdIwQYMBaAFEVkjcLAITndky090Ay74QqCmQKIMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAG4lYX3KQXenez4LpDnZhcFBEZi9YstUKPF5EKd+WplpVbcTQc1A3/Z+uHRmyV8h+pQzeF6Liob37G87YpacPplJI66cf2Rj7j8hSBNbdr+66E2qpcEhAF1iJmzBNyhb/ydlEuVpn8/EsoP+HvBeiDl5gon3562MzZIgV/pLdTfxHyW6hzAQhjGq2UhcvR+gXNVJvHP2eS4jlHnJkB9bfo0kvf87Q+D6XKX3q5c3mO8tqW6UpqHSC+uLEpzZiNLeuFa4TUIhgBgjDjlRrNDKu8ndancSn3yBHYnqJ2t9cR+coFnnjYABQpNrvk4mtmXY8SXoBzYG9Y+lqeAun6+0YyE=
11 |
12 |
13 |
14 |
15 |
16 |
17 | MIID7TCCAtWgAwIBAgIJANSq1uUtXl4DMA0GCSqGSIb3DQEBCwUAMFcxCzAJBgNVBAYTAkhLMRIwEAYDVQQIEwlIb25nIEtvbmcxFjAUBgNVBAoTDWV4cHJlc3Mtc2FtbDIxDDAKBgNVBAsTA2RldjEOMAwGA1UEAxMFZXNhbWwwHhcNMTUxMDAzMDM0ODA2WhcNMTgxMDAyMDM0ODA2WjBXMQswCQYDVQQGEwJISzESMBAGA1UECBMJSG9uZyBLb25nMRYwFAYDVQQKEw1leHByZXNzLXNhbWwyMQwwCgYDVQQLEwNkZXYxDjAMBgNVBAMTBWVzYW1sMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyx/yIgvJwfOCwMTNjL4Fslr21ky4O/uzxp0Y8wpHk9jk8Afcj3plQCr5X8dPKG2Rz4EIh//nQQL9tq2InaUdRwJkS9SeuuAcJG7DN/KDUtfrh4+cO2lZ4h7cQIdjpbBgpGEMhGy1wwpwHJsadoBuX0PKyT4O4oHkj1gwWO14qYnK4biviNBqmjGjmN+py+lUcACsQt22abA4s8Xjm/tlvnkgNRE3H44ICvSr8m5MVhyYGoAUe7Qprn2BcsMXd9mrlZ5hEdalNUDRbKb+W7mrKEkKFCbE3wi/Ns2bc4fbNXvwcZoF3/TPzl936u2eivTQESjCLsymIqdYHwRiVLifWQIDAQABo4G7MIG4MB0GA1UdDgQWBBSdBiMAVhKrjzd72sncR13imevq/DCBiAYDVR0jBIGAMH6AFJ0GIwBWEquPN3vaydxHXeKZ6+r8oVukWTBXMQswCQYDVQQGEwJISzESMBAGA1UECBMJSG9uZyBLb25nMRYwFAYDVQQKEw1leHByZXNzLXNhbWwyMQwwCgYDVQQLEwNkZXYxDjAMBgNVBAMTBWVzYW1sggkA1KrW5S1eXgMwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEARi25PJOR+x0ytYCmfXwG5LSXKNHx5BD6G+nBgXm1/DMMJ9ZY34FYMF3gDUu+NmQoVegqARTxetQcCICpAPdKnK0yQb6MXdj3VfQnEA+4hVGFmqnHTK90g0BudEmp1fWKBjJYpLd0oncVwJQJDK5OfS7fMUftN6/Kg6/fDuJMCNIECfKRE8tiXz2Ht924MjedKlH0+qoV1F2Fy5as+QRbj/QfrPTrZrfqhP04mavTPL2bdW6+ykeQWN3zMQtJA8kt2LI0y0CIGhFjLbqAceq+gDkp4drj7/Yw8qaqmxl6GP8w3GbfLu6mXCjCLCGgsATktvWq9dRfBuapaIpNDrv0NA==
18 |
19 |
20 |
21 | urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/test/misc/spmeta_noassertsign.xml:
--------------------------------------------------------------------------------
1 |
6 |
10 |
11 |
12 |
13 | MIIDozCCAougAwIBAgIJAKNsmL8QbfpwMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNVBAYTAkhLMRIwEAYDVQQIDAlIb25nIEtvbmcxCzAJBgNVBAcMAkhLMRMwEQYDVQQKDApub2RlLXNhbWwyMSMwIQYJKoZIhvcNAQkBFhRub2RlLnNhbWwyQGdtYWlsLmNvbTAeFw0xNTA3MDUxNzU2NDdaFw0xODA3MDQxNzU2NDdaMGgxCzAJBgNVBAYTAkhLMRIwEAYDVQQIDAlIb25nIEtvbmcxCzAJBgNVBAcMAkhLMRMwEQYDVQQKDApub2RlLXNhbWwyMSMwIQYJKoZIhvcNAQkBFhRub2RlLnNhbWwyQGdtYWlsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMQJAB8JrsLQbUuJa8akzLqO1EZqClS0tQp+w+5wgufp07WwGn/shma8dcQNj1dbjszI5HBeVFjOKIxlfjmNB9ovhQPstBjP/UPQYp1Ip2IoHCYX9HDgMz3xyXKbHthUzZaECz+p+7WtgwhczRkBLDOm2k15qhPYGPw0vH2zbVRGWUBS9dy2Mp3tqlVbP0xZ9CDNkhCJkV9SMNfoCVW/VYPqK2QBo7ki4obm5x5ixFQSSHsKbVARVzyQH5iNjFe1TdAp3rDwrE5Lc1NQlQaxR5Gnb2NZApDORRZIVlNv2WUdi9QvM0yCzjQ90jP0OAogHhRYaxg0/vgNEye46h+PiY0CAwEAAaNQME4wHQYDVR0OBBYEFEVkjcLAITndky090Ay74QqCmQKIMB8GA1UdIwQYMBaAFEVkjcLAITndky090Ay74QqCmQKIMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAG4lYX3KQXenez4LpDnZhcFBEZi9YstUKPF5EKd+WplpVbcTQc1A3/Z+uHRmyV8h+pQzeF6Liob37G87YpacPplJI66cf2Rj7j8hSBNbdr+66E2qpcEhAF1iJmzBNyhb/ydlEuVpn8/EsoP+HvBeiDl5gon3562MzZIgV/pLdTfxHyW6hzAQhjGq2UhcvR+gXNVJvHP2eS4jlHnJkB9bfo0kvf87Q+D6XKX3q5c3mO8tqW6UpqHSC+uLEpzZiNLeuFa4TUIhgBgjDjlRrNDKu8ndancSn3yBHYnqJ2t9cR+coFnnjYABQpNrvk4mtmXY8SXoBzYG9Y+lqeAun6+0YyE=
14 |
15 |
16 |
17 |
18 |
19 |
20 | MIID7TCCAtWgAwIBAgIJANSq1uUtXl4DMA0GCSqGSIb3DQEBCwUAMFcxCzAJBgNVBAYTAkhLMRIwEAYDVQQIEwlIb25nIEtvbmcxFjAUBgNVBAoTDWV4cHJlc3Mtc2FtbDIxDDAKBgNVBAsTA2RldjEOMAwGA1UEAxMFZXNhbWwwHhcNMTUxMDAzMDM0ODA2WhcNMTgxMDAyMDM0ODA2WjBXMQswCQYDVQQGEwJISzESMBAGA1UECBMJSG9uZyBLb25nMRYwFAYDVQQKEw1leHByZXNzLXNhbWwyMQwwCgYDVQQLEwNkZXYxDjAMBgNVBAMTBWVzYW1sMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyx/yIgvJwfOCwMTNjL4Fslr21ky4O/uzxp0Y8wpHk9jk8Afcj3plQCr5X8dPKG2Rz4EIh//nQQL9tq2InaUdRwJkS9SeuuAcJG7DN/KDUtfrh4+cO2lZ4h7cQIdjpbBgpGEMhGy1wwpwHJsadoBuX0PKyT4O4oHkj1gwWO14qYnK4biviNBqmjGjmN+py+lUcACsQt22abA4s8Xjm/tlvnkgNRE3H44ICvSr8m5MVhyYGoAUe7Qprn2BcsMXd9mrlZ5hEdalNUDRbKb+W7mrKEkKFCbE3wi/Ns2bc4fbNXvwcZoF3/TPzl936u2eivTQESjCLsymIqdYHwRiVLifWQIDAQABo4G7MIG4MB0GA1UdDgQWBBSdBiMAVhKrjzd72sncR13imevq/DCBiAYDVR0jBIGAMH6AFJ0GIwBWEquPN3vaydxHXeKZ6+r8oVukWTBXMQswCQYDVQQGEwJISzESMBAGA1UECBMJSG9uZyBLb25nMRYwFAYDVQQKEw1leHByZXNzLXNhbWwyMQwwCgYDVQQLEwNkZXYxDjAMBgNVBAMTBWVzYW1sggkA1KrW5S1eXgMwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEARi25PJOR+x0ytYCmfXwG5LSXKNHx5BD6G+nBgXm1/DMMJ9ZY34FYMF3gDUu+NmQoVegqARTxetQcCICpAPdKnK0yQb6MXdj3VfQnEA+4hVGFmqnHTK90g0BudEmp1fWKBjJYpLd0oncVwJQJDK5OfS7fMUftN6/Kg6/fDuJMCNIECfKRE8tiXz2Ht924MjedKlH0+qoV1F2Fy5as+QRbj/QfrPTrZrfqhP04mavTPL2bdW6+ykeQWN3zMQtJA8kt2LI0y0CIGhFjLbqAceq+gDkp4drj7/Yw8qaqmxl6GP8w3GbfLu6mXCjCLCGgsATktvWq9dRfBuapaIpNDrv0NA==
21 |
22 |
23 |
24 | urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
25 |
28 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/test/misc/spmeta_noauthnsign.xml:
--------------------------------------------------------------------------------
1 |
6 |
10 |
11 |
12 |
13 | MIIDozCCAougAwIBAgIJAKNsmL8QbfpwMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNVBAYTAkhLMRIwEAYDVQQIDAlIb25nIEtvbmcxCzAJBgNVBAcMAkhLMRMwEQYDVQQKDApub2RlLXNhbWwyMSMwIQYJKoZIhvcNAQkBFhRub2RlLnNhbWwyQGdtYWlsLmNvbTAeFw0xNTA3MDUxNzU2NDdaFw0xODA3MDQxNzU2NDdaMGgxCzAJBgNVBAYTAkhLMRIwEAYDVQQIDAlIb25nIEtvbmcxCzAJBgNVBAcMAkhLMRMwEQYDVQQKDApub2RlLXNhbWwyMSMwIQYJKoZIhvcNAQkBFhRub2RlLnNhbWwyQGdtYWlsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMQJAB8JrsLQbUuJa8akzLqO1EZqClS0tQp+w+5wgufp07WwGn/shma8dcQNj1dbjszI5HBeVFjOKIxlfjmNB9ovhQPstBjP/UPQYp1Ip2IoHCYX9HDgMz3xyXKbHthUzZaECz+p+7WtgwhczRkBLDOm2k15qhPYGPw0vH2zbVRGWUBS9dy2Mp3tqlVbP0xZ9CDNkhCJkV9SMNfoCVW/VYPqK2QBo7ki4obm5x5ixFQSSHsKbVARVzyQH5iNjFe1TdAp3rDwrE5Lc1NQlQaxR5Gnb2NZApDORRZIVlNv2WUdi9QvM0yCzjQ90jP0OAogHhRYaxg0/vgNEye46h+PiY0CAwEAAaNQME4wHQYDVR0OBBYEFEVkjcLAITndky090Ay74QqCmQKIMB8GA1UdIwQYMBaAFEVkjcLAITndky090Ay74QqCmQKIMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAG4lYX3KQXenez4LpDnZhcFBEZi9YstUKPF5EKd+WplpVbcTQc1A3/Z+uHRmyV8h+pQzeF6Liob37G87YpacPplJI66cf2Rj7j8hSBNbdr+66E2qpcEhAF1iJmzBNyhb/ydlEuVpn8/EsoP+HvBeiDl5gon3562MzZIgV/pLdTfxHyW6hzAQhjGq2UhcvR+gXNVJvHP2eS4jlHnJkB9bfo0kvf87Q+D6XKX3q5c3mO8tqW6UpqHSC+uLEpzZiNLeuFa4TUIhgBgjDjlRrNDKu8ndancSn3yBHYnqJ2t9cR+coFnnjYABQpNrvk4mtmXY8SXoBzYG9Y+lqeAun6+0YyE=
14 |
15 |
16 |
17 | urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
18 |
21 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "module": "commonjs",
5 | "moduleResolution": "node",
6 | "declaration": true,
7 | "declarationDir": "types",
8 | "emitDecoratorMetadata": true,
9 | "experimentalDecorators": true,
10 | "downlevelIteration": true,
11 | "sourceMap": true,
12 | "outDir": "./build",
13 | "baseUrl": "./",
14 | "removeComments": false,
15 | "strictNullChecks": true,
16 | "paths": {},
17 | "lib": [
18 | "dom",
19 | "es2015.core",
20 | "es2015.promise",
21 | "es2015.iterable",
22 | "es5"
23 | ]
24 | },
25 | "atom": { "rewriteTsconfig": false },
26 | "exclude": [
27 | "node_modules",
28 | "types/**/*.ts",
29 | "test/**/*.ts"
30 | ],
31 | "compileOnSave": false,
32 | "buildOnSave": false
33 | }
34 |
--------------------------------------------------------------------------------
/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "tslint:recommended",
3 | "rulesDirectory": [],
4 | "linterOptions": {
5 | "exclude": [
6 | "node_modules/**"
7 | ]
8 | },
9 | "rules": {
10 | "arrow-parens": [true, "ban-single-arg-parens"],
11 | "comment-format": false,
12 | "interface-name": [true, "never-prefix"],
13 | "jsdoc-format": false,
14 | "max-line-length": false,
15 | "member-access": false,
16 | "no-console": [false],
17 | "no-consecutive-blank-lines": [true, 3],
18 | "no-empty-interface": false,
19 | "no-string-literal": false,
20 | "object-literal-sort-keys": false,
21 | "object-literal-key-quotes": false,
22 | "object-literal-shorthand": false,
23 | "trailing-comma": false,
24 | "eofline": false,
25 | "no-empty": false,
26 | "align": false,
27 | "no-trailing-whitespace": false,
28 | "ordered-imports": false,
29 | "quotemark": [true, "single", "avoid-escape", "avoid-template"],
30 | "variable-name": [true, "ban-keywords", "check-format", "allow-leading-underscore", "allow-pascal-case"],
31 | "interface-over-type-literal": false,
32 | "no-var-requires": false
33 | },
34 | "jsRules": {}
35 | }
36 |
--------------------------------------------------------------------------------
/types.d.ts:
--------------------------------------------------------------------------------
1 | export * from './index'
2 | export * from './src/types'
--------------------------------------------------------------------------------