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..1376504
--- /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 /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-----
+MIIG4gIBAAKCAYEAsjKhsnr6xfzLPH7BkHc+n6swgPE/0CgvSW95uxKUDqfzjKv6
+gb+II7RX9P2wLp9jf7us2TpT5OtYlVkW8SHrfzvQQKKkYbU+jx0FXEXl0dRd/g5N
+rx/PkMmcJ1hhDcIdegWLoqyHlkLhIH1Q1KUoNjAY5B42ZqRfA8Z+nePOasK3WxWT
+fs90D7cTWjbtRQZLbIDzY5aROxzQfcXBsuA5YEyD/vNJyoDPinaKcPRVZO9W3yih
+6dZvakkmxSPna7W7RSezj6hWA7PYCRGPIrwCyA9RETUJADyJq/xCD4msx3OJ5EH4
+uCreaIbLxrn3QsWLTlBsY3K5KvaCV+WIogvcX3pD3lNORdhbGFsWCtJ5pxD9LcnY
+AxXipdhSNr1Ia9qDmok7OVZTYTM+N3Yl/QCc45juJ63j7LgP098I/K0s4UvZA/SB
+ehpGfsvtWMs3/DVsT3xQi9CuAef/qRg2OQRE1/gR6uJCgho1lVs/VoXfTHmiW+G7
+snE/Ucima5khHv35AgMBAAECggGAKVZrgj7bG8C32NHCz2OKKHoK526PkhcwWQW+
+JHJ73CaD7hcbJqwqxbWZTeDn1PjumPwNbdsFCS67PvIKy2dF/R8AAW55WZ005Pgj
+fTNNy+5K25uv07c6bGkIi2wKH6nvMpZEvTjuvyHGncXUUW/6sw9XRtvnXMo2rGaI
+itIE2WlQJZYMwDcZwmeC2sOxKPj72DDVxT1xdVgK2ZJdi8ROKxO07xi6/noBKyqy
+lN9pS9/ltCD15ovzDqHnl4XrsmXWpvMuBl6f9ACNTI0jZE1WoMMKhxPdWvRm+gId
+U3ikNK6eLfReHu6jeTQRNCAO9dExrAJzgV7G4jHwinDrBk8ywYqSYVrbpz5Sx/Ij
+W6Gt9XMjHz2y8Bs114foVW3Fr3Fj55/eQu1xa6WaxFcF5nEP2/bLXexMJHqeMI4r
+T+150G6pjHk2uvh61JB8aAfaqIrOP7/1hjbJBIHjD/ub2xZ7uwtibFQvhmOpzYE8
+jeO09A2byQU2yIXvZXxVJWE4vmwBAoHBAOuRI+WqFpRAlJ7yolRfM0uwo3R09+Aw
+LZ3tvnMHGJPipImFC5k2ralll/tstBVdRNEMIqsLcogBfMt3F1kx6hYtMXj3gy9S
+b0XKJvEikdQvmdUjVfkIlRI+yMm811xqtqNXcLqndSxTUkTotpxmU7p1AhdXpIv9
+IiXaBfuUvBi68M8tJ0tgJWKCDtwJWtlvhKRv6UXVauJbb8QczIgrpk0PVI9WvX0Z
+VN/3bq/BxJBjD/RvLN1uNqjsi/qoN1wWeQKBwQDBp5XrNzU8wctaLxdZrKCjfe0T
+X3Scm9xgWKZOZUBOH6ydbVya/g0VsFM6mgu6tz2yMGA4TlmqM2WfzhzVkb2aJ8Z4
+me2jsyqku3sANZzFaGRMu0i03LC6SFv9NQ+YA8p01Ry9KPF8RU0Ows9Zv/uVgPNp
+CEy8GfjbmJsbfEPkj5gNIJx5RNEgI6mSOOtTAiQK7Mra4bJwgvRSudhpMQJWUdbo
+J8k0+VSspmC0gIh108rAvlpEDTBgDa7QAbMGQ4ECgcB1bQNk79WTj2HGnhK3VkF+
+wI2qdsg9dCa5LBMcyfPBfGAiwTSX6n7FC4Soa3aVk8nDH3aEpw8vpvYrgrEb4Frd
+NSgNMeyuATzAoFWrLF1fVV8stRGdM18EGlIC5mTAh92FLQhfsywgrWQ8P3kQG54v
+OzaQpjq7IbMNBVKoJ2tgNIfn7o1A8KuSIF0B6JPmAcYwJi01h35hWc0sCGMYmhGr
+JjIzxbxtiNwbTP9bE49FnmwMoALQWqlaqZfZmlMGT5kCgcBKaPiEHvyH0fcvOfUA
+8gHvkE1uKjmGi6UMKEQOz3z8B9Ot0f3JWGDyuoPgepyTLCG6vDfcqs5tRb6AvxP5
+RDzUZQAwCwVy5z81eQx0MiWA/PG9QiFXzYzipzchfif1w08hwVl/naHcnExVpalC
+1S/4bEobS6Mgi+JBjsvarc7wnfRQ5vz44+ZvMQTROKnDhYkP4Zi4rgyAivEScHKl
+SL2bKWsoXVFE16EfjfaOpOzKSY0YrovEpkS2Q8uuBVkiyQECgcB4JN+HiWD5auBl
+S0eDa+cGd7dNcs3d1t++sIyGZtxclzlpzHl5mr5Ey9UdkCvB3JmUh+fSsxBile7Y
+n03lt29kozvJ5FsL6t8zp3Fs9HY9fvNJQ51J7xLJpeGuZkUebxQRad/Gs18EkP4c
+5Wpa8inZay7o2+VHPcgyp1OmAMwUxof8WNdzhpqe1SR/c58WOOu0OPyDP6gmEUu3
+rka3UsBdb2pXLUCipKVDOOO64ACNicH6Lp+jZgdNCg1N+KKdTdM=
+-----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 ";
+ if (strlen($sessionIndex) > 0) {
+ $color=HTMLColorFingerprint($sessionIndex);
+ echo " ";
+ NameIDArrayToHTML($nameID);
+ 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' => 'simpleSAMLphp Test SP
+head;
+
+$authnInstant = '';
+$expire = '';
+if ( $bIsAuthenticated ) {
+ $attributes = $as->getAttributes();
+
+ /** @var $session SimpleSAML\Session */
+ $requestedLOA = htmlentities($session->getData('string', 'RequiredAuthnContextClassRef'));
+ $IdPEntityID = htmlentities($as->getAuthData('saml:sp:IdP'));
+ $sessionIndex = htmlentities($as->getAuthData('saml:sp:SessionIndex'));
+ $authState = $session->getAuthState($sp);
+ //echo ""; print_r($authState); echo "
";
+ $authenticationAuthority=$authState['saml:AuthenticatingAuthority']; // Array of AuthenticatingAuthority's
+ $actualLOA = htmlentities($authState['saml:sp:AuthnContext']);
+ $nameID = $as->getAuthData('saml:sp:NameID');
+ $authnInstant = htmlentities(gmdate('r', $authState['AuthnInstant'] ));
+ $expire = htmlentities(gmdate('r', $authState['Expire'] ));
+
+ echo <<You are logged in to SP:{$sp}
+ {$IdPEntityID}
+
+html;
+
+ echo "Session
\n";
+
+ echo "{$sessionIndex}
";
+ }
+ echo "{$authnInstant}
";
+ echo "{$expire}
LOA
";
+ echo "{$actualLOA}
";
+ if (strlen($requestedLOA) > 0) {
+ echo "{$requestedLOA}
";
+ }
+
+ echo "NameID
\n";
+ echo "
+
+html;
+ foreach ($attributes as $attrName => $attrVal) {
+ echo " Attribute Value(s) ".AttributeNameToHTML($attrName)." \n";
+ if (is_array($attrVal)) {
+ for ($i=0;$i \n";
+ }
+ echo "
'; + echo htmlentities($SAMLResponse); + echo ''; + } + else + { + echo 'Error decoding SAMLResponse (invalid base64)