From a50aa8e1fa9ea313e0a156f278999653888fc4ef Mon Sep 17 00:00:00 2001
From: Michiel Kodde
Date: Mon, 28 Nov 2022 09:57:41 +0100
Subject: [PATCH 1/3] Build a SSP debug SP
---
.github/workflows/build-ssp-debug-sp.yml | 29 +
README.md | 12 +
docker/ssp-debug-sp/Dockerfile | 40 ++
docker/ssp-debug-sp/certificates/idp.crt | 24 +
docker/ssp-debug-sp/certificates/idp.key | 39 ++
docker/ssp-debug-sp/certificates/sp.crt | 23 +
docker/ssp-debug-sp/certificates/sp.key | 39 ++
docker/ssp-debug-sp/certificates/ssp.crt | 23 +
docker/ssp-debug-sp/certificates/ssp.key | 39 ++
.../ssp-debug-sp/conf/DebugSP/default-enable | 0
.../conf/DebugSP/lib/Auth/Source/SP.php | 83 +++
.../conf/DebugSP/www/sp/saml2-acs.php | 26 +
.../conf/SURFconext_short_to_urn.php | 19 +
docker/ssp-debug-sp/conf/accountgen.inc | 85 +++
docker/ssp-debug-sp/conf/authsources.php | 218 +++++++
docker/ssp-debug-sp/conf/config.php | 597 ++++++++++++++++++
docker/ssp-debug-sp/conf/nginx.conf | 23 +
.../ssp-debug-sp/conf/saml20-idp-hosted.php | 157 +++++
.../ssp-debug-sp/conf/saml20-idp-remote.php | 138 ++++
docker/ssp-debug-sp/conf/saml20-sp-remote.php | 47 ++
docker/ssp-debug-sp/conf/sp-config.inc | 48 ++
docker/ssp-debug-sp/conf/sp-utils.inc | 172 +++++
docker/ssp-debug-sp/conf/sp.php | 589 +++++++++++++++++
23 files changed, 2470 insertions(+)
create mode 100644 .github/workflows/build-ssp-debug-sp.yml
create mode 100644 docker/ssp-debug-sp/Dockerfile
create mode 100644 docker/ssp-debug-sp/certificates/idp.crt
create mode 100644 docker/ssp-debug-sp/certificates/idp.key
create mode 100644 docker/ssp-debug-sp/certificates/sp.crt
create mode 100644 docker/ssp-debug-sp/certificates/sp.key
create mode 100644 docker/ssp-debug-sp/certificates/ssp.crt
create mode 100644 docker/ssp-debug-sp/certificates/ssp.key
create mode 100644 docker/ssp-debug-sp/conf/DebugSP/default-enable
create mode 100644 docker/ssp-debug-sp/conf/DebugSP/lib/Auth/Source/SP.php
create mode 100644 docker/ssp-debug-sp/conf/DebugSP/www/sp/saml2-acs.php
create mode 100644 docker/ssp-debug-sp/conf/SURFconext_short_to_urn.php
create mode 100644 docker/ssp-debug-sp/conf/accountgen.inc
create mode 100644 docker/ssp-debug-sp/conf/authsources.php
create mode 100644 docker/ssp-debug-sp/conf/config.php
create mode 100644 docker/ssp-debug-sp/conf/nginx.conf
create mode 100644 docker/ssp-debug-sp/conf/saml20-idp-hosted.php
create mode 100644 docker/ssp-debug-sp/conf/saml20-idp-remote.php
create mode 100644 docker/ssp-debug-sp/conf/saml20-sp-remote.php
create mode 100644 docker/ssp-debug-sp/conf/sp-config.inc
create mode 100644 docker/ssp-debug-sp/conf/sp-utils.inc
create mode 100644 docker/ssp-debug-sp/conf/sp.php
diff --git a/.github/workflows/build-ssp-debug-sp.yml b/.github/workflows/build-ssp-debug-sp.yml
new file mode 100644
index 0000000..8ee97b2
--- /dev/null
+++ b/.github/workflows/build-ssp-debug-sp.yml
@@ -0,0 +1,29 @@
+name: Build docker SSP debug SP container
+
+on:
+ pull_request:
+ workflow_dispatch:
+
+jobs:
+ build-ssp-debug-sp:
+
+ runs-on: ubuntu-latest
+
+ steps:
+
+ - name: Check out the repo
+ uses: actions/checkout@v2
+
+ - name: Log into GitHub Container Registry
+ uses: docker/login-action@v1
+ with:
+ registry: ghcr.io
+ username: ${{ github.repository_owner }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Build the SSP Debug SP container and push to GitHub Packages
+ uses: docker/build-push-action@v2
+ with:
+ tags: ghcr.io/openconext/openconext-containers/openconext-ssp-debug-sp:latest
+ context: docker/ssp-debug-sp/
+ push: true
diff --git a/README.md b/README.md
index dfdbf3f..1c6098f 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,13 @@
# OpenConext-containers
+
+## SSP Debug SP
+The SSP debug SP container is specifically targeted for use with StepUp projects. The container is configured with
+a SP / IdP setup that tailors to use with StepUp authentication in mind. The debug SP (sp.php) can be used to fire
+SSO and SFO authentications to the Gateway.
+
+In order to work with this container, you will need to do some small additional setting up in your own Dockerfile/Docker
+Compose.
+
+1. Make sure you deploy a sp.key, idp.key, sp.crt and idp.crt to the `/var/cert` folder. They should match the SP
+ certificate of the SP's defined in your Gateway SAML entity setup. E.g the entities projected in
+ gateway.saml_entities`.
diff --git a/docker/ssp-debug-sp/Dockerfile b/docker/ssp-debug-sp/Dockerfile
new file mode 100644
index 0000000..af40d6e
--- /dev/null
+++ b/docker/ssp-debug-sp/Dockerfile
@@ -0,0 +1,40 @@
+FROM webdevops/php-nginx:7.2 AS ssp-debug-sp
+MAINTAINER Michiel Kodde (michiel@ibuildings.nl)
+
+# Install required applications & binaries to install SimpleSAMLphp
+RUN apt-get update && apt-get install -y git python zip libpng-dev nodejs
+RUN docker-php-ext-install pdo_mysql exif gd
+
+# Install Composer
+COPY --from=composer:1 /usr/bin/composer /usr/local/bin/composer
+# Install SSP: Clone and install rev adf1eb8 of SSP
+WORKDIR /app/
+RUN git clone https://github.com/simplesamlphp/simplesamlphp.git /app
+RUN git reset --hard adf1eb8
+
+# Install SSP: Copy files
+COPY conf/config.php /app/config/config.php
+COPY conf/authsources.php /app/config/authsources.php
+COPY conf/accountgen.inc /app/config/accountgen.inc
+COPY certificates/* /app/cert/
+COPY conf/saml20-idp-hosted.php /app/metadata/saml20-idp-hosted.php
+COPY conf/saml20-idp-remote.php /app/metadata/saml20-idp-remote.php
+COPY conf/saml20-sp-remote.php /app/metadata/saml20-sp-remote.php
+COPY conf/SURFconext_short_to_urn.php /app/attributemap/SURFconext_short_to_urn.php
+
+# Install SSP: Install dependencies and build
+RUN composer require simplesamlphp/simplesamlphp-module-saml2debug
+RUN composer install --prefer-dist -n -o
+
+# Install SSP: Copy DebugSP files
+COPY conf/DebugSP /app/modules/DebugSP
+COPY conf/sp.php /app/www/sp.php
+COPY conf/sp-config.inc /app/www/sp-config.inc
+COPY conf/sp-utils.inc /app/www/sp-utils.inc
+
+# Enable the SSP IdP
+RUN touch modules/exampleauth/enable
+
+# Configure the webserver: deploy the nginx vhost config & set php-fpm pool config
+COPY conf/nginx.conf /opt/docker/etc/nginx/vhost.conf
+RUN echo '' > /opt/docker/etc/nginx/vhost.common.d/10-php.conf
diff --git a/docker/ssp-debug-sp/certificates/idp.crt b/docker/ssp-debug-sp/certificates/idp.crt
new file mode 100644
index 0000000..2b45bfe
--- /dev/null
+++ b/docker/ssp-debug-sp/certificates/idp.crt
@@ -0,0 +1,24 @@
+-----BEGIN CERTIFICATE-----
+MIID7TCCAlUCFA/gdInhlGAC81SV1MS4HTXKLa2PMA0GCSqGSIb3DQEBCwUAMDMx
+GDAWBgNVBAMMD0RlbW8gR1NTUCAyIElkUDEXMBUGA1UECgwORGV2ZWxvcG1lbnQg
+Vk0wHhcNMjEwNDIwMDcwMjI2WhcNMjYwNDE5MDcwMjI2WjAzMRgwFgYDVQQDDA9E
+ZW1vIEdTU1AgMiBJZFAxFzAVBgNVBAoMDkRldmVsb3BtZW50IFZNMIIBojANBgkq
+hkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAxJFJZyGp5Epp/y0rqRL63Q30S/97zlst
+5Be/vtSwJL/M1yINk38mFGcjVEbuAxyDXHoHhgbwothfikI/1GLygPF4BGjse6fC
+0JSOAyT8YrGvGm4NlKCrDnTcnryWkUZZFZWxzw5F6MdJ1N4+fa2b3KxSRokwrI8h
+soxZxYmzaN01CBrNH4lv2RZ8dFttujUkUjWedOsMcjosg6bSHuSwHvbh1cNCj0Xq
+bJyuEPdFlfi2WL4B8sQIUXPn3ms64K72+ZLPE/HhZ2Ush/mGA0b2Z0pCDX0728WF
+og3ShTz6lXL0XL1Q1sl4ThIZxNraGJ5WxGqsWu5Kykk35gxQI0w9rTWosOCSRZcL
+gVWE1GumlYv3x9XsXpj9+FG75E8Sre2uL0KlGqvcevKhc7h5hg5L059uFX6YnCDr
++F+03Iw5P1cDXaZ84Fua7MTCmldFcyIZxuib7vclhZCZGKgRxhmxZnSBDPT+D/zo
+eq6WW5AJZEo3Ud4ZyRrolLueU66v/+VZAgMBAAEwDQYJKoZIhvcNAQELBQADggGB
+AFd1oxY5qWs7x+keY8jf3AAV3ao3UIKuHpVm6YnkIoTLe+ova5IjY0blj9IYfDTE
+UCoQkwekijJleNadrTQvBvh5ZAj+ghQOJhz2GoVA7CMA+QRIwU51tL7Umss4IQ8S
+NEoz7JrZXfRqM34VAVhZb+9jImUJdpyeiOFLvdVyYkGrJ77+tEmxLpXHXCmPkayp
+O7G0AGbkJHEzhsFSUfdd5O9zh1wX2xW1bXGFIBtBi3g6SsxfPtG69RIuC4E7mvWi
+C9+139Ht9cM90tFRqO6C/ZonZPSR4G95oNI8jKnPS5oToDDzxK+qqCyRRlEts+pV
+SIZiD2Equc+ejSkCiW1zNsKyimRv0arXZCm+GP7qh3bDEWXaGeG91beTRipTvphr
+2+RGr9XDY1mEGqISIogNOQp+TQa5vj18pYRdiNtRcqwxoj/DtMfDpnzuyKD2g4Z8
+Z0+zTe9v0wzDa7Snk0nGWtF2mmW7cClyCpJm1vYE9Z2EWBth7ykndxGD3SpD62fW
+Jw==
+-----END CERTIFICATE-----
\ No newline at end of file
diff --git a/docker/ssp-debug-sp/certificates/idp.key b/docker/ssp-debug-sp/certificates/idp.key
new file mode 100644
index 0000000..a8dc04a
--- /dev/null
+++ b/docker/ssp-debug-sp/certificates/idp.key
@@ -0,0 +1,39 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIG4wIBAAKCAYEAxJFJZyGp5Epp/y0rqRL63Q30S/97zlst5Be/vtSwJL/M1yIN
+k38mFGcjVEbuAxyDXHoHhgbwothfikI/1GLygPF4BGjse6fC0JSOAyT8YrGvGm4N
+lKCrDnTcnryWkUZZFZWxzw5F6MdJ1N4+fa2b3KxSRokwrI8hsoxZxYmzaN01CBrN
+H4lv2RZ8dFttujUkUjWedOsMcjosg6bSHuSwHvbh1cNCj0XqbJyuEPdFlfi2WL4B
+8sQIUXPn3ms64K72+ZLPE/HhZ2Ush/mGA0b2Z0pCDX0728WFog3ShTz6lXL0XL1Q
+1sl4ThIZxNraGJ5WxGqsWu5Kykk35gxQI0w9rTWosOCSRZcLgVWE1GumlYv3x9Xs
+Xpj9+FG75E8Sre2uL0KlGqvcevKhc7h5hg5L059uFX6YnCDr+F+03Iw5P1cDXaZ8
+4Fua7MTCmldFcyIZxuib7vclhZCZGKgRxhmxZnSBDPT+D/zoeq6WW5AJZEo3Ud4Z
+yRrolLueU66v/+VZAgMBAAECggGAA+SkwYgnJ0BaDRXF8ZlQoqQuHHs45oNjy0q1
+H4By5Kdv1Sr1feBczrakOn0VJbag22oHUB4/EdqbOc/KF9jF2MvvhpbVaDWQZDUt
+At7uqL3ALBPV7QWpnaWu4O33RXVROl42oVU1CUE5MyAbuL2BgsNe9cqtzh0fm7uv
+43uws/j9neV5/o/oSTJq0Jsm9zMqPv6U3tfw7So9y3W4X6hD3LkjC+rMHK5T0Ebi
+I6/iDvBYHDXXMAm16HcVNpCFIAIXFT5WNdc21I89l4gbEMjoh+bkLhPHqFmTVVON
+Qhn58UleXWSk1qJCWRYkNcwY2HPehA4aW8moACcS8XH6GeY20HP2fMPGULyNp3Kj
+0pfq66R827ZViF3B4hTQpfFERLYJ/VkMhgRP1TDyvVwAdEM9kcUJS4u8uMGXxpgF
+f1CWlmBARgvqdgkXhzfJDEsB/sOJhob9BDvberQyAESCWn3EJLROLTStvWeuCjWZ
+s/BDz8DcFcIEdE8iuv7TYWJS6RgBAoHBAPAHNL5YzyRXyTn/PDzWmHKssvPGhP9D
+eV5Ao+qOcnuo09oNkbYscWmhGD8LrbLy5XkgwlSXfZCHtrY1JjQyUA6ZpGfXszV7
+rwXa6BVs9aVQ78DYvAzsQEXPHoKMiWwXqzZ1BQFmfYCqMunYNgLqMdNfjR5ApLX7
++IvejYe0I9azU4XEBamloh6x/lLXpi9vGCC0ppbW/qt3xMYXgpFaqrDQ6Ae3gOHu
+ZmftPRdHtnhqHatF/lOY+WHV/YU4zqP4gQKBwQDRpb6Wy9LMs9E0ZdsnFccdW6tP
+XgPBDCs/rrGhida+BJMlZYszuaDbqrwcbgLfBS/Ub7M3pIz3q5f2dpy+hXkf1jXX
+xmPki7QM+WAmyYkvdbTCHnjCoNu1IjlvlSHqNO/Dvd9lPFQH70yOEZtsUq4dtssn
+81ktFXZYbWm6/ZNxi+Q/MaaOwxMsFqim8fTn4kijVyeX2sjchyMfL2bGRpfGgxQv
+rCTOUayyL2sbqQOh+vRzS4qhX2l0EbuWgafiQNkCgcEAsRHv0/g6H6pvNUzYSF1b
+K0XB4lpyJMnHEEQJaHDbfeRHHRZjhwv0QqNn+qKH6nqL1LbZBYSYSfYEURiWbW0s
+aAjqIv0aJHtw25XpHl06PlGd/RsmZzYmGBm6fT5l5orzcIIVRjownalxU9d/yNiy
+FyfnOAkiOWp/qddte03mHm4+UHESaFtbZN+UKdMSsu121DHQr3g9eYsqa6ROWyKS
+x0vl0EOMXZ/8hfCa38C0mNJXvtEs1MkGOCmgFBabQpWBAoHAUwFowJPa1qmrfy+E
+4ajBuWH+JeJ3YgvLY99q/SZyG7H8AKZ/wu8QPWkQKcF06ZBIK7g+IR3JopYSCMdV
+sClwl6Zckx49ltOpaimiZDkPU/cqpmEiNw0xcDoou4E0eGKVO88FkDOeobWhfe6C
+txTVU3Z4YUz8VdlVjhVj82FK634T1OF3rLaX9LDT/aV27git8d4kEv/Q31+yDDrc
+WkzA8xwa9fUWbYnw8mvL4Ju+kHeoKa4TKWl5ezc6KpETQ4WhAoHALvByZ0ch2G2V
+NomRIiCXftGns+mFcTYv/JadMvKQvpwrDPdixqL5rDsPeE/woNmegTsOI3cCZrzr
+zo+W1gUktCcHd9HE4b+8yuAFg2i/FJu9qBqSl2+32a6jt95tr4YySaycWW0NBbjv
+sDsp5eXrq2Tv/6/s2KNdWvpptwhT1/hekll3Mv9vr9ETLG79Wcg5bBrbTwyYfj7O
+qu4tIssiOAqNIH0AGg9alGEIsh/F0wXnAn7QRNvuVmyFZBZ9qAIs
+-----END RSA PRIVATE KEY-----
diff --git a/docker/ssp-debug-sp/certificates/sp.crt b/docker/ssp-debug-sp/certificates/sp.crt
new file mode 100644
index 0000000..1201546
--- /dev/null
+++ b/docker/ssp-debug-sp/certificates/sp.crt
@@ -0,0 +1,23 @@
+-----BEGIN CERTIFICATE-----
+MIID4zCCAksCFE/RXnB+y6e2zlC0Zpi7Pl6GbyuAMA0GCSqGSIb3DQEBCwUAMC4x
+EzARBgNVBAMMClJBIFNBTUwgU1AxFzAVBgNVBAoMDkRldmVsb3BtZW50IFZNMB4X
+DTIxMDQyMDA3MDIyM1oXDTI2MDQxOTA3MDIyM1owLjETMBEGA1UEAwwKUkEgU0FN
+TCBTUDEXMBUGA1UECgwORGV2ZWxvcG1lbnQgVk0wggGiMA0GCSqGSIb3DQEBAQUA
+A4IBjwAwggGKAoIBgQCyMqGyevrF/Ms8fsGQdz6fqzCA8T/QKC9Jb3m7EpQOp/OM
+q/qBv4gjtFf0/bAun2N/u6zZOlPk61iVWRbxIet/O9BAoqRhtT6PHQVcReXR1F3+
+Dk2vH8+QyZwnWGENwh16BYuirIeWQuEgfVDUpSg2MBjkHjZmpF8Dxn6d485qwrdb
+FZN+z3QPtxNaNu1FBktsgPNjlpE7HNB9xcGy4DlgTIP+80nKgM+Kdopw9FVk71bf
+KKHp1m9qSSbFI+drtbtFJ7OPqFYDs9gJEY8ivALID1ERNQkAPImr/EIPiazHc4nk
+Qfi4Kt5ohsvGufdCxYtOUGxjcrkq9oJX5YiiC9xfekPeU05F2FsYWxYK0nmnEP0t
+ydgDFeKl2FI2vUhr2oOaiTs5VlNhMz43diX9AJzjmO4nrePsuA/T3wj8rSzhS9kD
+9IF6GkZ+y+1Yyzf8NWxPfFCL0K4B5/+pGDY5BETX+BHq4kKCGjWVWz9Whd9MeaJb
+4buycT9RyKZrmSEe/fkCAwEAATANBgkqhkiG9w0BAQsFAAOCAYEAjuAYYpA337xi
+Uem4MTmCB68VVEPxVeiR3geTqZdk42ep6ATfalbAIAsqzTsh5QPU5FZByrZauOWA
+6m5HLmlEY3UQmI6l1P9KcOAIVfHQ0uVIpREuEaiFJlA2pif/Epk+Go/jp+yKPHms
+/IT/ZhZTzUCM3xbcan9rDA779pgi/NqYSHJ1EljiD+Wt8jDk67hZAjHum9b79UNs
+bJqB4wHrNkoyOZZnmW88nDeJGvBpoeo/zsy4xi20E23oBP7ti7QVEvsvaZtJ5L7S
+mysHP03fIkfquXswZ8Xl5wS3Vjr82wx9LOGunzZzFF4awRrsIuovvxrTBTD/NNHA
+v0Mm7UC0I8A27mlpufneN4TFcXmYW0KZxkiLbcrXtOicqgRyfEB1UC2C8RAPmeX3
+VGM+odFNhJjkCecms4/xpSqj13CE6S6ci2+osfiMWm5uBw6wAfPt/5rPrvy50dWx
+J13vign9EqLAy7aVRzK8ghu1bOLlXV5Hp6kwwMYYqZBV5A0xOuSj
+-----END CERTIFICATE-----
\ No newline at end of file
diff --git a/docker/ssp-debug-sp/certificates/sp.key b/docker/ssp-debug-sp/certificates/sp.key
new file mode 100644
index 0000000..b400366
--- /dev/null
+++ b/docker/ssp-debug-sp/certificates/sp.key
@@ -0,0 +1,39 @@
+-----BEGIN RSA PRIVATE KEY-----
+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
+-----END RSA PRIVATE KEY-----
diff --git a/docker/ssp-debug-sp/certificates/ssp.crt b/docker/ssp-debug-sp/certificates/ssp.crt
new file mode 100644
index 0000000..1201546
--- /dev/null
+++ b/docker/ssp-debug-sp/certificates/ssp.crt
@@ -0,0 +1,23 @@
+-----BEGIN CERTIFICATE-----
+MIID4zCCAksCFE/RXnB+y6e2zlC0Zpi7Pl6GbyuAMA0GCSqGSIb3DQEBCwUAMC4x
+EzARBgNVBAMMClJBIFNBTUwgU1AxFzAVBgNVBAoMDkRldmVsb3BtZW50IFZNMB4X
+DTIxMDQyMDA3MDIyM1oXDTI2MDQxOTA3MDIyM1owLjETMBEGA1UEAwwKUkEgU0FN
+TCBTUDEXMBUGA1UECgwORGV2ZWxvcG1lbnQgVk0wggGiMA0GCSqGSIb3DQEBAQUA
+A4IBjwAwggGKAoIBgQCyMqGyevrF/Ms8fsGQdz6fqzCA8T/QKC9Jb3m7EpQOp/OM
+q/qBv4gjtFf0/bAun2N/u6zZOlPk61iVWRbxIet/O9BAoqRhtT6PHQVcReXR1F3+
+Dk2vH8+QyZwnWGENwh16BYuirIeWQuEgfVDUpSg2MBjkHjZmpF8Dxn6d485qwrdb
+FZN+z3QPtxNaNu1FBktsgPNjlpE7HNB9xcGy4DlgTIP+80nKgM+Kdopw9FVk71bf
+KKHp1m9qSSbFI+drtbtFJ7OPqFYDs9gJEY8ivALID1ERNQkAPImr/EIPiazHc4nk
+Qfi4Kt5ohsvGufdCxYtOUGxjcrkq9oJX5YiiC9xfekPeU05F2FsYWxYK0nmnEP0t
+ydgDFeKl2FI2vUhr2oOaiTs5VlNhMz43diX9AJzjmO4nrePsuA/T3wj8rSzhS9kD
+9IF6GkZ+y+1Yyzf8NWxPfFCL0K4B5/+pGDY5BETX+BHq4kKCGjWVWz9Whd9MeaJb
+4buycT9RyKZrmSEe/fkCAwEAATANBgkqhkiG9w0BAQsFAAOCAYEAjuAYYpA337xi
+Uem4MTmCB68VVEPxVeiR3geTqZdk42ep6ATfalbAIAsqzTsh5QPU5FZByrZauOWA
+6m5HLmlEY3UQmI6l1P9KcOAIVfHQ0uVIpREuEaiFJlA2pif/Epk+Go/jp+yKPHms
+/IT/ZhZTzUCM3xbcan9rDA779pgi/NqYSHJ1EljiD+Wt8jDk67hZAjHum9b79UNs
+bJqB4wHrNkoyOZZnmW88nDeJGvBpoeo/zsy4xi20E23oBP7ti7QVEvsvaZtJ5L7S
+mysHP03fIkfquXswZ8Xl5wS3Vjr82wx9LOGunzZzFF4awRrsIuovvxrTBTD/NNHA
+v0Mm7UC0I8A27mlpufneN4TFcXmYW0KZxkiLbcrXtOicqgRyfEB1UC2C8RAPmeX3
+VGM+odFNhJjkCecms4/xpSqj13CE6S6ci2+osfiMWm5uBw6wAfPt/5rPrvy50dWx
+J13vign9EqLAy7aVRzK8ghu1bOLlXV5Hp6kwwMYYqZBV5A0xOuSj
+-----END CERTIFICATE-----
\ No newline at end of file
diff --git a/docker/ssp-debug-sp/certificates/ssp.key b/docker/ssp-debug-sp/certificates/ssp.key
new file mode 100644
index 0000000..b400366
--- /dev/null
+++ b/docker/ssp-debug-sp/certificates/ssp.key
@@ -0,0 +1,39 @@
+-----BEGIN RSA PRIVATE KEY-----
+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
+-----END RSA PRIVATE KEY-----
diff --git a/docker/ssp-debug-sp/conf/DebugSP/default-enable b/docker/ssp-debug-sp/conf/DebugSP/default-enable
new file mode 100644
index 0000000..e69de29
diff --git a/docker/ssp-debug-sp/conf/DebugSP/lib/Auth/Source/SP.php b/docker/ssp-debug-sp/conf/DebugSP/lib/Auth/Source/SP.php
new file mode 100644
index 0000000..6dbdc6d
--- /dev/null
+++ b/docker/ssp-debug-sp/conf/DebugSP/lib/Auth/Source/SP.php
@@ -0,0 +1,83 @@
+ 'https://...',
+ 'DebugSP:extraPOSTvars' => array(
+ 'SomePOSTvariable' => 'SomeValue',
+ 'AnotherPOSTvariable' => 'AnotherValue'
+ ),
+ );
+ $as->login($params);
+*/
+
+// Extend from the SimpleSAMLphp SAML 2.0 authentication source "saml:SP"
+class sspmod_DebugSP_Auth_Source_SP extends sspmod_saml_Auth_Source_SP {
+
+ public function __construct($info, $config) {
+ parent::__construct($info, $config);
+ }
+
+ public function sendSAML2AuthnRequest(array &$state, \SAML2\Binding $binding, \SAML2\AuthnRequest $ar) {
+
+ if ( isset( $state['DebugSP:AssertionConsumerServiceURL'] ) ) {
+ // Set the AssertionConsumerServiceURL in the AuthnRequest
+ $ar->setAssertionConsumerServiceURL( $state['DebugSP:AssertionConsumerServiceURL'] );
+ }
+
+ if ($binding instanceof \SAML2\HTTPPost) {
+ // replicate \SAML2\HTTPPost::send(Message $message) so we can set additional POST variables
+ $destination = $ar->getDestination();
+ $relayState = $ar->getRelayState();
+ $post = array();
+
+ // Set extra POST variables
+ if (isset($state['DebugSP:extraPOSTvars'])) {
+ assert(is_array($state['DebugSP:extraPOSTvars']), 'DebugSP:extraPOSTvars must be array()');
+ foreach ($state['DebugSP:extraPOSTvars'] as $key => $value) {
+ $post[$key] = $value;
+ }
+ }
+
+ // Create SAMLRequest
+ $msgStr = $ar->toSignedXML();
+ $msgStr = $msgStr->ownerDocument->saveXML($msgStr);
+
+ \SAML2\Utils::getContainer()->debugMessage($msgStr, 'out');
+
+ $post['SAMLRequest'] = base64_encode($msgStr);
+
+ if ($relayState !== null) {
+ $post['RelayState'] = $relayState;
+ }
+
+ \SAML2\Utils::getContainer()->postRedirect($destination, $post);
+
+ return;
+ }
+
+ // Use partent implementation
+ parent::sendSAML2AuthnRequest($state, $binding, $ar);
+ }
+}
diff --git a/docker/ssp-debug-sp/conf/DebugSP/www/sp/saml2-acs.php b/docker/ssp-debug-sp/conf/DebugSP/www/sp/saml2-acs.php
new file mode 100644
index 0000000..5ee7952
--- /dev/null
+++ b/docker/ssp-debug-sp/conf/DebugSP/www/sp/saml2-acs.php
@@ -0,0 +1,26 @@
+ 'urn:mace:dir:attribute-def:sn',
+ 'givenName' => 'urn:mace:dir:attribute-def:givenName',
+ 'cn' => 'urn:mace:dir:attribute-def:cn',
+ 'displayName' => 'urn:mace:dir:attribute-def:displayName',
+ 'mail' => 'urn:mace:dir:attribute-def:mail',
+ 'uid' => 'urn:mace:dir:attribute-def:uid',
+ 'eduPersonAffiliation' => 'urn:mace:dir:attribute-def:eduPersonAffiliation',
+ 'eduPersonEntitlement' => 'urn:mace:dir:attribute-def:eduPersonEntitlement',
+ 'eduPersonPrincipalName' => 'urn:mace:dir:attribute-def:eduPersonPrincipalName',
+ 'preferredLanguage' => 'urn:mace:dir:attribute-def:preferredLanguage',
+ 'eduPersonTargetedID' => 'urn:mace:dir:attribute-def:eduPersonTargetedID',
+ // urn:mace:terena.org
+ 'schacHomeOrganization' => 'urn:mace:terena.org:attribute-def:schacHomeOrganization',
+ 'schacHomeOrganizationType' => 'urn:mace:terena.org:attribute-def:schacHomeOrganizationType',
+);
diff --git a/docker/ssp-debug-sp/conf/accountgen.inc b/docker/ssp-debug-sp/conf/accountgen.inc
new file mode 100644
index 0000000..fde731f
--- /dev/null
+++ b/docker/ssp-debug-sp/conf/accountgen.inc
@@ -0,0 +1,85 @@
+ 'urn:collab:person:'.$scope.':'.$uid,
+ 'uid' => array($uid),
+ 'eduPersonPrincipalName' => $uid.'@'.$scope,
+ 'givenName' => 'gn-'.$uid,
+ 'sn' => 'sn-'.$scope,
+ 'cn' => $uid.' '.$scope,
+ 'mail' => str_replace('@', '+'.$uid.'@', $email),
+ 'displayName' => 'd-'.$uid.' '.$scope,
+ 'eduPersonAffiliation' => array('student'),
+ 'schacHomeOrganization' => $scope,
+ 'schacHomeOrganizationType' => 'urn:mace:terena.org:schac:homeOrganizationType:int:university',
+ );
+ $config['example-userpass'][$uid.':'.$uid]=$account;
+ }
+
+ // Without SHO
+ $uid=$prefix.'-nosho';
+ $account=array(
+ 'NameID' => 'urn:collab:person:'.$scope.':'.$uid,
+ 'uid' => array($uid),
+ 'eduPersonPrincipalName' => $uid.'@'.$scope,
+ 'givenName' => 'gn-'.$uid,
+ 'sn' => 'sn-'.$scope,
+ 'cn' => $uid.' '.$scope,
+ 'mail' => str_replace('@', '+'.$uid.'@', $email),
+ 'displayName' => 'd-'.$uid.' '.$scope,
+ 'eduPersonAffiliation' => array('student'),
+ //'schacHomeOrganization' => $scope,
+ 'schacHomeOrganizationType' => 'urn:mace:terena.org:schac:homeOrganizationType:int:university',
+ );
+ $config['example-userpass'][$uid.':'.$uid]=$account;
+
+ // Without mail
+ $uid=$prefix.'-nomail';
+ $account=array(
+ 'NameID' => 'urn:collab:person:'.$scope.':'.$uid,
+ 'uid' => array($uid),
+ 'eduPersonPrincipalName' => $uid.'@'.$scope,
+ 'givenName' => 'gn-'.$uid,
+ 'sn' => 'sn-'.$scope,
+ 'cn' => $uid.' '.$scope,
+ //'mail' => str_replace('@', '+'.$uid.'@', $email),
+ 'displayName' => 'd-'.$uid.' '.$scope,
+ 'eduPersonAffiliation' => array('student'),
+ 'schacHomeOrganization' => $scope,
+ 'schacHomeOrganizationType' => 'urn:mace:terena.org:schac:homeOrganizationType:int:university',
+ );
+ $config['example-userpass'][$uid.':'.$uid]=$account;
+
+ // Without cn
+ $uid=$prefix.'-nocn';
+ $account=array(
+ 'NameID' => 'urn:collab:person:'.$scope.':'.$uid,
+ 'uid' => array($uid),
+ 'eduPersonPrincipalName' => $uid.'@'.$scope,
+ 'givenName' => 'gn-'.$uid,
+ 'sn' => 'sn-'.$scope,
+ //'cn' => $uid.' '.$scope,
+ 'mail' => str_replace('@', '+'.$uid.'@', $email),
+ 'displayName' => 'd-'.$uid.' '.$scope,
+ 'eduPersonAffiliation' => array('student'),
+ 'schacHomeOrganization' => $scope,
+ 'schacHomeOrganizationType' => 'urn:mace:terena.org:schac:homeOrganizationType:int:university',
+ );
+ $config['example-userpass'][$uid.':'.$uid]=$account;
+
+}
\ No newline at end of file
diff --git a/docker/ssp-debug-sp/conf/authsources.php b/docker/ssp-debug-sp/conf/authsources.php
new file mode 100644
index 0000000..66797cd
--- /dev/null
+++ b/docker/ssp-debug-sp/conf/authsources.php
@@ -0,0 +1,218 @@
+ array(
+ // The default is to use core:AdminPassword, but it can be replaced with
+ // any authentication source.
+
+ 'core:AdminPassword',
+ ),
+
+ 'example-userpass' => array(
+ 'exampleauth:UserPass',
+
+ 'admin:admin' => array(
+ 'NameID' => 'urn:collab:person:stepup.example.com:admin',
+ 'uid' => array('admin'),
+ 'mail' => 'admin@stepup.example.com',
+ 'eduPersonPrincipalName' => 'admin@stepup.example.com',
+ 'givenName' => 'Admin',
+ 'sn' => 'Admin',
+ 'cn' => 'Admin',
+ 'displayName' => 'Admin',
+ 'eduPersonAffiliation' => array('employee'),
+ 'schacHomeOrganization' => 'stepup.example.com',
+ 'schacHomeOrganizationType' => 'urn:mace:terena.org:schac:homeOrganizationType:int:university',
+ ),
+
+ 'michiel:michiel' => array(
+ 'NameID' => 'urn:collab:person:stepup.example.com:michiel',
+ 'uid' => array('michiel'),
+ 'mail' => 'michiel@ibuildings.nl',
+ 'eduPersonPrincipalName' => 'michiel@stepup.example.com',
+ 'givenName' => 'Michiel',
+ 'sn' => 'Kodde',
+ 'cn' => 'JC',
+ 'displayName' => 'JC',
+ 'eduPersonAffiliation' => array('employee'),
+ 'schacHomeOrganization' => 'stepup.example.com',
+ 'schacHomeOrganizationType' => 'urn:mace:terena.org:schac:homeOrganizationType:int:NREN',
+ ),
+
+ // Test accounts are added using account_gen below
+
+ ),
+
+ // An authentication source which can authenticate against both SAML 2.0
+ // and Shibboleth 1.3 IdPs.
+ 'default-sp' => array(
+ 'DebugSP:SP',
+
+ // The entity ID of this SP.
+ // Can be NULL/unset, in which case an entity ID is generated based on the metadata URL.
+ 'entityID' => 'https://ssp.stepup.example.com/module.php/saml/sp/metadata.php/default-sp',
+
+ // The entity ID of the IdP this should SP should contact.
+ // Can be NULL/unset, in which case the user will be shown a list of available IdPs.
+ 'idp' => NULL,
+
+ // The URL to the discovery service.
+ // Can be NULL/unset, in which case a builtin discovery service will be used.
+ 'discoURL' => NULL,
+
+ 'certificate' => 'sp.crt',
+ 'privatekey' => 'sp.key',
+
+ // See end of file for request.sign and signature alg config!
+ ),
+ 'second-sp' => array(
+ 'DebugSP:SP',
+
+ // The entity ID of this SP.
+ // Can be NULL/unset, in which case an entity ID is generated based on the metadata URL.
+ 'entityID' => 'https://ssp.stepup.example.com/module.php/saml/sp/metadata.php/second-sp',
+
+ // The entity ID of the IdP this should SP should contact.
+ // Can be NULL/unset, in which case the user will be shown a list of available IdPs.
+ 'idp' => NULL,
+
+ // The URL to the discovery service.
+ // Can be NULL/unset, in which case a builtin discovery service will be used.
+ 'discoURL' => NULL,
+
+ 'certificate' => 'sp.crt',
+ 'privatekey' => 'sp.key',
+
+ // See end of file for request.sign and signature.algorithm config!
+ //'redirect.sign' => TRUE,
+ //'signature.algorithm' => 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256',
+ ),
+ 'third-sp' => array(
+ 'DebugSP:SP',
+
+ // The entity ID of this SP.
+ // Can be NULL/unset, in which case an entity ID is generated based on the metadata URL.
+ 'entityID' => 'https://ssp.stepup.example.com/module.php/saml/sp/metadata.php/third-sp',
+
+ // The entity ID of the IdP this should SP should contact.
+ // Can be NULL/unset, in which case the user will be shown a list of available IdPs.
+ 'idp' => NULL,
+
+ // The URL to the discovery service.
+ // Can be NULL/unset, in which case a builtin discovery service will be used.
+ 'discoURL' => NULL,
+
+ 'certificate' => 'sp.crt',
+ 'privatekey' => 'sp.key',
+
+ // See end of file for request.sign and signature.algorithm config!
+ //'redirect.sign' => TRUE,
+ //'signature.algorithm' => 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256',
+ ),
+ 'fourth-sp' => array(
+ 'DebugSP:SP',
+
+ // The entity ID of this SP.
+ // Can be NULL/unset, in which case an entity ID is generated based on the metadata URL.
+ 'entityID' => 'https://ssp.stepup.example.com/module.php/saml/sp/metadata.php/fourth-sp',
+
+ // The entity ID of the IdP this should SP should contact.
+ // Can be NULL/unset, in which case the user will be shown a list of available IdPs.
+ 'idp' => NULL,
+
+ // The URL to the discovery service.
+ // Can be NULL/unset, in which case a builtin discovery service will be used.
+ 'discoURL' => NULL,
+
+ 'certificate' => 'sp.crt',
+ 'privatekey' => 'sp.key',
+
+ // See end of file for request.sign and signature.algorithm config!
+ //'redirect.sign' => TRUE,
+ //'signature.algorithm' => 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256',
+ ),
+
+);
+
+
+// Use the the global variables that were set in sp.php to modify the hosted SP configuration on the fly
+// They won't always be set (e.g. when SSP is used as IdP) so we use isset() to reduce notices
+
+if ( isset($GLOBALS['gSP_redirect_sign']) ) {
+ $config['default-sp']['redirect.sign'] = $GLOBALS['gSP_redirect_sign'] ? TRUE : FALSE;
+ $config['second-sp']['redirect.sign'] = $GLOBALS['gSP_redirect_sign'] ? TRUE : FALSE;
+ $config['third-sp']['redirect.sign'] = $GLOBALS['gSP_redirect_sign'] ? TRUE : FALSE;
+ $config['fourth-sp']['redirect.sign'] = $GLOBALS['gSP_redirect_sign'] ? TRUE : FALSE;
+}
+if ( isset($GLOBALS['gSP_signature_algorithm']) && strlen($GLOBALS['gSP_signature_algorithm']) > 0 ) {
+ $config['default-sp']['signature.algorithm'] = $GLOBALS['gSP_signature_algorithm'];
+ $config['second-sp']['signature.algorithm'] = $GLOBALS['gSP_signature_algorithm'];
+ $config['third-sp']['signature.algorithm'] = $GLOBALS['gSP_signature_algorithm'];
+ $config['fourth-sp']['signature.algorithm'] = $GLOBALS['gSP_signature_algorithm'];
+}
+if ( isset($GLOBALS['gSP_secondary_key']) && $GLOBALS['gSP_secondary_key']) {
+ $config['default-sp']['certificate']='sp2.crt';
+ $config['default-sp']['privatekey']='sp2.key';
+ $config['second-sp']['certificate']='sp2.crt';
+ $config['second-sp']['privatekey']='sp2.key';
+ $config['third-sp']['certificate']='sp2.crt';
+ $config['third-sp']['privatekey']='sp2.key';
+ $config['fourth-sp']['certificate']='sp2.crt';
+ $config['fourth-sp']['privatekey']='sp2.key';
+}
+
+if ( isset($GLOBALS['gSP_ProtocolBinding']) ) {
+ $config['default-sp']['ProtocolBinding'] = $GLOBALS['gSP_ProtocolBinding'];
+ $config['second-sp']['ProtocolBinding'] = $GLOBALS['gSP_ProtocolBinding'];
+ $config['third-sp']['ProtocolBinding'] = $GLOBALS['gSP_ProtocolBinding'];
+ $config['fourth-sp']['ProtocolBinding'] = $GLOBALS['gSP_ProtocolBinding'];
+}
+
+# In test mode (testcookie is present) use the test certificates for the SP's
+if ( isset($_COOKIE['testcookie']) ) {
+ $config['default-sp']['certificate'] = '/vagrant/deploy/tests/behat/fixtures/test_public_key.crt';
+ $config['default-sp']['privatekey'] = '/vagrant/deploy/tests/behat/fixtures/test_private_key.key';
+ $config['second-sp']['certificate'] = '/vagrant/deploy/tests/behat/fixtures/test_public_key.crt';
+ $config['second-sp']['privatekey'] = '/vagrant/deploy/tests/behat/fixtures/test_private_key.key';
+ $config['third-sp']['certificate'] = '/vagrant/deploy/tests/behat/fixtures/test_public_key.crt';
+ $config['third-sp']['privatekey'] = '/vagrant/deploy/tests/behat/fixtures/test_private_key.key';
+ $config['fourth-sp']['certificate'] = '/vagrant/deploy/tests/behat/fixtures/test_public_key.crt';
+ $config['fourth-sp']['privatekey'] = '/vagrant/deploy/tests/behat/fixtures/test_private_key.key';
+}
+
+// Accounts for accountgen script
+// Allows read email addresses to be used for multiple accounts
+// The accountsgen scrip mangles the email address to e.g. joe+slug@stepup.example.com
+$accounts=array(
+ // username => email (this can be a real email address)
+ 'user' => 'user@stepup.example.com',
+ 'joe' => 'joe@stepup.example.com',
+ 'jane' => 'jane@stepup.example.com',
+);
+
+// List of varieties of account to generate
+$slugs=array(
+ "1", "2", "3", "4", "5", "sms", "-yk", "-tiqr", "-u2f", "-bio", "-ra", "-raa"
+);
+
+// for a username 'joe' this will generate joe-a1, joe-a2, ..., joe-a-yk, ... joe-a-raa
+// for a username 'joe' this will generate joe-b1, joe-b2, ..., joe-b-yk, ... joe-b-raa
+// ...
+// For all accounts the username is equal to the password. E.g. "joe-a1" / "joe-a1"
+foreach ($accounts as $user => $email) {
+ // username , email, schachomeorganization
+ account_gen($config, "${user}-", $email, 'stepup.example.com', $slugs);
+ account_gen($config, "${user}-a", $email, 'institution-a.example.com', $slugs);
+ account_gen($config, "${user}-b", $email, 'institution-b.example.com', $slugs);
+ account_gen($config, "${user}-c", $email, 'institution-c.example.com', $slugs);
+ account_gen($config, "${user}-d", $email, 'Institution-D.EXAMPLE.COM', $slugs); // Note: uppercase "I" and "D"
+ account_gen($config, "${user}-e", $email, 'Institution-e.example.com', $slugs);
+ account_gen($config, "${user}-f", $email, 'Institution-f.example.com', $slugs);
+}
diff --git a/docker/ssp-debug-sp/conf/config.php b/docker/ssp-debug-sp/conf/config.php
new file mode 100644
index 0000000..0fe2ff3
--- /dev/null
+++ b/docker/ssp-debug-sp/conf/config.php
@@ -0,0 +1,597 @@
+ 'https://ssp.stepup.example.com/',
+
+ /**
+ * Locations on the filesystem:
+ */
+ 'certdir' => '/app/cert/',
+ 'loggingdir' => '/var/log/simplesamlphp/',
+ 'datadir' => '/var/lib/simplesamlphp/data/',
+ 'metadatadir' => '/app/metadata/',
+ 'attributenamemapdir' => '/app/attributemap/',
+
+ /*
+ * A directory where simpleSAMLphp can save temporary files.
+ *
+ * SimpleSAMLphp will attempt to create this directory if it doesn't exist.
+ */
+ 'tempdir' => '/tmp/simplesaml',
+
+
+ /*
+ * If you enable this option, simpleSAMLphp will log all sent and received messages
+ * to the log file.
+ *
+ * This option also enables logging of the messages that are encrypted and decrypted.
+ *
+ * Note: The messages are logged with the DEBUG log level, so you also need to set
+ * the 'logging.level' option to LOG_DEBUG.
+ */
+ 'debug' => FALSE,
+ 'showerrors' => TRUE,
+
+ /**
+ * Custom error show function called from SimpleSAML_Error_Error::show.
+ * See docs/simplesamlphp-errorhandling.txt for function code example.
+ *
+ * Example:
+ * 'errors.show_function' => array('sspmod_example_Error_Show', 'show'),
+ */
+
+ /**
+ * This option allows you to enable validation of XML data against its
+ * schemas. A warning will be written to the log if validation fails.
+ */
+ 'debug.validatexml' => FALSE,
+
+ /**
+ * This password must be kept secret, and modified from the default value 123.
+ * This password will give access to the installation page of simpleSAMLphp with
+ * metadata listing and diagnostics pages.
+ * You can also put a hash here; run "bin/pwgen.php" to generate one.
+ */
+ 'auth.adminpassword' => 'admin',
+ 'admin.protectindexpage' => false,
+ 'admin.protectmetadata' => false,
+
+ /**
+ * This is a secret salt used by simpleSAMLphp when it needs to generate a secure hash
+ * of a value. It must be changed from its default value to a secret value. The value of
+ * 'secretsalt' can be any valid string of any length.
+ *
+ * A possible way to generate a random salt is by running the following command from a unix shell:
+ * tr -c -d '0123456789abcdefghijklmnopqrstuvwxyz' /dev/null;echo
+ */
+ 'secretsalt' => 'CHANGE_ME_for_testing_only',
+
+ /*
+ * Some information about the technical persons running this installation.
+ * The email address will be used as the recipient address for error reports, and
+ * also as the technical contact in generated metadata.
+ */
+ 'technicalcontact_name' => 'John Doe',
+ 'technicalcontact_email' => 'jdoe@stepup.example.com',
+
+ /*
+ * The timezone of the server. This option should be set to the timezone you want
+ * simpleSAMLphp to report the time in. The default is to guess the timezone based
+ * on your system timezone.
+ *
+ * See this page for a list of valid timezones: http://php.net/manual/en/timezones.php
+ */
+ 'timezone' => 'Europe/Amsterdam',
+
+ /*
+ * Logging.
+ *
+ * define the minimum log level to log
+ * SimpleSAML_Logger::ERR No statistics, only errors
+ * SimpleSAML_Logger::WARNING No statistics, only warnings/errors
+ * SimpleSAML_Logger::NOTICE Statistics and errors
+ * SimpleSAML_Logger::INFO Verbose logs
+ * SimpleSAML_Logger::DEBUG Full debug logs - not reccomended for production
+ *
+ * Choose logging handler.
+ *
+ * Options: [syslog,file,errorlog]
+ *
+ */
+ 'logging.level' => SimpleSAML\Logger::NOTICE,
+ 'logging.handler' => 'errorlog',
+
+ /*
+ * Choose which facility should be used when logging with syslog.
+ *
+ * These can be used for filtering the syslog output from simpleSAMLphp into its
+ * own file by configuring the syslog daemon.
+ *
+ * See the documentation for openlog (http://php.net/manual/en/function.openlog.php) for available
+ * facilities. Note that only LOG_USER is valid on windows.
+ *
+ * The default is to use LOG_LOCAL5 if available, and fall back to LOG_USER if not.
+ */
+ 'logging.facility' => defined('LOG_LOCAL5') ? constant('LOG_LOCAL5') : LOG_USER,
+
+ /*
+ * The process name that should be used when logging to syslog.
+ * The value is also written out by the other logging handlers.
+ */
+ 'logging.processname' => 'simplesamlphp',
+
+ /* Logging: file - Logfilename in the loggingdir from above.
+ */
+ 'logging.logfile' => 'simplesamlphp.log',
+
+ /* (New) statistics output configuration.
+ *
+ * This is an array of outputs. Each output has at least a 'class' option, which
+ * selects the output.
+ */
+ 'statistics.out' => array(
+ // Log statistics to the normal log.
+ /*
+ array(
+ 'class' => 'core:Log',
+ 'level' => 'notice',
+ ),
+ */
+ // Log statistics to files in a directory. One file per day.
+ /*
+ array(
+ 'class' => 'core:File',
+ 'directory' => '/var/log/stats',
+ ),
+ */
+ ),
+
+
+ /*
+ * Enable
+ *
+ * Which functionality in simpleSAMLphp do you want to enable. Normally you would enable only
+ * one of the functionalities below, but in some cases you could run multiple functionalities.
+ * In example when you are setting up a federation bridge.
+ */
+ 'enable.saml20-idp' => true,
+ 'enable.shib13-idp' => false,
+ 'enable.adfs-idp' => false,
+ 'enable.wsfed-sp' => false,
+ 'enable.authmemcookie' => false,
+
+ /*
+ * This value is the duration of the session in seconds. Make sure that the time duration of
+ * cookies both at the SP and the IdP exceeds this duration.
+ */
+ 'session.duration' => 8 * (60*60), // 8 hours.
+ 'session.requestcache' => 4 * (60*60), // 4 hours
+
+ /*
+ * Sets the duration, in seconds, data should be stored in the datastore. As the datastore is used for
+ * login and logout requests, thid option will control the maximum time these operations can take.
+ * The default is 4 hours (4*60*60) seconds, which should be more than enough for these operations.
+ */
+ 'session.datastore.timeout' => (4*60*60), // 4 hours
+
+ /*
+ * Sets the duration, in seconds, auth state should be stored.
+ */
+ 'session.state.timeout' => (60*60), // 1 hour
+
+ /*
+ * Option to override the default settings for the session cookie name
+ */
+ 'session.cookie.name' => 'SimpleSAMLSessionID',
+
+ /*
+ * Expiration time for the session cookie, in seconds.
+ *
+ * Defaults to 0, which means that the cookie expires when the browser is closed.
+ *
+ * Example:
+ * 'session.cookie.lifetime' => 30*60,
+ */
+ 'session.cookie.lifetime' => 0,
+
+ /*
+ * Limit the path of the cookies.
+ *
+ * Can be used to limit the path of the cookies to a specific subdirectory.
+ *
+ * Example:
+ * 'session.cookie.path' => '/simplesaml/',
+ */
+ 'session.cookie.path' => '/',
+
+ /*
+ * Cookie domain.
+ *
+ * Can be used to make the session cookie available to several domains.
+ *
+ * Example:
+ * 'session.cookie.domain' => '.example.org',
+ */
+ 'session.cookie.domain' => NULL,
+
+ /*
+ * Set the secure flag in the cookie.
+ *
+ * Set this to TRUE if the user only accesses your service
+ * through https. If the user can access the service through
+ * both http and https, this must be set to FALSE.
+ */
+ 'session.cookie.secure' => TRUE,
+
+ /*
+ * When set to FALSE fallback to transient session on session initialization
+ * failure, throw exception otherwise.
+ */
+ 'session.disable_fallback' => TRUE,
+
+ /*
+ * Enable secure POST from HTTPS to HTTP.
+ *
+ * If you have some SP's on HTTP and IdP is normally on HTTPS, this option
+ * enables secure POSTing to HTTP endpoint without warning from browser.
+ *
+ * For this to work, module.php/core/postredirect.php must be accessible
+ * also via HTTP on IdP, e.g. if your IdP is on
+ * https://idp.example.org/ssp/, then
+ * http://idp.example.org/ssp/module.php/core/postredirect.php must be accessible.
+ */
+ 'enable.http_post' => FALSE,
+
+ /*
+ * Options to override the default settings for php sessions.
+ */
+ 'session.phpsession.cookiename' => null,
+ 'session.phpsession.savepath' => null,
+ 'session.phpsession.httponly' => TRUE,
+
+ /*
+ * Option to override the default settings for the auth token cookie
+ */
+ 'session.authtoken.cookiename' => 'SimpleSAMLAuthToken',
+
+ /*
+ * Languages available, RTL languages, and what language is default
+ */
+ 'language.available' => array('en', 'nl'),
+ 'language.rtl' => array (), // array('ar','dv','fa','ur','he'),
+ 'language.default' => 'en',
+
+ /**
+ * Custom getLanguage function called from SimpleSAML_XHTML_Template::getLanguage().
+ * Function should return language code of one of the available languages or NULL.
+ * See SimpleSAML_XHTML_Template::getLanguage() source code for more info.
+ *
+ * This option can be used to implement a custom function for determining
+ * the default language for the user.
+ *
+ * Example:
+ * 'language.get_language_function' => array('sspmod_example_Template', 'getLanguage'),
+ */
+
+ /*
+ * Extra dictionary for attribute names.
+ * This can be used to define local attributes.
+ *
+ * The format of the parameter is a string with :.
+ *
+ * Specifying this option will cause us to look for modules//dictionaries/.definition.json
+ * The dictionary should look something like:
+ *
+ * {
+ * "firstattribute": {
+ * "en": "English name",
+ * "no": "Norwegian name"
+ * },
+ * "secondattribute": {
+ * "en": "English name",
+ * "no": "Norwegian name"
+ * }
+ * }
+ *
+ * Note that all attribute names in the dictionary must in lowercase.
+ *
+ * Example: 'attributes.extradictionary' => 'ourmodule:ourattributes',
+ */
+ 'attributes.extradictionary' => NULL,
+
+ /*
+ * Which theme directory should be used?
+ */
+ 'theme.use' => 'default',
+
+
+ /*
+ * Default IdP for WS-Fed.
+ */
+ 'default-wsfed-idp' => 'urn:federation:pingfederate:localhost',
+
+ /*
+ * Whether the discovery service should allow the user to save his choice of IdP.
+ */
+ 'idpdisco.enableremember' => TRUE,
+ 'idpdisco.rememberchecked' => TRUE,
+
+ // Disco service only accepts entities it knows.
+ 'idpdisco.validate' => TRUE,
+
+ 'idpdisco.extDiscoveryStorage' => NULL,
+
+ /*
+ * IdP Discovery service look configuration.
+ * Wether to display a list of idp or to display a dropdown box. For many IdP' a dropdown box
+ * gives the best use experience.
+ *
+ * When using dropdown box a cookie is used to highlight the previously chosen IdP in the dropdown.
+ * This makes it easier for the user to choose the IdP
+ *
+ * Options: [links,dropdown]
+ *
+ */
+ 'idpdisco.layout' => 'dropdown',
+
+ /*
+ * Whether simpleSAMLphp should sign the response or the assertion in SAML 1.1 authentication
+ * responses.
+ *
+ * The default is to sign the assertion element, but that can be overridden by setting this
+ * option to TRUE. It can also be overridden on a pr. SP basis by adding an option with the
+ * same name to the metadata of the SP.
+ */
+ 'shib13.signresponse' => TRUE,
+
+
+
+ /*
+ * Authentication processing filters that will be executed for all IdPs
+ * Both Shibboleth and SAML 2.0
+ */
+ 'authproc.idp' => array(
+
+ ),
+
+ /*
+ * Authentication processing filters that will be executed for all SPs
+ * Both Shibboleth and SAML 2.0
+ */
+ 'authproc.sp' => array(
+ /*
+ 10 => array(
+ 'class' => 'core:AttributeMap', 'removeurnprefix'
+ ),
+ */
+
+ /*
+ * Generate the 'group' attribute populated from other variables, including eduPersonAffiliation.
+ */
+ 60 => array('class' => 'core:GenerateGroups', 'eduPersonAffiliation'),
+ // All users will be members of 'users' and 'members'
+ 61 => array('class' => 'core:AttributeAdd', 'groups' => array('users', 'members')),
+
+ // Adopts language from attribute to use in UI
+ 90 => 'core:LanguageAdaptor',
+
+ ),
+
+
+ /*
+ * This option configures the metadata sources. The metadata sources is given as an array with
+ * different metadata sources. When searching for metadata, simpleSAMPphp will search through
+ * the array from start to end.
+ *
+ * Each element in the array is an associative array which configures the metadata source.
+ * The type of the metadata source is given by the 'type' element. For each type we have
+ * different configuration options.
+ *
+ * Flat file metadata handler:
+ * - 'type': This is always 'flatfile'.
+ * - 'directory': The directory we will load the metadata files from. The default value for
+ * this option is the value of the 'metadatadir' configuration option, or
+ * 'metadata/' if that option is unset.
+ *
+ * XML metadata handler:
+ * This metadata handler parses an XML file with either an EntityDescriptor element or an
+ * EntitiesDescriptor element. The XML file may be stored locally, or (for debugging) on a remote
+ * web server.
+ * The XML hetadata handler defines the following options:
+ * - 'type': This is always 'xml'.
+ * - 'file': Path to the XML file with the metadata.
+ * - 'url': The url to fetch metadata from. THIS IS ONLY FOR DEBUGGING - THERE IS NO CACHING OF THE RESPONSE.
+ *
+ *
+ * Examples:
+ *
+ * This example defines two flatfile sources. One is the default metadata directory, the other
+ * is a metadata directory with autogenerated metadata files.
+ *
+ * 'metadata.sources' => array(
+ * array('type' => 'flatfile'),
+ * array('type' => 'flatfile', 'directory' => 'metadata-generated'),
+ * ),
+ *
+ * This example defines a flatfile source and an XML source.
+ * 'metadata.sources' => array(
+ * array('type' => 'flatfile'),
+ * array('type' => 'xml', 'file' => 'idp.example.org-idpMeta.xml'),
+ * ),
+ *
+ *
+ * Default:
+ * 'metadata.sources' => array(
+ * array('type' => 'flatfile')
+ * ),
+ */
+ 'metadata.sources' => array(
+ array('type' => 'flatfile'),
+ ),
+
+
+ /*
+ * Configure the datastore for simpleSAMLphp.
+ *
+ * - 'phpsession': Limited datastore, which uses the PHP session.
+ * - 'memcache': Key-value datastore, based on memcache.
+ * - 'sql': SQL datastore, using PDO.
+ *
+ * The default datastore is 'phpsession'.
+ *
+ * (This option replaces the old 'session.handler'-option.)
+ */
+ //'store.type' => 'phpsession',
+ 'store.type' => 'phpsession',
+
+
+ /*
+ * The DSN the sql datastore should connect to.
+ *
+ * See http://www.php.net/manual/en/pdo.drivers.php for the various
+ * syntaxes.
+ */
+ 'store.sql.dsn' => 'sqlite:/path/to/sqlitedatabase.sq3',
+
+ /*
+ * The username and password to use when connecting to the database.
+ */
+ 'store.sql.username' => NULL,
+ 'store.sql.password' => NULL,
+
+ /*
+ * The prefix we should use on our tables.
+ */
+ 'store.sql.prefix' => 'simpleSAMLphp',
+
+
+ /*
+ * Configuration for the MemcacheStore class. This allows you to store
+ * multiple redudant copies of sessions on different memcache servers.
+ *
+ * 'memcache_store.servers' is an array of server groups. Every data
+ * item will be mirrored in every server group.
+ *
+ * Each server group is an array of servers. The data items will be
+ * load-balanced between all servers in each server group.
+ *
+ * Each server is an array of parameters for the server. The following
+ * options are available:
+ * - 'hostname': This is the hostname or ip address where the
+ * memcache server runs. This is the only required option.
+ * - 'port': This is the port number of the memcache server. If this
+ * option isn't set, then we will use the 'memcache.default_port'
+ * ini setting. This is 11211 by default.
+ * - 'weight': This sets the weight of this server in this server
+ * group. http://php.net/manual/en/function.Memcache-addServer.php
+ * contains more information about the weight option.
+ * - 'timeout': The timeout for this server. By default, the timeout
+ * is 3 seconds.
+ *
+ * Example of redudant configuration with load balancing:
+ * This configuration makes it possible to lose both servers in the
+ * a-group or both servers in the b-group without losing any sessions.
+ * Note that sessions will be lost if one server is lost from both the
+ * a-group and the b-group.
+ *
+ * 'memcache_store.servers' => array(
+ * array(
+ * array('hostname' => 'mc_a1'),
+ * array('hostname' => 'mc_a2'),
+ * ),
+ * array(
+ * array('hostname' => 'mc_b1'),
+ * array('hostname' => 'mc_b2'),
+ * ),
+ * ),
+ *
+ * Example of simple configuration with only one memcache server,
+ * running on the same computer as the web server:
+ * Note that all sessions will be lost if the memcache server crashes.
+ *
+ * 'memcache_store.servers' => array(
+ * array(
+ * array('hostname' => 'localhost'),
+ * ),
+ * ),
+ *
+ */
+ 'memcache_store.servers' => array(
+ array(
+ array('hostname' => 'localhost'),
+ ),
+ ),
+
+
+ /*
+ * This value is the duration data should be stored in memcache. Data
+ * will be dropped from the memcache servers when this time expires.
+ * The time will be reset every time the data is written to the
+ * memcache servers.
+ *
+ * This value should always be larger than the 'session.duration'
+ * option. Not doing this may result in the session being deleted from
+ * the memcache servers while it is still in use.
+ *
+ * Set this value to 0 if you don't want data to expire.
+ *
+ * Note: The oldest data will always be deleted if the memcache server
+ * runs out of storage space.
+ */
+ 'memcache_store.expires' => 36 * (60*60), // 36 hours.
+
+
+ /*
+ * Should signing of generated metadata be enabled by default.
+ *
+ * Metadata signing can also be enabled for a individual SP or IdP by setting the
+ * same option in the metadata for the SP or IdP.
+ */
+ 'metadata.sign.enable' => FALSE,
+
+ /*
+ * The default key & certificate which should be used to sign generated metadata. These
+ * are files stored in the cert dir.
+ * These values can be overridden by the options with the same names in the SP or
+ * IdP metadata.
+ *
+ * If these aren't specified here or in the metadata for the SP or IdP, then
+ * the 'certificate' and 'privatekey' option in the metadata will be used.
+ * if those aren't set, signing of metadata will fail.
+ */
+ 'metadata.sign.privatekey' => NULL,
+ 'metadata.sign.privatekey_pass' => NULL,
+ 'metadata.sign.certificate' => NULL,
+
+
+ /*
+ * Proxy to use for retrieving URLs.
+ *
+ * Example:
+ * 'proxy' => 'tcp://proxy.example.com:5100'
+ */
+ 'proxy' => NULL,
+
+);
diff --git a/docker/ssp-debug-sp/conf/nginx.conf b/docker/ssp-debug-sp/conf/nginx.conf
new file mode 100644
index 0000000..b8b0146
--- /dev/null
+++ b/docker/ssp-debug-sp/conf/nginx.conf
@@ -0,0 +1,23 @@
+server {
+ listen 443 default_server;
+
+ access_log /docker.stderr;
+ error_log /docker.stderr;
+
+ server_name _ *.vm docker;
+
+ root "/app/www";
+ index index.php;
+
+ include /opt/docker/etc/nginx/vhost.common.d/*.conf;
+ include /opt/docker/etc/nginx/vhost.ssl.conf;
+
+ location ~ \.php$ {
+ fastcgi_split_path_info ^(.+\.php)(/.+)$;
+ fastcgi_pass php;
+ fastcgi_param PATH_INFO $fastcgi_path_info;
+ include fastcgi_params;
+ fastcgi_param SCRIPT_FILENAME $request_filename;
+ fastcgi_read_timeout 600;
+ }
+}
diff --git a/docker/ssp-debug-sp/conf/saml20-idp-hosted.php b/docker/ssp-debug-sp/conf/saml20-idp-hosted.php
new file mode 100644
index 0000000..6714f90
--- /dev/null
+++ b/docker/ssp-debug-sp/conf/saml20-idp-hosted.php
@@ -0,0 +1,157 @@
+ '__DEFAULT__',
+
+ 'signature.algorithm' => 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256',
+
+ /* X.509 key and certificate. Relative to the cert directory. */
+ 'privatekey' => 'idp.key',
+ 'certificate' => 'idp.crt',
+
+ /*
+ * Authentication source to use. Must be one that is configured in
+ * 'config/authsources.php'.
+ */
+ 'auth' => 'example-userpass',
+
+
+ //'attributes.NameFormat' => 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
+ //'attributes.NameFormat' => 'urn:oasis:names:tc:SAML:2.0:attrname-format:basic',
+ 'attributes.NameFormat' => 'urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified',
+
+ // Sign logout request and logout responses
+ 'redirect.sign' => TRUE,
+
+ // Require validate signature on requests
+ 'redirect.validate' => FALSE,
+
+ // Sign response
+ 'saml20.sign.response' => FALSE,
+
+ // Sign assertion
+ 'saml20.sign.assertion' => TRUE,
+
+ // No artifact binding support
+ 'saml20.sendartifact' => FALSE,
+
+ //'signature.algorithm' => 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256',
+
+ 'attributes.NameFormat' => 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
+
+ // Use (or 'select') an unspecified NameID. The NameID is generated in the authproc below.
+ // This is the NameID that will be but in the Subject of the SAML Assertion
+ 'NameIDFormat' => 'urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified',
+
+ // Authproc to make the output of this IdP sufficiently like OpenConext to allow
+ // OpenConext Stepup to work.
+ // The configured authsource must provide the required attributes.
+ // Required is an "NameID" attribute. This will be used both in the Subject and in the "eduPersonTargetedID"
+ //
+ 'authproc' => array(
+
+ // Generate an unspecified NameID for use by this IdP
+ // Note that this NameID won't be used until it is "selected" in the saml20-idp-hosted.php by adding:
+ // 'NameIDFormat' => 'urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified',
+ //
+ // Use the value of the "NameID" attribute from the authsource as value for the NameID
+ 1 => array(
+ 'class' => 'saml:AttributeNameID',
+ 'attribute' => 'NameID',
+ 'Format' => 'urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified',
+
+ // Don't add NameQualifier and SPNameQualifier attributes to the generated NameID
+ 'NameQualifier' => FALSE,
+ 'SPNameQualifier' => FALSE,
+ ),
+
+ // Copy the NameID to the eduPersonTargetedID attribute
+ // Note that this will generate a eduPersonTargetedID with a PERSISTENT targeted NameID
+ //
+ // This will not work when the RA and Selfservice are behind the Stepup Gateway
+ // Using this might be useful to test the Stepup Gateway NameID passing behaviour
+ //
+ // When the Stepup Selfservice and RA are behind the Stepup Gateway the NameID in the Subject
+ // and the NameID in the eduPersonTargetedID must match so that the Stepup Gatway will pass it to
+ // the SelfService and RA applications. An eduPersonTargetedID with an UNSPECIFIED NameID
+ // (For OpenConext urn:collab:person:etc..) is non standard.
+ //
+ // If you enable this (2) rule you will want to disable the custom (3) rule below as it overwrites the
+ // eduPersonTargetedID generated by this rule.
+ /*
+ 2 => array(
+ 'class' => 'core:TargetedID', // Generate a eduPersonTargetedID attribute
+ 'attribute' => 'NameID',
+ 'nameId' => TRUE, // Use the "Nested" NameID format
+ // Don't add NameQualifier and SPNameQualifier attributes to the generated NameID
+ 'NameQualifier' => FALSE,
+ 'SPNameQualifier' => FALSE,
+ ),
+ */
+
+ // Create an eduPersonTargetedID attribute with an unspecified NameID with the value
+ // of the "NameID" attribute from the authsource.
+ 3 => array(
+ 'class' => 'core:PHP',
+ 'code' =>
+ '
+ $nameId = new \SAML2\XML\saml\NameID();
+ $nameId->value = $attributes["NameID"][0]; // Use value of "NameID" attribute
+ $nameId->Format = \SAML2\Constants::NAMEID_UNSPECIFIED; // Unspecified NameID
+ //$nameId->NameQualifier = "...";
+ //$nameId->SPNameQualifier = "...";
+ $doc = \SAML2\DOMDocumentFactory::create();
+ $root = $doc->createElement("root");
+ $doc->appendChild($root);
+ $nameId->toXML($root);
+ $eduPersonTargetedID = $doc->saveXML($root->firstChild);
+ $attributes["eduPersonTargetedID"] = array($eduPersonTargetedID);
+ ',
+ ),
+
+ // Remove the NameID attribute to prevent any confusion, it was only there to specify the NameID
+ // to use in the Subject and eduPersonTargetedID attribute
+ 4 => array(
+ 'class' => 'core:AttributeAlter',
+ 'subject' => 'NameID',
+ 'pattern' => '/.*/',
+ '%remove',
+ ),
+
+ // Convert "short" atribute names (uid, mail, eduPersonTargetedID, ...) to their long urn:mace...
+ // equivalent
+ 10 => array(
+ 'class' => 'core:AttributeMap',
+ 'SURFconext_short_to_urn'
+ ),
+
+ ),
+
+ // Required because the eduPersonTargetedID is a "complex" attribute and not a simple string value.
+ 'attributeencodings' => array(
+ 'urn:mace:dir:attribute-def:eduPersonTargetedID' => 'raw'
+ ),
+
+);
+
+if ( isset($_COOKIE['testcookie']) ) {
+ $metadata['https://ssp.stepup.example.com/saml2/idp/metadata.php']['publickey'] = '/vagrant/deploy/tests/behat/fixtures/test_public_key.crt';
+ $metadata['https://ssp.stepup.example.com/saml2/idp/metadata.php']['privatekey'] = '/vagrant/deploy/tests/behat/fixtures/test_private_key.key';
+}
diff --git a/docker/ssp-debug-sp/conf/saml20-idp-remote.php b/docker/ssp-debug-sp/conf/saml20-idp-remote.php
new file mode 100644
index 0000000..d8e5ef4
--- /dev/null
+++ b/docker/ssp-debug-sp/conf/saml20-idp-remote.php
@@ -0,0 +1,138 @@
+ 'https://ssp.stepup.example.com/saml2/idp/metadata.php',
+ 'signature.algorithm' => 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256',
+ 'certificate' => 'idp.crt',
+ 'SingleSignOnService' =>
+ array (
+ 0 =>
+ array (
+ 'Binding' => $GLOBALS['gSP_SSOBinding'],
+ 'Location' => 'https://ssp.stepup.example.com/saml2/idp/SSOService.php',
+ ),
+ ),
+ 'ArtifactResolutionService' =>
+ array (
+ 0 =>
+ array (
+ 'index' => 0,
+ 'Location' => 'https://ssp.stepup.example.com/saml2/idp/ArtifactResolutionService.php',
+ 'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:SOAP',
+ ),
+ ),
+ 'name' => array(
+ 'en' => 'ssp.stepup.example.com - SSP Test IdP',
+ 'nl' => 'ssp.stepup.example.com - SSP Test IdP',
+ ),
+
+);
+
+
+////////////////////////////////////////////////////////////////////////////
+// The metadata of the OpenConext Stepup IdP, for use by the hosted SPs
+
+$metadata['https://gateway.stepup.example.com/authentication/metadata'] = array (
+ 'entityid' => 'https://gateway.stepup.example.com/authentication/metadata',
+ //'signature.algorithm' => 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256',
+ 'contacts' =>
+ array (
+ ),
+ 'metadata-set' => 'saml20-idp-remote',
+ 'SingleSignOnService' =>
+ array (
+ 0 =>
+ array (
+ 'Binding' => $GLOBALS['gSP_SSOBinding'],
+ 'Location' => 'https://gateway.stepup.example.com/authentication/single-sign-on',
+ ),
+ ),
+ 'SingleLogoutService' =>
+ array (
+ ),
+ 'ArtifactResolutionService' =>
+ array (
+ ),
+ 'keys' =>
+ array (
+ 0 =>
+ array (
+ 'encryption' => false,
+ 'signing' => true,
+ 'type' => 'X509Certificate',
+ 'X509Certificate' => '{{ gateway_saml_idp_publickey | depem }}',
+ ),
+ ),
+);
+
+if ( isset($_COOKIE['testcookie']) ) {
+ $metadata['https://gateway.stepup.example.com/authentication/metadata']['keys'][0]['X509Certificate'] = depem(file_get_contents('/vagrant/deploy/tests/behat/fixtures/test_public_key.crt'));
+}
+
+////////////////////////////////////////////////////////////////////////////
+// The metadata of the OpenConext Stepup IdP - SFO, for use by the hosted SPs
+
+$metadata['https://gateway.stepup.example.com/second-factor-only/metadata'] = array (
+ 'entityid' => 'https://gateway.stepup.example.com/second-factor-only/metadata',
+ //'signature.algorithm' => 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256',
+ 'contacts' =>
+ array (
+ ),
+ 'metadata-set' => 'saml20-idp-remote',
+ 'SingleSignOnService' =>
+ array (
+ 0 =>
+ array (
+ 'Binding' => $GLOBALS['gSP_SSOBinding'],
+ 'Location' => 'https://gateway.stepup.example.com/second-factor-only/single-sign-on',
+ ),
+ ),
+ 'SingleLogoutService' =>
+ array (
+ ),
+ 'ArtifactResolutionService' =>
+ array (
+ ),
+ 'keys' =>
+ array (
+ 0 =>
+ array (
+ 'encryption' => false,
+ 'signing' => true,
+ 'type' => 'X509Certificate',
+ 'X509Certificate' => '{{ gateway_saml_idp_publickey | depem }}',
+ ),
+ ),
+);
+
+if ( isset($_COOKIE['testcookie']) ) {
+ $metadata['https://gateway.stepup.example.com/second-factor-only/metadata']['keys'][0]['X509Certificate'] = depem(file_get_contents('/vagrant/deploy/tests/behat/fixtures/test_public_key.crt'));
+}
+
+/**
+ * Remove the spicing from the certificate, this is a php port of the python (keyczar) implementation that is used
+ * in the ninja templates ( return re.sub(r'\s+|(-----(BEGIN|END).*-----)', '', string) )
+ */
+function depem($input)
+{
+ return str_replace([
+ '-----BEGIN CERTIFICATE-----',
+ '-----END CERTIFICATE-----',
+ "\r\n",
+ "\n",
+ ], [
+ '',
+ '',
+ "\n",
+ ''
+ ], $input);
+}
diff --git a/docker/ssp-debug-sp/conf/saml20-sp-remote.php b/docker/ssp-debug-sp/conf/saml20-sp-remote.php
new file mode 100644
index 0000000..d15fb6b
--- /dev/null
+++ b/docker/ssp-debug-sp/conf/saml20-sp-remote.php
@@ -0,0 +1,47 @@
+
+ array (
+ 0 =>
+ array (
+ 'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
+ 'Location' => 'https://ssp.stepup.example.com/module.php/saml/sp/saml2-acs.php/default-sp',
+ 'index' => 0,
+ ),
+ ),
+ 'SingleLogoutService' =>
+ array (
+ 0 =>
+ array (
+ 'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
+ 'Location' => 'https://ssp.stepup.example.com/module.php/saml/sp/saml2-logout.php/default-sp',
+ ),
+ ),
+ 'certificate' => 'sp.crt'
+);
+
+
+///////////////////////////////////////////////////////////////////////////////////
+// Stepup Gateway in it's SP role
+
+$metadata['https://gateway.stepup.example.com/authentication/metadata'] = array(
+ 'AssertionConsumerService' =>
+ array (
+ 0 =>
+ array (
+ 'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
+ 'Location' => 'https://gateway.stepup.example.com/authentication/consume-assertion',
+ 'index' => 0,
+ ),
+ ),
+ 'certificate' => '{{ gateway_saml_sp_publickey | depem }}'
+);
diff --git a/docker/ssp-debug-sp/conf/sp-config.inc b/docker/ssp-debug-sp/conf/sp-config.inc
new file mode 100644
index 0000000..87d7eef
--- /dev/null
+++ b/docker/ssp-debug-sp/conf/sp-config.inc
@@ -0,0 +1,48 @@
+ array(
+ 'name' => 'Displayname of the IdP in the SP interface',
+ 'loa' => array(
+ 1 => 'AuthnContextClassRef for loa 1',
+ 2 => 'AuthnContextClassRef for loa 2',
+ 3 => 'AuthnContextClassRef for loa 3',
+ ),
+ )
+ */
+ 'https://gateway.stepup.example.com/authentication/metadata' => array(
+ 'name' => 'OpenConext Stepup Gateway - gateway.stepup.example.com',
+ 'loa' => array(
+ '1.5' => 'http://stepup.example.com/assurance/loa-self-asserted',
+ 1 => 'http://stepup.example.com/assurance/level1',
+ 2 => 'http://stepup.example.com/assurance/level2',
+ 3 => 'http://stepup.example.com/assurance/level3',
+ ),
+ ),
+ 'https://gateway.stepup.example.com/second-factor-only/metadata' => array(
+ 'name' => 'OpenConext Stepup Gateway - gateway.stepup.example.com - SFO',
+ 'loa' => array(
+ '1.5'=> 'http://stepup.example.com/assurance/loa-self-asserted',
+ 1 => 'http://no.level.1.for.sfo.example.com/assurance/sfo-level1', // Note does not exist
+ 2 => 'http://stepup.example.com/assurance/sfo-level2',
+ 3 => 'http://stepup.example.com/assurance/sfo-level3',
+ ),
+ ),
+ 'https://ssp.stepup.example.com/saml2/idp/metadata.php' => array(
+ 'name' => 'Local SSP IdP - ssp.stepup.example.com',
+ 'loa' => array(
+ '1.5' => '',
+ 1 => '',
+ 2 => '',
+ 3 => '',
+ ),
+ ),
+);
diff --git a/docker/ssp-debug-sp/conf/sp-utils.inc b/docker/ssp-debug-sp/conf/sp-utils.inc
new file mode 100644
index 0000000..881cea2
--- /dev/null
+++ b/docker/ssp-debug-sp/conf/sp-utils.inc
@@ -0,0 +1,172 @@
+ 0){
+ $m = $l + $l - $v;
+ $sv = ($v - $m ) / $v;
+ $h *= 6.0;
+ $sextant = floor($h);
+ $fract = $h - $sextant;
+ $vsf = $v * $sv * $fract;
+ $mid1 = $m + $vsf;
+ $mid2 = $v - $vsf;
+ switch ($sextant) {
+ case 0:
+ $r = $v; $g = $mid1; $b = $m;
+ break;
+ case 1:
+ $r = $mid2; $g = $v; $b = $m;
+ break;
+ case 2:
+ $r = $m; $g = $v; $b = $mid1;
+ break;
+ case 3:
+ $r = $m; $g = $mid2; $b = $v;
+ break;
+ case 4:
+ $r = $mid1; $g = $m; $b = $v;
+ break;
+ case 5:
+ $r = $v; $g = $m; $b = $mid2;
+ break;
+ }
+ }
+ // Convert from RGB values (0 .. 1) to hex (00 .. FF)
+ $color='#' .str_pad(dechex($r*256),2,'0',STR_PAD_LEFT)
+ .str_pad(dechex($g*256),2,'0',STR_PAD_LEFT)
+ .str_pad(dechex($b*256),2,'0',STR_PAD_LEFT);
+ return $color;
+}
+
+
+function XMLTextNode2HTML_TS($domnode)
+{
+ if (!is_null($domnode) && isset($domnode[0])) {
+ $time = SimpleSAML_Utilities::parseSAML2Time($domnode[0]->textContent);
+ $offset = $time - time();
+ $str = ''.gmdate('r', $time).'';
+ $str .= ' (now '. (($offset>0) ? '+':'') . round(($offset/60)) . ' minutes)';
+ return $str;
+ }
+
+ return 'N/A';
+}
+
+
+function AttributeNameToHTML($attribute) {
+ static $oidToName = array(
+ 'urn:oid:1.3.6.1.4.1.1076.20.40.40.1' => 'collabPersonId, Deprecated!',
+ 'urn:oid:1.3.6.1.4.1.5923.1.1.1.10' => 'urn:mace:dir:attribute-def:eduPersonTargetedID',
+ 'urn:oid:2.5.4.4' => 'urn:mace:dir:attribute-def:sn',
+ 'urn:oid:2.5.4.42' => 'urn:mace:dir:attribute-def:givenName',
+ 'urn:oid:2.5.4.3' => 'urn:mace:dir:attribute-def:cn',
+ 'urn:oid:2.16.840.1.113730.3.1.241' => 'urn:mace:dir:attribute-def:displayName',
+ 'urn:oid:0.9.2342.19200300.100.1.3' => 'urn:mace:dir:attribute-def:mail',
+ 'urn:oid:1.3.6.1.4.1.25178.1.2.9' => 'urn:mace:terena.org:attribute-def:schacHomeOrganization',
+ 'urn:oid:1.3.6.1.4.1.25178.1.2.10' => 'urn:mace:terena.org:attribute-def:schacHomeOrganizationType',
+ 'urn:oid:1.3.6.1.4.1.25178.1.2.14' => 'urn:schac:attribute-def:schacPersonalUniqueCode',
+ 'urn:oid:1.3.6.1.4.1.5923.1.1.1.1' => 'urn:mace:dir:attribute-def:eduPersonAffiliation',
+ 'urn:oid:1.3.6.1.4.1.5923.1.1.1.9' => 'urn:mace:dir:attribute-def:eduPersonScopedAffiliation',
+ 'urn:oid:1.3.6.1.4.1.5923.1.1.1.7' => 'urn:mace:dir:attribute-def:eduPersonEntitlement',
+ 'urn:oid:1.3.6.1.4.1.5923.1.1.1.6' => 'urn:mace:dir:attribute-def:eduPersonPrincipalName',
+ 'urn:oid:1.3.6.1.4.1.5923.1.5.1.1' => 'urn:mace:dir:attribute-def:isMemberOf',
+ 'urn:oid:0.9.2342.19200300.100.1.1' => 'urn:mace:dir:attribute-def:uid',
+ 'urn:oid:2.16.840.1.113730.3.1.39' => 'urn:mace:dir:attribute-def:preferredLanguage',
+ 'urn:oid:1.3.6.1.4.1.5923.1.1.1.16' => 'urn:mace:dir:attribute-def:eduPersonORCID',
+ 'urn:oid:1.3.6.1.4.1.1466.115.121.1.15' => 'Directory String (RFC 4517), Error!'
+ );
+
+ static $error = array(
+ 'urn:oid:1.3.6.1.4.1.1076.20.40.40.1', // collabPersonId (deprecated)
+ 'urn:oid:1.3.6.1.4.1.1466.115.121.1.15' // This is an LDAP string type, not an attribute. This was mistakenly used by SURFconext instead of urn:oid:1.3.6.1.4.1.25178.1.2.9 (schacHomeOrganization)
+ );
+ if (in_array($attribute, $error))
+ $color="style='color: red'";
+ if (isset($oidToName[$attribute])) {
+ $title=$oidToName[$attribute];
+ return "".htmlentities($attribute)."";
+ }
+
+ return htmlentities($attribute);
+}
+
+
+function XMLTextNode2HTML($domnode)
+{
+ if (!is_null($domnode) && isset($domnode[0])) {
+ return ''.htmlentities($domnode[0]->textContent).'';
+ }
+
+ return 'N/A';
+}
+
+
+function HTML_select($label, $id, $options, $value="", $info="")
+{
+ $label=htmlentities($label);
+ $id=htmlentities($id);
+ $value=htmlentities($value);
+ echo "";
+}
+
+
+function NameIDArrayToHTML($nameID, $compact=false)
+{
+ foreach ($nameID as $key => $value) {
+ $k = htmlentities($key);
+ $v = htmlentities($value);
+ $color='';
+ if ($k == 'Value') {
+ $color=HTMLColorFingerprint($v);
+ }
+ $labelstyle='';
+ if ($compact)
+ $labelstyle="style='width: 60px; clear: both'";
+ echo "{$v} ";
+ }
+}
\ No newline at end of file
diff --git a/docker/ssp-debug-sp/conf/sp.php b/docker/ssp-debug-sp/conf/sp.php
new file mode 100644
index 0000000..199ab37
--- /dev/null
+++ b/docker/ssp-debug-sp/conf/sp.php
@@ -0,0 +1,589 @@
+isAuthenticated();
+
+// Build return URL. This is where ask simplesamlPHP to direct the browser to after login or logout
+// Point to this script, but without any request parameters so we won't trigger an login again (and again, and again, and ...)
+$returnURL = ($_SERVER['HTTPS'] == 'on') ? 'https://' : 'http://';
+$returnURL .= $_SERVER['HTTP_HOST'];
+$returnURL .= $_SERVER['SCRIPT_NAME'];
+$returnURL .= '?sp='.urlencode($sp);
+
+// Process login and logout actions. Neither login nor logout return
+if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'login' ) {
+
+ // Save submitted form in session
+ $params_to_save=$_REQUEST;
+ unset($params_to_save['action']);
+ $session->setData('array', 'SSP_DEMO_SP_FORM_DATA', $params_to_save);
+
+ // Unset existing RequiredAuthnContextClassRef first
+ $session->deleteData('string', 'RequiredAuthnContextClassRef');
+ $bForceAuthn = false;
+ if ( (isset($_REQUEST['forceauthn'])) && ($_REQUEST['forceauthn'] == 'true') )
+ $bForceAuthn = true;
+
+ // For use by SAML2Keeper callback function
+ $session->setData('string', 'SAML2Keeper_ReturnTo', $returnURL);
+
+ $context = array(
+ 'ReturnTo' => $returnURL,
+ 'ReturnCallback' => array('sspmod_saml2keeper_SAML2Keeper','loginCallback'),
+ 'ForceAuthn' => $bForceAuthn,
+ 'saml:NameIDPolicy' => null,
+ );
+
+ // IdP
+ if ( (isset($_REQUEST['idp'])) ) {
+ $context['saml:idp'] = $_REQUEST['idp'];
+ }
+
+ // LOA
+ if ( isset($_REQUEST['loa']) && isset($_REQUEST['idp']) && isset($gIDPmap[$_REQUEST['idp']]['loa'][$_REQUEST['loa']]) ) {
+ $loa = $gIDPmap[$_REQUEST['idp']]['loa'][$_REQUEST['loa']];
+ // Store the requested LOA in the session so we can verify it later
+ $session->setData('string', 'RequiredAuthnContextClassRef', $loa);
+ $context['saml:AuthnContextClassRef'] = $loa; // Specify LOA
+ }
+
+ // Scoping IdPList
+ if ( isset($_REQUEST['scopingIDP']) && strlen($_REQUEST['scopingIDP']) > 0 ) {
+ $context['saml:IDPList'] = array($_REQUEST['scopingIDP']);
+
+ if ( isset($_REQUEST['scopingIDP2']) && strlen($_REQUEST['scopingIDP2']) > 0 ) {
+ $context['saml:IDPList'][]=$_REQUEST['scopingIDP2'];
+ }
+ }
+
+ // RequesterID
+ if ( isset($_REQUEST['requesterid']) && strlen($_REQUEST['requesterid']) > 0 ) {
+ $context['saml:RequesterID'] = array($_REQUEST['requesterid']);
+
+ if ( isset($_REQUEST['requesterid2']) && strlen($_REQUEST['requesterid2']) > 0 ) {
+ $context['saml:RequesterID'][] = $_REQUEST['requesterid2'];
+ }
+ }
+
+ // NameIDPolicy
+ if ( isset($_REQUEST['nameidpolicy']) && strlen($_REQUEST['nameidpolicy']) > 0 ) {
+ $context['saml:NameIDPolicy'] = $_REQUEST['nameidpolicy'];
+ }
+
+ // Subject NameID
+ if ( isset($_REQUEST['subject']) && strlen($_REQUEST['subject']) > 0 ) {
+ $context['saml:NameID'] = array(
+ 'Value' => $_REQUEST['subject'],
+ 'Format' => SAML2_Const::NAMEID_UNSPECIFIED
+ );
+ }
+
+ // AssertionConsumerServiceURL
+ if ( isset($_REQUEST['acsurl']) && strlen($_REQUEST['acsurl']) > 0 ) {
+ $context['DebugSP:AssertionConsumerServiceURL'] = $_REQUEST['acsurl'];
+ }
+
+ // Emulate ADFS
+ if ( (isset($_REQUEST['emulateadfs'])) && ($_REQUEST['emulateadfs'] == 'true') )
+ {
+ $context['DebugSP:extraPOSTvars'] = array(
+ 'AuthMethod' => 'ADFS.SCSA',
+ 'Context' => '1C63828278F1B0AC2FE61429E099FFA7AC94917CQe1t1xgG78zLHhUxBXm0ous4yl0zfQumsKI79lrHMOIjdTdeF/i1Yx+pQ+mgnubT9mh+DfBYMs7wU1g+eXiAs2gnwKWmnMzeuxgG+m5Nky5Wd63NcEgLZ2zNTYuW70X514HMtLAw+l1H8cptQMXfXt9ageHOdY+65eq4IsNwnB0mPhRkua58R9xO3I4MfBzy90GqwgjmDeZAo5vsKgk0iZRgZ1CS4hPyIWX+ryU2tnYp5UEuDE9gGlR9cQr2uHW10LOG22ZfEy8rJie2T2A2bCQVyF47nmBnvoKYV6YyEDpozSYJpUqHmIgvaWgFu5dvDvZ0fvrVQaQ1ZUKHTT76Cg==6SO/qvyH0bmayeNGyzqAy/Oim2UAOvhxm18rTs+72Qm2fSK6Pfo1ZEDNKmLRk6IemCvkUYWMa4VmxIdATswREx/aSrp4YS3QejDBoZlCwz4LqFWJMiqTPxJfWhahP0hBNEORN8cU5vBQXXIahWqlkaHzs6IPjH4WoMe5vsSKVTetaOMbMC3ZML67BWpAnEXKWoR/gar1jH5v961ljdKJozzgwsJIAY4TNSoB+AEzRd4C3wLSTCott1DyRtMmEmS5DpaDOaxmZ/X+z16t1hb9VKgEqt1xZJ0uw451d5oeuisN9zSqbWQzyiJdkk6k11YU9q2rvg342qLJk6xeTtRc6+DLQ24vZIHC8RU2jcHveLDJvOq89BBJ0LHtnV/7PJpb4PGf1OUqWZidnRAS0/dqprEVzPEnvdzIJ8vPRGzE0dkQhgzDi+cbMsuZrDqYWaMuodvDbGrETxZ9hu0MI3l9pgjuIh8xF7TT/6qTJnGExRaGFebcjMXC99thZ3A7XeJESDNXNxgDgFQf6OwHLjLuhw==va+cZ6Y7NIyBU9vCVb+qRGSx0Yk=DNF3KVEb8ju/T+ise1j0QBS2OYsepwzgWaUtOASvUPI6NPlvyQIHxX1Py6oHcUkbWP1jaVTzwEGadaq428nPMWSeU/MDWqyz2jyrwuIUWglc64AMlcXd0BOdT1I6khKMsUGY8CSa1tRD2arcIH1TUrrk7jY3qfAGtgNbFlElPwc/2l4dkN7QXdHRcmntFp4D/9yEG9FkWzTyXLvCvGqcQeu8L1fKTwq8Upqk9iT2PKnmT/gH+IUt3votmCMV9bxYols0aQWfv2RX2HX3Gow9xKZuOn+ckjZRqBJ1Kp9wGMAB65XQPli5UQzezEHX28oUPH/PEgnu6RKDgsN55h22ag==DB540D051F8F73EA2F3B5190BFC0F349E595EB34 SAMLRequest: PHNhbWwycDpBdXRoblJlcXVlc3QgeG1sbnM6c2FtbDJwPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6cHJvdG9jb2wiIHhtbG5zOnNhbWwyPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIiBJRD0iXzkwZWFkMWNlLTM3NmMtNGE1ZC05ODAzLWQ5Y2M4MDA2M2Q0ZiIgVmVyc2lvbj0iMi4wIiBJc3N1ZUluc3RhbnQ9IjIwMTgtMDQtMjNUMTM6NDk6NTBaIiBEZXN0aW5hdGlvbj0iaHR0cHM6Ly9zYS1ndy50ZXN0Mi5zdXJmY29uZXh0Lm5sL3NlY29uZC1mYWN0b3Itb25seS9zaW5nbGUtc2lnbi1vbiIgQXNzZXJ0aW9uQ29uc3VtZXJTZXJ2aWNlVVJMPSJodHRwczovL2FkZnMtMjAxMi50ZXN0Mi5zdXJmY29uZXh0Lm5sOjQ0My9hZGZzL2xzLz9TQU1MUmVxdWVzdD1wVkpOanhNeERQMHJvOXpubzVscFlhTzJVdGtLVVdtQmFsczRjRUZ1eGtNalpaSWhkbUQ1OTZRcGlJVkRMNXdTUGZzOVB6OTVTVERhU1cwaW45MGpmbzFJWER5TjFwSEtoWldJd1NrUFpFZzVHSkVVYTNYWXZIMVFzbXJVRkR4NzdhMTRScm5OQUNJTWJMd1R4VzY3RXAlMkZiMmVtdTBYTG90SnpMUmklMkJHV1R1SHJwJTJGTCUyQlFKMXYyaFBKOTNjZFMwTUlJcVBHQ2d4VnlJSkpUcFJ4SjBqQnNjSmFtWXZ5NllyWlh1Y3RhcGJxUGJGSjFGczB6YkdBV2ZXbVhraVZkZlFEMVNtZmxseEtzdUtZaGkwZCUyRmpFbGJPNVdsdXFSYkg1YmZYZU80b2poZ09HYjBiamg4ZUhQMktUUWNaUUFaaXM0ekNMa0Jrbml6bkE4MVNQdm84V3E4djNBdFYwZldVSm1qTGE0d0RSY2ttVEtQYSUyRkluMWxYRyUyRmNsOXRwbnE1TnBONGNqJTJGdHklMkYlMkY1d0ZPdmxSVnZsZE1MNlAyMk95TkFEd3o4dWwlMkZYekdjdnJCYjFMN25iYnZiZEclMkZ5aGUlMkJ6QUMzelolMkZRVXhmRHJsVmNRQkhCaDJuNEszMTMlMkI4REF1TktjSWdvNnZWMTVOOTN1djRKJmFtcDtSZWxheVN0YXRlPWh0dHBzJTNBJTJGJTJGcGlldGVyLmFhaS5zdXJmbmV0Lm5sJTJGc2ltcGxlc2FtbHBocCUyRnNwLnBocCUzRnNwJTNEZGVmYXVsdC1zcCZhbXA7U2lnQWxnPWh0dHAlM0ElMkYlMkZ3d3cudzMub3JnJTJGMjAwMSUyRjA0JTJGeG1sZHNpZy1tb3JlJTIzcnNhLXNoYTI1NiZhbXA7U2lnbmF0dXJlPUt6TzhYV0liVTZGdUVWZVZ4RFlNZzJ1T2xoZTlBQVAwd09uWlZVM3RVMU1ibWNKUDlXa3Q1Z0R3a2RKcXhDbUlJWGVDdnBhNDVLWUdlTzNFNWppampSOHlMUFpTalJUalJRem81V2h5bzJTaXRjTkxOZzZ4WFdZY0Z6bmdIcEdKeGRyJTJGVmxjSTR0RXFUNFZSN0VwbXp3amJtd1RaRGMyOW9hdEtZRGNUUjBjTjh2M0VtMVRIR0ZOc1B0bERvRVd5c0laWjFONkRpRVAxYmE4aTE5OVhoRiUyQldXZzVzNHdqMXltMnBDendQelJkYyUyRmpreDRQcG1MTyUyQjNVY3R3amoySG5RNmNiJTJCeHBsJTJCJTJCVUFwalZ1a3ZlNWdiempMbzI4JTJCUGklMkZXQmJ0Ym0lMkZrMzE5UlZ2dWFEdVVvJTJGM3VTUU1BJTJCbHR6b0ZIOGEwRTJ0Q0pNVGg1TWRnUm10ZyUzRCUzRCI+DQogIDxzYW1sMjpJc3N1ZXI+aHR0cDovL2FkZnMtMjAxMi50ZXN0Mi5zdXJmY29uZXh0Lm5sPC9zYW1sMjpJc3N1ZXI+PFNpZ25hdHVyZSB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnIyI+PFNpZ25lZEluZm8+PENhbm9uaWNhbGl6YXRpb25NZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzEwL3htbC1leGMtYzE0biMiIC8+PFNpZ25hdHVyZU1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1sZHNpZy1tb3JlI3JzYS1zaGEyNTYiIC8+PFJlZmVyZW5jZSBVUkk9IiNfOTBlYWQxY2UtMzc2Yy00YTVkLTk4MDMtZDljYzgwMDYzZDRmIj48VHJhbnNmb3Jtcz48VHJhbnNmb3JtIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnI2VudmVsb3BlZC1zaWduYXR1cmUiIC8+PFRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyIgLz48L1RyYW5zZm9ybXM+PERpZ2VzdE1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1sZW5jI3NoYTI1NiIgLz48RGlnZXN0VmFsdWU+Q2ZKV1hpTXJLU0g0b3pPVWZTL0VNOXBXbFRSc3p2QkpMN2Y3MUZrZ3ZCbz08L0RpZ2VzdFZhbHVlPjwvUmVmZXJlbmNlPjwvU2lnbmVkSW5mbz48U2lnbmF0dXJlVmFsdWU+YzFqakFhdnVjMi9TSHZQYzdJdktJVkRSZUZuZVAzbTlITkZzTzErZEx2bWhxUXl5NkhoN3ZRMlFJalVGb2FybkYxZnJpOUY1RlNxL2JsR1I4RENvNEpndUlxKzNnRXBjN1JYR2EyTWc4dE5CV2tWdUg2UnZBTGM1Qk5DSDNtODVTTHgwcklGbERWc0tzZi9IQ0lTc2taV3Z6VVJGVVRFZnZjRVljWjZZZjNXYURmK1YvbE5jYXpCeVQ0L3RmNVVFN0VIM1JYckc2dUFqbHhjekN4a09UUE1SMnIvNmxwaEF1UmIxcjY1bThYQXFZNVFnbG5SVXBOM3U3ZEt4bGN5VUVaY2xKTW5JN21ya2NyMUdwODV6allkK0N4TmFwanNEQXplVjdSSVNLdHNaY0NFYWhncStIdTZVOEtBUmZHZmdFQ1dZNGY0c2lWRGp2d0NVaTlUME13PT08L1NpZ25hdHVyZVZhbHVlPjxLZXlJbmZvPjxYNTA5RGF0YT48WDUwOUNlcnRpZmljYXRlPk1JSURFekNDQWZ1Z0F3SUJBZ0lRU044elc2Q1lsSUpPQUZ6ZFN0VFQrakFOQmdrcWhraUc5dzBCQVFzRkFEQXNNU293S0FZRFZRUUREQ0Z6YVdkdWFXNW5MbVF5TURFeUxuUmxjM1F5TG5OMWNtWmpiMjVsZUhRdWJtd3dIaGNOTVRjd09USTBNVFl6TkRFM1doY05Nakl3T1RJMU1UWXpOREUzV2pBc01Tb3dLQVlEVlFRRERDRnphV2R1YVc1bkxtUXlNREV5TG5SbGMzUXlMbk4xY21aamIyNWxlSFF1Ym13d2dnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUUNkL1RXMUpvY05PV2w1aUZsN1JrWTQwa1A1U2NpQllCNnRJRXl3ZmxGNHRrRUR3S1Jxc1EyRXNaOTN1aWdnQi9wWFVhNlRHdlM3dnpRalJxZGhGZ0Nwb2htaGVwUzlQd3UvL0krcDY4VlpDdHNsdDFVSkd0NjJBRk9ad2FUU1FQbjRlR2RoRHI0c1g5TXIrdVVPU1plZWlEdHVFaGlNSWprZDJJYWJPeVNkOUxTK05Nc29pY1NoWEd5MERZR05yN2gyaHl1L2xUK3VMSnZsUFJ0V29aNDdpS1kwVUdpcVNJN013WlNQQjBoT2p5ZW9wbCsvWExENGhEKzNWVUFDMkttSDZaTzBBYWErc1JRZStNVFlVNHZvN29YTitkaEZoOG9VcFFrNjN4MjBtYTE1N3RSU1lqQlVwTURkclMvdk4vNWQ3c21URnQ1dFV4dlVHTGNGR0E4SkFnTUJBQUdqTVRBdk1BNEdBMVVkRHdFQi93UUVBd0lIZ0RBZEJnTlZIUTRFRmdRVUZ2ZzR3d3ByTDBlWi9ZL09zSDkyVDMrK3RsVXdEUVlKS29aSWh2Y05BUUVMQlFBRGdnRUJBRXEvQ2p5N2J0THFmWnp4dlZwUEJYZnVmYk5RSHJBeFY1QnA2a0QyY0NYUzlWQ0swdUdKdkZsemRVMDNDTE9uME4xYTJBUU5JSmZPZVg2dXlTQ1F1WXE0aDRWeUxVSVUyWE1QS1V3OGF2cWhuM0pxbGx4WUJuOE9XdENiRS9BWTdLU2lMWHk5V1BYcHRhdFpyeTV4T0x1SzYxZCtsSzJrdTlVc2xVcTY5b3BIZHhNZ3VqV0EvOUV1SkRINEVEblJ0c0lDT1oyZmxibEllQng4VU5zemExWjJ3NlIxUmtWQVN3YVZDL3JXOVpJaXhkTjdyQzUxQU1qU2YzUnBUc0cvT1Y2blNFcHJNa2hVWWRoSFdSb09XZk8rUGJmZGE1Sm85SHMyeHZENE43L2hPSjQzdC8wV0o1bng3NkNxMTNHcGlFYmlIbXZIQU1jS3R4aHVBS2M4NEk0PTwvWDUwOUNlcnRpZmljYXRlPjwvWDUwOURhdGE+PC9LZXlJbmZvPjwvU2lnbmF0dXJlPg0KICA8c2FtbDI6U3ViamVjdD4NCiAgICA8c2FtbDI6TmFtZUlEIEZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6MS4xOm5hbWVpZC1mb3JtYXQ6dW5zcGVjaWZpZWQiPnVybjpjb2xsYWI6cGVyc29uOmluc3RpdHV0aW9uLWEubmw6cGlldGVyLWExPC9zYW1sMjpOYW1lSUQ+DQogIDwvc2FtbDI6U3ViamVjdD4NCiAgPHNhbWwycDpSZXF1ZXN0ZWRBdXRobkNvbnRleHQgQ29tcGFyaXNvbj0iZXhhY3QiPg0KICAgIDxzYW1sMjpBdXRobkNvbnRleHRDbGFzc1JlZj5odHRwOi8vdGVzdDIuc3VyZmNvbmV4dC5ubC9hc3N1cmFuY2Uvc2ZvLWxldmVsMjwvc2FtbDI6QXV0aG5Db250ZXh0Q2xhc3NSZWY+DQogIDwvc2FtbDJwOlJlcXVlc3RlZEF1dGhuQ29udGV4dD4NCjwvc2FtbDJwOkF1dGhuUmVxdWVzdD4='
+ );
+ }
+
+
+ // login
+ $as->login( $context );
+
+ exit; // Added for clarity
+}
+
+if( isset($_REQUEST['action']) && $_REQUEST['action'] == 'logout' ) {
+ $as->logout( array (
+ 'ReturnTo' => $returnURL,
+ ) ); // Process logout
+ exit; // Added for clarity
+}
+
+if( isset($_REQUEST['action']) && $_REQUEST['action'] == 'reset' ) {
+ $session->deleteData('array', 'SSP_DEMO_SP_FORM_DATA');
+ $_REQUEST=array();
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Output HTML
+
+$saved_parameters = $session->getData('array', 'SSP_DEMO_SP_FORM_DATA');
+if (is_array($saved_parameters)) {
+ $saved_parameters = array();
+}
+if (!isset($_REQUEST['idp'])) {
+ $_REQUEST=array_merge($saved_parameters, $_REQUEST);
+}
+
+$idp=htmlentities(isset($_REQUEST['idp']) ? $_REQUEST['idp'] : "");
+$loa=htmlentities(isset($_REQUEST['loa']) ? $_REQUEST['loa'] : "");
+$nameidpolicy=htmlentities(isset($_REQUEST['nameidpolicy']) ? $_REQUEST['nameidpolicy'] : "");
+$ssobinding=htmlentities(isset($_REQUEST['ssobinding']) ? $_REQUEST['ssobinding'] : "");
+$requesterid=htmlentities(isset($_REQUEST['requesterid']) ? $_REQUEST['requesterid'] : "");
+$requesterid2=htmlentities(isset($_REQUEST['requesterid2']) ? $_REQUEST['requesterid2'] : "");
+$scopingIDP=htmlentities(isset($_REQUEST['scopingIDP']) ? $_REQUEST['scopingIDP'] : "");
+$scopingIDP2=htmlentities(isset($_REQUEST['scopingIDP2']) ? $_REQUEST['scopingIDP2'] : "");
+$sp=htmlentities(isset($_REQUEST['sp']) ? $_REQUEST['sp'] : "default-sp");
+$subject=htmlentities(isset($_REQUEST['subject']) ? $_REQUEST['subject'] : "");
+$acsurl=htmlentities(isset($_REQUEST['acsurl']) ? $_REQUEST['acsurl'] : "");
+
+echo <<
+
+
+
+
+ simpleSAMLphp Test SP
+
+
+