├── .nvmrc
├── index.js
├── .gitignore
├── .npmignore
├── test
└── data
│ ├── response_no_status.xml
│ ├── response_bad_version.xml
│ ├── good_response_decrypted.xml
│ ├── namespaced_assertion.xml
│ ├── response_error_status.xml
│ ├── logout_request.xml
│ ├── namespaced_assertion_with_empty_inclusivenamespaces.xml
│ ├── namespaced_assertion_with_inclusivenamespaces.xml
│ ├── empty_attribute_value.xml
│ ├── blank_assertion.xml
│ ├── test.crt
│ ├── test2.crt
│ ├── no_subject.xml
│ ├── test.pem
│ ├── test2.pem
│ ├── response_notbefore_future_decoded.xml
│ ├── response_no_audience_no_timing.xml
│ ├── response_empty_audience_no_timing.xml
│ ├── good_response.xml
│ ├── response_audience_no_timing.xml
│ ├── unsigned_assertion.xml
│ ├── good_assertion_signed_data.xml
│ ├── response_notbefore_future.xml
│ ├── empty_session_index.xml
│ ├── empty_nameid.xml
│ ├── response_unsigned_assertion.xml
│ ├── good_assertion_no_session_index.xml
│ ├── good_assertion.xml
│ ├── response_external_signed_assertion.xml
│ ├── response_notbefore_future_encrypted_decoded.xml
│ ├── good_assertion_commented_out_digest.xml
│ ├── good_assertion_explicit_namespaces.xml
│ ├── response_notbefore_future_signed.xml
│ ├── response_notbefore_future_encrypted.xml
│ ├── redirect_response.xml
│ ├── response_notbefore_future_encrypted_then_signed.xml
│ ├── good_response_twice_signed_dsig_ns_at_top.xml
│ ├── response_notbefore_future_signed_then_encrypted.xml
│ ├── good_response_twice_signed.xml
│ ├── post_response.xml
│ ├── response_notbefore_future_encrypted_then_signed_base64.xml
│ └── response_notbefore_future_signed_then_encrypted_base64.xml
├── catalog-info.yaml
├── .github
├── PULL_REQUEST_TEMPLATE.md
└── workflows
│ └── notify-ci-status.yml
├── package.json
├── .circleci
└── config.yml
├── LICENSE
├── README.md
└── lib
└── saml2.coffee
/.nvmrc:
--------------------------------------------------------------------------------
1 | 12
2 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | module.exports = require('./lib-js/saml2');
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *~
2 | node_modules
3 | lib-js
4 | *.html
5 | package-lock.json
6 | coverage
7 | .nyc_output/
8 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | *~
2 | coverage
3 | node_modules
4 | lib
5 | *.html
6 | .circleci/
7 | .github/
8 | .nvmrc
9 |
--------------------------------------------------------------------------------
/test/data/response_no_status.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/test/data/response_bad_version.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/test/data/good_response_decrypted.xml:
--------------------------------------------------------------------------------
1 | Lorem ipsum dolor sit amet, consectetur adipiscing elit.
--------------------------------------------------------------------------------
/test/data/namespaced_assertion.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/catalog-info.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: backstage.io/v1alpha1
2 | kind: Component
3 | metadata:
4 | name: saml2
5 | description: Node module to abstract away the complexities of the SAML protocol behind an easy to use interface.
6 | owner: unknown
7 | spec:
8 | type: unknown
9 | lifecycle: production
10 | owner: unknown
11 | system: Clever
12 |
--------------------------------------------------------------------------------
/test/data/response_error_status.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/test/data/logout_request.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | http://idp.example.com/metadata.xml
4 | tstudent
5 | _2
6 |
7 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ## Clever Coding Standards Agreement
2 |
3 | - [ ] Author and Review Statement, "We agree this code adheres to our [Clever Global Coding Standards](https://app.getguru.com/folders/ibabX5oT/Engineering-Standards-Best-Practices?activeCard=a8a444f4-9149-4ec7-a0fd-8ba42519d93e) and other applicable [Coding Standards](https://app.getguru.com/folders/ibabX5oT/Engineering-Standards-Best-Practices)"
4 |
5 | ## JIRA
6 | [Link to JIRA](insert url here)
7 |
8 | ## Overview
9 | (insert PR description here)
10 |
11 | ## Testing
12 | (how did you test this)
13 |
14 | ## Rollout
15 | (are there any special rollout considerations? specific steps? risks?)
16 |
17 | ## Rollback
18 | (specific steps? risks?)
--------------------------------------------------------------------------------
/.github/workflows/notify-ci-status.yml:
--------------------------------------------------------------------------------
1 | name: Notify CI status
2 |
3 | on:
4 | check_suite:
5 | types: [completed]
6 | status:
7 |
8 | jobs:
9 | call-workflow:
10 | if: >-
11 | (github.event.branches[0].name == github.event.repository.default_branch &&
12 | (github.event.state == 'error' || github.event.state == 'failure')) ||
13 | (github.event.check_suite.head_branch == github.event.repository.default_branch &&
14 | github.event.check_suite.conclusion != 'success')
15 | uses: Clever/ci-scripts/.github/workflows/reusable-notify-ci-status.yml@master
16 | secrets:
17 | CIRCLE_CI_INTEGRATIONS_URL: ${{ secrets.CIRCLE_CI_INTEGRATIONS_URL }}
18 | CIRCLE_CI_INTEGRATIONS_USERNAME: ${{ secrets.CIRCLE_CI_INTEGRATIONS_USERNAME }}
19 | CIRCLE_CI_INTEGRATIONS_PASSWORD: ${{ secrets.CIRCLE_CI_INTEGRATIONS_PASSWORD }}
20 | SLACK_BOT_TOKEN: ${{ secrets.DAPPLE_BOT_TOKEN }}
21 |
--------------------------------------------------------------------------------
/test/data/namespaced_assertion_with_empty_inclusivenamespaces.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/test/data/namespaced_assertion_with_inclusivenamespaces.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/test/data/empty_attribute_value.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | http://idp.example.com/metadata.xml
4 |
5 | tstudent
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/test/data/blank_assertion.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | http://idp.example.com/metadata.xml
4 |
5 | tstudent
6 |
7 |
8 |
9 |
10 |
11 |
12 | https://sp.example.com/metadata.xml
13 |
14 |
15 |
16 |
17 | urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/test/data/test.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIDGTCCAgGgAwIBAgIJAO8HJfrb3JZeMA0GCSqGSIb3DQEBBQUAMCMxITAfBgNV
3 | BAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0xNDAzMTgwMTE3MTdaFw0y
4 | NDAzMTcwMTE3MTdaMCMxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0
5 | ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMFf1kCef6FTPMxQSoTh
6 | AZGFNmixh8fRDLsUo58pEFwztBRUPWS6s6Ql8mA75aAEdo4+JVyE8QPi5F+fWbnT
7 | oWkIw7E7YGl6s+EScSMQYHKCLq4mPHPMHtZspFowNp+Vax88SSUo1TKlpVNVIGim
8 | 8JQ5SRi3p0aD6UAiu9WxQ5s+xHnDwgvQiu3Sa4COl5NQjkC1r2LrhJnJQQiw0hsn
9 | 1nGgg15jEaDCZa8uPw1EtHv8smoZpjTbwRBVjXtzLskYIRyYLQjvqR+/QAd0XZca
10 | v0LdTwQR6obg/CwSgv7qG/WN6t25VIIGQDIUkVMBhLDmCh8QRpTvx1YWumSWW4D2
11 | k2kCAwEAAaNQME4wHQYDVR0OBBYEFLpo8Vz1m19xvPmzx+2wf2PaSTIpMB8GA1Ud
12 | IwQYMBaAFLpo8Vz1m19xvPmzx+2wf2PaSTIpMAwGA1UdEwQFMAMBAf8wDQYJKoZI
13 | hvcNAQEFBQADggEBALhwpLS6C+97nWrEICI5yetQjexCJGltMESg1llNYjsbIuJ/
14 | S4XbrVzhN4nfNGMSbj8rb/9FT6TSru5QLjJQQmj38pqsWtEhR2vBLclqGqEcJfvP
15 | Mdn1qAJhJfhrs0KUpsX6xFTnSkNoyGxCP8Wh2C1L0NL5r+x58lkma5vL6ncwWYY+
16 | 0C3bt1XbBRdeOZHUwuYTIcD+BCNixQiNor7KjO1TzpOb6V3m1SKHu8idDM5fUcKo
17 | oGbV3WuE7AJrAG5fvt59V9MtMPc2FklVFminfTeYKboEaxZJxuPDbQs2IyJ/0lI8
18 | P0Mv4LIKj4+OipQ/fGbZuE7cOioPKKl02dE7eCA=
19 | -----END CERTIFICATE-----
20 |
--------------------------------------------------------------------------------
/test/data/test2.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIDGTCCAgGgAwIBAgIJAJQd/RSI51tKMA0GCSqGSIb3DQEBBQUAMCMxITAfBgNV
3 | BAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0xNDAzMTgyMDMxMDNaFw0y
4 | NDAzMTcyMDMxMDNaMCMxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0
5 | ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALxerkURM4678nuft7LQ
6 | I7g5jySUHwHROCheAVt+kemVeg7JNFzPaF1AOm2n4S4xq4aI03/HW725sxZTJIit
7 | 6TBSiboC6yuN/cM/mzwjhbV+gCQRz2DrI7MkGGujn5bH+vu3qzxpXSoSqrkuHWrd
8 | eNGHLBP0C/0pHU2RZJOGG1h+S+tiW+EGKz1PItfL7mg8V2EhieUBYLgxGxVsNYwt
9 | L7dWcib7Y4476Yx25d34k1IgBrvkyo3yx1GizwG00+0FR3/ykMYOexwiZzCrKbZo
10 | z1Bf0itu9vqjbzDy9gbkEQBIcZxpE5GOwAtyLNKgBdSyFj3zbRTUIyOtNdTv5CN3
11 | 4WMCAwEAAaNQME4wHQYDVR0OBBYEFFIQ7r0sopn/h79pX1qiQaWzcMGoMB8GA1Ud
12 | IwQYMBaAFFIQ7r0sopn/h79pX1qiQaWzcMGoMAwGA1UdEwQFMAMBAf8wDQYJKoZI
13 | hvcNAQEFBQADggEBAHcMfEAswmSVRsRofaibLeP72Hm8zutb25ntpm3gcak+DikE
14 | 4ZwI/HGYw2YpzGZ9v8ysxc/egc7lLKn+yOlObRdIFJmXu5MSf0G6D5/NRv8RagCa
15 | 3x6KgjgZOTx5MNR8KX2y79bOupMMj/PnI4jA2jXbFFSUwz6MQFP/4VyhlpYqdhn3
16 | Qpuu8YVrW7KHcYm6RQHlrC70WCcfZEWLEHjU/uRwFK1+hMsULbbu3O8/zmJsU6O4
17 | b2ZbjCoPvsAZYPK0/OJYbyUxfpfHZ82KmF261HEKIchEWPkpiZivtrPfIOZFy6iV
18 | 4bt0PT/SGoIbKOxh0Nxxyt2mHnpd030tUXNYLTc=
19 | -----END CERTIFICATE-----
20 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "saml2-js",
3 | "version": "4.0.4",
4 | "description": "SAML 2.0 node helpers",
5 | "author": "Clever",
6 | "license": "Apache-2.0",
7 | "main": "index.js",
8 | "engines": {
9 | "node": ">=10.x"
10 | },
11 | "scripts": {
12 | "build": "coffee --bare -c -o lib-js lib",
13 | "test": "NODE_ENV=test mocha --require coffeescript/register test/*.coffee",
14 | "test-cov": "NODE_ENV=test nyc --extension .coffee -r html -r text mocha --require coffeescript/register test/*.coffee",
15 | "prepare": "npm run build"
16 | },
17 | "repository": {
18 | "type": "git",
19 | "url": "git://github.com/Clever/saml2.git"
20 | },
21 | "keywords": [
22 | "saml",
23 | "node"
24 | ],
25 | "bugs": {
26 | "url": "https://github.com/Clever/saml2/issues"
27 | },
28 | "devDependencies": {
29 | "coffeescript": "^1.12.7",
30 | "mocha": "^8.4.0",
31 | "nyc": "^15.0.0"
32 | },
33 | "dependencies": {
34 | "@xmldom/xmldom": "^0.8.6",
35 | "async": "^3.2.0",
36 | "debug": "^4.3.0",
37 | "underscore": "^1.8.0",
38 | "xml-crypto": "^6.1.2",
39 | "xml-encryption": "^3.0.2",
40 | "xmlbuilder2": "^2.4.0",
41 | "xpath": "^0.0.34"
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/test/data/no_subject.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | https://idp.example.com/metadata.xml
8 |
9 |
10 | https://sp.example.com/metadata.xml
11 |
12 |
13 |
14 |
15 | urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
16 |
17 |
18 |
19 |
20 | Test
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/test/data/test.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDBX9ZAnn+hUzzM
3 | UEqE4QGRhTZosYfH0Qy7FKOfKRBcM7QUVD1kurOkJfJgO+WgBHaOPiVchPED4uRf
4 | n1m506FpCMOxO2BperPhEnEjEGBygi6uJjxzzB7WbKRaMDaflWsfPEklKNUypaVT
5 | VSBopvCUOUkYt6dGg+lAIrvVsUObPsR5w8IL0Irt0muAjpeTUI5Ata9i64SZyUEI
6 | sNIbJ9ZxoINeYxGgwmWvLj8NRLR7/LJqGaY028EQVY17cy7JGCEcmC0I76kfv0AH
7 | dF2XGr9C3U8EEeqG4PwsEoL+6hv1jerduVSCBkAyFJFTAYSw5gofEEaU78dWFrpk
8 | lluA9pNpAgMBAAECggEAfi4XFBtYlOBHr9pEheh8qYQPOMl/HDeg4wJYsiaNclya
9 | iRle5jeduOK6AWmUMJI4+iA7KN/mlO6crnjAh608idkaOK/R/YH/lkH+aS7qgE3K
10 | QADbOYRcKvbBV8hWHFPXjo47/G9kjqPf+Tx25VLpcQ7gT6ynDjBNJ3iCsLH2t3lf
11 | M3rgdeRqauRrCvHb8zJzLgOFd+d5UZWGzcQxfSlRTkReBul2QPEK+GE3tLVVWWCg
12 | sC51teOHnPq6l0ymgFou6Z48e2QXXGc7I7ebYWIwjBQlHwhwT32q1uNB/xXyOHmh
13 | jJ5z7N8ZJk0mrtDZ8N3ClhMUdVH8+nm5G79WVonTwQKBgQDjaMR8B98s3QPOFoWG
14 | 3JK5xBw4dV2z7cTPr/qakA12E5vslqKjab51NQ1kzU7GyRWhNthv4iHM8KyerLH2
15 | GgZfYM4cve9uW5KOZKRPrBkvou3XBe/FFikRk19EvTL6BXqhnxyYYdOC6LfppGI9
16 | 8PbEGq0Z1BF0fbadw3Pmxvi5xQKBgQDZr6WTESfLHfXHJ6EmI3yvM3RBrUdojRY7
17 | WpwGcn6MkqnuFuTqkqJ1UUbB7wsDFvuBEXLvd3mgmWJYLditVvhhCxbqbPO2rj/B
18 | 1FC34FdMQLl2981ucz6qwTolaUwjBlhtoMnL+03hoJTG7lf2ZxlfbJZzXawMa0m/
19 | 1RHHChyhVQKBgQDEPSJhDcHuywJ/kzvCtxD+sVbQ+abUn/fYaTnOq0SSgjVpokvS
20 | zGuIZTGbrPev3tKFffikA/W7Dm1HuCsR/j9FixoR/21gRDFiI0MPZamOTAEGLp9L
21 | 6eWivxPVE5er3ZKHafCZJsIJE52xRyNn5Epty79YrIIrjlhKJ+IaYdU9KQKBgAaC
22 | okkLskz40GjsXn1tgkUbHNb5/7C4x3lu9EudEPvTRxG/zYjWadVoYN1b8NBe15a8
23 | lttij1imPbK1bE2C1FrSohTQvVkxTObXGrLlGrdFGEbekl5DRBSHQt3rkENb5Tki
24 | Hebj1ShyTQDGEAtmefPIo5c/re2RJ9t829NAEishAoGAGOW5CPq7Q0tEvOVE+/br
25 | JXddPyZe++FB1e7i+iVYrA5F8wtvhVHsVsSxpm47XdAyAFdLdnttrnwzt3EA+QvB
26 | tsprKkdbwhTwaVKRDwnIAfwwpvONAV+/6X5W0UDJEmevDQZR8x74nBHWezdDv+lk
27 | Ig9R0ZWbG6k7TkdrLwTbs1c=
28 | -----END PRIVATE KEY-----
29 |
--------------------------------------------------------------------------------
/test/data/test2.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC8Xq5FETOOu/J7
3 | n7ey0CO4OY8klB8B0TgoXgFbfpHplXoOyTRcz2hdQDptp+EuMauGiNN/x1u9ubMW
4 | UySIrekwUom6Ausrjf3DP5s8I4W1foAkEc9g6yOzJBhro5+Wx/r7t6s8aV0qEqq5
5 | Lh1q3XjRhywT9Av9KR1NkWSThhtYfkvrYlvhBis9TyLXy+5oPFdhIYnlAWC4MRsV
6 | bDWMLS+3VnIm+2OOO+mMduXd+JNSIAa75MqN8sdRos8BtNPtBUd/8pDGDnscImcw
7 | qym2aM9QX9Irbvb6o28w8vYG5BEASHGcaRORjsALcizSoAXUshY9820U1CMjrTXU
8 | 7+Qjd+FjAgMBAAECggEAOIrTFLhNGZMg/iq7IVmI30unw/sSM6Fxkexly+j6M3tC
9 | 4B1VMmavlQ4qe6/gz9To/8Eie0CEMTcEorbiSISrcm3UGZm2raQ5f9of5rVi9U+7
10 | dxhBf34VgThcfDLpPIFavSQsqj2WUYK47E0DV4iTM5G3kWW4E4271gTGg+HFY5JA
11 | nv3f3cY9J4d0j/Jw9QbDElSVpxQw9/+KVsiae7fCqdIhTU9WtowbgAX6pjAxwL1F
12 | D7FJ6tccuOBdyyG32fVBWEhivYjYVyn6AuaIBkuZK2oLjQofkq+7W68aVh+CMpx4
13 | QoZtSh1sVaZ7X6o43yh11S8sd/LoqSNLOh9t6MmugQKBgQD5gGMmo53sOasar1f3
14 | bj9edXE4ZafDXFv88M2e2NQsCx0a2EPGc8Mx/JzH+4JcMrgiphDj4POOSIsEyq3B
15 | iHMFIU/4Fl/XS08aMTcx5qhrSZlT8wAQApPEWSOwhH0LKljqblVW9p3hSd2kP9ei
16 | na4FnOsjpZieNjPa7438+6QhGQKBgQDBRq7aGTPXj4BFEY/1Nq+5MVdOiOdohZKq
17 | tbT0jJcwAH0TBTWH/0NIh5u4vfy5CVkIQAM/vOl4VTu5aHwnX+yU2tANUEXvgGyi
18 | uAc96sW1COt28eDxoSP+ZZJk/GRqetvrItnAWJbWYzjn2xCG5+B/2Kom/IOoYCYd
19 | 0ZFFeVk52wKBgAobkGi9UiWCxJLFLbwhZEHQYjDVtXEtqbBalQntYNMT9C7lOgGt
20 | KOg6gqN7ZfGUQG9u6NpCf7tw5ujfySBBBd/cVKAJUAKp01+NRN4pqQMHrUWAX61G
21 | XXQj5FU/WM19/rIonB50yTqaQndn+rVky+sAS2pbSA6IxZsF/2uTSjfpAoGAc28p
22 | 420F/4rfi2Dv3/7neO41PNybiVutu3OHPj/x1GOWUBPeYvlcUCdeJDqkhEdG+5xv
23 | 1FOaBZqybwwuir3J6SW++RSmkGLdf1n2SU69AmDvcT0JoochnkE/7DyqJMZ4LrnD
24 | 4BOJE0ZzqFa4SjqXZQQcq+hJIfk7Crgt0Zamad0CgYAl51GpsFqtU/acA5xBrckU
25 | CB94urSYwdz4kjbZNoMkvp0FraKuSohD0jQuRv7GtxFaRxGLHClp4GzMjI6a03LS
26 | W41nVPjWvF1xoYABKDku0RYR4OYr/YfkVSFy797SnawJyMPfxBffSYyp6wJUe10b
27 | hpNq9wGUVe9umBSwAMqOmg==
28 | -----END PRIVATE KEY-----
29 |
--------------------------------------------------------------------------------
/test/data/response_notbefore_future_decoded.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | This data has no meaning.
7 | http://idp.example.com/metadata.xml
8 |
9 | tstudent
10 |
11 |
12 |
13 |
14 |
15 |
16 | https://sp.example.com/metadata.xml
17 |
18 |
19 |
20 |
21 | Test
22 |
23 |
24 |
25 |
26 | urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/test/data/response_no_audience_no_timing.xml:
--------------------------------------------------------------------------------
1 | PHNhbWxwOlJlc3BvbnNlIHhtbG5zOnNhbWxwPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6cHJvdG9jb2wiIElEPSJfMiIgVmVyc2lvbj0iMi4wIiBJblJlc3BvbnNlVG89Il8xIiBEZXN0aW5hdGlvbj0iaHR0cHM6Ly9zcC5leGFtcGxlLmNvbS9hc3NlcnQiPgogICAgPHNhbWxwOlN0YXR1cz4KICAgICAgICA8c2FtbHA6U3RhdHVzQ29kZSBWYWx1ZT0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnN0YXR1czpTdWNjZXNzIiAvPgogICAgPC9zYW1scDpTdGF0dXM+CiAgICA8QXNzZXJ0aW9uIHhtbG5zPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIiBJRD0iXzMiIElzc3VlSW5zdGFudD0iMjAxNC0wMy0xMlQyMTozNTowNS4zOTJaIiBWZXJzaW9uPSIyLjAiPgogICAgICAgIDxEYXRhIElEPSJfNSI+VGhpcyBkYXRhIGhhcyBubyBtZWFuaW5nLjwvRGF0YT4KICAgICAgICA8SXNzdWVyPmh0dHA6Ly9pZHAuZXhhbXBsZS5jb20vbWV0YWRhdGEueG1sPC9Jc3N1ZXI+CiAgICAgICAgPFN1YmplY3Q+CiAgICAgICAgICAgIDxOYW1lSUQgRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6bmFtZWlkLWZvcm1hdDp0cmFuc2llbnQiPnRzdHVkZW50PC9OYW1lSUQ+CiAgICAgICAgICAgIDxTdWJqZWN0Q29uZmlybWF0aW9uIE1ldGhvZD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmNtOmJlYXJlciI+CiAgICAgICAgICAgICAgICA8U3ViamVjdENvbmZpcm1hdGlvbkRhdGEgSW5SZXNwb25zZVRvPSJfNCIgTm90T25PckFmdGVyPSIyMDE0LTAzLTEyVDIxOjQwOjA1LjM5MloiIFJlY2lwaWVudD0iaHR0cHM6Ly9zcC5leGFtcGxlLmNvbS9hc3NlcnQiIC8+CiAgICAgICAgICAgIDwvU3ViamVjdENvbmZpcm1hdGlvbj4KICAgICAgICA8L1N1YmplY3Q+CiAgICAgICAgPENvbmRpdGlvbnM+PC9Db25kaXRpb25zPgogICAgICAgIDxBdHRyaWJ1dGVTdGF0ZW1lbnQ+CiAgICAgICAgICAgIDxBdHRyaWJ1dGUgTmFtZT0iaHR0cDovL3NjaGVtYXMueG1sc29hcC5vcmcvd3MvMjAwNS8wNS9pZGVudGl0eS9jbGFpbXMvZ2l2ZW5uYW1lIj4KICAgICAgICAgICAgICAgIDxBdHRyaWJ1dGVWYWx1ZT5UZXN0PC9BdHRyaWJ1dGVWYWx1ZT4KICAgICAgICAgICAgPC9BdHRyaWJ1dGU+CiAgICAgICAgPC9BdHRyaWJ1dGVTdGF0ZW1lbnQ+CiAgICAgICAgPEF1dGhuU3RhdGVtZW50IEF1dGhuSW5zdGFudD0iMjAxNC0wMy0xMlQyMTozNTowNS4zNTRaIiBTZXNzaW9uSW5kZXg9Il8zIj4KICAgICAgICAgICAgPEF1dGhuQ29udGV4dD4KICAgICAgICAgICAgICAgIDxBdXRobkNvbnRleHRDbGFzc1JlZj51cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YWM6Y2xhc3NlczpQYXNzd29yZFByb3RlY3RlZFRyYW5zcG9ydDwvQXV0aG5Db250ZXh0Q2xhc3NSZWY+CiAgICAgICAgICAgIDwvQXV0aG5Db250ZXh0PgogICAgICAgIDwvQXV0aG5TdGF0ZW1lbnQ+CiAgICA8L0Fzc2VydGlvbj4KPC9zYW1scDpSZXNwb25zZT4K
2 |
--------------------------------------------------------------------------------
/test/data/response_empty_audience_no_timing.xml:
--------------------------------------------------------------------------------
1 | PHNhbWxwOlJlc3BvbnNlIHhtbG5zOnNhbWxwPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6cHJvdG9jb2wiIElEPSJfMiIgVmVyc2lvbj0iMi4wIiBJblJlc3BvbnNlVG89Il8xIiBEZXN0aW5hdGlvbj0iaHR0cHM6Ly9zcC5leGFtcGxlLmNvbS9hc3NlcnQiPgogICAgPHNhbWxwOlN0YXR1cz4KICAgICAgICA8c2FtbHA6U3RhdHVzQ29kZSBWYWx1ZT0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnN0YXR1czpTdWNjZXNzIiAvPgogICAgPC9zYW1scDpTdGF0dXM+CiAgICA8QXNzZXJ0aW9uIHhtbG5zPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIiBJRD0iXzMiIElzc3VlSW5zdGFudD0iMjAxNC0wMy0xMlQyMTozNTowNS4zOTJaIiBWZXJzaW9uPSIyLjAiPgogICAgICAgIDxEYXRhIElEPSJfNSI+VGhpcyBkYXRhIGhhcyBubyBtZWFuaW5nLjwvRGF0YT4KICAgICAgICA8SXNzdWVyPmh0dHA6Ly9pZHAuZXhhbXBsZS5jb20vbWV0YWRhdGEueG1sPC9Jc3N1ZXI+CiAgICAgICAgPFN1YmplY3Q+CiAgICAgICAgICAgIDxOYW1lSUQgRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6bmFtZWlkLWZvcm1hdDp0cmFuc2llbnQiPnRzdHVkZW50PC9OYW1lSUQ+CiAgICAgICAgICAgIDxTdWJqZWN0Q29uZmlybWF0aW9uIE1ldGhvZD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmNtOmJlYXJlciI+CiAgICAgICAgICAgICAgICA8U3ViamVjdENvbmZpcm1hdGlvbkRhdGEgSW5SZXNwb25zZVRvPSJfNCIgTm90T25PckFmdGVyPSIyMDE0LTAzLTEyVDIxOjQwOjA1LjM5MloiIFJlY2lwaWVudD0iaHR0cHM6Ly9zcC5leGFtcGxlLmNvbS9hc3NlcnQiIC8+CiAgICAgICAgICAgIDwvU3ViamVjdENvbmZpcm1hdGlvbj4KICAgICAgICA8L1N1YmplY3Q+CiAgICAgICAgPENvbmRpdGlvbnM+CiAgICAgICAgICAgIDxBdWRpZW5jZVJlc3RyaWN0aW9uPgogICAgICAgICAgICAgICAgPEF1ZGllbmNlPjwvQXVkaWVuY2U+CiAgICAgICAgICAgIDwvQXVkaWVuY2VSZXN0cmljdGlvbj4KICAgICAgICA8L0NvbmRpdGlvbnM+CiAgICAgICAgPEF0dHJpYnV0ZVN0YXRlbWVudD4KICAgICAgICAgICAgPEF0dHJpYnV0ZSBOYW1lPSJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9naXZlbm5hbWUiPgogICAgICAgICAgICAgICAgPEF0dHJpYnV0ZVZhbHVlPlRlc3Q8L0F0dHJpYnV0ZVZhbHVlPgogICAgICAgICAgICA8L0F0dHJpYnV0ZT4KICAgICAgICA8L0F0dHJpYnV0ZVN0YXRlbWVudD4KICAgICAgICA8QXV0aG5TdGF0ZW1lbnQgQXV0aG5JbnN0YW50PSIyMDE0LTAzLTEyVDIxOjM1OjA1LjM1NFoiIFNlc3Npb25JbmRleD0iXzMiPgogICAgICAgICAgICA8QXV0aG5Db250ZXh0PgogICAgICAgICAgICAgICAgPEF1dGhuQ29udGV4dENsYXNzUmVmPnVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphYzpjbGFzc2VzOlBhc3N3b3JkUHJvdGVjdGVkVHJhbnNwb3J0PC9BdXRobkNvbnRleHRDbGFzc1JlZj4KICAgICAgICAgICAgPC9BdXRobkNvbnRleHQ+CiAgICAgICAgPC9BdXRoblN0YXRlbWVudD4KICAgIDwvQXNzZXJ0aW9uPgo8L3NhbWxwOlJlc3BvbnNlPgo=
2 |
--------------------------------------------------------------------------------
/test/data/good_response.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | O=Internet Widgits Pty Ltd
18 | 17223777059262469726
19 |
20 |
21 |
22 |
23 | ql07diGZymd3QR1wTMOt6n5TbWOUmPg7Oumx1dtzfr75eYELnz3eHuwWHJ8r6ZjK+Oac5Qa7blluei7VTkod/En8JvUn63yoPNtFMWciL38bjPE9bkWBi4qugptmhOSg2nAjqUNu1n5DfPN32AB7VAmk6lfe+Q29vlHbliPfAIBxUpxZHUe4aGcHG7E0+telG/Zjy5sZXnLyrSHrOenkdBEDkUQf5jiIDgphWeEx3O2/wdgwTLpjMWX2Dk27BxivGitzcd/RBHUAA4LGEqsx6p7LLEzrlxwpA0818bhKDL1MT8Y4bfbkfDtj5rsqG4ZcYlembMday5Te4e5rGxnH2A==
24 |
25 |
26 |
27 |
28 | KIwhFfRvambizmOl1TCmbYZF6E/62Ye16byOe+G2Ruu8shHsSH1yc5HuzOQ4eQVtWn3rSU7Q8iNJQGPWbxhxc4KGBvUhAYvK7dpNZ5ZNoQNP0ABE3MLr5d5uo5KhMk+TudBj8rh4FiO0UnsRns3Xd+4c9kf3o7rTw7FT05ll7QGAxCOwEeV54El542FQ+RKgVXoNMHaHZFZeYG8LcrKC7lCq9wuTqe6md1rA+JOhqXle8O0jqqAzYhT9VdR9iq0X
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/test/data/response_audience_no_timing.xml:
--------------------------------------------------------------------------------
1 | PHNhbWxwOlJlc3BvbnNlIHhtbG5zOnNhbWxwPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6cHJvdG9jb2wiIElEPSJfMiIgVmVyc2lvbj0iMi4wIiBJblJlc3BvbnNlVG89Il8xIiBEZXN0aW5hdGlvbj0iaHR0cHM6Ly9zcC5leGFtcGxlLmNvbS9hc3NlcnQiPgogICAgPHNhbWxwOlN0YXR1cz4KICAgICAgICA8c2FtbHA6U3RhdHVzQ29kZSBWYWx1ZT0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnN0YXR1czpTdWNjZXNzIiAvPgogICAgPC9zYW1scDpTdGF0dXM+CiAgICA8QXNzZXJ0aW9uIHhtbG5zPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIiBJRD0iXzMiIElzc3VlSW5zdGFudD0iMjAxNC0wMy0xMlQyMTozNTowNS4zOTJaIiBWZXJzaW9uPSIyLjAiPgogICAgICAgIDxEYXRhIElEPSJfNSI+VGhpcyBkYXRhIGhhcyBubyBtZWFuaW5nLjwvRGF0YT4KICAgICAgICA8SXNzdWVyPmh0dHA6Ly9pZHAuZXhhbXBsZS5jb20vbWV0YWRhdGEueG1sPC9Jc3N1ZXI+CiAgICAgICAgPFN1YmplY3Q+CiAgICAgICAgICAgIDxOYW1lSUQgRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6bmFtZWlkLWZvcm1hdDp0cmFuc2llbnQiPnRzdHVkZW50PC9OYW1lSUQ+CiAgICAgICAgICAgIDxTdWJqZWN0Q29uZmlybWF0aW9uIE1ldGhvZD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmNtOmJlYXJlciI+CiAgICAgICAgICAgICAgICA8U3ViamVjdENvbmZpcm1hdGlvbkRhdGEgSW5SZXNwb25zZVRvPSJfNCIgTm90T25PckFmdGVyPSIyMDE0LTAzLTEyVDIxOjQwOjA1LjM5MloiIFJlY2lwaWVudD0iaHR0cHM6Ly9zcC5leGFtcGxlLmNvbS9hc3NlcnQiIC8+CiAgICAgICAgICAgIDwvU3ViamVjdENvbmZpcm1hdGlvbj4KICAgICAgICA8L1N1YmplY3Q+CiAgICAgICAgPENvbmRpdGlvbnM+CiAgICAgICAgICAgIDxBdWRpZW5jZVJlc3RyaWN0aW9uPgogICAgICAgICAgICAgICAgPEF1ZGllbmNlPmh0dHBzOi8vc3AuZXhhbXBsZS5jb20vbWV0YWRhdGEueG1sPC9BdWRpZW5jZT4KICAgICAgICAgICAgPC9BdWRpZW5jZVJlc3RyaWN0aW9uPgogICAgICAgIDwvQ29uZGl0aW9ucz4KICAgICAgICA8QXR0cmlidXRlU3RhdGVtZW50PgogICAgICAgICAgICA8QXR0cmlidXRlIE5hbWU9Imh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL2dpdmVubmFtZSI+CiAgICAgICAgICAgICAgICA8QXR0cmlidXRlVmFsdWU+VGVzdDwvQXR0cmlidXRlVmFsdWU+CiAgICAgICAgICAgIDwvQXR0cmlidXRlPgogICAgICAgIDwvQXR0cmlidXRlU3RhdGVtZW50PgogICAgICAgIDxBdXRoblN0YXRlbWVudCBBdXRobkluc3RhbnQ9IjIwMTQtMDMtMTJUMjE6MzU6MDUuMzU0WiIgU2Vzc2lvbkluZGV4PSJfMyI+CiAgICAgICAgICAgIDxBdXRobkNvbnRleHQ+CiAgICAgICAgICAgICAgICA8QXV0aG5Db250ZXh0Q2xhc3NSZWY+dXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFjOmNsYXNzZXM6UGFzc3dvcmRQcm90ZWN0ZWRUcmFuc3BvcnQ8L0F1dGhuQ29udGV4dENsYXNzUmVmPgogICAgICAgICAgICA8L0F1dGhuQ29udGV4dD4KICAgICAgICA8L0F1dGhuU3RhdGVtZW50PgogICAgPC9Bc3NlcnRpb24+Cjwvc2FtbHA6UmVzcG9uc2U+Cg==
2 |
--------------------------------------------------------------------------------
/test/data/unsigned_assertion.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | http://idp.example.com/metadata.xml
4 |
5 | tstudent
6 |
7 |
8 |
9 |
10 |
11 |
12 | https://sp.example.com/metadata.xml
13 |
14 |
15 |
16 |
17 | Test
18 |
19 |
20 | tstudent@example.com
21 |
22 |
23 | tstudent
24 |
25 |
26 | CN=Students,CN=Users,DC=idp,DC=example,DC=com
27 |
28 |
29 | Student
30 |
31 |
32 | Test Student
33 |
34 |
35 |
36 |
37 | urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/test/data/good_assertion_signed_data.xml:
--------------------------------------------------------------------------------
1 |
2 | http://idp.example.com/metadata.xml
3 |
4 |
5 | tstudent
6 |
7 |
8 |
9 |
10 |
11 |
12 | https://sp.example.com/metadata.xml
13 |
14 |
15 |
16 |
17 | Test
18 |
19 |
20 | tstudent@example.com
21 |
22 |
23 | tstudent
24 |
25 |
26 | CN=Students,CN=Users,DC=idp,DC=example,DC=com
27 |
28 |
29 | Student
30 |
31 |
32 | Test Student
33 |
34 |
35 |
36 |
37 | urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
38 |
39 |
40 |
--------------------------------------------------------------------------------
/test/data/response_notbefore_future.xml:
--------------------------------------------------------------------------------
1 | PHNhbWxwOlJlc3BvbnNlIHhtbG5zOnNhbWxwPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6cHJvdG9jb2wiIElEPSJfMiIgVmVyc2lvbj0iMi4wIiBJblJlc3BvbnNlVG89Il8xIiBEZXN0aW5hdGlvbj0iaHR0cHM6Ly9zcC5leGFtcGxlLmNvbS9hc3NlcnQiPgogICAgPHNhbWxwOlN0YXR1cz4KICAgICAgICA8c2FtbHA6U3RhdHVzQ29kZSBWYWx1ZT0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnN0YXR1czpTdWNjZXNzIiAvPgogICAgPC9zYW1scDpTdGF0dXM+CiAgICA8QXNzZXJ0aW9uIHhtbG5zPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIiBJRD0iXzMiIElzc3VlSW5zdGFudD0iMjAxNC0wMy0xMlQyMTozNTowNS4zOTJaIiBWZXJzaW9uPSIyLjAiPgogICAgICAgIDxEYXRhIElEPSJfNSI+VGhpcyBkYXRhIGhhcyBubyBtZWFuaW5nLjwvRGF0YT4KICAgICAgICA8SXNzdWVyPmh0dHA6Ly9pZHAuZXhhbXBsZS5jb20vbWV0YWRhdGEueG1sPC9Jc3N1ZXI+CiAgICAgICAgPFN1YmplY3Q+CiAgICAgICAgICAgIDxOYW1lSUQgRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6bmFtZWlkLWZvcm1hdDp0cmFuc2llbnQiPnRzdHVkZW50PC9OYW1lSUQ+CiAgICAgICAgICAgIDxTdWJqZWN0Q29uZmlybWF0aW9uIE1ldGhvZD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmNtOmJlYXJlciI+CiAgICAgICAgICAgICAgICA8U3ViamVjdENvbmZpcm1hdGlvbkRhdGEgSW5SZXNwb25zZVRvPSJfNCIgTm90T25PckFmdGVyPSIyMDE0LTAzLTEyVDIxOjQwOjA1LjM5MloiIFJlY2lwaWVudD0iaHR0cHM6Ly9zcC5leGFtcGxlLmNvbS9hc3NlcnQiIC8+CiAgICAgICAgICAgIDwvU3ViamVjdENvbmZpcm1hdGlvbj4KICAgICAgICA8L1N1YmplY3Q+CiAgICAgICAgPENvbmRpdGlvbnMgTm90QmVmb3JlPSIyMDU0LTAzLTEyVDIxOjM1OjA1LjM4N1oiIE5vdE9uT3JBZnRlcj0iMjA1NC0wMy0xMlQyMjozNTowNS4zODdaIj4KICAgICAgICAgICAgPEF1ZGllbmNlUmVzdHJpY3Rpb24+CiAgICAgICAgICAgICAgICA8QXVkaWVuY2U+aHR0cHM6Ly9zcC5leGFtcGxlLmNvbS9tZXRhZGF0YS54bWw8L0F1ZGllbmNlPgogICAgICAgICAgICA8L0F1ZGllbmNlUmVzdHJpY3Rpb24+CiAgICAgICAgPC9Db25kaXRpb25zPgogICAgICAgIDxBdHRyaWJ1dGVTdGF0ZW1lbnQ+CiAgICAgICAgICAgIDxBdHRyaWJ1dGUgTmFtZT0iaHR0cDovL3NjaGVtYXMueG1sc29hcC5vcmcvd3MvMjAwNS8wNS9pZGVudGl0eS9jbGFpbXMvZ2l2ZW5uYW1lIj4KICAgICAgICAgICAgICAgIDxBdHRyaWJ1dGVWYWx1ZT5UZXN0PC9BdHRyaWJ1dGVWYWx1ZT4KICAgICAgICAgICAgPC9BdHRyaWJ1dGU+CiAgICAgICAgPC9BdHRyaWJ1dGVTdGF0ZW1lbnQ+CiAgICAgICAgPEF1dGhuU3RhdGVtZW50IEF1dGhuSW5zdGFudD0iMjAxNC0wMy0xMlQyMTozNTowNS4zNTRaIiBTZXNzaW9uSW5kZXg9Il8zIj4KICAgICAgICAgICAgPEF1dGhuQ29udGV4dD4KICAgICAgICAgICAgICAgIDxBdXRobkNvbnRleHRDbGFzc1JlZj51cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YWM6Y2xhc3NlczpQYXNzd29yZFByb3RlY3RlZFRyYW5zcG9ydDwvQXV0aG5Db250ZXh0Q2xhc3NSZWY+CiAgICAgICAgICAgIDwvQXV0aG5Db250ZXh0PgogICAgICAgIDwvQXV0aG5TdGF0ZW1lbnQ+CiAgICA8L0Fzc2VydGlvbj4KPC9zYW1scDpSZXNwb25zZT4K
2 |
--------------------------------------------------------------------------------
/test/data/empty_session_index.xml:
--------------------------------------------------------------------------------
1 | PD94bWwgdmVyc2lvbj0iMS4wIj8+DQo8c2FtbHA6UmVzcG9uc2UgRGVzdGluYXRpb249Imh0dHBzOi8vc3AuZXhhbXBsZS5jb20vYXNzZXJ0IiBJRD0iXzIiIEluUmVzcG9uc2VUbz0iXzEiIFZlcnNpb249IjIuMCIgeG1sbnM6c2FtbHA9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpwcm90b2NvbCI+DQogIDxzYW1scDpTdGF0dXM+DQogICAgPHNhbWxwOlN0YXR1c0NvZGUgVmFsdWU9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpzdGF0dXM6U3VjY2VzcyIvPg0KICA8L3NhbWxwOlN0YXR1cz4NCiAgPHNhbWw6QXNzZXJ0aW9uIElEPSJfMyIgSXNzdWVJbnN0YW50PSIyMDE2LTAyLTEwVDIxOjEyOjA5WiIgVmVyc2lvbj0iMi4wIiB4bWxuczpzYW1sPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIiB4bWxuczp4cz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiIHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiPg0KICAgIDxzYW1sOklzc3Vlcj5odHRwczovL2lkcC5leGFtcGxlLmNvbS9tZXRhZGF0YS54bWw8L3NhbWw6SXNzdWVyPg0KICAgIDxzYW1sOlN1YmplY3Q+DQogICAgICA8c2FtbDpOYW1lSUQgRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoxLjE6bmFtZWlkLWZvcm1hdDplbWFpbEFkZHJlc3MiLz4NCiAgICAgIDxzYW1sOlN1YmplY3RDb25maXJtYXRpb24gTWV0aG9kPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6Y206YmVhcmVyIj4NCiAgICAgICAgPHNhbWw6U3ViamVjdENvbmZpcm1hdGlvbkRhdGEgSW5SZXNwb25zZVRvPSJfMSIgTm90T25PckFmdGVyPSIyMDE2LTAyLTEwVDIxOjE1OjA5WiIgUmVjaXBpZW50PSIiLz4NCiAgICAgIDwvc2FtbDpTdWJqZWN0Q29uZmlybWF0aW9uPg0KICAgIDwvc2FtbDpTdWJqZWN0Pg0KICAgIDxzYW1sOkNvbmRpdGlvbnMgTm90QmVmb3JlPSIyMDE2LTAyLTEwVDIxOjA5OjA5WiIgTm90T25PckFmdGVyPSIyMDE2LTAyLTEwVDIxOjE1OjA5WiI+DQogICAgICA8c2FtbDpBdWRpZW5jZVJlc3RyaWN0aW9uPg0KICAgICAgICA8c2FtbDpBdWRpZW5jZT5odHRwczovL3NwLmV4YW1wbGUuY29tL21ldGFkYXRhLnhtbDwvc2FtbDpBdWRpZW5jZT4NCiAgICAgIDwvc2FtbDpBdWRpZW5jZVJlc3RyaWN0aW9uPg0KICAgIDwvc2FtbDpDb25kaXRpb25zPg0KICAgIDxzYW1sOkF1dGhuU3RhdGVtZW50IEF1dGhuSW5zdGFudD0iMjAxNi0wMi0xMFQyMToxMjowOFoiIFNlc3Npb25Ob3RPbk9yQWZ0ZXI9IjIwMTYtMDItMTFUMjE6MTI6MDlaIj4NCiAgICAgIDxzYW1sOkF1dGhuQ29udGV4dD4NCiAgICAgICAgPHNhbWw6QXV0aG5Db250ZXh0Q2xhc3NSZWY+dXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFjOmNsYXNzZXM6UGFzc3dvcmRQcm90ZWN0ZWRUcmFuc3BvcnQ8L3NhbWw6QXV0aG5Db250ZXh0Q2xhc3NSZWY+DQogICAgICA8L3NhbWw6QXV0aG5Db250ZXh0Pg0KICAgIDwvc2FtbDpBdXRoblN0YXRlbWVudD4NCiAgICA8c2FtbDpBdHRyaWJ1dGVTdGF0ZW1lbnQ+DQogICAgICA8QXR0cmlidXRlIE5hbWU9Imh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL2dpdmVubmFtZSI+DQogICAgICAgIDxBdHRyaWJ1dGVWYWx1ZT5UZXN0PC9BdHRyaWJ1dGVWYWx1ZT4NCiAgICAgIDwvQXR0cmlidXRlPg0KICAgIDwvc2FtbDpBdHRyaWJ1dGVTdGF0ZW1lbnQ+DQogIDwvc2FtbDpBc3NlcnRpb24+DQo8L3NhbWxwOlJlc3BvbnNlPg==
2 |
--------------------------------------------------------------------------------
/test/data/empty_nameid.xml:
--------------------------------------------------------------------------------
1 | PD94bWwgdmVyc2lvbj0iMS4wIj8+DQo8c2FtbHA6UmVzcG9uc2UgRGVzdGluYXRpb249Imh0dHBzOi8vc3AuZXhhbXBsZS5jb20vYXNzZXJ0IiBJRD0iXzIiIEluUmVzcG9uc2VUbz0iXzEiIFZlcnNpb249IjIuMCIgeG1sbnM6c2FtbHA9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpwcm90b2NvbCI+DQogIDxzYW1scDpTdGF0dXM+DQogICAgPHNhbWxwOlN0YXR1c0NvZGUgVmFsdWU9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpzdGF0dXM6U3VjY2VzcyIvPg0KICA8L3NhbWxwOlN0YXR1cz4NCiAgPHNhbWw6QXNzZXJ0aW9uIElEPSJfMyIgSXNzdWVJbnN0YW50PSIyMDE2LTAyLTEwVDIxOjEyOjA5WiIgVmVyc2lvbj0iMi4wIiB4bWxuczpzYW1sPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIiB4bWxuczp4cz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiIHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiPg0KICAgIDxzYW1sOklzc3Vlcj5odHRwczovL2lkcC5leGFtcGxlLmNvbS9tZXRhZGF0YS54bWw8L3NhbWw6SXNzdWVyPg0KICAgIDxzYW1sOlN1YmplY3Q+DQogICAgICA8c2FtbDpOYW1lSUQgRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoxLjE6bmFtZWlkLWZvcm1hdDplbWFpbEFkZHJlc3MiLz4NCiAgICAgIDxzYW1sOlN1YmplY3RDb25maXJtYXRpb24gTWV0aG9kPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6Y206YmVhcmVyIj4NCiAgICAgICAgPHNhbWw6U3ViamVjdENvbmZpcm1hdGlvbkRhdGEgSW5SZXNwb25zZVRvPSJfMSIgTm90T25PckFmdGVyPSIyMDE2LTAyLTEwVDIxOjE1OjA5WiIgUmVjaXBpZW50PSIiLz4NCiAgICAgIDwvc2FtbDpTdWJqZWN0Q29uZmlybWF0aW9uPg0KICAgIDwvc2FtbDpTdWJqZWN0Pg0KICAgIDxzYW1sOkNvbmRpdGlvbnMgTm90QmVmb3JlPSIyMDE2LTAyLTEwVDIxOjA5OjA5WiIgTm90T25PckFmdGVyPSIyMDE2LTAyLTEwVDIxOjE1OjA5WiI+DQogICAgICA8c2FtbDpBdWRpZW5jZVJlc3RyaWN0aW9uPg0KICAgICAgICA8c2FtbDpBdWRpZW5jZT5odHRwczovL3NwLmV4YW1wbGUuY29tL21ldGFkYXRhLnhtbDwvc2FtbDpBdWRpZW5jZT4NCiAgICAgIDwvc2FtbDpBdWRpZW5jZVJlc3RyaWN0aW9uPg0KICAgIDwvc2FtbDpDb25kaXRpb25zPg0KICAgIDxzYW1sOkF1dGhuU3RhdGVtZW50IEF1dGhuSW5zdGFudD0iMjAxNi0wMi0xMFQyMToxMjowOFoiIFNlc3Npb25JbmRleD0iXzQiIFNlc3Npb25Ob3RPbk9yQWZ0ZXI9IjIwMTYtMDItMTFUMjE6MTI6MDlaIj4NCiAgICAgIDxzYW1sOkF1dGhuQ29udGV4dD4NCiAgICAgICAgPHNhbWw6QXV0aG5Db250ZXh0Q2xhc3NSZWY+dXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFjOmNsYXNzZXM6UGFzc3dvcmRQcm90ZWN0ZWRUcmFuc3BvcnQ8L3NhbWw6QXV0aG5Db250ZXh0Q2xhc3NSZWY+DQogICAgICA8L3NhbWw6QXV0aG5Db250ZXh0Pg0KICAgIDwvc2FtbDpBdXRoblN0YXRlbWVudD4NCiAgICA8c2FtbDpBdHRyaWJ1dGVTdGF0ZW1lbnQ+DQogICAgICA8QXR0cmlidXRlIE5hbWU9Imh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL2dpdmVubmFtZSI+DQogICAgICAgIDxBdHRyaWJ1dGVWYWx1ZT5UZXN0PC9BdHRyaWJ1dGVWYWx1ZT4NCiAgICAgIDwvQXR0cmlidXRlPg0KICAgIDwvc2FtbDpBdHRyaWJ1dGVTdGF0ZW1lbnQ+DQogIDwvc2FtbDpBc3NlcnRpb24+DQo8L3NhbWxwOlJlc3BvbnNlPg==
--------------------------------------------------------------------------------
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | version: 2.1
2 |
3 | references:
4 | defaults: &defaults
5 | working_directory: ~/Clever/saml2
6 | environment:
7 | CIRCLE_ARTIFACTS: /tmp/circleci-artifacts
8 | CIRCLE_TEST_REPORTS: /tmp/circleci-test-results
9 |
10 | orbs:
11 | node: circleci/node@5.0.3
12 |
13 | executors:
14 | tester:
15 | <<: *defaults
16 | docker:
17 | - image: cimg/base:stable
18 | node-v12:
19 | <<: *defaults
20 | docker:
21 | - image: cimg/node:12.22
22 |
23 | commands:
24 | clone-ci-scripts:
25 | description: Clone the ci-scripts repo
26 | steps:
27 | - run:
28 | name: Clone ci-scripts
29 | command: cd .. && git clone --depth 1 -v https://github.com/Clever/ci-scripts.git && cd ci-scripts && git show --oneline -s
30 |
31 | jobs:
32 | build:
33 | executor: node-v12
34 | steps:
35 | - checkout
36 | - run: npm install
37 | - persist_to_workspace:
38 | root: ~/Clever
39 | paths: ["."]
40 |
41 | test:
42 | parameters:
43 | node-version:
44 | type: string
45 | executor: tester
46 | steps:
47 | - checkout
48 | - node/install:
49 | node-version: << parameters.node-version >>
50 | - node/install-packages:
51 | with-cache: false
52 | override-ci-command: npm install
53 | - run: npm run test
54 |
55 | publish:
56 | executor: node-v12
57 | steps:
58 | - attach_workspace:
59 | at: ~/Clever
60 | - clone-ci-scripts
61 | - run: if [ "${CIRCLE_BRANCH}" == "master" ]; then ../ci-scripts/circleci/npm-publish $NPM_TOKEN .; fi;
62 |
63 | publish_utility:
64 | executor: node-v12
65 | steps:
66 | - attach_workspace:
67 | at: ~/Clever
68 | - clone-ci-scripts
69 | - run: ../ci-scripts/circleci/catalog-sync $CATAPULT_URL $CATAPULT_USER $CATAPULT_PASS saml2 utility
70 | workflows:
71 | version: 2
72 | build_test_publish:
73 | jobs:
74 | - build
75 | - test:
76 | matrix:
77 | parameters:
78 | node-version: ["14", "16", "18", "20", "22", "24", "latest"]
79 | - publish:
80 | requires:
81 | - build
82 | - test
83 | - publish_utility:
84 | requires:
85 | - build
86 | - test
87 |
--------------------------------------------------------------------------------
/test/data/response_unsigned_assertion.xml:
--------------------------------------------------------------------------------
1 | PHNhbWxwOlJlc3BvbnNlIHhtbG5zOnNhbWxwPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6cHJvdG9jb2wiIElEPSJfMiIgVmVyc2lvbj0iMi4wIiBJblJlc3BvbnNlVG89Il8xIiBEZXN0aW5hdGlvbj0iaHR0cHM6Ly9zcC5leGFtcGxlLmNvbS9hc3NlcnQiPg0KICA8c2FtbHA6U3RhdHVzPg0KICAgIDxzYW1scDpTdGF0dXNDb2RlIFZhbHVlPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6c3RhdHVzOlN1Y2Nlc3MiLz4NCiAgPC9zYW1scDpTdGF0dXM+DQo8QXNzZXJ0aW9uIHhtbG5zPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIiBJRD0iXzMiIElzc3VlSW5zdGFudD0iMjAxNC0wMy0xMlQyMTozNTowNS4zOTJaIiBWZXJzaW9uPSIyLjAiPg0KICA8RGF0YSBJRD0iXzUiPlRoaXMgZGF0YSBoYXMgbm8gbWVhbmluZy48L0RhdGE+DQogIDxJc3N1ZXI+aHR0cDovL2lkcC5leGFtcGxlLmNvbS9tZXRhZGF0YS54bWw8L0lzc3Vlcj4NCiAgPFN1YmplY3Q+DQogICAgPE5hbWVJRCBGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpuYW1laWQtZm9ybWF0OnRyYW5zaWVudCI+dHN0dWRlbnQ8L05hbWVJRD4NCiAgICA8U3ViamVjdENvbmZpcm1hdGlvbiBNZXRob2Q9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpjbTpiZWFyZXIiPg0KICAgICAgPFN1YmplY3RDb25maXJtYXRpb25EYXRhIEluUmVzcG9uc2VUbz0iXzQiIE5vdE9uT3JBZnRlcj0iMjAxNC0wMy0xMlQyMTo0MDowNS4zOTJaIiBSZWNpcGllbnQ9Imh0dHBzOi8vc3AuZXhhbXBsZS5jb20vYXNzZXJ0Ii8+DQogICAgPC9TdWJqZWN0Q29uZmlybWF0aW9uPg0KICA8L1N1YmplY3Q+DQogIDxDb25kaXRpb25zIE5vdEJlZm9yZT0iMjAxNC0wMy0xMlQyMTozNTowNS4zODdaIiBOb3RPbk9yQWZ0ZXI9IjIwMTQtMDMtMTJUMjI6MzU6MDUuMzg3WiI+DQogICAgPEF1ZGllbmNlUmVzdHJpY3Rpb24+DQogICAgICA8QXVkaWVuY2U+aHR0cHM6Ly9zcC5leGFtcGxlLmNvbS9tZXRhZGF0YS54bWw8L0F1ZGllbmNlPg0KICAgIDwvQXVkaWVuY2VSZXN0cmljdGlvbj4NCiAgPC9Db25kaXRpb25zPg0KICA8QXR0cmlidXRlU3RhdGVtZW50Pg0KICAgIDxBdHRyaWJ1dGUgTmFtZT0iaHR0cDovL3NjaGVtYXMueG1sc29hcC5vcmcvd3MvMjAwNS8wNS9pZGVudGl0eS9jbGFpbXMvZ2l2ZW5uYW1lIj4NCiAgICAgIDxBdHRyaWJ1dGVWYWx1ZT5UZXN0PC9BdHRyaWJ1dGVWYWx1ZT4NCiAgICA8L0F0dHJpYnV0ZT4NCiAgPC9BdHRyaWJ1dGVTdGF0ZW1lbnQ+DQogIDxBdXRoblN0YXRlbWVudCBBdXRobkluc3RhbnQ9IjIwMTQtMDMtMTJUMjE6MzU6MDUuMzU0WiIgU2Vzc2lvbkluZGV4PSJfMyI+DQogICAgPEF1dGhuQ29udGV4dD4NCiAgICAgIDxBdXRobkNvbnRleHRDbGFzc1JlZj51cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YWM6Y2xhc3NlczpQYXNzd29yZFByb3RlY3RlZFRyYW5zcG9ydDwvQXV0aG5Db250ZXh0Q2xhc3NSZWY+DQogICAgPC9BdXRobkNvbnRleHQ+DQogIDwvQXV0aG5TdGF0ZW1lbnQ+DQo8U2lnbmF0dXJlIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjIj48U2lnbmVkSW5mbz48Q2Fub25pY2FsaXphdGlvbk1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyIvPjxTaWduYXR1cmVNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjcnNhLXNoYTEiLz48UmVmZXJlbmNlIFVSST0iI181Ij48VHJhbnNmb3Jtcz48VHJhbnNmb3JtIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIi8+PC9UcmFuc2Zvcm1zPjxEaWdlc3RNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjc2hhMSIvPjxEaWdlc3RWYWx1ZT4xaWVPaWxkbnBmUml1NlZBZzBjeHBLTjlkZ1E9PC9EaWdlc3RWYWx1ZT48L1JlZmVyZW5jZT48L1NpZ25lZEluZm8+PFNpZ25hdHVyZVZhbHVlPkRZL3MzTmF6V2Q2VWpGVzA2TkdIbTUxSEtrclp3aHFRTXF5ZWdGY0JBT1VFd2VKZW95ekVmOWJaUmRacSs4cFdlNUNVT2NJWE1SWTRicjFNbFNnSEVDYzNYckI0aUNLYTdMbkFqRytnWXFDNnZwVGlsSERxaTJoRkhSTUZWTnMwZS9RVkRwNmkvWUg3a3RWcTJpY0VDNzNmNkJKSldlZjltaWxnVnN1Q05GU0k1OHM2bEhGd0VyVGFKV2tBd2grVHhlTWFPV0UyYmdkQTJ0Mlh4QUFBOW1LSk5VaGpsQUs1OGFiNjhnbVhwdlQ3NUtNSlcybzdaQzVyZmJmVXREU1NvOG51aU9WREo0MFZZcGxla3VjdGlrTWMyYUVrdTJweW1NV1Z4SXZUaW03TVBxSVMrMzRuczJDOXFJTEtlUkZZa24wY25qOFZybUtta0oyUUxJYjFaUT09PC9TaWduYXR1cmVWYWx1ZT48L1NpZ25hdHVyZT48L0Fzc2VydGlvbj4NCjwvc2FtbHA6UmVzcG9uc2U+
--------------------------------------------------------------------------------
/test/data/good_assertion_no_session_index.xml:
--------------------------------------------------------------------------------
1 |
2 | http://idp.example.com/metadata.xml
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | bzIFJU/QWpxqY/8wYIi1MhtaIYY=
13 |
14 |
15 | LUAuLKGIAyGcMldwk2gTbyrcrLRZhJZkfK/PgxmHRxJ3lI+xn1A1n8RvHV8OWhFCG7sdTuSEDcqHN6nBQpZZaJ18qIkupV5vwPm3Mu6HFYSKAOrn245sjcjFCG9lJgxOiyeozE8QZ3FNeLnMYuSl7zB9nmjFQJMcHxmrVoCINjbokzjpNiXw56jUqlLJ+kT9ToKjHgcjChlJX75yYSuv+JT8s1UBT3PM7KoqTl97/KS2y7NQR+3hm9vk8uzcrrXgqr7WnizS17FG9q+ivic7w04F/S+yT3FVP5s0TCuck7ER5cYxYEzh+YWF6T7Ar0urn/2gfPMZ32l3tm0KLNaSMw==
16 |
17 |
18 |
19 |
20 |
21 | tstudent
22 |
23 |
24 |
25 |
26 |
27 |
28 | https://sp.example.com/metadata.xml
29 |
30 |
31 |
32 |
33 | Test
34 |
35 |
36 | tstudent@example.com
37 |
38 |
39 | tstudent
40 |
41 |
42 | CN=Students,CN=Users,DC=idp,DC=example,DC=com
43 |
44 |
45 | Student
46 |
47 |
48 | Test Student
49 |
50 |
51 |
52 |
53 | urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/test/data/good_assertion.xml:
--------------------------------------------------------------------------------
1 |
2 | http://idp.example.com/metadata.xml
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | /otGbaGvPsxvHXpaxzS5QXWvJRQ=
13 |
14 |
15 | BOeWxdgnJw1hx2Vvwja947xDb8/5T+zFI1o8xw4aPH7lxxWVXk9s8UOYP99yjH1c+2iFNzm5VNaZG5op08bxZSHRsgU4DQ35jMO/D8Ra42zKRXHOd0TunjZ8WQhYV8RoESHKjsUGyjLhlavFMyUDMr+O4d3GSn+r5lBlw40zwyn7f7j+or8gyemp618vlTXrT31L9+xZaLRKgF8I0ZC4WpfJZGWOj7x4u/X1xfggf0jtDmbLrY8aMIXrH1cn46VnMqIrEwMC1zIJfPU+GeBQRDgcGhzq2ttaA2v3rGMzamk3qlqgMOEbI3kBWXSTuddPRkn5GVhQkb9nGa/0neAWzQ==
16 |
17 |
18 |
19 |
20 |
21 | tstudent
22 |
23 |
24 |
25 |
26 |
27 |
28 | https://sp.example.com/metadata.xml
29 |
30 |
31 |
32 |
33 | Test
34 |
35 |
36 | tstudent@example.com
37 |
38 |
39 | tstudent
40 |
41 |
42 | CN=Students,CN=Users,DC=idp,DC=example,DC=com
43 |
44 |
45 | Student
46 |
47 |
48 | Test Student
49 |
50 |
51 |
52 |
53 | urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
54 |
55 |
56 |
--------------------------------------------------------------------------------
/test/data/response_external_signed_assertion.xml:
--------------------------------------------------------------------------------
1 | PHNhbWxwOlJlc3BvbnNlIHhtbG5zOnNhbWxwPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6cHJvdG9jb2wiIElEPSJfMiIgVmVyc2lvbj0iMi4wIiBJblJlc3BvbnNlVG89Il8xIiBEZXN0aW5hdGlvbj0iaHR0cHM6Ly9zcC5leGFtcGxlLmNvbS9hc3NlcnQiPg0KICA8c2FtbHA6U3RhdHVzPg0KICAgIDxzYW1scDpTdGF0dXNDb2RlIFZhbHVlPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6c3RhdHVzOlN1Y2Nlc3MiLz4NCiAgPC9zYW1scDpTdGF0dXM+DQogIDxBc3NlcnRpb24geG1sbnM9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iIElEPSJfMyIgSXNzdWVJbnN0YW50PSIyMDE0LTAzLTEyVDIxOjM1OjA1LjM5MloiIFZlcnNpb249IjIuMCI+DQogICAgPERhdGEgSUQ9Il81Ij5UaGlzIGRhdGEgaGFzIG5vIG1lYW5pbmcuPC9EYXRhPg0KICAgIDxJc3N1ZXI+aHR0cDovL2lkcC5leGFtcGxlLmNvbS9tZXRhZGF0YS54bWw8L0lzc3Vlcj4NCiAgICA8U3ViamVjdD4NCiAgICAgIDxOYW1lSUQgRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6bmFtZWlkLWZvcm1hdDp0cmFuc2llbnQiPnRzdHVkZW50PC9OYW1lSUQ+DQogICAgICA8U3ViamVjdENvbmZpcm1hdGlvbiBNZXRob2Q9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpjbTpiZWFyZXIiPg0KCTxTdWJqZWN0Q29uZmlybWF0aW9uRGF0YSBJblJlc3BvbnNlVG89Il80IiBOb3RPbk9yQWZ0ZXI9IjIwMTQtMDMtMTJUMjE6NDA6MDUuMzkyWiIgUmVjaXBpZW50PSJodHRwczovL3NwLmV4YW1wbGUuY29tL2Fzc2VydCIvPg0KICAgICAgPC9TdWJqZWN0Q29uZmlybWF0aW9uPg0KICAgIDwvU3ViamVjdD4NCiAgICA8Q29uZGl0aW9ucyBOb3RCZWZvcmU9IjIwMTQtMDMtMTJUMjE6MzU6MDUuMzg3WiIgTm90T25PckFmdGVyPSIyMDE0LTAzLTEyVDIyOjM1OjA1LjM4N1oiPg0KICAgICAgPEF1ZGllbmNlUmVzdHJpY3Rpb24+DQoJPEF1ZGllbmNlPmh0dHBzOi8vc3AuZXhhbXBsZS5jb20vbWV0YWRhdGEueG1sPC9BdWRpZW5jZT4NCiAgICAgIDwvQXVkaWVuY2VSZXN0cmljdGlvbj4NCiAgICA8L0NvbmRpdGlvbnM+DQogICAgPEF0dHJpYnV0ZVN0YXRlbWVudD4NCiAgICAgIDxBdHRyaWJ1dGUgTmFtZT0iaHR0cDovL3NjaGVtYXMueG1sc29hcC5vcmcvd3MvMjAwNS8wNS9pZGVudGl0eS9jbGFpbXMvZ2l2ZW5uYW1lIj4NCgk8QXR0cmlidXRlVmFsdWU+VGVzdDwvQXR0cmlidXRlVmFsdWU+DQogICAgICA8L0F0dHJpYnV0ZT4NCiAgICA8L0F0dHJpYnV0ZVN0YXRlbWVudD4NCiAgICA8QXV0aG5TdGF0ZW1lbnQgQXV0aG5JbnN0YW50PSIyMDE0LTAzLTEyVDIxOjM1OjA1LjM1NFoiIFNlc3Npb25JbmRleD0iXzMiPg0KICAgICAgPEF1dGhuQ29udGV4dD4NCgk8QXV0aG5Db250ZXh0Q2xhc3NSZWY+dXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFjOmNsYXNzZXM6UGFzc3dvcmRQcm90ZWN0ZWRUcmFuc3BvcnQ8L0F1dGhuQ29udGV4dENsYXNzUmVmPg0KICAgICAgPC9BdXRobkNvbnRleHQ+DQogICAgPC9BdXRoblN0YXRlbWVudD4NCiAgPC9Bc3NlcnRpb24+DQo8U2lnbmF0dXJlIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjIj48U2lnbmVkSW5mbz48Q2Fub25pY2FsaXphdGlvbk1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyIvPjxTaWduYXR1cmVNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGRzaWctbW9yZSNyc2Etc2hhMjU2Ii8+PFJlZmVyZW5jZSBVUkk9IiNfMiI+PFRyYW5zZm9ybXM+PFRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNlbnZlbG9wZWQtc2lnbmF0dXJlIi8+PFRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyIvPjwvVHJhbnNmb3Jtcz48RGlnZXN0TWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnI3NoYTEiLz48RGlnZXN0VmFsdWU+S1dPVllha0JVQXgzbFhqQm5BeExiRHJWRzhRPTwvRGlnZXN0VmFsdWU+PC9SZWZlcmVuY2U+PC9TaWduZWRJbmZvPjxTaWduYXR1cmVWYWx1ZT5qQjBHbW85anVmZk9VVXY5bWIvaU1iSXA5YjFxZTkxL0RtMUZCcytTb0tMTzh1KzZ4T0xNTHArQ1h2bmxMK3VpVFlnVE1HYmRGWjZlNnpFSG96TFNCeWpOWjQ3aWVHVG9ocGh0c2VqQitZMTdDNUZjclQxS05ZVWtPMkNZd0l6cSt4TVJwK0MrQXIwQTJoRzRiMktxT0drc2JrZWp0TDY3bVNiNG9KaExKTUZ4Mk5FaU5VN1E2eTlGeHhJZW5IS0hXUFgzeEVxdHFVU3RvcXhRY2p3aWpYTm9IMUdKZWJUWEsvQW9NZG10bTMzS0pON1ova1lkWlFZdndGRmg2dzZHZTdVZVB4OVVXQmtUZUNSLytNb25RTG1lUzQwbDBHb3ZRU3BiYkdZd0RUbWlXYmZwVFlYdTFGRGN1cVMrTFkxM1RwTFpJai9BVHRHajM3Qm94Uk4zVXc9PTwvU2lnbmF0dXJlVmFsdWU+PC9TaWduYXR1cmU+PC9zYW1scDpSZXNwb25zZT4=
--------------------------------------------------------------------------------
/test/data/response_notbefore_future_encrypted_decoded.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 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
9 |
10 |
11 |
--------------------------------------------------------------------------------
/test/data/good_assertion_commented_out_digest.xml:
--------------------------------------------------------------------------------
1 |
2 | http://idp.example.com/metadata.xml
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | /otGbaGvPsxvHXpaxzS5QXWvJRQ=
13 |
14 |
15 | BOeWxdgnJw1hx2Vvwja947xDb8/5T+zFI1o8xw4aPH7lxxWVXk9s8UOYP99yjH1c+2iFNzm5VNaZG5op08bxZSHRsgU4DQ35jMO/D8Ra42zKRXHOd0TunjZ8WQhYV8RoESHKjsUGyjLhlavFMyUDMr+O4d3GSn+r5lBlw40zwyn7f7j+or8gyemp618vlTXrT31L9+xZaLRKgF8I0ZC4WpfJZGWOj7x4u/X1xfggf0jtDmbLrY8aMIXrH1cn46VnMqIrEwMC1zIJfPU+GeBQRDgcGhzq2ttaA2v3rGMzamk3qlqgMOEbI3kBWXSTuddPRkn5GVhQkb9nGa/0neAWzQ==
16 |
17 |
18 |
19 |
20 |
21 | tstudent
22 |
23 |
24 |
25 |
26 |
27 |
28 | https://sp.example.com/metadata.xml
29 |
30 |
31 |
32 |
33 | Test
34 |
35 |
36 | tstudent@example.com
37 |
38 |
39 | tstudent
40 |
41 |
42 | CN=Students,CN=Users,DC=idp,DC=example,DC=com
43 |
44 |
45 | Student
46 |
47 |
48 | Test Student
49 |
50 |
51 |
52 |
53 | urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
54 |
55 |
56 |
--------------------------------------------------------------------------------
/test/data/good_assertion_explicit_namespaces.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | http://idp.example.com/metadata.xml
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | bzIFJU/QWpxqY/8wYIi1MhtaIYY=
14 |
15 |
16 | LUAuLKGIAyGcMldwk2gTbyrcrLRZhJZkfK/PgxmHRxJ3lI+xn1A1n8RvHV8OWhFCG7sdTuSEDcqHN6nBQpZZaJ18qIkupV5vwPm3Mu6HFYSKAOrn245sjcjFCG9lJgxOiyeozE8QZ3FNeLnMYuSl7zB9nmjFQJMcHxmrVoCINjbokzjpNiXw56jUqlLJ+kT9ToKjHgcjChlJX75yYSuv+JT8s1UBT3PM7KoqTl97/KS2y7NQR+3hm9vk8uzcrrXgqr7WnizS17FG9q+ivic7w04F/S+yT3FVP5s0TCuck7ER5cYxYEzh+YWF6T7Ar0urn/2gfPMZ32l3tm0KLNaSMw==
17 |
18 |
19 |
20 |
21 |
22 | tstudent
23 |
24 |
25 |
26 |
27 |
28 |
29 | https://sp.example.com/metadata.xml
30 |
31 |
32 |
33 |
34 | Test
35 |
36 |
37 | tstudent@example.com
38 |
39 |
40 | tstudent
41 |
42 |
43 | CN=Students,CN=Users,DC=idp,DC=example,DC=com
44 |
45 |
46 | Student
47 |
48 |
49 | Test Student
50 |
51 |
52 |
53 |
54 | urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/test/data/response_notbefore_future_signed.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | This data has no meaning.
7 | http://idp.example.com/metadata.xml
8 |
9 |
10 | I7HHjuQfXmELXf7TyRClXhzshwQ=K5JAWPa2KVtx2r4s5FN0XagYCUaxlN2OQbbzvqxZRbsnqFhluYaBR0Hlv/aygvGkv7OFBfpvojKsshHxPOArNT7CM1YNhV2RQ9v5IL7A396XvNpWdcMgGRL4FcAEzOcgAwmRYjYUfqChbY7cFKyMvyVVowdE4wGKyYAZiRwC8npbjZNuqTekofheF0fxnYm3CRzT5akztMugY0HHmy9WsochrDtoglwkjrZTSBlgYLGD3Yk7mCZos6IGo9zK6eF/ycPxGqR597WQOtLr9dnmhs0IE3iKQaS2hY2WwoPqJZgDPOoHtFBaDrkVY/JG0ucrg0eVkKtNHRKTYSgzv+JK/w==
11 | MIIDGTCCAgGgAwIBAgIJAO8HJfrb3JZeMA0GCSqGSIb3DQEBBQUAMCMxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0xNDAzMTgwMTE3MTdaFw0yNDAzMTcwMTE3MTdaMCMxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMFf1kCef6FTPMxQSoThAZGFNmixh8fRDLsUo58pEFwztBRUPWS6s6Ql8mA75aAEdo4+JVyE8QPi5F+fWbnToWkIw7E7YGl6s+EScSMQYHKCLq4mPHPMHtZspFowNp+Vax88SSUo1TKlpVNVIGim8JQ5SRi3p0aD6UAiu9WxQ5s+xHnDwgvQiu3Sa4COl5NQjkC1r2LrhJnJQQiw0hsn1nGgg15jEaDCZa8uPw1EtHv8smoZpjTbwRBVjXtzLskYIRyYLQjvqR+/QAd0XZcav0LdTwQR6obg/CwSgv7qG/WN6t25VIIGQDIUkVMBhLDmCh8QRpTvx1YWumSWW4D2k2kCAwEAAaNQME4wHQYDVR0OBBYEFLpo8Vz1m19xvPmzx+2wf2PaSTIpMB8GA1UdIwQYMBaAFLpo8Vz1m19xvPmzx+2wf2PaSTIpMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBALhwpLS6C+97nWrEICI5yetQjexCJGltMESg1llNYjsbIuJ/S4XbrVzhN4nfNGMSbj8rb/9FT6TSru5QLjJQQmj38pqsWtEhR2vBLclqGqEcJfvPMdn1qAJhJfhrs0KUpsX6xFTnSkNoyGxCP8Wh2C1L0NL5r+x58lkma5vL6ncwWYY+0C3bt1XbBRdeOZHUwuYTIcD+BCNixQiNor7KjO1TzpOb6V3m1SKHu8idDM5fUcKooGbV3WuE7AJrAG5fvt59V9MtMPc2FklVFminfTeYKboEaxZJxuPDbQs2IyJ/0lI8P0Mv4LIKj4+OipQ/fGbZuE7cOioPKKl02dE7eCA=
12 |
13 | tstudent
14 |
15 |
16 |
17 |
18 |
19 |
20 | https://sp.example.com/metadata.xml
21 |
22 |
23 |
24 |
25 | Test
26 |
27 |
28 |
29 |
30 | urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/test/data/response_notbefore_future_encrypted.xml:
--------------------------------------------------------------------------------
1 | PHNhbWxwOlJlc3BvbnNlIHhtbG5zOnNhbWxwPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6cHJvdG9jb2wiIHhtbG5zOnNhbWw9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iIElEPSJfMiIgVmVyc2lvbj0iMi4wIiBJblJlc3BvbnNlVG89Il8xIiBEZXN0aW5hdGlvbj0iaHR0cHM6Ly9zcC5leGFtcGxlLmNvbS9hc3NlcnQiPg0KICAgIDxzYW1scDpTdGF0dXM+DQogICAgICAgIDxzYW1scDpTdGF0dXNDb2RlIFZhbHVlPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6c3RhdHVzOlN1Y2Nlc3MiLz4NCiAgICA8L3NhbWxwOlN0YXR1cz4NCiAgICANCjxzYW1sOkVuY3J5cHRlZEFzc2VydGlvbj48eGVuYzpFbmNyeXB0ZWREYXRhIHhtbG5zOnhlbmM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1sZW5jIyIgeG1sbnM6ZHNpZz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnIyIgVHlwZT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxlbmMjRWxlbWVudCI+PHhlbmM6RW5jcnlwdGlvbk1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1sZW5jI2FlczEyOC1jYmMiLz48ZHNpZzpLZXlJbmZvIHhtbG5zOmRzaWc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyMiPjx4ZW5jOkVuY3J5cHRlZEtleT48eGVuYzpFbmNyeXB0aW9uTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxlbmMjcnNhLW9hZXAtbWdmMXAiLz48eGVuYzpDaXBoZXJEYXRhPjx4ZW5jOkNpcGhlclZhbHVlPlduVU5MUnF0SEdrWE9uMXRKc2FWaDNBeXp2TDkrRnJKWWNoeE5BbkZDcGVWbG5nSC9oM3BSOFlLdG5BWEtmZHVSL2tVbXVRNFU4ZW14cDc3OXdjYzNqY2NEajJFcXZTUlhsNDM1MkhrQVV3T2Y2eWc3RURILzFKeFMrbHJRdURCd08yTCtmbVo1ckczdjdLeHlqc29GamMrQzhaNGNKaE5LWDcraFMyUWxBcHRDekNmNUhwaWk4TG9KVTk5bXUrZHJHckZZZ1A5SWV4QzZyWGRKSUNjM2NwWlh2d3ZKNDJYcXh5alNvTzU3OWFZTFdLZFdjdlVRVkhXaExIbTl4TTFkOVRDSGFRK0Q0NHlMM2xLUGViQVNMZGxwVWZ3S2V1UEs2MkZkN052ODVac2lWMm9WeEdzUmVmYk9zRk5hMEduTFNKSEpTYmxGYmZDQnlLaHJIV3BTQT09PC94ZW5jOkNpcGhlclZhbHVlPjwveGVuYzpDaXBoZXJEYXRhPjwveGVuYzpFbmNyeXB0ZWRLZXk+PC9kc2lnOktleUluZm8+DQogICA8eGVuYzpDaXBoZXJEYXRhPg0KICAgICAgPHhlbmM6Q2lwaGVyVmFsdWU+blVBYjk3SW0rbzBPN0pRd3V1R1dNdHpPR0hMZnFxVzVlVGVjejZYd0VldjBtQ3BsbHlRUzhHYnFIWHA1RWpVcXg1czZja3J5UXdKK2svT09uUTBFVnVCMStER1V6TmNjODJGWTF0NE9NRjJiRnVtUVBvK29GbUUyMWpHMnJabzhZSFdyMzNIVDNibzVYZUxPQ1JwTFRGRy9ZZ2lOSDRZN0dZblR4Sy9XZUtlN1JmY092QTZiWXBReWc0Qm1hdTZaeHBZaU42bmdMbFFqMmt4bFJHSG5yMWY0eFVGbjF0RVhvYThGTTNBTndiSlV2K1dyWEt4ZjlnZDNWSG9XL2VvVDVrK3pxLy9VejN4Wi9QTVhDa3loeGp0cmsxYWxkVTB5cEIxblV0UGo0N0lDNEJId2l1dEpneExMaTRrb2tRb0J0dU1PNzFyQ0c3bTFVUFI2Yy9idXlpaGMvZ0RuUTVWditzT3NndFA1NndoeTdoeVl1Y3hQRDUxMElSNlcySW5kMFp5eXNwcDRkM1JtZXBzSUZNRHNmcTE4VzZMWmFUQ1FSd0xyNTZORlJibjBaempEYy9GNEFhU1pleFdCTEg5VG9CcXdDVnpDNmorZjdGMWhEMHFQMU9jZ1dvcERFeHlTVllCNUtKQlIwUDNIRFBWdlg5VmNVN2lLVklQTUlRWEhVRnlMQjlZWjZBTCt4L1AvR2k1UG93MEh6bmU0TTFzQzk3eWc1RHU4WlQvcXM4cTBoVnJneTgweVR0Y3VwK1ZIZU96M3lxVWlWMDZJVlR1eStDRzZWbTR6am13RjB2b3BuanFKcElXRjMvN3ZZc1FmYlNJbld0OUdNdGYvQTgyNW4vRi8vMVpwRjFUL0pxTFRwR3NIczRRYmREdDJoR3pudThyWnpnMjZOT1dLR0wwVnZtdEJncmVWT3VnclYrV3FDNnVsZC9KWWFFZjFTSnNNOTZGcXdyME5tSXdWRFhJM09zZXc3QkRkTDVTRUV0UFRheHFXbVlybGpmRmZ0TXNLbGFBenU3SFpjU1V2Zi8wMTRobUJiaTBaY3N1cmVzQVBYMlFOcUJCaDJRYm95TS90VStxZSt2MXVsMTA3K2RLNFRnZU5oQWtsMHFnU1JsMmVNTkJDWUVPREZ0d0RmSVE3T3lLT1pFMzJsVzhmeGlMV3lleDdxczlDd2pCODRHeCtGMjVlSllPU0xJL0xvMUo4eE9McVN1UnVIYjRNNjR6bUZyalBENHdjcUZ2bTQ4d2UzWlVPVUVIREMyWDY4MjVoOWRvRGsrRDFtZFJoN3B5SEd0QmR6NTR4Tk5lajY5ZG1PNEJBcWRIZXhBNkNPTiszTndNYW02WmJoZm5RNkpscGVIUmtRZzkyeGh1d2NwWmo5bGpkSTl2bFM5T05XS09INGYwY3R1NEc3eFNjcGpDZkpBWlhuM2ZjeEg2U1VXY2g1UG1PYWFVazdCRmRLdTdzYitXcjNFWWsxd2F4aWtuNjNHdXJra1VhL2YrY1dDRWJZVXpZdWlHOUpkUVF1K1BHSmVjaXpKc21hL2lRTjl4NUxGUFNnM040L0RKZnVuRU9zN2tvVzhGR00zVWdnZ3h1N1VxY3lRNVphLzdVVmxoMmhtUFpsc09TNFlSNjh2VHFmaVYwQldsdmNoaE5ORTFxL3RYTWMxeHNhbGJVOS85UVcxcGxYTzMyb0F3ajVnSG0rcERSSUluakRKMDkxTFEzdnNweGVBbWJwOWJBYisyRC9DSXJaU21MWVhZMTY4aGFpVFFPYURHZXdtOElncm15UnhEWHkwWDFOU0FhL1U5Szd4cjZWNVhoaVVBVnVyVGN3Y1pnTVNOS29GMllwMlo5ajE4d0hpU09nd1Rna25UN0Z4K3BPMVdRMVBPVFJkN2JGa3RlMHR2a1BQaCttSk40cmN2N2ZpT3ljaEVnckdYNUo4YVp5ZUk5L2F6Z0RCVzdFdE1IRWNIakkyTFR0bEdXaG8wVjhBbzVFd09zd3lkRU5iTUFFNVBoWFhNc29kUXdadm1LZEt6U1AzWkR1VEhSUWVHcTdwc2NQc20xWERtZWxZOFFEeC84RUFpNzAwNy9leXA0Z1BKZVBTVlF3bHJGamFzS20rS1dQc1NqWG5CTGZ1TzVjOFZ6SDFhMDk5dlBxYTVZQzFQUUdPd3B4ZENxUG5HRmxuK2pTa05oaTNQcTZKNnZiTjVmbXBQS3VuWks3Y2E5b3VXNGlYRTBoUGhPY3l4bWZFeVV4R3NPQWtLSlBlZzdSVjRMUnpDNnB0cElDc0NXNU9PdW5nblhVSElWVnlRN0hXbDhBTStHclI2VjBidjBEcjh3U29IMmpjakRMclYxRHhtZktjd1kxV2JVNHZEWlBKYjFBZy85c2VJNEdwTmIyOFdmY3I5QUNhdlVsKzJEVjR2VXFKckRQRTFwRzFUVm1uUHhzQnNIbURiTThGL0FKUXRjRkNNYjRQcDdXbytrU3VWNVVibDlrR0VDMitGTkVTWlJsdlUxTVNNOFVBeGhkOHp0Tk1xcitVMTFDM2JlcWo2WjFpT1dDN21VU1dJMjByT2crTi9CY0pVUkZ4Mmo5QVpnS2J6dnBHcG4rSURSUXB2Sy9Saz08L3hlbmM6Q2lwaGVyVmFsdWU+DQogICA8L3hlbmM6Q2lwaGVyRGF0YT4NCjwveGVuYzpFbmNyeXB0ZWREYXRhPjwvc2FtbDpFbmNyeXB0ZWRBc3NlcnRpb24+PC9zYW1scDpSZXNwb25zZT4=
--------------------------------------------------------------------------------
/test/data/redirect_response.xml:
--------------------------------------------------------------------------------
1 | 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
--------------------------------------------------------------------------------
/test/data/response_notbefore_future_encrypted_then_signed.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | VNpShLvByJ91Q9vRHRCHCpMrj8I=tuwHh4kcJJAZIzRwYS9rzNkCIF4HGU9YhLJ9Nwft48axCJrUj0hkiIdZf3+vin6YUFj4JStPK0YBEIQsB5pxr91JZWnYLkotgD/T+rKhVkzxOMn3GcK24856cSFmQLmL53KRqzYSJIDY5y0c6E/kxDe9r+PMG4/ch83mjGOSPgHMFDYebIGEpw+7Y79qcGTfYUrnx7oIOOUspZNuaSv2yr3gqAmG8ZM06/F8FzunbW2S0nP8ymv09yfhoZf7XtJALDC6fmw/M0czbWWMVu+OC9pcRmCod5to5kud4BIoGILCpsLb9jy8uKPPpPuuFh0U8sMij45A3IHAJwi2btUJ6Q==
6 | MIIDGTCCAgGgAwIBAgIJAJQd/RSI51tKMA0GCSqGSIb3DQEBBQUAMCMxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0xNDAzMTgyMDMxMDNaFw0yNDAzMTcyMDMxMDNaMCMxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALxerkURM4678nuft7LQI7g5jySUHwHROCheAVt+kemVeg7JNFzPaF1AOm2n4S4xq4aI03/HW725sxZTJIit6TBSiboC6yuN/cM/mzwjhbV+gCQRz2DrI7MkGGujn5bH+vu3qzxpXSoSqrkuHWrdeNGHLBP0C/0pHU2RZJOGG1h+S+tiW+EGKz1PItfL7mg8V2EhieUBYLgxGxVsNYwtL7dWcib7Y4476Yx25d34k1IgBrvkyo3yx1GizwG00+0FR3/ykMYOexwiZzCrKbZoz1Bf0itu9vqjbzDy9gbkEQBIcZxpE5GOwAtyLNKgBdSyFj3zbRTUIyOtNdTv5CN34WMCAwEAAaNQME4wHQYDVR0OBBYEFFIQ7r0sopn/h79pX1qiQaWzcMGoMB8GA1UdIwQYMBaAFFIQ7r0sopn/h79pX1qiQaWzcMGoMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAHcMfEAswmSVRsRofaibLeP72Hm8zutb25ntpm3gcak+DikE4ZwI/HGYw2YpzGZ9v8ysxc/egc7lLKn+yOlObRdIFJmXu5MSf0G6D5/NRv8RagCa3x6KgjgZOTx5MNR8KX2y79bOupMMj/PnI4jA2jXbFFSUwz6MQFP/4VyhlpYqdhn3Qpuu8YVrW7KHcYm6RQHlrC70WCcfZEWLEHjU/uRwFK1+hMsULbbu3O8/zmJsU6O4b2ZbjCoPvsAZYPK0/OJYbyUxfpfHZ82KmF261HEKIchEWPkpiZivtrPfIOZFy6iV4bt0PT/SGoIbKOxh0Nxxyt2mHnpd030tUXNYLTc=
7 |
8 |
9 |
10 |
11 | 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
14 |
15 |
--------------------------------------------------------------------------------
/test/data/good_response_twice_signed_dsig_ns_at_top.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | VmOQiP59NeSBPwrhe5MDQJlNw/E=pPycwjnj6ezRb9vrmEQ0CTBlkRa7inhDCHUj2Z5s6pOuBZq2bdxY1jvplHz5FW6/2SPtsST5Wj6RZMClHGV8rlTBjgA92+EtGJHgaZYemvFTA1n/7SWI9vjP2Doy9JF8AeZlmN9xgZL/wVsKkdv/lk7B6stWfUI/PDRN5JVUYDvoSC2j1pxkdJ6zhFL9XWs9wUNlO2vsP1XsHrQ7ndn4h5K6J9frfc0IX6R7NBu/pDUk2Vx6Xh1RlhuZRD33KN38e58vs1qm1isFcoTgMhdAVjS41yf92b5KFuDp0x4dliV099QUZFtNH+7SH7pJXEkeLQnXpF/73jXLoMUjdn7qNQ==
6 | MIIDGTCCAgGgAwIBAgIJAO8HJfrb3JZeMA0GCSqGSIb3DQEBBQUAMCMxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0xNDAzMTgwMTE3MTdaFw0yNDAzMTcwMTE3MTdaMCMxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMFf1kCef6FTPMxQSoThAZGFNmixh8fRDLsUo58pEFwztBRUPWS6s6Ql8mA75aAEdo4+JVyE8QPi5F+fWbnToWkIw7E7YGl6s+EScSMQYHKCLq4mPHPMHtZspFowNp+Vax88SSUo1TKlpVNVIGim8JQ5SRi3p0aD6UAiu9WxQ5s+xHnDwgvQiu3Sa4COl5NQjkC1r2LrhJnJQQiw0hsn1nGgg15jEaDCZa8uPw1EtHv8smoZpjTbwRBVjXtzLskYIRyYLQjvqR+/QAd0XZcav0LdTwQR6obg/CwSgv7qG/WN6t25VIIGQDIUkVMBhLDmCh8QRpTvx1YWumSWW4D2k2kCAwEAAaNQME4wHQYDVR0OBBYEFLpo8Vz1m19xvPmzx+2wf2PaSTIpMB8GA1UdIwQYMBaAFLpo8Vz1m19xvPmzx+2wf2PaSTIpMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBALhwpLS6C+97nWrEICI5yetQjexCJGltMESg1llNYjsbIuJ/S4XbrVzhN4nfNGMSbj8rb/9FT6TSru5QLjJQQmj38pqsWtEhR2vBLclqGqEcJfvPMdn1qAJhJfhrs0KUpsX6xFTnSkNoyGxCP8Wh2C1L0NL5r+x58lkma5vL6ncwWYY+0C3bt1XbBRdeOZHUwuYTIcD+BCNixQiNor7KjO1TzpOb6V3m1SKHu8idDM5fUcKooGbV3WuE7AJrAG5fvt59V9MtMPc2FklVFminfTeYKboEaxZJxuPDbQs2IyJ/0lI8P0Mv4LIKj4+OipQ/fGbZuE7cOioPKKl02dE7eCA=
7 |
8 |
9 |
10 |
11 | This data has no meaning.
12 | http://idp.example.com/metadata.xml
13 |
14 |
15 | nS72XwOKD7SxpBrvb8MFkrmrPJM=cf4xvQneMFGQOsIgG/xrg8dpYbCvBZ5GUZkIMNA7BTT2tBuiP0djR/iS4uHPqnkbYLVnJd2gwh7Mg/7GySAVSSimfsNUk0LxKd59Nmw8z+iVTKzFnK7O6r4ifkPvWpIM28J1fJmqUINXRXBD1JQSY2p/4TPS1DQAUpYf8Yh1R4SWX0Xqiu2XgIrTXVrqh3X76fm4XMFmyL7FNt1wn8qzobqpfDYciNz1ZCfg9NwdFY4AeWSD3HeByJn9ct0CgNyDu5B6ii4CldfEUS6S15IlicuVimVteNXcSbyNN9/EOkBjCk9PtzgqzX5X4T0rF5CU6s2dSUAjCsmIEPWUr38B/w==
16 | MIIDGTCCAgGgAwIBAgIJAO8HJfrb3JZeMA0GCSqGSIb3DQEBBQUAMCMxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0xNDAzMTgwMTE3MTdaFw0yNDAzMTcwMTE3MTdaMCMxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMFf1kCef6FTPMxQSoThAZGFNmixh8fRDLsUo58pEFwztBRUPWS6s6Ql8mA75aAEdo4+JVyE8QPi5F+fWbnToWkIw7E7YGl6s+EScSMQYHKCLq4mPHPMHtZspFowNp+Vax88SSUo1TKlpVNVIGim8JQ5SRi3p0aD6UAiu9WxQ5s+xHnDwgvQiu3Sa4COl5NQjkC1r2LrhJnJQQiw0hsn1nGgg15jEaDCZa8uPw1EtHv8smoZpjTbwRBVjXtzLskYIRyYLQjvqR+/QAd0XZcav0LdTwQR6obg/CwSgv7qG/WN6t25VIIGQDIUkVMBhLDmCh8QRpTvx1YWumSWW4D2k2kCAwEAAaNQME4wHQYDVR0OBBYEFLpo8Vz1m19xvPmzx+2wf2PaSTIpMB8GA1UdIwQYMBaAFLpo8Vz1m19xvPmzx+2wf2PaSTIpMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBALhwpLS6C+97nWrEICI5yetQjexCJGltMESg1llNYjsbIuJ/S4XbrVzhN4nfNGMSbj8rb/9FT6TSru5QLjJQQmj38pqsWtEhR2vBLclqGqEcJfvPMdn1qAJhJfhrs0KUpsX6xFTnSkNoyGxCP8Wh2C1L0NL5r+x58lkma5vL6ncwWYY+0C3bt1XbBRdeOZHUwuYTIcD+BCNixQiNor7KjO1TzpOb6V3m1SKHu8idDM5fUcKooGbV3WuE7AJrAG5fvt59V9MtMPc2FklVFminfTeYKboEaxZJxuPDbQs2IyJ/0lI8P0Mv4LIKj4+OipQ/fGbZuE7cOioPKKl02dE7eCA=
17 |
18 | tstudent
19 |
20 |
21 |
22 |
23 |
24 |
25 | https://sp.example.com/metadata.xml
26 |
27 |
28 |
29 |
30 | Test
31 |
32 |
33 |
34 |
35 | urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/test/data/response_notbefore_future_signed_then_encrypted.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 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
9 |
10 |
--------------------------------------------------------------------------------
/test/data/good_response_twice_signed.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | AOtFKxIx0k7nIKQfj+FI0UCa1y4=DfgTCB/5JZ8mS0rb/N1aUsSzMVTYLYb0FbRtDyMDXemYVILXcN/rnLKHQBuH1Yjxe+pPXMBdkceK6aD+Ir+B7K+zNFtkqYCqEWYbBRuQI/TpPwxQ/3hNm7i5ml2d09ngZGlZlvN+v7/3QsoL/Ygda/xYLV9Zsp3nhbLOU0wLMlr1wB2yWzW94OidpwSzKf3d+jEo4+xWG7JTeAwLQiVcjI9NOOF+d7ZzymMccTeXmNqHVwBO8HMbGfVUItw4Ji+iFkAoageNPK0GAcDRhSnTJ1SeNGWdfUX5myTi7Vp6SfJAyBxJVeT/4n9WANbiLaYFL9Cc6qnC7EuUE7qkavq7hA==
6 | MIIDGTCCAgGgAwIBAgIJAO8HJfrb3JZeMA0GCSqGSIb3DQEBBQUAMCMxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0xNDAzMTgwMTE3MTdaFw0yNDAzMTcwMTE3MTdaMCMxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMFf1kCef6FTPMxQSoThAZGFNmixh8fRDLsUo58pEFwztBRUPWS6s6Ql8mA75aAEdo4+JVyE8QPi5F+fWbnToWkIw7E7YGl6s+EScSMQYHKCLq4mPHPMHtZspFowNp+Vax88SSUo1TKlpVNVIGim8JQ5SRi3p0aD6UAiu9WxQ5s+xHnDwgvQiu3Sa4COl5NQjkC1r2LrhJnJQQiw0hsn1nGgg15jEaDCZa8uPw1EtHv8smoZpjTbwRBVjXtzLskYIRyYLQjvqR+/QAd0XZcav0LdTwQR6obg/CwSgv7qG/WN6t25VIIGQDIUkVMBhLDmCh8QRpTvx1YWumSWW4D2k2kCAwEAAaNQME4wHQYDVR0OBBYEFLpo8Vz1m19xvPmzx+2wf2PaSTIpMB8GA1UdIwQYMBaAFLpo8Vz1m19xvPmzx+2wf2PaSTIpMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBALhwpLS6C+97nWrEICI5yetQjexCJGltMESg1llNYjsbIuJ/S4XbrVzhN4nfNGMSbj8rb/9FT6TSru5QLjJQQmj38pqsWtEhR2vBLclqGqEcJfvPMdn1qAJhJfhrs0KUpsX6xFTnSkNoyGxCP8Wh2C1L0NL5r+x58lkma5vL6ncwWYY+0C3bt1XbBRdeOZHUwuYTIcD+BCNixQiNor7KjO1TzpOb6V3m1SKHu8idDM5fUcKooGbV3WuE7AJrAG5fvt59V9MtMPc2FklVFminfTeYKboEaxZJxuPDbQs2IyJ/0lI8P0Mv4LIKj4+OipQ/fGbZuE7cOioPKKl02dE7eCA=
7 |
8 |
9 |
10 |
11 | This data has no meaning.
12 | http://idp.example.com/metadata.xml
13 |
14 |
15 | yn+85TrLn8fAxUeVzVHteQpDmmQ=kSpgT3WImsWeiKAVZn0lRkuZNFgl97Up4u1Eei9b0VZGKknGMBlgpeFB0yWT1WX0QUsSAbBbNKgyEC28PjZ08qbQzv/dAUx6lZp6CdfD97BXxhtylNfs7dL/MLatj4aXQkwAduZUDmb8q6LR/2Liz/cC/QyNZygib2PLi6NWdaYR7Kdxf/P44JHJRs1kFTZ5JXCbj8itv6i+pY2OfOqS0W2galaK7sBrFb0tKWqZkvXD8wTQsb6cdR201ofyNplM/m5TAkl1ORGnjSi23UN6RFmAnWXvre2XaclBKD8IvdiTebbK4J8DQ/fyj5vTkfNXh0JTNS0qArBwSBmVo246yQ==
16 | MIIDGTCCAgGgAwIBAgIJAO8HJfrb3JZeMA0GCSqGSIb3DQEBBQUAMCMxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0xNDAzMTgwMTE3MTdaFw0yNDAzMTcwMTE3MTdaMCMxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMFf1kCef6FTPMxQSoThAZGFNmixh8fRDLsUo58pEFwztBRUPWS6s6Ql8mA75aAEdo4+JVyE8QPi5F+fWbnToWkIw7E7YGl6s+EScSMQYHKCLq4mPHPMHtZspFowNp+Vax88SSUo1TKlpVNVIGim8JQ5SRi3p0aD6UAiu9WxQ5s+xHnDwgvQiu3Sa4COl5NQjkC1r2LrhJnJQQiw0hsn1nGgg15jEaDCZa8uPw1EtHv8smoZpjTbwRBVjXtzLskYIRyYLQjvqR+/QAd0XZcav0LdTwQR6obg/CwSgv7qG/WN6t25VIIGQDIUkVMBhLDmCh8QRpTvx1YWumSWW4D2k2kCAwEAAaNQME4wHQYDVR0OBBYEFLpo8Vz1m19xvPmzx+2wf2PaSTIpMB8GA1UdIwQYMBaAFLpo8Vz1m19xvPmzx+2wf2PaSTIpMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBALhwpLS6C+97nWrEICI5yetQjexCJGltMESg1llNYjsbIuJ/S4XbrVzhN4nfNGMSbj8rb/9FT6TSru5QLjJQQmj38pqsWtEhR2vBLclqGqEcJfvPMdn1qAJhJfhrs0KUpsX6xFTnSkNoyGxCP8Wh2C1L0NL5r+x58lkma5vL6ncwWYY+0C3bt1XbBRdeOZHUwuYTIcD+BCNixQiNor7KjO1TzpOb6V3m1SKHu8idDM5fUcKooGbV3WuE7AJrAG5fvt59V9MtMPc2FklVFminfTeYKboEaxZJxuPDbQs2IyJ/0lI8P0Mv4LIKj4+OipQ/fGbZuE7cOioPKKl02dE7eCA=
17 |
18 | tstudent
19 |
20 |
21 |
22 |
23 |
24 | https://sp.example.com/metadata.xml
25 |
26 |
27 |
28 |
29 | Test
30 |
31 |
32 |
33 |
34 | urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/test/data/post_response.xml:
--------------------------------------------------------------------------------
1 | PD94bWwgdmVyc2lvbj0iMS4wIj8+CjxzYW1scDpSZXNwb25zZSB4bWxuczpzYW1scD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnByb3RvY29sIiBJRD0iXzIiIFZlcnNpb249IjIuMCIgSW5SZXNwb25zZVRvPSJfMSIgRGVzdGluYXRpb249Imh0dHBzOi8vc3AuZXhhbXBsZS5jb20vYXNzZXJ0Ij4KICA8c2FtbHA6U3RhdHVzPgogICAgPHNhbWxwOlN0YXR1c0NvZGUgVmFsdWU9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpzdGF0dXM6U3VjY2VzcyIvPgogIDwvc2FtbHA6U3RhdHVzPgogIDxFbmNyeXB0ZWRBc3NlcnRpb24geG1sbnM9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iPgogICAgPEVuY3J5cHRlZERhdGEgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1sZW5jIyIgVHlwZT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxlbmMjQ29udGVudCI+CiAgICAgIDxFbmNyeXB0aW9uTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxlbmMjYWVzMjU2LWNiYyIvPgogICAgICA8S2V5SW5mbyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnIyI+CiAgICAgICAgPGU6RW5jcnlwdGVkS2V5IHhtbG5zOmU9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1sZW5jIyI+CiAgICAgICAgICA8ZTpFbmNyeXB0aW9uTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxlbmMjcnNhLW9hZXAtbWdmMXAiPgogICAgICAgICAgICA8RGlnZXN0TWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnI3NoYTEiLz4KICAgICAgICAgIDwvZTpFbmNyeXB0aW9uTWV0aG9kPgogICAgICAgICAgPEtleUluZm8+CiAgICAgICAgICAgIDxkczpYNTA5RGF0YSB4bWxuczpkcz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnIyI+CiAgICAgICAgICAgICAgPGRzOlg1MDlJc3N1ZXJTZXJpYWw+CiAgICAgICAgICAgICAgICA8ZHM6WDUwOUlzc3Vlck5hbWU+Tz1JbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQ8L2RzOlg1MDlJc3N1ZXJOYW1lPgogICAgICAgICAgICAgICAgPGRzOlg1MDlTZXJpYWxOdW1iZXI+MTcyMjM3NzcwNTkyNjI0Njk3MjY8L2RzOlg1MDlTZXJpYWxOdW1iZXI+CiAgICAgICAgICAgICAgPC9kczpYNTA5SXNzdWVyU2VyaWFsPgogICAgICAgICAgICA8L2RzOlg1MDlEYXRhPgogICAgICAgICAgPC9LZXlJbmZvPgogICAgICAgICAgPGU6Q2lwaGVyRGF0YT4KICAgICAgICAgICAgPGU6Q2lwaGVyVmFsdWU+bGFqK1VIdG50RTJSL2hTc3QydXUreWFwc0toV2xvdXpiNUpoSkhJZmpsSjVnNElEbldsK1h3MFRaa2lNMDd3Qk9rQzUrNUZvaXZrTDNUeEhUaWxSQkRNSGdVQ0FFT2xSNnN6b1ZKTzdDOUt4WEh1WFdoSzVBTWhJVmFBSFNTNDRPbEMzZVpTUlFFdFBieFJlNjJNUEFmdWl1Mzk2RWtXVzZpQ0g2azdJaUVZTG5Fd1B5ZGFQOHVBd05mQVpxaGZxbEdidFJPTFFFWVpZSlk2VXlZMURCV3NZbHZ1NEkrTVpITlUvRGd6SHpjdVFEYVhXcUxLSVBQUGhuQWZ1eTM5b3JsV3Y4SmMvQ1RxMmFMRjZ1Tng2WFZrZFFPTi9HcGlzWDVpbnRlaWIyYWtnTUh5dzMxaW1zb3ZVK0RnRjVSZ24xaWFQbU9leXNTaGlxeWo2UTVEamhnPT08L2U6Q2lwaGVyVmFsdWU+CiAgICAgICAgICA8L2U6Q2lwaGVyRGF0YT4KICAgICAgICA8L2U6RW5jcnlwdGVkS2V5PgogICAgICA8L0tleUluZm8+CiAgICAgIDxDaXBoZXJEYXRhPgogICAgICAgIDxDaXBoZXJWYWx1ZT41dnRnbU9uSE1VNy9YUTREb0ZSR2VpUThYRFpQay9KRFNVbFFJQXpoMHB6aWFPY0FrTTkzNDduaHFwK1FSeVk5bHh3ajVtbWN4UXdVMmdHcVVuQ3JaRkJocysraFdOeUIvaTcya1FvOHlGQk53NjNFQ3VzRjRvN3B6MjFQUmFPT3RGYjREZ29PZ21BVFVmVzNjUmY1OHVjcHgyZWNUaENwcStVVEUzaFhTcWJQbVBKSm5PNkVCL3N1N1hHc3NrWjY3V3orMldVRUFJM0d1OVpiY09vby81NzZ1VExRbzRiVkc4S01TNHJLeDNQQU9ibUZiNklhMmhhWngrUmYvTWJiaUhkbktXZTZJZzladEhSTWVBbm5ObStEOENXVUFMYzltVWFDcUhOWmpGVWpRMG5GMUJveHgySjZNMGNrREFXWWxFRnMvb3I4cTQ3ai9leFA5M2RMS0lvTVFzZk5sVW5OSlBoZ09QVkpZc2tWTWhuZG5KOVVOdzFIKzR5RjN2QjZjVWdBcGRHZllDdXBrUXVRUkJhVkF1SDJlWWF4WGZJaTYralFObEFNdHhBZGlqL2RHbkVyeXhyaTl3R09wQk4xRFo5WGpXL3RLQVJZbVFaamc5V1dNNHc3STQrMjY3SG1LTm1weHhtWFJjZEo5T3gxYTNPSDFKV2o5Z0dETUVXRjVDZWxBNlRMNXRDM3l6VFRJKzkyN3JUc0c2UmVCUU1mbXZudEtnNys3ZmNCN1pxYktIYVQ5U2VLZHJLSWhGbmJQaE1ySi9uMmZWdEJhbnNnTDlkTnpZdWtERjk5WkxsamJUS0pFR2htQ09vcGRNdFJDSDhJTWNzQlc2RnFqSXpoWTVjS3NWbTBkQTNobGl1cXFTbEJvYnFSZHhQTGh0WTVmUXdNaXNnakl5N0tzS295MXlxWkRLa285OHZYb2YxdWN5UHZnRGU2NHJhVHBPUkVUTDNSaVZadUR6aDBOdW1HV0VmbGNrZTdUQ1VQVWJmWmtKMnVkMFJDdHdBOVI0UWQ1MVY5ZjNha3BpK2pHQTZuOEJDTkRGenluNmt6VWdYUG14NCtQSXRkRTIzaVIvRFdVQmthRmwyTmpqZExJZzJCMTZ5RERGOFltWFh4MVg0NGtBMW1QejhzVTk3U2ZRL0dLanhnQmdWdGp5TDJBMUhSWCtSekd4b0FvTGhDMURHcGxwRjcrUFFQUHlJNTVDTkRzMDlyUDdieUFOeW1sUnRBUjYwUXdVM3R5eGFvRnA1b0RKdEVoeGw5TGdYT3V0dldxcTNsb01YR3FZaE5USG1SLzlaaTVyOHRwcVNoS3NnTTczMDNMV2tpbnEwSDhUQ0lDQmZHTXp2aW5GaWhoNHRkbTF1b2d6dzhISitJenJ1YzdLTEE5eHFZZ0lLYThUUUJFeE1TWTVzczVZSENJRDk1NFFxdFowUnFtQUR6aFV2Rll1ZzhhZ0pUOVA5SW9IZTRYTXpaMjcxRHd1RzFqRy9QM0pJM1VMMDlvSzF3Wllzb2ptQnk4QS95NVl1NlYwWlN5UWY3Y0ZRRDdLY1o5bDY3VU83UWh2WWdRWDhJVXZkV2o4STM4WTArMVVHYkhodXk3SE4reUJDQ3MvcGpUTmtvK1prMURUZ2h5ZkhXVDJNWHhEUHVzTER2MmYxa0tpY1I2SW9melE4WVpad2lkcjMvdFJRRndjQlAvbXV5bHMyNXJWMkVTOWhVbHd0dC9EQ2ptU3hmY2E5ZE96aGpuMmhNVFRadkhmTml6ZVQ5N0pxdUNMdERwZWxONzFlci9idHFHWThYV3ZCMlBBTXFvK2dDcXFxQUpxbjVDMys4bXppSS82NlF1UlVFYkE4RG5kSy95YXp6R3ErcEluaDBId21GYWszb1ROcjk5WmlTTDlIQ3B2cFpueHJOdGV6UmdIeVcwVmp6R3FYL2Y0V2wzRitmQjVrK2s3M2RaeDZoR2Q2VVZUNmZYZy9IUmRQaHRGWUZNaVdRNnlTUkNUY1ZCekJFT1hJNTF4dEdndUtSQ2RqVTNHY0Y5WlpaSDVBMFluYmdUMXVjbkprL0dZd0lYR3loOFZxT052Tmo4NVRVUW1qTk9iZTBicUFMQ0xDMkh3S215Wk9mVUl4R3FMTzRDOEFWOXlBdytxUm9nRGM2U1h6ZHN0QU9YUGsxR1JHbXhtNmd6QWJyeWlXRUtQTlc2dStEQlhqV2VHUldmK0tnbHZKL3hmTHFSR2FNRGxESGh6bTQyTTVzRkdOQ1Jqb2VieHk4djlpenMrSTVLb0JJcGhwWkh5UStyL0hHRTJWRWhOMEJONUV6K2NJWEF6SG95d1JSaEZETkJsR1djN2psRGYvYjROd0FQQlNFQWZzMkdaMG9FblNVa245enQ3V1BSTjRsMTVERmx0K1Z0TWFoYWM4OXMwSlFRVWhjMHBRM1kvaXVpTC9HemNnV2lvbmp1UDl6KzhGMVRVYVJWOUpGTktKaVNHcXRESXlMMWJ3bkF5dktmR04xamxqWXhucmZ6K2pDSEN3ZWQ5Z0hFckxVSHdDdlNoOHhwTmp6Ris0TkhEUmMvL1c0djJqZ0trWkl6RkdCWkJ2NGo0dkFLVnhOQUhMSFduRTBEd1liTXhTTWp5NjkwR3IrTFMyVkN1MzNoWjlGQ0l1cGljNjRXRHlWRCtlcTNXNlVFNDE1Nno5cnRwcHZoSjNObldRanNDWU12dkFseUN5dFVIVzkraGE3OElPYXJPM3M2c1Z2QU9IMVVTLzlueUoyUnFoaWxWc0tDZkwvbDFieWJGY1NqZENONXBnYnh1U0o2TFNpTFFYRGhSUzRkOUt1VlJPT0RZZklVaTVQcnNFWkVHdlJaS3dRL0g4OTg4WHBPbmVQVFk5WElRY0Q4RFlRMU5UYlhmVEZ1bWRRSkVsemIxbnZpSjE3WVUxcXhBKzJaLzBKVzF4OUhiUDhsajlZTEZSRnc3VDRGaXlObHY4UXF0ZkhUcHUvTEVDMEVaV205eEJ2UDdYUzBVTm1nL01RbjBrUzJaMWJvNkZYVmpyeTlOYWVFTWtGSGVSWXVMeTh6eVBsN1ZBNmU1cExTUjFUbkk5V3I4ODB4RWV6QSt6bjFWS1VjOVh1T3VYVEp6Zjd1NmhrM2QxVXR0ejgyYk1xQzdFeVJRSW8yNGkzb0RpaTY0Uk0yaXhha3loYm9xMDZwNnBsQkRFdXpoZ1FMcFQ0UGZOa0lhSEpJMHl2NVZHcFJ3T2U4MU0rMHNabXVibEczQzEwbmxVWWhtTXN4ZDdxa1hTdnBsRHUxbDBaSDZsczUwQUs1ZG5wRkVoUUFzY0F6UVBLMGNydlZUL3NqZ0dicGMycGpCaHpyTGhFWkxBY2h0YlB3T2ZOWjc3YWZ5R2drM0NjUjBVTGl2Qmp6VHZnanJ5cElhN0tNZUtrTWZZNGtIMUVzNk8vckJJQUVjRFJNVFUrL2QwL3MrZHN2SGZ3THpzcHFQYm1hTkNxRGttOWJMUXB0V1NuanVydVpxM3hGVnJSWURMaFhpa21EMER0OWZ2VGU3TUt4TXdyRzdoMnU5ZkZ2MFZ1VnM5N0lBbnQvM2RURWMycGp4cm84OXA1cDBGZ0xFRjkwOXdGREgwTHpValovLzBJcURBSWsyN0ltNDNHQjBNN25NSHB0aXhjalFNek1ERGNueTJvdnB3eCthV2JCbm5EZU9HUG5FV0xGaHdRQng1TVI2Q05uT2tRMXdQcW1HVHpMZEQ1aHhIRVpEYnY2eEYzWXdDNlc2UjRmS0tWY082aTFBZFZpcUQwRlF3UnlrSm9NNkE5VFgyVDBJTkpZS2tQdGFXbU1hcis5TlhLdWxEbWtaOThaYWVZMjBRTnhBMjhLbGovRSswdkZkNjZTUmh0WjFhbmZZdzRwbFZUNUNDSlp1VUg1MlNYTVFsSDZHR2lENWgvSGc4UmpmTFhqUlgxeGxkYm9YaUlEY21BTDFheGFwckdVSFVjN3lreG1IVVVoL05RK1RCRW1vQ2xMVnprUVBKTFQxN0R6cTZyYTRlb1VMWEpTYzNzT0VDWEpSaXh0eHY4bXNUODlMQmxldUZtNno2NUNoT3JMQVhMTi9IVUNHbUwvWVA4SVRxZ3pVYmVzMEFFVlQza2ZBd1VTZkZRSE1aVE5MOEdnVXY0ZXhVZTVEcEpYVkQ2Y05OU1BLTG80T0Q4Y2ljaGw1by9naFhVMmhnRHM3QjZWOGdYK2Q5RzF4bnp2TjMrM1BYSEdHMm15L3d6WVJ6VUJna2VaU3pLRE5WYzhuT1FaNU14N04zNEJGYkdqSm5YUEhPZk9jVjZ1V2hsN2doS2JFWWNSYW1BcEpFNTRWeEU1eThqT2NGZ21CdU9VcGM0VzgyazVhV0Q3QVdibmt2VnBEeFZVZEEwaitpQWxsYUNXWTRZWEFPMzRkSUVYdGhSYlRUNmNuTTlaRVVPZ1JsRlJkdmNySXFhVVZIVWl0MzNhUWN1MjMvRVpZMHFNRDFtK0ZZckxIT1U1UVh3VjFtVzR2aXdBNFNrRTMvRnFUM3UyR29ibEJqVVAyaGx3NTAra3NCSXVjZWJFdG1EZE54MWN1azVIVkFzMWQyOEoyVmZhWkFmWEFPV3F0Y3N2cm9wYTRNWDBpSmVVWE9lTkV4cFhhdGZCcEtPOXEyNHdhQTZwRnVRS3ROM01JdDVtMTFSc0JnNjVwelhNRldXV2JwV3ZGenYyUFlRdXlBYmZFK2R5MWRoQlBJdzhSVzVYMG1Sbjl3K3Y1M3VncGYrV3ZCTytYOXlReUFnekh0WjlRQzRRRWVxTE54T1MwdFRBVkhzWUo4Q3VnRTVGem92NVlIZXM4Ui9rTVVoSEJiWEJ5U1JuaFVxdG1wclJMT0I4THE0amx4UStpRzNoeitZOTQxY21CejdxaUpCYXAwdmk1a3NHaDRpKzFpaFUwRTRQRWUxS1VnNGJ3Q0RVVkgvYnlsWVVJb2RJWGlXN05qb1MxaVFFd3QrNHduVzArL081aExEYU00blBYNEovVFJxT2haWkRmM3B5UjAxMHEzZU5KbThLMGgxVEdaemZJZTZRZnZqTnl2dUVmZUR6U0RuZHZiMXEvNWlhK1RWdEl0ZkEveVJEc1VQUTE2V045eWRQUEFoSm5uTERvazNLa2VidzVPUXJ6S0pTTVhHR01aQWQ0RzhVV2JCVVE2S3YyU0NLOTFXSmVkQmxBNHdHOUN4bm5NcjhraDNIditwQXVSa3VaTWNDNC9Lc2o3U2NlTFAxOEY5Q0U4ZXBnTGxhTGhEOEkrZjdsWHNjZTc3OTQrUDZCcEpUQy9EQzhvdE1XaTlkZ050bE9uZHhIRU1xUk1DRWpMbDAxNlhFK2NQMFo4Z3Zma00rWTFrR3dyclZOZGVNYi9TOUJzK2JsQ3ZUMW16NkhzRmJ3PT08L0NpcGhlclZhbHVlPgogICAgICA8L0NpcGhlckRhdGE+CiAgICA8L0VuY3J5cHRlZERhdGE+CiAgPC9FbmNyeXB0ZWRBc3NlcnRpb24+Cjwvc2FtbHA6UmVzcG9uc2U+Cg==
--------------------------------------------------------------------------------
/test/data/response_notbefore_future_encrypted_then_signed_base64.xml:
--------------------------------------------------------------------------------
1 | PD94bWwgdmVyc2lvbj0iMS4wIj8+DQo8c2FtbHA6UmVzcG9uc2UgeG1sbnM6c2FtbHA9InVybjpv
2 | YXNpczpuYW1lczp0YzpTQU1MOjIuMDpwcm90b2NvbCIgeG1sbnM6c2FtbD0idXJuOm9hc2lzOm5h
3 | bWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiIgSUQ9InBmeDk1ZmI2MjQ1LTI3YWUtNjA5ZC0xYzlk
4 | LWQxN2NmY2EwNTU2NyIgVmVyc2lvbj0iMi4wIiBJblJlc3BvbnNlVG89Il8xIiBEZXN0aW5hdGlv
5 | bj0iaHR0cHM6Ly9zcC5leGFtcGxlLmNvbS9hc3NlcnQiPjxkczpTaWduYXR1cmUgeG1sbnM6ZHM9
6 | Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyMiPg0KICA8ZHM6U2lnbmVkSW5mbz48
7 | ZHM6Q2Fub25pY2FsaXphdGlvbk1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIw
8 | MDEvMTAveG1sLWV4Yy1jMTRuIyIvPg0KICAgIDxkczpTaWduYXR1cmVNZXRob2QgQWxnb3JpdGht
9 | PSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjcnNhLXNoYTEiLz4NCiAgPGRzOlJl
10 | ZmVyZW5jZSBVUkk9IiNwZng5NWZiNjI0NS0yN2FlLTYwOWQtMWM5ZC1kMTdjZmNhMDU1NjciPjxk
11 | czpUcmFuc2Zvcm1zPjxkczpUcmFuc2Zvcm0gQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8y
12 | MDAwLzA5L3htbGRzaWcjZW52ZWxvcGVkLXNpZ25hdHVyZSIvPjxkczpUcmFuc2Zvcm0gQWxnb3Jp
13 | dGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzEwL3htbC1leGMtYzE0biMiLz48L2RzOlRyYW5z
14 | Zm9ybXM+PGRzOkRpZ2VzdE1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAv
15 | MDkveG1sZHNpZyNzaGExIi8+PGRzOkRpZ2VzdFZhbHVlPlZOcFNoTHZCeUo5MVE5dlJIUkNIQ3BN
16 | cmo4ST08L2RzOkRpZ2VzdFZhbHVlPjwvZHM6UmVmZXJlbmNlPjwvZHM6U2lnbmVkSW5mbz48ZHM6
17 | U2lnbmF0dXJlVmFsdWU+dHV3SGg0a2NKSkFaSXpSd1lTOXJ6TmtDSUY0SEdVOVloTEo5TndmdDQ4
18 | YXhDSnJVajBoa2lJZFpmMyt2aW42WVVGajRKU3RQSzBZQkVJUXNCNXB4cjkxSlpXbllMa290Z0Qv
19 | VCtyS2hWa3p4T01uM0djSzI0ODU2Y1NGbVFMbUw1M0tScXpZU0pJRFk1eTBjNkUva3hEZTlyK1BN
20 | RzQvY2g4M21qR09TUGdITUZEWWViSUdFcHcrN1k3OXFjR1RmWVVybng3b0lPT1VzcFpOdWFTdjJ5
21 | cjNncUFtRzhaTTA2L0Y4Rnp1bmJXMlMwblA4eW12MDl5ZmhvWmY3WHRKQUxEQzZmbXcvTTBjemJX
22 | V01WdStPQzlwY1JtQ29kNXRvNWt1ZDRCSW9HSUxDcHNMYjlqeTh1S1BQcFB1dUZoMFU4c01pajQ1
23 | QTNJSEFKd2kyYnRVSjZRPT08L2RzOlNpZ25hdHVyZVZhbHVlPg0KPGRzOktleUluZm8+PGRzOlg1
24 | MDlEYXRhPjxkczpYNTA5Q2VydGlmaWNhdGU+TUlJREdUQ0NBZ0dnQXdJQkFnSUpBSlFkL1JTSTUx
25 | dEtNQTBHQ1NxR1NJYjNEUUVCQlFVQU1DTXhJVEFmQmdOVkJBb01HRWx1ZEdWeWJtVjBJRmRwWkdk
26 | cGRITWdVSFI1SUV4MFpEQWVGdzB4TkRBek1UZ3lNRE14TUROYUZ3MHlOREF6TVRjeU1ETXhNRE5h
27 | TUNNeElUQWZCZ05WQkFvTUdFbHVkR1Z5Ym1WMElGZHBaR2RwZEhNZ1VIUjVJRXgwWkRDQ0FTSXdE
28 | UVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTHhlcmtVUk00Njc4bnVmdDdMUUk3
29 | ZzVqeVNVSHdIUk9DaGVBVnQra2VtVmVnN0pORnpQYUYxQU9tMm40UzR4cTRhSTAzL0hXNzI1c3ha
30 | VEpJaXQ2VEJTaWJvQzZ5dU4vY00vbXp3amhiVitnQ1FSejJEckk3TWtHR3VqbjViSCt2dTNxenhw
31 | WFNvU3Fya3VIV3JkZU5HSExCUDBDLzBwSFUyUlpKT0dHMWgrUyt0aVcrRUdLejFQSXRmTDdtZzhW
32 | MkVoaWVVQllMZ3hHeFZzTll3dEw3ZFdjaWI3WTQ0NzZZeDI1ZDM0azFJZ0Jydmt5bzN5eDFHaXp3
33 | RzAwKzBGUjMveWtNWU9leHdpWnpDcktiWm96MUJmMGl0dTl2cWpiekR5OWdia0VRQkljWnhwRTVH
34 | T3dBdHlMTktnQmRTeUZqM3piUlRVSXlPdE5kVHY1Q04zNFdNQ0F3RUFBYU5RTUU0d0hRWURWUjBP
35 | QkJZRUZGSVE3cjBzb3BuL2g3OXBYMXFpUWFXemNNR29NQjhHQTFVZEl3UVlNQmFBRkZJUTdyMHNv
36 | cG4vaDc5cFgxcWlRYVd6Y01Hb01Bd0dBMVVkRXdRRk1BTUJBZjh3RFFZSktvWklodmNOQVFFRkJR
37 | QURnZ0VCQUhjTWZFQXN3bVNWUnNSb2ZhaWJMZVA3MkhtOHp1dGIyNW50cG0zZ2NhaytEaWtFNFp3
38 | SS9IR1l3MllwekdaOXY4eXN4Yy9lZ2M3bExLbit5T2xPYlJkSUZKbVh1NU1TZjBHNkQ1L05SdjhS
39 | YWdDYTN4NktnamdaT1R4NU1OUjhLWDJ5NzliT3VwTU1qL1BuSTRqQTJqWGJGRlNVd3o2TVFGUC80
40 | VnlobHBZcWRobjNRcHV1OFlWclc3S0hjWW02UlFIbHJDNzBXQ2NmWkVXTEVIalUvdVJ3RksxK2hN
41 | c1VMYmJ1M084L3ptSnNVNk80YjJaYmpDb1B2c0FaWVBLMC9PSllieVV4ZnBmSFo4MkttRjI2MUhF
42 | S0ljaEVXUGtwaVppdnRyUGZJT1pGeTZpVjRidDBQVC9TR29JYktPeGgwTnh4eXQybUhucGQwMzB0
43 | VVhOWUxUYz08L2RzOlg1MDlDZXJ0aWZpY2F0ZT48L2RzOlg1MDlEYXRhPjwvZHM6S2V5SW5mbz48
44 | L2RzOlNpZ25hdHVyZT4NCiAgICA8c2FtbHA6U3RhdHVzPg0KICAgICAgICA8c2FtbHA6U3RhdHVz
45 | Q29kZSBWYWx1ZT0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnN0YXR1czpTdWNjZXNzIi8+
46 | DQogICAgPC9zYW1scDpTdGF0dXM+DQogICAgDQo8c2FtbDpFbmNyeXB0ZWRBc3NlcnRpb24+PHhl
47 | bmM6RW5jcnlwdGVkRGF0YSB4bWxuczp4ZW5jPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3ht
48 | bGVuYyMiIHhtbG5zOmRzaWc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyMiIFR5
49 | cGU9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1sZW5jI0VsZW1lbnQiPjx4ZW5jOkVuY3J5
50 | cHRpb25NZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGVuYyNh
51 | ZXMxMjgtY2JjIi8+PGRzaWc6S2V5SW5mbyB4bWxuczpkc2lnPSJodHRwOi8vd3d3LnczLm9yZy8y
52 | MDAwLzA5L3htbGRzaWcjIj48eGVuYzpFbmNyeXB0ZWRLZXk+PHhlbmM6RW5jcnlwdGlvbk1ldGhv
53 | ZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1sZW5jI3JzYS1vYWVwLW1n
54 | ZjFwIi8+PHhlbmM6Q2lwaGVyRGF0YT48eGVuYzpDaXBoZXJWYWx1ZT5XblVOTFJxdEhHa1hPbjF0
55 | SnNhVmgzQXl6dkw5K0ZySlljaHhOQW5GQ3BlVmxuZ0gvaDNwUjhZS3RuQVhLZmR1Ui9rVW11UTRV
56 | OGVteHA3Nzl3Y2MzamNjRGoyRXF2U1JYbDQzNTJIa0FVd09mNnlnN0VESC8xSnhTK2xyUXVEQndP
57 | MkwrZm1aNXJHM3Y3S3h5anNvRmpjK0M4WjRjSmhOS1g3K2hTMlFsQXB0Q3pDZjVIcGlpOExvSlU5
58 | OW11K2RyR3JGWWdQOUlleEM2clhkSklDYzNjcFpYdnd2SjQyWHF4eWpTb081NzlhWUxXS2RXY3ZV
59 | UVZIV2hMSG05eE0xZDlUQ0hhUStENDR5TDNsS1BlYkFTTGRscFVmd0tldVBLNjJGZDdOdjg1WnNp
60 | VjJvVnhHc1JlZmJPc0ZOYTBHbkxTSkhKU2JsRmJmQ0J5S2hySFdwU0E9PTwveGVuYzpDaXBoZXJW
61 | YWx1ZT48L3hlbmM6Q2lwaGVyRGF0YT48L3hlbmM6RW5jcnlwdGVkS2V5PjwvZHNpZzpLZXlJbmZv
62 | Pg0KICAgPHhlbmM6Q2lwaGVyRGF0YT4NCiAgICAgIDx4ZW5jOkNpcGhlclZhbHVlPm5VQWI5N0lt
63 | K28wTzdKUXd1dUdXTXR6T0dITGZxcVc1ZVRlY3o2WHdFZXYwbUNwbGx5UVM4R2JxSFhwNUVqVXF4
64 | NXM2Y2tyeVF3SitrL09PblEwRVZ1QjErREdVek5jYzgyRlkxdDRPTUYyYkZ1bVFQbytvRm1FMjFq
65 | RzJyWm84WUhXcjMzSFQzYm81WGVMT0NScExURkcvWWdpTkg0WTdHWW5UeEsvV2VLZTdSZmNPdkE2
66 | YllwUXlnNEJtYXU2WnhwWWlONm5nTGxRajJreGxSR0hucjFmNHhVRm4xdEVYb2E4Rk0zQU53YkpV
67 | ditXclhLeGY5Z2QzVkhvVy9lb1Q1ayt6cS8vVXozeFovUE1YQ2t5aHhqdHJrMWFsZFUweXBCMW5V
68 | dFBqNDdJQzRCSHdpdXRKZ3hMTGk0a29rUW9CdHVNTzcxckNHN20xVVBSNmMvYnV5aWhjL2dEblE1
69 | VnYrc09zZ3RQNTZ3aHk3aHlZdWN4UEQ1MTBJUjZXMkluZDBaeXlzcHA0ZDNSbWVwc0lGTURzZnEx
70 | OFc2TFphVENRUndMcjU2TkZSYm4wWnpqRGMvRjRBYVNaZXhXQkxIOVRvQnF3Q1Z6QzZqK2Y3RjFo
71 | RDBxUDFPY2dXb3BERXh5U1ZZQjVLSkJSMFAzSERQVnZYOVZjVTdpS1ZJUE1JUVhIVUZ5TEI5WVo2
72 | QUwreC9QL0dpNVBvdzBIem5lNE0xc0M5N3lnNUR1OFpUL3FzOHEwaFZyZ3k4MHlUdGN1cCtWSGVP
73 | ejN5cVVpVjA2SVZUdXkrQ0c2Vm00emptd0Ywdm9wbmpxSnBJV0YzLzd2WXNRZmJTSW5XdDlHTXRm
74 | L0E4MjVuL0YvLzFacEYxVC9KcUxUcEdzSHM0UWJkRHQyaEd6bnU4clp6ZzI2Tk9XS0dMMFZ2bXRC
75 | Z3JlVk91Z3JWK1dxQzZ1bGQvSllhRWYxU0pzTTk2RnF3cjBObUl3VkRYSTNPc2V3N0JEZEw1U0VF
76 | dFBUYXhxV21ZcmxqZkZmdE1zS2xhQXp1N0haY1NVdmYvMDE0aG1CYmkwWmNzdXJlc0FQWDJRTnFC
77 | QmgyUWJveU0vdFUrcWUrdjF1bDEwNytkSzRUZ2VOaEFrbDBxZ1NSbDJlTU5CQ1lFT0RGdHdEZklR
78 | N095S09aRTMybFc4ZnhpTFd5ZXg3cXM5Q3dqQjg0R3grRjI1ZUpZT1NMSS9MbzFKOHhPTHFTdVJ1
79 | SGI0TTY0em1GcmpQRDR3Y3FGdm00OHdlM1pVT1VFSERDMlg2ODI1aDlkb0RrK0QxbWRSaDdweUhH
80 | dEJkejU0eE5OZWo2OWRtTzRCQXFkSGV4QTZDT04rM053TWFtNlpiaGZuUTZKbHBlSFJrUWc5Mnho
81 | dXdjcFpqOWxqZEk5dmxTOU9OV0tPSDRmMGN0dTRHN3hTY3BqQ2ZKQVpYbjNmY3hINlNVV2NoNVBt
82 | T2FhVWs3QkZkS3U3c2IrV3IzRVlrMXdheGlrbjYzR3Vya2tVYS9mK2NXQ0ViWVV6WXVpRzlKZFFR
83 | dStQR0plY2l6SnNtYS9pUU45eDVMRlBTZzNONC9ESmZ1bkVPczdrb1c4RkdNM1VnZ2d4dTdVcWN5
84 | UTVaYS83VVZsaDJobVBabHNPUzRZUjY4dlRxZmlWMEJXbHZjaGhOTkUxcS90WE1jMXhzYWxiVTkv
85 | OVFXMXBsWE8zMm9Bd2o1Z0htK3BEUklJbmpESjA5MUxRM3ZzcHhlQW1icDliQWIrMkQvQ0lyWlNt
86 | TFlYWTE2OGhhaVRRT2FER2V3bThJZ3JteVJ4RFh5MFgxTlNBYS9VOUs3eHI2VjVYaGlVQVZ1clRj
87 | d2NaZ01TTktvRjJZcDJaOWoxOHdIaVNPZ3dUZ2tuVDdGeCtwTzFXUTFQT1RSZDdiRmt0ZTB0dmtQ
88 | UGgrbUpONHJjdjdmaU95Y2hFZ3JHWDVKOGFaeWVJOS9hemdEQlc3RXRNSEVjSGpJMkxUdGxHV2hv
89 | MFY4QW81RXdPc3d5ZEVOYk1BRTVQaFhYTXNvZFF3WnZtS2RLelNQM1pEdVRIUlFlR3E3cHNjUHNt
90 | MVhEbWVsWThRRHgvOEVBaTcwMDcvZXlwNGdQSmVQU1ZRd2xyRmphc0ttK0tXUHNTalhuQkxmdU81
91 | YzhWekgxYTA5OXZQcWE1WUMxUFFHT3dweGRDcVBuR0ZsbitqU2tOaGkzUHE2SjZ2Yk41Zm1wUEt1
92 | blpLN2NhOW91VzRpWEUwaFBoT2N5eG1mRXlVeEdzT0FrS0pQZWc3UlY0TFJ6QzZwdHBJQ3NDVzVP
93 | T3VuZ25YVUhJVlZ5UTdIV2w4QU0rR3JSNlYwYnYwRHI4d1NvSDJqY2pETHJWMUR4bWZLY3dZMVdi
94 | VTR2RFpQSmIxQWcvOXNlSTRHcE5iMjhXZmNyOUFDYXZVbCsyRFY0dlVxSnJEUEUxcEcxVFZtblB4
95 | c0JzSG1EYk04Ri9BSlF0Y0ZDTWI0UHA3V28ra1N1VjVVYmw5a0dFQzIrRk5FU1pSbHZVMU1TTThV
96 | QXhoZDh6dE5NcXIrVTExQzNiZXFqNloxaU9XQzdtVVNXSTIwck9nK04vQmNKVVJGeDJqOUFaZ0ti
97 | enZwR3BuK0lEUlFwdksvUms9PC94ZW5jOkNpcGhlclZhbHVlPg0KICAgPC94ZW5jOkNpcGhlckRh
98 | dGE+DQo8L3hlbmM6RW5jcnlwdGVkRGF0YT48L3NhbWw6RW5jcnlwdGVkQXNzZXJ0aW9uPjwvc2Ft
99 | bHA6UmVzcG9uc2U+
100 |
--------------------------------------------------------------------------------
/test/data/response_notbefore_future_signed_then_encrypted_base64.xml:
--------------------------------------------------------------------------------
1 | PHNhbWxwOlJlc3BvbnNlIHhtbG5zOnNhbWxwPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6
2 | cHJvdG9jb2wiIElEPSJfMiIgVmVyc2lvbj0iMi4wIiBJblJlc3BvbnNlVG89Il8xIiBEZXN0aW5h
3 | dGlvbj0iaHR0cHM6Ly9zcC5leGFtcGxlLmNvbS9hc3NlcnQiPg0KICAgIDxzYW1scDpTdGF0dXM+
4 | DQogICAgICAgIDxzYW1scDpTdGF0dXNDb2RlIFZhbHVlPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FN
5 | TDoyLjA6c3RhdHVzOlN1Y2Nlc3MiLz4NCiAgICA8L3NhbWxwOlN0YXR1cz4NCiAgICANCjxFbmNy
6 | eXB0ZWRBc3NlcnRpb24geG1sbnM9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRp
7 | b24iPjx4ZW5jOkVuY3J5cHRlZERhdGEgeG1sbnM6eGVuYz0iaHR0cDovL3d3dy53My5vcmcvMjAw
8 | MS8wNC94bWxlbmMjIiB4bWxuczpkc2lnPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRz
9 | aWcjIiBUeXBlPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGVuYyNFbGVtZW50Ij48eGVu
10 | YzpFbmNyeXB0aW9uTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94
11 | bWxlbmMjYWVzMTI4LWNiYyIvPjxkc2lnOktleUluZm8geG1sbnM6ZHNpZz0iaHR0cDovL3d3dy53
12 | My5vcmcvMjAwMC8wOS94bWxkc2lnIyI+PHhlbmM6RW5jcnlwdGVkS2V5Pjx4ZW5jOkVuY3J5cHRp
13 | b25NZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGVuYyNyc2Et
14 | b2FlcC1tZ2YxcCIvPjx4ZW5jOkNpcGhlckRhdGE+PHhlbmM6Q2lwaGVyVmFsdWU+TUgvSElYMmw5
15 | QVA0c1dJRmhCeTlKYm9ZWHd1eXlaRU9HSEtveW1helovdHZMRE5JZGxsbGs0TjZrbjU0cEdkdkNw
16 | cTJ2Z0EyamRCdkcydVJ6eVZrQU5aZGI2RWFMQ3RWaE5wRUl5cnkrbklhVzJ4d2hwL0lHU0FmbU9H
17 | eTh3MGc5Tjhqc1lxZ3VlK0wzQ3VjbUIzUkh2eUF4ODV5N09DV3Raa1Jkd3JMbi9YL1lBOGYxZGNa
18 | ajd3MkRPN21WWVhybkl4OEJVTDNDc3JQNU0vSUpWdjZ3UldPRTBzRG9iSDVFS1FBSmtUQWlhTDMw
19 | dHdHOVA3WTJiYjdtekQzN1F4cVJUY29tMjh0Ry9DQXAydlBxaitCdWdYeDd6Uk1RanhkZk5Cc1RV
20 | L2FvYnp5WDFEZWJIazJzb0ovK2tFTTF3UnBRNnpXeUFONVpRNHlta2wwcjdVS053PT08L3hlbmM6
21 | Q2lwaGVyVmFsdWU+PC94ZW5jOkNpcGhlckRhdGE+PC94ZW5jOkVuY3J5cHRlZEtleT48L2RzaWc6
22 | S2V5SW5mbz4NCiAgIDx4ZW5jOkNpcGhlckRhdGE+DQogICAgICA8eGVuYzpDaXBoZXJWYWx1ZT5n
23 | c3hwZUNPM0JpelpqMVpxZ25HR2lMVWN6cFR3SUM0bjlMQ09VMEFXdUxSdndRUmJmRHQyOVdJNnJE
24 | RGpHWVBXUU03SFRTWC9WTVVoRzQ4YnYrWjdEem9qbmpWOExZaXF0WVF3ci92ZWhpODg1ZnlvNlJZ
25 | cVhpb1cxbERDMHQ4YnNRaXpscEpmSzB0SkFEaUxiQnNubWRZbU9PeURSVHp2Wm9teEZFN3ZKYmFC
26 | NmdJVXhOa2I5MzdnUVo2VnBtVHhpSnJwRHQvZFJ0VmFLRmlBNWlWYmZyTDBnME1BeEZyYUVnalhr
27 | MFd1akdHc2t6bUNjcGM5bUtmS3VMS1h2bXR5M1pRTXU5Zk9zUUJEQW9odjBrQjVKOFpESVcyNTQ3
28 | akNDZVRqT256VE82RVJFNnlFcHhpV2V4Sy90VUFFT2NYY3U1aTV4cWM4ai9MclZxTUhxcVNuTlVW
29 | R2JZUFNvUGlhbXhhbjQzTzM2bkdmU3doRWd6ODBzdXNGRFFSOGV5Z0k1WkQ4VDZOQWM4LzZyd1pK
30 | eW9uMmFBczgydk5iemo2Ymo3ZVJ3K3hGS2dCNDFMRUxna0UvUFg5VDkxdDV1a1RzbVJyNXNnam13
31 | TWEzT0E1WVVYYy8rd0YyZVMrTlJiOU0yNmtYcU95aVpaQWhraXJudVhLQ0kvMTZ2aE9CbUJPRzRR
32 | ZVpaSC9OM2VIUmpMS1l5ZVRRclBSY2Q0SHplY2NjMGs4alRUQkZjMFJ6YTBTaERqYVZjQXE5WlIv
33 | Vmd6NExSc2FKMi9Gc0tuLzBFRCtrd3BRVmgzT0h5Zk5HMGpPUHNEUE8xeXFuenNBeStPZHFudWgv
34 | TzVBUXhZWHlGZGw1YXlyd2ZzTzNTY3BGWEhWWkRPMEZYSnpZOXQ3TndFNlRtdzRVVG1QbHIzNGE4
35 | T1ZOYU5NdGxXSHJFb2xOZG9YdStiNGZvQXljV1pxSGlnVXFJSDJpU1lRcW5nNHlqOVIvaHBEY01y
36 | STYyakZLWjk4c2pGaW8yVXNwVURXc1hXdkdSL0M1OW5qRy9EcU9wcUpKRHR6Q29ycXFtQktIOTRP
37 | WGxQUkJCK1FlUGlMaFNyU3M2UXhVNnA0cWIzTDkwRktsUjdhOG8waU1IbHBDYm5zZDZPekhoWGht
38 | UjhTZU1ET3BEWWhucStsUTJmcE5KVFFyOEtoUGgzYnBwekxIZTh5aWZQSDM0RTlVN1dvMFFTK0tk
39 | MWJaSzRPWUE5cWE0b0RhcVJYaXdGZnczWmRQS0RzbzZnTHQ1bkczVm1yS3dxUWxHNzZhc1dNbHhs
40 | QzFMbEc5QkFlWGM1ZnhmazU2OEl0VGJkSmp6ZmUyczZpY3NYaTkrcjA0OTlpMEt0L3ErTTFEMUZt
41 | dUtkRGl1cUNvSXQ2dDZLbEVldDNZT1Z0MW1lZUxuQnlHTmpVanFRQzVnQmRSM3pTU2ZYcmJoOFFx
42 | RitQQU4vUUp6OHlNSDF1UUlCUndZTnR6bTRXcjhISWN5d20rZm9aa1BoeGh6R0JaeG80cHp2K28w
43 | anZOeWZXbmltT01jYTM1OERtZmZPa0hvY0lKMWs5QlV2aUpIMmwvZEdwbFRzcVhTT1I3NW5nUUFa
44 | R1hFMVArNW9QVTRtR1cxbjBpK3RqNkc5S2ZqRm9Lei94cmpaa1BXM2NVVFFhU2g0Q05vR3YwK2p2
45 | WG54QmZzdmFzNTVzUWNFWEtqUDNGck9selV5UkR6SUVjNGRjbHZSOVZwRzVLKzNqZHRWU3lIcTJW
46 | eWcvMFRuZS9ydzhqUEhEdS85WTFVVzRYWFVSWjdQd0dTKzBlSmhoVzlpMXVZcFJrb0FWc1IwOFdB
47 | bXg4WFVQL1NGTWZqQVhuVWY0Uy9OSGJqcUVBQXNwblZPUHJ1ZUhtWnlVRTJRQTlEUGtCcEdJOHRr
48 | SlB1QWY1eTFUQ1dSMDF0U0E5Zzg1d3EzNTBRSWlMNzgvT1pOdjZkTVQvMDhQZ2x4ZjJFdEpUQUZT
49 | dEsrQVRuU0w1Y1p0MDRCSFpIMWpEWDJHZTBwaEhBUTEwTVZEYTNTU2o0QjR2TFdLSDR2Vm9QRTZX
50 | VHVpZVdGMmhaeEE2RGRMNTlrWFRMV0pYSHNBOUNTaUZ3dTNsRDZaK05IVVgxR0J3Z3lJL3ZNNUhz
51 | cVg4Mk1Xd2E3SW55WnZpS1llTk5rdXBZWkUrN2Vaa08waUQxeWFFQVlVeUtnN0NsVlpnWmo5b2Jv
52 | cWFVbDZBUnJmV1M0eXJraG5IUmdBazFSZ0tLODlPWW1YVUhBNmFQemJTaDVuOHZZUzYwaXdnTkN6
53 | bUlha3lUc2VnVzFZbVN4Rk53SzRlZG5XTVc2TlFkanZhRWRnYVZFUlZDRXg1bmxrbEVvaDJwTFFa
54 | T0hSYVVDblhrRzN5VWJ0R2QyM0F4WndIY1JnOFpxYVEvOVpLL0tpSTd1eWFoWHIrU0xiQ2E5SU92
55 | VEVucnN3SjFBSm9zTGRCbjIySktVME1hU0JyQThBL0RWd3lWa0JEOGNNWHlkcTNMblVib3NBODBH
56 | QkFGUGcycS9sVHNZWElCWUZKZktrYnlEb0I2clZ3Y3lSL05jL3dTbUpRUkZud3lCZEE3RFRhQVhN
57 | aGNXUzdwLzNZdVk1RmVZVjhEVTd4bWtlRmE4d3J3NXQ0OFFLbGxGQitsbTdSak15TmNYQXE0Ylgx
58 | bEcyUEo2Um04RzhrNmozTWNsV1FYcGVRSThuKzJ0d0dzV1FhcWNOUGJ0SXpWVGE4M2J3TmF3emVv
59 | ejFlL0txcXZGU2xackxMYXR6N2xYcUp0VFZqU1BuMXpZYis1ZVhyRmU4MFNlTzE4c3hGWHN4bmw4
60 | VS9PVlRvRDV1eHREOFJzSGpqRjVjTVYydkY0ckdGTkJjbno2Ukg2QTNkd0hCdlo2NFE1NFUwb2N6
61 | ZzZvSUdCbnMweE5NOUhVREE0SVFBYUdrU29HWTdzVEp5djB5Tjk3ZFMvSWVIZVV2ZXh2ODZlSFVl
62 | b2t3QXl1Yks4Z1JCQTl0a3F5Mi8veStCM1VlaXArZm9UWGlLaWt1dTFkN2p1bWpxYmE5MDBpRFUw
63 | MTRkVkphVU9LYkY0TE5XZG9PNkh4NTBoOEpoNjlVSS9LTnQ0TU9VWVFPNVZJaGM3OEJpUFRScjhE
64 | dXdNd1FTQ090RlYrcSt0VUxnK1UxRVpaVjdqU1F5NWJGN2lJbzJlN3BBMGRSaGM3aXVmV21NN3B2
65 | bzNIRU5ZNGFhZDVLdXM5VXNYWG80K2V2aVdiOXU5L2FtWFZwbWJyNTdmUmRmZGZXUHd4cmlFTGNX
66 | RVRiUWxUdTY5c3lPeTc0TTdmckt0TDg1bUJWRFRJenlna3lzWVIrWlNXMEVvTU1PUUVrOStkSkhX
67 | Vk1rRjhlVjNCSDBYbFkwczNFNFpCdlQySWdFWUNvd2YzS0FqUGJKcDE4N0JvWDN3Z2E4c2hpWnR4
68 | K0gvNkRZekxxeHV5c0JPVnl3eHVnOEx2Zk9wWEJiR0NoMWpOUWQvMnU5VVBxNjJVbnNJR2pqVndZ
69 | bVpSOW5IZHVWTTEvd3JUTkJOODVKems5ZzczdE1vK3RFRFNpUlhWZEdVR3crcVJmdjJHM3hQUFJJ
70 | NVRhb1BkRHlWWGFOSGwydWJlV2lGcDE3TDR2S3lOemp5VEowbDZ2dng5WE5MRy9oM1NUOHN2bGVx
71 | cXpvTzRwM0ZseUt4VGNQWkxINXc5cW5nbTlSdktsc1hjcU84ZVBxMWZobkxPNlVYNDBxcURKWThY
72 | NXNTVHNyK055QzdNQkF5K3lvWmlnQURrcDZ0RE5VTVJMMmp5UHI2aWpFRjcxUkVzald6V3N1Ylps
73 | Qkp1SGdaclR2dGZRT3dnUFNrYWlCQzdjaUdTUUlSeDhUaFpiNzRMOTVMbkFNakpMRkxqdVRxZnFs
74 | N2JSNGRTMyszWDI1WVRGb2E3Tk44T1FyUEJkUGNkemozNUpIR3Y4eGRZcXg3L1BCdTZ5aGhiaXdm
75 | Y1lpMFlqMm5sR3laUjFBenJTWVhDN1c0S1NlVTZjaDZXRmNzY280em1KL1A2TlMzQjBtRHJTNks2
76 | YzgrRTNuVU85VTZkSkJDZWdSb1VlclZCLzFXNFRIMjJMcWRycm1CUWoyaDRFb25CS0E0TFJjTXdo
77 | VEJMS0srM2lOdEJaQUR6K0dTYlVJOE9NRCtMV1dhU3p2RlU2Q0lPNUNZcVM4aDFzb2puM1lmQXYv
78 | YUR2RUZjRm1SQmpva1A4bXJzT0V4NGwrUTBrOURUTzRjdkMxQ3hHRlUxekZZUWNZMHZ6TkZKZTE1
79 | bjQ3RmZwbUFKNG5xRWpkK0xhOVBOM1c1UElOazlaL09reHJYeWZLTkZ5TUlEa2lWMkp5Qm85NU9S
80 | UGVYSEhFWEtkQWdsRGxscEllMmtpdTk5RnlSSlV6NmZNc2pEL3NYOVBxVGd1TDZ6L0dzN0taMDFz
81 | Q2ZudGtPZ2pQam9kb3YzWHFGTWZKRFFkVmYvVjQ2KzE5elhmdGlOUWcrNnU5WXF6MzN5c2QwSGVk
82 | UWpTekdBM1JWQi9EblRaenJjaEkzbStVQnZvTmNCR1ZtNFhlKzQvSkMzWWx1NDZOdHUzME1JT2kw
83 | cHZab0hoN2pwZzZMaENEbDBYdGd4Mi9PWXVVd0NzU3dtUk1QTEQxZHRRd1hNYy9FVVNJZjVBY1h2
84 | anI3TDgrN284eWs4RWpaRkRnTWw5eVVneEM4ZENzN2p4VjRFRWRKK2hkU3FMZERBZTZSTnpyQUEw
85 | cUVVZFhIOGpRWEd3NFJxOFNvRnFkakZVMndjR0E0VFpVelFuck15S2dOdVhPU2hGMmFtbEJocmlP
86 | T2hTT3puSnFxVkU0NTVyTXdHRE84NXFxUWp0S0RzdzlKcnY4NjRVTUJpbmhmOFpqaW54Y1orZFFU
87 | cjhNL2djMERjSWhaTlBZdGZQOElBMlZJRm1TR3llcm9tTlNML0krejk3N0h5blhTZ05ZY0lmcU9E
88 | WklnaTRCUmpaek94enFCQmJWOGVHeDhYU21SdWVjNnFkMmI1aThyR0lCWHZwZ1pGN0ZUTEFEVFRj
89 | ZU9xUy9xendsQm9mVFRZN2tPTFFYTFlMamFJcG1yZGVXNS9TWWZCOFE1dyt3RDlxcWNMczFPYXRI
90 | R21KTnRhZDFsUWUwNFpmUVlRVEtnVjU2MmV1cUxNZWpUbkV6dTFEcVk2czlqNW00eHdVL2QyN2xT
91 | Q0dCdHZBbXlwQTdqbnE5WURXa0tZQlVRWmVKNjdTWXlLN0VHUUVlcDYweUM2eDNtNWt3U1VHYTMr
92 | amJLYzVINU4xajJ1akhNbEhDTGlFWWM5K2NFYjBvQmhHajZ4bEpSbHhTcitpalQ0NlBrQ0ZlYTh2
93 | L1FHTENlblFBelFqTUVvSDM0b2xTQnRSZ0lXRHFpOEVCZjM2TTgraDQzTHc2Y21JRkdyYllFUUN6
94 | Z09kN1VzMzlkYVc2R2gra3VvVTJvdFNnVGw0NTh4ekhNdCs4N2hwbm5aaTdXTmdNUGhFRFVXKzdD
95 | YllYZzlWWCt6TFVrTFhnQlRrNkpCL1RnRXUzc1J1aVBJOWQ4S2lRcUNzVUVVK2dCYWhSeGdDRzZw
96 | N2ZJd1huR1Y2OXZVa1ZvVFd3eWxSWHdUcnJBOUdXQ0crM29pNkFxT2JoajRCTW5WUW5GalByT1RK
97 | WG1iajRUdFZKUUNKYkpTdjF4TGtyMVRxak12MFV4Y0N3N0EwY0pMbVB6RlZ0aWFVa2k3aXowZ29v
98 | SW1SYzVzdVVsMkxRZlZUYjNyVWZna3A0RXl5ZVo4a1lMNE81eDNYVkEzalgyU1dnbWp6ZGVYTFpk
99 | RGpLWlVxclNONFBydmlJTVN5TVUyTnEzdnNra3N6VTFoYU1jbEZPd1BqMU94eSt5bUYvL2NpcUtz
100 | OUdWVXpDRkl2Nno0N1QvZjVVamYxVGFZM1NybjdwSk5QMUVIZzZHeVVONWJEaS9HQlZNdU5qTTAz
101 | OUN0a2VGZnprbGNrK0dyeXJhYUh1bThRSklZeFJ3UmNVQnlqa1VDUmdVUUtVb1FXVTQvNWZEcG1M
102 | b04xQVFmZS8xaW15bVlOUkt4Tnd2S3ErVlhuWTc0OXZWdStrZThCM25IU1BicWtxMGh3WFFFV0hO
103 | d3c2UlZFYU5vV0JTZ0pEci9PSzAxdlFrWGxjMWNLanJ0TkJxWjFQTGVpVE9Rby9rVVMreHZTSnV1
104 | S0pDNm8vY2VERWpCekdmajV3eTN1VkNVRGRXTyt2QXpSVnErcWIrYzk1dUFVUXMrejRyVXBobzZh
105 | a0hlayszQXVKbFZoY09BRGJyMEIzZ25mQlVTbTJrSkVlNjNRcDl3M3BjVkJVdk8wMlFMM291Q1hE
106 | RmNJa3lFbDFLYUo0YXRReks0SnplOTd3NVVXWENPaks0L00wZU9zMkhJMU84aFZyb1NaZnBhN05N
107 | anhBMG9kOUNKR3NEZGdBVWQ3eHRnUnZQT2l0THlKNVphOWJmU0tJTld1eUMwYnN4d0tVZnhJcHli
108 | eE15cGJESmlrSFhTRkRBNEZJaGxTQml5VzNXRm5rWU90OGVTeU1zbVY0UzhhMDczejBHSVk3ZGxu
109 | djR5TVdBSEVzNG1KZVprVmptWCszZ3doSjwveGVuYzpDaXBoZXJWYWx1ZT4NCiAgIDwveGVuYzpD
110 | aXBoZXJEYXRhPg0KPC94ZW5jOkVuY3J5cHRlZERhdGE+PC9FbmNyeXB0ZWRBc3NlcnRpb24+PC9z
111 | YW1scDpSZXNwb25zZT4=
112 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | Copyright 2014 Clever, Inc.
179 |
180 | Licensed under the Apache License, Version 2.0 (the "License");
181 | you may not use this file except in compliance with the License.
182 | You may obtain a copy of the License at
183 |
184 | http://www.apache.org/licenses/LICENSE-2.0
185 |
186 | Unless required by applicable law or agreed to in writing, software
187 | distributed under the License is distributed on an "AS IS" BASIS,
188 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
189 | See the License for the specific language governing permissions and
190 | limitations under the License.
191 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Maintenance Notice
2 |
3 | This library is currently in maintenance mode. Until further notice, the primary directive is to handle bug reports and security issues with this library.
4 |
5 | Any library alternatives and suggestions can be filed under an issue.
6 |
7 | # SAML2-js
8 |
9 | [](https://circleci.com/gh/Clever/saml2/tree/master)
10 |
11 | `saml2-js` is a node module that abstracts away the complexities of the SAML protocol behind an easy to use interface. It achieves this this by helping you implement a service provider for the SAML protocol. It currently does not implement the features to act as an identity provider.
12 |
13 | ## Usage
14 |
15 | Install with [npm](https://www.npmjs.com/).
16 |
17 | ```bash
18 | npm install saml2-js --save
19 | ```
20 |
21 | Include the SAML library.
22 |
23 | ```javascript
24 | var saml2 = require('saml2-js');
25 | ```
26 |
27 | ## Documentation
28 |
29 | This library exports two constructors.
30 |
31 | - [`ServiceProvider`](#ServiceProvider) - Represents a service provider that relies on a trusted [`IdentityProvider`](#IdentityProvider) for authentication and authorization in the SAML flow.
32 | - [`IdentityProvider`](#IdentityProvider) - Represents an online service that authenticates users in the SAML flow.
33 |
34 |
35 |
36 | **Note:** Some options can be set on the [SP](#ServiceProvider), [IdP](#IdentityProvider), and/or on a per-method basis. For the options that are set in multiple places, they are overridden in the following order: per-method basis *overrides* [IdP](#IdentityProvider) which *overrides* [SP](#ServiceProvider).
37 |
38 |
39 |
40 | ### ServiceProvider(options)
41 | Represents a service provider that relies on a trusted [`IdentityProvider`](#IdentityProvider) for authentication and authorization in the SAML flow.
42 |
43 | #### Options
44 | An object that can contain the below options. All options are strings, unless specified otherwise. See [note](#note_options) for more information on options.
45 |
46 | - `entity_id` - **Required** - Unique identifier for the service provider, often the URL of the metadata file.
47 | - `private_key` - **Required** - (PEM format string) - Private key for the service provider.
48 | - `certificate` - **Required** - (PEM format string) - Certificate for the service provider.
49 | - `assert_endpoint` - **Required** - URL of service provider assert endpoint.
50 | - `alt_private_keys` - (Array of PEM format strings) - Additional private keys to use when attempting to decrypt responses. Useful for adding backward-compatibility for old certificates after a rollover.
51 | - `alt_certs` - (Array of PEM format strings) - Additional certificates to expose in the SAML metadata. Useful for staging new certificates for rollovers.
52 | - `audience` - (String or RegExp) — If set, at least one of the `` values within the `` condition of a SAML authentication response must match. Defaults to `entity_id`.
53 | - `notbefore_skew` - (Number) – To account for clock skew between IdP and SP, accept responses with a NotBefore condition ahead of the current time (according to our clock) by this number of seconds. Defaults to 1. Set it to 0 for optimum security but no tolerance for clock skew.
54 | - `force_authn` - (Boolean) - If true, forces re-authentication of users even if the user has a SSO session with the [IdP](#IdentityProvider). This can also be configured on the [IdP](#IdentityProvider) or on a per-method basis.
55 | - `auth_context` - Specifies `AuthnContextClassRef`. This can also be configured on a per-method basis.
56 | - `nameid_format` - Format for Name ID. This can also be configured on a per-method basis.
57 | - `sign_get_request` - (Boolean) - If true, signs the request. This can also be configured on the [IdP](#IdentityProvider) or on a per-method basis.
58 | - `allow_unencrypted_assertion` - (Boolean) - If true, allows unencrypted assertions. This can also be configured on the [IdP](#IdentityProvider) or on a per-method basis.
59 |
60 | #### Returns the following functions
61 | - [`create_login_request_url(IdP, options, cb)`](#create_login_request_url) - Get a URL to initiate a login.
62 | - [`redirect_assert(IdP, options, cb)`](#redirect_assert) - Gets a SAML response object if the login attempt is valid, used for redirect binding.
63 | - [`post_assert(IdP, options, cb)`](#post_assert) - Gets a SAML response object if the login attempt is valid, used for post binding.
64 | - [`create_logout_request_url(IdP, options, cb)`](#create_logout_request_url)- Creates a SAML Request URL to initiate a user logout.
65 | - [`create_logout_response_url(IdP, options, cb)`](#create_logout_response_url) - Creates a SAML Response URL to confirm a successful [IdP](#IdentityProvider) initiated logout.
66 | - [`create_metadata()`](#create_metadata) - Returns the XML metadata used during the initial SAML configuration.
67 |
68 | #### Example
69 | ```javascript
70 |
71 | var sp_options = {
72 | entity_id: "https://sp.example.com/metadata.xml",
73 | private_key: fs.readFileSync("key-file.pem").toString(),
74 | certificate: fs.readFileSync("cert-file.crt").toString(),
75 | assert_endpoint: "https://sp.example.com/assert",
76 | force_authn: true,
77 | auth_context: { comparison: "exact", class_refs: ["urn:oasis:names:tc:SAML:1.0:am:password"] },
78 | nameid_format: "urn:oasis:names:tc:SAML:2.0:nameid-format:transient",
79 | sign_get_request: false,
80 | allow_unencrypted_assertion: true
81 | }
82 |
83 | // Call service provider constructor with options
84 | var sp = new saml2.ServiceProvider(sp_options);
85 |
86 | // Example use of service provider.
87 | // Call metadata to get XML metatadata used in configuration.
88 | var metadata = sp.create_metadata();
89 |
90 | ```
91 |
92 | #### Service provider function definitions
93 |
94 |
95 |
96 | ##### create_login_request_url(IdP, options, cb)
97 | Get a URL to initiate a login.
98 |
99 | Takes the following arguments:
100 | - `IdP` - [IdP](#IdentityProvider)
101 | - `options` - An object that can contain the below options. All options are strings, unless specified otherwise. See [note](#note_options) for more information on options.
102 | - `relay_state` - SAML relay state.
103 | - `auth_context` - Specifies `AuthnContextClassRef`. This can also be configured on the [SP](#ServiceProvider).
104 | - `nameid_format` - Format for Name ID. This can also be configured on the [SP](#ServiceProvider).
105 | - `force_authn`- (Boolean) - If true, forces re-authentication of users even if the user has a SSO session with the [IdP](#IdentityProvider). This can also be configured on the [IdP](#IdentityProvider) or [SP](#ServiceProvider).
106 | - `sign_get_request` - (Boolean) - If true, signs the request. This can also be configured on the [IdP](#IdentityProvider) or [SP](#ServiceProvider).
107 | - `cb(error, login_url, request_id)` - Callback called with the login URL and ID of the request.
108 |
109 |
110 |
111 |
112 | ##### redirect_assert(IdP, options, cb)
113 | Gets a SAML response object if the login attempt is valid, used for redirect binding.
114 |
115 | Takes the following arguments:
116 | - `IdP` - [IdP](#IdentityProvider)
117 | - `options` - An object that can contain the below options. All options are strings, unless specified otherwise. See [note](#note_options) for more information on options.
118 | - `request_body` - (Object) - An object containing the parsed query string parameters. This object should contain the value for either a `SAMLResponse` or `SAMLRequest`.
119 | - `allow_unencrypted_assertion` - (Boolean) - If true, allows unencrypted assertions. This can also be configured on the [IdP](#IdentityProvider) or [SP](#ServiceProvider).
120 | - `require_session_index` - (Boolean) - If false, allow the assertion to be valid without a `SessionIndex` attribute on the `AuthnStatement` node.
121 | - `cb(error, response)` - Callback called with the [request response](#assert_response).
122 |
123 |
124 | Example of the SAML assert response returned:
125 |
126 | ```javascript
127 | { response_header:
128 | { id: '_abc-1',
129 | destination: 'https://sp.example.com/assert',
130 | in_response_to: '_abc-2' },
131 | type: 'authn_response',
132 | user:
133 | { name_id: 'nameid',
134 | session_index: '_abc-3',
135 | attributes:
136 | { 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname': [ 'Test' ] } } }
137 | ```
138 |
139 |
140 |
141 | ##### post_assert(IdP, options, cb)
142 | Gets a SAML response object if the login attempt is valid, used for post binding.
143 |
144 | Takes the following arguments:
145 | - `IdP` - [IdP](#IdentityProvider)
146 | - `options` - An object that can contain the below options. All options are strings, unless specified otherwise. See [note](#note_options) for more information on options.
147 | - `request_body` - (Object) - An object containing the parsed query string parameters. This object should contain the value for either a `SAMLResponse` or `SAMLRequest`.
148 | - `allow_unencrypted_assertion` - (Boolean) - If true, allows unencrypted assertions. This can also be configured on the [IdP](#IdentityProvider) or [SP](#ServiceProvider).
149 | - `require_session_index` - (Boolean) - If false, allow the assertion to be valid without a `SessionIndex` attribute on the `AuthnStatement` node.
150 | - `audience` - (String or RegExp) — If set, at least one of the `` values within the `` condition of a SAML authentication response must match. Defaults to `entity_id`.
151 | - `notbefore_skew` - (Number) – To account for clock skew between IdP and SP, accept responses with a NotBefore condition ahead of the current time (according to our clock) by this number of seconds. Defaults to 1. Set it to 0 for optimum security but no tolerance for clock skew.
152 | - `cb(error, response)` - Callback called with the [request response](#assert_response).
153 |
154 |
155 |
156 |
157 | ##### create_logout_request_url(IdP, options, cb)
158 | Creates a SAML Request URL to initiate a user logout.
159 |
160 | Takes the following arguments:
161 | - `IdP` - [IdP](#IdentityProvider). Note: Can pass `sso_logout_url` instead of IdP.
162 | - `options` - An object that can contain the below options. All options are strings, unless specified otherwise. See [note](#note_options) for more information on options.
163 | + `name_id` - Format for Name ID. This can also be configured on a per-method basis.
164 | + `session_index` - Session index to use for creating logout request.
165 | + `allow_unencrypted_assertion` - (Boolean) - If true, allows unencrypted assertions. This can also be configured on the [IdP](#IdentityProvider) or [SP](#ServiceProvider).
166 | + `sign_get_request` - (Boolean) - If true, signs the request. This can also be configured on the [IdP](#IdentityProvider) or [SP](#ServiceProvider).
167 | + `relay_state` - SAML relay state.
168 | - `cb(error, request_url)` - Callback called with the logout request url.
169 |
170 |
171 |
172 |
173 | ##### create_logout_response_url(IdP, options, cb)
174 | Creates a SAML Response URL to confirm a successful [IdP](#IdentityProvider) initiated logout.
175 |
176 | Takes the following arguments:
177 | - `IdP` - [IdP](#IdentityProvider). Note: Can pass `sso_logout_url` instead of IdP.
178 | - `options` - An object that can contain the below options. All options are strings, unless specified otherwise. See [note](#note_options) for more information on options.
179 | + `in_response_to` - The ID of the request that this is in response to. Should be checked against any sent request IDs.
180 | + `sign_get_request` - (Boolean) - If true, signs the request. This can also be configured on the [IdP](#IdentityProvider) or [SP](#ServiceProvider).
181 | + `relay_state` - SAML relay state.
182 | - `cb(error, response_url)` - Callback called with the logout response url.
183 |
184 |
185 |
186 | ##### create_metadata()
187 | Returns the XML metadata used during the initial SAML configuration.
188 |
189 |
190 |
191 | ### IdentityProvider(options)
192 | Represents an online service that authenticates users in the SAML flow.
193 |
194 | Returns no functions, exists solely to be passed to an [SP](#ServiceProvider) function.
195 |
196 | #### Options
197 | An object that can contain the below options. All options are strings, unless specified otherwise. See [note](#note_options) for more information on options.
198 |
199 | - `sso_login_url` - **Required** - Login url to use during a login request.
200 | - `sso_logout_url` - **Required** - Logout url to use during a logout request.
201 | - `certificates` - **Required** - (PEM format string or array of PEM format strings) - Certificate or certificates (array of certificate) for the identity provider.
202 | - `force_authn` - (Boolean) - If true, forces re-authentication of users even if the user has a SSO session with the [IdP](#IdentityProvider). This can also be configured on the [SP](#ServiceProvider) or on a per-method basis.
203 | - `sign_get_request` - (Boolean) - If true, signs the request. This can also be configured on the [[SP](#ServiceProvider) or on a per-method basis.
204 | - `allow_unencrypted_assertion` - (Boolean) - If true, allows unencrypted assertions. This can also be configured on the [SP](#ServiceProvider) or on a per-method basis.
205 |
206 | #### Example
207 | ```javascript
208 |
209 | // Initialize options object
210 | var idp_options = {
211 | sso_login_url: "https://idp.example.com/login",
212 | sso_logout_url: "https://idp.example.com/logout",
213 | certificates: [fs.readFileSync("cert-file1.crt").toString(), fs.readFileSync("cert-file2.crt").toString()],
214 | force_authn: true,
215 | sign_get_request: false,
216 | allow_unencrypted_assertion: false
217 | };
218 |
219 | // Call identity provider constructor with options
220 | var idp = new saml2.IdentityProvider(idp_options);
221 |
222 | // Example usage of identity provider.
223 | // Pass identity provider into a service provider function with options and a callback.
224 | sp.post_assert(idp, {}, callback);
225 |
226 | ```
227 |
228 |
229 | ## Example: Express implementation
230 |
231 | Library users will need to implement a set of URL endpoints, here is an example of [express](http://expressjs.com/) endpoints.
232 |
233 | ```javascript
234 | var saml2 = require('saml2-js');
235 | var fs = require('fs');
236 | var express = require('express');
237 | var app = express();
238 | // If you're using express <4.0:
239 | // var bodyParser = require('body-parser');
240 | // app.use(bodyParser.urlencoded({
241 | // extended: true
242 | // }));
243 | app.use(express.urlencoded());
244 |
245 | // Create service provider
246 | var sp_options = {
247 | entity_id: "https://sp.example.com/metadata.xml",
248 | private_key: fs.readFileSync("key-file.pem").toString(),
249 | certificate: fs.readFileSync("cert-file.crt").toString(),
250 | assert_endpoint: "https://sp.example.com/assert"
251 | };
252 | var sp = new saml2.ServiceProvider(sp_options);
253 |
254 | // Create identity provider
255 | var idp_options = {
256 | sso_login_url: "https://idp.example.com/login",
257 | sso_logout_url: "https://idp.example.com/logout",
258 | certificates: [fs.readFileSync("cert-file1.crt").toString(), fs.readFileSync("cert-file2.crt").toString()]
259 | };
260 | var idp = new saml2.IdentityProvider(idp_options);
261 |
262 | // ------ Define express endpoints ------
263 |
264 | // Endpoint to retrieve metadata
265 | app.get("/metadata.xml", function(req, res) {
266 | res.type('application/xml');
267 | res.send(sp.create_metadata());
268 | });
269 |
270 | // Starting point for login
271 | app.get("/login", function(req, res) {
272 | sp.create_login_request_url(idp, {}, function(err, login_url, request_id) {
273 | if (err != null)
274 | return res.send(500);
275 | res.redirect(login_url);
276 | });
277 | });
278 |
279 | // Variables used in login/logout process
280 | var name_id, session_index;
281 |
282 | // Assert endpoint for when login completes
283 | app.post("/assert", function(req, res) {
284 | var options = {request_body: req.body};
285 | sp.post_assert(idp, options, function(err, saml_response) {
286 | if (err != null)
287 | return res.send(500);
288 |
289 | // Save name_id and session_index for logout
290 | // Note: In practice these should be saved in the user session, not globally.
291 | name_id = saml_response.user.name_id;
292 | session_index = saml_response.user.session_index;
293 |
294 | res.send("Hello #{name_id}! session_index: #{session_index}.");
295 | });
296 | });
297 |
298 | // Starting point for logout
299 | app.get("/logout", function(req, res) {
300 | var options = {
301 | name_id: name_id,
302 | session_index: session_index
303 | };
304 |
305 | sp.create_logout_request_url(idp, options, function(err, logout_url) {
306 | if (err != null)
307 | return res.send(500);
308 | res.redirect(logout_url);
309 | });
310 | });
311 |
312 | app.listen(3000);
313 |
314 | ```
315 |
--------------------------------------------------------------------------------
/lib/saml2.coffee:
--------------------------------------------------------------------------------
1 | _ = require 'underscore'
2 | async = require 'async'
3 | crypto = require 'crypto'
4 | debug = require('debug') 'saml2'
5 | url = require 'url'
6 | util = require 'util'
7 | xmlbuilder = require 'xmlbuilder2'
8 | xpath = require 'xpath'
9 | xmldom = require '@xmldom/xmldom'
10 | xmlenc = require 'xml-encryption'
11 | zlib = require 'zlib'
12 | SignedXml = require('xml-crypto').SignedXml
13 |
14 | XMLNS =
15 | SAML: 'urn:oasis:names:tc:SAML:2.0:assertion'
16 | SAMLP: 'urn:oasis:names:tc:SAML:2.0:protocol'
17 | MD: 'urn:oasis:names:tc:SAML:2.0:metadata'
18 | DS: 'http://www.w3.org/2000/09/xmldsig#'
19 | XENC: 'http://www.w3.org/2001/04/xmlenc#'
20 | EXC_C14N: 'http://www.w3.org/2001/10/xml-exc-c14n#'
21 |
22 | class SAMLError extends Error
23 | constructor: (@message, @extra) ->
24 | super @message
25 |
26 | # Creates an AuthnRequest and returns it as a string of xml along with the randomly generated ID for the created
27 | # request.
28 | create_authn_request = (issuer, assert_endpoint, destination, force_authn, context, nameid_format) ->
29 | if context?
30 | context_element = { 'saml:AuthnContextClassRef': context.class_refs, '@Comparison': context.comparison }
31 |
32 | id = '_' + crypto.randomBytes(21).toString('hex')
33 | xml = xmlbuilder.create
34 | AuthnRequest:
35 | '@xmlns': XMLNS.SAMLP
36 | '@xmlns:saml': XMLNS.SAML
37 | '@Version': '2.0'
38 | '@ID': id
39 | '@IssueInstant': (new Date()).toISOString()
40 | '@Destination': destination
41 | '@AssertionConsumerServiceURL': assert_endpoint
42 | '@ProtocolBinding': 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST'
43 | '@ForceAuthn': force_authn
44 | 'saml:Issuer': issuer
45 | NameIDPolicy:
46 | '@Format': nameid_format or 'urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified'
47 | '@AllowCreate': 'true'
48 | RequestedAuthnContext: context_element
49 | .end()
50 | { id, xml }
51 |
52 | # Adds an embedded signature to a previously generated AuthnRequest
53 | sign_authn_request = (xml, private_key, options) ->
54 | signer = new SignedXml options
55 | signer.addReference({
56 | xpath: "//*[local-name(.)='AuthnRequest']",
57 | transforms: ['http://www.w3.org/2000/09/xmldsig#enveloped-signature', 'http://www.w3.org/2001/10/xml-exc-c14n#']
58 | digestAlgorithm: "http://www.w3.org/2001/04/xmlenc#sha256"
59 | })
60 | signer.privateKey = private_key
61 | signer.canonicalizationAlgorithm = 'http://www.w3.org/2001/10/xml-exc-c14n#';
62 | signer.signatureAlgorithm = options?.signatureAlgorithm || 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256'
63 |
64 | signer.computeSignature xml
65 |
66 |
67 | return signer.getSignedXml()
68 |
69 | # Creates metadata and returns it as a string of XML. The metadata has one POST assertion endpoint.
70 | create_metadata = (entity_id, assert_endpoint, signing_certificates, encryption_certificates) ->
71 | signing_cert_descriptors = for signing_certificate in signing_certificates or []
72 | certificate_to_keyinfo('signing', signing_certificate)
73 |
74 | encryption_cert_descriptors = for encryption_certificate in encryption_certificates or []
75 | certificate_to_keyinfo('encryption', encryption_certificate)
76 |
77 | xmlbuilder.create
78 | 'md:EntityDescriptor':
79 | '@xmlns:md': XMLNS.MD
80 | '@xmlns:ds': XMLNS.DS
81 | '@entityID': entity_id
82 | '@validUntil': (new Date(Date.now() + 1000 * 60 * 60)).toISOString()
83 | 'md:SPSSODescriptor':
84 | '@protocolSupportEnumeration': 'urn:oasis:names:tc:SAML:1.1:protocol urn:oasis:names:tc:SAML:2.0:protocol'
85 | 'md:KeyDescriptor': signing_cert_descriptors.concat(encryption_cert_descriptors)
86 | 'md:SingleLogoutService':
87 | '@Binding': 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect'
88 | '@Location': assert_endpoint
89 | 'md:AssertionConsumerService':
90 | '@Binding': 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST'
91 | '@Location': assert_endpoint
92 | '@index': '0'
93 | .end()
94 |
95 | # Creates a LogoutRequest and returns it as a string of xml.
96 | create_logout_request = (issuer, name_id, session_index, destination) ->
97 | id = '_' + crypto.randomBytes( 21 ).toString( 'hex' )
98 | xml = xmlbuilder.create
99 | 'samlp:LogoutRequest':
100 | '@xmlns:samlp': XMLNS.SAMLP
101 | '@xmlns:saml': XMLNS.SAML
102 | '@ID': id
103 | '@Version': '2.0'
104 | '@IssueInstant': (new Date()).toISOString()
105 | '@Destination': destination
106 | 'saml:Issuer': issuer
107 | 'saml:NameID': name_id
108 | 'samlp:SessionIndex': session_index
109 | .end()
110 |
111 | {id, xml}
112 |
113 | # Creates a LogoutResponse and returns it as a string of xml.
114 | create_logout_response = (issuer, in_response_to, destination, status='urn:oasis:names:tc:SAML:2.0:status:Success') ->
115 | xmlbuilder.create(
116 | {'samlp:LogoutResponse':
117 | '@Destination': destination
118 | '@ID': '_' + crypto.randomBytes(21).toString('hex')
119 | '@InResponseTo': in_response_to
120 | '@IssueInstant': (new Date()).toISOString()
121 | '@Version': '2.0'
122 | '@xmlns:samlp': XMLNS.SAMLP
123 | '@xmlns:saml': XMLNS.SAML
124 | 'saml:Issuer': issuer
125 | 'samlp:Status':
126 | 'samlp:StatusCode': '@Value': status
127 | }, { headless: true }
128 | ).end()
129 |
130 | # Takes a base64 encoded @key and returns it formatted with newlines and a PEM header according to @type. If it already
131 | # has a PEM header, it will just return the original key.
132 | format_pem = (key, type) ->
133 | return key if (/-----BEGIN [0-9A-Z ]+-----[^-]*-----END [0-9A-Z ]+-----/g.exec(key))?
134 | return "-----BEGIN #{type.toUpperCase()}-----\n" + key.match(/.{1,64}/g).join("\n") + "\n-----END #{type.toUpperCase()}-----"
135 |
136 | # Takes a compressed/base64 enoded @saml_request and @private_key and signs the request using RSA-SHA256. It returns
137 | # the result as an object containing the query parameters.
138 | sign_request = (saml_request, private_key, relay_state, response=false) ->
139 | action = if response then "SAMLResponse" else "SAMLRequest"
140 | data = "#{action}=" + encodeURIComponent(saml_request)
141 | if relay_state
142 | data += "&RelayState=" + encodeURIComponent(relay_state)
143 | data += "&SigAlg=" + encodeURIComponent('http://www.w3.org/2001/04/xmldsig-more#rsa-sha256')
144 |
145 | saml_request_data = "#{action}=" + encodeURIComponent(saml_request)
146 | relay_state_data = if relay_state? then "&RelayState=" + encodeURIComponent(relay_state) else ""
147 | sigalg_data = "&SigAlg=" + encodeURIComponent('http://www.w3.org/2001/04/xmldsig-more#rsa-sha256')
148 | sign = crypto.createSign 'RSA-SHA256'
149 | sign.update(saml_request_data + relay_state_data + sigalg_data)
150 |
151 | samlQueryString = {}
152 |
153 | if response
154 | samlQueryString.SAMLResponse = saml_request
155 | else
156 | samlQueryString.SAMLRequest = saml_request
157 |
158 | if relay_state
159 | samlQueryString.RelayState = relay_state
160 |
161 | samlQueryString.SigAlg = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256'
162 | samlQueryString.Signature = sign.sign(format_pem(private_key, 'PRIVATE KEY'), 'base64')
163 |
164 | samlQueryString
165 |
166 | # Converts a pem certificate to a KeyInfo object for use with XML.
167 | certificate_to_keyinfo = (use, certificate) ->
168 | {
169 | '@use': use
170 | 'ds:KeyInfo':
171 | '@xmlns:ds': XMLNS.DS
172 | 'ds:X509Data':
173 | 'ds:X509Certificate': extract_certificate_data certificate
174 | }
175 |
176 | # Returns the raw certificate data with all extraneous characters removed.
177 | extract_certificate_data = (certificate) ->
178 | cert_data = /-----BEGIN CERTIFICATE-----([^-]*)-----END CERTIFICATE-----/g.exec certificate
179 | cert_data = if cert_data? then cert_data[1] else certificate
180 | throw new Error('Invalid Certificate') unless cert_data?
181 |
182 | return cert_data.replace(/[\r\n]/g, '')
183 |
184 | # Takes in an xml @dom containing a SAML Status and returns true if at least one status is Success.
185 | check_status_success = (dom) ->
186 | status = dom.getElementsByTagNameNS(XMLNS.SAMLP, 'Status')
187 | return false unless status.length is 1
188 | for status_code in status[0].childNodes or []
189 | if status_code.attributes?
190 | status = get_attribute_value status_code, 'Value'
191 | return status is 'urn:oasis:names:tc:SAML:2.0:status:Success'
192 | false
193 |
194 | get_status = (dom) ->
195 | status_list = {}
196 | status = dom.getElementsByTagNameNS(XMLNS.SAMLP, 'Status')
197 | return status_list unless status.length is 1
198 |
199 | for status_code in status[0].childNodes or []
200 | if status_code.attributes?
201 | top_status = get_attribute_value status_code, 'Value'
202 | status_list[top_status] ?= []
203 | for sub_status_code in status_code.childNodes or []
204 | if sub_status_code?.attributes?
205 | status = get_attribute_value sub_status_code, 'Value'
206 | status_list[top_status].push status
207 | status_list
208 |
209 | to_error = (err) ->
210 | return null unless err?
211 | return new Error(util.inspect err) unless err instanceof Error
212 | err
213 |
214 | # Takes in an XML @dom of an object containing an EncryptedAssertion and attempts to decrypt it
215 | # using the @private_keys in the given order.
216 | #
217 | # @cb will be called with an error if the decryption fails, or the EncryptedAssertion cannot be
218 | # found. If successful, it will be called with the decrypted data as a string.
219 | decrypt_assertion = (dom, private_keys, cb) ->
220 | # This is needed because xmlenc sometimes throws an exception, and sometimes calls the passed-in
221 | # callback.
222 | cb = _.wrap cb, (fn, err, args...) -> setTimeout (-> fn to_error(err), args...), 0
223 |
224 | try
225 | encrypted_assertion = dom.getElementsByTagNameNS(XMLNS.SAML, 'EncryptedAssertion')
226 | unless encrypted_assertion.length is 1
227 | return cb new Error("Expected 1 EncryptedAssertion; found #{encrypted_assertion.length}.")
228 |
229 | encrypted_data = encrypted_assertion[0].getElementsByTagNameNS(XMLNS.XENC, 'EncryptedData')
230 | unless encrypted_data.length is 1
231 | return cb new Error("Expected 1 EncryptedData inside EncryptedAssertion; found #{encrypted_data.length}.")
232 |
233 | encrypted_assertion = encrypted_assertion[0].toString()
234 | errors = []
235 | async.eachOfSeries private_keys, (private_key, index, cb_e) ->
236 | xmlenc.decrypt encrypted_assertion, {key: format_pem(private_key, 'PRIVATE KEY')}, (err, result) ->
237 | if err?
238 | errors.push new Error("Decrypt failed: #{util.inspect err}") if err?
239 | return cb_e()
240 |
241 | debug "Decryption successful with private key ##{index}."
242 | cb null, result
243 | , -> cb new Error("Failed to decrypt assertion with provided key(s): #{util.inspect errors}")
244 | catch err
245 | cb new Error("Decrypt failed: #{util.inspect err}")
246 |
247 | # This checks the signature of a saml document and returns either array containing the signed data if valid, or null
248 | # if the signature is invalid. Comparing the result against null is NOT sufficient for signature checks as it doesn't
249 | # verify the signature is signing the important content, nor is it preventing the parsing of unsigned content.
250 | check_saml_signature = (xml, certificate) ->
251 | doc = (new xmldom.DOMParser()).parseFromString(xml)
252 |
253 | # xpath failed to capture nodes of direct descendents of the root.
254 | # Call documentElement to explicitly start from the root element of the document.
255 | signature = xpath.select("./*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']", doc.documentElement)
256 | return null unless signature.length is 1
257 | sig = new SignedXml(
258 | {
259 | publicCert: format_pem(certificate, 'CERTIFICATE')
260 | }
261 | )
262 | # sig.keyInfoProvider = getKey: -> format_pem(certificate, 'CERTIFICATE')
263 | sig.loadSignature signature[0]
264 | try
265 | valid = sig.checkSignature xml
266 | if valid
267 | return get_signed_data(doc, sig)
268 | else
269 | return null
270 | catch e
271 | # temporary hack
272 | if (e.message.indexOf("invalid signature") != -1)
273 | return null; # returns null for incorrect signature
274 | else
275 | throw e; # throw back the error
276 |
277 |
278 | # Gets the data that is actually signed according to xml-crypto. This function should mirror the way xml-crypto finds
279 | # elements for security reasons.
280 | # deprecate
281 | get_signed_data = (doc, sig) ->
282 | return sig.getSignedReferences(); # use new API
283 | # Takes in an xml @dom of an object containing a SAML Response and returns an object containing the Destination and
284 | # InResponseTo attributes of the Response if present. It will throw an error if the Response is missing or does not
285 | # appear to be valid.
286 | parse_response_header = (dom) ->
287 | for response_type in ['Response', 'LogoutResponse', 'LogoutRequest']
288 | response = dom.getElementsByTagNameNS(XMLNS.SAMLP, response_type)
289 | break if response.length > 0
290 | throw new Error("Expected 1 Response; found #{response.length}") unless response.length is 1
291 |
292 | response_header = {
293 | version: get_attribute_value response[0], 'Version'
294 | destination: get_attribute_value response[0], 'Destination'
295 | in_response_to: get_attribute_value response[0], 'InResponseTo'
296 | id: get_attribute_value response[0], 'ID'
297 | }
298 |
299 | # If no version attribute is supplied, assume v2
300 | version = response_header.version or '2.0'
301 | throw new Error "Invalid SAML Version #{version}" unless version is "2.0"
302 | response_header
303 |
304 | # Takes in an xml @dom of an object containing a SAML Assertion and returns the NameID. If there is no NameID found,
305 | # it will return null. It will throw an error if the Assertion is missing or does not appear to be valid.
306 | get_name_id = (dom) ->
307 | assertion = dom.getElementsByTagNameNS(XMLNS.SAML, 'Assertion')
308 | throw new Error("Expected 1 Assertion; found #{assertion.length}") unless assertion.length is 1
309 |
310 | subject = assertion[0].getElementsByTagNameNS(XMLNS.SAML, 'Subject')
311 | throw new Error("Expected 1 Subject; found #{subject.length}") unless subject.length is 1
312 |
313 | nameid = subject[0].getElementsByTagNameNS(XMLNS.SAML, 'NameID')
314 | return null unless nameid.length is 1
315 |
316 | nameid[0].firstChild?.data
317 |
318 | get_attribute_value = (node, attributeName) ->
319 | attributes = node.attributes or []
320 | attribute = _.filter attributes, (attr) -> attr.name is attributeName
321 | attribute[0]?.value
322 |
323 | # Takes in an xml @dom of an object containing a SAML Assertion and returns the SessionIndex. It will throw an error
324 | # if there is no SessionIndex, no Assertion, or the Assertion does not appear to be valid. Optionally you can pass a
325 | # second argument `false` making SessionIndex optional. Doing so returns `null` instead of throwing an Error if the
326 | # SessionIndex attribute does not exist.
327 | get_session_info = (dom, index_required=true) ->
328 | assertion = dom.getElementsByTagNameNS(XMLNS.SAML, 'Assertion')
329 | throw new Error("Expected 1 Assertion; found #{assertion.length}") unless assertion.length is 1
330 |
331 | authn_statement = assertion[0].getElementsByTagNameNS(XMLNS.SAML, 'AuthnStatement')
332 | throw new Error("Expected 1 AuthnStatement; found #{authn_statement.length}") unless authn_statement.length is 1
333 |
334 | info =
335 | index: get_attribute_value authn_statement[0], 'SessionIndex'
336 | not_on_or_after: get_attribute_value authn_statement[0], 'SessionNotOnOrAfter'
337 |
338 | if index_required and not info.index?
339 | throw new Error("SessionIndex not an attribute of AuthnStatement.")
340 |
341 | info
342 |
343 | # Takes in an xml @dom of an object containing a SAML Assertion and returns and object containing the attributes
344 | # contained within the Assertion. It will throw an error if the Assertion is missing or does not appear to be valid.
345 | parse_assertion_attributes = (dom) ->
346 | assertion = dom.getElementsByTagNameNS(XMLNS.SAML, 'Assertion')
347 | throw new Error("Expected 1 Assertion; found #{assertion.length}") unless assertion.length is 1
348 |
349 | attribute_statement = assertion[0].getElementsByTagNameNS(XMLNS.SAML, 'AttributeStatement')
350 | throw new Error("Expected 1 AttributeStatement inside Assertion; found #{attribute_statement.length}") unless attribute_statement.length <= 1
351 | return {} if attribute_statement.length is 0
352 |
353 | assertion_attributes = {}
354 | for attribute in attribute_statement[0].getElementsByTagNameNS(XMLNS.SAML, 'Attribute')
355 | attribute_name = get_attribute_value attribute, 'Name'
356 | throw new Error("Invalid attribute without name") unless attribute_name?
357 | attribute_values = attribute.getElementsByTagNameNS(XMLNS.SAML, 'AttributeValue')
358 | assertion_attributes[attribute_name] = _.map(attribute_values, (attribute_value) ->
359 | attribute_value.childNodes[0]?.data or '')
360 | assertion_attributes
361 |
362 | # Takes in an object containing SAML Assertion Attributes and returns an object with certain common attributes changed
363 | # into nicer names. Attributes that are not expected are ignored, and attributes with more than one value with have
364 | # all values except the first one dropped.
365 | pretty_assertion_attributes = (assertion_attributes) ->
366 | claim_map =
367 | "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress": "email"
368 | "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname": "given_name"
369 | "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name": "name"
370 | "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn": "upn"
371 | "http://schemas.xmlsoap.org/claims/CommonName": "common_name"
372 | "http://schemas.xmlsoap.org/claims/Group": "group"
373 | "http://schemas.microsoft.com/ws/2008/06/identity/claims/role": "role"
374 | "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname": "surname"
375 | "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/privatepersonalidentifier": "ppid"
376 | "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier": "name_id"
377 | "http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod": "authentication_method"
378 | "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/denyonlysid": "deny_only_group_sid"
379 | "http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlyprimarysid": "deny_only_primary_sid"
380 | "http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlyprimarygroupsid": "deny_only_primary_group_sid"
381 | "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid": "group_sid"
382 | "http://schemas.microsoft.com/ws/2008/06/identity/claims/primarygroupsid": "primary_group_sid"
383 | "http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid": "primary_sid"
384 | "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname": "windows_account_name"
385 |
386 | _.chain(assertion_attributes)
387 | .pairs()
388 | .filter(([k, v]) -> (claim_map[k]? and v.length > 0))
389 | .map(([k, v]) -> [claim_map[k], v[0]])
390 | .object()
391 | .value()
392 |
393 | # takes in an XML string, returns an XML string
394 | # applies all inclusive namespaces for signature assertions onto assertion tag
395 | # used as recommended workaround for xml-crypto library limitation with inclusive namespaces
396 | # see https://github.com/yaronn/xml-crypto/issues/48#issuecomment-129705816
397 | add_namespaces_to_child_assertions = (xml_string) ->
398 | doc = new xmldom.DOMParser().parseFromString xml_string
399 |
400 | response_elements = doc.getElementsByTagNameNS XMLNS.SAMLP, 'Response'
401 | return xml_string if response_elements.length isnt 1
402 | response_element = response_elements[0]
403 |
404 | assertion_elements = response_element.getElementsByTagNameNS XMLNS.SAML, 'Assertion'
405 | return xml_string if assertion_elements.length isnt 1
406 | assertion_element = assertion_elements[0]
407 |
408 | inclusive_namespaces = assertion_element.getElementsByTagNameNS(XMLNS.EXC_C14N, 'InclusiveNamespaces')[0]
409 | namespaces = if inclusive_namespaces and prefixList = inclusive_namespaces.getAttribute('PrefixList')?.trim()
410 | ("xmlns:#{ns}" for ns in prefixList.split(' '))
411 | else
412 | (attr.name for attr in response_element.attributes when attr.name.match /^xmlns:/)
413 |
414 | # add the namespaces that are present in response and missing in assertion.
415 | for ns in namespaces
416 | if response_element.getAttribute(ns) and !assertion_element.getAttribute(ns)
417 | new_attribute = doc.createAttribute ns
418 | new_attribute.value = response_element.getAttribute ns
419 | assertion_element.setAttributeNode new_attribute
420 |
421 | return new xmldom.XMLSerializer().serializeToString response_element
422 |
423 | # Takes a DOM of a saml_response, private keys with which to attempt decryption and the
424 | # certificate(s) of the identity provider that issued it and will return a user object containing
425 | # the attributes or an error if keys are incorrect or the response is invalid.
426 | parse_authn_response = (saml_response, sp_private_keys, idp_certificates, allow_unencrypted, ignore_signature, require_session_index, ignore_timing, notbefore_skew, sp_audience, cb) ->
427 | user = {}
428 |
429 | async.waterfall [
430 | (cb_wf) ->
431 | # Decrypt the assertion
432 | decrypt_assertion saml_response, sp_private_keys, (err, result) ->
433 | return cb_wf null, result unless err?
434 | return cb_wf err, result unless allow_unencrypted and err.message == "Expected 1 EncryptedAssertion; found 0."
435 | assertion = saml_response.getElementsByTagNameNS(XMLNS.SAML, 'Assertion')
436 | unless assertion.length is 1
437 | return cb_wf new Error("Expected 1 Assertion or 1 EncryptedAssertion; found #{assertion.length}")
438 | cb_wf null, assertion[0].toString()
439 | (result, cb_wf) ->
440 | # Validate the signature
441 | debug result
442 | if ignore_signature
443 | return cb_wf null, (new xmldom.DOMParser()).parseFromString(result)
444 |
445 | saml_response_str = saml_response.toString()
446 | for cert, i in idp_certificates or []
447 | try
448 | signed_data = check_saml_signature(result, cert) or check_saml_signature saml_response_str, cert
449 | catch ex
450 | return cb_wf new Error("SAML Assertion signature check failed! (Certificate \##{i+1} may be invalid. #{ex.message}")
451 | unless signed_data
452 | continue # Cert was not valid, try the next one
453 |
454 | for sd in signed_data
455 | signed_dom = (new xmldom.DOMParser()).parseFromString(sd)
456 |
457 | assertion = signed_dom.getElementsByTagNameNS(XMLNS.SAML, 'Assertion')
458 | if assertion.length is 1
459 | return cb_wf null, signed_dom
460 |
461 | encryptedAssertion = signed_dom.getElementsByTagNameNS(XMLNS.SAML, 'EncryptedAssertion')
462 | if encryptedAssertion.length is 1
463 | return decrypt_assertion saml_response, sp_private_keys, (err, result) ->
464 | return cb_wf null, (new xmldom.DOMParser()).parseFromString(result) unless err?
465 | return cb_wf err
466 | return cb_wf new Error("Signed data did not contain a SAML Assertion!")
467 | return cb_wf new Error("SAML Assertion signature check failed! (checked #{idp_certificates.length} certificate(s))")
468 | (decrypted_assertion, cb_wf) ->
469 | # Validate the assertion conditions
470 | conditions = decrypted_assertion.getElementsByTagNameNS(XMLNS.SAML, 'Conditions')[0]
471 | if conditions?
472 | if ignore_timing != true
473 | for attribute in conditions.attributes
474 | condition = attribute.name.toLowerCase()
475 | if condition == 'notbefore' and Date.parse(attribute.value) > Date.now() + (notbefore_skew * 1000)
476 | return cb_wf new SAMLError('SAML Response is not yet valid', {NotBefore: attribute.value})
477 | if condition == 'notonorafter' and Date.parse(attribute.value) <= Date.now()
478 | return cb_wf new SAMLError('SAML Response is no longer valid', {NotOnOrAfter: attribute.value})
479 |
480 | audience_restriction = conditions.getElementsByTagNameNS(XMLNS.SAML, 'AudienceRestriction')[0]
481 | audiences = audience_restriction?.getElementsByTagNameNS(XMLNS.SAML, 'Audience')
482 | if audiences?.length > 0
483 | validAudience = _.find audiences, (audience) ->
484 | audienceValue = audience.firstChild?.data?.trim()
485 | !_.isEmpty(audienceValue?.trim()) and (
486 | (_.isRegExp(sp_audience) and sp_audience.test(audienceValue)) or
487 | (_.isString(sp_audience) and sp_audience.toLowerCase() == audienceValue.toLowerCase())
488 | )
489 | if !validAudience?
490 | return cb_wf new SAMLError('SAML Response is not valid for this audience')
491 | return cb_wf null, decrypted_assertion
492 | (validated_assertion, cb_wf) ->
493 | # Populate attributes
494 | try
495 | session_info = get_session_info validated_assertion, require_session_index
496 | user.name_id = get_name_id validated_assertion
497 | user.session_index = session_info.index
498 | if session_info.not_on_or_after?
499 | user.session_not_on_or_after = session_info.not_on_or_after
500 |
501 | assertion_attributes = parse_assertion_attributes validated_assertion
502 | user = _.extend user, pretty_assertion_attributes(assertion_attributes)
503 | user = _.extend user, attributes: assertion_attributes
504 | cb_wf null, { user }
505 | catch err
506 | return cb_wf err
507 | ], cb
508 |
509 | parse_logout_request = (dom) ->
510 | request = dom.getElementsByTagNameNS(XMLNS.SAMLP, "LogoutRequest")
511 | throw new Error("Expected 1 LogoutRequest; found #{request.length}") unless request.length is 1
512 |
513 | request = {}
514 |
515 | issuer = dom.getElementsByTagNameNS(XMLNS.SAML, 'Issuer')
516 | request.issuer = issuer[0].firstChild?.data if issuer.length is 1
517 | name_id = dom.getElementsByTagNameNS(XMLNS.SAML, 'NameID')
518 | request.name_id = name_id[0].firstChild?.data if name_id.length is 1
519 | session_index = dom.getElementsByTagNameNS(XMLNS.SAMLP, 'SessionIndex')
520 | request.session_index = session_index[0].firstChild?.data if session_index.length is 1
521 |
522 | request
523 |
524 | set_option_defaults = (request_options, idp_options, sp_options) ->
525 | _.defaults({}, request_options, idp_options, sp_options)
526 |
527 | module.exports.ServiceProvider =
528 | class ServiceProvider
529 | # Initializes a service provider given the passed options.
530 | #
531 | # @entity_id, @private_key, @assert_endpoint, @certificate, @alt_private_keys, @alt_certs can
532 | # only be set here and are used by exported functions.
533 | #
534 | # Rest of options can be set/overwritten by the identity provider and/or at function call.
535 | constructor: (options) ->
536 | {@entity_id, @private_key, @certificate, @assert_endpoint, @alt_private_keys, @alt_certs} = options
537 |
538 | options.audience ?= @entity_id
539 | options.notbefore_skew ?= 1
540 |
541 | @alt_private_keys = [].concat(@alt_private_keys or [])
542 | @alt_certs = [].concat(@alt_certs or [])
543 |
544 | @shared_options = _.pick(options,
545 | "force_authn", "auth_context", "nameid_format", "sign_get_request", "allow_unencrypted_assertion", "audience", "notbefore_skew")
546 |
547 | # Returns:
548 | # Redirect URL at which a user can login
549 | # ID of the request
550 | # Params:
551 | # identity_provider
552 | # options
553 | # cb
554 | create_login_request_url: (identity_provider, options, cb) ->
555 | options = set_option_defaults options, identity_provider.shared_options, @shared_options
556 |
557 | { id, xml } = create_authn_request @entity_id, @assert_endpoint, identity_provider.sso_login_url, options.force_authn, options.auth_context, options.nameid_format
558 | zlib.deflateRaw xml, (err, deflated) =>
559 | return cb err if err?
560 | try
561 | uri = url.parse identity_provider.sso_login_url, true
562 | catch ex
563 | return cb ex
564 | delete uri.search # If you provide search and query search overrides query :/
565 | if options.sign_get_request
566 | _.extend(uri.query, sign_request(deflated.toString('base64'), @private_key, options.relay_state))
567 | else
568 | uri.query.SAMLRequest = deflated.toString 'base64'
569 | uri.query.RelayState = options.relay_state if options.relay_state?
570 | cb null, url.format(uri), id
571 |
572 | # Returns:
573 | # An xml string with an AuthnRequest with an embedded xml signature
574 | # Params:
575 | # identity_provider
576 | # options
577 | create_authn_request_xml: (identity_provider, options) ->
578 | options = set_option_defaults options, identity_provider.shared_options, @shared_options
579 |
580 | { id, xml } = create_authn_request @entity_id, @assert_endpoint, identity_provider.sso_login_url, options.force_authn, options.auth_context, options.nameid_format
581 | return sign_authn_request(xml, @private_key, options)
582 |
583 | # Returns:
584 | # An object containing the parsed response for a redirect assert.
585 | # This type of assert inflates the response before parsing it.
586 | # Params:
587 | # identity_provider
588 | # options
589 | # cb
590 | redirect_assert: (identity_provider, options, cb) ->
591 | options = _.defaults(_.extend(options, {get_request: true}), {require_session_index: true})
592 | options = set_option_defaults options, identity_provider.shared_options, @shared_options
593 | @_assert identity_provider, options, cb
594 |
595 | # Returns:
596 | # An object containing the parsed response for a post assert.
597 | # Params:
598 | # identity_provider
599 | # options
600 | # cb
601 | post_assert: (identity_provider, options, cb) ->
602 | options = _.defaults(_.extend(options, {get_request: false}), {require_session_index: true})
603 | options = set_option_defaults options, identity_provider.shared_options, @shared_options
604 | @_assert identity_provider, options, cb
605 |
606 | # Private function, called by redirect and post assert to return a response to
607 | # corresponding assert.
608 | _assert: (identity_provider, options, cb) ->
609 | unless options.request_body?.SAMLResponse? or options.request_body?.SAMLRequest?
610 | return setImmediate cb, new Error("Request body does not contain SAMLResponse or SAMLRequest.")
611 |
612 | unless _.isNumber(options.notbefore_skew)
613 | return setImmediate cb, new Error("Configuration error: `notbefore_skew` must be a number")
614 |
615 | saml_response = null
616 | response = {}
617 |
618 | async.waterfall [
619 | (cb_wf) ->
620 | raw = Buffer.from(options.request_body.SAMLResponse or options.request_body.SAMLRequest, 'base64')
621 |
622 | # Inflate response for redirect requests before parsing it.
623 | if (options.get_request)
624 | return zlib.inflateRaw raw, cb_wf
625 | setImmediate cb_wf, null, raw
626 |
627 | (response_buffer, cb_wf) =>
628 | debug saml_response
629 | saml_response_abnormalized = add_namespaces_to_child_assertions(response_buffer.toString())
630 | saml_response = (new xmldom.DOMParser()).parseFromString(saml_response_abnormalized)
631 |
632 | try
633 | response = { response_header: parse_response_header(saml_response) }
634 | catch err
635 | return cb err
636 | switch
637 | when saml_response.getElementsByTagNameNS(XMLNS.SAMLP, 'Response').length is 1
638 | unless check_status_success(saml_response)
639 | return cb_wf new SAMLError("SAML Response was not success!", {status: get_status(saml_response)})
640 |
641 | response.type = 'authn_response'
642 |
643 | parse_authn_response(
644 | saml_response,
645 | [@private_key].concat(@alt_private_keys),
646 | identity_provider.certificates,
647 | options.allow_unencrypted_assertion,
648 | options.ignore_signature,
649 | options.require_session_index,
650 | options.ignore_timing,
651 | options.notbefore_skew,
652 | options.audience
653 | cb_wf)
654 |
655 | when saml_response.getElementsByTagNameNS(XMLNS.SAMLP, 'LogoutResponse').length is 1
656 | unless check_status_success(saml_response)
657 | return cb_wf new SAMLError("SAML Response was not success!", {status: get_status(saml_response)})
658 |
659 | response.type = 'logout_response'
660 | setImmediate cb_wf, null, {}
661 |
662 | when saml_response.getElementsByTagNameNS(XMLNS.SAMLP, 'LogoutRequest').length is 1
663 | response.type = 'logout_request'
664 | setImmediate cb_wf, null, parse_logout_request saml_response
665 |
666 | (result, cb_wf) ->
667 | _.extend response, result
668 | cb_wf null, response
669 | ], cb
670 |
671 | # ----- Optional -----
672 |
673 | # Returns:
674 | # Redirect URL, at which a user is logged out.
675 | # Params:
676 | # identity_provider
677 | # options
678 | # cb
679 | create_logout_request_url: (identity_provider, options, cb) =>
680 | identity_provider = { sso_logout_url: identity_provider, options: {} } if _.isString(identity_provider)
681 | options = set_option_defaults options, identity_provider.shared_options, @shared_options
682 | {id, xml} = create_logout_request @entity_id, options.name_id, options.session_index, identity_provider.sso_logout_url
683 | zlib.deflateRaw xml, (err, deflated) =>
684 | return cb err if err?
685 | try
686 | uri = url.parse identity_provider.sso_logout_url, true
687 | catch ex
688 | return cb ex
689 | query = null
690 | if options.sign_get_request
691 | query = sign_request deflated.toString('base64'), @private_key, options.relay_state
692 | else
693 | query = SAMLRequest: deflated.toString 'base64'
694 | query.RelayState = options.relay_state if options.relay_state?
695 | uri.query = _.extend(query, uri.query)
696 | uri.search = null
697 | uri.query = query
698 | cb null, url.format(uri), id
699 |
700 | # Returns:
701 | # Redirect URL to confirm a successful logout.
702 | # Params:
703 | # identity_provider
704 | # options
705 | # cb
706 | create_logout_response_url: (identity_provider, options, cb) ->
707 | identity_provider = { sso_logout_url: identity_provider, options: {} } if _.isString(identity_provider)
708 | options = set_option_defaults options, identity_provider.shared_options, @shared_options
709 |
710 | xml = create_logout_response @entity_id, options.in_response_to, identity_provider.sso_logout_url
711 | zlib.deflateRaw xml, (err, deflated) =>
712 | return cb err if err?
713 | try
714 | uri = url.parse identity_provider.sso_logout_url
715 | catch ex
716 | return cb ex
717 | if options.sign_get_request
718 | uri.query = sign_request deflated.toString('base64'), @private_key, options.relay_state, true
719 | else
720 | uri.query = SAMLResponse: deflated.toString 'base64'
721 | uri.query.RelayState = options.relay_state if options.relay_state?
722 | cb null, url.format(uri)
723 |
724 | # Returns:
725 | # XML metadata, used during initial SAML configuration
726 | create_metadata: =>
727 | certs = [@certificate].concat @alt_certs
728 | create_metadata @entity_id, @assert_endpoint, certs, certs
729 |
730 | module.exports.IdentityProvider =
731 | class IdentityProvider
732 | constructor: (options) ->
733 | {@sso_login_url, @sso_logout_url, @certificates} = options
734 | @certificates = [ @certificates ] unless _.isArray(@certificates)
735 | @shared_options = _.pick(options, "force_authn", "sign_get_request", "allow_unencrypted_assertion")
736 |
737 | if process.env.NODE_ENV is "test"
738 | module.exports.create_authn_request = create_authn_request
739 | module.exports.sign_authn_request = sign_authn_request
740 | module.exports.create_metadata = create_metadata
741 | module.exports.format_pem = format_pem
742 | module.exports.sign_request = sign_request
743 | module.exports.check_saml_signature = check_saml_signature
744 | module.exports.check_status_success = check_status_success
745 | module.exports.pretty_assertion_attributes = pretty_assertion_attributes
746 | module.exports.decrypt_assertion = decrypt_assertion
747 | module.exports.parse_response_header = parse_response_header
748 | module.exports.parse_logout_request = parse_logout_request
749 | module.exports.get_name_id = get_name_id
750 | module.exports.get_session_info = get_session_info
751 | module.exports.parse_assertion_attributes = parse_assertion_attributes
752 | module.exports.add_namespaces_to_child_assertions = add_namespaces_to_child_assertions
753 | module.exports.set_option_defaults = set_option_defaults
754 | module.exports.extract_certificate_data = extract_certificate_data
755 |
--------------------------------------------------------------------------------