diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml
new file mode 100644
index 0000000000000000000000000000000000000000..298642bfe9878840a2301885df91c3a558c01d17
--- /dev/null
+++ b/.github/workflows/documentation.yml
@@ -0,0 +1,53 @@
+name: Documentation
+
+on:
+  push:
+    branches: [ master, release-* ]
+    paths:
+      - '**.md'
+  pull_request:
+    branches: [ master, release-* ]
+    paths:
+      - '**.md'
+
+jobs:
+  quality:
+    name: Quality checks
+    runs-on: [ubuntu-latest]
+
+    steps:
+      - uses: actions/checkout@v3
+
+      - name: Lint markdown files
+        uses: nosborn/github-action-markdown-cli@v3.1.0
+        with:
+          files: .
+          ignore_path: .markdownlintignore
+
+      - name: Perform spell check
+        uses: codespell-project/actions-codespell@master
+        with:
+          path: '**/*.md'
+          check_filenames: true
+          ignore_words_list: tekst
+
+  build:
+    name: Build documentation
+    needs: quality
+    runs-on: [ubuntu-latest]
+
+    steps:
+      - name: Run docs build if any of markdown-files have changed
+        if: steps.changed-files-specific.outputs.any_changed == 'true' && github.event_name != 'pull_request'
+        uses: actions/github-script@v6
+        with:
+          # Token has to be generated on a user account that controls the docs-repository.
+          # The _only_ scope to select is "Access public repositories", nothing more.
+          github-token: ${{ secrets.PAT_TOKEN }}
+          script: |
+            await github.rest.actions.createWorkflowDispatch({
+              owner: 'simplesamlphp',
+              repo: 'docs',
+              workflow_id: 'mk_docs.yml',
+              ref: 'main'
+            })
diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml
index ba59d41e96c997ed4249dbee1be0af9d6fa8d82b..a85f4aa085d97cb4655f976d4ba1e798c167d692 100644
--- a/.github/workflows/php.yml
+++ b/.github/workflows/php.yml
@@ -37,7 +37,7 @@ jobs:
           git config --global core.autocrlf false
           git config --global core.eol lf
 
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v3
 
       - name: Get composer cache directory
         id: composer-cache
@@ -91,7 +91,7 @@ jobs:
       - name: Setup problem matchers for PHP
         run: echo "::add-matcher::${{ runner.tool_cache }}/php.json"
 
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v3
 
       - name: Get composer cache directory
         id: composer-cache
@@ -132,7 +132,7 @@ jobs:
       - name: Setup problem matchers for PHP
         run: echo "::add-matcher::${{ runner.tool_cache }}/php.json"
 
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v3
 
       - name: Get composer cache directory
         id: composer-cache
@@ -170,7 +170,7 @@ jobs:
       - name: Setup problem matchers for PHP
         run: echo "::add-matcher::${{ runner.tool_cache }}/php.json"
 
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v3
 
       - name: Get composer cache directory
         id: composer-cache
diff --git a/.markdownlintignore b/.markdownlintignore
new file mode 100644
index 0000000000000000000000000000000000000000..140fada73f4e74552a2c5e757c9a4b81b4cd36b0
--- /dev/null
+++ b/.markdownlintignore
@@ -0,0 +1 @@
+vendor/*
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 25dc2a9854bba08b960710417f814336aaf0a8eb..c8e96d5d81b960f8955ea155172cd5a1a4c811a1 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,4 +1,5 @@
 # Contribution guidelines
+
 **SimpleSAMLphp welcomes all contributions**. It is impossible to make a product like this without the efforts of many people, so please don't be shy and share your help with us. Even the tiniest contribution can make a difference!
 
 These guidelines briefly explain how to contribute to SimpleSAMLphp effectively and consistently, making sure to keep high quality standards and making it easier for you to contribute.
@@ -6,6 +7,7 @@ These guidelines briefly explain how to contribute to SimpleSAMLphp effectively
 [TOC]
 
 ## Team members
+
 Currently, the core team members are:
 
 * Jaime PĂ©rez Crespo, *maintainer and main developer*, UNINETT <jaime.perez@uninett.no>
@@ -22,6 +24,7 @@ We have been lucky enough to have so many people help us through the years. Simp
 ***Big thanks to you all!***
 
 ## First things first
+
 Before embarking yourself in a contribution, please make sure you are familiar with the way SimpleSAMLphp is written, the way it works, and what is required or not.
 
 * Make sure to read [the documentation](https://simplesamlphp.org/docs/stable/). If you use the search engine in the website, please verify that you are reading the latest stable version. If you want to make a change, check [the development branch of the documentation](https://simplesamlphp.org/docs/development/).
@@ -30,26 +33,29 @@ Before embarking yourself in a contribution, please make sure you are familiar w
 * If you think you have discovered a bug, please check the [issue tracker](https://github.com/simplesamlphp/simplesamlphp/issues) and the [pull requests](https://github.com/simplesamlphp/simplesamlphp/pulls) to verify it hasn't been reported already.
 
 ## Contributing code
+
 New features are always welcome, provided they will be useful to someone apart from yourself. Please take a look at the [list of issues](https://github.com/simplesamlphp/simplesamlphp/issues) to see what people are asking for. Our [roadmap](https://simplesamlphp.org/releaseplan) might also be a good place to start if you do not know exactly how you can contribute.
 
 When submitting a pull request, please make sure to account for:
 
 ### Coding standards
+
 * Respect the coding standards. We try to comply with PHP's [PSR-12](http://www.php-fig.org/psr/psr-12/). Pay special attention to the rules below:
-    * Lines should not be longer than 80 characters.
-    * Use **4 spaces** instead of tabs.
-    * Keep the keywords in **lowercase**, including `true`, `false` and `null`.
-    * Make sure your classes work with *autoloading*.
-    * Never include a trailing `?>` in your files.
-    * The first line of every file must be `<?php`.
-    * Use namespaces if you are adding new files.
+  * Lines should not be longer than 80 characters.
+  * Use **4 spaces** instead of tabs.
+  * Keep the keywords in **lowercase**, including `true`, `false` and `null`.
+  * Make sure your classes work with *autoloading*.
+  * Never include a trailing `?>` in your files.
+  * The first line of every file must be `<?php`.
+  * Use namespaces if you are adding new files.
 * Do not include too many changes in every commit. Commits should be focused and address one single problem or feature. By having **multiple, small commits** instead of fewer large ones, it is easier to track what you are doing, revert changes in case of an error and help you make changes if needed.
 * Try to write clean **commit messages**, largely based on the [seven rules](http://chris.beams.io/posts/git-commit/):
-    * Write a **short** subject line, followed by a blank line and a longer explanation.
-    * Prefix the subject line with the component(s) changed, e.g. "docs: Update foo", or "SAML: Don't log bar twice", or "tests: Add tests for quux".
-    * Explain **what and why** in the commit message, not just _how_. Things that seem obvious now might become quite confusing when rediscovered years later.
+  * Write a **short** subject line, followed by a blank line and a longer explanation.
+  * Prefix the subject line with the component(s) changed, e.g. "docs: Update foo", or "SAML: Don't log bar twice", or "tests: Add tests for quux".
+  * Explain **what and why** in the commit message, not just **how**. Things that seem obvious now might become quite confusing when rediscovered years later.
 
 ### Comments, comparisons, and simplicity
+
 * Add comments that describe why/how your code works.
 * Include complete **phpdoc** documentation for every property and method you add. If you change a method or property, make sure to update the existing *phpdoc* accordingly. Do not forget to document all parameters, returned values and exceptions thrown.
 * Use strict comparison operators like `===` and check for specific values when writing tests.
@@ -57,12 +63,15 @@ When submitting a pull request, please make sure to account for:
 * Try to keep **backwards-compatibility**. Code that breaks current configurations and installations is difficult to deploy, and therefore we try to avoid that as much as possible.
 
 ### Unit tests
+
 Add **unit tests** to verify that your code not only works but also keeps working over time. When adding tests, keep the same directory structure used for regular classes. Try to cover **all your code** with tests. The bigger the test coverage, the more reliable and better our library is. Read our [guidelines](TESTING.md) to learn more about tests.
 
 ### Documentation
+
 In order to keep this library user-friendly, we ask that you add proper **documentation** explaining how to use your new feature or how your code changes things.
 
 ### Pull requests
+
 Please follow all instructions below:
 
 1. Submit your code as a **pull request** in github from a branch with a descriptive name in your own fork of the repository.
@@ -72,6 +81,7 @@ Please follow all instructions below:
 Sometimes it can take a long time before we are able to process your pull requests. Do not get discouraged, we will eventually reach your change. Remember that by following these guidelines, you are making it easier for us to analyze your request so the process will be smooth and fast. We really appreciate you helping us out, not only with your code, but also by following these guidelines.
 
 ## Reporting bugs
+
 Before reporting a bug, please make sure it is indeed a bug. Check [the documentation](https://simplesamlphp.org/docs/stable/) to verify what the intended behaviour is. Review the [issue tracker](https://github.com/simplesamlphp/simplesamlphp/issues) and the [pull requests](https://github.com/simplesamlphp/simplesamlphp/pulls) to see if someone has already reported the same issue.
 
 If you are able, a pull request is much more appreciated than just a new issue. If not, please do not hesitate to open one. It is better to have just an issue report than nothing!
@@ -86,6 +96,7 @@ You can help us diagnose and fix bugs by asking and providing answers to the fol
 * Is this a security issue? If so, how severe is it? How can an attacker exploit it? Read more about security issues in the next section.
 
 ## Reporting vulnerabilities
+
 In case you find a vulnerability in SimpleSAMLphp, or you want to confirm a possible security issue in the software, please get in touch with us through [UNINETT's CERT team](https://www.uninett.no/cert). Please use our PGP public key to encrypt any possibly sensitive data that you may need to submit. We will get back to you as soon as possible according to our working hours in Central European Time.
 
 When reporting a security issue, please add as much information as possible to help us identify, confirm, replicate and fix the problem. In particular, remember to include the following information in your report:
@@ -107,11 +118,13 @@ Finally, be reasonable. We'll do our best to resolve the issue according to our
 You can find the list of security advisories we have published [here](https://simplesamlphp.org/security).
 
 ## Translations
+
 SimpleSAMLphp is translated to many languages, though it needs constant updates from translators, as well as new translations to other languages. For the moment, translations can be contributed as **pull requests**. We are looking at better ways to translate the software that would make your life easier, so stay tuned! You can also join the [translators mailing list](http://groups.google.com/group/simplesamlphp-translation) to keep up to date on the latest news.
 
 Before starting a new translation, decide what style you want to use, whether you want to address the user in a polite manner or not, etc. Be coherent and keep that style through all your translations. If there is already a translation and you want to complete it, make sure to keep the same style used by your fellow translators.
 
-## Documentation
+## Documentation improvements
+
 Did you find a typo in the documentation? Does something make no sense? Did we use poor english? Tell us!
 
 Documentation is included in our own repository in *markdown* format. You can submit pull requests with fixes. If you encounter some feature that is not documented, or the documentation does not reflect the real behaviour of the library, please do not hesitate to open an issue.
@@ -119,4 +132,5 @@ Documentation is included in our own repository in *markdown* format. You can su
 Good documentation is key to make things easier for our users!
 
 ## Community
+
 You do not feel capable of contributing with your code, but are using SimpleSAMLphp and can share your knowledge and experience? Please, do so! Join our [users mailing list](http://groups.google.com/group/simplesamlphp) and help other users when you can. Your experience might be valuable for many!
diff --git a/README.md b/README.md
index 504f8b645d4905977ae13a670c7b437c0c9b04a3..78a9c89c62b1c5f4887ac0b5d1b1c6a2ef494836 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,11 @@
-SimpleSAMLphp
-=============
+# SimpleSAMLphp
+
 ![Build Status](https://github.com/simplesamlphp/simplesamlphp/workflows/CI/badge.svg?branch=master)
 [![Coverage Status](https://codecov.io/gh/simplesamlphp/simplesamlphp/branch/master/graph/badge.svg)](https://codecov.io/gh/simplesamlphp/simplesamlphp)
 [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/simplesamlphp/simplesamlphp/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/simplesamlphp/simplesamlphp/?branch=master)
 [![Type coverage](https://shepherd.dev/github/simplesamlphp/simplesamlphp/coverage.svg)](https://shepherd.dev/github/simplesamlphp/simplesamlphp)
 [![BrowserStack Status](https://automate.browserstack.com/badge.svg?badge_key=LzlCL29sZEVDRXJpdGtxZUdITFA3YjYyUFBBYkVVZDVDcG1YZXRaN2pvTT0tLVhCNzkwVUNGVFVjVFVicUg0R1BNR0E9PQ==--f9efb6f330bd98dd6e3c7b816ac2f0982275a872)](https://automate.browserstack.com/public-build/LzlCL29sZEVDRXJpdGtxZUdITFA3YjYyUFBBYkVVZDVDcG1YZXRaN2pvTT0tLVhCNzkwVUNGVFVjVFVicUg0R1BNR0E9PQ==--f9efb6f330bd98dd6e3c7b816ac2f0982275a872)
 
-
 This is the official repository of the SimpleSAMLphp software.
 
 * [SimpleSAMLphp homepage](https://simplesamlphp.org)
diff --git a/docs/index.md b/docs/index.md
index ae75db85e11d0be00d1491f66fa71afa2d2e781a..0d0a4ca17d970d86a3014dbf9ed9311d5f4bfa41 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -1,19 +1,18 @@
-SimpleSAMLphp Documentation
-===========================
+# SimpleSAMLphp Documentation
 
- * Installation and upgrading
+* Installation and upgrading
   * [Installing SimpleSAMLphp](simplesamlphp-install)
   * [Upgrade notes](simplesamlphp-upgrade-notes)
   * [Installation from the repository](simplesamlphp-install-repo)
   * [Changelog](simplesamlphp-changelog)
- * Using SimpleSAMLphp as a SAML Service Provider
+* Using SimpleSAMLphp as a SAML Service Provider
   * [Service Provider Quickstart](simplesamlphp-sp)
   * [Hosted SP Configuration Reference](./saml:sp)
   * [IdP remote reference](simplesamlphp-reference-idp-remote)
   * [Configuring HTTP-Artifact](./simplesamlphp-artifact-sp)
   * [Using scoping](./simplesamlphp-scoping)
   * [Holder-of-Key profile](simplesamlphp-hok-sp)
- * Using SimpleSAMLphp as a SAML Identity Provider
+* Using SimpleSAMLphp as a SAML Identity Provider
   * [Identity Provider QuickStart](simplesamlphp-idp)
   * [IdP hosted reference](simplesamlphp-reference-idp-hosted)
   * [SP remote reference](simplesamlphp-reference-sp-remote)
@@ -21,14 +20,14 @@ SimpleSAMLphp Documentation
   * [Configuring HTTP-Artifact](./simplesamlphp-artifact-idp)
   * [Identity Provider Advanced Topics](simplesamlphp-idp-more)
   * [Holder-of-Key profile](simplesamlphp-hok-idp)
- * Further topics
+* Further topics
   * [Maintenance and configuration](simplesamlphp-maintenance) - covers session handling, php configuration etc.
   * [Automated Metadata Management](/docs/contrib_modules/metarefresh/simplesamlphp-automated_metadata)
   * [Key rollover](./saml:keyrollover)
   * [Authentication Processing Filters](simplesamlphp-authproc) - attribute filtering, attribute mapping, consent, group generation etc.
   * [State Information Lost](simplesamlphp-nostate) - more about this common error message
   * [Advanced features](simplesamlphp-advancedfeatures) - covers bridging protocols, attribute filtering, etc.
- * SimpleSAMLphp Modules
+* SimpleSAMLphp Modules
   * [Documentation for specific modules](/docs/contributed_modules.html)
   * [Theming SimpleSAMLphp](simplesamlphp-theming)
   * [Creating authentication sources](./simplesamlphp-authsource)
diff --git a/docs/simplesamlphp-advancedfeatures.md b/docs/simplesamlphp-advancedfeatures.md
index 1373b279ad9b0f9bec8e4cc0503b8e6586e41704..76ac9e9c78d0756ff91d30bb982f301c9586db2e 100644
--- a/docs/simplesamlphp-advancedfeatures.md
+++ b/docs/simplesamlphp-advancedfeatures.md
@@ -1,23 +1,18 @@
-SimpleSAMLphp Advanced Features
-===============================
+# SimpleSAMLphp Advanced Features
 
 [TOC]
 
-SimpleSAMLphp documentation
----------------------------
+## SimpleSAMLphp documentation
 
 This document is part of the SimpleSAMLphp documentation suite.
 
 - [List of all SimpleSAMLphp documentation](http://simplesamlphp.org/docs)
 
-
 This document assumes that you already have a installation of
 SimpleSAMLphp running, configured and working. This is the next
 step :)
 
-
-Bridging between protocols
---------------------------
+## Bridging between protocols
 
 A bridge between two protocols is built using both an IdP and an SP, connected together.
 To let a SAML 2.0 SP talk to a SAML 1.1 IdP, you build a SimpleSAMLphp bridge from a SAML 2.0 IdP and a SAML 1.1 SP.
@@ -25,39 +20,34 @@ The SAML 2.0 SP talks to the SAML 2.0 IdP, which hands the request over to the S
 
 If you have followed the instructions for setting up an SP, and have configured an authentication source, all you need to do is to add that authentication source to the IdP.
 
-**Example of bridge configuration**
+### Example of bridge configuration
 
 In `metadata/saml20-idp-hosted.php`:
 
-    'auth' => 'default-sp',
+```php
+'auth' => 'default-sp',
+```
 
 In `config/authsources.php`:
 
-    'default-sp' => [
-        'saml:SP',
-    ],
-
+```php
+'default-sp' => [
+    'saml:SP',
+],
+```
 
-
-Attribute control
------------------
+## Attribute control
 
 Filtering, mapping, etc can be performed by using existing or create new *Authentication Processing Filters*. For more information, read:
 
-  * [Authentication Processing Filters in SimpleSAMLphp](simplesamlphp-authproc)
-
+- [Authentication Processing Filters in SimpleSAMLphp](simplesamlphp-authproc)
 
-
-Automatic update of SAML 2.0 Metadata XML from HTTPS
-----------------------------------------------------
+## Automatic update of SAML 2.0 Metadata XML from HTTPS
 
 The `metarefresh` module is the preferred method for doing this.
 Please see the [metarefresh documentation](/docs/contrib_modules/metarefresh/simplesamlphp-automated_metadata).
 
-
-
-Using simpleSAMLphp on a web server requiring the use of a web proxy
---------------------------------------------------------------------
+## Using simpleSAMLphp on a web server requiring the use of a web proxy
 
 Some modules in simpleSAMLphp may require fetching HTTP/HTTPS content from external websites (e.g. the metarefresh module needs to fetch the metadata from an external source).
 
@@ -65,19 +55,13 @@ simpleSAMLphp can be configured to send HTTP/S requests via such a proxy. The pr
 
 The default is not to use a proxy ('proxy' = null) and no username and password are used ('proxy.auth' = false).
 
-
-
-Auth MemCookie
---------------
+## Auth MemCookie
 
 [Auth MemCookie](http://authmemcookie.sourceforge.net/) support is deprecated in the standard code base of SimpleSAMLphp
  and will no longer be available starting in SimpleSAMLphp 2.0. Please use the new
  [memcookie module](https://github.com/simplesamlphp/simplesamlphp-module-memcookie) instead.
 
-
-
-Metadata signing
-----------------
+## Metadata signing
 
 SimpleSAMLphp supports signing of the metadata it generates. Metadata signing is configured by four options:
 
@@ -86,73 +70,76 @@ SimpleSAMLphp supports signing of the metadata it generates. Metadata signing is
 - `metadata.sign.privatekey_pass`: Passphrase which should be used to open the private key. This parameter is optional, and should be left out if the private key is unencrypted.
 - `metadata.sign.certificate`: Location of certificate data which matches the private key.
 - `metadata.sign.algorithm`: The algorithm to use when signing metadata for this entity. Defaults to RSA-SHA256. Possible values:
-
-    * `http://www.w3.org/2000/09/xmldsig#rsa-sha1`
-       *Note*: the use of SHA1 is **deprecated** and will be disallowed in the future.
-    * `http://www.w3.org/2001/04/xmldsig-more#rsa-sha256`
-      The default.
-    * `http://www.w3.org/2001/04/xmldsig-more#rsa-sha384`
-    * `http://www.w3.org/2001/04/xmldsig-more#rsa-sha512`
+  - `http://www.w3.org/2000/09/xmldsig#rsa-sha1`
+    *Note*: the use of SHA1 is **deprecated** and will be disallowed in the future.
+  - `http://www.w3.org/2001/04/xmldsig-more#rsa-sha256`
+    The default.
+  - `http://www.w3.org/2001/04/xmldsig-more#rsa-sha384`
+  - `http://www.w3.org/2001/04/xmldsig-more#rsa-sha512`
 
 These options can be configured globally in the `config/config.php`-file, or per SP/IdP by adding them to the hosted metadata for the SP/IdP. The configuration in the metadata for the SP/IdP takes precedence over the global configuration.
 
 There is also an additional fallback for the private key and the certificate. If `metadata.sign.privatekey` and `metadata.sign.certificate` isn't configured, SimpleSAMLphp will use the `privatekey`, `privatekey_pass` and `certificate` options in the metadata for the SP/IdP.
 
-
-
-
-Session checking function
--------------------------
+## Session checking function
 
 Optional session checking function, called on session init and loading, defined with 'session.check_function' in config.php.
 
 Example code for the function with GeoIP country check:
 
+```php
+public static function checkSession($session, $init = false)
+{
+    $data_type = 'example:check_session';
+    $data_key = 'remote_addr';
 
-    public static function checkSession($session, $init = FALSE) {
-        $data_type = 'example:check_session';
-        $data_key = 'remote_addr';
-
-        $remote_addr = NULL;
-        if (!empty($_SERVER['REMOTE_ADDR'])) {
-            $remote_addr = (string)$_SERVER['REMOTE_ADDR'];
-        }
-
-        if ($init) {
-            $session->setData($data_type, $data_key, $remote_addr, \SimpleSAML\Session::DATA_TIMEOUT_SESSION_END);
-            return;
-        }
-
-        if (!function_exists('geoip_country_code_by_name')) {
-            SimpleSAML\Logger::warning('geoip php module required.');
-            return TRUE;
-        }
+    $remote_addr = null;
+    if (!empty($_SERVER['REMOTE_ADDR'])) {
+        $remote_addr = (string)$_SERVER['REMOTE_ADDR'];
+    }
 
-        $stored_remote_addr = $session->getData($data_type, $data_key);
-        if ($stored_remote_addr === NULL) {
-            SimpleSAML\Logger::warning('Stored data not found.');
-            return FALSE;
-        }
+    if ($init) {
+        $session->setData(
+            $data_type,
+            $data_key,
+            $remote_addr,
+            \SimpleSAML\Session::DATA_TIMEOUT_SESSION_END
+        );
+        return;
+    }
 
-        $country_a = geoip_country_code_by_name($remote_addr);
-        $country_b = geoip_country_code_by_name($stored_remote_addr);
+    if (!function_exists('geoip_country_code_by_name')) {
+        \SimpleSAML\Logger::warning('geoip php module required.');
+        return true;
+    }
 
-        if ($country_a === $country_b) {
-            if ($stored_remote_addr !== $remote_addr) {
-                $session->setData($data_type, $data_key, $remote_addr, \SimpleSAML\Session::DATA_TIMEOUT_SESSION_END);
-            }
+    $stored_remote_addr = $session->getData($data_type, $data_key);
+    if ($stored_remote_addr === null) {
+        \SimpleSAML\Logger::warning('Stored data not found.');
+        return false;
+    }
 
-            return TRUE;
+    $country_a = geoip_country_code_by_name($remote_addr);
+    $country_b = geoip_country_code_by_name($stored_remote_addr);
+
+    if ($country_a === $country_b) {
+        if ($stored_remote_addr !== $remote_addr) {
+            $session->setData(
+                $data_type,
+                $data_key,
+                $remote_addr,
+                \SimpleSAML\Session::DATA_TIMEOUT_SESSION_END
+            );
         }
 
-        return FALSE;
+        return true;
     }
 
+    return false;
+}
+```
 
-
-
-Support
--------
+## Support
 
 If you need help to make this work, or want to discuss
 SimpleSAMLphp with other users of the software, you are fortunate:
@@ -161,10 +148,6 @@ you are welcome to join! The forums are open for you to ask
 questions, contribute answers other further questions, request
 improvements or contribute with code or plugins of your own.
 
--  [SimpleSAMLphp homepage](https://simplesamlphp.org)
--  [List of all available SimpleSAMLphp documentation](https://simplesamlphp.org/docs/)
--  [Join the SimpleSAMLphp user's mailing list](https://simplesamlphp.org/lists)
-
-
-
-
+- [SimpleSAMLphp homepage](https://simplesamlphp.org)
+- [List of all available SimpleSAMLphp documentation](https://simplesamlphp.org/docs/)
+- [Join the SimpleSAMLphp user's mailing list](https://simplesamlphp.org/lists)
diff --git a/docs/simplesamlphp-artifact-idp.md b/docs/simplesamlphp-artifact-idp.md
index bb08461ea4dc9777e08573cc19636a9ee6dfaa38..4cf783f033039e009c2ea34d44d9140b57a2f2c1 100644
--- a/docs/simplesamlphp-artifact-idp.md
+++ b/docs/simplesamlphp-artifact-idp.md
@@ -3,10 +3,9 @@ Adding HTTP-Artifact support to the IdP
 
 This document describes the necessary steps to enable support for the HTTP-Artifact binding on a SimpleSAMLphp IdP:
 
-1.  Configure SimpleSAMLphp to use memcache to store the session.
-2.  Enable support for sending artifacts in `saml20-idp-hosted`.
-3.  Add the webserver certificate to the generated metadata.
-
+1. Configure SimpleSAMLphp to use memcache to store the session.
+2. Enable support for sending artifacts in `saml20-idp-hosted`.
+3. Add the webserver certificate to the generated metadata.
 
 Memcache
 --------
@@ -17,30 +16,31 @@ You need both a memcache server and a the PHP memcached client (extension).
 How this is done depends on the distribution.
 If you are running Debian or Ubuntu, you can install this by running:
 
-    apt install memcached php-memcached
+```bash
+apt install memcached php-memcached
+```
 
 simpleSAMLphp also supports the legacy `php-memcache` (without `d`) variant.
 
 *Note*: For security, you must make sure that the memcache server is inaccessible to other hosts.
 The default configuration on Debian is for the memcache server to be accessible to only the local host.
 
-
 Once the memcache server is configured, you can configure simplesamlphp to use it to store sessions.
 You can do this by setting the `store.type` option in `config.php` to `memcache`.
 If you are running memcache on a different server than the IdP, you must also change the `memcache_store.servers` option in `config.php`.
 
-
 Enabling artifact on the IdP
 ----------------------------
 
 To enable the IdP to send artifacts, you must add the `saml20.sendartifact` option to the `saml20-idp-hosted` metadata file:
 
-    $metadata['https://example.org/saml-idp'] = [
-        [....]
-        'auth' => 'example-userpass',
-        'saml20.sendartifact' => TRUE,
-    ];
-
+```php
+$metadata['https://example.org/saml-idp'] = [
+    [....]
+    'auth' => 'example-userpass',
+    'saml20.sendartifact' => true,
+];
+```
 
 Add new metadata to SPs
 -----------------------
@@ -49,14 +49,15 @@ After enabling the Artifact binding, your IdP metadata will change to add a Arti
 You therefore need to update the metadata for your IdP at your SPs.
 `saml20-idp-remote` metadata for SimpleSAMLphp SPs should contain something like:
 
-    'ArtifactResolutionService' => [
-        [
-            'index' => 0,
-            'Location' => 'https://idp.example.org/simplesaml/saml2/idp/ArtifactResolutionService.php',
-            'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:SOAP',
-        ],
+```php
+'ArtifactResolutionService' => [
+    [
+        'index' => 0,
+        'Location' => 'https://idp.example.org/simplesaml/saml2/idp/ArtifactResolutionService.php',
+        'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:SOAP',
     ],
-
+],
+```
 
 SP metadata on the IdP
 ----------------------
@@ -65,22 +66,23 @@ An SP using the HTTP-Artifact binding must have an AssertionConsumerService endp
 This means that you must use the complex endpoint format in `saml20-sp-remote` metadata.
 In general, that should look something like:
 
-    'AssertionConsumerService' => array (
-        [
-            'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
-            'Location' => 'https://sp.example.org/simplesaml/module.php/saml/sp/assertionConsumerService/default-sp',
-            'index' => 0,
-        ],
-        [
-            'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact',
-            'Location' => 'https://sp.example.org/simplesaml/module.php/saml/sp/assertionConsumerService/default-sp',
-            'index' => 2,
-        ],
-    ),
+```php
+'AssertionConsumerService' => [
+    [
+        'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
+        'Location' => 'https://sp.example.org/simplesaml/module.php/saml/sp/assertionConsumerService/default-sp',
+        'index' => 0,
+    ],
+    [
+        'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact',
+        'Location' => 'https://sp.example.org/simplesaml/module.php/saml/sp/assertionConsumerService/default-sp',
+        'index' => 2,
+    ],
+],
+```
 
 (The specific values of the various fields will vary depending on the SP.)
 
-
 Certificate in metadata
 -----------------------
 
@@ -89,9 +91,11 @@ You may therefore have to add the webserver certificate to the metadata that you
 To do this, you need to set the `https.certificate` option in the `saml20-idp-hosted` metadata file.
 That option should refer to a file containing the webserver certificate.
 
-    $metadata['https://example.org/saml-idp'] = [
-        [....]
-        'auth' => 'example-userpass',
-        'saml20.sendartifact' => TRUE,
-        'https.certificate' => '/etc/apache2/webserver.crt',
-    ];
+```php
+$metadata['https://example.org/saml-idp'] = [
+    [....]
+    'auth' => 'example-userpass',
+    'saml20.sendartifact' => true,
+    'https.certificate' => '/etc/apache2/webserver.crt',
+];
+```
diff --git a/docs/simplesamlphp-authproc.md b/docs/simplesamlphp-authproc.md
index 1b8ea9d6d74480659ae24382e9f5296b45c2e1eb..53d6c3d649a067a5812d67e7efc92dfabbcfffd1 100644
--- a/docs/simplesamlphp-authproc.md
+++ b/docs/simplesamlphp-authproc.md
@@ -1,9 +1,7 @@
-Authentication Processing Filters in SimpleSAMLphp
-==================================================
+# Authentication Processing Filters in SimpleSAMLphp
 
 [TOC]
 
-
 In SimpleSAMLphp, there is an API where you can *do stuff* at the IdP after authentication is complete, and just before you are sent back to the SP. The same API is available on the SP, after you have received a successful Authentication Response from the IdP and before you are sent back to the SP application.
 
 Authentication processing filters postprocess authentication information received from authentication sources. It is possible to use this for additional authentication checks, requesting the user's consent before delivering attributes about the user, modifying the user's attributes, and other things which should be performed before returning the user to the service provider he came from.
@@ -24,8 +22,7 @@ Be aware that Authentication Processing Filters do replace some of the previous
 
 Later in this document, we will describe in detail the alternative Authentication Processing Filters that will replicate these functionalities.
 
-How to configure Auth Proc Filters
-----------------------------------
+## How to configure Auth Proc Filters
 
 *Auth Proc Filters* can be set globally, or to be specific for only one SP or one IdP. That means there are five locations where you can configure *Auth Proc Filters*:
 
@@ -37,20 +34,22 @@ How to configure Auth Proc Filters
 
 The configuration of *Auth Proc Filters* is a list of filters with priority as *index*. Here is an example of *Auth Proc Filters* configured in `config.php`:
 
-	'authproc.idp' => [
-		10 => [
-			'class' => 'core:AttributeMap', 
-			'addurnprefix'
-		],
-		20 => 'core:TargetedID',
-		50 => 'core:AttributeLimit',
-		90 => [
-			'class' 	=> 'consent:Consent', 
-			'store' 	=> 'consent:Cookie', 
-			'focus' 	=> 'yes', 
-			'checked' 	=> TRUE
-		],
-	],
+```php
+'authproc.idp' => [
+    10 => [
+        'class' => 'core:AttributeMap', 
+        'addurnprefix'
+    ],
+    20 => 'core:TargetedID',
+    50 => 'core:AttributeLimit',
+    90 => [
+        'class' => 'consent:Consent', 
+        'store' => 'consent:Cookie', 
+        'focus' => 'yes', 
+        'checked' => true
+    ],
+],
+```
 
 This configuration will execute *Auth Proc Filters* one by one, with the priority value in increasing order. When *Auth Proc Filters* is configured in multiple places, in example both globally, in the hosted IdP and remote SP metadata, then the list is interleaved sorted by priority.
 
@@ -62,23 +61,28 @@ You will see that a bunch of useful filters is included in the `core` module. In
 
 When you know the class definition of a filter, and the priority, the simple way to configure the filter is:
 
-	20 => 'core:TargetedID',
+```php
+20 => 'core:TargetedID',
+```
 
 This is analogous to:
 
-	20 => [
-		'class' => 'core:TargetedID'
-	],
+```php
+20 => [
+    'class' => 'core:TargetedID'
+],
+```
 
 Some *Auth Proc Filters* have optional or required *parameters*. To send parameters to *Auth Proc Filters*, you need to choose the second of the two alernatives above. Here is an example of provided parameters to the consent module:
 
-	90 => [
-		'class' 	=> 'consent:Consent', 
-		'store' 	=> 'consent:Cookie', 
-		'focus' 	=> 'yes', 
-		'checked' 	=> TRUE
-	],
-
+```php
+90 => [
+    'class' => 'consent:Consent', 
+    'store' => 'consent:Cookie', 
+    'focus' => 'yes', 
+    'checked' => true,
+],
+```
 
 ### Filters in `config.php`
 
@@ -93,7 +97,6 @@ The filters in `authproc.idp` will be executed at the IdP side regardless of whi
 
 The filters in `authproc.sp` will be executed at the SP side regardless of which SP and IdP entity that is involved.
 
-
 ### Filters in metadata
 
 Filters can be added both in `hosted` and `remote` metadata. Here is an example of a filter added in a metadata file:
@@ -112,44 +115,39 @@ Filters can be added both in `hosted` and `remote` metadata. Here is an example
 
 The example above is in `saml20-idp-hosted`.
 
-
-
-Auth Proc Filters included in the SimpleSAMLphp distribution
-------------------------------------------------------------
+## Auth Proc Filters included in the SimpleSAMLphp distribution
 
 The following filters are included in the SimpleSAMLphp distribution:
 
-- [`core:AttributeAdd`](./core:authproc_attributeadd): Add attributes to the response.
-- [`core:AttributeCopy`](./core:authproc_attributecopy): Copy existing attributes to the response.
-- [`core:AttributeAlter`](./core:authproc_attributealter): Do search-and-replace on attributevalues.
-- [`core:AttributeLimit`](./core:authproc_attributelimit): Limit the attributes in the response.
-- [`core:AttributeMap`](./core:authproc_attributemap): Change the name of the attributes.
-- [`core:AttributeValueMap`](./core:authproc_attributevaluemap): Map attribute values to new values and attribute name.
-- [`core:Cardinality`](./core:authproc_cardinality): Ensure the number of attribute values is within the specified multiplicity.
-- [`core:CardinalitySingle`](./core:authproc_cardinalitysingle): Ensure the correct cardinality of single-valued attributes.
-- [`core:GenerateGroups`](./core:authproc_generategroups): Generate a `group` attribute for the user.
-- [`core:LanguageAdaptor`](./core:authproc_languageadaptor): Transferring language setting from IdP to SP.
-- [`core:PHP`](./core:authproc_php): Modify attributes with custom PHP code.
-- [`core:ScopeAttribute`](./core:authproc_scopeattribute): Add scope to attribute.
-- [`core:ScopeFromAttribute`](./core:authproc_scopefromattribute): Create a new attribute based on the scope on a different attribute.
-- [`core:StatisticsWithAttribute`](./core:authproc_statisticswithattribute): Create a statistics logentry.
-- [`core:TargetedID`](./core:authproc_targetedid): Generate the `eduPersonTargetedID` attribute.
-- [`core:WarnShortSSOInterval`](./core:authproc_warnshortssointerval): Give a warning if the user logs into the same SP twice within a few seconds.
-- [`saml:AttributeNameID`](./saml:nameid): Generate custom NameID with the value of an attribute.
-- [`saml:AuthnContextClassRef`](./saml:authproc_authncontextclassref): Set the authentication context in the response.
-- [`saml:ExpectedAuthnContextClassRef`](./saml:authproc_expectedauthncontextclassref): Verify the user's authentication context.
-- [`saml:FilterScopes`](./saml:filterscopes): Filter attribute values with scopes forbidden for an IdP.
-- [`saml:NameIDAttribute`](./saml:nameidattribute): Create an attribute based on the NameID we receive from the IdP.
-- [`saml:PersistentNameID`](./saml:nameid): Generate persistent NameID from an attribute.
-- [`saml:PersistentNameID2TargetedID`](./saml:nameid): Store persistent NameID as eduPersonTargetedID.
-- [`saml:TransientNameID`](./saml:nameid): Generate transient NameID.
+* [`core:AttributeAdd`](./core:authproc_attributeadd): Add attributes to the response.
+* [`core:AttributeCopy`](./core:authproc_attributecopy): Copy existing attributes to the response.
+* [`core:AttributeAlter`](./core:authproc_attributealter): Do search-and-replace on attributevalues.
+* [`core:AttributeLimit`](./core:authproc_attributelimit): Limit the attributes in the response.
+* [`core:AttributeMap`](./core:authproc_attributemap): Change the name of the attributes.
+* [`core:AttributeValueMap`](./core:authproc_attributevaluemap): Map attribute values to new values and attribute name.
+* [`core:Cardinality`](./core:authproc_cardinality): Ensure the number of attribute values is within the specified multiplicity.
+* [`core:CardinalitySingle`](./core:authproc_cardinalitysingle): Ensure the correct cardinality of single-valued attributes.
+* [`core:GenerateGroups`](./core:authproc_generategroups): Generate a `group` attribute for the user.
+* [`core:LanguageAdaptor`](./core:authproc_languageadaptor): Transferring language setting from IdP to SP.
+* [`core:PHP`](./core:authproc_php): Modify attributes with custom PHP code.
+* [`core:ScopeAttribute`](./core:authproc_scopeattribute): Add scope to attribute.
+* [`core:ScopeFromAttribute`](./core:authproc_scopefromattribute): Create a new attribute based on the scope on a different attribute.
+* [`core:StatisticsWithAttribute`](./core:authproc_statisticswithattribute): Create a statistics logentry.
+* [`core:TargetedID`](./core:authproc_targetedid): Generate the `eduPersonTargetedID` attribute.
+* [`core:WarnShortSSOInterval`](./core:authproc_warnshortssointerval): Give a warning if the user logs into the same SP twice within a few seconds.
+* [`saml:AttributeNameID`](./saml:nameid): Generate custom NameID with the value of an attribute.
+* [`saml:AuthnContextClassRef`](./saml:authproc_authncontextclassref): Set the authentication context in the response.
+* [`saml:ExpectedAuthnContextClassRef`](./saml:authproc_expectedauthncontextclassref): Verify the user's authentication context.
+* [`saml:FilterScopes`](./saml:filterscopes): Filter attribute values with scopes forbidden for an IdP.
+* [`saml:NameIDAttribute`](./saml:nameidattribute): Create an attribute based on the NameID we receive from the IdP.
+* [`saml:PersistentNameID`](./saml:nameid): Generate persistent NameID from an attribute.
+* [`saml:PersistentNameID2TargetedID`](./saml:nameid): Store persistent NameID as eduPersonTargetedID.
+* [`saml:TransientNameID`](./saml:nameid): Generate transient NameID.
 
 See the [Third-party modules](https://simplesamlphp.org/modules) page on the SimpleSAMLphp website
 for externally hosted modules that may provide a processing filter.
 
-
-Writing your own Auth Proc Filter
----------------------------------
+## Writing your own Auth Proc Filter
 
 Look at the included *Auth Proc Filters* as examples. Copy the classes into your own module and start playing around.
 
@@ -159,13 +157,13 @@ If a filter for some reason needs to redirect the user, for example to show a we
 
 Requirements for authentication processing filters:
 
- - Must be derived from the `\SimpleSAML\Auth\ProcessingFilter`-class.
- - If a constructor is implemented, it must first call the parent constructor, passing along all parameters, before accessing any of the parameters. In general, only the $config parameter should be accessed.
- - The `process(&$request)`-function must be implemented. If this function completes, it is assumed that processing is completed, and that the $request array has been updated.
- - If the `process`-function does not return, it must at a later time call `\SimpleSAML\Auth\ProcessingChain::resumeProcessing` with the new request state. The request state must be an update of the array passed to the `process`-function.
- - No pages may be shown to the user from the `process`-function. Instead, the request state should be saved, and the user should be redirected to a new page. This must be done to prevent unpredictable events if the user for example reloads the page.
- - No state information should be stored in the filter object. It must instead be stored in the request state array. Any changes to variables in the filter object may be lost.
- - The filter object must be serializable. It may be serialized between being constructed and the call to the `process`-function. This means that, for example, no database connections should be created in the constructor and later used in the `process`-function.
+* Must be derived from the `\SimpleSAML\Auth\ProcessingFilter`-class.
+* If a constructor is implemented, it must first call the parent constructor, passing along all parameters, before accessing any of the parameters. In general, only the $config parameter should be accessed.
+* The `process(&$request)`-function must be implemented. If this function completes, it is assumed that processing is completed, and that the $request array has been updated.
+* If the `process`-function does not return, it must at a later time call `\SimpleSAML\Auth\ProcessingChain::resumeProcessing` with the new request state. The request state must be an update of the array passed to the `process`-function.
+* No pages may be shown to the user from the `process`-function. Instead, the request state should be saved, and the user should be redirected to a new page. This must be done to prevent unpredictable events if the user for example reloads the page.
+* No state information should be stored in the filter object. It must instead be stored in the request state array. Any changes to variables in the filter object may be lost.
+* The filter object must be serializable. It may be serialized between being constructed and the call to the `process`-function. This means that, for example, no database connections should be created in the constructor and later used in the `process`-function.
 
 *Note*: An Auth Proc Filter will not work in the "Test authentication sources" option in the web UI of a SimpleSAMLphp IdP. It will only be triggered in conjunction with an actual SP. So you need to set up an IdP *and* and SP when testing your filter.
 
diff --git a/docs/simplesamlphp-authsource.md b/docs/simplesamlphp-authsource.md
index 79c298bbc4eed3baa69f1f7c55385afe95bbcadf..e2d09a186242d41a8de612eab01d0915deffd613 100644
--- a/docs/simplesamlphp-authsource.md
+++ b/docs/simplesamlphp-authsource.md
@@ -1,5 +1,4 @@
-Creating authentication sources
-===============================
+# Creating authentication sources
 
 All authentication sources are located in the `lib/Auth/Source/` directory in a module, and the class name is `\SimpleSAML\Module\<module>\Auth\Source\<name>`.
 The authentication source must extend the `\SimpleSAML\Auth\Source` class or one of its subclasses.
@@ -20,9 +19,7 @@ If the module needs to redirect the user, for example because it needs to show t
 For that we have the `\SimpleSAML\Auth\State` class.
 This is only a convenience class, and you are not required to use it (but its use is encouraged, since it handles some potential pitfalls).
 
-
-Saving state
-------------
+## Saving state
 
 The `\SimpleSAML\Auth\State` class has two functions that you should use:
 `saveState($state, $stage)`, and `loadState($id, $stage)`.
@@ -31,9 +28,7 @@ It is used to prevent a malicious user from taking a state you save in one locat
 
 The `saveState()`-function returns an id, which you should pass to the `loadState()`-function later.
 
-
-Username/password authentication
---------------------------------
+## Username/password authentication
 
 Since username/password authentication is quite a common operation, a base class has been created for this.
 This is the `\SimpleSAML\Module\core\Auth\UserPassBase` class, which is can be found as `modules/core/lib/Auth/UserPassBase.php`.
@@ -46,54 +41,52 @@ If the username or password is incorrect, it should throw an error saying so:
 
 "[Implementing custom username/password authentication](./simplesamlphp-customauth)" describes how to implement username/password authentication using that base class.
 
+## Generic rules & requirements
 
-Generic rules & requirements
-----------------------------
-
--  Must be derived from the `\SimpleSAML\Auth\Source`-class.
+- Must be derived from the `\SimpleSAML\Auth\Source`-class.
 
-    **Rationale**:
-     - Deriving all authentication sources from a single base class allows us extend all authentication sources by extending the base class.
+  **Rationale**:
+  - Deriving all authentication sources from a single base class allows us extend all authentication sources by extending the base class.
 
--  If a constructor is implemented, it must first call the parent constructor, passing along all parameters, before accessing any of the parameters.
-   In general, only the $config parameter should be accessed when implementing the authentication source.
+- If a constructor is implemented, it must first call the parent constructor, passing along all parameters, before accessing any of the parameters.
+  In general, only the $config parameter should be accessed when implementing the authentication source.
 
-    **Rationale**:
-     - PHP doesn't automatically call any parent constructor, so it needs to be done manually.
-     - The `$info`-array is used to provide information to the `\SimpleSAML\Auth\Source` base class, and therefore needs to be included.
-     - Including the `$config`-array makes it possible to add generic configuration options that are valid for all authentication sources.
+  **Rationale**:
+  - PHP doesn't automatically call any parent constructor, so it needs to be done manually.
+  - The `$info`-array is used to provide information to the `\SimpleSAML\Auth\Source` base class, and therefore needs to be included.
+  - Including the `$config`-array makes it possible to add generic configuration options that are valid for all authentication sources.
 
--  The `authenticate(&$state)`-function must be implemented.
-   If this function completes, it is assumed that the user is authenticated, and that the `$state`-array has been updated with the user's attributes.
+- The `authenticate(&$state)`-function must be implemented.
+  If this function completes, it is assumed that the user is authenticated, and that the `$state`-array has been updated with the user's attributes.
 
-    **Rationale**:
-     - Allowing the `authenticate()`-function to return after updating the `$state`-array enables us to do authentication without redirecting the user.
-       This can be used if the authentication doesn't require user input, for example if the authentication can be done based on the IP-address of the user.
+  **Rationale**:
+  - Allowing the `authenticate()`-function to return after updating the `$state`-array enables us to do authentication without redirecting the user.
+    This can be used if the authentication doesn't require user input, for example if the authentication can be done based on the IP-address of the user.
 
--   If the `authenticate`-function does not return, it must at a later time call `\SimpleSAML\Auth\Source::completeAuth` with the new state array.
-    The state array must be an update of the array passed to the `authenticate`-function.
+- If the `authenticate`-function does not return, it must at a later time call `\SimpleSAML\Auth\Source::completeAuth` with the new state array.
+  The state array must be an update of the array passed to the `authenticate`-function.
 
-    **Rationale**:
-     - Preserving the same state array allows us to save information in that array before the authentication starts, and restoring it when authentication completes.
+  **Rationale**:
+  - Preserving the same state array allows us to save information in that array before the authentication starts, and restoring it when authentication completes.
 
--   No pages may be shown to the user from the `authenticate()`-function.
-    Instead, the state should be saved, and the user should be redirected to a new page.
+- No pages may be shown to the user from the `authenticate()`-function.
+  Instead, the state should be saved, and the user should be redirected to a new page.
 
-    **Rationale**:
-     - The `authenticate()`-function is called in the context of a different PHP page.
-       If the user reloads that page, unpredictable results may occur.
+  **Rationale**:
+  - The `authenticate()`-function is called in the context of a different PHP page.
+    If the user reloads that page, unpredictable results may occur.
 
--   No state information about any authentication should be stored in the authentication source object.
-    It must instead be stored in the state array.
-    Any changes to variables in the authentication source object may be lost.
+- No state information about any authentication should be stored in the authentication source object.
+  It must instead be stored in the state array.
+  Any changes to variables in the authentication source object may be lost.
 
-    **Rationale**:
-     - This saves us from having to save the entire authentication object between requests.
-       Instead, we can recreate it from the configuration.
+  **Rationale**:
+  - This saves us from having to save the entire authentication object between requests.
+    Instead, we can recreate it from the configuration.
 
--   The authentication source object must be serializable.
-    It may be serialized between being constructed and the call to the `authenticate()`-function.
-    This means that, for example, no database connections should be created in the constructor and later used in the `authenticate()`-function.
+- The authentication source object must be serializable.
+  It may be serialized between being constructed and the call to the `authenticate()`-function.
+  This means that, for example, no database connections should be created in the constructor and later used in the `authenticate()`-function.
 
-    **Rationale**:
-     - If parsing the configuration and creating the authentication object is shown to be a bottleneck, we can cache an initialized authentication source.
+  **Rationale**:
+  - If parsing the configuration and creating the authentication object is shown to be a bottleneck, we can cache an initialized authentication source.
diff --git a/docs/simplesamlphp-changelog.md b/docs/simplesamlphp-changelog.md
index adbe2377a9899118bdbc4a5126eb47d29793808f..0945297b042de2caba3dc9305b3e8292ad37bb86 100644
--- a/docs/simplesamlphp-changelog.md
+++ b/docs/simplesamlphp-changelog.md
@@ -1,5 +1,4 @@
-SimpleSAMLphp changelog
-=======================
+# SimpleSAMLphp changelog
 
 [TOC]
 
@@ -8,828 +7,902 @@ See the upgrade notes for specific information about upgrading.
 
 ## Version 2.0.0
 
-  * Support for certificate fingerprints was removed
-  * Support for SAML 1.1 was removed
-  * Old-style PHP templates were removed
-  * Old-style dictionaries were removed
-  * The default value for attrname-format was changed to 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri'
-    to comply with SAML2INT
-  * core:PairwiseID and core:SubjectID authprocs no longer support the 'scope' config-setting.
-    Use 'scopeAttribute' instead to identify the attribute holding the scope.
-  * Accepting unsolicited responses can be disabled by setting `enable_unsolicited` to `false` in the SP authsource.
-  * Certificates and private keys can now be retrieved from a database
+* Support for certificate fingerprints was removed
+* Support for SAML 1.1 was removed
+* Old-style PHP templates were removed
+* Old-style dictionaries were removed
+* The default value for attrname-format was changed to 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri'
+  to comply with SAML2INT
+* core:PairwiseID and core:SubjectID authprocs no longer support the 'scope' config-setting.
+  Use 'scopeAttribute' instead to identify the attribute holding the scope.
+* Accepting unsolicited responses can be disabled by setting `enable_unsolicited` to `false` in the SP authsource.
+* Certificates and private keys can now be retrieved from a database
 
 ## Version 1.19.1
 
 Released TBD
 
-  * Fixed a bug in the Artifact Resolution Service (#1428)
-  * Fixed compatibility with Composer pre 1.8.5 (Debian 10) (#1427)
-  * Updated npm dependencies up to February 1, 2021
+* Fixed a bug in the Artifact Resolution Service (#1428)
+* Fixed compatibility with Composer pre 1.8.5 (Debian 10) (#1427)
+* Updated npm dependencies up to February 1, 2021
 
-### memcacheMonitor
-  * Fix a bug in the Twig-template that causes an exception on newer Twig-versions
+`memcacheMonitor`
 
-### negotiate
-  * Fix a bug that was breaking the module when using the old UI
+* Fix a bug in the Twig-template that causes an exception on newer Twig-versions
 
-### statistics
-  * Fix a bug in the Twig-template that causes an exception on newer Twig-versions
+`negotiate`
+
+* Fix a bug that was breaking the module when using the old UI
+
+`statistics`
+
+* Fix a bug in the Twig-template that causes an exception on newer Twig-versions
 
 ## Version 1.19.0
 
 Released 2021-01-21
 
-  * This version will be the last of the 1.x branch and will provide a migration path to our new
-    templating system, routing system and translation system.
-  * SAML 1 / Shib 1.3 support is now marked deprecated and will be removed in SimpleSAMLphp 2.0.
-  * Raised minimum PHP version to 7.1
-  * Dropped support for Symfony 3.x
-  * Update the SAML2 library dependency to 4.1.9
-  * Fix a bug where SSP wouldn't write to the tmp-directory if it didn't own it, but could write to it (#1314)
-  * Fixed several bugs in saml:NameIDAttribute (#1245)
-  * Fix artifact resolution (#1343)
-  * Allow additional audiences to be specified (#1345)
-  * Allow configurable ProviderName (#1348)
-  * Support saml:Extensions in saml:SP authsources (#1349)
-  * The `attributename`-setting in the core:TargetedID authproc-filter has been deprecated in
-    favour of the `identifyingAttribute`-setting.
-  * Filter multiauth authentication sources from SP using AuthnContextClassRef (#1362)
-  * Allow easy enabling of SameSite = 'None' (#1382)
-  * Do not accept the hashed admin password for authentication (#1418)
+* This version will be the last of the 1.x branch and will provide a migration path to our new
+  templating system, routing system and translation system.
+* SAML 1 / Shib 1.3 support is now marked deprecated and will be removed in SimpleSAMLphp 2.0.
+* Raised minimum PHP version to 7.1
+* Dropped support for Symfony 3.x
+* Update the SAML2 library dependency to 4.1.9
+* Fix a bug where SSP wouldn't write to the tmp-directory if it didn't own it, but could write to it (#1314)
+* Fixed several bugs in saml:NameIDAttribute (#1245)
+* Fix artifact resolution (#1343)
+* Allow additional audiences to be specified (#1345)
+* Allow configurable ProviderName (#1348)
+* Support saml:Extensions in saml:SP authsources (#1349)
+* The `attributename`-setting in the core:TargetedID authproc-filter has been deprecated in
+  favour of the `identifyingAttribute`-setting.
+* Filter multiauth authentication sources from SP using AuthnContextClassRef (#1362)
+* Allow easy enabling of SameSite = 'None' (#1382)
+* Do not accept the hashed admin password for authentication (#1418)
 
 ## Version 1.18.8
 
 Released 2020-09-02
 
-  * Fixed Artifact Resolution due to incorrect use of Issuer objects (#1343).
-  * Fixed some of the German translations (#1331). Thanks @htto!
-  * Harden against CVE-2020-13625;  this package is not affected, but 3rd party modules may (#1333).
-  * Harden against several JS issues (npm update & npm audit fix)
-  * Fixed inconsistent configuration of backtraces logging
-  * Support for Symfony 3.x is now deprecated
-  * Support for Twig 1.x is now deprecated
+* Fixed Artifact Resolution due to incorrect use of Issuer objects (#1343).
+* Fixed some of the German translations (#1331). Thanks @htto!
+* Harden against CVE-2020-13625;  this package is not affected, but 3rd party modules may (#1333).
+* Harden against several JS issues (npm update & npm audit fix)
+* Fixed inconsistent configuration of backtraces logging
+* Support for Symfony 3.x is now deprecated
+* Support for Twig 1.x is now deprecated
+
+`authcrypt`
+
+* The dependency for whitehat101/apr1-md5 was moved from the base repository to the module (v0.9.2)
+
+`authx509`
+
+* Restore PHP 5.6 compatibility (v0.9.5)
+
+`cron`
+
+* Fixed old-ui (#1248)
 
-### authcrypt
-  * The dependency for whitehat101/apr1-md5 was moved from the base repository to the module (v0.9.2)
+`ldap`
 
-### authx509
-  * Restore PHP 5.6 compatibility (v0.9.5)
+* Moved array with binary attributes to authsource config (v0.9.9)
+  Instead of having to edit code, you can now set 'attributes.binary' in the authsource configuration.
 
-### cron
-  * Fixed old-ui (#1248)
+`metarefresh`
 
-### ldap
-  * Moved array with binary attributes to authsource config (v0.9.9)
-    Instead of having to edit code, you can now set 'attributes.binary' in the authsource configuration.
+* Add attributewhitelist to support e.g. R&S+Sirtfi (v0.9.5)
+* Restore PHP 5.6 compatibility (v0.9.6)
 
-### metarefresh
-  * Add attributewhitelist to support e.g. R&S+Sirtfi (v0.9.5)
-  * Restore PHP 5.6 compatibility (v0.9.6)
+`negotiate`
 
-### negotiate ###
-  * Restore PHP 5.6 compatibility (v0.9.8)
-  * Fixed a link (v0.9.9)
+* Restore PHP 5.6 compatibility (v0.9.8)
+* Fixed a link (v0.9.9)
 
-### saml2 library
-  * Fixed a bug in the AuthnRequest-class that would raise an InvalidArgumentException when setting
-      the AssertionConsumerServiceIndex as an integer on an saml:SP authsource.
-      Thanks to Andrea @ Oracle for reporting this.
+`saml2 library`
+
+* Fixed a bug in the AuthnRequest-class that would raise an InvalidArgumentException when setting
+  the AssertionConsumerServiceIndex as an integer on an saml:SP authsource.
+  Thanks to Andrea @ Oracle for reporting this.
 
 ## Version 1.18.7
 
 Released 2020-05-12
 
-  * Fix spurious warnings when session_create_id() fails to create ID (#1291)
-  * Fix inconsistency in the way PATH_INFO is being used (#1227).
-  * Fix a potential security issue [CVE-2020-11022](https://nvd.nist.gov/vuln/detail/CVE-2020-11022) by updating jQuery. If any of your custom modules rely on jQuery,
-      make sure you read the following [update notes](https://jquery.com/upgrade-guide/3.5/), since jQuery has solved this in a non-BC way (#1321).
-  * Fix incorrect Polish translations (#1311).
-  * Fix a broken migration query in the LogoutStore (#1324).
-  * Fix an issue with the SameSite cookie parameter when running on PHP versions older than 7.3 (#1320).
+* Fix spurious warnings when session_create_id() fails to create ID (#1291)
+* Fix inconsistency in the way PATH_INFO is being used (#1227).
+* Fix a potential security issue [CVE-2020-11022](https://nvd.nist.gov/vuln/detail/CVE-2020-11022) by updating jQuery. If any of your custom modules rely on jQuery,
+  make sure you read the following [update notes](https://jquery.com/upgrade-guide/3.5/), since jQuery has solved this in a non-BC way (#1321).
+* Fix incorrect Polish translations (#1311).
+* Fix a broken migration query in the LogoutStore (#1324).
+* Fix an issue with the SameSite cookie parameter when running on PHP versions older than 7.3 (#1320).
+
+`adfs`
+
+* Fixed a broken link to one of the assets (v0.9.6).
+
+`ldap`
+
+* Handle binary attributes in a generic way (v0.9.5).
+
+`oauth`
+
+* Fix PHP 7.4 incompatibility (v0.9.2).
+
+`preprodwarning`
 
-### adfs
-  * Fixed a broken link to one of the assets (v0.9.6).
+* Fix Dutch translations (v0.9.2).
 
-### ldap
-  * Handle binary attributes in a generic way (v0.9.5).
+`sanitycheck`
 
-### oauth
-  * Fix PHP 7.4 incompatibility (v0.9.2).
+* Fix broken HTML (v0.9.1).
 
-### preprodwarning
-  * Fix Dutch translations (v0.9.2).
+`saml`
 
-### sanitycheck
-  * Fix broken HTML (v0.9.1).
+* Fix several issues in the saml:NameIDAttribute authproc filter (#1325).
 
-### saml
-  * Fix several issues in the saml:NameIDAttribute authproc filter (#1325).
+`saml2 library`
 
-### saml2 library
-  * fixed a standards compliance issue regarding ContactPerson EMail addresses (v3.4.4).
-  * fixed an issue parsing very large metadata files (v3.4.3).
+* fixed a standards compliance issue regarding ContactPerson EMail addresses (v3.4.4).
+* fixed an issue parsing very large metadata files (v3.4.3).
 
 ## Version 1.18.6
 
 Released 2020-04-17
 
-  * Fix source code disclosure on case-insensitive file systems. See
-    [SSPSA 202004-01](https://simplesamlphp.org/security/202004-01).
-  * Fix spurious error in logs when using a custom theme (#1312).
-  * Fix broken metadata converter (#1305).
+* Fix source code disclosure on case-insensitive file systems. See
+  [SSPSA 202004-01](https://simplesamlphp.org/security/202004-01).
+* Fix spurious error in logs when using a custom theme (#1312).
+* Fix broken metadata converter (#1305).
 
 ## Version 1.18.5
 
 Released 2020-03-19
 
-  * Make the URLs for the cron module work again (#1248).
-  * Email error reports now include metadata again (#1269).
-  * Fix exampleauth module when using the legacy UI (#1275).
-  * Fix authorize module when using custom reject message.
-  * Documentation improvements.
-  * Fix connection persistence for deployments that switched to memcached.
+* Make the URLs for the cron module work again (#1248).
+* Email error reports now include metadata again (#1269).
+* Fix exampleauth module when using the legacy UI (#1275).
+* Fix authorize module when using custom reject message.
+* Documentation improvements.
+* Fix connection persistence for deployments that switched to memcached.
 
 ## Version 1.18.4
 
 Released 2020-01-24
 
-  * Resolved a security issue in email reports. See
-    [SSPSA 202001-01](https://simplesamlphp.org/security/202001-01).
-  * Resolved a security issue with the logging system. See
-    [SSPSA 202001-02](https://simplesamlphp.org/security/202001-02).
-  * Fixed SQL store index creation for PostgreSQL.
-  * Handle case where cookie 'domain' parameter was not set.
-  * Update versions of included JavaScript dependencies.
+* Resolved a security issue in email reports. See
+  [SSPSA 202001-01](https://simplesamlphp.org/security/202001-01).
+* Resolved a security issue with the logging system. See
+  [SSPSA 202001-02](https://simplesamlphp.org/security/202001-02).
+* Fixed SQL store index creation for PostgreSQL.
+* Handle case where cookie 'domain' parameter was not set.
+* Update versions of included JavaScript dependencies.
 
 ## Version 1.18.3
 
 Released 2019-12-09
 
-  * Fixed an issue with several modules being enabled by default (#1257).
-  * Fixed an issue with metadata generation for trusted entities (#1247, #1251).
+* Fixed an issue with several modules being enabled by default (#1257).
+* Fixed an issue with metadata generation for trusted entities (#1247, #1251).
 
-### ldap
-  * Fixed an issue affecting the installation in case-insensitive file systems (#1253).
+`ldap`
+
+* Fixed an issue affecting the installation in case-insensitive file systems (#1253).
 
 ## Version 1.18.2
 
 Released 2019-11-26
 
-  * Fixed an issue with the `ldap` module that prevented installing SimpleSAMLphp from the repository (#1241).
+* Fixed an issue with the `ldap` module that prevented installing SimpleSAMLphp from the repository (#1241).
 
 ## Version 1.18.1
 
 Released 2019-11-26
 
-   * Fixed an issue that prevented custom themes from working (#1240).
-   * Fixed an issue with translations in the discovery service (#1244).
-   * Fixed an issue with schema validation.
+* Fixed an issue that prevented custom themes from working (#1240).
+* Fixed an issue with translations in the discovery service (#1244).
+* Fixed an issue with schema validation.
 
 ## Version 1.18.0
 
 Released 2019-11-19
 
-  * Fixed an issue with warnings being logged when using PHP 7.2 or newer (#1168).
-  * Fixed an issue with web server aliases or rewritten URLs not working (#1023, #1093).
-  * Fixed an issue that prevented errors to be logged if the log file was not writeable (#1194).
-  * Fixed an issue with old-style NameIDPolicy configurations that disallowed creating new NameIDs (#1230).
-  * Resolved a security issue that exposed host information to unauthenticated users. See
-    [SSPSA 201911-02](https://simplesamlphp.org/security/201911-02).
-  * Replaced custom Email class with the phpmailer library.
-  * Allow logging to STDERR in the `logging.handler` option by setting it to `stderr`.
-  * Allow use of stream wrappers (e.g. s3://) in paths.
-  * Improved 'update or insert' handling for different SQL drivers.
-  * The default algorithm within the TimeLimitedToken class has been bumped from SHA-1 to SHA-256
-    as announced by deprecation notice in 1.15-RC1.
-  * Most modules have been externalized. They will not be included in our future releases by default,
-    but will be easily installable using Composer. For now, they are still included in the package.
-  * Many minor fixes to code, css, documentation
-
-### metarefresh
-  * The algorithm to compute the fingerprint of the certificate that signed
-    metadata can be specified with the new `validateFingerprintAlgorithm`
-    configuration option.
-
-### saml
-  * Make the id of the generated signed metadata only change when metadata content changes.
-  * New SP metadata configuration options `AssertionConsumerService` and `SingleLogoutServiceLocation`
-    to allow overriding the default URL paths.
-  * Added support for per-IDP configurable `AuthnContextClassRef`/`AuthnContextComparison`.
+* Fixed an issue with warnings being logged when using PHP 7.2 or newer (#1168).
+* Fixed an issue with web server aliases or rewritten URLs not working (#1023, #1093).
+* Fixed an issue that prevented errors to be logged if the log file was not writeable (#1194).
+* Fixed an issue with old-style NameIDPolicy configurations that disallowed creating new NameIDs (#1230).
+* Resolved a security issue that exposed host information to unauthenticated users. See
+  [SSPSA 201911-02](https://simplesamlphp.org/security/201911-02).
+* Replaced custom Email class with the phpmailer library.
+* Allow logging to STDERR in the `logging.handler` option by setting it to `stderr`.
+* Allow use of stream wrappers (e.g. s3://) in paths.
+* Improved 'update or insert' handling for different SQL drivers.
+* The default algorithm within the TimeLimitedToken class has been bumped from SHA-1 to SHA-256
+  as announced by deprecation notice in 1.15-RC1.
+* Most modules have been externalized. They will not be included in our future releases by default,
+  but will be easily installable using Composer. For now, they are still included in the package.
+* Many minor fixes to code, css, documentation
+
+`metarefresh`
+
+* The algorithm to compute the fingerprint of the certificate that signed
+  metadata can be specified with the new `validateFingerprintAlgorithm`
+  configuration option.
+
+`saml`
+
+* Make the id of the generated signed metadata only change when metadata content changes.
+* New SP metadata configuration options `AssertionConsumerService` and `SingleLogoutServiceLocation`
+  to allow overriding the default URL paths.
+* Added support for per-IDP configurable `AuthnContextClassRef`/`AuthnContextComparison`.
 
 ## Version 1.17.8
 
 Released 2019-11-20
 
-  * Resolved a security issue that exposed host information to unauthenticated users. See
-    [SSPSA 201911-02](https://simplesamlphp.org/security/201911-02).
+* Resolved a security issue that exposed host information to unauthenticated users. See
+  [SSPSA 201911-02](https://simplesamlphp.org/security/201911-02).
 
-### consentAdmin
+`consentAdmin`
 
-  * Fixed an issue with CSS and JavaScript not loading for the module in the new user
-    interface.
+* Fixed an issue with CSS and JavaScript not loading for the module in the new user
+  interface.
 
 ## Version 1.17.7
 
 Released 2019-11-06
 
-  * Resolved a security issue that allows to bypass signature validation. See
-    [SSPSA 201911-01](https://simplesamlphp.org/security/201911-01).
+* Resolved a security issue that allows to bypass signature validation. See
+  [SSPSA 201911-01](https://simplesamlphp.org/security/201911-01).
 
 ## Version 1.17.6
 
 Released 2019-08-29
 
-  * Fixed a regression with logout database initialization when using MySQL (#1177).
-  * Fixed an issue with logout when using iframes (#1191).
-  * Fixed an issue causing log entries to be logged with incorrect relative order (#1107).
+* Fixed a regression with logout database initialization when using MySQL (#1177).
+* Fixed an issue with logout when using iframes (#1191).
+* Fixed an issue causing log entries to be logged with incorrect relative order (#1107).
 
 ## Version 1.17.5
 
 Released 2019-08-02
 
-  * Fixed a bug in the SP API where NameID objects weren't taken care of (introduced in 1.17.0).
-  * Fixed a regression where MetaDataStorageHandlerPdo::getMetaData() would not return a value (#1165).
-  * Fixed an issue with table indexes (#1089).
-  * Fixed an issue with table migrations on SQlite (#1169).
-  * Fixed an issue with generated eduPersonTargetedID lacking a format specified (#1135).
-  * Updated composer dependencies.
+* Fixed a bug in the SP API where NameID objects weren't taken care of (introduced in 1.17.0).
+* Fixed a regression where MetaDataStorageHandlerPdo::getMetaData() would not return a value (#1165).
+* Fixed an issue with table indexes (#1089).
+* Fixed an issue with table migrations on SQlite (#1169).
+* Fixed an issue with generated eduPersonTargetedID lacking a format specified (#1135).
+* Updated composer dependencies.
 
 ## Version 1.17.4
 
 Released 2019-07-11
 
-  * Fix an issue introduced in 1.17.3 with `enable.http_post`.
+* Fix an issue introduced in 1.17.3 with `enable.http_post`.
   
 ## Version 1.17.3
 
 Released 2019-07-10
 
-  * Resolved a security issue that could lead to a reflected XSS.  See
-    [SSPSA 201907-01](https://simplesamlphp.org/security/201907-01).
-  * Add new options `session.cookie.samesite` and `language.cookie.samesite` that can be
-    used to set a specific value for the cookies' SameSite attribute. The default it not
-    to set it.
-  * Upgraded jQuery to version 3.4.
-  * HHVM is no longer supported.
-  * Fixed a bug (#926) where dynamic metadata records where not loaded from a database.
-  * Fixed an issue when an error occurs during a passive authentication request.
-  * Handle duplicate insertions for SQL Server.
-  * Fix a bug in Short SSO Interval warning filter.
-  * Apply a workaround for SIGSEGVs during session creation with PHP-FPM 7.3.
-
-### adfs
-  * Fixed a missing option to supply a passphrase for the ADFS IDP signing certificate.
-
-### authlinkedin
-  * This module has been removed now that LinkedIn no longer supports OAuth1.
-    If you relied on this module, you may consider migrating to the
-    [authoauth2 module](https://github.com/cirrusidentity/simplesamlphp-module-authoauth2).
-    A migration guide for LinkedIn authentication is included in their README.
+* Resolved a security issue that could lead to a reflected XSS.  See
+  [SSPSA 201907-01](https://simplesamlphp.org/security/201907-01).
+* Add new options `session.cookie.samesite` and `language.cookie.samesite` that can be
+  used to set a specific value for the cookies' SameSite attribute. The default it not
+  to set it.
+* Upgraded jQuery to version 3.4.
+* HHVM is no longer supported.
+* Fixed a bug (#926) where dynamic metadata records where not loaded from a database.
+* Fixed an issue when an error occurs during a passive authentication request.
+* Handle duplicate insertions for SQL Server.
+* Fix a bug in Short SSO Interval warning filter.
+* Apply a workaround for SIGSEGVs during session creation with PHP-FPM 7.3.
+
+`adfs`
+
+* Fixed a missing option to supply a passphrase for the ADFS IDP signing certificate.
+
+`authlinkedin`
+
+* This module has been removed now that LinkedIn no longer supports OAuth1.
+  If you relied on this module, you may consider migrating to the
+  [authoauth2 module](https://github.com/cirrusidentity/simplesamlphp-module-authoauth2).
+  A migration guide for LinkedIn authentication is included in their README.
 
 ## Version 1.17.2
 
 Released 2019-04-02
 
-  * Fixed that generated metadata was missing some information
-    when PHP's zend.assertions option is set to < 1.
-  * Fixed that MDUI Keywords and Logo were not parsed from metadata.
-  * Fixed DiscoPower module tab display.
-  * Fixed use group name in Attribute Add Users Groups filter.
-  * Add metadatadir setting to the default config template.
-  * Fixed exception processing in loadExceptionState().
-  * Fixed preferredidp in built-in 'links'-style discovery.
+* Fixed that generated metadata was missing some information
+  when PHP's zend.assertions option is set to < 1.
+* Fixed that MDUI Keywords and Logo were not parsed from metadata.
+* Fixed DiscoPower module tab display.
+* Fixed use group name in Attribute Add Users Groups filter.
+* Add metadatadir setting to the default config template.
+* Fixed exception processing in loadExceptionState().
+* Fixed preferredidp in built-in 'links'-style discovery.
 
 ## Version 1.17.1
 
 Released 2019-03-07
 
-  * Fixed an issue with composer that made it impossible to install modules
-    if SimpleSAMLphp was installed itself with the provided package (tar.gz file).
+* Fixed an issue with composer that made it impossible to install modules
+  if SimpleSAMLphp was installed itself with the provided package (tar.gz file).
 
 ## Version 1.17.0
 
 Released 2019-03-07
 
-  * Introduce a new experimental user interface based on Twig templates.
-    The new Twig templates co-exist next to the old ones and come
-    with a new look-and-feel for SimpleSAMLphp and independent interfaces for
-    users and administrators. This new interface uses also a new build system
-    to generate bundled assets.
-  * Introduce Symfony-style routing and dependency injection(#966).
-  * Generate session IDs complying with PHP config settings when using the PHP
-    session handler (#569).
-  * Update OpenSSL RSA bit length in docs (#993).
-  * Update all code, configuration templates and documentation to PHP
-    short array syntax.
-  * All classes moved to namespaces and code reformatted to PSR-2.
-  * Use bcrypt for new password hashes, old ones will remain working (#996).
-  * Many code cleanups.
-  * Update the SAML2 library dependency to 3.2.5.
-  * Update the Clipboard.JS library dependency to 2.0.4.
-  * Translated to Zulu and Xhosa.
-  * Multiple bug fixes and corrections.
+* Introduce a new experimental user interface based on Twig templates.
+  The new Twig templates co-exist next to the old ones and come
+  with a new look-and-feel for SimpleSAMLphp and independent interfaces for
+  users and administrators. This new interface uses also a new build system
+  to generate bundled assets.
+* Introduce Symfony-style routing and dependency injection(#966).
+* Generate session IDs complying with PHP config settings when using the PHP
+  session handler (#569).
+* Update OpenSSL RSA bit length in docs (#993).
+* Update all code, configuration templates and documentation to PHP
+  short array syntax.
+* All classes moved to namespaces and code reformatted to PSR-2.
+* Use bcrypt for new password hashes, old ones will remain working (#996).
+* Many code cleanups.
+* Update the SAML2 library dependency to 3.2.5.
+* Update the Clipboard.JS library dependency to 2.0.4.
+* Translated to Zulu and Xhosa.
+* Multiple bug fixes and corrections.
 
 ### Interoperability
-  * The minimum PHP version required is now 5.5.
-  * Fixed compatibility with PHP 7.3 and HVVM.
-  * SimpleSAMLphp can now be used with applications that use Twig 2 and/or Symfony 4.
-  * The SAML2 library now uses getters/setters to manipulate objects properties.
-
-### authfacebook
-  * Fix Facebook compatibility (query parameters).
-
-### authorize
-  * Add the possibility to configure a custom rejection message.
-
-### consent
-  * The module is now disabled by default.
-
-### core
-  * Allow `core:PHP` to manipulate the entire state array.
-  * IdP initiated login: add compatibility with Shibboleth parameters.
-
-### multiauth
-  * Added a `preselect` configuration option to skip authsource selection (#1005).
-
-### negotiate
-  * The `keytab` setting now allows for relative paths too.
-
-### preprodwarning
-  * This module is now deprecated. Use the `production` configuration
-    option instead; set it to `false` to show a pre-production warning
-    before authentication.
-
-### saml
-  * Add initial support for SAML Subject ID Attributes.
-  * Allow to specify multiple supported NameIdFormats in IdP hosted and SP
-    remote metadata.
-  * Allow to specify NameIDPolicy Format and AllowCreate in hosted SP
-    and remote IdP configuration. Restore the possibility to omit it from
-    AuthnRequests entirely (#984).
-  * Add a `assertion.allowed_clock_skew` setting to influence how lenient
-    we should be with the timestamps in received SAML messages.
-  * If the Issuer of a SAML response does not match the entity we sent the
-    request to, log a warning instead of bailing out with an exception.
-  * Allow setting the AudienceRestriction in SAML2 requests (#998).
-  * Allow disabling the Scoping element in SP and remote IdP configuration with
-    the `disable_scoping` option, for compatibility with ADFS which does not
-    accept the element (#985).
-  * Receiving an eduPersonTargetedID in string form will no longer break
-    parsing of the assertion.
-
-### sanitycheck
-  * Translated into several languages.
+
+* The minimum PHP version required is now 5.5.
+* Fixed compatibility with PHP 7.3 and HVVM.
+* SimpleSAMLphp can now be used with applications that use Twig 2 and/or Symfony 4.
+* The SAML2 library now uses getters/setters to manipulate objects properties.
+
+`authfacebook`
+
+* Fix Facebook compatibility (query parameters).
+
+`authorize`
+
+* Add the possibility to configure a custom rejection message.
+
+`consent`
+
+* The module is now disabled by default.
+
+`core`
+
+* Allow `core:PHP` to manipulate the entire state array.
+* IdP initiated login: add compatibility with Shibboleth parameters.
+
+`multiauth
+
+* Added a `preselect` configuration option to skip authsource selection (#1005).
+
+`negotiate`
+
+* The `keytab` setting now allows for relative paths too.
+
+`preprodwarning`
+
+* This module is now deprecated. Use the `production` configuration
+  option instead; set it to `false` to show a pre-production warning
+  before authentication.
+
+`saml`
+
+* Add initial support for SAML Subject ID Attributes.
+* Allow to specify multiple supported NameIdFormats in IdP hosted and SP
+  remote metadata.
+* Allow to specify NameIDPolicy Format and AllowCreate in hosted SP
+  and remote IdP configuration. Restore the possibility to omit it from
+  AuthnRequests entirely (#984).
+* Add a `assertion.allowed_clock_skew` setting to influence how lenient
+  we should be with the timestamps in received SAML messages.
+* If the Issuer of a SAML response does not match the entity we sent the
+  request to, log a warning instead of bailing out with an exception.
+* Allow setting the AudienceRestriction in SAML2 requests (#998).
+* Allow disabling the Scoping element in SP and remote IdP configuration with
+  the `disable_scoping` option, for compatibility with ADFS which does not
+  accept the element (#985).
+* Receiving an eduPersonTargetedID in string form will no longer break
+  parsing of the assertion.
+
+`sanitycheck`
+
+* Translated into several languages.
 
 ## Version 1.16.3
 
 Released 2018-12-20
 
-  * Resolved a security issue that could expose the user's credentials locally.  See
-    [SSPSA 201812-01](https://simplesamlphp.org/security/201812-01).
-  * Downgraded the level of log messages regarding the `userid.attribute` configuration option
-    from _warning_ to _debug_.
-  * Make the `attr` configuration option of the _negotiate_ allow both a string and an array.
-  * Look for the _keytab_ file used by the _negotiate_ module in the `cert` directory, accepting
-    both absolute and relative paths.
-  * Fixed some broken links.
-  * Other minor bugfixes.
+* Resolved a security issue that could expose the user's credentials locally.  See
+  [SSPSA 201812-01](https://simplesamlphp.org/security/201812-01).
+* Downgraded the level of log messages regarding the `userid.attribute` configuration option
+  from _warning_ to _debug_.
+* Make the `attr` configuration option of the _negotiate_ allow both a string and an array.
+* Look for the _keytab_ file used by the _negotiate_ module in the `cert` directory, accepting
+  both absolute and relative paths.
+* Fixed some broken links.
+* Other minor bugfixes.
 
 ## Version 1.16.2
 
 Released 2018-09-28
 
-  * Fixed an issue with PHP sessions in PHP 7.2.
-  * Fixed a bug in the OAuth module.
-  * Make schema validation work again.
-  * Properly document the `saml:AuthnContextClassRef` authentication processing filter.
-  * Fixed an issue that made it impossible to install the software with composer using the
-    "stable" minimum-stability setting.
-  * Changed the default authentication context class to "PasswordProtectedTransport" by default
-    when authentication happened on an HTTPS exchange.
+* Fixed an issue with PHP sessions in PHP 7.2.
+* Fixed a bug in the OAuth module.
+* Make schema validation work again.
+* Properly document the `saml:AuthnContextClassRef` authentication processing filter.
+* Fixed an issue that made it impossible to install the software with composer using the
+  "stable" minimum-stability setting.
+* Changed the default authentication context class to "PasswordProtectedTransport" by default
+  when authentication happened on an HTTPS exchange.
 
 ## Version 1.16.1
 
 Released 2018-09-07
 
-  * Fix a bug preventing the consent page from showing.
-  * Add Catalan to the list of available languages.
+* Fix a bug preventing the consent page from showing.
+* Add Catalan to the list of available languages.
 
 ## Version 1.16.0
 
 Released 2018-09-06
 
 ### Changes
-  * Default signature algorithm is now RSA-SHA256.
-  * Renamed class `SimpleSAML_Error_BadUserInnput` to `SimpleSAML_Error_BadUserInput`
-  * PHP 7.2 compatibility, including removing deprecated use of assert with string.
-  * Avoid logging database credentials in backtraces.
-  * Fix edge case in getServerPort.
-  * Updated Spanish translation.
-  * Improvements to documentation, testsuite, code quality and coding style.
-
-### New features
-  * Added support for SAML "Enhanced Client or Proxy" (ECP) protocol,
-    IdP side with HTTP Basic Authentication as authentication method.
-    See the [ECP IdP documentation](./simplesamlphp-ecp-idp) for details.
-  * New option `sendmail_from`, the from address for email sent by SSP.
-  * New option `options` for PDO database connections, e.g. for TLS setup.
-  * New option `search.scope` for LDAP authsources.
-  * Add support for the DiscoHints IPHint metadata property.
-  * Add support to specify metadata XML in config with the `xml` parameter,
-    next to the existing `file` and `url` options.
-  * Also support CGI/RewriteRule setups that set the `REDIRECT_SIMPLESAMLPHP_CONFIG_DIR`
-    environment variable next to regular `SIMPLESAMLPHP_CONFIG_DIR`.
-  * Support creating an AuthSource via factory, for example useful in tests.
-  * Support preloading of a virtual config file via `SimpleSAML_Configuration::setPreLoadedConfig`
-    to allow for dynamic population of authsources.php.
-  * Add basic documentation on Nginx configuration.
-  * Test authentication: optionally show AuthData array.
-  * Improve performance of PDO Metadata Storage handler entity lookup.
-
-### adfs
-  * Make signature algorithm configurable with `signature.algorithm`.
-  * Use configuration assertion lifetime when available.
-  * Use `adfs:wreply` parameter when available.
-
-### authmyspace
-  * Module removed because service is no longer available.
-
-### cas
-  * Respect all LDAP options in LDAP call.
-
-### casserver
-  * Module removed; superseded by externally hosted module.
-
-### consent
-  * Sort attribute values for consent.
-  * Fix table layout for MySQL > 5.6.
-  * Rename `noconsentattributes` to `attributes.exclude`; the former
-    is now considered deprecated.
-
-### consentAdmin
-  * Work better with TargetedIDs when operating as a proxy.
-  * Add `attributes.exclude` option to correspond to the same option
-    in the Consent module.
-
-### core
-  * StatisticsWithAttribute: add `passive-` prefix when logging passive
-    requests, set new option `skipPassive` to skip logging these altogether.
-  * Replace deprecated `create_function` with an anonymous function.
-  * New authproc filter Cardinality to enforce attribute cardinality.
-  * SQLPermanentStorage: proper expiration of stored values.
-  * AttributeLimit: new options `regex` and `ignoreCase`.
-  * AttributeMap: prevent possible infinite loop with some PHP versions.
-
-### ldap
-  * AttributeAddUsersGroups: if `attribute.groupname` is set, use the
-    configured attribute as the group name rather than the DN.
-  * Also base64encode the `ms-ds-consistencyguid` attribute.
-
-### metarefresh
-  * Return XML parser error for better debugging of problems.
-  * Only actually parse metadata types that have been enabled.
-  * Fix missing translation.
-
-### Oauth
-  * Make module HTTP proxy-aware.
-  * Remove unused demo app.
-
-### saml
-  * AttributeConsumingService: allow to set isDefault and index options.
-  * Encrypted attributes in an assertion are now decrypted correctly.
-  * Prefer the HTTP-Redirect binding for AuthnRequests if available.
-
-### smartattributes
-  * Fix to make the `add_authority` option work.
-
-### sqlauth
-  * The module is now disabled by default.
-
-### statistics
-  * Show a decent error message when no data is available.
+
+* Default signature algorithm is now RSA-SHA256.
+* Renamed class `SimpleSAML_Error_BadUserInnput` to `SimpleSAML_Error_BadUserInput`
+* PHP 7.2 compatibility, including removing deprecated use of assert with string.
+* Avoid logging database credentials in backtraces.
+* Fix edge case in getServerPort.
+* Updated Spanish translation.
+* Improvements to documentation, testsuite, code quality and coding style.
+
+`New features`
+
+* Added support for SAML "Enhanced Client or Proxy" (ECP) protocol,
+  IdP side with HTTP Basic Authentication as authentication method.
+  See the [ECP IdP documentation](./simplesamlphp-ecp-idp) for details.
+* New option `sendmail_from`, the from address for email sent by SSP.
+* New option `options` for PDO database connections, e.g. for TLS setup.
+* New option `search.scope` for LDAP authsources.
+* Add support for the DiscoHints IPHint metadata property.
+* Add support to specify metadata XML in config with the `xml` parameter,
+  next to the existing `file` and `url` options.
+* Also support CGI/RewriteRule setups that set the `REDIRECT_SIMPLESAMLPHP_CONFIG_DIR`
+  environment variable next to regular `SIMPLESAMLPHP_CONFIG_DIR`.
+* Support creating an AuthSource via factory, for example useful in tests.
+* Support preloading of a virtual config file via `SimpleSAML_Configuration::setPreLoadedConfig`
+  to allow for dynamic population of authsources.php.
+* Add basic documentation on Nginx configuration.
+* Test authentication: optionally show AuthData array.
+* Improve performance of PDO Metadata Storage handler entity lookup.
+
+`adfs`
+
+* Make signature algorithm configurable with `signature.algorithm`.
+* Use configuration assertion lifetime when available.
+* Use `adfs:wreply` parameter when available.
+
+`authmyspace`
+
+* Module removed because service is no longer available.
+
+`cas`
+
+* Respect all LDAP options in LDAP call.
+
+`casserver`
+
+* Module removed; superseded by externally hosted module.
+
+`consent`
+
+* Sort attribute values for consent.
+* Fix table layout for MySQL > 5.6.
+* Rename `noconsentattributes` to `attributes.exclude`; the former
+  is now considered deprecated.
+
+`consentAdmin`
+
+* Work better with TargetedIDs when operating as a proxy.
+* Add `attributes.exclude` option to correspond to the same option
+  in the Consent module.
+
+`core`
+
+* StatisticsWithAttribute: add `passive-` prefix when logging passive
+  requests, set new option `skipPassive` to skip logging these altogether.
+* Replace deprecated `create_function` with an anonymous function.
+* New authproc filter Cardinality to enforce attribute cardinality.
+* SQLPermanentStorage: proper expiration of stored values.
+* AttributeLimit: new options `regex` and `ignoreCase`.
+* AttributeMap: prevent possible infinite loop with some PHP versions.
+
+`ldap`
+
+* AttributeAddUsersGroups: if `attribute.groupname` is set, use the
+  configured attribute as the group name rather than the DN.
+* Also base64encode the `ms-ds-consistencyguid` attribute.
+
+`metarefresh`
+
+* Return XML parser error for better debugging of problems.
+* Only actually parse metadata types that have been enabled.
+* Fix missing translation.
+
+`oauth`
+
+* Make module HTTP proxy-aware.
+* Remove unused demo app.
+
+`saml`
+
+* AttributeConsumingService: allow to set isDefault and index options.
+* Encrypted attributes in an assertion are now decrypted correctly.
+* Prefer the HTTP-Redirect binding for AuthnRequests if available.
+
+`smartattributes`
+
+* Fix to make the `add_authority` option work.
+
+`sqlauth`
+
+* The module is now disabled by default.
+
+`statistics`
+
+* Show a decent error message when no data is available.
 
 ## Version 1.15.4
 
 Released 2018-03-02
 
-  * Resolved a security issue related to signature validation in the SAML2 library. See [SSPSA 201803-01](https://simplesamlphp.org/security/201803-01).
+* Resolved a security issue related to signature validation in the SAML2 library. See [SSPSA 201803-01](https://simplesamlphp.org/security/201803-01).
 
 ## Version 1.15.3
 
 Released 2018-02-27
 
-  * Resolved a security issue related to signature validation in the SAML2 library. See [SSPSA 201802-01](https://simplesamlphp.org/security/201802-01).
-  * Fixed edge-case scenario where an application uses one of the known LoggingHandlers' name as a defined class
-  * Fixed issue #793 in the PHP logging handler.
+* Resolved a security issue related to signature validation in the SAML2 library. See [SSPSA 201802-01](https://simplesamlphp.org/security/201802-01).
+* Fixed edge-case scenario where an application uses one of the known LoggingHandlers' name as a defined class
+* Fixed issue #793 in the PHP logging handler.
 
 ## Version 1.15.2
 
 Released 2018-01-31
 
-  * Resolved a Denial of Service security issue when validating timestamps in the SAML2 library. See [SSPSA 201801-01](https://simplesamlphp.org/security/201801-01).
-  * Resolved a security issue with the open redirect protection mechanism. See [SSPSA 201801-02](https://simplesamlphp.org/security/201801-02).
-  * Fix _undefined method_ error when using memcacheD.
+* Resolved a Denial of Service security issue when validating timestamps in the SAML2 library. See [SSPSA 201801-01](https://simplesamlphp.org/security/201801-01).
+* Resolved a security issue with the open redirect protection mechanism. See [SSPSA 201801-02](https://simplesamlphp.org/security/201801-02).
+* Fix _undefined method_ error when using memcacheD.
+
+`authfacebook`
+
+* Fix compatibility with Facebook strict URI match.
 
-### `authfacebook`
-  * Fix compatibility with Facebook strict URI match.
+`consent`
 
-### `consent`
-  * Fix statistics not being gathered.
+* Fix statistics not being gathered.
 
-### `sqlauth`
-  * Prevented a security issue with the connection charset used for MySQL backends. See [SSPSA 201801-03](https://simplesamlphp.org/security/201801-03).
+`sqlauth`
+
+* Prevented a security issue with the connection charset used for MySQL backends. See [SSPSA 201801-03](https://simplesamlphp.org/security/201801-03).
 
 ## Version 1.15.1
 
 Released 2018-01-12
 
-### Bug fixes
-  * AuthX509 error messages were broken.
-  * Properly calculate supported protocols based on config.
-  * NameIDAttribute filter: update to use SAML2\XML\saml\NameID.
-  * Replace remaining uses of SimpleSAML_Logger with namespace version.
-  * Statistics: prevent mixed content errors.
-  * Add 'no-store' to the cache-control header to avoid Chrome
-    caching redirects.
+`Bug fixes`
+
+* AuthX509 error messages were broken.
+* Properly calculate supported protocols based on config.
+* NameIDAttribute filter: update to use SAML2\XML\saml\NameID.
+* Replace remaining uses of SimpleSAML_Logger with namespace version.
+* Statistics: prevent mixed content errors.
+* Add 'no-store' to the cache-control header to avoid Chrome
+  caching redirects.
 
 ## Version 1.15.0
 
 Released 2017-11-20
 
-### New features
-  * Added support for authenticated web proxies with the `proxy.auth` setting.
-  * Added new `AttributeValueMap` authproc filter.
-  * Added attributemaps for OIDs from SIS (Swedish Standards Institute) and
-    for eduPersonUniqueId, eduPersonOrcid and sshPublicKey.
-  * Added an option to specify metadata signing and digest algorithm
-    `metadata.sign.algorithm`.
-  * Added an option for regular expression matching of trusted.url.domains via new
-    `trusted.url.regex` setting.
-  * The `debug` option is more finegrained and allows one to specify whether
-    to log full SAML messages, backtraces or schema validations separately.
-  * Added a check for the latest SimpleSAMLphp version on the front page.
-    It can be disabled via the new setting `admin.checkforupdates`.
-  * Added a warning when there's a probable misconfiguration of PHP sessions.
-  * Added ability to define additional attributes on ContactPerson elements
-    in metadata, e.g. for use in Sirtfi contacts.
-  * Added option to set a secure flag also on the language cookie.
-  * Added option to specify the base URL for the application protected.
-  * Added support for PHP Memcached extension next to Memcache extension.
-  * Added Redis as possible session storage mechanism.
-  * Added support to specify custom metadata storage handlers.
-  * Invalidate opcache after writing a file, so simpleSAMLphp works when
-    `opcache.validate_timestamps` is disabled.
-  * Metadata converter will deal properly with XML with leading whitespace.
-  * Update `ldapwhoami()` call for PHP 7.3.
-  * Made response POST page compatible with strict Content Security Policy on
-    calling webpage.
-  * Updated Greek, Polish, Traditional Chinese and Spanish translations and
-    added Afrikaans.
-
-### Bug fixes
-  * The deprecated OpenIdP has been removed from the metadata template.
-  * Trailing slash is no longer required in `baseurlpath`.
-  * Make redirections more resilient.
-  * Fixed empty protocolSupportEnumeration in AttributeAuthorityDescriptor.
-  * Other bug fixes and numerous documentation enhancements.
-  * Fixed a bug in the Redis store that could lead to incorrect
-    _duplicate assertion_ errors.
-
-### API and user interface
-  * Updated to Xmlseclibs 3.0.
-    Minimum PHP version is now 5.4, mcrypt requirement dropped.
-  * Added a PSR-4 autoloader for modules. Now modules can declare their
-    classes under the SimpleSAML\Module namespace.
-  * Added new hook for module loader exception handling `exception_handler`.
-  * Expose RegistrationInfo in parsed SAML metadata.
-  * The AuthnInstant is now available in the state array.
-  * Introduced Twig templating for user interface.
-  * Lots of refactoring, code cleanup and added many unit tests.
-
-### `adfs`
-  * Fixed POST response form parameter encoding.
-
-### `authYubiKey`
-  * Fixed PHP 7 support.
-
-### `authfacebook`
-  * Updated to work with latest Facebook API.
-
-### `authlinkedin`
-  * Added setting `attributes` to specify which attributes to request
-    from LinkedIn.
-
-### `authtwitter`
-  * Added support for fetching the user's email address as attribute.
-
-### `consent`
-  * Added support for regular expressions in `consent.disable`.
-
-### `core`
-  * Added logging of `REMOTE_ADDR` on successful login.
-  * `AttributeMap`: allow fetching mapping files from modules.
-  * `ScopeAttribute`: added option `onlyIfEmpty` to add a scope only if
-     none was present.
-  * `AttributeCopy`: added option to copy to multiple destination attributes.
-
-### `cron`
-  * Allow invocation via PHP command line interface.
-
-### `discopower`
-  * Added South Africa tab.
-
-### `ldap`
-  * Added `search.filter` setting to limit LDAP queries to a custom search
-    filter.
-  * Added OpenLDAP support in AttributeAddUsersGroups.
-  * Fixed for using non standard LDAP port numbers.
-  * Fixed configuration option of whether to follow LDAP referrals.
-
-### `memcacheMonitor`
-  * Fixed several missing strings.
-
-### `metarefresh`
-  * Fixed several spurious PHP notices.
-
-### `multiauth`
-  * Fixed selected source timeout.
-
-### `negotiate`
-  * Fixed authentication failure on empty attributes-array.
-  * Fixed PHP notices concerning missing arguments.
-
-### `oauth`
-  * Updated library to improve support for OAuth 1.0 Revision A.
-
-### `radius`
-  * Improved error messages.
-  * Added parameter `realm` that will be suffixed to the username entered.
-
-### `saml`
-  * Handle instead of reject assertions that do not contain a NameID.
-  * Added options to configure `AllowCreate` and `SPNameQualifier`.
-  * Added option `saml:NameID` to set the Subject NameID in a SAML AuthnRequest.
-  * Added filter `FilterScopes` to remove values which are not properly scoped.
-  * Make sure we log the user out before reauthenticating.
-  * More robust handling of IDPList support in proxy mode.
-  * Increased `_authSource` field length in Logout Store.
-  * We now send the eduPersonTargetedID attribute in the correct
-    NameID XML form, instead of the incorrect simple string. We will also
-    refuse to parse an assertion with an eduPersonTargetedID in 'string' format.
-
-### `smartattributes`
-  * Fix SmartName authproc that failed to load.
-
-### `sqlauth`
-  * Fixed SQL schema for usergroups table.
+`New features`
+
+* Added support for authenticated web proxies with the `proxy.auth` setting.
+* Added new `AttributeValueMap` authproc filter.
+* Added attributemaps for OIDs from SIS (Swedish Standards Institute) and
+  for eduPersonUniqueId, eduPersonOrcid and sshPublicKey.
+* Added an option to specify metadata signing and digest algorithm
+  `metadata.sign.algorithm`.
+* Added an option for regular expression matching of trusted.url.domains via new
+  `trusted.url.regex` setting.
+* The `debug` option is more finegrained and allows one to specify whether
+  to log full SAML messages, backtraces or schema validations separately.
+* Added a check for the latest SimpleSAMLphp version on the front page.
+  It can be disabled via the new setting `admin.checkforupdates`.
+* Added a warning when there's a probable misconfiguration of PHP sessions.
+* Added ability to define additional attributes on ContactPerson elements
+  in metadata, e.g. for use in Sirtfi contacts.
+* Added option to set a secure flag also on the language cookie.
+* Added option to specify the base URL for the application protected.
+* Added support for PHP Memcached extension next to Memcache extension.
+* Added Redis as possible session storage mechanism.
+* Added support to specify custom metadata storage handlers.
+* Invalidate opcache after writing a file, so simpleSAMLphp works when
+  `opcache.validate_timestamps` is disabled.
+* Metadata converter will deal properly with XML with leading whitespace.
+* Update `ldapwhoami()` call for PHP 7.3.
+* Made response POST page compatible with strict Content Security Policy on
+  calling webpage.
+* Updated Greek, Polish, Traditional Chinese and Spanish translations and
+  added Afrikaans.
+
+`Bug fixes`
+
+* The deprecated OpenIdP has been removed from the metadata template.
+* Trailing slash is no longer required in `baseurlpath`.
+* Make redirections more resilient.
+* Fixed empty protocolSupportEnumeration in AttributeAuthorityDescriptor.
+* Other bug fixes and numerous documentation enhancements.
+* Fixed a bug in the Redis store that could lead to incorrect
+  _duplicate assertion_ errors.
+
+`API and user interface`
+
+* Updated to Xmlseclibs 3.0.
+  Minimum PHP version is now 5.4, mcrypt requirement dropped.
+* Added a PSR-4 autoloader for modules. Now modules can declare their
+  classes under the SimpleSAML\Module namespace.
+* Added new hook for module loader exception handling `exception_handler`.
+* Expose RegistrationInfo in parsed SAML metadata.
+* The AuthnInstant is now available in the state array.
+* Introduced Twig templating for user interface.
+* Lots of refactoring, code cleanup and added many unit tests.
+
+`adfs`
+
+* Fixed POST response form parameter encoding.
+
+`authYubiKey`
+
+* Fixed PHP 7 support.
+
+`authfacebook`
+
+* Updated to work with latest Facebook API.
+
+`authlinkedin`
+
+* Added setting `attributes` to specify which attributes to request
+  from LinkedIn.
+
+`authtwitter`
+
+* Added support for fetching the user's email address as attribute.
+
+`consent`
+
+* Added support for regular expressions in `consent.disable`.
+
+`core`
+
+* Added logging of `REMOTE_ADDR` on successful login.
+* `AttributeMap`: allow fetching mapping files from modules.
+* `ScopeAttribute`: added option `onlyIfEmpty` to add a scope only if
+   none was present.
+* `AttributeCopy`: added option to copy to multiple destination attributes.
+
+`cron`
+
+* Allow invocation via PHP command line interface.
+
+`discopower`
+
+* Added South Africa tab.
+
+`ldap`
+
+* Added `search.filter` setting to limit LDAP queries to a custom search
+  filter.
+* Added OpenLDAP support in AttributeAddUsersGroups.
+* Fixed for using non standard LDAP port numbers.
+* Fixed configuration option of whether to follow LDAP referrals.
+
+`memcacheMonitor`
+
+* Fixed several missing strings.
+
+`metarefresh`
+
+* Fixed several spurious PHP notices.
+
+`multiauth`
+
+* Fixed selected source timeout.
+
+`negotiate`
+
+* Fixed authentication failure on empty attributes-array.
+* Fixed PHP notices concerning missing arguments.
+
+`oauth`
+
+* Updated library to improve support for OAuth 1.0 Revision A.
+
+`radius`
+
+* Improved error messages.
+* Added parameter `realm` that will be suffixed to the username entered.
+
+`saml`
+
+* Handle instead of reject assertions that do not contain a NameID.
+* Added options to configure `AllowCreate` and `SPNameQualifier`.
+* Added option `saml:NameID` to set the Subject NameID in a SAML AuthnRequest.
+* Added filter `FilterScopes` to remove values which are not properly scoped.
+* Make sure we log the user out before reauthenticating.
+* More robust handling of IDPList support in proxy mode.
+* Increased `_authSource` field length in Logout Store.
+* We now send the eduPersonTargetedID attribute in the correct
+  NameID XML form, instead of the incorrect simple string. We will also
+  refuse to parse an assertion with an eduPersonTargetedID in 'string' format.
+
+`smartattributes`
+
+* Fix SmartName authproc that failed to load.
+
+`sqlauth`
+
+* Fixed SQL schema for usergroups table.
 
 ## Version 1.14.17
 
 Released 2017-10-25
 
-  * Resolved a security issue with the SAML 1.1 Service Provider. See [SSPSA 201710-01](https://simplesamlphp.org/security/201710-01).
+* Resolved a security issue with the SAML 1.1 Service Provider. See [SSPSA 201710-01](https://simplesamlphp.org/security/201710-01).
 
 ## Version 1.14.16
 
 Released 2017-09-04
 
-  * Resolved a security issue in the consentAdmin module. See [SSPSA 201709-01](https://simplesamlphp.org/security/201709-01).
+* Resolved a security issue in the consentAdmin module. See [SSPSA 201709-01](https://simplesamlphp.org/security/201709-01).
 
 ## Version 1.14.15
 
 Released 2017-08-08
 
-  * Resolved a security issue with the creation and validation of time-limited tokens. See [SSPSA 201708-01](https://simplesamlphp.org/security/201708-01).
-  * Fixed an issue with session handling that could lead to crashes after upgrading from earlier 1.14.x versions.
-  * Fixed issue #557 with instances of SimpleSAMLphp installed from the repository as well as custom modules.
-  * Fixed issue #648 to properly handle SAML responses being sent to reply the same request, but using different response IDs.
-  * Fixed issues #612 and #618 with the mobile view of the web interface.
-  * Fixed issue #639 related to IdP names containing special characters not being properly displayed by discopower.
-  * Fixed issue #571 causing timeouts when using Active Directory as a backend.
-  * Other minor fixes.
+* Resolved a security issue with the creation and validation of time-limited tokens. See [SSPSA 201708-01](https://simplesamlphp.org/security/201708-01).
+* Fixed an issue with session handling that could lead to crashes after upgrading from earlier 1.14.x versions.
+* Fixed issue #557 with instances of SimpleSAMLphp installed from the repository as well as custom modules.
+* Fixed issue #648 to properly handle SAML responses being sent to reply the same request, but using different response IDs.
+* Fixed issues #612 and #618 with the mobile view of the web interface.
+* Fixed issue #639 related to IdP names containing special characters not being properly displayed by discopower.
+* Fixed issue #571 causing timeouts when using Active Directory as a backend.
+* Other minor fixes.
 
 ## Version 1.14.14
 
 Released 2017-05-05
 
-  * Resolved a security issue with in the authcrypt module (Htpasswd authentication source) and in SimpleSAMLphp's session validation. See [SSPSA 201705-01](https://simplesamlphp.org/security/201705-01).
-  * Resolved a security issue with in the multiauth module. See [SSPSA 201704-02](https://simplesamlphp.org/security/201704-02).
+* Resolved a security issue with in the authcrypt module (Htpasswd authentication source) and in SimpleSAMLphp's session validation. See [SSPSA 201705-01](https://simplesamlphp.org/security/201705-01).
+* Resolved a security issue with in the multiauth module. See [SSPSA 201704-02](https://simplesamlphp.org/security/201704-02).
 
 ## Version 1.14.13
 
 Released 2017-04-27
 
-  * Resolved a security issue with unauthenticated encryption in the SimpleSAML\Utils\Crypto class. See [SSPSA 201704-01](https://simplesamlphp.org/security/201704-01).
-  * Added requirement for the Multibyte String PHP extension and the corresponding checks.
-  * Set a default name for SimpleSAMLphp sessions in the configuration template for the PHP session handler.
+* Resolved a security issue with unauthenticated encryption in the SimpleSAML\Utils\Crypto class. See [SSPSA 201704-01](https://simplesamlphp.org/security/201704-01).
+* Added requirement for the Multibyte String PHP extension and the corresponding checks.
+* Set a default name for SimpleSAMLphp sessions in the configuration template for the PHP session handler.
   
 ## Version 1.14.12
 
 Released 2017-03-30
 
-  * Resolved a security issue in the authcrypt module (Htpasswd authentication source) and in SimpleSAMLphp's session validation. See [SSPSA 201703-01](https://simplesamlphp.org/security/201703-01).
-  * Resolved a security issue with IV generation in the  `SimpleSAML\Utils\Crypto::_aesEncrypt()` method. See [SSPSA 201703-02](https://simplesamlphp.org/security/201703-02).
-  * Fixed an issue with the authfacebook module, broken after a change in Facebook's API.
-  * Fixed an issue in the discopower module that ignored the `hide.from.discovery` metadata option.
-  * Fixed an issue with trusted URLs validation that prevented a URL from being accepted if a standard port was explicitly included but not specified in the configuration.
-  * Fixed an issue that prevented detecting a Memcache server being down when fetching Memcache statistics.
-  * Fixed an issue with operating system detection that made SimpleSAMLphp identify OSX as Windows.
+* Resolved a security issue in the authcrypt module (Htpasswd authentication source) and in SimpleSAMLphp's session validation. See [SSPSA 201703-01](https://simplesamlphp.org/security/201703-01).
+* Resolved a security issue with IV generation in the  `SimpleSAML\Utils\Crypto::_aesEncrypt()` method. See [SSPSA 201703-02](https://simplesamlphp.org/security/201703-02).
+* Fixed an issue with the authfacebook module, broken after a change in Facebook's API.
+* Fixed an issue in the discopower module that ignored the `hide.from.discovery` metadata option.
+* Fixed an issue with trusted URLs validation that prevented a URL from being accepted if a standard port was explicitly included but not specified in the configuration.
+* Fixed an issue that prevented detecting a Memcache server being down when fetching Memcache statistics.
+* Fixed an issue with operating system detection that made SimpleSAMLphp identify OSX as Windows.
 
 ## Version 1.14.11
 
 Released 2016-12-12
 
-  * Resolved a security issue involving signature validation of SAML 1.1 messages. See [SSPSA 201612-02](https://simplesamlphp.org/security/201612-02).
-  * Fixed an issue when the user identifier used to generate a persistent NameID was missing due to a misconfiguration, causing SimpleSAMLphp to generate the nameID based on the null data type.
-  * Fixed an issue when persistent NameIDs were generated out of attributes with empty strings or multiple values.
-  * Fixed issue #530. An empty SubjectConfirmation element was causing SimpleSAMLphp to crash. On the other hand, invalid SubjectConfirmation elements were ignored in PHP 7.0.
+* Resolved a security issue involving signature validation of SAML 1.1 messages. See [SSPSA 201612-02](https://simplesamlphp.org/security/201612-02).
+* Fixed an issue when the user identifier used to generate a persistent NameID was missing due to a misconfiguration, causing SimpleSAMLphp to generate the nameID based on the null data type.
+* Fixed an issue when persistent NameIDs were generated out of attributes with empty strings or multiple values.
+* Fixed issue #530. An empty SubjectConfirmation element was causing SimpleSAMLphp to crash. On the other hand, invalid SubjectConfirmation elements were ignored in PHP 7.0.
 
 ## Version 1.14.10
 
 Released 2016-12-02
 
-  * Resolved a security issue involving signature validation. See [SSPSA 201612-01](https://simplesamlphp.org/security/201612-01).
-  * Fixed issue #517. A misconfigured session when acting as a service provider was leading to a PHP fatal error.
-  * Fixed issue #519. Prevent persistent NameIDs from being generated from empty strings.
-  * Fixed issue #520. It was impossible to verify Apache's custom MD5 passwords when using the Htpasswd authentication source.
-  * Fixed issue #523. Avoid problems caused by different line-ending strategies in the project files.
-  * Other minor fixes and enhancements.
+* Resolved a security issue involving signature validation. See [SSPSA 201612-01](https://simplesamlphp.org/security/201612-01).
+* Fixed issue #517. A misconfigured session when acting as a service provider was leading to a PHP fatal error.
+* Fixed issue #519. Prevent persistent NameIDs from being generated from empty strings.
+* Fixed issue #520. It was impossible to verify Apache's custom MD5 passwords when using the Htpasswd authentication source.
+* Fixed issue #523. Avoid problems caused by different line-ending strategies in the project files.
+* Other minor fixes and enhancements.
 
 ## Version 1.14.9
 
 Released 2016-11-10
 
-  * Fixed an issue that resulted in PHP 7 errors being masked.
-  * Fixed the smartattributes:SmartName authentication processing filter.
-  * Fixed issue #500. When parsing metadata, two 'attributes.required' options were generated.
-  * Fixed the list of requirements in composer, the documentation, and the configuration page.
-  * Fixed issue #479. There were several minor issues with XHTML compliance.
-  * Other minor fixes.
+* Fixed an issue that resulted in PHP 7 errors being masked.
+* Fixed the smartattributes:SmartName authentication processing filter.
+* Fixed issue #500. When parsing metadata, two 'attributes.required' options were generated.
+* Fixed the list of requirements in composer, the documentation, and the configuration page.
+* Fixed issue #479. There were several minor issues with XHTML compliance.
+* Other minor fixes.
 
 ## Version 1.14.8
 
 Released 2016-08-23
 
-  * Fixed an issue in AuthMemCookie causing it to crash when an attribute received contains XML as its value.
-  * Fixed an issue in AuthMemCookie that made it impossible to set its own cookie.
-  * Fixed an issue when acting as a proxy and receiving attributes that contain XML as their values.
-  * Fixed an issue that led to incorrect URL guessing when a script is invoked with a URI that doesn't include its name.
+* Fixed an issue in AuthMemCookie causing it to crash when an attribute received contains XML as its value.
+* Fixed an issue in AuthMemCookie that made it impossible to set its own cookie.
+* Fixed an issue when acting as a proxy and receiving attributes that contain XML as their values.
+* Fixed an issue that led to incorrect URL guessing when a script is invoked with a URI that doesn't include its name.
 
 ## Version 1.14.7
 
 Released 2016-08-01
 
-  * Fixed issue #424. Attributes containing XML as their values (like eduPersonTargetedID) were empty.
+* Fixed issue #424. Attributes containing XML as their values (like eduPersonTargetedID) were empty.
 
 ## Version 1.14.6
 
 Released 2016-07-18
 
-  * Fixed issue #418. SimpleSAMLphp was unable to obtain the current URL correctly when invoked from third-party applications.
+* Fixed issue #418. SimpleSAMLphp was unable to obtain the current URL correctly when invoked from third-party applications.
 
 ## Version 1.14.5
 
 Released 2016-07-12
 
-  * Fixed several issues with session handling when cookies couldn't be set for some reason.
-  * Fixed an issue that caused wrong URLs to be generated in the web interface under certain circumstances.
-  * Fixed the exception handler to be compatible with PHP 7.
-  * Fixed an issue in the dropdown IdP selection page that prevented it to work with PHP 5.3.
-  * Fixed compatibility with Windows machines.
-  * Fixed an issue with the PDO and Serialize metadata storage handlers.
-  * Fixed the authwindowslive module. It stopped working after the former API was discontinued.
-  * Other minor issues and fixes.
+* Fixed several issues with session handling when cookies couldn't be set for some reason.
+* Fixed an issue that caused wrong URLs to be generated in the web interface under certain circumstances.
+* Fixed the exception handler to be compatible with PHP 7.
+* Fixed an issue in the dropdown IdP selection page that prevented it to work with PHP 5.3.
+* Fixed compatibility with Windows machines.
+* Fixed an issue with the PDO and Serialize metadata storage handlers.
+* Fixed the authwindowslive module. It stopped working after the former API was discontinued.
+* Other minor issues and fixes.
 
 ## Version 1.14.4
 
 Released 2016-06-08
 
-  * Fixed two minor security issues that allowed malicious URLs to be presented to the user in a link. Reported by John Page.
-  * Fixed issue #366. The LDAP class was trying to authenticate even when no password was provided (using the CAS module).
-  * Fixed issue #401. The authenticate.php script was printing exceptions instead of throwing them for the exception handler to capture them.
-  * Fixed issue #399. The size limitation of the TEXT type in MySQL was creating problems in certain setups.
-  * Fixed issue #5. Incoherent population of the $_SERVER variable was creating broken links when running PHP with FastCGI.
-  * Other typos and minor bugs: #389, #392.
+* Fixed two minor security issues that allowed malicious URLs to be presented to the user in a link. Reported by John Page.
+* Fixed issue #366. The LDAP class was trying to authenticate even when no password was provided (using the CAS module).
+* Fixed issue #401. The authenticate.php script was printing exceptions instead of throwing them for the exception handler to capture them.
+* Fixed issue #399. The size limitation of the TEXT type in MySQL was creating problems in certain setups.
+* Fixed issue #5. Incoherent population of the $_SERVER variable was creating broken links when running PHP with FastCGI.
+* Other typos and minor bugs: #389, #392.
 
 ## Version 1.14.3
 
 Released 2016-04-19
 
-  * Fixed a bug in the login form that prevented the login button to be displayed in mobile devices.
-  * Resolved an issue in the PHP session handler that made it impossible to use PHP sessions simultaneously with other applications.
+* Fixed a bug in the login form that prevented the login button to be displayed in mobile devices.
+* Resolved an issue in the PHP session handler that made it impossible to use PHP sessions simultaneously with other applications.
 
 ## Version 1.14.2
 
 Released 2016-03-11
 
-  * Use stable versions of the externalized modules to prevent possible issues when further developing them.
+* Use stable versions of the externalized modules to prevent possible issues when further developing them.
 
 ## Version 1.14.1
 
 Released 2016-03-08
 
-  * Resolved an information leakage security issue in the sanitycheck module. See [SSPSA 201603-01](/security/201603-01).
+* Resolved an information leakage security issue in the sanitycheck module. See [SSPSA 201603-01](/security/201603-01).
 
 ## Version 1.14.0
 
@@ -837,824 +910,822 @@ Released 2016-02-15
 
 ### Security
 
-  * Resolved a security issue with multiple modules that were not validating the URLs they were redirecting to.
-  * Added a security check to disable loading external entities in XML documents.
-  * Enforced admin access to the metadata converter tool.
-  * Changed `xmlseclibs` dependency to point to `robrichards/xmlseclibs` version 1.4.1.
+* Resolved a security issue with multiple modules that were not validating the URLs they were redirecting to.
+* Added a security check to disable loading external entities in XML documents.
+* Enforced admin access to the metadata converter tool.
+* Changed `xmlseclibs` dependency to point to `robrichards/xmlseclibs` version 1.4.1.
 
-### New features
+`New features`
 
-  * Allow setting the location of the configuration directory with an environment variable.
-  * Added support for the Metadata Query Protocol by means of the new MDX metadata storage handler.
-  * Added support for the Sender-Vouches method.
-  * Added support for WantAssertionsSigned and AuthnRequestsSigned in SAML 2.0 SP metadata.
-  * Added support for file uploads in the metadata converter.
-  * Added support for setting the prefix for Memcache keys.
-  * Added support for the Hide From Discovery REFEDS Entity Category.
-  * Added support for the eduPersonAssurance attribute.
-  * Added support for the full SCHAC 1.5.0 schema.
-  * Added support for UNIX sockets when configuring memcache servers.
-  * Added the SAML NameID to the attributes status page, when available.
-  * Added attribute definitions for schacGender (schac), sisSchoolGrade and sisLegalGuardianFor (skolfederation.se).
-  * Attributes required in metadata are now taken into account when parsing.
+* Allow setting the location of the configuration directory with an environment variable.
+* Added support for the Metadata Query Protocol by means of the new MDX metadata storage handler.
+* Added support for the Sender-Vouches method.
+* Added support for WantAssertionsSigned and AuthnRequestsSigned in SAML 2.0 SP metadata.
+* Added support for file uploads in the metadata converter.
+* Added support for setting the prefix for Memcache keys.
+* Added support for the Hide From Discovery REFEDS Entity Category.
+* Added support for the eduPersonAssurance attribute.
+* Added support for the full SCHAC 1.5.0 schema.
+* Added support for UNIX sockets when configuring memcache servers.
+* Added the SAML NameID to the attributes status page, when available.
+* Added attribute definitions for schacGender (schac), sisSchoolGrade and sisLegalGuardianFor (skolfederation.se).
+* Attributes required in metadata are now taken into account when parsing.
 
-### Bug fixes
+`Bug fixes`
 
-  * Fixed an issue with friendly names in the attributes released.
-  * Fixed an issue with memcache that would result in a push for every fetch, when several servers configured.
-  * Fixed an issue with memcache that would result in an endless loop if all servers are down.
-  * Fixed an issue with HTML escaping in error reports.
-  * Fixed an issue with the 'admin.protectmetadata' option not being enforced for SP metadata.
-  * Fixed an issue with SAML 1.X SSO authentications that removed the NameID of the subject from available data.
-  * Fixed an issue with the login form that resulted in a `NOSTATE` error if the user clicked the login button twice.
-  * Fixed an issue with replay detection in IdP-initiated flows.
-  * Fixed an issue with SessionNotOnOrAfter that kept moving forward in the future with every SSO authentication.
-  * Fixed an issue with the session cookie being set twice for the first time.
-  * Fixed an issue with the XXE attack prevention mechanism conflicting with other applications running in the same server.
-  * Fixed an issue that prevented the SAML 1.X IdP to restart when the session is lost.
-  * Fixed an issue that prevented classes using namespaces to be loaded automatically.
-  * Fixed an issue that prevented certain metadata signatures to be verified (fixed upstream in `xmlseclibs`).
-  * Other bug fixes and numerous documentation enhancements.
+* Fixed an issue with friendly names in the attributes released.
+* Fixed an issue with memcache that would result in a push for every fetch, when several servers configured.
+* Fixed an issue with memcache that would result in an endless loop if all servers are down.
+* Fixed an issue with HTML escaping in error reports.
+* Fixed an issue with the 'admin.protectmetadata' option not being enforced for SP metadata.
+* Fixed an issue with SAML 1.X SSO authentications that removed the NameID of the subject from available data.
+* Fixed an issue with the login form that resulted in a `NOSTATE` error if the user clicked the login button twice.
+* Fixed an issue with replay detection in IdP-initiated flows.
+* Fixed an issue with SessionNotOnOrAfter that kept moving forward in the future with every SSO authentication.
+* Fixed an issue with the session cookie being set twice for the first time.
+* Fixed an issue with the XXE attack prevention mechanism conflicting with other applications running in the same server.
+* Fixed an issue that prevented the SAML 1.X IdP to restart when the session is lost.
+* Fixed an issue that prevented classes using namespaces to be loaded automatically.
+* Fixed an issue that prevented certain metadata signatures to be verified (fixed upstream in `xmlseclibs`).
+* Other bug fixes and numerous documentation enhancements.
 
-### API and user interface
+`API and user interface`
 
-  * Added a new and simple database class to serve as PDO interface for all the database needs.
-  * Added the possibility to copy metadata and other elements by clicking a button in the web interface.
-  * Removed the old, unused `pack` installer tool.
-  * Improved usability by telling users the endpoints are not to be accessed directly.
-  * Moved the hostname, port and protocol diagnostics tool to the admin directory.
-  * Several classes and functions deprecated.
-  * Changed the signature of several functions.
-  * Deleted old and deprecated code, interfaces and endpoints.
-  * Deleted old jQuery remnants.
-  * Deleted the undocumented dynamic XML metadata storage handler.
-  * Deleted the backwards-compatible authentication source.
-  * Updated jQuery to the latest 1.8.X version.
-  * Updated translations.
+* Added a new and simple database class to serve as PDO interface for all the database needs.
+* Added the possibility to copy metadata and other elements by clicking a button in the web interface.
+* Removed the old, unused `pack` installer tool.
+* Improved usability by telling users the endpoints are not to be accessed directly.
+* Moved the hostname, port and protocol diagnostics tool to the admin directory.
+* Several classes and functions deprecated.
+* Changed the signature of several functions.
+* Deleted old and deprecated code, interfaces and endpoints.
+* Deleted old jQuery remnants.
+* Deleted the undocumented dynamic XML metadata storage handler.
+* Deleted the backwards-compatible authentication source.
+* Updated jQuery to the latest 1.8.X version.
+* Updated translations.
 
-### `authcrypt`
+`authcrypt`
 
-  * Added whitehat101/apr1-md5 as a dependency for Apache htpasswd.
+* Added whitehat101/apr1-md5 as a dependency for Apache htpasswd.
 
-### `authX509`
+`authX509`
 
-  * Added an authentication processing filter to warn about certificate expiration.
+* Added an authentication processing filter to warn about certificate expiration.
 
-### `ldap`
+`ldap`
 
-  * Added a new `port` configuration option.
-  * Better error reporting.
+* Added a new `port` configuration option.
+* Better error reporting.
 
-### `metaedit`
+`metaedit`
 
-  * Removed the `admins` configuration option.
+* Removed the `admins` configuration option.
 
-### `metarefresh`
+`metarefresh`
 
-  * Added the possibility to specify which types of entities to load.
-  * Added the possibility to verify metadata signatures by using the public key present in a certificate.
-  * Fix `certificate` precedence over `fingerprint` in the configuration options when verifying metadata signatures.
+* Added the possibility to specify which types of entities to load.
+* Added the possibility to verify metadata signatures by using the public key present in a certificate.
+* Fix `certificate` precedence over `fingerprint` in the configuration options when verifying metadata signatures.
 
-### `smartnameattribute`
+`smartnameattribute`
 
-  * This module was deprecated long time ago and has now been removed. Use the `smartattributes` module instead.
+* This module was deprecated long time ago and has now been removed. Use the `smartattributes` module instead.
 
 ## Version 1.13.2
 
 Released 2014-11-04
 
-  * Solved performance issues when processing large metadata sets.
-  * Fix an issue in the web interface when only one language is enabled.
+* Solved performance issues when processing large metadata sets.
+* Fix an issue in the web interface when only one language is enabled.
 
 ## Version 1.13.1
 
 Released 2014-10-27
 
-  * Solved an issue with empty fields in metadata to cause SimpleSAMLphp to fail with a translation error. Issues #97 and #114.
-  * Added Basque language to the list of known languages. Issue #117.
-  * Optimized the execution of redirections by removing an additional, unnecessary function call.
-  * Solved an issue that caused SimpleSAMLphp to fail when the RelayState parameter was empty or missing on an IdP-initiated authentication. Issues #99 and # 104.
-  * Fixed a certificate check for SubjectConfirmations with Holder of Key methods.
+* Solved an issue with empty fields in metadata to cause SimpleSAMLphp to fail with a translation error. Issues #97 and #114.
+* Added Basque language to the list of known languages. Issue #117.
+* Optimized the execution of redirections by removing an additional, unnecessary function call.
+* Solved an issue that caused SimpleSAMLphp to fail when the RelayState parameter was empty or missing on an IdP-initiated authentication. Issues #99 and # 104.
+* Fixed a certificate check for SubjectConfirmations with Holder of Key methods.
 
 ## Version 1.13
 
 Released 2014-09-25.
 
-  * Added the 'remember me' option to the default login page.
-  * Improved error reporting.
-  * Added a new 'logging.format' option to control the formatting of the logs.
-  * Added support for the 'objectguid' binary attribute in LDAP modules.
-  * Added support for custom search and private attributes read credentials in all LDAP modules.
-  * Added support for the WantAuthnRequestsSigned option in generated SAML metadata.
-  * Tracking identifiers are no longer generated based on MD5.
-  * Several functions, classes and interfaces marked as deprecated.
-  * Bug fixes and documentation enhancements.
-  * Updated translations.
-  * New language: Basque.
+* Added the 'remember me' option to the default login page.
+* Improved error reporting.
+* Added a new 'logging.format' option to control the formatting of the logs.
+* Added support for the 'objectguid' binary attribute in LDAP modules.
+* Added support for custom search and private attributes read credentials in all LDAP modules.
+* Added support for the WantAuthnRequestsSigned option in generated SAML metadata.
+* Tracking identifiers are no longer generated based on MD5.
+* Several functions, classes and interfaces marked as deprecated.
+* Bug fixes and documentation enhancements.
+* Updated translations.
+* New language: Basque.
 
-### `adfs`
+`adfs`
 
-  * Honour the 'wreply' parameter when redirecting.
+* Honour the 'wreply' parameter when redirecting.
 
-### `aggregator`
+`aggregator`
 
-  * Fixed an issue when regenerating metadata from certain metadata sources.
+* Fixed an issue when regenerating metadata from certain metadata sources.
 
-### `discopower`
+`discopower`
 
-  * Bug fix.
+* Bug fix.
 
-### `expirycheck`
+`expirycheck`
 
-  * Translations are now possible for this module.
+* Translations are now possible for this module.
 
-### `metarefresh`
+`metarefresh`
 
-  * Use cached metadata if something goes wrong when refreshing feeds.
+* Use cached metadata if something goes wrong when refreshing feeds.
 
-### `openidProvider`
+`openidProvider`
 
-  * Fix for compatibility with versions of PHP greater or equal to 5.4.
+* Fix for compatibility with versions of PHP greater or equal to 5.4.
 
-### `saml`
+`saml`
 
-  * Make it possible to add friendly names to attributes in SP metadata.
-  * The RSA_1.5 (RSA with PKCS#1 v1.5 padding) encryption algorithm is now blacklisted by default for security reasons.
-  * Stop checking the 'IDPList' parameter in IdPs.
-  * Solved an issue that allowed bypassing authentication status checks when presenting an 'IDPList' parameter.
-  * The 'Destination' attribute is now always sent in logout responses issued by an SP.
+* Make it possible to add friendly names to attributes in SP metadata.
+* The RSA_1.5 (RSA with PKCS#1 v1.5 padding) encryption algorithm is now blacklisted by default for security reasons.
+* Stop checking the 'IDPList' parameter in IdPs.
+* Solved an issue that allowed bypassing authentication status checks when presenting an 'IDPList' parameter.
+* The 'Destination' attribute is now always sent in logout responses issued by an SP.
 
-### `sqlauth`
+`sqlauth`
 
-  * Updated documentation to remove bad practice with regard to password storage.
+* Updated documentation to remove bad practice with regard to password storage.
 
 ## Version 1.12
 
 Released 2014-03-24.
 
-  * Removed example authproc filters from configuration template.
-  * Stopped using the 'target-densitydpi' option removed from WebKit.
-  * The SimpleSAML_Utilities::generateRandomBytesMTrand() function is now deprecated.
-  * Removed code for compatibility with PHP versions older than 5.3.
-  * Removed the old interface of SimpleSAML_Session.
-  * Fixed a memory leak in SimpleSAML_Session regarding serialization and unserialization.
-  * Support for RegistrationInfo (MDRPI) elements in the metadata of identity and service providers.
-  * Renamed SimpleSAML_Utilities::parseSAML2Time() function to xsDateTimeToTimestamp().
-  * New SimpleSAML_Utilities::redirectTrustedURL() and redirectUntrustedURL() functions.
-  * Deprecated the SimpleSAML_Utilities::redirect() function.
-  * Improved Russian translation.
-  * Added Czech translation.
-  * New 'errorreporting' option to enable or disable error reporting feature.
-  * Example certificate removed.
-  * New SimpleSAML_Configuration::getEndpointPrioritizedByBinding() function.
-  * PHP 5.3 or newer required.
-  * Started using Composer as dependency manager.
-  * Detached the basic SAML2 library and moved to a standalone library in GitHub.
-  * Added support for exporting shibmd:Scope metadata with regular expressions.
-  * Remember me option in the IdP.
-  * New SimpleSAML_Utilities::setCookie wrapper.
-  * Custom HTTP codes on error.
-  * Added Romanian translation.
-  * Bug fixes and documentation enhancements.
+* Removed example authproc filters from configuration template.
+* Stopped using the 'target-densitydpi' option removed from WebKit.
+* The SimpleSAML_Utilities::generateRandomBytesMTrand() function is now deprecated.
+* Removed code for compatibility with PHP versions older than 5.3.
+* Removed the old interface of SimpleSAML_Session.
+* Fixed a memory leak in SimpleSAML_Session regarding serialization and unserialization.
+* Support for RegistrationInfo (MDRPI) elements in the metadata of identity and service providers.
+* Renamed SimpleSAML_Utilities::parseSAML2Time() function to xsDateTimeToTimestamp().
+* New SimpleSAML_Utilities::redirectTrustedURL() and redirectUntrustedURL() functions.
+* Deprecated the SimpleSAML_Utilities::redirect() function.
+* Improved Russian translation.
+* Added Czech translation.
+* New 'errorreporting' option to enable or disable error reporting feature.
+* Example certificate removed.
+* New SimpleSAML_Configuration::getEndpointPrioritizedByBinding() function.
+* PHP 5.3 or newer required.
+* Started using Composer as dependency manager.
+* Detached the basic SAML2 library and moved to a standalone library in GitHub.
+* Added support for exporting shibmd:Scope metadata with regular expressions.
+* Remember me option in the IdP.
+* New SimpleSAML_Utilities::setCookie wrapper.
+* Custom HTTP codes on error.
+* Added Romanian translation.
+* Bug fixes and documentation enhancements.
 
-### `adfs`
+`adfs`
 
-  * Support for exporting metadata.
+* Support for exporting metadata.
 
-### `aggregator`
+`aggregator`
 
-  * Support for RegistrationInfo (MDRPI) elements in the metadata.
-  * Fix for HTTP header injection vulnerability.
-  * Fix for directory traversal vulnerability.
+* Support for RegistrationInfo (MDRPI) elements in the metadata.
+* Fix for HTTP header injection vulnerability.
+* Fix for directory traversal vulnerability.
 
-### `aggregator2`
+`aggregator2`
 
-  * Support for RegistrationInfo (MDRPI) elements in the metadata.
+* Support for RegistrationInfo (MDRPI) elements in the metadata.
 
-### `aselect`
+`aselect`
 
-  * License changed to LGPL 2.1.
+* License changed to LGPL 2.1.
 
-### `authfacebook`
+`authfacebook`
 
-  * Updated extlibinc to 3.2.2.
+* Updated extlibinc to 3.2.2.
 
-### `authtwitter`
+`authtwitter`
 
-  * Added 'force_login' configuration option.
+* Added 'force_login' configuration option.
 
-### `cdc`
+`cdc`
 
-  * Bugfix related to request validation.
+* Bugfix related to request validation.
 
-### `core`
+`core`
 
-  * The AttributeAlter filter no longer throws an exception if the attribute was not found.
-  * Support for removal of values in the AttributeAlter filter, with '%remove' flag.
-  * Support for empty strings and NULL values as a replacement in the AttributeAlter filter.
-  * Bugfixes in the AttributeAlter filter.
-  * Support for NULL attribute values.
-  * Support for limiting values and not only attributes in the AttributeLimit filter.
-  * Log a message when a user authenticates successfully.
-  * Added %duplicate flag to AttributeMap, to leave original names in place when using map file.
-  * Fix infinite loop when overwriting attributes with AttributeMap.
+* The AttributeAlter filter no longer throws an exception if the attribute was not found.
+* Support for removal of values in the AttributeAlter filter, with '%remove' flag.
+* Support for empty strings and NULL values as a replacement in the AttributeAlter filter.
+* Bugfixes in the AttributeAlter filter.
+* Support for NULL attribute values.
+* Support for limiting values and not only attributes in the AttributeLimit filter.
+* Log a message when a user authenticates successfully.
+* Added %duplicate flag to AttributeMap, to leave original names in place when using map file.
+* Fix infinite loop when overwriting attributes with AttributeMap.
 
-### `discopower`
+`discopower`
 
-  * Bugfix for incorrect handling of the 'idpdisco.extDiscoveryStorage' option.
+* Bugfix for incorrect handling of the 'idpdisco.extDiscoveryStorage' option.
 
-### `ldap`
+`ldap`
 
-  * Support for configuring the duplicate attribute handling policy in AttributeAddFromLDAP, 'attribute.policy' option.
-  * Support for binary attributes in the AttributeAddFromLDAP filter.
-  * Support for multiple attributes in the AttributeAddFromLDAP filter.
+* Support for configuring the duplicate attribute handling policy in AttributeAddFromLDAP, 'attribute.policy' option.
+* Support for binary attributes in the AttributeAddFromLDAP filter.
+* Support for multiple attributes in the AttributeAddFromLDAP filter.
 
-### `metarefresh`
+`metarefresh`
 
-  * Support for specifying permissions of the resulting files.
+* Support for specifying permissions of the resulting files.
 
-### `negotiate`
+`negotiate`
 
-  * Added support for "attributes"-parameter.
+* Added support for "attributes"-parameter.
 
-### `oauth`
+`oauth`
 
-  * Bugfix related to authorize URL building.
+* Bugfix related to authorize URL building.
 
-### `openidProvider`
+`openidProvider`
 
-  * Support for SReg and AX requests.
+* Support for SReg and AX requests.
 
-### `saml`
+`saml`
 
-  * Send 'isPassive' in passive discovery requests.
-  * Support for generating NameIDFormat in service providers with NameIDPolicy set.
-  * Support for AttributeConsumingService and AssertionConsumingServiceIndex.
-  * Support for the HTTP-POST binding in WebSSO profile.
-  * Fix for entity ID validation problems when using the IDPList configuration option.
+* Send 'isPassive' in passive discovery requests.
+* Support for generating NameIDFormat in service providers with NameIDPolicy set.
+* Support for AttributeConsumingService and AssertionConsumingServiceIndex.
+* Support for the HTTP-POST binding in WebSSO profile.
+* Fix for entity ID validation problems when using the IDPList configuration option.
 
-### `smartattributes`
+`smartattributes`
 
-  * New 'add_candidate' option to allow the user to decide whether to prepend or not the candidate attribute name to the resulting value.
+* New 'add_candidate' option to allow the user to decide whether to prepend or not the candidate attribute name to the resulting value.
 
-### `statistics`
+`statistics`
 
-  * Bugfix in statistics aggregator.
+* Bugfix in statistics aggregator.
 
 ## Version 1.11
 
 Released 2013-06-05.
 
-  * Support for RSA_SHA256, RSA_SHA384 and RSA_SHA512 in HTTP Redirect binding.
-  * Support for RegistrationInfo element in SAML 2.0 metadata.
-  * Support for AuthnRequestsSigned and WantAssertionsSigned when generating metadata.
-  * Third party OpenID library updated with a bugfix.
-  * Added the Name attribute to EntitiesDescriptor.
-  * Removed deprecated option 'session.requestcache' from config-template.
-  * Workaround for SSL SNI extension not being correctly set.
-  * New language cookie and parameter config options.
-  * Add 'module.enable' configuration option for enabling/disabling modules.
-  * Check for existence of memcache extension. 
-  * Initial support for limiting redirects to trusted hosts.
-  * Demo example now shows both friendly and canonical name of the attributes.
-  * Other minor fixes for bugs and typos.
-  * Several translations updated.
-  * Added Latvian translation.
+* Support for RSA_SHA256, RSA_SHA384 and RSA_SHA512 in HTTP Redirect binding.
+* Support for RegistrationInfo element in SAML 2.0 metadata.
+* Support for AuthnRequestsSigned and WantAssertionsSigned when generating metadata.
+* Third party OpenID library updated with a bugfix.
+* Added the Name attribute to EntitiesDescriptor.
+* Removed deprecated option 'session.requestcache' from config-template.
+* Workaround for SSL SNI extension not being correctly set.
+* New language cookie and parameter config options.
+* Add 'module.enable' configuration option for enabling/disabling modules.
+* Check for existence of memcache extension.
+* Initial support for limiting redirects to trusted hosts.
+* Demo example now shows both friendly and canonical name of the attributes.
+* Other minor fixes for bugs and typos.
+* Several translations updated.
+* Added Latvian translation.
 
-### `authorize`
+`authorize`
 
-  * Added a logout link to the 403 error page.
+* Added a logout link to the 403 error page.
 
-### `authtwitter`
+`authtwitter`
 
-  * Updated API endpoint for version 1.1.
-  * Fix for oauth_verifier parameter.
+* Updated API endpoint for version 1.1.
+* Fix for oauth_verifier parameter.
 
-### `authX509`
+`authX509`
 
-  * ldapusercert validation made optional.
+* ldapusercert validation made optional.
 
-### `consent`
+`consent`
 
-  * Added support for SQLite databases.
+* Added support for SQLite databases.
 
-### `core`
+`core`
 
-  * Fix error propagation in UserPass(Org)Base authentication sources.
-  * MCrypt module marked as required.
+* Fix error propagation in UserPass(Org)Base authentication sources.
+* MCrypt module marked as required.
 
-### `discopower`
+`discopower`
 
-  * Get the name of an IdP from mdui:DisplayName.
+* Get the name of an IdP from mdui:DisplayName.
 
-### `expirycheck`
+`expirycheck`
 
-  * PHP 5.4 compatibility fixes.
+* PHP 5.4 compatibility fixes.
 
-### `InfoCard`
+`InfoCard`
 
-  * PHP 5.4 compatibility fixes.
+* PHP 5.4 compatibility fixes.
 
-### `ldap`
+`ldap`
 
-  * Added an option to disable following referrals.
+* Added an option to disable following referrals.
 
-### `metarefresh`
+`metarefresh`
 
-  * Improved help message.
+* Improved help message.
 
-### `oauth`
+`oauth`
 
-  * PHP 5.4 compatibility fixes.
+* PHP 5.4 compatibility fixes.
 
-### `saml`
+`saml`
 
-  * Verify that the issuer of an AuthnResponse is the same entity ID we sent a request to.
-  * Added separate option to enable Holder of Key support on SP.
-  * Fix for HoK profile metadata.
-  * New filter for storing persistent NameID in eduPersonTargetedID attribute.
-  * Support for UIInfo elements.
-  * Bugfix for SAML SP metadata signing.
-  * Ignore default technical contact.
-  * Support for MDUI elements in SP metadata.
-  * Support for more contact types in SP metadata.
-  * New information in statistics with the time it took for a login to happen.
+* Verify that the issuer of an AuthnResponse is the same entity ID we sent a request to.
+* Added separate option to enable Holder of Key support on SP.
+* Fix for HoK profile metadata.
+* New filter for storing persistent NameID in eduPersonTargetedID attribute.
+* Support for UIInfo elements.
+* Bugfix for SAML SP metadata signing.
+* Ignore default technical contact.
+* Support for MDUI elements in SP metadata.
+* Support for more contact types in SP metadata.
+* New information in statistics with the time it took for a login to happen.
 
-### `sanitycheck`
+`sanitycheck`
 
-  * Configuration file made optional.
+* Configuration file made optional.
 
-### `smartattributes`
+`smartattributes`
 
-  * New filter: smartattributes:SmartID.
-  * New filter: smartattributes:SmartName.
+* New filter: smartattributes:SmartID.
+* New filter: smartattributes:SmartName.
 
-### `smartnameattribute`
+`smartnameattribute`
 
-  * Deprecated.
+* Deprecated.
 
-### `wsfed`
+`wsfed`
 
-  * Support for SLO in WS-Fed.
+* Support for SLO in WS-Fed.
 
 ## Version 1.10
 
 Released 2012-09-25.
 
-  * Add support for storing data without expiration timestamp in memcache.
-  * Fix for reauthentication in old shib13 authentication handler.
-  * Clean up executable-permissions on files.
-  * Change encryption to use the rsa-oaep-mgf1p key padding instead of PKCS 1.5.
-  * Update translations.
-  * Added Serbian translation.
+* Add support for storing data without expiration timestamp in memcache.
+* Fix for reauthentication in old shib13 authentication handler.
+* Clean up executable-permissions on files.
+* Change encryption to use the rsa-oaep-mgf1p key padding instead of PKCS 1.5.
+* Update translations.
+* Added Serbian translation.
 
-### `core`
+`core`
 
-  * `core:UserPass(Org)Base`: Add "remember username" option.
+* `core:UserPass(Org)Base`: Add "remember username" option.
 
-### `papi`
+`papi`
 
-  * New authentication module supporting PAPI protocol.
+* New authentication module supporting PAPI protocol.
 
-### `radius`
+`radius`
 
-  * New feature to configure multiple radius servers.
+* New feature to configure multiple radius servers.
 
-### `riak`
+`riak`
 
-  * New module for storing sessions in a Riak database.
+* New module for storing sessions in a Riak database.
 
-### `saml`
+`saml`
 
-  * Add support for overriding SAML 2.0 SP authentication request generation.
-  * Add support for blacklisting encryption algorithms.
+* Add support for overriding SAML 2.0 SP authentication request generation.
+* Add support for blacklisting encryption algorithms.
 
 ## Version 1.9.2
 
 Released 2012-08-29
 
-  * Fix related to the security issue addressed in version 1.9.1.
+* Fix related to the security issue addressed in version 1.9.1.
 
 ## Version 1.9.1
 
 Released 2012-08-02.
 
-  * Fix for a new attack against PKCS 1.5 in XML encryption.
+* Fix for a new attack against PKCS 1.5 in XML encryption.
 
 ## Version 1.9
 
 Released 2012-06-13.
 
-  * Restructure error templates to share a common base template.
-  * Warnings about URL length limits from Suhosin PHP extension.
-  * New base class for errors from authentication sources.
-  * Support for overriding URL generation when behind a reverse proxy.
-  * New languages: Russian, Estonian, Hebrew, Chinese, Indonesian
-  * Add getAuthSource()-function to SimpleSAML_Auth_Simple.
-  * Add reauthenticate()-function to SimpleSAML_Auth_Source. (Is called when the IdP receives a new authentication request.)
-  * iframe logout: Make it possible to skip the "question-page" for code on the IdP.
-  * RTL text support.
-  * Make SimpleSAMLAuthToken cookie name configurable.
-  * Block writing secure cookies when we are on http.
-  * Fix state information being unavailable to UserPassOrgBase authentication templates.
-  * Make it possible to send POST-messages to http-endpoints without triggering a warning when the IdP supports both http and https.
-  * Add IPv6-support to the SimpleSAML_Utilities::ipCIDRcheck()-function.
-  * Do not allow users to switch to a language that is not enabled.
-  * iframe logout: Add a per-SP timeout option.
-  * SimpleSAML_Auth_LDAP: Better logging of the cause of exceptions.
-  * SimpleSAML_Auth_State: Add $allowMissing-parameter to loadState().
-  * module.php: More strict URL parsing.
-  * Add support for hashed admin passwords.
-  * Use openssl_random_pseudo_bytes() for better cross-platform random number generation.
-  * Add the current hostname to the error reports.
-  * Make the lifetime of SimpleSAML_Auth_State "state-arrays" configurable (via the `session.state.timeout`-option).
-  * SimpleSAML_Auth_State: Add cloneState()-function.
-  * Fix log levels used on Windows.
-  * SimpleSAML_Auth_LDAP: Clean up some unused code.
-  * core:UserPassOrgBase: Add selected organization to the authentication data that is stored in the session.
-  * Do not warn about missing Radius and LDAP PHP extensions unless those modules are enabled.
-  * Support for overriding the logic to determine the language.
-  * Avoid crashes due to deprecation-warnings issued by PHP.
-  * Use case-insensitive matching of language codes.
-  * Add X-Frame-Options to prevent other sites from loading the SSP-pages in an iframe.
-  * Add SimpleSAML_Utilities::isWindowsOS()-helper function.
-  * chmod() generated files to only be accessible to the owner of the files.
-  * Fix "re-posting" of POST data containing a key named "submit".
-  * Do not attempt to read new sessions from the session handler.
-  * Fix some pass-by-reference uses. (Support removed in PHP 5.4.)
-  * Warn the user if the secretsalt-option isn't set.
-  * A prototype for a new statistics logging core. Provides more structured logging of events, and support for multiple storage backends.
-  * Support for arbitrary namespace-prefixed attributes in md:EndpointType-elements.
-  * Fix invalid HTML for login pages where username is set.
-  * Remove unnecessary check for PHP version >= 5.2 when setting cookies.
-  * Better error message when a module is missing a default-enable or default-disable file.
-  * Support for validating RSA-SHA256 signatures.
-  * Fixes for session expiration handling.
+* Restructure error templates to share a common base template.
+* Warnings about URL length limits from Suhosin PHP extension.
+* New base class for errors from authentication sources.
+* Support for overriding URL generation when behind a reverse proxy.
+* New languages: Russian, Estonian, Hebrew, Chinese, Indonesian
+* Add getAuthSource()-function to SimpleSAML_Auth_Simple.
+* Add reauthenticate()-function to SimpleSAML_Auth_Source. (Is called when the IdP receives a new authentication request.)
+* iframe logout: Make it possible to skip the "question-page" for code on the IdP.
+* RTL text support.
+* Make SimpleSAMLAuthToken cookie name configurable.
+* Block writing secure cookies when we are on http.
+* Fix state information being unavailable to UserPassOrgBase authentication templates.
+* Make it possible to send POST-messages to http-endpoints without triggering a warning when the IdP supports both http and https.
+* Add IPv6-support to the SimpleSAML_Utilities::ipCIDRcheck()-function.
+* Do not allow users to switch to a language that is not enabled.
+* iframe logout: Add a per-SP timeout option.
+* SimpleSAML_Auth_LDAP: Better logging of the cause of exceptions.
+* SimpleSAML_Auth_State: Add $allowMissing-parameter to loadState().
+* module.php: More strict URL parsing.
+* Add support for hashed admin passwords.
+* Use openssl_random_pseudo_bytes() for better cross-platform random number generation.
+* Add the current hostname to the error reports.
+* Make the lifetime of SimpleSAML_Auth_State "state-arrays" configurable (via the `session.state.timeout`-option).
+* SimpleSAML_Auth_State: Add cloneState()-function.
+* Fix log levels used on Windows.
+* SimpleSAML_Auth_LDAP: Clean up some unused code.
+* core:UserPassOrgBase: Add selected organization to the authentication data that is stored in the session.
+* Do not warn about missing Radius and LDAP PHP extensions unless those modules are enabled.
+* Support for overriding the logic to determine the language.
+* Avoid crashes due to deprecation-warnings issued by PHP.
+* Use case-insensitive matching of language codes.
+* Add X-Frame-Options to prevent other sites from loading the SSP-pages in an iframe.
+* Add SimpleSAML_Utilities::isWindowsOS()-helper function.
+* chmod() generated files to only be accessible to the owner of the files.
+* Fix "re-posting" of POST data containing a key named "submit".
+* Do not attempt to read new sessions from the session handler.
+* Fix some pass-by-reference uses. (Support removed in PHP 5.4.)
+* Warn the user if the secretsalt-option isn't set.
+* A prototype for a new statistics logging core. Provides more structured logging of events, and support for multiple storage backends.
+* Support for arbitrary namespace-prefixed attributes in md:EndpointType-elements.
+* Fix invalid HTML for login pages where username is set.
+* Remove unnecessary check for PHP version >= 5.2 when setting cookies.
+* Better error message when a module is missing a default-enable or default-disable file.
+* Support for validating RSA-SHA256 signatures.
+* Fixes for session expiration handling.
 
-### `aselect`
+`aselect`
 
-  * New module that replaces the previous module.
-  * Better error handling.
-  * Support for request signing.
-  * Loses support for A-Select Cross.
+* New module that replaces the previous module.
+* Better error handling.
+* Support for request signing.
+* Loses support for A-Select Cross.
 
-### `authcrypt`
+`authcrypt`
 
-  * `authcrypt:Hash`: New authentication source for checking username & password against a list of usernames and hashed passwords.
-  * `authcrypt:Htpasswd`: New authentication source for checking username & password against a `.htpasswd`-file.
+* `authcrypt:Hash`: New authentication source for checking username & password against a list of usernames and hashed passwords.
+* `authcrypt:Htpasswd`: New authentication source for checking username & password against a `.htpasswd`-file.
 
-### `authfacebook`
+`authfacebook`
 
-  * Update to latest Facebook PHP SDK.
+* Update to latest Facebook PHP SDK.
 
-### `authorize`
+`authorize`
 
-  * `authorize:Authorize`: Add flag to change the behaviour from default-deny to default-allow.
-  * `authorize:Authorize`: Add flag to do simple string matching instead of regex-matching.
+* `authorize:Authorize`: Add flag to change the behaviour from default-deny to default-allow.
+* `authorize:Authorize`: Add flag to do simple string matching instead of regex-matching.
 
-### `authtwitter`
+`authtwitter`
 
-  * Update to use the correct API endpoint.
-  * Propagate "user aborted" errors back to the caller.
-  * Changes to error handling, throw more relevant exceptions.
-  * Store state information directly in the state array, instead of the session.
+* Update to use the correct API endpoint.
+* Propagate "user aborted" errors back to the caller.
+* Changes to error handling, throw more relevant exceptions.
+* Store state information directly in the state array, instead of the session.
 
-### `authYubiKey`
-
-  * Remove deprecated uses of split().
-
-### `cas`
-
-  * Make it possible for subclasses to override finalState().
-
-### `core`
-
-  * `core:AttributeCopy`: New filter to copy attributes.
-
-### `consent`
-
-  * Add a timeout option for the database connection.
-  * Fix disabling of consent when the data store is down.
-  * Simpler configuration for disabling consent for one SP or one IdP.
-  * Do not connect to the database when consent is disabled for the current SP/IdP.
-
-### `consentAdmin`
-
-  * Fix for bridged IdP setup with `userid.attribute` set in `saml20-idp-hosted` metadata.
-
-### `cron`
-
-  * Set the From-address to be the technical contact email address.
-
-### `expirycheck`
-
-  * `expirycheck:ExpiryDate`: New module to check account expiration.
-
-### `ldap`
+`authYubiKey`
+
+* Remove deprecated uses of split().
+
+`cas`
+
+* Make it possible for subclasses to override finalState().
+
+`core`
+
+* `core:AttributeCopy`: New filter to copy attributes.
+
+`consent`
+
+* Add a timeout option for the database connection.
+* Fix disabling of consent when the data store is down.
+* Simpler configuration for disabling consent for one SP or one IdP.
+* Do not connect to the database when consent is disabled for the current SP/IdP.
+
+`consentAdmin`
+
+* Fix for bridged IdP setup with `userid.attribute` set in `saml20-idp-hosted` metadata.
+
+`cron`
+
+* Set the From-address to be the technical contact email address.
+
+`expirycheck`
+
+* `expirycheck:ExpiryDate`: New module to check account expiration.
+
+`ldap`
 
-  * Add a base class for authentication processing filters which fetch data from LDAP.
-  * `ldap:AttributeAddUsersGroups`: Authentication processing filter that adds group information from LDAP.
+* Add a base class for authentication processing filters which fetch data from LDAP.
+* `ldap:AttributeAddUsersGroups`: Authentication processing filter that adds group information from LDAP.
 
-### `metarefresh`
+`metarefresh`
 
-  * Support for blacklisting and whitelisting entities.
-  * Support for conditional GET of metadata files.
-  * Reuse old metadata when fetching metadata fails.
+* Support for blacklisting and whitelisting entities.
+* Support for conditional GET of metadata files.
+* Reuse old metadata when fetching metadata fails.
 
-### `multiauth`
+`multiauth`
 
-  * Add `multiauth:preselect`-parameter, to skip the page to select authentication source.
-  * Make it possible to configure the names of the authentication sources.
-  * Remember the last selected authentication source.
+* Add `multiauth:preselect`-parameter, to skip the page to select authentication source.
+* Make it possible to configure the names of the authentication sources.
+* Remember the last selected authentication source.
 
-### `negotiate`
+`negotiate`
 
-  * New module implementing "negotiate" authentication, which can be used for Kerberos authentication (including Windows SSO).
+* New module implementing "negotiate" authentication, which can be used for Kerberos authentication (including Windows SSO).
 
-### `oauth`
+`oauth`
 
-  * Update to latest version of the OAuth library.
-  * Remove support for older versions of OAuth than OAuth Rev A.
+* Update to latest version of the OAuth library.
+* Remove support for older versions of OAuth than OAuth Rev A.
 
-### `openid`
+`openid`
 
-  * Separate linkback URL from page displaying OpenID URL field.
-  * Throw more relevant exceptions.
-  * Update to latest version of the OpenID library.
-  * Support for sending authentication requests via GET requests (with the prefer_http_redirect option).
-  * Prevent deprecation warnings from the OpenID library from causing deadlocks in the class loader.
+* Separate linkback URL from page displaying OpenID URL field.
+* Throw more relevant exceptions.
+* Update to latest version of the OpenID library.
+* Support for sending authentication requests via GET requests (with the prefer_http_redirect option).
+* Prevent deprecation warnings from the OpenID library from causing deadlocks in the class loader.
 
-### `openidProvider`
+`openidProvider`
 
-  * Prevent deprecation warnings from the OpenID library from causing deadlocks in the class loader.
+* Prevent deprecation warnings from the OpenID library from causing deadlocks in the class loader.
 
-### `radius`
+`radius`
 
-  * Support for setting the "NAS-Identifier" attribute.
+* Support for setting the "NAS-Identifier" attribute.
 
-### `saml`
+`saml`
 
-  * Preserve ID-attributes on elements during signing. (Makes it possible to change the binding for some messages.)
-  * Allow SAML artifacts to be received through a POST request.
-  * Log more debug information when we are unable to determine the binding a message was sent with.
-  * Require HTTP-POST messages to be sent as POST data and HTTP-Redirect messages to be sent as query parameters.
-  * Link to download certificates from metadata pages.
-  * Fix canonicalization of &lt;md:EntityDescriptor> and &lt;md:EntitiesDescriptor>.
-  * Support for receiving and sending extension in authentication request messages.
-  * Reuse SimpleSAML_Utilities::postRedirect() to send HTTP-POST messages.
-  * Allow ISO8601 durations with subsecond precision.
-  * Add support for parsing and serializing the &lt;mdrpi:PublicationInfo> metadata extension.
-  * Ignore cacheDuration when validating metadata.
-  * Add support for the Holder-of-Key profile, on both the [SP](./simplesamlphp-hok-sp) and [IdP](./simplesamlphp-hok-idp).
-  * Better error handling when receiving a SAML 2.0 artifact from an unknown entity.
-  * Fix parsing of &lt;md:AssertionIDRequestService> metadata elements.
-  * IdP: Do not always trigger reauthentication when the authentication request contains a IdPList-element.
-  * IdP: Add `saml:AllowCreate` to the state array. This makes it possible to access this parameter from authentication processing filters.
-  * IdP: Sign the artifact response message.
-  * IdP: Allow the "host" metadata option to include more than one path element.
-  * IdP: Support for generating metadata with MDUI extension elements.
-  * SP: Use the discojuice-module as a discovery service if it is enabled.
-  * SP: Add `saml:idp`-parameter to trigger login to a specific IdP to as_login.php.
-  * SP: Do not display error on duplicate response when we have a valid session.
-  * SP: Fix for logout after IdP initiated authentication.
-  * SP: Fix handling of authentication response without a saml:Issuer element.
-  * SP: Support for specifying required attributes in metadata.
-  * SP: Support for limiting the AssertionConsumerService endpoints listed in metadata.
-  * SP: Fix session expiration when the IdP limits the session lifetime.
-  * `saml:PersistentNameID`: Fail when the user has more than one value in the user ID attribute.
-  * `saml:SQLPersistentNameID`: Persistent NameID stored in a SQL database.
-  * `saml:AuthnContextClassRef`: New filter to set the AuthnContextClassRef in responses.
-  * `saml:ExpectedAuthnContextClassRef`: New filter to verify that the SP received the correct authentication class from the IdP.
+* Preserve ID-attributes on elements during signing. (Makes it possible to change the binding for some messages.)
+* Allow SAML artifacts to be received through a POST request.
+* Log more debug information when we are unable to determine the binding a message was sent with.
+* Require HTTP-POST messages to be sent as POST data and HTTP-Redirect messages to be sent as query parameters.
+* Link to download certificates from metadata pages.
+* Fix canonicalization of &lt;md:EntityDescriptor> and &lt;md:EntitiesDescriptor>.
+* Support for receiving and sending extension in authentication request messages.
+* Reuse SimpleSAML_Utilities::postRedirect() to send HTTP-POST messages.
+* Allow ISO8601 durations with subsecond precision.
+* Add support for parsing and serializing the &lt;mdrpi:PublicationInfo> metadata extension.
+* Ignore cacheDuration when validating metadata.
+* Add support for the Holder-of-Key profile, on both the [SP](./simplesamlphp-hok-sp) and [IdP](./simplesamlphp-hok-idp).
+* Better error handling when receiving a SAML 2.0 artifact from an unknown entity.
+* Fix parsing of &lt;md:AssertionIDRequestService> metadata elements.
+* IdP: Do not always trigger reauthentication when the authentication request contains a IdPList-element.
+* IdP: Add `saml:AllowCreate` to the state array. This makes it possible to access this parameter from authentication processing filters.
+* IdP: Sign the artifact response message.
+* IdP: Allow the "host" metadata option to include more than one path element.
+* IdP: Support for generating metadata with MDUI extension elements.
+* SP: Use the discojuice-module as a discovery service if it is enabled.
+* SP: Add `saml:idp`-parameter to trigger login to a specific IdP to as_login.php.
+* SP: Do not display error on duplicate response when we have a valid session.
+* SP: Fix for logout after IdP initiated authentication.
+* SP: Fix handling of authentication response without a saml:Issuer element.
+* SP: Support for specifying required attributes in metadata.
+* SP: Support for limiting the AssertionConsumerService endpoints listed in metadata.
+* SP: Fix session expiration when the IdP limits the session lifetime.
+* `saml:PersistentNameID`: Fail when the user has more than one value in the user ID attribute.
+* `saml:SQLPersistentNameID`: Persistent NameID stored in a SQL database.
+* `saml:AuthnContextClassRef`: New filter to set the AuthnContextClassRef in responses.
+* `saml:ExpectedAuthnContextClassRef`: New filter to verify that the SP received the correct authentication class from the IdP.
 
 ## Version 1.8.2
 
 Released 2012-01-10.
 
-  * Fix for user-assisted cross site scripting on a couple of pages.
+* Fix for user-assisted cross site scripting on a couple of pages.
 
 ## Version 1.8.1
 
 Released 2011-10-27.
 
-  * Fix for key oracle attack against XML encryption on SP.
-  * Fix for IdP initiated logout with IdP-initiated SSO.
-  * Fix a PHP notice if we are unable to open /dev/urandom.
-  * Fix a PHP notice during SAML 1.1 authentication.
+* Fix for key oracle attack against XML encryption on SP.
+* Fix for IdP initiated logout with IdP-initiated SSO.
+* Fix a PHP notice if we are unable to open /dev/urandom.
+* Fix a PHP notice during SAML 1.1 authentication.
 
 ## Version 1.8
 
-  * New authentication modules:
-      * [`authmyspace`](./authmyspace:oauthmyspace)
-      * [`authlinkedin`](./authlinkedin:oauthlinkedin)
-      * [`authwindowslive`](./authwindowslive:windowsliveid)
-  * Support for custom error handler, replacing the default display function.
-  * Allow error codes to be defined in modules.
-  * Better control of logout what we do after logout request.
-      * This makes it possible for the SP to display a warning when receiving a PartialLogout response from the IdP.
-  * New `cdc` module, for setting and reading common domain cookies.
-
-### `consent`
+* New authentication modules:
+  * [`authmyspace`](./authmyspace:oauthmyspace)
+  * [`authlinkedin`](./authlinkedin:oauthlinkedin)
+  * [`authwindowslive`](./authwindowslive:windowsliveid)
+* Support for custom error handler, replacing the default display function.
+* Allow error codes to be defined in modules.
+* Better control of logout what we do after logout request.
+  * This makes it possible for the SP to display a warning when receiving a PartialLogout response from the IdP.
+* New `cdc` module, for setting and reading common domain cookies.
 
-  * Support for disabling consent for some attributes.
+`consent`
 
-### `ldap`
+* Support for disabling consent for some attributes.
 
-  * `ldap:AttributeAddFromLDAP`: Extract values from multiple matching entries.
+`ldap`
 
-### `oauth`
+* `ldap:AttributeAddFromLDAP`: Extract values from multiple matching entries.
 
-  * Added support for:
-      * RSASHA1 signatures
-      * consent
-      * callbackurl
-      * verifier code
-      * request parameters
+`oauth`
 
-### `openid`
+* Added support for:
+  * RSASHA1 signatures
+  * consent
+  * callbackurl
+  * verifier code
+  * request parameters
 
-  * Support for sending custom extension arguments (e.g. UI extensions).
+`openid`
 
-### `saml`
+* Support for sending custom extension arguments (e.g. UI extensions).
 
-  * Extract Extensions from AuthnRequest for use by custom modules when authenticating.
-  * Allow signing of SP metadata.
-  * Better control over NameIDPolicy when sending AuthnRequest.
-  * Support encrypting/decrypting NameID in LogoutRequest.
-  * Option to disable client certificate in SOAP client.
-  * Better selection of AssertionConsumerService endpoint based on parameters in AuthnRequest.
-  * Set NotOnOrAfter in IdP LogoutRequest.
-  * Only return PartialLogout from the IdP.
+`saml`
 
+* Extract Extensions from AuthnRequest for use by custom modules when authenticating.
+* Allow signing of SP metadata.
+* Better control over NameIDPolicy when sending AuthnRequest.
+* Support encrypting/decrypting NameID in LogoutRequest.
+* Option to disable client certificate in SOAP client.
+* Better selection of AssertionConsumerService endpoint based on parameters in AuthnRequest.
+* Set NotOnOrAfter in IdP LogoutRequest.
+* Only return PartialLogout from the IdP.
 
 ## Version 1.7
 
-  * New authentication modules:
-      * `aselect`
-      * `authX509`
-  * Unified cookie configuration settings.
-  * Added protection against session fixation attacks.
-  * Error logging when failing to initialize the Session class.
-  * New session storage framework.
-      * Add and use generic key/value store.
-      * Support for storing sessions in SQL databases (MySQL, PostgreSQL & SQLite).
-      * Support for implementing custom session storage handlers.
-      * Allow loading of multiple sessions simultaneously.
-  * Set headers allowing caching of static files.
-  * More descriptive error pages:
-      * Unable to load $state array because the session was lost.
-      * Unable to find metadata for the given entityID.
-  * Support for multiple keys in metadata.
-      * Allow verification with any of the public keys in metadata.
-      * Allow key rollower by defining new and old certificate in configuration.
-      * Verify with signing keys, encrypt with encryption keys.
-  * Change `debug`-option to log messages instead of displaying them in the browser.
-      * Also logs data before encryption and after decryption.
-  * Support for custom attribute dictionaries.
-  * Add support for several authentication sessions within a single session.
-      * Allows several SPs on a single host.
-      * Allows for combining an SP and an IdP on a single host.
-  * HTTP proxy support.
+* New authentication modules:
+  * `aselect`
+  * `authX509`
+* Unified cookie configuration settings.
+* Added protection against session fixation attacks.
+* Error logging when failing to initialize the Session class.
+* New session storage framework.
+  * Add and use generic key/value store.
+  * Support for storing sessions in SQL databases (MySQL, PostgreSQL & SQLite).
+  * Support for implementing custom session storage handlers.
+  * Allow loading of multiple sessions simultaneously.
+* Set headers allowing caching of static files.
+* More descriptive error pages:
+  * Unable to load $state array because the session was lost.
+  * Unable to find metadata for the given entityID.
+* Support for multiple keys in metadata.
+  * Allow verification with any of the public keys in metadata.
+  * Allow key rollower by defining new and old certificate in configuration.
+  * Verify with signing keys, encrypt with encryption keys.
+* Change `debug`-option to log messages instead of displaying them in the browser.
+  * Also logs data before encryption and after decryption.
+* Support for custom attribute dictionaries.
+* Add support for several authentication sessions within a single session.
+  * Allows several SPs on a single host.
+  * Allows for combining an SP and an IdP on a single host.
+* HTTP proxy support.
 
 ### Internal API changes & features removed
 
-  * The `saml2` module has been removed.
-      * The `saml2:SP` authsource has been removed.
-      * The `sspmod_saml2_Error` class has been renamed to `sspmod_saml_Error`.
-      * The `sspmod_saml2_Message` class has been renamed to `sspmod_saml_Message`.
-  * Moved IdP functions from `sspmod_saml_Message` to `sspmod_saml_IdP_SAML2`.
-  * Removed several functions and classes that are unused:
-      * `SimpleSAML_Utilities::strleft`
-      * `SimpleSAML_Utilities::array_values_equal`
-      * `SimpleSAML_Utilities::getRequestURI`
-      * `SimpleSAML_Utilities::getScriptName`
-      * `SimpleSAML_Utilities::getSelfProtocol`
-      * `SimpleSAML_Utilities::cert_fingerprint`
-      * `SimpleSAML_Utilities::generateTrackID`
-      * `SimpleSAML_Utilities::buildBacktrace`
-      * `SimpleSAML_Utilities::formatBacktrace`
-      * `SimpleSAML_Metadata_MetaDataStorageHandlerSAML2Meta`
-      * `SimpleSAML_ModifiedInfo`
-  * Moved function from Utilities-class to more appropriate locations.
-      * `getAuthority` to `SimpleSAML_IdP`
-      * `generateUserId` to `sspmod_saml_IdP_SAML2`.
-  * Replaced calls to  with throwing an `SimpleSAML_Error_Error` exception.
-  * Removed metadata send functionality from old SP code.
-  * Removed bin/test.php and www/admin/test.php.
-  * Removed metashare.
-  * Removed www/auth/login-auto.php.
-  * Removed www/auth/login-feide.php.
-  * Removed optional parameters from `SimpleSAML_XHTML_Template::getLanguage()`.
-  * Removed functions from `SAML2_Assertion`: `get/setDestination`, `get/setInResponseTo`.
-    Replaced with `setSubjectConfirmation`.
-  * Removed several unused files & templates.
+* The `saml2` module has been removed.
+  * The `saml2:SP` authsource has been removed.
+  * The `sspmod_saml2_Error` class has been renamed to `sspmod_saml_Error`.
+  * The `sspmod_saml2_Message` class has been renamed to `sspmod_saml_Message`.
+* Moved IdP functions from `sspmod_saml_Message` to `sspmod_saml_IdP_SAML2`.
+* Removed several functions and classes that are unused:
+  * `SimpleSAML_Utilities::strleft`
+  * `SimpleSAML_Utilities::array_values_equal`
+  * `SimpleSAML_Utilities::getRequestURI`
+  * `SimpleSAML_Utilities::getScriptName`
+  * `SimpleSAML_Utilities::getSelfProtocol`
+  * `SimpleSAML_Utilities::cert_fingerprint`
+  * `SimpleSAML_Utilities::generateTrackID`
+  * `SimpleSAML_Utilities::buildBacktrace`
+  * `SimpleSAML_Utilities::formatBacktrace`
+  * `SimpleSAML_Metadata_MetaDataStorageHandlerSAML2Meta`
+  * `SimpleSAML_ModifiedInfo`
+* Moved function from Utilities-class to more appropriate locations.
+  * `getAuthority` to `SimpleSAML_IdP`
+  * `generateUserId` to `sspmod_saml_IdP_SAML2`.
+* Replaced calls to  with throwing an `SimpleSAML_Error_Error` exception.
+* Removed metadata send functionality from old SP code.
+* Removed bin/test.php and www/admin/test.php.
+* Removed metashare.
+* Removed www/auth/login-auto.php.
+* Removed www/auth/login-feide.php.
+* Removed optional parameters from `SimpleSAML_XHTML_Template::getLanguage()`.
+* Removed functions from `SAML2_Assertion`: `get/setDestination`, `get/setInResponseTo`.
+  Replaced with `setSubjectConfirmation`.
+* Removed several unused files & templates.
 
-### SAML 2 IdP
+`SAML2 IdP`
 
-  * Support for generation of NameID values via [processing filters](./saml:nameid)
-  * Obey the NameIDPolicy Format in authentication request.
-  * Allow AuthnContextClassRef to be set by processing filters.
-  * Rework iframe logout page to not rely on cookies.
+* Support for generation of NameID values via [processing filters](./saml:nameid)
+* Obey the NameIDPolicy Format in authentication request.
+* Allow AuthnContextClassRef to be set by processing filters.
+* Rework iframe logout page to not rely on cookies.
 
-### SAML 2 SP
+`SAML2 SP`
 
-  * Support SOAP logout.
-  * Various fixes to adhere more closely to the specification.
-      * Allow multiple SessionIndex-elements in LogoutRequest.
-      * Handle multiple Assertion-elements in Response.
-      * Reject duplicate assertions.
-      * Support for encrypted NameID in LogoutRequest.
-      * Verify Destination-attribute in LogoutRequest messages.
-  * Add specific options for signing and verifying authentication request and logout messages.
-  * `saml:NameIDAttribute` filter for extracting NameID from authentication response.
+* Support SOAP logout.
+* Various fixes to adhere more closely to the specification.
+  * Allow multiple SessionIndex-elements in LogoutRequest.
+  * Handle multiple Assertion-elements in Response.
+  * Reject duplicate assertions.
+  * Support for encrypted NameID in LogoutRequest.
+  * Verify Destination-attribute in LogoutRequest messages.
+* Add specific options for signing and verifying authentication request and logout messages.
+* `saml:NameIDAttribute` filter for extracting NameID from authentication response.
 
-### SAML 1 IdP
+`SAML1 IdP`
 
-  * Add `urn:mace:shibboleth:1.0` as supported protocol in generated metadata.
+* Add `urn:mace:shibboleth:1.0` as supported protocol in generated metadata.
 
-### SAML 1 SP
+`SAML1 SP`
 
-  * Support for IdP initiated authentication.
+* Support for IdP initiated authentication.
 
-### `aggregator`
+`aggregator`
 
-  * Allow metadata generation from command line.
+* Allow metadata generation from command line.
 
-### `authfacebook`
+`authfacebook`
 
-  * Change attribute names.
+* Change attribute names.
 
-### `casserver`
+`casserver`
 
-  * Support for proxying.
-  * Add ttl for tickets.
+* Support for proxying.
+* Add ttl for tickets.
 
-### `core`
+`core`
 
-  * `core:AttributeLimit`: Make it possible to specify a default set of attributes.
-  * Make the SP metadata available on the login pages.
+* `core:AttributeLimit`: Make it possible to specify a default set of attributes.
+* Make the SP metadata available on the login pages.
 
-### `discoPower`
+`discoPower`
 
-  * Sort IdPs without a name (where we only have an entityID) last in the list.
-  * CDC cookie support.
+* Sort IdPs without a name (where we only have an entityID) last in the list.
+* CDC cookie support.
 
-### `exampleAuth`
+`exampleAuth`
 
-  * Add example of integration with external authentication page.
+* Add example of integration with external authentication page.
 
-### `ldap`
+`ldap`
 
-  * Add `ldap:AttributeAddFromLDAP` filter for adding attributes from a LDAP directory.
+* Add `ldap:AttributeAddFromLDAP` filter for adding attributes from a LDAP directory.
 
-### `metarefresh`
+`metarefresh`
 
-  * Don't stop updates on the first exception.
+* Don't stop updates on the first exception.
 
-### `openid`
+`openid`
 
-  * Don't require access to the PHP session.
-  * Remove OpenID test page. (May as well use the normal test pages.)
-  * Support for attribute exchange.
-  * Add `target` option, for directing authentication to a specific OpenID provider.
-  * Add `realm` option, for specifying the realm we should send to the OpenID provider.
+* Don't require access to the PHP session.
+* Remove OpenID test page. (May as well use the normal test pages.)
+* Support for attribute exchange.
+* Add `target` option, for directing authentication to a specific OpenID provider.
+* Add `realm` option, for specifying the realm we should send to the OpenID provider.
 
-### `portal`
+`portal`
 
-  * Make it possible to register pages from modules, and not only from configuration.
+* Make it possible to register pages from modules, and not only from configuration.
 
-### `statistics`
+`statistics`
 
-  * New y-axis scaling algorithm
+* New y-axis scaling algorithm
 
-### `twitter`
-
-  * Change attribute names returned from twitter.
+`twitter`
 
+* Change attribute names returned from twitter.
 
 ## Version 1.6.3
 
 Released 2010-12-17.
 
-  * Fix for cross site scripting in redirect page.
+* Fix for cross site scripting in redirect page.
 
 ## Version 1.6.2
 
 Released 2010-07-29.
 
-  * Various security fixes.
+* Various security fixes.
 
 ## Version 1.6.1
 
 Released 2010-06-25.
 
-  * saml:SP: Fix SingleLogoutService endpoint in SSP-format metadata array.
-  * Shib13:IdP: Add urn:mace:shibboleth:1.0 to supported protocols.
-  * Fix SAMLParser::parseElement().
-  * SAML2:IdP: Fix persistent NameID generation.
-  * Fix scoping on IdP discovery page.
-  * metaedit: Fix endpoints parsed from XML.
-  * Dictionary update.
-  * Documentation fixes.
+* saml:SP: Fix SingleLogoutService endpoint in SSP-format metadata array.
+* Shib13:IdP: Add urn:mace:shibboleth:1.0 to supported protocols.
+* Fix SAMLParser::parseElement().
+* SAML2:IdP: Fix persistent NameID generation.
+* Fix scoping on IdP discovery page.
+* metaedit: Fix endpoints parsed from XML.
+* Dictionary update.
+* Documentation fixes.
 
 ## Version 1.6
 
@@ -1662,239 +1733,236 @@ Released 2010-05-31.
 
 [Upgrade notes](./simplesamlphp-upgrade-notes-1.6)
 
-  * Detection of cookies disabled on the IdP.
-  * New IdP core, which makes it simpler to share code between different IdPs, e.g. between SAML 1.1 and SAML 2.0.
-  * Dictionaries moved to JSON format.
-  * New authentication module: [`cas:CAS`](./cas:cas).
-  * All images that doesn't permit non-commercial use have been replaced.
-  * Better support for OrganizationName, OrganizationDisplayName and OrganizationURL in metadata.
-  * Cookie secure flag no longer automatically set.
-  * Cross-protocol logout between ADFS and SAML 2.
-  * New experimental module for aggregating metadata: [`aggregator2`](./aggregator2:aggregator2)
-  * Metadata support for multiple endpoints with [multiple bindings](./simplesamlphp-metadata-endpoints).
-  * The metadata generation is using a new set of classes.
-    As a result, all generated metadata elements now have a `md:`-prefix.
-  * The deprecated functions `init(...)` and `setAuthenticated(...) in the `SimpleSAML_Session` class have been removed.
-  * Configuration check and metadata check was removed, as they were often wrong.
-
-### SAML 2 SP
-
-  * SAML 2.0 HTTP-Artifact support on the [SP](./simplesamlphp-artifact-sp).
-
-### SAML 2 IdP
-
-  * SAML 2.0 HTTP-Artifact support on the [IdP](./simplesamlphp-artifact-idp).
-  * Support for sending PartialLogout status code in logout response.
-  * Set AuthnInstant to the timestamp for authentication.
-  * Combine normal and iframe versions of the logout handlers into a single endpoint.
-  * The SessionIndex is now unique per SP.
-  * Statistics for logout failures.
-  * Better generation of persistent NameID when `nameid.attribute` isn't specified.
+* Detection of cookies disabled on the IdP.
+* New IdP core, which makes it simpler to share code between different IdPs, e.g. between SAML 1.1 and SAML 2.0.
+* Dictionaries moved to JSON format.
+* New authentication module: [`cas:CAS`](./cas:cas).
+* All images that doesn't permit non-commercial use have been replaced.
+* Better support for OrganizationName, OrganizationDisplayName and OrganizationURL in metadata.
+* Cookie secure flag no longer automatically set.
+* Cross-protocol logout between ADFS and SAML 2.
+* New experimental module for aggregating metadata: [`aggregator2`](./aggregator2:aggregator2)
+* Metadata support for multiple endpoints with [multiple bindings](./simplesamlphp-metadata-endpoints).
+* The metadata generation is using a new set of classes.
+  As a result, all generated metadata elements now have a `md:`-prefix.
+* The deprecated functions `init(...)` and `setAuthenticated(...)` in the `SimpleSAML_Session` class have been removed.
+* Configuration check and metadata check was removed, as they were often wrong.
+
+`SAML2 SP`
+
+* SAML 2.0 HTTP-Artifact support on the [SP](./simplesamlphp-artifact-sp).
+
+`SAML2 IdP`
+
+* SAML 2.0 HTTP-Artifact support on the [IdP](./simplesamlphp-artifact-idp).
+* Support for sending PartialLogout status code in logout response.
+* Set AuthnInstant to the timestamp for authentication.
+* Combine normal and iframe versions of the logout handlers into a single endpoint.
+* The SessionIndex is now unique per SP.
+* Statistics for logout failures.
+* Better generation of persistent NameID when `nameid.attribute` isn't specified.
 
 ### The SP API
 
-  * Support for handling errors from the IdP.
-  * Support for passing parameters to the authentication module.
-    This can be used to specify SAML 2 parameters, such as isPassive and ForceAuthn.
-
-### `adfs`
+* Support for handling errors from the IdP.
+* Support for passing parameters to the authentication module.
+  This can be used to specify SAML 2 parameters, such as isPassive and ForceAuthn.
 
-  * Move to new IdP core.
+`adfs`
 
-### `casserver`
+* Move to new IdP core.
 
-  * Collect all endpoints in a single file.
-  * Fix prefix on the tickets.
+`casserver`
 
-### `consent`
+* Collect all endpoints in a single file.
+* Fix prefix on the tickets.
 
-  * Support for deactivating consent for specific services.
+`consent`
 
-### `consentAdmin`
+* Support for deactivating consent for specific services.
 
-  * Support for the SAML SP module.
+`consentAdmin`
 
-### `core`
+* Support for the SAML SP module.
 
-  * New filter: [`core:PHP`](./core:authproc_php), which allows processing of attributes with arbitrary PHP code.
-  * Support for multiple target attributes in [`core:AttributeMap`](./core:authproc_attributemap).
-  * New filter: [`core:ScopeFromAttribute`](./core:authproc_scopefromattribute), which allows the creation an attribute based on the scope of another attribute.
-  * Support for a target attribute in [`core:AttributeAlter`](./core:authproc_attributealter).
+`core`
 
-### `discoPower`
+* New filter: [`core:PHP`](./core:authproc_php), which allows processing of attributes with arbitrary PHP code.
+* Support for multiple target attributes in [`core:AttributeMap`](./core:authproc_attributemap).
+* New filter: [`core:ScopeFromAttribute`](./core:authproc_scopefromattribute), which allows the creation an attribute based on the scope of another attribute.
+* Support for a target attribute in [`core:AttributeAlter`](./core:authproc_attributealter).
 
-  * Support for new scoring algorithm.
+`discoPower`
 
-### `ldap`
+* Support for new scoring algorithm.
 
-  * SASL support in LDAPMulti
+`ldap`
 
-### `ldapstatus`
+* SASL support in LDAPMulti
 
-  * This module was removed, as it was very specific for Feide.
+`ldapstatus`
 
-### `multiauth`
+* This module was removed, as it was very specific for Feide.
 
-  * Support for specifying the target authentication source through a request parameter.
+`multiauth`
 
-### `oauth`
+* Support for specifying the target authentication source through a request parameter.
 
-  * Configurable which authentication source should be used.
+`oauth`
 
-### `openidProvider`
+* Configurable which authentication source should be used.
 
-  * OpenID 2.0 support.
-  * XRDS generation support.
+`openidProvider`
 
-### `saml`
+* OpenID 2.0 support.
+* XRDS generation support.
 
-  * Support for specifying parameters for authentication request.
-  * Add AttributeConsumingService to generated metadata.
-  * The two SPSSODescriptor elements in the metadata has been merged.
+`saml`
 
+* Support for specifying parameters for authentication request.
+* Add AttributeConsumingService to generated metadata.
+* The two SPSSODescriptor elements in the metadata has been merged.
 
 ## Version 1.5.1
 
 Released 2010-01-08.
 
-  * Fix security vulnerability due to insecure temp file creation:
-    * statistics: The logcleaner script outputs to a file in /tmp.
-    * InfoCard: Saves state directly in /tmp. Changed to the SimpleSAMLphp temp directory.
-    * openidProvider: Default configuration saves state information in /tmp.
-      Changed to '/var/lib/simplesamlphp-openid-provider'.
-    * SAML 1 artifact support: Saves certificates temporarily in '/tmp/simplesaml', but directory creation was insecure.
-  * statistics: Handle new year wraparound.
-  * Dictionary updates.
-  * Fix bridged logout.
-  * Some documentation updates.
-  * Fix all metadata to use assignments to arrays.
-  * Fix $session->getIdP().
-  * Support AuthnContextClassRef in saml-module.
-  * Do not attempt to send logout request to an IdP that does not support logout.
-  * LDAP: Disallow bind with empty password.
-  * LDAP: Assume that LDAP_NO_SUCH_OBJECT is an error due to invalid username/password.
-  * statistics: Fix configuration template.
-  * Handle missing authority in idp-hosted metadata better.
-
+* Fix security vulnerability due to insecure temp file creation:
+  * statistics: The logcleaner script outputs to a file in /tmp.
+  * InfoCard: Saves state directly in /tmp. Changed to the SimpleSAMLphp temp directory.
+  * openidProvider: Default configuration saves state information in /tmp.
+    Changed to '/var/lib/simplesamlphp-openid-provider'.
+  * SAML 1 artifact support: Saves certificates temporarily in '/tmp/simplesaml', but directory creation was insecure.
+* statistics: Handle new year wraparound.
+* Dictionary updates.
+* Fix bridged logout.
+* Some documentation updates.
+* Fix all metadata to use assignments to arrays.
+* Fix $session->getIdP().
+* Support AuthnContextClassRef in saml-module.
+* Do not attempt to send logout request to an IdP that does not support logout.
+* LDAP: Disallow bind with empty password.
+* LDAP: Assume that LDAP_NO_SUCH_OBJECT is an error due to invalid username/password.
+* statistics: Fix configuration template.
+* Handle missing authority in idp-hosted metadata better.
 
 ## Version 1.5
 
 Released 2009-11-05. Revision 1937.
 
-  * New API for SP authentication.
-  * Make use of the portal module on the frontpage.
-  * SQL datastore.
-  * Support for setting timezone in config (instead of php.ini).
-  * Logging of PHP errors and notices to SimpleSAMLphp log file.
-  * Improve handling of unhandled errors and exceptions.
-  * Admin authentication through authentication sources.
-  * Various bugfixes & cleanups.
-  * Translation updates.
-  * Set the dropdown list as default for built in disco service.
-
-### New modules:
+* New API for SP authentication.
+* Make use of the portal module on the frontpage.
+* SQL datastore.
+* Support for setting timezone in config (instead of php.ini).
+* Logging of PHP errors and notices to SimpleSAMLphp log file.
+* Improve handling of unhandled errors and exceptions.
+* Admin authentication through authentication sources.
+* Various bugfixes & cleanups.
+* Translation updates.
+* Set the dropdown list as default for built in disco service.
 
-  * `adfs`
-  * [`authorize`](./authorize:authorize)
-  * `authtwitter`
-  * [`autotest`](./autotest:test)
-  * `exampleattributeserver`
-  * `metaedit`
-  * [`multiauth`](./multiauth:multiauth)
-  * `oauth`
-  * [`openidProvider`](./openidProvider:provider)
-  * [`radius`](./radius:radius)
-  * [`saml`](./saml:sp)
+`New modules`
 
-### `aggregator`:
+* `adfs`
+* [`authorize`](./authorize:authorize)
+* `authtwitter`
+* [`autotest`](./autotest:test)
+* `exampleattributeserver`
+* `metaedit`
+* [`multiauth`](./multiauth:multiauth)
+* `oauth`
+* [`openidProvider`](./openidProvider:provider)
+* [`radius`](./radius:radius)
+* [`saml`](./saml:sp)
 
-  * Add ARP + ARP signing functionality to the aggregator.
-  * Improvements to the aggregator module. Added documentation, and re-written more OO-oriented.
-  * Add support for reconstructing XML where XML for an entity is already cached.
-  * Add support for excluding tags in metadata aggregator.
+`aggregator`
 
-### `AuthMemCookie`:
+* Add ARP + ARP signing functionality to the aggregator.
+* Improvements to the aggregator module. Added documentation, and re-written more OO-oriented.
+* Add support for reconstructing XML where XML for an entity is already cached.
+* Add support for excluding tags in metadata aggregator.
 
-  * Delete the session cookie when deleting the session.
-  * Support for authentication sources.
-  * Set expiry time of session data when saving to memcache.
-  * Support multiple memcache servers.
+`AuthMemCookie`
 
-### `cas`:
+* Delete the session cookie when deleting the session.
+* Support for authentication sources.
+* Set expiry time of session data when saving to memcache.
+* Support multiple memcache servers.
 
-  * Added support for attributes in <cas:serviceResponse>.
+`cas`
 
-### `consent`:
+* Added support for attributes in <cas:serviceResponse>.
 
-  * Support for hiding some attribute values.
+`consent`
 
-### `consentAdmin`:
+* Support for hiding some attribute values.
 
-  * Added config option to display description.
+`consentAdmin`
 
-### `core`:
+* Added config option to display description.
 
-  * New WarnShortSSOInterval filter.
+`core`
 
-### `discopower`:
+* New WarnShortSSOInterval filter.
 
-  * Live search in discopower-module.
+`discopower`
 
-### `ldap`:
+* Live search in discopower-module.
 
-  * Support for proxy authentication.
-  * Add 'debug' and 'timeout' options.
-  * Privilege separation for LDAP attribute retrieval.
-  * Allow search.base to be an array.
-  * (LDAPMulti) Add support for including the organization as part of the username.
+`ldap`
 
-### `ldapstatus`:
+* Support for proxy authentication.
+* Add 'debug' and 'timeout' options.
+* Privilege separation for LDAP attribute retrieval.
+* Allow search.base to be an array.
+* (LDAPMulti) Add support for including the organization as part of the username.
 
-  * Do a connect-test to all ip-addresses for a hostname.
-  * Check whether hostname exists before attempting to connect.
-  * hobbit output.
-  * Check schema version.
-  * Add command line tab to single LDAP status page for easier debugging.
+`ldapstatus`
 
-### `logpeek`:
+* Do a connect-test to all ip-addresses for a hostname.
+* Check whether hostname exists before attempting to connect.
+* hobbit output.
+* Check schema version.
+* Add command line tab to single LDAP status page for easier debugging.
 
-  * Blockwise reading of logfile for faster execution.
+`logpeek`
 
-### `metarefresh`:
+* Blockwise reading of logfile for faster execution.
 
-  * Adding support for generating Shibboleth ARP files.
-  * Add 'serialize' metadata format.
+`metarefresh`
 
-### `preprodwarning`:
+* Adding support for generating Shibboleth ARP files.
+* Add 'serialize' metadata format.
 
-  * Don't show warning in passive request.
-  * Focus on continue-button.
+`preprodwarning`
 
-### SAML:
+* Don't show warning in passive request.
+* Focus on continue-button.
 
-  * Support for multiple AssertionConsumerService endpoints.
-  * SAML 1 artifact support on the SP side.
-  * New SAML authentication module.
-  * Deprecation of www/saml2/sp & www/shib13/sp.
-  * Support for encrypted NameID.
-  * NameIDPolicy replaces NameIDFormat.
-  * Better support for IdP initiated SSO and bookmarked login pages.
-  * Improvements to iframe logout page.
-  * Scoping support.
-  * New library for SAML 2 messages.
-  * Support for transporting errors from the IdP to the SP.
-  * Sign both the assertion and the response element by default.
-  * Support for sending XML attribute values from the IdP.
+`saml`
 
-### `statistics`:
+* Support for multiple AssertionConsumerService endpoints.
+* SAML 1 artifact support on the SP side.
+* New SAML authentication module.
+* Deprecation of www/saml2/sp & www/shib13/sp.
+* Support for encrypted NameID.
+* NameIDPolicy replaces NameIDFormat.
+* Better support for IdP initiated SSO and bookmarked login pages.
+* Improvements to iframe logout page.
+* Scoping support.
+* New library for SAML 2 messages.
+* Support for transporting errors from the IdP to the SP.
+* Sign both the assertion and the response element by default.
+* Support for sending XML attribute values from the IdP.
 
-  * Extended Google chart encoding... Add option of alternative compare plot in graph...
-  * Added support for Ratio type reports in the statistics module..
-  * Changed default rule to SSO.
-  * Added incremental aggregation, independent time resolution from rule def, combined coldefs and more.
-  * Add DST support in date handler. Added summary columns per delimiter. Added pie chart. +++
-  * Log first SSO to a service during a session.
+`statistics`
 
+* Extended Google chart encoding... Add option of alternative compare plot in graph...
+* Added support for Ratio type reports in the statistics module..
+* Changed default rule to SSO.
+* Added incremental aggregation, independent time resolution from rule def, combined coldefs and more.
+* Add DST support in date handler. Added summary columns per delimiter. Added pie chart. +++
+* Log first SSO to a service during a session.
 
 ## Version 1.4
 
@@ -1902,76 +1970,74 @@ Released 2009-03-12. Revision 1405.
 
 Updates to `config.php`. Please check for updates in your local modified configuration.
 
-  * Language updates
-  * Documentation update. New authentication source API now default and documented.
-  * New authentication source (new API):
-    * LDAP
-    * LDAPMulti  
-	* YubiKey authentication source. (Separate module)  
-	* Facebook authentication source. (Separate module)
-  * New Authentication Processing Filter:
-    * AttributeAlter
-    * AttributeFilter
-    * AttributeMap
-    * Smartname. does it best to guess the full name of the user based on several attributes.
-    * Language adaptor: allow adopting UI by preferredLanguage SAML 2.0 Attribute both on the IdP and the SP. And if the user selects a language, this can be sent to the SP as an attribute.
-  * New module: portal, allows you to created tabbed interface for custom pages within SimpleSAMLphp. In example user consent management and attribute viewer.
-  * New module: ldapstatus. Used by Feide to monitor connections to a large list of LDAP connections. Contact Feide on details on how to use.
-  * ldapstatus also got certificate check capabilities.
-  * New module: MemcacheMonitor: Show statistics for memcache servers.
-  * New module: DiscoPower. A tabbed discovery service module with a lot of functionality.
-  * New module: SAML 2.0 Debugginer. An improved version of the one found on rnd.feide.no earlier is not included in SimpleSAMLphp allowing you to run it locally.
-  * New module: Simple Consent Amdin module that have one button to remove all consent for one user.
-  * New module: Consent Administration. Contribution from Wayf.
-  * We also have a consent administration module that we use in Feide that is not checked in to subversion.
-  * New module: logpeek. Lets administrator lookup loglines matching a TRackID.
-  * New module: PreprodWarning: Adding a warning to users that access a preprod system.
-  * New module: CAS Server
-  * New module: Aggregator: Aggregates metadata. Used in Kalmar Union.
-  * New module: Metarefresh, download, parses and consumes metadata.
-  * New module: SanityCheck. Checks if things looks good and reports bad configuration etc.
-  * New module: Cron. Will perform tasks regularly. 
-  * Module: SAML2.0. SAML 2.0 SP implemented as an module. Yet not documented how to use, but all SAML 2.0 SP functionality may be moved out to this module for better modularization.
-  * New module: statistics. Parses STAT log files, and aggregates based on a generic rule system. Output is stored in aggregated text files, and a frontend is included to present statistics with tables and graphs. Used sanitycheck and cron.
-  * Added support for IdP initiated SSO.
-  * Added support for IdP-initiated SLO with iFrame type logout.
-  * Major updates to iFrame AJAX SLO. Improved user experience.
-  * iFrame AJAX SLO is not safe against simultaneous update of the session.
-  * Added support for bookmarking login pages. By adding enough information in the URL to be able to bootstrap a new IdP-initiated SSO and sending.
-  * Major updates to the infocard module.
-  * Added some handling of isPassive with authentication processing filters.
-  * More localized UI.
-  * New login as administrator link on frontpage.
-  * Tabbed frontpage. Restructured.
-  * Simplifications to the theming and updated documentation on theming SimpleSAMLphp.
-  * Attribute presentation hook allows you to tweak attributes before presentation in the attribute viewers. Used by Feide to group orgUnit information in a hieararchy.
-  * Verification of the Recipient attribute in the response. Will improve security if for some reason an IdP is not includeding sufficient Audience restrictions.
-  * Added hook to let modules tell about themself moduleinfo hook.
-  * Improved cron mails
-  * Improved sanity check exception handling
-  * Preserver line breaks in stack trace UI
-  * Improvements to WS-Federation support: dynamic realms, logout etc.
-  * Better handling of presentation of JPEG photos as attributes.
-  * Support limiting size of attribute retrieved from LDAP.
-  * Added notes about how to aggregate and consume metadata. Just a start.
-  * Large improvements to Configuration class, and config helper functions.
-  * STAT logging is moved into separate authentication processing filter.
-  * Fix for NoPassive responses to Google Apps with alternative NameIDFormats.  
-  * LDAP module allows to search multiple searchbases.
-  * All documentation is converted from docbook to markdown format.
-  * Added headers to not allow google to index pages.
-  * Added check on frontpage for magic quotes
-  * Added statistic logging to Consent class.
-  * Improvements to Exception handler in LDAP class, and better logging.
-  * LDAP class supports turning on LDAP-debug logging.
-  * Much improvements to SAML 2.0 Metadata generation and parsing.
-  * Adding more recent jQuery library.
-  * Generic interface for including jQuery dependencies in template headers.
-  * Improved UI on default theme
-  * Fix for session duration in the Conditions element in the Assertion (SAML 2.0).
-  * Updated with new Feide IdP metadata in metadata-templates
-  
-
+* Language updates
+* Documentation update. New authentication source API now default and documented.
+* New authentication source (new API):
+  * LDAP
+  * LDAPMulti  
+  * YubiKey authentication source. (Separate module)  
+  * Facebook authentication source. (Separate module)
+* New Authentication Processing Filter:
+  * AttributeAlter
+  * AttributeFilter
+  * AttributeMap
+  * Smartname. does it best to guess the full name of the user based on several attributes.
+  * Language adaptor: allow adopting UI by preferredLanguage SAML 2.0 Attribute both on the IdP and the SP. And if the user selects a language, this can be sent to the SP as an attribute.
+* New module: portal, allows you to created tabbed interface for custom pages within SimpleSAMLphp. In example user consent management and attribute viewer.
+* New module: ldapstatus. Used by Feide to monitor connections to a large list of LDAP connections. Contact Feide on details on how to use.
+* ldapstatus also got certificate check capabilities.
+* New module: MemcacheMonitor: Show statistics for memcache servers.
+* New module: DiscoPower. A tabbed discovery service module with a lot of functionality.
+* New module: SAML 2.0 Debugginer. An improved version of the one found on rnd.feide.no earlier is not included in SimpleSAMLphp allowing you to run it locally.
+* New module: Simple Consent Amdin module that have one button to remove all consent for one user.
+* New module: Consent Administration. Contribution from Wayf.
+* We also have a consent administration module that we use in Feide that is not checked in to subversion.
+* New module: logpeek. Lets administrator lookup loglines matching a TRackID.
+* New module: PreprodWarning: Adding a warning to users that access a preprod system.
+* New module: CAS Server
+* New module: Aggregator: Aggregates metadata. Used in Kalmar Union.
+* New module: Metarefresh, download, parses and consumes metadata.
+* New module: SanityCheck. Checks if things looks good and reports bad configuration etc.
+* New module: Cron. Will perform tasks regularly.
+* Module: SAML2.0. SAML 2.0 SP implemented as an module. Yet not documented how to use, but all SAML 2.0 SP functionality may be moved out to this module for better modularization.
+* New module: statistics. Parses STAT log files, and aggregates based on a generic rule system. Output is stored in aggregated text files, and a frontend is included to present statistics with tables and graphs. Used sanitycheck and cron.
+* Added support for IdP initiated SSO.
+* Added support for IdP-initiated SLO with iFrame type logout.
+* Major updates to iFrame AJAX SLO. Improved user experience.
+* iFrame AJAX SLO is not safe against simultaneous update of the session.
+* Added support for bookmarking login pages. By adding enough information in the URL to be able to bootstrap a new IdP-initiated SSO and sending.
+* Major updates to the infocard module.
+* Added some handling of isPassive with authentication processing filters.
+* More localized UI.
+* New login as administrator link on frontpage.
+* Tabbed frontpage. Restructured.
+* Simplifications to the theming and updated documentation on theming SimpleSAMLphp.
+* Attribute presentation hook allows you to tweak attributes before presentation in the attribute viewers. Used by Feide to group orgUnit information in a hieararchy.
+* Verification of the Recipient attribute in the response. Will improve security if for some reason an IdP is not includeding sufficient Audience restrictions.
+* Added hook to let modules tell about themself moduleinfo hook.
+* Improved cron mails
+* Improved sanity check exception handling
+* Preserver line breaks in stack trace UI
+* Improvements to WS-Federation support: dynamic realms, logout etc.
+* Better handling of presentation of JPEG photos as attributes.
+* Support limiting size of attribute retrieved from LDAP.
+* Added notes about how to aggregate and consume metadata. Just a start.
+* Large improvements to Configuration class, and config helper functions.
+* STAT logging is moved into separate authentication processing filter.
+* Fix for NoPassive responses to Google Apps with alternative NameIDFormats.  
+* LDAP module allows to search multiple searchbases.
+* All documentation is converted from docbook to markdown format.
+* Added headers to not allow google to index pages.
+* Added check on frontpage for magic quotes
+* Added statistic logging to Consent class.
+* Improvements to Exception handler in LDAP class, and better logging.
+* LDAP class supports turning on LDAP-debug logging.
+* Much improvements to SAML 2.0 Metadata generation and parsing.
+* Adding more recent jQuery library.
+* Generic interface for including jQuery dependencies in template headers.
+* Improved UI on default theme
+* Fix for session duration in the Conditions element in the Assertion (SAML 2.0).
+* Updated with new Feide IdP metadata in metadata-templates
 
 ## Version 1.3
 
@@ -1979,38 +2045,37 @@ Released 2008-11-04. Revision 973.
 
 Configuration file `config.php` should not include significant changes, except one language added.
 
-### New features
-
-  * Documentation update
-  * Added new language. Now there are two different portuguese
-    dialects.
-  * Consent "module" modified. Now added support for preselecting the
-    checkbox by a configuration parameter. Consent module supports
-    including attributes values (possible to configure).
-  * CSS and look changed. Removed transparency to fix problem for some
-    browsers.
-  * The login-admin authentication module does not ask for username any
-    more.
-  * Added support for persistent NameID Format. (Added by Hans
-    ZAndbelt)
-  * Added experimental SAML 2.0 SP AuthSource module.
-  * More readable XML output formatting. In example metadata.
-  * Better support for choosing whether or not to sign authnrequest.
-    Possible to specify both at SP hosted and IdP remote.
-  * Adding more example metadata in metadata-templates.
-  * Improved e-mails sent from SimpleSAMLphp. Now both plain text and
-    html.
-  * Configuration class may return information about what version.
-  * iFrame AJAX SLO improved. Now with non-JavaScript fallback
-    handling.
-
-### Bug fixes
-
-  * Fixed warning with XML validator.
-  * Improved loading of private/public keys in XML/Signer.
-  * Improvements to CAS module.
-  * Fixed memcache stats.
-
+`New features`
+
+* Documentation update
+* Added new language. Now there are two different portuguese
+  dialects.
+* Consent "module" modified. Now added support for preselecting the
+  checkbox by a configuration parameter. Consent module supports
+  including attributes values (possible to configure).
+* CSS and look changed. Removed transparency to fix problem for some
+  browsers.
+* The login-admin authentication module does not ask for username any
+  more.
+* Added support for persistent NameID Format. (Added by Hans
+  ZAndbelt)
+* Added experimental SAML 2.0 SP AuthSource module.
+* More readable XML output formatting. In example metadata.
+* Better support for choosing whether or not to sign authnrequest.
+  Possible to specify both at SP hosted and IdP remote.
+* Adding more example metadata in metadata-templates.
+* Improved e-mails sent from SimpleSAMLphp. Now both plain text and
+  html.
+* Configuration class may return information about what version.
+* iFrame AJAX SLO improved. Now with non-JavaScript fallback
+  handling.
+
+`Bug fixes`
+
+* Fixed warning with XML validator.
+* Improved loading of private/public keys in XML/Signer.
+* Improvements to CAS module.
+* Fixed memcache stats.
 
 ## Version 1.2
 
@@ -2022,45 +2087,40 @@ When you upgrade from an previous version you should copy `authsources.php` from
 
 There are also some changes to the templates. If you have any custom templates, they should be updated to match the ones included. Of notable changes is that the `t(...)`-functtes, they should be updated to match the ones included. Of notable changes is that the `t(...)`-function has been simplified, and takes far fewer parameters. It is backwardscompatible, but will write a warning to the log until updated. The backwards compatibility will be removed in a future version.
 
-### New features
-
-  * Experimental support for modules. Currently modules can contain
-    custom authentication sources, authentication processing filters
-    and themes.
-  * An generic SQL authentication module added for those who store their
-    users in an SQL database.
-  * Limited support for validating against a CA root certificate. The
-    current implementation only supports cases where the certificate is
-    directly signed by the CA.
-  * Allow an IdP to have multiple valid certificate fingerprints, to
-    allow for easier updating of certificates.
-  * Shibboleth 1.3 authentication for Auth MemCookie.
-  * Support for link to privacy policy on consent-pages.
-  * Customizable initial focus on consent-page.
-  * Almost all pages should be translatable.
-  * Allow SAML 2.0 SP to handle error replies from IdP.
-  * PostgreSQL support for consent storage.
-  * Add support for encrypted private keys.
-  * Proof-of-concept MetaShare service, for easy publishing and sharing
-    of metadata.
-
-
-### Bug fixes
-
-  * Fixed generated SAML 2.0 metadata to be correct.
-  * Fixed logout for Auth MemCookie.
-  * Sign SAML 2.0 authentication response on failure (such as
-    NoPassive).
-  * Fixes for IsPassive in the SAML 2.0 IdP.
-  * Fix default syslog configuration on Windows.
-  * Fix order of signing and encryption of SAML 2.0 responses
-  * Fix generated metadata for Shib 1.3
-  * Fix order of elements in encrypted assertions to be schema
-    compliant.
-  * Fix session index sent to SAML 2.0 SPs.
-  * Remember SAML 2.0 NameID sent to SPs, and include it in logout
-    requests.
-
+`New features`
+
+* Experimental support for modules. Currently modules can contain
+  custom authentication sources, authentication processing filters
+  and themes.
+* An generic SQL authentication module added for those who store their
+  users in an SQL database.
+* Limited support for validating against a CA root certificate. The
+  current implementation only supports cases where the certificate is
+  directly signed by the CA.
+* Allow an IdP to have multiple valid certificate fingerprints, to
+  allow for easier updating of certificates.
+* Shibboleth 1.3 authentication for Auth MemCookie.
+* Support for link to privacy policy on consent-pages.
+* Customizable initial focus on consent-page.
+* Almost all pages should be translatable.
+* Allow SAML 2.0 SP to handle error replies from IdP.
+* PostgreSQL support for consent storage.
+* Add support for encrypted private keys.
+* Proof-of-concept MetaShare service, for easy publishing and sharing
+  of metadata.
+
+`Bug fixes`
+
+* Fixed generated SAML 2.0 metadata to be correct.
+* Fixed logout for Auth MemCookie.
+* Sign SAML 2.0 authentication response on failure (such as NoPassive).
+* Fixes for IsPassive in the SAML 2.0 IdP.
+* Fix default syslog configuration on Windows.
+* Fix order of signing and encryption of SAML 2.0 responses
+* Fix generated metadata for Shib 1.3
+* Fix order of elements in encrypted assertions to be schema compliant.
+* Fix session index sent to SAML 2.0 SPs.
+* Remember SAML 2.0 NameID sent to SPs, and include it in logout requests.
 
 ## Version 1.1
 
@@ -2072,82 +2132,80 @@ There are also several changes to the template files. If you have done any custo
 
 New localizations in version 1.1: Sami, Svenska (swedish), Suomeksi (finnish), Nederlands, Luxembourgish, Slovenian, Hrvatski (Croatian), Magyar (Hungarian).
 
-### New features
-
-  * Add support for saving the users choice of IdP in the IdP discovery
-    service.
-  * Add a config option for whether the Response element or the
-    Assertion element in the response should be signed.
-  * Make it easier to add attribute alteration functions.
-  * Added support for multiple languages in metadata name and
-    description (for IdP discovery service).
-  * Added configuration checker for checking if configuration files
-    should be updated.
-  * Add support for icons in IdP discovery service.
-  * Add support for external IdP discovery services.
-  * Support password encrypted private keys.
-  * Added PHP autoloading as the preferred way of loading the
-    SimpleSAMLphp library.
-  * New error report script which will report errors to the
-    `technicalcontact_email` address.
-  * Support lookup of the DN of the user who is logging in by searching
-    for an attribute when using the LDAP authentication module.
-  * Add support for fetching name and description of entities from XML
-    metadata files.
-  * Support for setting custom AttributeNameFormats.
-  * Support for signing generated metadata.
-  * Support for signature validation of metadata.
-  * Added consent support for Shib 1.3 logging.
-  * Added errorlog logging handler for logging to the default Apache
-    error log.
-  * Added support for WS-Federation single signon.
-  * Allow `session_save_path` to be overridden by setting the
-    `session.phpsession.savepath` option in `config.php`.
-  * Add support for overriding autogenerated metadata values, such as
-    the `AssertionConsumerService` address.
-  * Added IsPassive support in the SAML 2.0 IdP.
-  * Add attribute filter for generating eduPersonTargetedID attribute.
-  * Add support for validation of sent and received messages and
-    metadata.
-  * Add support for dynamic metadata loading with cache.
-  * Add support for dynamic generation of entityid and metadata.
-  * Added wayf.dk login module.
-  * Add support for encrypting and decrypting assertions.
-  * CAS authentication module: Add support for serviceValidate.
-  * CAS authentication module: Add support for getting attributes from
-    response by specifying XPath mappings.
-  * Add support for specifying a certificate in the `saml20-idp-remote`
-    metadata instead of a fingerprint.
-  * Add an attribute alter function for dynamic group generation.
-  * Add support for attribute processing in SAML 2 SP.
-  * Added tlsclient authentication module.
-  * Allow the templates to override the header and footer of pages.
-  * Major improvements to the Feide authentication module.
-  * Add support for ForceAuthn in the SAML 2.0 IdP.
-  * Choose language based on the languages the user has selected in the
-    web browser.
-  * Added fallback to base language if translation isn't found.
-
-
-### Bug fixes
-
-  * Modified IdP discovery service to support Shibboleth 2.0 SP.
-  * Fix setcookie warning for PHP version \< 5.2.
-  * Fix logout not being performed for Auth MemCache sometimes.
-  * Preserve case of attribute names during LDAP attribute retrieval.
-  * Fix IdP-initiated logout.
-  * Ensure that changed sessions with changed SP associations are
-    written to memcache.
-  * Prevent infinite recursion during logging.
-  * Don't send the relaystate from the SP which initiated the logout to
-    other SPs during logout.
-  * Prevent consent module from revealing DB password when an error
-    occurs.
-  * Fix logout with memcache session handler.
-  * Allow new session to be created in login modules.
-  * Removed the strict parameter from base64\_decode for PHP 5.1
-    compatibility.
-
+`New features`
+
+* Add support for saving the users choice of IdP in the IdP discovery
+  service.
+* Add a config option for whether the Response element or the
+  Assertion element in the response should be signed.
+* Make it easier to add attribute alteration functions.
+* Added support for multiple languages in metadata name and
+  description (for IdP discovery service).
+* Added configuration checker for checking if configuration files
+  should be updated.
+* Add support for icons in IdP discovery service.
+* Add support for external IdP discovery services.
+* Support password encrypted private keys.
+* Added PHP autoloading as the preferred way of loading the
+  SimpleSAMLphp library.
+* New error report script which will report errors to the
+  `technicalcontact_email` address.
+* Support lookup of the DN of the user who is logging in by searching
+  for an attribute when using the LDAP authentication module.
+* Add support for fetching name and description of entities from XML
+  metadata files.
+* Support for setting custom AttributeNameFormats.
+* Support for signing generated metadata.
+* Support for signature validation of metadata.
+* Added consent support for Shib 1.3 logging.
+* Added errorlog logging handler for logging to the default Apache
+  error log.
+* Added support for WS-Federation single signon.
+* Allow `session_save_path` to be overridden by setting the
+  `session.phpsession.savepath` option in `config.php`.
+* Add support for overriding autogenerated metadata values, such as
+  the `AssertionConsumerService` address.
+* Added IsPassive support in the SAML 2.0 IdP.
+* Add attribute filter for generating eduPersonTargetedID attribute.
+* Add support for validation of sent and received messages and
+  metadata.
+* Add support for dynamic metadata loading with cache.
+* Add support for dynamic generation of entityid and metadata.
+* Added wayf.dk login module.
+* Add support for encrypting and decrypting assertions.
+* CAS authentication module: Add support for serviceValidate.
+* CAS authentication module: Add support for getting attributes from
+  response by specifying XPath mappings.
+* Add support for specifying a certificate in the `saml20-idp-remote`
+  metadata instead of a fingerprint.
+* Add an attribute alter function for dynamic group generation.
+* Add support for attribute processing in SAML 2 SP.
+* Added tlsclient authentication module.
+* Allow the templates to override the header and footer of pages.
+* Major improvements to the Feide authentication module.
+* Add support for ForceAuthn in the SAML 2.0 IdP.
+* Choose language based on the languages the user has selected in the
+  web browser.
+* Added fallback to base language if translation isn't found.
+
+`Bug fixes`
+
+* Modified IdP discovery service to support Shibboleth 2.0 SP.
+* Fix setcookie warning for PHP version \< 5.2.
+* Fix logout not being performed for Auth MemCache sometimes.
+* Preserve case of attribute names during LDAP attribute retrieval.
+* Fix IdP-initiated logout.
+* Ensure that changed sessions with changed SP associations are
+  written to memcache.
+* Prevent infinite recursion during logging.
+* Don't send the relaystate from the SP which initiated the logout to
+  other SPs during logout.
+* Prevent consent module from revealing DB password when an error
+  occurs.
+* Fix logout with memcache session handler.
+* Allow new session to be created in login modules.
+* Removed the strict parameter from base64\_decode for PHP 5.1
+  compatibility.
 
 ## Version 1.0
 
@@ -2162,48 +2220,47 @@ Released 2007-10-15. Revision 28.
 Both `config.php` and metadata format are changed. Look at the
 templates to understand the new format.
 
-  * Documentation is updated!
-  * Metadata files made tidier. Unused entries removed. Look at the new
-    templates on how to change your existing metadata.
-  * Support for sending metadata by mail to Feide. Automatically
-    detecting whether you have configured Feide as the default IdP or
-    not.
-  * Improved SAML 2.0 Metadata generation
-  * Added support for Shibboleth 1.3 IdP functionality (beta, contact
-    me if any problems)
-  * Added RADIUS authentication backend
-  * Added support for HTTP-Redirect debugging when enable `debug=true`
-  * SAML 2.0 SP example now contains a logout page.
-  * Added new authentication backend with support for multiple LDAP
-    based on which organization the user selects.
-  * Added SAML 2.0 Discovery Service
-  * Initial 'proof of concept' implementation of "User consent on
-    attribute release"
-  * Fixed some minor bugs.
-
+* Documentation is updated!
+* Metadata files made tidier. Unused entries removed. Look at the new
+  templates on how to change your existing metadata.
+* Support for sending metadata by mail to Feide. Automatically
+  detecting whether you have configured Feide as the default IdP or
+  not.
+* Improved SAML 2.0 Metadata generation
+* Added support for Shibboleth 1.3 IdP functionality (beta, contact
+  me if any problems)
+* Added RADIUS authentication backend
+* Added support for HTTP-Redirect debugging when enable `debug=true`
+* SAML 2.0 SP example now contains a logout page.
+* Added new authentication backend with support for multiple LDAP
+  based on which organization the user selects.
+* Added SAML 2.0 Discovery Service
+* Initial 'proof of concept' implementation of "User consent on
+  attribute release"
+* Fixed some minor bugs.
 
 ## Version 0.4
 
 Released 2007-09-14. Revision X.
 
-  * Improved documentation
-  * Authentication plugin API. Only LDAP authentication plugin is
-    included, but it is now easier to implement your own plugin.
-  * Added support for SAML 2.0 IdP to work with Google Apps for
-    Education. Tested.
-  * Initial implementation of SAML 2.0 Single Log Out functionality
-    both for SP and IdP. Seems to work, but not yet well-tested.
-  * Added support for bridging SAML 2.0 to SAML 2.0.
-  * Added some time skew offset to the NotBefore timestamp on the
-    assertion, to allow some time skew between the SP and IdP.
-  * Fixed Browser/POST page to automatically submit, and have fall back
-    functionality for user agents with no JavaScript support.
-  * Fixed some bug with warning traversing Shibboleth 1.3 Assertions.
-  * Fixed tabindex on the login page of the LDAP authentication module
-    to allow you to tab from username, to password and then to submit.
-  * Fixed bug on autodiscovering hostname in multihost environments.
-  * Cleaned out some debug messages, and added a debug option in the
-    configuration file. This debug option let's you turn on the
-    possibility of showing all SAML messages to users in the web
-    browser, and manually submit them.
-  * Several minor bugfixes.
+* Improved documentation
+* Authentication plugin API. Only LDAP authentication plugin is
+  included, but it is now easier to implement your own plugin.
+* Added support for SAML 2.0 IdP to work with Google Apps for
+  Education. Tested.
+* Initial implementation of SAML 2.0 Single Log Out functionality
+  both for SP and IdP. Seems to work, but not yet well-tested.
+* Added support for bridging SAML 2.0 to SAML 2.0.
+* Added some time skew offset to the NotBefore timestamp on the
+  assertion, to allow some time skew between the SP and IdP.
+* Fixed Browser/POST page to automatically submit, and have fall back
+  functionality for user agents with no JavaScript support.
+* Fixed some bug with warning traversing Shibboleth 1.3 Assertions.
+* Fixed tabindex on the login page of the LDAP authentication module
+  to allow you to tab from username, to password and then to submit.
+* Fixed bug on autodiscovering hostname in multihost environments.
+* Cleaned out some debug messages, and added a debug option in the
+  configuration file. This debug option let's you turn on the
+  possibility of showing all SAML messages to users in the web
+  browser, and manually submit them.
+* Several minor bugfixes.
diff --git a/docs/simplesamlphp-customauth.md b/docs/simplesamlphp-customauth.md
index 2e48d002a7bd1dbf87ba2409ef340b2b92fba909..f5e316b6238d09eaa0899b5c8391d94ed8c6effe 100644
--- a/docs/simplesamlphp-customauth.md
+++ b/docs/simplesamlphp-customauth.md
@@ -16,13 +16,14 @@ It will be located under `modules/mymodule`.
 
 First we need to create the module directory:
 
-    cd modules
-    mkdir mymodule
+```bash
+cd modules
+mkdir mymodule
+```
 
 Since this is a custom module, it should always be enabled in the configuration.
 Now that we have our own module, we can move on to creating an authentication source.
 
-
 Creating a basic authentication source
 --------------------------------------
 
@@ -33,38 +34,43 @@ It will be implemented in the file `modules/mymodule/lib/Auth/Source/MyAuth.php`
 To begin with, we will create a very simple authentication source, where the username and password is hardcoded into the source code.
 Create the file `modules/mymodule/lib/Auth/Source/MyAuth.php` with the following contents:
 
-    <?php
-    namespace SimpleSAML\Module\mymodule\Auth\Source;
+```php
+<?php
 
-    class MyAuth extends \SimpleSAML\Module\core\Auth\UserPassBase {
-        protected function login($username, $password) {
-            if ($username !== 'theusername' || $password !== 'thepassword') {
-                throw new \SimpleSAML\Error\Error('WRONGUSERPASS');
-            }
-            return [
-                'uid' => ['theusername'],
-                'displayName' => ['Some Random User'],
-                'eduPersonAffiliation' => ['member', 'employee'],
-            ];
+namespace SimpleSAML\Module\mymodule\Auth\Source;
+
+class MyAuth extends \SimpleSAML\Module\core\Auth\UserPassBase
+{
+    protected function login($username, $password)
+    {
+        if ($username !== 'theusername' || $password !== 'thepassword') {
+            throw new \SimpleSAML\Error\Error('WRONGUSERPASS');
         }
+
+        return [
+            'uid' => ['theusername'],
+            'displayName' => ['Some Random User'],
+            'eduPersonAffiliation' => ['member', 'employee'],
+        ];
     }
+}
+```
 
 Some things to note:
 
-  - The classname is `\SimpleSAML\Module\mymodule\Auth\Source\MyAuth`.
-    This tells SimpleSAMLphp to look for the class in `modules/mymodule/lib/Auth/Source/MyAuth.php`.
-
-  - Our authentication source subclasses `\SimpleSAML\Module\core\Auth\UserPassBase`.
-    This is a helper-class that implements much of the common code needed for username/password authentication.
+- The classname is `\SimpleSAML\Module\mymodule\Auth\Source\MyAuth`.
+  This tells SimpleSAMLphp to look for the class in `modules/mymodule/lib/Auth/Source/MyAuth.php`.
 
-  - The `login` function receives the username and password the user enters.
-    It is expected to authenticate the user.
-    If the username or password is correct, it must return a set of attributes for the user.
-    Otherwise, it must throw the `\SimpleSAML\Error\Error('WRONGUSERPASS');` exception.
+- Our authentication source subclasses `\SimpleSAML\Module\core\Auth\UserPassBase`.
+  This is a helper-class that implements much of the common code needed for username/password authentication.
 
-  - Attributes are returned as an associative array of `name => values` pairs.
-    All attributes can have multiple values, so the values are always stored in an array.
+- The `login` function receives the username and password the user enters.
+  It is expected to authenticate the user.
+  If the username or password is correct, it must return a set of attributes for the user.
+  Otherwise, it must throw the `\SimpleSAML\Error\Error('WRONGUSERPASS');` exception.
 
+- Attributes are returned as an associative array of `name => values` pairs.
+  All attributes can have multiple values, so the values are always stored in an array.
 
 Configuring our authentication source
 -------------------------------------
@@ -74,19 +80,24 @@ Before we can test our authentication source, we must add an entry for it in `co
 
 The entry looks like this:
 
-    'myauthinstance' => [
-        'mymodule:MyAuth',
-    ],
+```php
+'myauthinstance' => [
+    'mymodule:MyAuth',
+],
+```
 
 You can add it to the beginning of the list, so that the file looks something like this:
 
-    <?php
-    $config = [
-        'myauthinstance' => [
-            'mymodule:MyAuth',
-        ],
-        /* Other authentication sources follow. */
-    ];
+```php
+<?php
+
+$config = [
+    'myauthinstance' => [
+        'mymodule:MyAuth',
+    ],
+    /* Other authentication sources follow. */
+];
+```
 
 `myauthinstance` is the name of this instance of the authentication source.
 (You are allowed to have multiple instances of an authentication source with different configuration.)
@@ -95,7 +106,6 @@ The instance name is used to refer to this authentication source in other config
 The first element of the configuration of the authentication source must be `'mymodule:MyAuth'`.
 This tells SimpleSAMLphp to look for the `\SimpleSAML\Module\mymodule\Auth\Source\MyAuth` class.
 
-
 Testing our authentication source
 ---------------------------------
 
@@ -110,7 +120,6 @@ You should then arrive on a page listing the attributes we return from the `logi
 
 Next, you should log out by following the log out link.
 
-
 Using our authentication source in an IdP
 -----------------------------------------
 
@@ -118,22 +127,24 @@ To use our new authentication source in an IdP we just need to update the IdP co
 Open `metadata/saml20-idp-hosted.php`.
 In that file you should locate the `auth`-option for your IdP, and change it to `myauthinstance`:
 
-    <?php
+```php
+<?php
+
+/* ... */
+$metadata['https://example.org/saml-idp'] = [
     /* ... */
-    $metadata['https://example.org/saml-idp'] = [
-        /* ... */
-        /*
-         * Authentication source to use. Must be one that is configured in
-         * 'config/authsources.php'.
-         */
-        'auth' => 'myauthinstance',
-        /* ... */
-    ];
+    /*
+     * Authentication source to use. Must be one that is configured in
+     * 'config/authsources.php'.
+     */
+    'auth' => 'myauthinstance',
+    /* ... */
+];
+```
 
 You can then test logging in to the IdP.
 If you have logged in previously, you may need to log out first.
 
-
 Adding configuration to our authentication source
 -------------------------------------------------
 
@@ -142,71 +153,85 @@ We are now going to extend our authentication source to allow us to configure th
 
 First, we need to define the properties in the class that should hold our configuration:
 
-    private $username;
-    private $password;
+```php
+private $username;
+private $password;
+```
 
 Next, we create a constructor for the class.
 The constructor is responsible for parsing the configuration and storing it in the properties.
 
-    public function __construct($info, $config) {
+```php
+public function __construct($info, $config)
+{
+    parent::__construct($info, $config);
+
+    if (!is_string($config['username'])) {
+        throw new Exception('Missing or invalid username option in config.');
+    }
+    $this->username = $config['username'];
+
+    if (!is_string($config['password'])) {
+        throw new Exception('Missing or invalid password option in config.');
+    }
+    $this->password = $config['password'];
+}
+```
+
+We can then use the properties in the `login` function.
+The complete class file should look like this:
+
+```php
+<?php
+
+class MyAuth extends \SimpleSAML\Module\core\Auth\UserPassBase
+{
+    private $username;
+    private $password;
+
+    public function __construct($info, $config)
+    {
         parent::__construct($info, $config);
         if (!is_string($config['username'])) {
             throw new Exception('Missing or invalid username option in config.');
         }
         $this->username = $config['username'];
+
         if (!is_string($config['password'])) {
             throw new Exception('Missing or invalid password option in config.');
         }
         $this->password = $config['password'];
     }
 
-We can then use the properties in the `login` function.
-The complete class file should look like this:
-
-    <?php
-    class MyAuth extends \SimpleSAML\Module\core\Auth\UserPassBase {
-
-        private $username;
-        private $password;
-
-        public function __construct($info, $config) {
-            parent::__construct($info, $config);
-            if (!is_string($config['username'])) {
-                throw new Exception('Missing or invalid username option in config.');
-            }
-            $this->username = $config['username'];
-            if (!is_string($config['password'])) {
-                throw new Exception('Missing or invalid password option in config.');
-            }
-            $this->password = $config['password'];
-        }
-
-        protected function login($username, $password) {
-            if ($username !== $this->username || $password !== $this->password) {
-                throw new \SimpleSAML\Error\Error('WRONGUSERPASS');
-            }
-            return [
-                'uid' => [$this->username],
-                'displayName' => ['Some Random User'],
-                'eduPersonAffiliation' => ['member', 'employee'],
-            ];
+    protected function login($username, $password)
+    {
+        if ($username !== $this->username || $password !== $this->password) {
+            throw new \SimpleSAML\Error\Error('WRONGUSERPASS');
         }
 
+        return [
+            'uid' => [$this->username],
+            'displayName' => ['Some Random User'],
+            'eduPersonAffiliation' => ['member', 'employee'],
+        ];
     }
+}
+```
 
 We can then update our entry in `config/authsources.php` with the configuration options:
 
-    'myauthinstance' => [
-        'mymodule:MyAuth',
-        'username' => 'theconfigusername',
-        'password' => 'theconfigpassword',
-    ],
+```php
+'myauthinstance' => [
+    'mymodule:MyAuth',
+    'username' => 'theconfigusername',
+    'password' => 'theconfigpassword',
+],
+```
 
 Next, you should go to the "Test configured authentication sources" page again, and test logging in.
 Note that we have updated the username & password to "theconfigusername" and "theconfigpassword".
 (You may need to log out first before you can log in again.)
 
-
 A more complete example - custom database authentication
 --------------------------------------------------------
 
@@ -216,138 +241,152 @@ What follows is an example of an authentication source that fetches an user from
 
 This code assumes that the database contains a table that looks like this:
 
-    CREATE TABLE userdb (
-        username VARCHAR(32) PRIMARY KEY NOT NULL,
-        password_hash VARCHAR(64) NOT NULL,
-        full_name TEXT NOT NULL);
+```sql
+CREATE TABLE userdb (
+    username VARCHAR(32) PRIMARY KEY NOT NULL,
+    password_hash VARCHAR(64) NOT NULL,
+    full_name TEXT NOT NULL);
+```
 
 An example user (with password "secret"):
 
-    INSERT INTO userdb (username, password_hash, full_name)
-        VALUES('exampleuser', 'QwVYkvlrAMsXIgULyQ/pDDwDI3dF2aJD4XeVxg==', 'Example User');
+```sql
+INSERT INTO userdb (username, password_hash, full_name)
+    VALUES('exampleuser', 'QwVYkvlrAMsXIgULyQ/pDDwDI3dF2aJD4XeVxg==', 'Example User');
+```
 
 In this example, the `password_hash` contains a base64 encoded SSHA password.
 A SSHA password is created like this:
 
-    $password = 'secret';
-    $numSalt = 8; /* Number of bytes with salt. */
-    $salt = '';
-    for ($i = 0; $i < $numSalt; $i++) {
-        $salt .= chr(mt_rand(0, 255));
-    }
-    $digest = sha1($password . $salt, TRUE);
-    $password_hash = base64_encode($digest . $salt);
+```php
+$password = 'secret';
+$numSalt = 8; /* Number of bytes with salt. */
+$salt = '';
+for ($i = 0; $i < $numSalt; $i++) {
+    $salt .= chr(mt_rand(0, 255));
+}
+$digest = sha1($password . $salt, true);
+$password_hash = base64_encode($digest . $salt);
+```
 
 The class follows:
 
-    <?php
-    class MyAuth extends \SimpleSAML\Module\core\Auth\UserPassBase {
+```php
+<?php
 
-        /* The database DSN.
-         * See the documentation for the various database drivers for information about the syntax:
-         *     http://www.php.net/manual/en/pdo.drivers.php
-         */
-        private $dsn;
+class MyAuth extends \SimpleSAML\Module\core\Auth\UserPassBase
+{
+    /* The database DSN.
+     * See the documentation for the various database drivers for information about the syntax:
+     *     http://www.php.net/manual/en/pdo.drivers.php
+     */
+    private $dsn;
 
-        /* The database username, password & options. */
-        private $username;
-        private $password;
-        private $options;
+    /* The database username, password & options. */
+    private $username;
+    private $password;
+    private $options;
 
-        public function __construct($info, $config) {
-            parent::__construct($info, $config);
+    public function __construct($info, $config)
+    {
+        parent::__construct($info, $config);
 
-            if (!is_string($config['dsn'])) {
-                throw new Exception('Missing or invalid dsn option in config.');
-            }
-            $this->dsn = $config['dsn'];
-            if (!is_string($config['username'])) {
-                throw new Exception('Missing or invalid username option in config.');
-            }
-            $this->username = $config['username'];
-            if (!is_string($config['password'])) {
-                throw new Exception('Missing or invalid password option in config.');
-            }
-            $this->password = $config['password'];
-            if (isset($config['options']) {
-                if (!is_array($config['options'])) {
-                    throw new Exception('Missing or invalid options option in config.');
-                }
-                $this->options = $config['options'];
-            }
+        if (!is_string($config['dsn'])) {
+            throw new Exception('Missing or invalid dsn option in config.');
         }
+        $this->dsn = $config['dsn'];
 
-        /**
-         * A helper function for validating a password hash.
-         *
-         * In this example we check a SSHA-password, where the database
-         * contains a base64 encoded byte string, where the first 20 bytes
-         * from the byte string is the SHA1 sum, and the remaining bytes is
-         * the salt.
-         */
-        private function checkPassword($passwordHash, $password) {
-            $passwordHash = base64_decode($passwordHash);
-            $digest = substr($passwordHash, 0, 20);
-            $salt = substr($passwordHash, 20);
-
-            $checkDigest = sha1($password . $salt, TRUE);
-            return $digest === $checkDigest;
+        if (!is_string($config['username'])) {
+            throw new Exception('Missing or invalid username option in config.');
         }
+        $this->username = $config['username'];
 
-        protected function login($username, $password) {
+        if (!is_string($config['password'])) {
+            throw new Exception('Missing or invalid password option in config.');
+        }
+        $this->password = $config['password'];
 
-            /* Connect to the database. */
-            $db = new PDO($this->dsn, $this->username, $this->password, $this->options);
-            $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+        if (isset($config['options']) {
+            if (!is_array($config['options'])) {
+                throw new Exception('Missing or invalid options option in config.');
+            }
+            $this->options = $config['options'];
+        }
+    }
 
-            /* Ensure that we are operating with UTF-8 encoding.
-             * This command is for MySQL. Other databases may need different commands.
-             */
-            $db->exec("SET NAMES 'utf8'");
+    /**
+     * A helper function for validating a password hash.
+     *
+     * In this example we check a SSHA-password, where the database
+     * contains a base64 encoded byte string, where the first 20 bytes
+     * from the byte string is the SHA1 sum, and the remaining bytes is
+     * the salt.
+     */
+    private function checkPassword($passwordHash, $password)
+    {
+        $passwordHash = base64_decode($passwordHash);
+        $digest = substr($passwordHash, 0, 20);
+        $salt = substr($passwordHash, 20);
+
+        $checkDigest = sha1($password . $salt, true);
+        return $digest === $checkDigest;
+    }
 
-            /* With PDO we use prepared statements. This saves us from having to escape
-             * the username in the database query.
-             */
-            $st = $db->prepare('SELECT username, password_hash, full_name FROM userdb WHERE username=:username');
+    protected function login($username, $password)
+    {
+        /* Connect to the database. */
+        $db = new PDO($this->dsn, $this->username, $this->password, $this->options);
+        $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
 
-            if (!$st->execute(['username' => $username])) {
-                throw new Exception('Failed to query database for user.');
-            }
+        /* Ensure that we are operating with UTF-8 encoding.
+         * This command is for MySQL. Other databases may need different commands.
+         */
+        $db->exec("SET NAMES 'utf8'");
 
-            /* Retrieve the row from the database. */
-            $row = $st->fetch(PDO::FETCH_ASSOC);
-            if (!$row) {
-                /* User not found. */
-                SimpleSAML\Logger::warning('MyAuth: Could not find user ' . var_export($username, TRUE) . '.');
-                throw new \SimpleSAML\Error\Error('WRONGUSERPASS');
-            }
+        /* With PDO we use prepared statements. This saves us from having to escape
+         * the username in the database query.
+         */
+        $st = $db->prepare('SELECT username, password_hash, full_name FROM userdb WHERE username=:username');
 
-            /* Check the password. */
-            if (!$this->checkPassword($row['password_hash'], $password)) {
-                /* Invalid password. */
-                SimpleSAML\Logger::warning('MyAuth: Wrong password for user ' . var_export($username, TRUE) . '.');
-                throw new \SimpleSAML\Error\Error('WRONGUSERPASS');
-            }
+        if (!$st->execute(['username' => $username])) {
+            throw new Exception('Failed to query database for user.');
+        }
 
-            /* Create the attribute array of the user. */
-            $attributes = [
-                'uid' => [$username],
-                'displayName' => [$row['full_name']],
-                'eduPersonAffiliation' => ['member', 'employee'],
-            ];
+        /* Retrieve the row from the database. */
+        $row = $st->fetch(PDO::FETCH_ASSOC);
+        if (!$row) {
+            /* User not found. */
+            SimpleSAML\Logger::warning('MyAuth: Could not find user ' . var_export($username, true) . '.');
+            throw new \SimpleSAML\Error\Error('WRONGUSERPASS');
+        }
 
-            /* Return the attributes. */
-            return $attributes;
+        /* Check the password. */
+        if (!$this->checkPassword($row['password_hash'], $password)) {
+            /* Invalid password. */
+            SimpleSAML\Logger::warning('MyAuth: Wrong password for user ' . var_export($username, true) . '.');
+            throw new \SimpleSAML\Error\Error('WRONGUSERPASS');
         }
 
+        /* Create the attribute array of the user. */
+        $attributes = [
+            'uid' => [$username],
+            'displayName' => [$row['full_name']],
+            'eduPersonAffiliation' => ['member', 'employee'],
+        ];
+
+        /* Return the attributes. */
+        return $attributes;
     }
+}
+```
 
 And configured in `config/authsources.php`:
 
-    'myauthinstance' => [
-        'mymodule:MyAuth',
-        'dsn' => 'mysql:host=sql.example.org;dbname=userdatabase',
-        'username' => 'db_username',
-        'password' => 'secret_db_password',
-    ],
-
+```php
+'myauthinstance' => [
+    'mymodule:MyAuth',
+    'dsn' => 'mysql:host=sql.example.org;dbname=userdatabase',
+    'username' => 'db_username',
+    'password' => 'secret_db_password',
+],
+```
diff --git a/docs/simplesamlphp-database.md b/docs/simplesamlphp-database.md
index d92fab45d9d8da8021c28a74a9f11dcc9e1ecc25..e72158faef80eaf08f2e65f8c933e449ecd68a62 100644
--- a/docs/simplesamlphp-database.md
+++ b/docs/simplesamlphp-database.md
@@ -1,91 +1,101 @@
-SimpleSAML\Database
-=============================
-
-<!-- 
-	This file is written in Markdown syntax. 
-	For more information about how to use the Markdown syntax, read here:
-	http://daringfireball.net/projects/markdown/syntax
--->
-
+# SimpleSAML\Database
 
 [TOC]
 
-Purpose
--------
+## Purpose
+
 This document covers the SimpleSAML\Database class and is only relevant to anyone writing code for SimpleSAMLphp, including modules, that require a database connection.
 
 The Database class provides a single class that can be used to connect to a database which can be shared by anything within SimpleSAMLphp.
 
-Getting Started
----------------
+## Getting Started
+
 If you are just using the already configured database, which would normally be the case, all you need to do is get the global instance of the Database class.
 
-	$db = \SimpleSAML\Database::getInstance();
+```php
+$db = \SimpleSAML\Database::getInstance();
+```
 
 If there is a requirement to connect to an alternate database server (ex. authenticating users that exist on a different SQL server or database) you can specify an alternate configuration.
 
-	$config = new \SimpleSAML\Configuration($myconfigarray, "mymodule/lib/Auth/Source/myauth.php");
-	$db = \SimpleSAML\Database::getInstance($config);
+```php
+$config = new \SimpleSAML\Configuration($myconfigarray, "mymodule/lib/Auth/Source/myauth.php");
+$db = \SimpleSAML\Database::getInstance($config);
+```
 
 That will create a new instance of the database, separate from the global instance, specific to the configuration defined in $myconfigarray. If you are going to specify an alternate config, your configuration array must contain the same keys that exist in the primary config (database.dsn, database.username, database.password, database.prefix, etc).
 
-Database Prefix
----------------
+## Database Prefix
+
 Administrators can add a prefix to all the table names that this database classes accesses and you should take that in account when querying. Assuming that a prefix has been configured as "sp_":
 
-	$table = $db->applyPrefix("saml20_idp_hosted");
+```php
+$table = $db->applyPrefix("saml20_idp_hosted");
+```
 
 $table would be set to "sp_saml20_idp_hosted"
 
-Querying The Database
----------------------
+## Querying The Database
+
 You can query the database through two public functions read() and write() which are fairly self-explanitory when it comes to determining which one to use when querying.
 
 ### Writing to The Database
+
 Since the database class allows administrators to configure primary and secondary database servers, the write function will always use the primary database connection.
 
 The write function takes 2 parameters: SQL, params.
 
-	$table = $db->applyPrefix("test");
-	$values = [
-		'id' => 20,
-		'data' => 'Some data',
-	];
-	
-	$query = $db->write("INSERT INTO $table (id, data) VALUES (:id, :data)", $values);
+```php
+$table = $db->applyPrefix("test");
+$values = [
+    'id' => 20,
+    'data' => 'Some data',
+];
+
+$query = $db->write("INSERT INTO $table (id, data) VALUES (:id, :data)", $values);
+```
 
 The values specified in the $values array will be bound to the placeholders and will be executed on the primary. By default, values are binded as PDO::PARAM_STR. If you need to override this, you can specify it in the values array.
 
-	$table = $db->applyPrefix("test");
-	$values = [
-		'id' => [20, PDO::PARAM_INT],
-		'data' => 'Some data',
-	];
-	
-	$query = $db->write("INSERT INTO $table (id, data) VALUES (:id, :data)", $values);
+```php
+$table = $db->applyPrefix("test");
+$values = [
+    'id' => [20, PDO::PARAM_INT],
+    'data' => 'Some data',
+];
+
+$query = $db->write("INSERT INTO $table (id, data) VALUES (:id, :data)", $values);
+```
 
 You can also skip usage of prepared statements. You should **only** use this if you have a statement that has no user input (ex. CREATE TABLE). If the params variable is explicitly set to false, it will skip usage of prepared statements. This is only available when writing to the database.
 
-	$table = $db->applyPrefix("test");
-	$query = $db->write("CREATE TABLE IF NOT EXISTS $table (id INT(16) NOT NULL, data TEXT NOT NULL)", false);
+```php
+$table = $db->applyPrefix("test");
+$query = $db->write("CREATE TABLE IF NOT EXISTS $table (id INT(16) NOT NULL, data TEXT NOT NULL)", false);
+```
 
 ### Reading The Database
+
 Since the database class allows administrators to configure primary and secondary database servers, the read function will randomly select a secondary server to query. If no secondaries are configured, it will read from the primary.
 
 The read function takes 2 parameters: SQL, params.
 
-	$table = $db->applyPrefix("test");
-	$values = [
-		'id' => 20,
-	];
-	
-	$query = $db->read("SELECT * FROM $table WHERE id = :id", $values);
+```php
+$table = $db->applyPrefix("test");
+$values = [
+    'id' => 20,
+];
+
+$query = $db->read("SELECT * FROM $table WHERE id = :id", $values);
+```
 
 The values specified in the $values array will be bound to the placeholders and will be executed on the selected secondary. By default, values are binded as PDO::PARAM_STR. If you need to override this, you can specify it in the values array.
 
-	$table = $db->applyPrefix("test");
-	$values = [
-		'id' => [20, PDO::PARAM_INT],
-	];
-	
-	$query = $db->read("SELECT * FROM $table WHERE id = :id", $values);
+```php
+$table = $db->applyPrefix("test");
+$values = [
+    'id' => [20, PDO::PARAM_INT],
+];
+
+$query = $db->read("SELECT * FROM $table WHERE id = :id", $values);
+```
diff --git a/docs/simplesamlphp-ecp-idp.md b/docs/simplesamlphp-ecp-idp.md
index 54e291971ad613e7b996967a04343f9f4170f5dc..e541c0056e5d9e8863c52e449283573a335d7378 100644
--- a/docs/simplesamlphp-ecp-idp.md
+++ b/docs/simplesamlphp-ecp-idp.md
@@ -1,12 +1,11 @@
-Adding Enhanced Client or Proxy (ECP) Profile support to the IdP
-===============================================================
+# Adding Enhanced Client or Proxy (ECP) Profile support to the IdP
 
 This document describes the necessary steps to enable support for the [SAML V2.0 Enhanced Client or Proxy Profile Version 2.0](http://docs.oasis-open.org/security/saml/Post2.0/saml-ecp/v2.0/cs01/saml-ecp-v2.0-cs01.pdf) on a simpleSAMLphp Identity Provider (IdP).
 
 The SAML V2.0 Enhanced Client or Proxy (ECP) profile is a SSO profile for use with HTTP, and clients with the capability to directly contact a principal's identity provider(s) without requiring discovery and redirection by the service provider, as in the case of a browser. It is particularly useful for desktop or server-side HTTP clients.
 
-Limitations
------------
+## Limitations
+
 * Authentication must be done via [HTTP Basic authentication](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication#Basic_authentication_scheme).
 * Authentication must not require user interaction (e.g. auth filters that require user input).
 * Channel Bindings are unsupported.
@@ -14,61 +13,57 @@ Limitations
 
 This feature has been tested to work with Microsoft Office 365, but other service providers may require features of the ECP profile that are currently unsupported!
 
-Enabling ECP Profile on the IdP
------------------------------------
+## Enabling ECP Profile on the IdP
 
 To enable the IdP to send ECP assertions you must add the `saml20.ecp` option to the `saml20-idp-hosted` metadata file:
 
-    $metadata['https://example.org/saml-idp'] = [
-        [....]
-        'auth' => 'example-userpass',
-        'saml20.ecp' => true,
-    ];
+```php
+$metadata['https://example.org/saml-idp'] = [
+    [....]
+    'auth' => 'example-userpass',
+    'saml20.ecp' => true,
+];
+```
 
 Note: authentication filters that require interaction with the user will not work with ECP.
 
-Add new metadata to SPs
------------------------
+## Add new metadata to SPs
 
 After enabling the ECP Profile your IdP metadata will change. An additional ECP `SingleSignOnService` endpoint is added.
 You therefore need to update the metadata for your IdP at your SPs.
 The `saml20-idp-remote` metadata for simpleSAMLphp SPs should contain something like the following code:
 
-	'SingleSignOnService' =>
-	  array (
-	    0 =>
-	    array (
-	      'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
-	      'Location' => 'https://idp.example.org/simplesaml/saml2/idp/SSOService.php',
-	    ),
-	    1 =>
-	    array (
-	      'index' => 0,
-	      'Location' => 'https://didp.example.org/simplesaml/saml2/idp/SSOService.php',
-	      'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:SOAP',
-	    ),
-	  ),
+```php
+'SingleSignOnService' => [
+    0 => [
+        'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
+        'Location' => 'https://idp.example.org/simplesaml/saml2/idp/SSOService.php',
+    ],
+    1 => [
+        'index' => 0,
+        'Location' => 'https://didp.example.org/simplesaml/saml2/idp/SSOService.php',
+        'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:SOAP',
+    ],
+],
+```
 
-SP metadata on the IdP
-----------------------
+## SP metadata on the IdP
 
 A SP using the ECP Profile must have an `AssertionConsumerService` endpoint supporting that profile.
 This means that you have to use the complex endpoint format in `saml20-sp-remote` metadata.
 In general, this should look like the following code:
 
-	'AssertionConsumerService' =>
-	  array (
-	    0 =>
-	    array (
-	      'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
-	      'Location' => 'https://sp.example.org/Shibboleth.sso/SAML2/POST',
-	      'index' => 1,
-	    ),
-	    1 =>
-	    array (
-	      'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:PAOS',
-	      'Location' => 'https://sp.example.org/ECP',
-	      'index' => 2,
-	    ),
-	  ),
-
+```php
+'AssertionConsumerService' => [
+    0 => [
+      'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
+      'Location' => 'https://sp.example.org/Shibboleth.sso/SAML2/POST',
+      'index' => 1,
+    ],
+    1 => [
+      'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:PAOS',
+      'Location' => 'https://sp.example.org/ECP',
+      'index' => 2,
+    ],
+],
+```
diff --git a/docs/simplesamlphp-errorhandling.md b/docs/simplesamlphp-errorhandling.md
index 2631b69ed67a8a7e397e1be94bc681d8a9120f59..b3a4c32f918066597f397a5b12b2df7467a45461 100644
--- a/docs/simplesamlphp-errorhandling.md
+++ b/docs/simplesamlphp-errorhandling.md
@@ -1,5 +1,4 @@
-Exception and error handling in SimpleSAMLphp
-=============================================
+# Exception and error handling in SimpleSAMLphp
 
 [TOC]
 
@@ -10,35 +9,39 @@ This means that internal SimpleSAMLphp exceptions must be mapped to transport sp
 E.g.: When a `\SAML2\Exception\Protocol\NoPassiveException` error is thrown by an authentication processing filter in a SAML 2.0 IdP, we want to map that exception to the `urn:oasis:names:tc:SAML:2.0:status:NoPassive` status code.
 That status code should then be returned to the SP.
 
-
-Throwing exceptions
--------------------
+## Throwing exceptions
 
 How you throw an exception depends on where you want to throw it from.
 The simplest case is if you want to throw it during the `authenticate()`-method in an authentication module or during the `process()`-method in a processing filter.
 In those methods, you can just throw an exception:
 
-    public function process(array &$state): void
-    {
-        if ($state['something'] === false) {
-            throw new \SimpleSAML\Error\Exception('Something is wrong...');
-        }
+```php
+public function process(array &$state): void
+{
+    if ($state['something'] === false) {
+        throw new \SimpleSAML\Error\Exception('Something is wrong...');
     }
+}
+```
 
 Exceptions thrown at this stage will be caught and delivered to the appropriate error handler.
 
 If you want to throw an exception outside of those methods, i.e. after you have done a redirect, you need to use the `\SimpleSAML\Auth\State::throwException()` function:
 
-    <?php
-    $id = $_REQUEST['StateId'];
-    $state = \SimpleSAML\Auth\State::loadState($id, 'somestage...');
-    \SimpleSAML\Auth\State::throwException($state,
-        new \SimpleSAML\Error\Exception('Something is wrong...'));
+```php
+<?php
 
-The `\SimpleSAML\Auth\State::throwException` function will then transfer your exception to the appropriate error handler.
+$id = $_REQUEST['StateId'];
+$state = \SimpleSAML\Auth\State::loadState($id, 'somestage...');
+\SimpleSAML\Auth\State::throwException(
+    $state,
+    new \SimpleSAML\Error\Exception('Something is wrong...')
+);
+```
 
+The `\SimpleSAML\Auth\State::throwException` function will then transfer your exception to the appropriate error handler.
 
-### Note
+`Note`
 
 Note that we use the `\SimpleSAML\Error\Exception` class in both cases.
 This is because the delivery of the exception may require a redirect to a different web page.
@@ -48,9 +51,7 @@ The normal `Exception` class in PHP isn't always serializable.
 If you throw an exception that isn't a subclass of the `\SimpleSAML\Error\Exception` class, your exception will be converted to an instance of `\SimpleSAML\Error\UnserializableException`.
 The `\SimpleSAML\Auth\State::throwException` function does not accept any exceptions that does not subclass the `\SimpleSAML\Error\Exception` class.
 
-
-Returning specific SAML 2 errors
---------------------------------
+## Returning specific SAML 2 errors
 
 By default, all thrown exceptions will be converted to a generic SAML 2 error.
 In some cases, you may want to convert the exception to a specific SAML 2 status code.
@@ -75,15 +76,12 @@ To return a specific SAML 2 error, you should:
 * Add that exception to the list in `fromException()`.
 * Consider adding the exception to `toException()` in the same file. (See the next section.)
 
-
-### Note
+`Note`
 
 While it is possible to throw SAML 2 errors directly from within authentication sources and processing filters, this practice is discouraged.
 Throwing SAML 2 errors will tie your code directly to the SAML 2 protocol, and it may be more difficult to use with other protocols.
 
-
-Converting SAML 2 errors to normal exceptions
----------------------------------------------
+## Converting SAML 2 errors to normal exceptions
 
 On the SP side, we want to convert SAML 2 errors to SimpleSAMLphp exceptions again.
 This is handled by the `toException()` method in `\SimpleSAML\Module\saml\Error`.
@@ -92,20 +90,15 @@ The result is that generic exceptions are thrown from that authentication source
 
 For example, `NoPassive` errors will be converted back to instances of `\SAML2\Exception\Protocol\NoPassiveException`.
 
-
-Other protocols
----------------
+## Other protocols
 
 The error handling code has not yet been added to other protocols, but the framework should be easy to adapt for other protocols.
 To eventually support other protocols was a goal when designing this framework.
 
-
-Technical details
------------------------
+## Technical details
 
 This section attempts to describe the internals of the error handling framework.
 
-
 ### `\SimpleSAML\Error\Exception`
 
 The `\SimpleSAML\Error\Exception` class extends the normal PHP `Exception` class.
@@ -121,14 +114,12 @@ Since preserving the stack trace can be useful for debugging, we save a variant
 This variable can be accessed through the `getBacktrace()` method.
 It returns an array with one line of text for each function call in the stack, ending on the point where the exception was created.
 
-
 #### Note
 
 Since we lose the original `$trace` variable during serialization, PHP will fill it with a new stack trace when the exception is unserialized.
 This may be confusing since the new stack trace leads into the `unserialize()` function.
 It is therefore recommended to use the getBacktrace() method.
 
-
 ### `\SimpleSAML\Auth\State`
 
 There are two methods in this class that deals with exceptions:
@@ -136,7 +127,6 @@ There are two methods in this class that deals with exceptions:
 * `throwException($state, $exception)`, which throws an exception.
 * `loadExceptionState($id)`, which restores a state containing an exception.
 
-
 #### `throwException`
 
 This method delivers the exception to the code that initialized the exception handling in the authentication state.
@@ -151,20 +141,20 @@ If the exception is delivered by a function call, the function will be called wi
 If the exception is delivered by a redirect, \SimpleSAML\Auth\State will save the exception in a field in the state array, pass a parameter with the id of the state array to the URL.
 The `\SimpleSAML\Auth\State::EXCEPTION_PARAM` constant contains the name of that parameter, while the `\SimpleSAML\Auth\State::EXCEPTION_DATA` constant holds the name of the field where the exception is saved.
 
-
 #### `loadException`
 
 To retrieve the exception, the application should check for the state parameter in the request, and then retrieve the state array by calling `\SimpleSAML\Auth\State::loadExceptionState()`.
 The exception can be located in a field named `\SimpleSAML\Auth\State::EXCEPTION_DATA`.
 The following code illustrates this behaviour:
 
-    if (array_key_exists(\SimpleSAML\Auth\State::EXCEPTION_PARAM, $_REQUEST)) {
-        $state = \SimpleSAML\Auth\State::loadExceptionState();
-        $exception = $state[\SimpleSAML\Auth\State::EXCEPTION_DATA];
-
-        /* Process exception. */
-    }
+```php
+if (array_key_exists(\SimpleSAML\Auth\State::EXCEPTION_PARAM, $_REQUEST)) {
+    $state = \SimpleSAML\Auth\State::loadExceptionState();
+    $exception = $state[\SimpleSAML\Auth\State::EXCEPTION_DATA];
 
+    /* Process exception. */
+}
+```
 
 ### `\SimpleSAML\Auth\ProcessingChain`
 
@@ -177,29 +167,29 @@ The result will be delivered directly if it is possible, but if not, it will be
 
 The code for handling this becomes something like:
 
-    if (array_key_exists(\SimpleSAML\Auth\State::EXCEPTION_PARAM, $_REQUEST)) {
-        $state = \SimpleSAML\Auth\State::loadExceptionState();
-        $exception = $state[\SimpleSAML\Auth\State::EXCEPTION_DATA];
-
-        /* Handle exception... */
-        [...]
-    }
+```php
+if (array_key_exists(\SimpleSAML\Auth\State::EXCEPTION_PARAM, $_REQUEST)) {
+    $state = \SimpleSAML\Auth\State::loadExceptionState();
+    $exception = $state[\SimpleSAML\Auth\State::EXCEPTION_DATA];
 
-    $procChain = [...];
+    /* Handle exception... */
+    [...]
+}
 
-    $state = [
-        'ReturnURL' => \SimpleSAML\Utils\HTTP::getSelfURLNoQuery(),
-        \SimpleSAML\Auth\State::EXCEPTION_HANDLER_URL => \SimpleSAML\Utils\HTTP::getSelfURLNoQuery(),
-        [...],
-    ]
+$procChain = [...];
 
-    try {
-        $procChain->processState($state);
-    } catch (\SimpleSAML\Error\Exception $e) {
-        /* Handle exception. */
-        [...];
-    }
+$state = [
+    'ReturnURL' => \SimpleSAML\Utils\HTTP::getSelfURLNoQuery(),
+    \SimpleSAML\Auth\State::EXCEPTION_HANDLER_URL => \SimpleSAML\Utils\HTTP::getSelfURLNoQuery(),
+    [...],
+]
 
+try {
+    $procChain->processState($state);
+} catch (\SimpleSAML\Error\Exception $e) {
+    /* Handle exception. */
+    [...];
+}
 
 #### Note
 
@@ -207,19 +197,18 @@ An exception which isn't a subclass of `\SimpleSAML\Error\Exception` will be con
 This happens regardless of whether the exception is delivered directly or through the error handler.
 This is done to be consistent in what the application receives - now it will always receive the same exception, regardless of whether it is delivered directly or through a redirect.
 
-
-Custom error show function
---------------------------
+## Custom error show function
 
 Optional custom error show function, called from \SimpleSAML\Error\Error::show, is defined with 'errors.show_function' in config.php.
 
 Example code for this function, which implements the same functionality as \SimpleSAML\Error\Error::show, looks something like:
 
-    public static function show(\SimpleSAML\Configuration $config, array $data)
-    {
-        $t = new \SimpleSAML\XHTML\Template($config, 'error.twig', 'errors');
-        $t->data = array_merge($t->data, $data);
-        $t->send();
-        exit;
-    }
-
+```php
+public static function show(\SimpleSAML\Configuration $config, array $data)
+{
+    $t = new \SimpleSAML\XHTML\Template($config, 'error.twig', 'errors');
+    $t->data = array_merge($t->data, $data);
+    $t->send();
+    exit;
+}
+```
diff --git a/docs/simplesamlphp-googleapps.md b/docs/simplesamlphp-googleapps.md
index b267e9db0c065f26ec6e41aa95d0971b7119b8d3..fcff46b9ac8a8ed22c565efac06929c25fba786f 100644
--- a/docs/simplesamlphp-googleapps.md
+++ b/docs/simplesamlphp-googleapps.md
@@ -1,16 +1,13 @@
-Setting up a SimpleSAMLphp SAML 2.0 IdP to use with Google Workspace (G Suite / Google Apps) for Education
-============================================
+# Setting up a SimpleSAMLphp SAML 2.0 IdP to use with Google Workspace (G Suite / Google Apps) for Education
 
 [TOC]
 
-SimpleSAMLphp news and documentation
-------------------------------------
+## SimpleSAMLphp news and documentation
 
 This document is part of the SimpleSAMLphp documentation suite.
 
- * [List of all SimpleSAMLphp documentation](https://simplesamlphp.org/docs)
- * [SimpleSAMLphp homepage](https://simplesamlphp.org)
-
+* [List of all SimpleSAMLphp documentation](https://simplesamlphp.org/docs)
+* [SimpleSAMLphp homepage](https://simplesamlphp.org)
 
 ## Introduction
 
@@ -20,44 +17,46 @@ This article assumes that you have already read the SimpleSAMLphp installation m
 a version of SimpleSAMLphp at your server.
 
 In this example we will setup this server as an IdP for Google Workspace:
-	dev2.andreas.feide.no
 
+dev2.andreas.feide.no
 
 ## Enabling the Identity Provider functionality
 
 Edit `config.php`, and enable the SAML 2.0 IdP:
 
-    'enable.saml20-idp' => true,
+```php
+'enable.saml20-idp' => true,
+```
 
 ## Setting up a signing certificate
 
 You must generate a certificate for your IdP.
 Here is an example of an openssl command to generate a new key and a self signed certificate to use for signing SAML messages:
 
-    openssl req -newkey rsa:3072 -new -x509 -days 3652 -nodes -out googleworkspaceidp.crt -keyout googleworkspaceidp.pem
+```bash
+openssl req -newkey rsa:3072 -new -x509 -days 3652 -nodes -out googleworkspaceidp.crt -keyout googleworkspaceidp.pem
+```
 
 The certificate above will be valid for 10 years.
 
 Here is an example of typical user input when creating a certificate request:
 
-    Country Name (2 letter code) [AU]:NO
-    State or Province Name (full name) [Some-State]:Trondheim
-    Locality Name (eg, city) []:Trondheim
-    Organization Name (eg, company) [Internet Widgits Pty Ltd]:UNINETT
-    Organizational Unit Name (eg, section) []:
-    Common Name (eg, YOUR name) []:dev2.andreas.feide.no
-    Email Address []:
-    
-    Please enter the following 'extra' attributes
-    to be sent with your certificate request
-    A challenge password []:
-    An optional company name []:
+Country Name (2 letter code) [AU]:NO
+State or Province Name (full name) [Some-State]:Trondheim
+Locality Name (eg, city) []:Trondheim
+Organization Name (eg, company) [Internet Widgits Pty Ltd]:UNINETT
+Organizational Unit Name (eg, section) []:
+Common Name (eg, YOUR name) []:dev2.andreas.feide.no
+Email Address []:
 
-**Note**: SimpleSAMLphp will only work with RSA and not DSA certificates.
+Please enter the following 'extra' attributes
+to be sent with your certificate request
+A challenge password []:
+An optional company name []:
 
+**Note**: SimpleSAMLphp will only work with RSA and not DSA certificates.
 
-Authentication source
----------------------
+## Authentication source
 
 The next step is to configure the way users authenticate on your IdP. Various modules in the `modules/` directory provides methods for authenticating your users. This is an overview of those that are included in the SimpleSAMLphp distribution:
 
@@ -72,52 +71,48 @@ The next step is to configure the way users authenticate on your IdP. Various mo
 
 For more authentication modules, see [SimpleSAMLphp Identity Provider QuickStart](simplesamlphp-idp).
 
-
 In this guide, we will use the `exampleauth:UserPass` authentication module. This module does not have any dependencies, and is therefore simple to set up.
 
 After you have successfully tested that everything is working with the simple `exampleauth:UserPass`, you are encouraged to setup SimpleSAMLphp IdP towards your user storage, such as an LDAP directory. (Use the links on the authentication sources above to read more about these setups. `ldap:LDAP` is the most common authentication source.)
 
-
-Configuring the authentication source
--------------------------------------
+## Configuring the authentication source
 
 The `exampleauth:UserPass` authentication module is part of the `exampleauth` module. This module isn't enabled by default, so you will have to enable it. In
 `config.php`, search for the `module.enable` key and set `exampleauth` to true:
 
-```
-    'module.enable' => [
-         'exampleauth' => true,
-         …
-    ],
+```php
+'module.enable' => [
+    'exampleauth' => true,
+    …
+],
 ```
 
 The next step is to create an authentication source with this module. An authentication source is an authentication module with a specific configuration. Each authentication source has a name, which is used to refer to this specific configuration in the IdP configuration. Configuration for authentication sources can be found in `config/authsources.php`.
 
 In this example we will use `example-userpass`, and hence that section is what matters and will be used.
 
-	<?php
-	$config = [
-		'example-userpass' => [
-			'exampleauth:UserPass',
-			'student:studentpass' => [
-				'uid' => ['student'],
-			],
-			'employee:employeepass' => [
-				'uid' => ['employee'],
-			],
-		],
-	];
-	?>
-
-This configuration creates two users - `student` and `employee`, with the passwords `studentpass` and `employeepass`. The username and password are stored in the array index `student:studentpass` for the `student`-user. The attributes (only `uid` in this example) will be returned by the IdP when the user logs on.
+```php
+<?php
 
+$config = [
+    'example-userpass' => [
+        'exampleauth:UserPass',
+        'student:studentpass' => [
+            'uid' => ['student'],
+        ],
+        'employee:employeepass' => [
+            'uid' => ['employee'],
+        ],
+    ],
+];
+```
 
+This configuration creates two users - `student` and `employee`, with the passwords `studentpass` and `employeepass`. The username and password are stored in the array index `student:studentpass` for the `student`-user. The attributes (only `uid` in this example) will be returned by the IdP when the user logs on.
 
 ## Configuring metadata for an SAML 2.0 IdP
 
 If you want to setup a SAML 2.0 IdP for Google Workspace, you need to configure two metadata files: `saml20-idp-hosted.php` and `saml20-sp-remote.php`.
 
-
 ### Configuring SAML 2.0 IdP Hosted metadata
 
 This is the configuration of the IdP itself. Here is some example config:
@@ -125,7 +120,6 @@ This is the configuration of the IdP itself. Here is some example config:
 ```php
 // The SAML entity ID is the index of this config.
 $metadata['https://example.org/saml-idp'] => [
-
     // The hostname of the server (VHOST) that this SAML entity will use.
     'host' => '__DEFAULT__',
 
@@ -137,31 +131,32 @@ $metadata['https://example.org/saml-idp'] => [
 ]
 ```
 
-**Note**: You can only have one entry in the file with host equal to `__DEFAULT__`, therefore you should replace the existing entry with this one, instead of adding this entry as a new entry in the file. 
-
+**Note**: You can only have one entry in the file with host equal to `__DEFAULT__`, therefore you should replace the existing entry with this one, instead of adding this entry as a new entry in the file.
 
 ### Configuring SAML 2.0 SP Remote metadata
 
 In the `saml20-sp-remote.php` file we will configure an entry for Google Workspace for Education. There is already an entry for Google Workspace in the template, but we will change the domain name:
 
-      /*
-       * This example shows an example config that works with Google Workspace (G Suite / Google Apps) for education.
-       * What is important is that you have an attribute in your IdP that maps to the local part of the email address
-       * at Google Workspace. E.g. if your google account is foo.com, and you have a user with email john@foo.com, then you
-       * must properly configure the saml:AttributeNameID authproc-filter with the name of an attribute that for this user has the value of 'john'.
-       */
-      $metadata['https://www.google.com/a/g.feide.no'] => [
-        'AssertionConsumerService'   => 'https://www.google.com/a/g.feide.no/acs', 
-        'NameIDFormat'               => 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress',
-        'simplesaml.attributes'      => false,
-        'authproc'                   => [
-          1 => [
-            'saml:AttributeNameID',
-            'attribute' => 'uid',
-            'format' => 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress',
-          ],
+```php
+/*
+ * This example shows an example config that works with Google Workspace (G Suite / Google Apps) for education.
+ * What is important is that you have an attribute in your IdP that maps to the local part of the email address
+ * at Google Workspace. E.g. if your google account is foo.com, and you have a user with email john@foo.com, then you
+ * must properly configure the saml:AttributeNameID authproc-filter with the name of an attribute that for this user has the value of 'john'.
+ */
+$metadata['https://www.google.com/a/g.feide.no'] => [
+    'AssertionConsumerService' => 'https://www.google.com/a/g.feide.no/acs', 
+    'NameIDFormat' => 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress',
+    'simplesaml.attributes' => false,
+    'authproc' => [
+        1 => [
+          'saml:AttributeNameID',
+          'attribute' => 'uid',
+          'format' => 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress',
         ],
-      ];
+    ],
+];
+```
 
 You must also map some attributes received from the authentication module into email field sent to Google Workspace. In this example, the  `uid` attribute is set.  When you later configure the IdP to connect to a LDAP directory or some other authentication source, make sure that the `uid` attribute is set properly, or you can configure another attribute to use here. The `uid` attribute contains the local part of the user name.
 
@@ -177,18 +172,18 @@ For an explanation of the parameters, see the
 Start by logging in to our Google Workspace for education account panel.
 Then select "Advanced tools":
 
-**Figure&nbsp;1.&nbsp;We go to advanced tools**
+Figure 1. **We go to advanced tools**
 
 ![We go to advanced tools](resources/simplesamlphp-googleapps/googleapps-menu.png)
 
 Then select "Set up single sign-on (SSO)":
 
-**Figure&nbsp;2.&nbsp;We go to setup SSO**
+Figure 2. **We go to setup SSO**
 
 ![We go to setup SSO](resources/simplesamlphp-googleapps/googleapps-sso.png)
 Upload a certificate, such as the googleworkspaceidp.crt created above:
 
-**Figure&nbsp;3.&nbsp;Uploading certificate**
+Figure 3. **Uploading certificate**
 
 ![Uploading certificate](resources/simplesamlphp-googleapps/googleapps-cert.png)
 Fill out the remaining fields:
@@ -201,13 +196,13 @@ You will find in the metadata the XML tag `<md:SingleSignOnService>`
 which contains the right URL to input in the field, it will look something
 like this:
 
-	https://dev2.andreas.feide.no/simplesaml/saml2/idp/SSOService.php
+`https://dev2.andreas.feide.no/simplesaml/saml2/idp/SSOService.php`
 
 You must also configure the IdP initiated Single LogOut endpoint of your server.
 You will find this in your metadata XML in the tag
 `<md:SingleLogoutService>`. It will look something like:
 
-	http://dev2.andreas.feide.no/simplesaml/saml2/idp/SingleLogoutService.php
+`http://dev2.andreas.feide.no/simplesaml/saml2/idp/SingleLogoutService.php`
 
 again, using the host name of your IdP server.
 
@@ -217,7 +212,7 @@ The network mask determines which IP addresses will be asked for SSO login.
 IP addresses not matching this mask will be presented with the normal Google Workspace login page.
 It is normally best to leave this field empty to enable authentication for all URLs.
 
-**Figure&nbsp;4.&nbsp;Fill out the remaining fields**
+Figure 4. **Fill out the remaining fields**
 
 ![Fill out the remaining fields](resources/simplesamlphp-googleapps/googleapps-ssoconfig.png)
 
@@ -229,7 +224,7 @@ Before we can test login, a new user must be defined in Google Workspace. This u
 
 Go to the URL of your mail account for this domain, the URL is similar to the following:
 
-	http://mail.google.com/a/yourgoogleappsdomain.com
+`http://mail.google.com/a/yourgoogleappsdomain.com`
 
 replacing the last part with your own Google Workspace domain name.
 
@@ -237,12 +232,10 @@ replacing the last part with your own Google Workspace domain name.
 
 Make sure that your IdP server runs HTTPS (TLS). The Apache documentation contains information for how to configure HTTPS.
 
-Support
--------
+## Support
 
 If you need help to make this work, or want to discuss SimpleSAMLphp with other users of the software, you are fortunate: Around SimpleSAMLphp there is a great Open source community, and you are welcome to join! The forums are open for you to ask questions, contribute answers other further questions, request improvements or contribute with code or plugins of your own.
 
--  [SimpleSAMLphp homepage](https://simplesamlphp.org)
--  [List of all available SimpleSAMLphp documentation](https://simplesamlphp.org/docs/)
--  [Join the SimpleSAMLphp user's mailing list](https://simplesamlphp.org/lists)
-
+* [SimpleSAMLphp homepage](https://simplesamlphp.org)
+* [List of all available SimpleSAMLphp documentation](https://simplesamlphp.org/docs/)
+* [Join the SimpleSAMLphp user's mailing list](https://simplesamlphp.org/lists)
diff --git a/docs/simplesamlphp-hok-idp.md b/docs/simplesamlphp-hok-idp.md
index ae055188405597feb0c07496368178b586f6c167..1b4908bdcab5600bc475926ca2c335202e72bdcc 100644
--- a/docs/simplesamlphp-hok-idp.md
+++ b/docs/simplesamlphp-hok-idp.md
@@ -1,5 +1,4 @@
-Adding Holder-of-Key Web Browser SSO Profile support to the IdP
-===============================================================
+# Adding Holder-of-Key Web Browser SSO Profile support to the IdP
 
 This document describes the necessary steps to enable support for the [SAML V2.0 Holder-of-Key (HoK) Web Browser SSO Profile](http://docs.oasis-open.org/security/saml/Post2.0/sstc-saml-holder-of-key-browser-sso.pdf)
 on a SimpleSAMLphp Identity Provider (IdP).
@@ -10,68 +9,72 @@ while preserving maximum compatibility with existing deployments on client and s
 When using this profile the communication between the user and the IdP is required to be protected by the TLS protocol. Additionally, the user needs a TLS client certificate.
 This certificate is usually selfsigned and stored in the certificate store of the browser or the underlying operating system.
 
-Configuring Apache
-------------------
+## Configuring Apache
 
 The IdP requests a client certificate from the user agent during the TLS handshake. This behaviour is enabled with the following Apache webserver configuration:
 
-    SSLEngine on
-    SSLCertificateFile /etc/openssl/certs/server.crt
-    SSLCertificateKeyFile /etc/openssl/private/server.key
-    SSLVerifyClient optional_no_ca
-    SSLOptions +ExportCertData
+```apacheconf
+SSLEngine on
+SSLCertificateFile /etc/openssl/certs/server.crt
+SSLCertificateKeyFile /etc/openssl/private/server.key
+SSLVerifyClient optional_no_ca
+SSLOptions +ExportCertData
+```
 
 If the user agent can successfully prove possession of the private key associated to the public key from the certificate, the received certificate is stored in the
 environment variable `SSL_CLIENT_CERT` of the webserver. The IdP embeds the client certificate into the created HoK assertion.
 
-Enabling HoK SSO Profile on the IdP
------------------------------------
+## Enabling HoK SSO Profile on the IdP
 
 To enable the IdP to send HoK assertions you must add the `saml20.hok.assertion` option to the `saml20-idp-hosted` metadata file:
 
-    $metadata['https://example.org/saml-idp'] = [
-        [....]
-        'auth' => 'example-userpass',
-        'saml20.hok.assertion' => TRUE,
-    ];
+```php
+$metadata['https://example.org/saml-idp'] = [
+    [....]
+    'auth' => 'example-userpass',
+    'saml20.hok.assertion' => true,
+];
+```
 
-Add new metadata to SPs
------------------------
+## Add new metadata to SPs
 
 After enabling the Holder-of-Key Web Browser SSO Profile your IdP metadata will change. An additional HoK `SingleSignOnService` endpoint is added.
 You therefore need to update the metadata for your IdP at your SPs.
 The `saml20-idp-remote` metadata for SimpleSAMLphp SPs should contain something like the following code:
 
-	'SingleSignOnService' => array (
-		array (
-			'hoksso:ProtocolBinding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
-			'Binding' => 'urn:oasis:names:tc:SAML:2.0:profiles:holder-of-key:SSO:browser',
-			'Location' => 'https://idp.example.org/simplesaml/saml2/idp/SSOService.php',
-		),
-		array (
-			'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
-			'Location' => 'https://idp.example.org/simplesaml/saml2/idp/SSOService.php',
-		),
-	),
-
-SP metadata on the IdP
-----------------------
+```php
+'SingleSignOnService' => [
+    [
+        'hoksso:ProtocolBinding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
+        'Binding' => 'urn:oasis:names:tc:SAML:2.0:profiles:holder-of-key:SSO:browser',
+        'Location' => 'https://idp.example.org/simplesaml/saml2/idp/SSOService.php',
+    ],
+    [
+        'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
+        'Location' => 'https://idp.example.org/simplesaml/saml2/idp/SSOService.php',
+    ],
+],
+```
+
+## SP metadata on the IdP
 
 A SP using the HoK Web Browser SSO Profile must have an `AssertionConsumerService` endpoint supporting that profile.
 This means that you have to use the complex endpoint format in `saml20-sp-remote` metadata.
 In general, this should look like the following code:
 
-	'AssertionConsumerService' => array (
-		[
-			'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
-			'Location' => 'https://sp.example.org/simplesaml/module.php/saml/sp/assertionConsumerService/default-sp',
-			'index' => 0,
-		],
-		[
-			'Binding' => 'urn:oasis:names:tc:SAML:2.0:profiles:holder-of-key:SSO:browser',
-			'Location' => 'https://sp.example.org/simplesaml/module.php/saml/sp/assertionConsumerService/default-sp',
-			'index' => 4,
-		],
-	),
+```php
+'AssertionConsumerService' => [
+    [
+        'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
+        'Location' => 'https://sp.example.org/simplesaml/module.php/saml/sp/assertionConsumerService/default-sp',
+        'index' => 0,
+    ],
+    [
+        'Binding' => 'urn:oasis:names:tc:SAML:2.0:profiles:holder-of-key:SSO:browser',
+        'Location' => 'https://sp.example.org/simplesaml/module.php/saml/sp/assertionConsumerService/default-sp',
+        'index' => 4,
+    ],
+],
+```
 
 (The specific values of the various fields will vary depending on the SP.)
diff --git a/docs/simplesamlphp-idp-more.md b/docs/simplesamlphp-idp-more.md
index eabaf95d58ab2b4b6c82a1a5bddde92b63ca20af..38f05e387b346c0c1c06e4b81e8be7919322949e 100644
--- a/docs/simplesamlphp-idp-more.md
+++ b/docs/simplesamlphp-idp-more.md
@@ -8,15 +8,15 @@ AJAX iFrame Single Log-Out
 
 If you have read about the AJAX iFrame Single Log-Out approach at Andreas' blog and want to enable it, edit your saml20-idp-hosted.php metadata, and add this configuration line for the IdP:
 
-	'logouttype' => 'iframe',
-
+```php
+'logouttype' => 'iframe',
+```
 
 Attribute Release Consent
 -------------------------
 
 The attribute release consent is documented in a [separate document](/docs/contrib_modules/consent/consent.html).
 
-
 Support for bookmarking the login page
 --------------------------------------
 
@@ -24,11 +24,10 @@ Most SAML software crash fatally when users bookmark the login page and return l
 
 SimpleSAMLphp has implemented a graceful fallback to tackle this situation. When SimpleSAMLphp is not able to lookup a session during the login process, it falls back to the *IdP-first flow*, described in the next section, where the reference to the request is not needed.
 
-What happens in the IdP-first flow is that a *SAML unsolicited response* is sent directly to the SP. An *unsolicited response* is a SAML Response with no reference to a SAML Request (no `InReplyTo` field). 
+What happens in the IdP-first flow is that a *SAML unsolicited response* is sent directly to the SP. An *unsolicited response* is a SAML Response with no reference to a SAML Request (no `InReplyTo` field).
 
 When a SimpleSAMLphp IdP falls back to IdP-first flow, the `RelayState` parameter sent by the SP in the SAML request is also lost. The RelayState information contain a reference key for the SP to lookup where to send the user after successful authentication. The SimpleSAMLphp Service Provider supports configuring a static URL to redirect the user after a unsolicited response is received. See more information about the `RelayState` parameter in the next section: *IdP-first flow*.
 
-
 IdP-first flow
 --------------
 
@@ -36,11 +35,11 @@ If you do not want to start the SSO flow at the SP, you may use the IdP-first se
 
 Here is an example of such a URL:
 
-	https://idp.example.org/simplesaml/saml2/idp/SSOService.php?spentityid=urn:mace:feide.no:someservice
+`https://idp.example.org/simplesaml/saml2/idp/SSOService.php?spentityid=urn:mace:feide.no:someservice`
 
 You can also add a `RelayState` parameter to the IdP-first URL:
 
-	https://idp.example.org/simplesaml/saml2/idp/SSOService.php?spentityid=urn:mace:feide.no:someservice&RelayState=https://sp.example.org/somepage
+`https://idp.example.org/simplesaml/saml2/idp/SSOService.php?spentityid=urn:mace:feide.no:someservice&RelayState=https://sp.example.org/somepage`
 
 The `RelayState` parameter is often used to carry the URL the SP should redirect to after authentication. It is also possible to specify the Assertion
 Consumer URL with the `ConsumerURL` parameter.
@@ -49,12 +48,11 @@ For compatibility with certain SPs, SimpleSAMLphp will also accept the
 `providerId`, `target` and `shire` parameters as aliases for `spentityid`,
 `RelayState` and `ConsumerURL`, respectively.
 
-
 IdP-initiated logout
 --------------------
 
 IdP-initiated logout can be initiated by visiting the URL:
 
-    https://idp.example.org/simplesaml/saml2/idp/SingleLogoutService.php?ReturnTo=<URL to return to after logout>
+`https://idp.example.org/simplesaml/saml2/idp/SingleLogoutService.php?ReturnTo=<URL to return to after logout>`
 
 It will send a logout request to each SP, and afterwards return the user to the URL specified in the `ReturnTo` parameter. Bear in mind that IdPs might disallow redirecting to URLs other than those of their own for security reasons, so in order to get the redirection to work, it might be necessary to ask the IdP to whitelist the URL we are planning to redirect to.
diff --git a/docs/simplesamlphp-idp.md b/docs/simplesamlphp-idp.md
index 97cdb5318d7ea77208a52c5bbe5861346563b05b..0a26891e11c1dad617a179866c04d27ae9c82fff 100644
--- a/docs/simplesamlphp-idp.md
+++ b/docs/simplesamlphp-idp.md
@@ -1,21 +1,18 @@
-SimpleSAMLphp Identity Provider QuickStart
-===========================================
+# SimpleSAMLphp Identity Provider QuickStart
 
 [TOC]
 
 This guide will describe how to configure SimpleSAMLphp as an identity provider (IdP). You should previously have installed SimpleSAMLphp as described in [the SimpleSAMLphp installation instructions](simplesamlphp-install)
 
-
-Enabling the Identity Provider functionality
---------------------------------------------
+## Enabling the Identity Provider functionality
 
 The first that must be done is to enable the identity provider functionality. This is done by editing `config/config.php`. The option `enable.saml20-idp` controls whether SAML 2.0 IdP support is enabled. Enable it by assigning `true` to them:
 
-    'enable.saml20-idp' => true,
-
+```php
+'enable.saml20-idp' => true,
+```
 
-Authentication module
----------------------
+## Authentication module
 
 The next step is to configure the way users authenticate on your IdP. Various modules in the `modules/` directory provides methods for authenticating your users. This is an overview of those that are included in the SimpleSAMLphp distribution:
 
@@ -64,155 +61,152 @@ The next step is to configure the way users authenticate on your IdP. Various mo
 
 In this guide, we will use the `exampleauth:UserPass` authentication module. This module does not have any dependencies, and is therefore simple to set up.
 
-
-Configuring the authentication module
--------------------------------------
+## Configuring the authentication module
 
 The `exampleauth:UserPass` authentication module is part of the `exampleauth` module. This module isn't enabled by default, so you will have to enable it. In
 `config.php`, search for the `module.enable` key and set `exampleauth` to true:
 
-```
-    'module.enable' => [
-         'exampleauth' => true,
-         …
-    ],
+```php
+'module.enable' => [
+    'exampleauth' => true,
+    …
+],
 ```
 
 The next step is to create an authentication source with this module. An authentication source is an authentication module with a specific configuration. Each authentication source has a name, which is used to refer to this specific configuration in the IdP configuration. Configuration for authentication sources can be found in `config/authsources.php`.
 
 In this setup, this file should contain a single entry:
 
-	<?php
-	$config = [
-		'example-userpass' => [
-			'exampleauth:UserPass',
-			'student:studentpass' => [
-				'uid' => ['student'],
-				'eduPersonAffiliation' => ['member', 'student'],
-			],
-			'employee:employeepass' => [
-				'uid' => ['employee'],
-				'eduPersonAffiliation' => ['member', 'employee'],
-			],
-		],
-	];
+```php
+<?php
+
+$config = [
+    'example-userpass' => [
+        'exampleauth:UserPass',
+        'student:studentpass' => [
+            'uid' => ['student'],
+            'eduPersonAffiliation' => ['member', 'student'],
+        ],
+        'employee:employeepass' => [
+            'uid' => ['employee'],
+            'eduPersonAffiliation' => ['member', 'employee'],
+        ],
+    ],
+];
+```
 
 This configuration creates two users - `student` and `employee`, with the passwords `studentpass` and `employeepass`. The username and password are stored in the array index (`student:studentpass` for the `student`-user). The attributes for each user are configured in the array referenced by the index. So for the student user, these are:
 
-	[
-		'uid' => ['student'],
-		'eduPersonAffiliation' => ['member', 'student'],
-	],
+```php
+[
+    'uid' => ['student'],
+    'eduPersonAffiliation' => ['member', 'student'],
+],
+```
 
 The attributes will be returned by the IdP when the user logs on.
 
-
-Creating a self signed certificate
-----------------------------------
+## Creating a self signed certificate
 
 The IdP needs a certificate to sign its SAML assertions with. Here is an example of an `openssl`-command which can be used to generate a new private key key and the corresponding self-signed certificate. The private key and certificate go into the directory defined in the certdir setting (defaults to `cert/`)
 
 This key and certificate can be used to sign SAML messages:
 
-    openssl req -newkey rsa:3072 -new -x509 -days 3652 -nodes -out example.org.crt -keyout example.org.pem
+```bash
+openssl req -newkey rsa:3072 -new -x509 -days 3652 -nodes -out example.org.crt -keyout example.org.pem
+```
 
 The certificate above will be valid for 10 years.
 
-
-### Note ###
+`Note`:
 
 SimpleSAMLphp will only work with RSA certificates. DSA certificates are not supported.
 
-
-Configuring the IdP
--------------------
+## Configuring the IdP
 
 The SAML 2.0 IdP is configured by the metadata stored in
 `metadata/saml20-idp-hosted.php`.
 This is a minimal configuration:
 
-    <?php
-    $metadata['https://example.org/saml-idp'] = [
-        /*
-         * The hostname for this IdP. This makes it possible to run multiple
-         * IdPs from the same configuration. '__DEFAULT__' means that this one
-         * should be used by default.
-         */
-        'host' => '__DEFAULT__',
-
-        /*
-         * The private key and certificate to use when signing responses.
-         * These can be stored as files in the cert-directory or retrieved
-         * from a database.
-         */
-        'privatekey' => 'example.org.pem',
-        'certificate' => 'example.org.crt',
-
-        /*
-         * The authentication source which should be used to authenticate the
-         * user. This must match one of the entries in config/authsources.php.
-         */
-        'auth' => 'example-userpass',
-    ];
+```php
+<?php
+
+$metadata['https://example.org/saml-idp'] = [
+    /*
+     * The hostname for this IdP. This makes it possible to run multiple
+     * IdPs from the same configuration. '__DEFAULT__' means that this one
+     * should be used by default.
+     */
+    'host' => '__DEFAULT__',
+
+    /*
+     * The private key and certificate to use when signing responses.
+     * These can be stored as files in the cert-directory or retrieved
+     * from a database.
+     */
+    'privatekey' => 'example.org.pem',
+    'certificate' => 'example.org.crt',
+
+    /*
+     * The authentication source which should be used to authenticate the
+     * user. This must match one of the entries in config/authsources.php.
+     */
+    'auth' => 'example-userpass',
+];
+```
 
 For more information about available options in the idp-hosted metadata
 files, see the [IdP hosted reference](simplesamlphp-reference-idp-hosted).
 
-
-Using the `uri` NameFormat on attributes
-----------------------------------------
+## Using the `uri` NameFormat on attributes
 
 The [interoperable SAML 2 profile](https://kantarainitiative.github.io/SAMLprofiles/saml2int.html) specifies that attributes should be delivered using the `urn:oasis:names:tc:SAML:2.0:attrname-format:uri` NameFormat.
 We therefore recommended enabling this in new installations.
 This can be done by adding the following to the saml20-idp-hosted configuration:
 
-    'attributes.NameFormat' => 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
-    'authproc' => [
-        // Convert LDAP names to oids.
-        100 => ['class' => 'core:AttributeMap', 'name2oid'],
-    ],
-
+```php
+'attributes.NameFormat' => 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
+'authproc' => [
+    // Convert LDAP names to oids.
+    100 => ['class' => 'core:AttributeMap', 'name2oid'],
+],
+```
 
-Adding SPs to the IdP
----------------------
+## Adding SPs to the IdP
 
 The identity provider you are configuring needs to know about the service providers you are going to connect to it.
 This is configured by metadata stored in `metadata/saml20-sp-remote.php`.
 This is a minimal example of a `metadata/saml20-sp-remote.php` metadata file for a SimpleSAMLphp SP:
 
-    <?php
-    $metadata['https://sp.example.org/simplesaml/module.php/saml/sp/metadata.php/default-sp'] = [
-        'AssertionConsumerService' => 'https://sp.example.org/simplesaml/module.php/saml/sp/assertionConsumerService/default-sp',
-        'SingleLogoutService'      => 'https://sp.example.org/simplesaml/module.php/saml/sp/singleLogoutService/default-sp',
-    ];
+```php
+<?php
+
+$metadata['https://sp.example.org/simplesaml/module.php/saml/sp/metadata.php/default-sp'] = [
+    'AssertionConsumerService' => 'https://sp.example.org/simplesaml/module.php/saml/sp/assertionConsumerService/default-sp',
+    'SingleLogoutService' => 'https://sp.example.org/simplesaml/module.php/saml/sp/singleLogoutService/default-sp',
+];
+```
 
 Note that the URI in the entityID and the URLs to the AssertionConsumerService and SingleLogoutService endpoints change between different service providers.
 If you have the metadata of the remote SP as an XML file, you can use the built-in XML to SimpleSAMLphp metadata converter, which by default is available as `/admin/metadata-converter.php` in your SimpleSAMLphp installation.
 
 For more information about available options in the sp-remote metadata files, see the [SP remote reference](simplesamlphp-reference-sp-remote).
 
-
-Adding this IdP to other SPs
-----------------------------
+## Adding this IdP to other SPs
 
 The method for adding this IdP to a SP varies between different types of SPs. In general, most SPs need some metadata from the IdP. This should be available from `/saml2/idp/metadata.php`.
 
-
-Testing the IdP
----------------
+## Testing the IdP
 
 The simplest way to test the IdP is to configure a SimpleSAMLphp SP
 on the same machine. See the instructions for
 [configuring SimpleSAMLphp as an SP](simplesamlphp-sp).
 
-
-### Note ###
+`Note`:
 
 When running a SimpleSAMLphp IdP and a SimpleSAMLphp SP on the same computer, the SP and IdP **MUST** be configured with different hostnames. This prevents cookies from the SP to interfere with cookies from the IdP.
 
-
-Support
--------
+## Support
 
 If you need help to make this work, or want to discuss SimpleSAMLphp with other users of the software, you are fortunate: Around SimpleSAMLphp there is a great Open source community, and you are welcome to join! The forums are open for you to ask questions, contribute answers other further questions, request improvements or contribute with code or plugins of your own.
 
@@ -220,27 +214,26 @@ If you need help to make this work, or want to discuss SimpleSAMLphp with other
 - [List of all available SimpleSAMLphp documentation](https://simplesamlphp.org/docs/)
 - [Join the SimpleSAMLphp user's mailing list](https://simplesamlphp.org/lists)
 
-
-
-A. IdP-first setup
-------------------
+## IdP-first setup
 
 If you do not want to start the SSO flow at the SP, you may use the IdP-first setup. To do this, redirect the user to the SSOService endpoint on the IdP with one parameter `spentityid` that match the SP EntityId that the user should be logged into.
 
 Here is an example of such a URL:
 
-	https://idp.example.org/simplesaml/saml2/idp/SSOService.php?spentityid=sp.example.org
+`https://idp.example.org/simplesaml/saml2/idp/SSOService.php?spentityid=sp.example.org`
 
 If the SP is a SimpleSAMLphp SP, you must also specify a `RelayState` parameter for the SP.
 This must be set to a URL the user should be redirected to after authentication.
 The `RelayState` parameter can be specified in the [SP configuration](./saml:sp), or it can be sent from the IdP.
 To send the RelayState parameter from a SimpleSAMLphp IdP, specify it in the query string to SSOService.php:
 
-    https://idp.example.org/simplesaml/saml2/idp/SSOService.php?spentityid=sp.example.org&RelayState=https://sp.example.org/welcome.php
+`https://idp.example.org/simplesaml/saml2/idp/SSOService.php?spentityid=sp.example.org&RelayState=https://sp.example.org/welcome.php`
 
 To set it in the SP configuration, add it to `authsources.php`:
 
-    'default-sp' => [
-        'saml:SP',
-        'RelayState' => 'https://sp.example.org/welcome.php',
-    ],
+```php
+'default-sp' => [
+    'saml:SP',
+    'RelayState' => 'https://sp.example.org/welcome.php',
+],
+```
diff --git a/docs/simplesamlphp-install-repo.md b/docs/simplesamlphp-install-repo.md
index 8c4548b6ba3f2cf8b0da551e2c1981a3a03c8d47..904fe91e153a780c81d05c1803f424c9e6c116c2 100644
--- a/docs/simplesamlphp-install-repo.md
+++ b/docs/simplesamlphp-install-repo.md
@@ -6,52 +6,66 @@ These are some notes about running SimpleSAMLphp from the repository.
 Prerequisites
 -------------
 
- * NodeJS version >= 10.0.
-
+* NodeJS version >= 10.0.
 
 Installing from git
 -------------------
 
 Go to the directory where you want to install SimpleSAMLphp:
 
-    cd /var
+```bash
+cd /var
+```
 
 Then do a git clone:
 
-    git clone git@github.com:simplesamlphp/simplesamlphp.git simplesamlphp
+```bash
+git clone git@github.com:simplesamlphp/simplesamlphp.git simplesamlphp
+```
 
 Initialize configuration and metadata:
 
-    cd /var/simplesamlphp
-    cp -r config-templates/* config/
-    cp -r metadata-templates/* metadata/
+```bash
+cd /var/simplesamlphp
+cp -r config-templates/* config/
+cp -r metadata-templates/* metadata/
+```
 
 Install the external dependencies with Composer (you can refer to
 [getcomposer.org](https://getcomposer.org/) to get detailed
 instructions on how to install Composer itself) and npm:
 
-    php composer.phar install
-    npm install
+```bash
+php composer.phar install
+npm install
+```
 
 Build the assets:
 
-    npm run build
-
+```bash
+npm run build
+```
 
 Upgrading
 ---------
 
 Go to the root directory of your SimpleSAMLphp installation:
 
-    cd /var/simplesamlphp
+```bash
+cd /var/simplesamlphp
+```
 
 Ask git to update to the latest version:
 
-    git fetch origin
-    git pull origin master
+```bash
+git fetch origin
+git pull origin master
+```
 
 Install or upgrade the external dependencies with Composer and npm:
 
-    php composer.phar install
-    npm install
-    npm run build
+```bash
+php composer.phar install
+npm install
+npm run build
+```
diff --git a/docs/simplesamlphp-install.md b/docs/simplesamlphp-install.md
index 560ddfade1ee7e827c281b98918083f75ed6c87c..40b17c6686650cf4450bbfadbae5104f9e677d91 100644
--- a/docs/simplesamlphp-install.md
+++ b/docs/simplesamlphp-install.md
@@ -1,53 +1,46 @@
-SimpleSAMLphp Installation and Configuration
-============================================
+# SimpleSAMLphp Installation and Configuration
 
 [TOC]
 
-
 This document is part of the SimpleSAMLphp documentation suite.
 
- * [List of all SimpleSAMLphp documentation](https://simplesamlphp.org/docs)
- * [SimpleSAMLphp homepage](https://simplesamlphp.org)
-
+* [List of all SimpleSAMLphp documentation](https://simplesamlphp.org/docs)
+* [SimpleSAMLphp homepage](https://simplesamlphp.org)
 
 This document covers the installation of the latest stable version of SimpleSAMLphp.
-If you want to install the development version, take a look at the instructions for [installing SimpleSAMLphp from the 
+If you want to install the development version, take a look at the instructions for [installing SimpleSAMLphp from the
 repository](simplesamlphp-install-repo).
 
-
-Prerequisites
--------------
-
- * A web server capable of executing PHP scripts.
- * PHP version >= 7.2.0.
- * Support for the following PHP extensions:
-   * Always required: `date`, `dom`, `hash`, `intl`, `json`, `libxml`, `mbstring`, `openssl`, `pcre`, `SPL`, `zlib`
-   * When automatically checking for latest versions, and used by some modules: `cURL`
-   * When authenticating against an LDAP server: `ldap`
-   * When authenticating against a RADIUS server: `radius`
-   * When using the native PHP session handler: `session`
-   * When saving session information to a memcache server: `memcache`
-   * When using databases:
-     * Always required: `PDO`
-     * Database driver: (`mysql`, `pgsql`, ...)
- * Support for the following PHP packages:
-   * When saving session information to a Redis server: `predis`
+## Prerequisites
+
+* A web server capable of executing PHP scripts.
+* PHP version >= 7.2.0.
+* Support for the following PHP extensions:
+  * Always required: `date`, `dom`, `hash`, `intl`, `json`, `libxml`, `mbstring`, `openssl`, `pcre`, `SPL`, `zlib`
+  * When automatically checking for latest versions, and used by some modules: `cURL`
+  * When authenticating against an LDAP server: `ldap`
+  * When authenticating against a RADIUS server: `radius`
+  * When using the native PHP session handler: `session`
+  * When saving session information to a memcache server: `memcache`
+  * When using databases:
+    * Always required: `PDO`
+    * Database driver: (`mysql`, `pgsql`, ...)
+* Support for the following PHP packages:
+  * When saving session information to a Redis server: `predis`
 
 What actual packages are required for the various extensions varies between different platforms and distributions.
 
-
-Download and install SimpleSAMLphp
-----------------------------------
+## Download and install SimpleSAMLphp
 
 The most recent release of SimpleSAMLphp can always be found at
 [https://simplesamlphp.org/download](https://simplesamlphp.org/download).
 
 Go to the directory where you want to install SimpleSAMLphp and extract the archive file you just downloaded:
 
-```
-    cd /var
-    tar xzf simplesamlphp-x.y.z.tar.gz
-    mv simplesamlphp-x.y.z simplesamlphp
+```bash
+cd /var
+tar xzf simplesamlphp-x.y.z.tar.gz
+mv simplesamlphp-x.y.z simplesamlphp
 ```
 
 ## Upgrading from a previous version of SimpleSAMLphp
@@ -58,71 +51,65 @@ changes.
 
 Extract the new version:
 
-```
-    cd /var
-    tar xzf simplesamlphp-x.y.z.tar.gz
+```bash
+cd /var
+tar xzf simplesamlphp-x.y.z.tar.gz
 ```
 
 Copy the configuration files from the previous version (in case the configuration directory is inside SimpleSAMLphp,
 keep reading for other alternatives):
 
-```
-    cd /var/simplesamlphp-x.y.z
-    rm -rf config metadata
-    cp -rv ../simplesamlphp/config config
-    cp -rv ../simplesamlphp/metadata metadata
+```bash
+cd /var/simplesamlphp-x.y.z
+rm -rf config metadata
+cp -rv ../simplesamlphp/config config
+cp -rv ../simplesamlphp/metadata metadata
 ```
 
-If you have installed any [third-party modules](https://simplesamlphp.org/modules) or [customised the theme](simplesamlphp-theming.md), 
+If you have installed any [third-party modules](https://simplesamlphp.org/modules) or [customised the theme](simplesamlphp-theming.md),
 you should check whether your third-party modules need upgrading and then copy or replace those directories too.
 
 Replace the old version with the new version:
 
-```
-    cd /var
-    mv simplesamlphp simplesamlphp.old
-    mv simplesamlphp-x.y.z simplesamlphp
+```bash
+cd /var
+mv simplesamlphp simplesamlphp.old
+mv simplesamlphp-x.y.z simplesamlphp
 ```
 
 If the format of the config files or metadata has changed from your previous version of SimpleSAMLphp (check the
 upgrade notes), you may have to update your configuration and metadata after updating the SimpleSAMLphp code.
 
-
 ### Upgrading configuration files
 
 A good approach is to run a `diff` between your previous `config.php` file and the new `config.php` file located in
-`config-templates/config.php`, and apply relevant modifications to the new template. This will ensure that all new 
+`config-templates/config.php`, and apply relevant modifications to the new template. This will ensure that all new
 entries in the latest version of config.php are included, as well as preserve your local modifications.
 
-
 ### Upgrading metadata files
 
 Most likely the metadata format is backwards compatible. If not, you should receive a very clear error message at
 startup indicating how and what you need to update. You should look through the metadata in the `metadata-templates`
 directory after the upgrade to see whether recommended defaults have been changed.
 
-
-Configuration
--------------
+## Configuration
 
 ### Location of configuration files
 
 By default, SimpleSAMLphp looks for its configuration in the `config` directory in the root of its own directory. This
-has some drawbacks, like making it harder to update SimpleSAMLphp or to install it as a composer dependency, or to 
+has some drawbacks, like making it harder to update SimpleSAMLphp or to install it as a composer dependency, or to
 package it for different operating systems.
 
 In order to avoid this limitations, it is possible to specify an alternative location for the configuration directory
-by setting the `SIMPLESAMLPHP_CONFIG_DIR` environment variable to point to this location. This way, the configuration 
+by setting the `SIMPLESAMLPHP_CONFIG_DIR` environment variable to point to this location. This way, the configuration
 directory doesn't need to be inside the library's directory, making it easier to manage and to update. The simplest way
 to set this environment variable is to set it in your web server's configuration. See the next section for more
 information.
 
-
-Configuring Apache
-------------------
+## Configuring Apache
 
 Examples below assume that SimpleSAMLphp is installed in the default location, `/var/simplesamlphp`. You may choose
-another location, but this requires a path update in a few files. See Appendix _Installing SimpleSAMLphp 
+another location, but this requires a path update in a few files. See Appendix _Installing SimpleSAMLphp
 in alternative locations_ for more details.
 
 The only subdirectory of `SimpleSAMLphp` that needs to be accessible from the web is `www`. There are several ways of
@@ -132,39 +119,38 @@ one possible configuration.
 Find the Apache configuration file for the virtual hosts where you want to run SimpleSAMLphp. The configuration may
 look like this:
 
-```
-    <VirtualHost *>
-            ServerName service.example.com
-            DocumentRoot /var/www/service.example.com
+```apacheconf
+<VirtualHost *>
+    ServerName service.example.com
+    DocumentRoot /var/www/service.example.com
 
-            SetEnv SIMPLESAMLPHP_CONFIG_DIR /var/simplesamlphp/config
+    SetEnv SIMPLESAMLPHP_CONFIG_DIR /var/simplesamlphp/config
 
-            Alias /simplesaml /var/simplesamlphp/www
+    Alias /simplesaml /var/simplesamlphp/www
 
-            <Directory /var/simplesamlphp/www>
-                Require all granted
-            </Directory>
-    </VirtualHost>
+    <Directory /var/simplesamlphp/www>
+        Require all granted
+    </Directory>
+</VirtualHost>
 ```
 
 Note the `Alias` directive, which gives control to SimpleSAMLphp for all urls matching
 `http(s)://service.example.com/simplesaml/*`. SimpleSAMLphp makes several SAML interfaces available on the web; all of
-them are accessible through the `www` subdirectory of your SimpleSAMLphp installation. You can name the alias 
-whatever you want, but the name must be specified in the `baseurlpath` configuration option in the `config.php` file of 
+them are accessible through the `www` subdirectory of your SimpleSAMLphp installation. You can name the alias
+whatever you want, but the name must be specified in the `baseurlpath` configuration option in the `config.php` file of
 SimpleSAMLphp as described in
 [the section called “SimpleSAMLphp configuration: config.php”](#section_6 "SimpleSAMLphp configuration: config.php").
 Here is an example of how this configuration may look like in `config.php`:
 
-```
+```php
 $config = [
     [...]
     'baseurlpath' => 'simplesaml/',
     [...]
 ]
 ```
-    
 
-Note also the `SetEnv` directive in the Apache configuration. It sets the `SIMPLESAMLPHP_CONFIG_DIR` environment 
+Note also the `SetEnv` directive in the Apache configuration. It sets the `SIMPLESAMLPHP_CONFIG_DIR` environment
 variable, in this case, to the default location for the configuration directory. You can omit this environment
 variable, and SimpleSAMLphp will then look for the `config` directory inside its own directory. If you need to move
 your configuration to a different location, you can use this environment variable to tell SimpleSAMLphp where to look
@@ -175,12 +161,10 @@ This is just the basic configuration to get things working. For a checklist
 further completing your documentation, please see
 [Maintenance and configuration: Apache](simplesamlphp-maintenance#section_5).
 
-
-Configuring Nginx
-------------------
+## Configuring Nginx
 
 Examples below assume that SimpleSAMLphp is installed in the default location, `/var/simplesamlphp`. You may choose
-another location, but this requires a path update in a few files. See Appendix _Installing SimpleSAMLphp 
+another location, but this requires a path update in a few files. See Appendix _Installing SimpleSAMLphp
 in alternative locations_ for more details.
 
 The only subdirectory of `SimpleSAMLphp` that needs to be accessible from the web is `www`. There are several ways of
@@ -190,110 +174,107 @@ one possible configuration.
 Find the Nginx configuration file for the virtual hosts where you want to run SimpleSAMLphp. The configuration may
 look like this:
 
-```
-    server {
-        listen 443 ssl;
-        server_name idp.example.com;
+```nginx
+server {
+    listen 443 ssl;
+    server_name idp.example.com;
 
-        ssl_certificate        /etc/pki/tls/certs/idp.example.com.crt;
-        ssl_certificate_key    /etc/pki/tls/private/idp.example.com.key;
-        ssl_protocols          TLSv1.3 TLSv1.2;
-        ssl_ciphers            EECDH+AESGCM:EDH+AESGCM;
+    ssl_certificate        /etc/pki/tls/certs/idp.example.com.crt;
+    ssl_certificate_key    /etc/pki/tls/private/idp.example.com.key;
+    ssl_protocols          TLSv1.3 TLSv1.2;
+    ssl_ciphers            EECDH+AESGCM:EDH+AESGCM;
 
-        location ^~ /simplesaml {
-            alias /var/simplesamlphp/www;
+    location ^~ /simplesaml {
+        alias /var/simplesamlphp/www;
 
-            location ~^(?<prefix>/simplesaml)(?<phpfile>.+?\.php)(?<pathinfo>/.*)?$ {
-                include          fastcgi_params;
-                fastcgi_pass     $fastcgi_pass;
-                fastcgi_param SCRIPT_FILENAME $document_root$phpfile;
+        location ~^(?<prefix>/simplesaml)(?<phpfile>.+?\.php)(?<pathinfo>/.*)?$ {
+            include          fastcgi_params;
+            fastcgi_pass     $fastcgi_pass;
+            fastcgi_param SCRIPT_FILENAME $document_root$phpfile;
 
-                # Must be prepended with the baseurlpath
-                fastcgi_param SCRIPT_NAME /simplesaml$phpfile;
+            # Must be prepended with the baseurlpath
+            fastcgi_param SCRIPT_NAME /simplesaml$phpfile;
 
-                fastcgi_param PATH_INFO $pathinfo if_not_empty;
-            }
+            fastcgi_param PATH_INFO $pathinfo if_not_empty;
         }
     }
+}
 ```
 
-SimpleSAMLphp configuration: config.php
----------------------------------------
+## SimpleSAMLphp configuration: config.php
 
 There are a few steps that you should complete in the main configuration file, `config.php`, right away:
 
--  Set the `baseurlpath` configuration option. Make it point to the canonical URL of your deployment, where
-   SimpleSAMLphp can be reached:
-   
-   ```
-       'baseurlpath' => 'https://your.canonical.host.name/simplesaml/',
-   ```
+* Set the `baseurlpath` configuration option. Make it point to the canonical URL of your deployment, where
+  SimpleSAMLphp can be reached:
 
-   Please note that your canonical URL should always use HTTPS in order to protect your users. Additionally, if you
-   are running behind a **reverse proxy** and you are offloading TLS to it, the proper way to tell SimpleSAMLphp that
-   its base URL should use HTTPS is to set the `baseurlpath` configuration option properly. SimpleSAMLphp deliberately
-   **ignores** the `X-Forwarded-*` set of headers that your proxy might be setting, so **do not rely on those**. 
+```php
+'baseurlpath' => 'https://your.canonical.host.name/simplesaml/',
+```
 
--  Set an administrator password. This is needed to access some of the pages in your SimpleSAMLphp installation web
-   interface.
-   
-   Hashed passwords can also be used here. See the [`authcrypt`](./authcrypt:authcrypt) documentation
-   for more information.
+  Please note that your canonical URL should always use HTTPS in order to protect your users. Additionally, if you
+  are running behind a **reverse proxy** and you are offloading TLS to it, the proper way to tell SimpleSAMLphp that
+  its base URL should use HTTPS is to set the `baseurlpath` configuration option properly. SimpleSAMLphp deliberately
+  **ignores** the `X-Forwarded-*` set of headers that your proxy might be setting, so **do not rely on those**.
 
-   ```
-       'auth.adminpassword' => 'setnewpasswordhere',
-   ```
+* Set an administrator password. This is needed to access some of the pages in your SimpleSAMLphp installation web
+  interface.
 
--  Set a secret salt. This should be a random string. Some parts of the SimpleSAMLphp needs this salt to generate
-   cryptographically secure hashes. SimpleSAMLphp will give an error if the salt is not changed from the default value.
-   The command below can help you to generated a random string on (some) unix systems:
+  Hashed passwords can also be used here. See the [`authcrypt`](./authcrypt:authcrypt) documentation
+  for more information.
 
-   ```
-   tr -c -d '0123456789abcdefghijklmnopqrstuvwxyz' </dev/urandom | dd bs=32 count=1 2>/dev/null;echo
-   ```
+```php
+'auth.adminpassword' => 'setnewpasswordhere',
+```
 
-   Here is an example of the configuration option:
+* Set a secret salt. This should be a random string. Some parts of the SimpleSAMLphp needs this salt to generate
+  cryptographically secure hashes. SimpleSAMLphp will give an error if the salt is not changed from the default value.
+  The command below can help you to generated a random string on (some) unix systems:
 
-   ```
-       'secretsalt' => 'randombytesinsertedhere',
-   ```
+```bash
+tr -c -d '0123456789abcdefghijklmnopqrstuvwxyz' </dev/urandom | dd bs=32 count=1 2>/dev/null;echo
+```
 
-   **Please note that changing the secret salt may break access to services for your users**. 
+  Here is an example of the configuration option:
 
--  Configure your data storage. You can do this by editing the `store.type` configuration option, and setting it to
-   one of the supported values. Now configure the backend of your choice with the relevant options, if needed.
-   
--  Configure your sessions. You have to configure your sessions with the appropriate parameters so that the cookies
-   used by SimpleSAMLphp to track users are always delivered to the software. You may do this by editing the
-   `session.*` configuration options. Note that if you are using the `phpsession` data storage, the cookie-related
-   configuration options are configured in the `session.phpsession.*` options.
+```php
+'secretsalt' => 'randombytesinsertedhere',
+```
 
--  Set technical contact information. This information will be available in the generated metadata. The e-mail address
-   will also be used for receiving error reports sent automatically by SimpleSAMLphp. Here is an example:
+  **Please note that changing the secret salt may break access to services for your users**.
 
-   ```
-       'technicalcontact_name' => 'John Smith',
-       'technicalcontact_email' => 'john.smith@example.com',
-   ```
+* Configure your data storage. You can do this by editing the `store.type` configuration option, and setting it to
+  one of the supported values. Now configure the backend of your choice with the relevant options, if needed.
 
--  If you use SimpleSAMLphp in a country where English is not widespread, you may want to change the default language
-   from English to something else:
+* Configure your sessions. You have to configure your sessions with the appropriate parameters so that the cookies
+  used by SimpleSAMLphp to track users are always delivered to the software. You may do this by editing the
+  `session.*` configuration options. Note that if you are using the `phpsession` data storage, the cookie-related
+  configuration options are configured in the `session.phpsession.*` options.
 
-   ```
-       'language.default' => 'no',
-   ```
+* Set technical contact information. This information will be available in the generated metadata. The e-mail address
+  will also be used for receiving error reports sent automatically by SimpleSAMLphp. Here is an example:
 
--  Set your timezone
+```php
+'technicalcontact_name' => 'John Smith',
+'technicalcontact_email' => 'john.smith@example.com',
+```
 
-   ```
-       'timezone' => 'Europe/Oslo',
-   ```
+* If you use SimpleSAMLphp in a country where English is not widespread, you may want to change the default language
+  from English to something else:
+
+```php
+'language.default' => 'no',
+```
+
+* Set your timezone
 
-   You can see [a list of Supported Timezones at php.net](http://php.net/manual/en/timezones.php).
+```php
+'timezone' => 'Europe/Oslo',
+```
 
+  You can see [a list of Supported Timezones at php.net](http://php.net/manual/en/timezones.php).
 
-Configuring PHP
----------------
+## Configuring PHP
 
 ### Sending e-mails from PHP
 
@@ -304,18 +285,17 @@ send e-mails.
 By default SimpleSAMLphp uses the PHP `mail()` function, which you can configure via `php.ini`.
 For more advanced configuration, including using a remote SMTP server, see the `mail.*` options in `config.php`.
 
-Enabling and disabling modules
-------------------------------
+## Enabling and disabling modules
 
-If you want to enable some of the modules that are installed with SimpleSAMLphp, but are disabled by default, you 
+If you want to enable some of the modules that are installed with SimpleSAMLphp, but are disabled by default, you
 can do that in the configuration:
 
-```
-    'module.enable' => [
-         'exampleauth' => true, // Setting to TRUE enables.
-         'saml' => false, // Setting to FALSE disables.
-         'core' => null, // Unset or NULL uses default for this module.
-    ],
+```php
+'module.enable' => [
+    'exampleauth' => true, // Setting to TRUE enables.
+    'saml' => false, // Setting to FALSE disables.
+    'core' => null, // Unset or NULL uses default for this module.
+],
 ```
 
 Set to `true` the modules you want to enable, and to `false` those that you want to disable.
@@ -323,22 +303,19 @@ Set to `true` the modules you want to enable, and to `false` those that you want
 Prior to SSP V2 you could enable or disable modules by setting empty files with names (`enable`, `disable`,
 `default-enable`) in the module's root directory. You need to now use the `module.enable` config option.
 
-
-The SimpleSAMLphp admin interface
----------------------------------
+## The SimpleSAMLphp admin interface
 
 After installing SimpleSAMLphp, you can access the homepage of your installation, which by default does
 not show much information:
 
-    https://service.example.org/simplesaml/
+`https://service.example.org/simplesaml/`
 
 The exact URL depends on how you set it up with your web server, and of course on your hostname.
 If this works, you can now also acceas the admin module by adding `admin/` to your base URL:
 
-    https://service.example.org/simplesaml/admin/
+`https://service.example.org/simplesaml/admin/`
 
-
-**Warning**: before you can actually use SimpleSAMLphp for something useful, you need to configure it either as a 
+**Warning**: before you can actually use SimpleSAMLphp for something useful, you need to configure it either as a
 Service Provider or as an Identity Provider, depending on your use case.
 
 Here is an example screenshot of what the SimpleSAMLphp page looks like:
@@ -348,14 +325,14 @@ Here is an example screenshot of what the SimpleSAMLphp page looks like:
 ### Check your PHP environment
 
 At the bottom of the admin page there are some green lights. SimpleSAMLphp runs some tests to see whether the
-required and recommended prerequisites are met. If any of the lights are red, you may have to install some PHP 
+required and recommended prerequisites are met. If any of the lights are red, you may have to install some PHP
 extensions or external PHP packages (e.g. you need the PHP LDAP extension to use the LDAP authentication module).
 
 ## Building assets
 
 Run the following commands to build the default theme.
 
-```
+```bash
 npm install
 npm run build
 ```
@@ -363,50 +340,46 @@ npm run build
 ## Next steps
 
 You have now successfully installed SimpleSAMLphp, and the next steps depend on whether you want to setup a Service
-Provider (in order to protect access to an existing application) or an Identity Provider (which you would connect to 
-a user database where your users can authenticate). Documentation on bridging between federation protocols is found 
+Provider (in order to protect access to an existing application) or an Identity Provider (which you would connect to
+a user database where your users can authenticate). Documentation on bridging between federation protocols is found
 in a separate document.
 
- - [Using SimpleSAMLphp as a Service Provider (SP)](simplesamlphp-sp)
-   + [Remote IdP reference](simplesamlphp-reference-idp-remote)
-   + [Connecting to the UK Access Federation or InCommon](simplesamlphp-ukaccess)
- - [Using SimpleSAMLphp as an Identity Provider (IdP)](simplesamlphp-idp)
-   + [Hosted IdP reference](simplesamlphp-reference-idp-hosted)
-   + [Remote SP reference](simplesamlphp-reference-sp-remote)
-   + [Setting up an IdP for Google Workspace (G Suite / Google Apps)](simplesamlphp-googleapps)
-   + [Advanced Topics](simplesamlphp-idp-more)
- - [Automated Metadata Management](/docs/contrib_modules/metarefresh/simplesamlphp-automated_metadata)
- - [Maintenance and configuration](simplesamlphp-maintenance)
+* [Using SimpleSAMLphp as a Service Provider (SP)](simplesamlphp-sp)
+  * [Remote IdP reference](simplesamlphp-reference-idp-remote)
+  * [Connecting to the UK Access Federation or InCommon](simplesamlphp-ukaccess)
+* [Using SimpleSAMLphp as an Identity Provider (IdP)](simplesamlphp-idp)
+  * [Hosted IdP reference](simplesamlphp-reference-idp-hosted)
+  * [Remote SP reference](simplesamlphp-reference-sp-remote)
+  * [Setting up an IdP for Google Workspace (G Suite / Google Apps)](simplesamlphp-googleapps)
+  * [Advanced Topics](simplesamlphp-idp-more)
+* [Automated Metadata Management](/docs/contrib_modules/metarefresh/simplesamlphp-automated_metadata)
+* [Maintenance and configuration](simplesamlphp-maintenance)
 
-
-Support
--------
+## Support
 
 If you need help to make this work, or want to discuss SimpleSAMLphp with other users of the software, you are
-in luck: there is a great Open Source community around SimpleSAMLphp, and you are welcome to join! The forums are open 
-for you to ask questions, help others by answering their questions, request improvements or contribute with 
+in luck: there is a great Open Source community around SimpleSAMLphp, and you are welcome to join! The forums are open
+for you to ask questions, help others by answering their questions, request improvements or contribute with
 code or plugins of your own.
 
--  [Homepage](https://simplesamlphp.org)
--  [Documentation](https://simplesamlphp.org/docs/)
--  [Mailing lists](https://simplesamlphp.org/lists)
-
+* [Homepage](https://simplesamlphp.org)
+* [Documentation](https://simplesamlphp.org/docs/)
+* [Mailing lists](https://simplesamlphp.org/lists)
 
-Appendix: Installing SimpleSAMLphp in alternative locations
--------------------------------------------------
+## Appendix: Installing SimpleSAMLphp in alternative locations
 
 There may be several reasons why you want to install SimpleSAMLphp in an alternative way.
 
-- You are installing SimpleSAMLphp in a hosted environment where you do not have root access, and cannot change
-   Apache configuration. You can still install SimpleSAMLphp, keep on reading!
+* You are installing SimpleSAMLphp in a hosted environment where you do not have root access, and cannot change
+  Apache configuration. You can still install SimpleSAMLphp, keep on reading!
 
-- You have full permissions to the server, but cannot edit web server configuration for some reason like internal 
-policies.
+* You have full permissions to the server, but cannot edit web server configuration for some reason like internal
+  policies.
 
-The SimpleSAMLphp package contains one folder named `simplesamlphp-x.y.z` (where `x.y.z` is the version number). In 
-this folder there are a lot of subfolders for library, metadata, configuration, etc. One of these folders is named 
-`www`. **Only this folder should be exposed on the web**. The recommended configuration is to put the whole 
-`simplesamlphp` folder outside the web root, and then link to the `www` folder by using the `Alias` directive, as 
+The SimpleSAMLphp package contains one folder named `simplesamlphp-x.y.z` (where `x.y.z` is the version number). In
+this folder there are a lot of subfolders for library, metadata, configuration, etc. One of these folders is named
+`www`. **Only this folder should be exposed on the web**. The recommended configuration is to put the whole
+`simplesamlphp` folder outside the web root, and then link to the `www` folder by using the `Alias` directive, as
 described in [the section called “Configuring Apache”](#section_4 "Configuring Apache"). This is not the only
 possible way, though.
 
@@ -414,7 +387,7 @@ As an example, let's see how you can install SimpleSAMLphp in your home director
 
 1. Extract the SimpleSAMLphp archive in your home directory:
 
-   ```
+   ```bash
    cd ~
    tar xzf simplesamlphp-1.x.y.tar.gz
    mv simplesamlphp-1.x.y simplesamlphp
@@ -422,55 +395,54 @@ As an example, let's see how you can install SimpleSAMLphp in your home director
 
 2. Then you can try to make a symlink into the `public_html` directory.
 
-   ```
+   ```bash
    cd ~/public_html
    ln -s ../simplesamlphp/www simplesaml
    ```
 
-3. Next, you need to set the `baseurlpath` configuration option with the URL pointing to the `simplesaml` link you 
-just created in your `public_html` directory. For example, if your home directory is reachable in
-`https://host.example/~myaccount/`, set the base URL path accordingly:
+3. Next, you need to set the `baseurlpath` configuration option with the URL pointing to the `simplesaml` link you
+   just created in your `public_html` directory. For example, if your home directory is reachable in
+   `https://host.example/~myaccount/`, set the base URL path accordingly:
 
-   ```
-       'baseurlpath' => 'https://host.example/~myaccount/simplesaml/', 
+   ```bash
+   'baseurlpath' => 'https://host.example/~myaccount/simplesaml/', 
    ```
 
    Now, you can go to the URL of your installation and check if things work:
 
-       https://host.example/~myaccount/simplesaml/
-
+   `https://host.example/~myaccount/simplesaml/`
 
-#### Tip
+### Tip
 
-Symlinking may fail, because some Apache configurations do not allow you to link to files from outside the 
+Symlinking may fail, because some Apache configurations do not allow you to link to files from outside the
 `public_html` folder. If so, you can move the `www` folder instead of symlinking it:
 
-```
-    cd ~/public_html
-    mv ../simplesamlphp/www simplesaml
+```bash
+cd ~/public_html
+mv ../simplesamlphp/www simplesaml
 ```
 
 Now you have the following directory structure.
 
-- `~/simplesamlphp`
+* `~/simplesamlphp`
 
-- `~/public_html/simplesaml` where `simplesaml` is the `www` directory from the `simplesamlphp` installation directory,
+* `~/public_html/simplesaml` where `simplesaml` is the `www` directory from the `simplesamlphp` installation directory,
   either moved or a symlink.
 
 Now, we need to make a few configuration changes. First, let's edit `~/public_html/simplesaml/_include.php`:
 
 Change the two lines from:
 
-```
-    require_once(dirname(dirname(__FILE__)) . '/lib/_autoload.php');
+```php
+require_once(dirname(dirname(__FILE__)) . '/lib/_autoload.php');
 ```
 
 to something like:
 
-```
-    require_once(dirname(dirname(dirname(__FILE__))) . '/lib/_autoload.php');
+```bash
+require_once(dirname(dirname(dirname(__FILE__))) . '/lib/_autoload.php');
 ```
 
-**Warning**: note that this will make upgrading SimpleSAMLphp much more difficult, since you will need to move the 
+**Warning**: note that this will make upgrading SimpleSAMLphp much more difficult, since you will need to move the
 `www` directory and manually edit files every time you upgrade. It is also possible that this method does not work in
 future versions of SimpleSAMLphp, and therefore it is discouraged and should be used only as a last resort.
diff --git a/docs/simplesamlphp-maintenance.md b/docs/simplesamlphp-maintenance.md
index 3dc86173119fd55a18704fef5588587da525ecf7..7e849a914a3d43a7ebf83ec07a5e2a5e8b187afa 100644
--- a/docs/simplesamlphp-maintenance.md
+++ b/docs/simplesamlphp-maintenance.md
@@ -1,5 +1,4 @@
-SimpleSAMLphp Maintenance
-=========================
+# SimpleSAMLphp Maintenance
 
 <!--
 	This file is written in Markdown syntax.
@@ -7,18 +6,16 @@ SimpleSAMLphp Maintenance
 	http://daringfireball.net/projects/markdown/syntax
 -->
 
-
 [TOC]
 
-SimpleSAMLphp news and documentation
-------------------------------------
+## SimpleSAMLphp news and documentation
 
 Please check the following sources of information to stay up to date with regard to SimpleSAMLphp:
 
- * [SimpleSAMLphp documentation](http://simplesamlphp.org/docs)
- * [SimpleSAMLphp homepage](https://simplesamlphp.org)
- * [SimpleSAMLphp mailing lists](https://simplesamlphp.org/lists)
- * [SimpleSAMLphp in twitter](https://twitter.com/simplesamlphp)
+* [SimpleSAMLphp documentation](http://simplesamlphp.org/docs)
+* [SimpleSAMLphp homepage](https://simplesamlphp.org)
+* [SimpleSAMLphp mailing lists](https://simplesamlphp.org/lists)
+* [SimpleSAMLphp in twitter](https://twitter.com/simplesamlphp)
 
 ## Session management
 
@@ -26,26 +23,32 @@ SimpleSAMLphp has an abstraction layer for session management. That means it is
 
 The `store.type` configuration option in `config.php` allows you to select which method SimpleSAMLphp should use to store the session information. Currently, three session handlers are included in the distribution:
 
-  * `phpsession` uses the built in session management in PHP. This is the default, and is simplest to use. It will not work in a load-balanced environment in most configurations.
-  * `memcache` uses the memcache software to cache sessions in memory. Sessions can be distributed and replicated among several memcache servers, enabling both load-balancing and fail-over.
-  * `sql` stores the session in an SQL database.
-  * `redis` stores the session in Redis.
+* `phpsession` uses the built in session management in PHP. This is the default, and is simplest to use. It will not work in a load-balanced environment in most configurations.
+* `memcache` uses the memcache software to cache sessions in memory. Sessions can be distributed and replicated among several memcache servers, enabling both load-balancing and fail-over.
+* `sql` stores the session in an SQL database.
+* `redis` stores the session in Redis.
 
-    'store.type' => 'phpsession',
+```php
+'store.type' => 'phpsession',
+```
 
 ### Configuring PHP sessions
 
 To use the PHP session handler, set the `store.type` configuration option in `config.php`:
 
-    'store.type' => 'phpsession',
+```php
+'store.type' => 'phpsession',
+```
 
 Keep in mind that **PHP does not allow two sessions to be open at the same time**. This means if you are using PHP sessions both in your
 application and in SimpleSAMLphp at the same time, **they need to have different names**. When using the PHP session handler in
 SimpleSAMLphp, it is configured with different options than for other session handlers:
 
-    'session.phpsession.cookiename' => null,
-    'session.phpsession.savepath' => null,
-    'session.phpsession.httponly' => true,
+```php
+'session.phpsession.cookiename' => null,
+'session.phpsession.savepath' => null,
+'session.phpsession.httponly' => true,
+```
 
 Make sure to set `session.phpsession.cookiename` to a name different than the one in use by any other applications. If you are using
 SimpleSAMLphp as an Identity Provider, or any other applications using it are not using the default session name, you can use the default
@@ -58,7 +61,9 @@ If you need to restore your session's application after calling SimpleSAMLphp, y
 
 To use the memcache session handler, set the `store.type` parameter in `config.php`:
 
-    'store.type' => 'memcache',
+```php
+'store.type' => 'memcache',
+```
 
 memcache allows you to store multiple redundant copies of sessions on different memcache servers.
 
@@ -68,54 +73,57 @@ Each server group is an array of servers. The data items will be load-balanced b
 
 Each server is an array of parameters for the server. The following options are available:
 
-`hostname`
-:   Host name or ip address where the memcache server runs, or specify other transports like *unix:///path/ssp.sock* to
-    use UNIX domain sockets. In that case, port will be ignored and forced to *0*.
-
-    This is the only required option.
+`hostname`:
+Host name or ip address where the memcache server runs, or specify other transports like *unix:///path/ssp.sock* to
+use UNIX domain sockets. In that case, port will be ignored and forced to *0*.
 
-`port`
-:   Port number of the memcache server. If not set, the `memcache.default_port` ini setting is used. This is 11211 by
-    default.
+This is the only required option.
 
-    The port will be forced to *0* when a UNIX domain socket is specified in *hostname*.
+`port`:
+Port number of the memcache server. If not set, the `memcache.default_port` ini setting is used. This is 11211 by
+default.
 
-`weight`
-:   Weight of this server in this server group.
-    [http://php.net/manual/en/function.Memcache-addServer.php](http://php.net/manual/en/function.Memcache-addServer.php)
-    has more information about the weight option.
+The port will be forced to *0* when a UNIX domain socket is specified in *hostname*.
 
-`timeout`
-:   Timeout for this server. By default, the timeout is 3
-    seconds.
+`weight`:
+Weight of this server in this server group.
+[http://php.net/manual/en/function.Memcache-addServer.php](http://php.net/manual/en/function.Memcache-addServer.php)
+has more information about the weight option.
 
+`timeout`:
+Timeout for this server. By default, the timeout is 3
+seconds.
 
 Here are two examples of configuration of memcache session handling:
 
-**Example&nbsp;1.&nbsp;Example of redundant configuration with load balancing**
+### Example 1. Example of redundant configuration with load balancing
 
 Example of redundant 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' => [
-      [
+```php
+'memcache_store.servers' => [
+    [
         ['hostname' => 'mc_a1'],
         ['hostname' => 'mc_a2'],
-      ],
-      [
+    ],
+    [
         ['hostname' => 'mc_b1'],
         ['hostname' => 'mc_b2'],
-      ],
     ],
+],
+```
 
-**Example&nbsp;2.&nbsp;Example of simple configuration with only one memcache server**
+### Example 2. Example of simple configuration with only one memcache server
 
 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' => [
-      [
+```php
+'memcache_store.servers' => [
+    [
         ['hostname' => 'localhost'],
-      ],
     ],
+],
+```
 
 The expiration value (`memcache_store.expires`) is the duration for which data should be retained in memcache. Data are dropped from the memcache servers when this time expires. The time will be reset every time the data is written to the memcache servers.
 
@@ -123,23 +131,27 @@ This value should always be larger than the `session.duration` option. Not doing
 
 Set this value to 0 if you don't want data to expire.
 
-#### Note
+`Note`
 
 The oldest data will always be deleted if the memcache server runs
 out of storage space.
 
-**Example&nbsp;3.&nbsp;Example of configuration setting for session expiration**
+### Example 3. Example of configuration setting for session expiration
 
 Here is an example of this configuration parameter:
 
-    'memcache_store.expires' =>  36 * (60*60), // 36 hours.
+```php
+'memcache_store.expires' =>  36 * (60*60), // 36 hours.
+```
 
 #### Memcache PHP configuration
 
 Configure memcache to not do internal failover. This parameter is
 configured in `php.ini`.
 
-    memcache.allow_failover = Off
+```php
+memcache.allow_failover = Off
+```
 
 #### Environmental configuration
 
@@ -147,7 +159,6 @@ Setup a firewall restricting access to the memcache server.
 
 Because SimpleSAMLphp uses a timestamp to check which session is most recent in a fail-over setup, it is very important to run synchronized clocks on all web servers where you run SimpleSAMLphp.
 
-
 ### Configuring SQL storage
 
 To store session to a SQL database, set the `store.type` option to `sql`.
@@ -164,6 +175,7 @@ To store sessions in Redis, set the `store.type` option to `redis`.
 By default SimpleSAMLphp will attempt to connect to Redis on the `localhost` at port `6379`. These can be configured via the `store.redis.host` and `store.redis.port` options, respectively. You may also set a key prefix with the `store.redis.prefix` option.
 
 For Redis instances that [require authentication](https://redis.io/commands/auth):
+
 * If authentication is managed with the `requirepass` directive (legacy password protection): use the `store.redis.password` option
 * If authentication is managed with [ACL's](https://redis.io/docs/manual/security/acl/) (which are recommended as of Redis 6): use the `store.redis.password` and `store.redis.username` options
 
@@ -173,7 +185,7 @@ Several metadata storage backends are available by default, including `flatfile`
 [`pdo`](https://simplesamlphp.org/docs/stable/simplesamlphp-metadata-pdostoragehandler). Here you have an
 example configuration of different metadata sources in use at the same time:
 
-```
+```php
 'metadata.sources' => [
     ['type' => 'flatfile'],
     ['type' => 'flatfile', 'directory' => 'metadata/metarefresh-kalmar'],
@@ -188,9 +200,9 @@ and override the methods needed to change the backend used. This class **must**
 
 Bear in mind that **your class name must follow the PSR-0 autoloading standard**. This means it needs to be
 named in a particular way, with the use of namespaces being the preferred convention. For example, if your
-module is named _mymodule_ and your class is named _MyMetadataHandler_, you should define it like this: 
+module is named `mymodule` and your class is named `MyMetadataHandler`, you should define it like this:
 
-```
+```php
 <?php
 namespace SimpleSAML\Module\mymodule\MetadataStore;
 
@@ -230,27 +242,27 @@ Turn off PHPSESSID in query string.
 
 Here are some checkpoints
 
- 1. Remove all entities in metadata files that you do not trust. It is easy to forget about some of the entities that were used for test.
- 2. If you during testing have been using a certificate that has been exposed (notably: the one found in the SimpleSAMLphp distribution): Obtain and install a new one.
- 3. Make sure you have installed the latest security upgrades for your OS.
- 4. Make sure to use HTTPS rather than HTTP.
- 5. Block access to your servers on anything except port 443. SimpleSAMLphp only uses plain HTTP(S), so there is no need to open ports for SOAP or other communication.
-
+1. Remove all entities in metadata files that you do not trust. It is easy to forget about some of the entities that were used for test.
+2. If you during testing have been using a certificate that has been exposed (notably: the one found in the SimpleSAMLphp distribution): Obtain and install a new one.
+3. Make sure you have installed the latest security upgrades for your OS.
+4. Make sure to use HTTPS rather than HTTP.
+5. Block access to your servers on anything except port 443. SimpleSAMLphp only uses plain HTTP(S), so there is no need to open ports for SOAP or other communication.
 
 ## Error handling, error reporting and metadata reporting
 
 SimpleSAMLphp supports allowing the user when encountering errors to send an e-mail to the administrator. You can turn off this feature in the config.php file.
 
-
 ## Multi-language support
 
 To add support for a new language, add your new language to the `language.available` configuration parameter in `config.php`:
 
-	/*
-	 * Languages available and which language is default
-	 */
-	'language.available' => ['en', 'no', 'da', 'es', 'xx'],
-	'language.default'   => 'en',
+```php
+/*
+ * Languages available and which language is default
+ */
+'language.available' => ['en', 'no', 'da', 'es', 'xx'],
+'language.default'   => 'en',
+```
 
 Please use the standardized two-character
 [language codes as specified in ISO-639-1](http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes).
@@ -259,11 +271,13 @@ You also can set the default language. You should ensure that the default langua
 
 All strings that can be localized are found in the files `dictionaries/`. Add a new entry for each string, with your language code, like this:
 
-    'user_pass_header' => [
-        'en' => 'Enter your username and password',
-        'no' => 'Skriv inn brukernavn og passord',
-        'xx' => 'Pooa jujjique jamba',
-      ],
+```php
+'user_pass_header' => [
+    'en' => 'Enter your username and password',
+    'no' => 'Skriv inn brukernavn og passord',
+    'xx' => 'Pooa jujjique jamba',
+],
+```
 
 You can translate as many of the texts as you would like; a full translation is not required unless you want to make this the default language. From the end users point of view, it looks best if all text fragments used in a given screen or form is in one single language.
 
@@ -271,12 +285,10 @@ You can translate as many of the texts as you would like; a full translation is
 
 Documentation on theming is moved [to a separate document](simplesamlphp-theming).
 
-
-Support
--------
+### Support
 
 If you need help to make this work, or want to discuss SimpleSAMLphp with other users of the software, you are fortunate: Around SimpleSAMLphp there is a great Open source community, and you are welcome to join! The forums are open for you to ask questions, contribute answers other further questions, request improvements or contribute with code or plugins of your own.
 
--  [SimpleSAMLphp homepage](https://simplesamlphp.org)
--  [List of all available SimpleSAMLphp documentation](http://simplesamlphp.org/docs/)
--  [Join the SimpleSAMLphp user's mailing list](https://simplesamlphp.org/lists)
+* [SimpleSAMLphp homepage](https://simplesamlphp.org)
+* [List of all available SimpleSAMLphp documentation](http://simplesamlphp.org/docs/)
+* [Join the SimpleSAMLphp user's mailing list](https://simplesamlphp.org/lists)
diff --git a/docs/simplesamlphp-metadata-endpoints.md b/docs/simplesamlphp-metadata-endpoints.md
index aeeff30bf280d332ac51573b13c0812876e672ba..8e65dd50ce81b148ea048e0a962e46096f064efe 100644
--- a/docs/simplesamlphp-metadata-endpoints.md
+++ b/docs/simplesamlphp-metadata-endpoints.md
@@ -12,13 +12,11 @@ Endpoint                       | Indexed | Default binding
 `SingleLogoutService`          | N       | HTTP-Redirect
 `SingleSignOnService`          | N       | HTTP-Redirect
 
-
 The various endpoints can be specified in three different ways:
 
-  * A single string.
-  * Array of strings.
-  * Array of arrays.
-
+* A single string.
+* Array of strings.
+* Array of arrays.
 
 A single string
 ---------------
@@ -28,7 +26,6 @@ A single string
 This is the simplest endpoint format.
 It can be used when there is only a single endpoint that uses the default binding.
 
-
 Array of strings
 ----------------
 
@@ -39,7 +36,6 @@ Array of strings
 
 This endpoint format can be used to represent multiple endpoints, all of which use the default binding.
 
-
 Array of arrays
 ---------------
 
@@ -67,4 +63,3 @@ It can also be used to specify the ResponseLocation attribute on endpoints, e.g.
             'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
         ],
     ],
-
diff --git a/docs/simplesamlphp-metadata-extensions-attributes.md b/docs/simplesamlphp-metadata-extensions-attributes.md
index 716580c033ddc42d16e3dfb022bae3f541919958..4e75bbd3b382c521d2d24aa6f140ed5b76be8088 100644
--- a/docs/simplesamlphp-metadata-extensions-attributes.md
+++ b/docs/simplesamlphp-metadata-extensions-attributes.md
@@ -15,10 +15,10 @@ An example of this is:
     <?php
     $metadata['entity-id-1'] = [
         /* ... */
-		'EntityAttributes' => [
-			'urn:simplesamlphp:v1:simplesamlphp' => ['is', 'really', 'cool'],
-			'{urn:simplesamlphp:v1}foo'          => ['bar'],
-		],
+        'EntityAttributes' => [
+            'urn:simplesamlphp:v1:simplesamlphp' => ['is', 'really', 'cool'],
+            '{urn:simplesamlphp:v1}foo'          => ['bar'],
+        ],
         /* ... */
     ];
 
@@ -37,9 +37,9 @@ metadata. Each item in the `EntityAttributes` array defines a new
 array. Each item in this array produces a separate `<AttributeValue>`
 element within the `<Attribute>` element.
 
-		'EntityAttributes' => [
-			'urn:simplesamlphp:v1:simplesamlphp' => ['is', 'really', 'cool'],
-		],
+    'EntityAttributes' => [
+        'urn:simplesamlphp:v1:simplesamlphp' => ['is', 'really', 'cool'],
+    ],
 
 This generates:
 
@@ -52,9 +52,9 @@ This generates:
 Each `<Attribute>` element requires a `NameFormat` attribute. This is
 specified using curly braces at the beginning of the key name:
 
-		'EntityAttributes' => [
-			'{urn:simplesamlphp:v1}foo' => ['bar'],
-		],
+    'EntityAttributes' => [
+        '{urn:simplesamlphp:v1}foo' => ['bar'],
+    ],
 
 This generates:
 
@@ -76,34 +76,33 @@ If given the following configuration...
         'privatekey' => 'example.com.pem',
         'auth' => 'example-userpass',
 
-		'EntityAttributes' => [
-			'urn:simplesamlphp:v1:simplesamlphp' => ['is', 'really', 'cool'],
-			'{urn:simplesamlphp:v1}foo'          => ['bar'],
-		],
-	];
+        'EntityAttributes' => [
+            'urn:simplesamlphp:v1:simplesamlphp' => ['is', 'really', 'cool'],
+            '{urn:simplesamlphp:v1}foo' => ['bar'],
+        ],
+    ];
 
 ... will generate the following XML metadata:
 
-	<?xml version="1.0"?>
-	<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:mdattr="urn:oasis:names:tc:SAML:metadata:attribute" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mdui="urn:oasis:names:tc:SAML:metadata:ui" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" entityID="https://example.com/saml-idp">
-	  <md:Extensions>
-		<mdattr:EntityAttributes xmlns:mdattr="urn:oasis:names:tc:SAML:metadata:attribute">
-		  <saml:Attribute xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" Name="urn:simplesamlphp:v1:simplesamlphp" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
-			<saml:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string">is</saml:AttributeValue>
-			<saml:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string">really</saml:AttributeValue>
-			<saml:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string">cool</saml:AttributeValue>
-		  </saml:Attribute>
-		  <saml:Attribute xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" Name="foo" NameFormat="urn:simplesamlphp:v1">
-			<saml:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string">bar</saml:AttributeValue>
-		  </saml:Attribute>
-		</mdattr:EntityAttributes>
-	  </md:Extensions>
-	  <md:IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
-		<md:KeyDescriptor use="signing">
-		  <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
-			<ds:X509Data>
-            ...
-
+    <?xml version="1.0"?>
+    <md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:mdattr="urn:oasis:names:tc:SAML:metadata:attribute" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mdui="urn:oasis:names:tc:SAML:metadata:ui" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" entityID="https://example.com/saml-idp">
+      <md:Extensions>
+        <mdattr:EntityAttributes xmlns:mdattr="urn:oasis:names:tc:SAML:metadata:attribute">
+          <saml:Attribute xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" Name="urn:simplesamlphp:v1:simplesamlphp" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+            <saml:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string">is</saml:AttributeValue>
+            <saml:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string">really</saml:AttributeValue>
+            <saml:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string">cool</saml:AttributeValue>
+          </saml:Attribute>
+          <saml:Attribute xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" Name="foo" NameFormat="urn:simplesamlphp:v1">
+            <saml:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string">bar</saml:AttributeValue>
+          </saml:Attribute>
+        </mdattr:EntityAttributes>
+      </md:Extensions>
+      <md:IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
+        <md:KeyDescriptor use="signing">
+          <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+            <ds:X509Data>
+              ...
 
 An example configuration to declare GĂ©ant Data Protection Code of Conduct
 entity category support for a service provider in `authsources.php`:
diff --git a/docs/simplesamlphp-metadata-extensions-rpi.md b/docs/simplesamlphp-metadata-extensions-rpi.md
index 9b45c5a79dbb7a38648058372a5588dc53ff1371..bf136709e5178051b360c27d3bd4f524f9a5ea08 100644
--- a/docs/simplesamlphp-metadata-extensions-rpi.md
+++ b/docs/simplesamlphp-metadata-extensions-rpi.md
@@ -7,7 +7,7 @@ SAML V2.0 Metadata Extensions for Registration and Publication Information
     http://daringfireball.net/projects/markdown/syntax
 -->
 
-  * Author: Jaime Perez [jaime.perez@uninett.no](mailto:jaime.perez@uninett.no)
+* Author: Jaime Perez [jaime.perez@uninett.no](mailto:jaime.perez@uninett.no)
 
 [TOC]
 
@@ -19,19 +19,19 @@ This extension aims to provide information about the registrars and publishers o
 available through different endpoints and modules that provide metadata all along SimpleSAMLphp. More specifically, this
 extension can be used for:
 
-- metadata published for a [hosted service provider](./saml:sp).
-- metadata published for a [hosted identity provider](./simplesamlphp-reference-idp-hosted).
-- metadata collected and published by means of the [`aggregator`](./aggregator:aggregator) or [`aggregator2`](./aggregator2:aggregator2) modules.
+* metadata published for a [hosted service provider](./saml:sp).
+* metadata published for a [hosted identity provider](./simplesamlphp-reference-idp-hosted).
+* metadata collected and published by means of the [`aggregator`](./aggregator:aggregator) or [`aggregator2`](./aggregator2:aggregator2) modules.
 
 Currently, only the `<mdrpi:RegistrationInfo>` element is supported.
 
 Depending on the metadata set you want to add this extension to, you will have to configure it on the corresponding
 configuration file:
 
-- `metadata/saml20-idp-hosted.php` for hosted identity providers.
-- `config/authsources.php` for hosted service providers.
-- `config/module_aggregator.php` for the `aggregator` module.
-- `config/module_aggregator2.php` for the `aggregator2` module.
+* `metadata/saml20-idp-hosted.php` for hosted identity providers.
+* `config/authsources.php` for hosted service providers.
+* `config/module_aggregator.php` for the `aggregator` module.
+* `config/module_aggregator2.php` for the `aggregator2` module.
 
 RegistrationInfo Items
 ----------------------
@@ -53,7 +53,6 @@ The configuration is the same for all the different files, and consists of a sin
     index must be the language code corresponding to the language of the URL. This parameter is optional, and will be omitted in the
     resulting metadata if not configured.
 
-
 Examples
 --------
 
diff --git a/docs/simplesamlphp-metadata-extensions-ui.md b/docs/simplesamlphp-metadata-extensions-ui.md
index 2d131609e6609bc66cffad096667d0690c2f8817..fb5f983230979ab56f47698cee63c881e8fd6b33 100644
--- a/docs/simplesamlphp-metadata-extensions-ui.md
+++ b/docs/simplesamlphp-metadata-extensions-ui.md
@@ -195,7 +195,6 @@ key.
 
             'GeolocationHint' => ['geo:47.37328,8.531126', 'geo:19.34343,12.342514'],
 
-
 Generated XML Metadata Examples
 ----------------
 
@@ -281,4 +280,3 @@ If given the following configuration...
           <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
             <ds:X509Data>
             ...
-
diff --git a/docs/simplesamlphp-metadata-pdostoragehandler.md b/docs/simplesamlphp-metadata-pdostoragehandler.md
index 54d711643b5ac25a0fc75b3b2fac4a9ab1bfcbcb..84598063369bf9c1a517a9277cfaa8e8b492c228 100644
--- a/docs/simplesamlphp-metadata-pdostoragehandler.md
+++ b/docs/simplesamlphp-metadata-pdostoragehandler.md
@@ -7,7 +7,6 @@ PDO Metadata Storage Handler
 	http://daringfireball.net/projects/markdown/syntax
 -->
 
-
 [TOC]
 
 Introduction
@@ -17,42 +16,40 @@ If you want to run a clustered SimpleSAMLphp IdP service and you would like to h
 
 The present document explains how to configure SimpleSAMLphp and your database.
 
-
-
 Preparations
 ------------
 
 You will need to have the appropriate PDO drivers for your database and you will have to configure the database section within the config/config.php file.
 
-
-
 Configuring SimpleSAMLphp
 -----------------------------
 
 You will first need to configure a PDO metadata source.
 
-	[root@simplesamlphp simplesamlphp]# vi config/config.php
+```bash
+[root@simplesamlphp simplesamlphp]# vi config/config.php
+```
 
 Here is an example of flatfile plus PDO:
 
-	'metadata.sources' => [
-		['type' => 'flatfile'],
-		['type' => 'pdo'],
-	],
-
-
+```php
+'metadata.sources' => [
+    ['type' => 'flatfile'],
+    ['type' => 'pdo'],
+],
+```
 
 Initializing the Database
 -------------------------
 
-
 Once you have configured your metadata sources to include a PDO source, you will need to initialize the database. This process will create tables in the database for each type of metadata set (saml20-idp-hosted, saml20-idp-remote, saml20-sp-remote, etc).
 
-	[root@simplesamlphp simplesamlphp]# php bin/initMDSPdo.php
+```bash
+[root@simplesamlphp simplesamlphp]# php bin/initMDSPdo.php
+```
 
 If you connect to your database, you will see 11 new empty tables; one for each metadata set.
 
-
 Adding Metadata
 ---------------
 
@@ -68,12 +65,14 @@ Another example is the saml20_idp_remote table:
 
 entity_id                | entity_data
 -------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-https://openidp.feide.no | {"name":{"en":"Feide OpenIdP - guest users","no":"Feide Gjestebrukere"},"description":"Here you can login with your account on Feide RnD OpenID. If you do not already have an account on this identity provider, you can create a new one by following the create new account link and follow the instructions.","SingleSignOnService":"https:\/\/openidp.feide.no\/simplesaml\/saml2\/idp\/SSOService.php","SingleLogoutService":"https:\/\/openidp.feide.no\/simplesaml\/saml2\/idp\/SingleLogoutService.php","certFingerprint":"c9ed4dfb07caf13fc21e0fec1572047eb8a7a4cb"}
+`https://openidp.feide.no` | {"name":{"en":"Feide OpenIdP - guest users","no":"Feide Gjestebrukere"},"description":"Here you can login with your account on Feide RnD OpenID. If you do not already have an account on this identity provider, you can create a new one by following the create new account link and follow the instructions.","SingleSignOnService":"https:\/\/openidp.feide.no\/simplesaml\/saml2\/idp\/SSOService.php","SingleLogoutService":"https:\/\/openidp.feide.no\/simplesaml\/saml2\/idp\/SingleLogoutService.php","certFingerprint":"c9ed4dfb07caf13fc21e0fec1572047eb8a7a4cb"}
 
 There is an included script in the `bin` directory that will import all flatfile metadata files and store them in the database, but you can use an external tool to maintain the metadata in the database. This document will only cover adding metadata using the included utility, but the tables above should provide enough information if you would like to create a utility to manage your metadata externally.
 
 To import all flatfile metadata files into the PDO database, run the following script
 
-	[root@simplesamlphp simplesamlphp]# php bin/importPdoMetadata.php
+```bash
+[root@simplesamlphp simplesamlphp]# php bin/importPdoMetadata.php
+```
 
 In the event that you import a metadata for an entity id that already exists in the database, it will be overwritten.
diff --git a/docs/simplesamlphp-modules.md b/docs/simplesamlphp-modules.md
index a07e2384d62b62cbeccccd6179bd2cb165fa5147..c302b530d8df33fa81754a1b8e920e8efb61e9a0 100644
--- a/docs/simplesamlphp-modules.md
+++ b/docs/simplesamlphp-modules.md
@@ -1,5 +1,4 @@
-SimpleSAMLphp modules
-==================================================
+# SimpleSAMLphp modules
 
 <!-- 
 	This file is written in Markdown syntax. 
@@ -7,38 +6,35 @@ SimpleSAMLphp modules
 	http://daringfireball.net/projects/markdown/syntax
 -->
 
-
 [TOC]
 
 This document describes how the module system in SimpleSAMLphp
 works. It describes what types of modules there are, how they are
 configured, and how to write new modules.
 
-Overview
---------
+## Overview
 
-There are currently three parts of SimpleSAMLphp which can be stored in 
-modules - authentication sources, authentication processing filters and 
-themes. There is also support for defining hooks - functions run at 
-specific times. More than one thing can be stored in a single module. 
-There is also support for storing supporting files, such as templates 
+There are currently three parts of SimpleSAMLphp which can be stored in
+modules - authentication sources, authentication processing filters and
+themes. There is also support for defining hooks - functions run at
+specific times. More than one thing can be stored in a single module.
+There is also support for storing supporting files, such as templates
 and dictionaries, in modules.
 
-The different functionalities which can be created as modules will be 
-described in more detail in the following sections; what follows is a 
+The different functionalities which can be created as modules will be
+described in more detail in the following sections; what follows is a
 short introduction to what you can do with them:
 
- - Authentication sources implement different methods for 
-   authenticating users, for example simple login forms which 
-   authenticate against a database backend, or login methods which use 
-   client-side certificates. 
- - Authentication processing filters perform various tasks after the 
-   user is authenticated and has a set of attributes. They can add, 
-   remove and modify attributes, do additional authentication checks, 
-   ask questions of the user, +++. 
- - Themes allow you to package custom templates for multiple modules 
-   into a single module.
-
+- Authentication sources implement different methods for
+  authenticating users, for example simple login forms which
+  authenticate against a database backend, or login methods which use
+  client-side certificates.
+- Authentication processing filters perform various tasks after the
+  user is authenticated and has a set of attributes. They can add,
+  remove and modify attributes, do additional authentication checks,
+  ask questions of the user, +++.
+- Themes allow you to package custom templates for multiple modules
+  into a single module.
 
 ## Module layout
 
@@ -119,93 +115,87 @@ www
     This function will then return a URL to the given file in the
     `www`-directory of `module`.
 
-
 ## Authentication sources
 
-An authentication source is used to authenticate a user and receive a 
-set of attributes belonging to this user. In a single-signon setup, the 
-authentication source will only be called once, and the attributes 
+An authentication source is used to authenticate a user and receive a
+set of attributes belonging to this user. In a single-signon setup, the
+authentication source will only be called once, and the attributes
 belonging to the user will be cached until the user logs out.
 
-Authentication sources are defined in `config/authsources.php`. This 
-file contains an array of `name => configuration` pairs. The name is 
-used to refer to the authentication source in metadata. When 
-configuring an IdP to authenticate against an authentication source, 
-\the `auth` option should be set to this name. The configuration for an 
-authentication source is an array. The first element in the array 
-identifies the class which implements the authentication source. The 
-remaining elements in the array are configuration entries for the 
+Authentication sources are defined in `config/authsources.php`. This
+file contains an array of `name => configuration` pairs. The name is
+used to refer to the authentication source in metadata. When
+configuring an IdP to authenticate against an authentication source,
+\the `auth` option should be set to this name. The configuration for an
+authentication source is an array. The first element in the array
+identifies the class which implements the authentication source. The
+remaining elements in the array are configuration entries for the
 authentication source.
 
-A typical configuration entry for an authentication source looks like 
+A typical configuration entry for an authentication source looks like
 this:
 
     'example-static' => [
-      /* This maps to modules/exampleauth/lib/Auth/Source/Static.php */
-      'exampleauth:StaticSource',
+        /* This maps to modules/exampleauth/lib/Auth/Source/Static.php */
+        'exampleauth:StaticSource',
     
-      /* The following is configuration which is passed on to
-       * the exampleauth:StaticSource authentication source. */
-      'uid' => 'testuser',
-      'eduPersonAffiliation' => ['member', 'employee'],
-      'cn' => ['Test User'],
+        /* The following is configuration which is passed on to
+         * the exampleauth:StaticSource authentication source. */
+        'uid' => 'testuser',
+        'eduPersonAffiliation' => ['member', 'employee'],
+        'cn' => ['Test User'],
     ],
 
 To use this authentication source in a SAML 2.0 IdP, set the
 `auth`-option of the IdP to `'example-static'`:
 
     'https://example.org/saml-idp' => [
-      'host' => '__DEFAULT__',
-      'privatekey' => 'example.org.pem',
-      'certificate' => 'example.org.crt',
-      'auth' => 'example-static',
+        'host' => '__DEFAULT__',
+        'privatekey' => 'example.org.pem',
+        'certificate' => 'example.org.crt',
+        'auth' => 'example-static',
     ],
 
 ### Creating authentication sources
 
 This is described in a separate document:
 
-  * [Creating authentication sources](simplesamlphp-authsource)
-
+- [Creating authentication sources](simplesamlphp-authsource)
 
-Authentication processing filters
----------------------------------
+## Authentication processing filters
 
 *Authentication processing filters* is explained in a separate document:
 
-  * [Authentication processing filters](simplesamlphp-authproc)
-
-
+- [Authentication processing filters](simplesamlphp-authproc)
 
 ## Themes
 
-This feature allows you to collect all your custom templates in one 
-place. The directory structure is like this: 
-`modules/<thememodule>/themes/<theme>/<module>/<template>` 
-`thememodule` is the module where you store your theme, while `theme` 
-is the name of the theme. A theme is activated by setting the 
-`theme.use` configuration option to `<thememodule>:<theme>`. `module` 
-is the module the template belongs to, and `template` is the template 
+This feature allows you to collect all your custom templates in one
+place. The directory structure is like this:
+`modules/<thememodule>/themes/<theme>/<module>/<template>`
+`thememodule` is the module where you store your theme, while `theme`
+is the name of the theme. A theme is activated by setting the
+`theme.use` configuration option to `<thememodule>:<theme>`. `module`
+is the module the template belongs to, and `template` is the template
 in that module.
 
-For example, `modules/example/themes/test/core/loginuserpass.php` 
-replaces `modules/core/templates/default/loginuserpass.php`. 
-`modules/example/themes/test/default/frontpage.php` replaces 
-`templates/default/frontpage.php`. This theme can be activated by 
+For example, `modules/example/themes/test/core/loginuserpass.php`
+replaces `modules/core/templates/default/loginuserpass.php`.
+`modules/example/themes/test/default/frontpage.php` replaces
+`templates/default/frontpage.php`. This theme can be activated by
 setting `theme.use` to `example:test`.
 
 ## Hook interface
 
-The hook interface allows you to call a hook function in all enabled 
-modules which define that hook. Hook functions are stored in a 
-directory called 'hooks' in each module directory. Each hook is 
-stored in a file named `hook_<hook name>.php`, and each file defines a 
+The hook interface allows you to call a hook function in all enabled
+modules which define that hook. Hook functions are stored in a
+directory called 'hooks' in each module directory. Each hook is
+stored in a file named `hook_<hook name>.php`, and each file defines a
 function named `<module name>_hook_<hook name>`.
 
-Each hook function accepts a single argument. This argument will be 
+Each hook function accepts a single argument. This argument will be
 passed by reference, which allows each hook to update that argument.
 
 For an example of hook usage, see the cron module, which adds a link
 to its information page in the Configuration section of the admin
 module, through the file `modules/cron/hooks/hook_configpage.php`.
-
diff --git a/docs/simplesamlphp-nostate.md b/docs/simplesamlphp-nostate.md
index d5b8196d78f702433354715d8f769dfde6f56174..c7315ac3a0a075b8b92c0c687b4c11fe79524dd9 100644
--- a/docs/simplesamlphp-nostate.md
+++ b/docs/simplesamlphp-nostate.md
@@ -1,5 +1,4 @@
-Debugging "State Information Lost" errors
-=========================================
+# Debugging "State Information Lost" errors
 
 **"State Information Lost"** (`\SimpleSAML\Error\NoState: NOSTATE`)
 
@@ -10,8 +9,7 @@ actually means, and some of the situations that can cause it.
 
 [TOC]
 
-What is "state information"?
-----------------------------
+## What is "state information"?
 
 The "state information" is data that SimpleSAMLphp stores in association with a
 request. The request is typically a SAML 2.0 authentication request sent to
@@ -21,14 +19,12 @@ This state information is given a random ID, e.g.
 "`_2da56e07840b59191d9797442b6b665d67d855cf77`", and is saved in the session of
 the user.
 
-What does it mean that it was lost?
------------------------------------
+## What does it mean that it was lost?
 
 This means that we tried to load state information with a specified ID, but
 were unable to find it in the session of the user.
 
-What can cause it to be lost?
------------------------------
+## What can cause it to be lost?
 
 There are several ways that this can happen, but most of them have to do
 with session storage. Here we will outline some generic alternatives, and
@@ -43,7 +39,7 @@ accessed. For example we may have the following scenario:
 1. The user accesses `https://www.example.org/`. A session is created for the user, and the session cookie is set for the current domain (www.example.org).
 1. The user needs to be authenticated. We therefore save some information about the current status in the state array, create a SAML 2.0 authentication request, and send it to the IdP.
 1. The user logs in on the IdP. The IdP then sends a response to the SP at `example.org`. However, the metadata for the SP that is registered at the IdP uses `https://example.org/` (without `www`) as the domain the response should be sent to. The authentication response is therefore sent to that domain.
-1. The SP (now at `https://example.org/`) tries to load the state information associated with the authentication response it received. But, because the domain name has changed, we do not receive the session cookie of the user. We are therefore unable to find the session of the user. When we attempt to load the state information from the session we are therefore unable to find it. 
+1. The SP (now at `https://example.org/`) tries to load the state information associated with the authentication response it received. But, because the domain name has changed, we do not receive the session cookie of the user. We are therefore unable to find the session of the user. When we attempt to load the state information from the session we are therefore unable to find it.
 
 There are several ways to solve this. One of the simplest is often to configure
 your webserver to only use one domain, and redirect all accesses to the other
@@ -55,11 +51,11 @@ change this in `php.ini`. If not, you should change it with the
 '`session.cookie.domain`' option in `config/config.php`. In either case, it should
 be set to the top-level domain with a "dot" in front of it. E.g.:
 
-	'session.cookie.domain' => '.example.org',
+    'session.cookie.domain' => '.example.org',
 
 Or in php.ini:
 
-	session.cookie_domain = ".example.org"
+    session.cookie_domain = ".example.org"
 
 Note that if you use PHP sessions, you will also have to make sure that your
 application uses the same domain when it sets the cookie. How that is done
@@ -95,7 +91,7 @@ settings used by the application:
 * `session.save_path`: This is the location the session files are saved. The default depends on your PHP installation.
 * `session.name`: This is the name of the session cookie. The default is "`PHPSESSID`".
 * `session.cookie_path`: The path that the session cookie is limited to. The default is "`/`", which means that it is available to all pages on your domain.
-* `session.cookie_domain`: This is the domain the session cookie is limited to. The default is unset, which makes the cookie available only to the current domain. 
+* `session.cookie_domain`: This is the domain the session cookie is limited to. The default is unset, which makes the cookie available only to the current domain.
 
 What those settings should be set to depends on the application. The simplest
 way to determine it may be to look for calls to `session_set_cookie_params` in
diff --git a/docs/simplesamlphp-reference-idp-hosted.md b/docs/simplesamlphp-reference-idp-hosted.md
index 0300d558e5339e9f42774e3d70a324ca89f0766f..140fefe337254542424f09eb8399f77cc2ff6860 100644
--- a/docs/simplesamlphp-reference-idp-hosted.md
+++ b/docs/simplesamlphp-reference-idp-hosted.md
@@ -1,43 +1,41 @@
-IdP hosted metadata reference
-=============================
+# IdP hosted metadata reference
 
 [TOC]
 
 This is a reference for the metadata file `metadata/saml20-idp-hosted.php`.
 Both files have the following format:
 
-    <?php
-    /* The index of the array is the entity ID of this IdP. */
-    $metadata['entity-id-1'] = [
-        'host' => 'idp.example.org',
-        /* Configuration options for the first IdP. */
-    ];
-    $metadata['entity-id-2'] = [
-        'host' => '__DEFAULT__',
-        /* Configuration options for the default IdP. */
-    ];
-    /* ... */
+```php
+<?php
+/* The index of the array is the entity ID of this IdP. */
+$metadata['entity-id-1'] = [
+    'host' => 'idp.example.org',
+    /* Configuration options for the first IdP. */
+];
+$metadata['entity-id-2'] = [
+    'host' => '__DEFAULT__',
+    /* Configuration options for the default IdP. */
+];
+/* ... */
+```
 
 The entity ID must be a URI, that is unlikely to change for technical or
 political reasons. We recommend it to be a domain name you own.
 The URL does not have to resolve to actual content, it's
 just an identifier. If your organization's domain is `example.org`:
 
-    https://example.org/saml-idp
+`https://example.org/saml-idp`
 
 For guidance in picking an entityID, see
 [InCommon's best practice](https://spaces.at.internet2.edu/display/federation/saml-metadata-entityid)
 on the matter.
 
-
 The `host` option is the hostname of the IdP, and will be used to
 select the correct configuration. One entry in the metadata-list can
 have the host `__DEFAULT__`. This entry will be used when no other
 entry matches.
 
-
-Common options
---------------
+## Common options
 
 `auth`
 :   Which authentication module should be used to authenticate users on
@@ -51,36 +49,40 @@ Common options
 :   Location of certificate data which should be used by this IdP, in PEM format.
 
 `contacts`
-:	Specify contacts in addition to the technical contact configured through config/config.php.
-	For example, specifying a support contact:
-
-		'contacts' => [
-		    [
-		        'contactType'       => 'support',
-		        'emailAddress'      => 'support@example.org',
-		        'givenName'         => 'John',
-		        'surName'           => 'Doe',
-		        'telephoneNumber'   => '+31(0)12345678',
-		        'company'           => 'Example Inc.',
-		    ],
-		],
-
-:	If you have support for a trust framework that requires extra attributes on the contact person element in your IdP metadata (for example, SIRTFI), you can specify an array of attributes on a contact.
-
-		'contacts' => [
-		    [
-		        'contactType'       => 'other',
-		        'emailAddress'      => 'mailto:abuse@example.org',
-		        'givenName'         => 'John',
-		        'surName'           => 'Doe',
-		        'telephoneNumber'   => '+31(0)12345678',
-		        'company'           => 'Example Inc.',
-		        'attributes'        => [
-		            'xmlns:remd'        => 'http://refeds.org/metadata',
-		            'remd:contactType'  => 'http://refeds.org/metadata/contactType/security',
-		        ],
-		    ],
-		],
+:   Specify contacts in addition to the technical contact configured through config/config.php.
+    For example, specifying a support contact:
+
+```php
+'contacts' => [
+    [
+        'contactType'       => 'support',
+        'emailAddress'      => 'support@example.org',
+        'givenName'         => 'John',
+        'surName'           => 'Doe',
+        'telephoneNumber'   => '+31(0)12345678',
+        'company'           => 'Example Inc.',
+    ],
+],
+```
+
+:   If you have support for a trust framework that requires extra attributes on the contact person element in your IdP metadata (for example, SIRTFI), you can specify an array of attributes on a contact.
+
+```php
+'contacts' => [
+    [
+        'contactType'       => 'other',
+        'emailAddress'      => 'mailto:abuse@example.org',
+        'givenName'         => 'John',
+        'surName'           => 'Doe',
+        'telephoneNumber'   => '+31(0)12345678',
+        'company'           => 'Example Inc.',
+        'attributes'        => [
+            'xmlns:remd'        => 'http://refeds.org/metadata',
+            'remd:contactType'  => 'http://refeds.org/metadata/contactType/security',
+        ],
+    ],
+],
+```
 
 `host`
 :   The hostname for this IdP. One IdP can also have the `host`-option
@@ -92,25 +94,27 @@ Common options
 
 `OrganizationName`, `OrganizationDisplayName`, `OrganizationURL`
 :   The name and URL of the organization responsible for this IdP.
-    You need to either specify _all three_ or none of these options.
+    You need to either specify *all three* or none of these options.
 
 :   The Name does not need to be suitable for display to end users, the DisplayName should be.
     The URL is a website the user can access for more information about the organization.
 
 :   This option can be translated into multiple languages by specifying the value as an array of language-code to translated name:
 
-        'OrganizationName' => [
-            'en' => 'Voorbeeld Organisatie Foundation b.a.',
-            'nl' => 'Stichting Voorbeeld Organisatie b.a.',
-        ],
-        'OrganizationDisplayName' => [
-            'en' => 'Example organization',
-            'nl' => 'Voorbeeldorganisatie',
-        ],
-        'OrganizationURL' => [
-            'en' => 'https://example.com',
-            'nl' => 'https://example.com/nl',
-        ],
+```php
+'OrganizationName' => [
+    'en' => 'Voorbeeld Organisatie Foundation b.a.',
+    'nl' => 'Stichting Voorbeeld Organisatie b.a.',
+],
+'OrganizationDisplayName' => [
+    'en' => 'Example organization',
+    'nl' => 'Voorbeeldorganisatie',
+],
+'OrganizationURL' => [
+    'en' => 'https://example.com',
+    'nl' => 'https://example.com/nl',
+],
+```
 
 `privatekey`
 :   Location of private key data for this IdP, in PEM format.
@@ -125,9 +129,7 @@ Common options
     A scope can either be a domain name or a regular expression
     matching a number of domains.
 
-
-SAML 2.0 options
-----------------
+## SAML 2.0 options
 
 The following SAML 2.0 options are available:
 
@@ -163,8 +165,7 @@ The following SAML 2.0 options are available:
     priority:
 
 :   1.  SP Remote Metadata
-
-    2.  IdP Hosted Metadata
+:   2.  IdP Hosted Metadata
 
 :   The default value is:
     `urn:oasis:names:tc:SAML:2.0:attrname-format:uri`
@@ -173,11 +174,9 @@ The following SAML 2.0 options are available:
     Specification:
 
 :   -   `urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified`
-
-    -   `urn:oasis:names:tc:SAML:2.0:attrname-format:uri` (The default
+:   -   `urn:oasis:names:tc:SAML:2.0:attrname-format:uri` (The default
         in Shibboleth 2.0, mandatory as per SAML2INT)
-
-    -   `urn:oasis:names:tc:SAML:2.0:attrname-format:basic` (The
+:   -   `urn:oasis:names:tc:SAML:2.0:attrname-format:basic` (The
         default in Sun Access Manager)
 
 :   You can also define your own value.
@@ -217,14 +216,13 @@ The following SAML 2.0 options are available:
     the following priority:
 
 :   1.  SP Remote Metadata
-
-    2.  IdP Hosted Metadata
+:   2.  IdP Hosted Metadata
 
 :   The three most commonly used values are:
 
 :   1.  `urn:oasis:names:tc:SAML:2.0:nameid-format:transient`
-    2.  `urn:oasis:names:tc:SAML:2.0:nameid-format:persistent`
-    3.  `urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress`
+:   2.  `urn:oasis:names:tc:SAML:2.0:nameid-format:persistent`
+:   3.  `urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress`
 
 :   The `transient` format will generate a new unique ID every time
     the user logs in.
@@ -274,12 +272,12 @@ The following SAML 2.0 options are available:
 :   The algorithm to use when signing any message generated by this identity provider. Defaults to RSA-SHA256.
 :   Possible values:
 
-    * `http://www.w3.org/2000/09/xmldsig#rsa-sha1`
-       *Note*: the use of SHA1 is **deprecated** and will be disallowed in the future.
-    * `http://www.w3.org/2001/04/xmldsig-more#rsa-sha256`
-       The default.
-    * `http://www.w3.org/2001/04/xmldsig-more#rsa-sha384`
-    * `http://www.w3.org/2001/04/xmldsig-more#rsa-sha512`
+* `http://www.w3.org/2000/09/xmldsig#rsa-sha1`
+  *Note*: the use of SHA1 is **deprecated** and will be disallowed in the future.
+* `http://www.w3.org/2001/04/xmldsig-more#rsa-sha256`
+  The default.
+* `http://www.w3.org/2001/04/xmldsig-more#rsa-sha384`
+* `http://www.w3.org/2001/04/xmldsig-more#rsa-sha512`
 
 `sign.logout`
 :   Whether to sign logout messages sent from this IdP.
@@ -299,15 +297,15 @@ The following SAML 2.0 options are available:
     page.
 
 `SingleSignOnServiceBinding`
-:	List of SingleSignOnService bindings that the IdP will claim support for.
-:	Possible values:
+:   List of SingleSignOnService bindings that the IdP will claim support for.
+:   Possible values:
 
-	* `urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect`
-	* `urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST`
+* `urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect`
+* `urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST`
 
-:	Defaults to HTTP-Redirect binding. Please note that the order
-	specified will be kept in the metadata, making the first binding
-	the default one.
+:   Defaults to HTTP-Redirect binding. Please note that the order
+    specified will be kept in the metadata, making the first binding
+    the default one.
 
 `SingleLogoutService`
 :   Override the default URL for the SingleLogoutService for this
@@ -321,22 +319,22 @@ The following SAML 2.0 options are available:
 
 `SingleLogoutServiceBinding`
 :   List of SingleLogoutService bindings the IdP will claim support for.
-:	Possible values:
+:   Possible values:
 
-	* `urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect`
-	* `urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST`
+* `urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect`
+* `urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST`
 
-:	Defaults to HTTP-Redirect binding. Please note that the order
-	specified will be kept in the metadata, making the first binding
-	the default one.
+:   Defaults to HTTP-Redirect binding. Please note that the order
+    specified will be kept in the metadata, making the first binding
+    the default one.
 
 `validate.authnrequest`
 :   Whether we require signatures on authentication requests sent to this IdP.
     Set it to:
 
-    true: authnrequest must be signed (and signature will be validated)
-    null: authnrequest may be signed, if it is, signature will be validated
-    false: authnrequest signature is never checked
+:   true: authnrequest must be signed (and signature will be validated)
+:   null: authnrequest may be signed, if it is, signature will be validated
+:   false: authnrequest signature is never checked
 
 :   Note that this option also exists in the SP-remote metadata, and
     any value in the SP-remote metadata overrides the one configured
@@ -349,7 +347,6 @@ The following SAML 2.0 options are available:
     any value in the SP-remote metadata overrides the one configured
     in the IdP metadata.
 
-
 ### Fields for signing and validating messages
 
 SimpleSAMLphp only signs authentication responses by default.
@@ -371,57 +368,57 @@ messages from that SP.
     responses received sent from this IdP should be validated. The
     default is `FALSE`
 
+**Example: Configuration for signed messages**:
 
-**Example: Configuration for signed messages**
-
-     'redirect.sign' => true,
-
+```php
+'redirect.sign' => true,
+```
 
-Metadata extensions
--------------------
+## Metadata extensions
 
 SimpleSAMLphp supports generating metadata with the MDUI, MDRPI and EntityAttributes metadata extensions.
 See the documentation for those extensions for more details:
 
-  * [MDUI extension](./simplesamlphp-metadata-extensions-ui)
-  * [MDRPI extension](./simplesamlphp-metadata-extensions-rpi)
-  * [EntityAttributes](./simplesamlphp-metadata-extensions-attributes)
+* [MDUI extension](./simplesamlphp-metadata-extensions-ui)
+* [MDRPI extension](./simplesamlphp-metadata-extensions-rpi)
+* [EntityAttributes](./simplesamlphp-metadata-extensions-attributes)
 
 For other metadata extensions, you can use the `saml:Extensions` option:
 
 `saml:Extensions`
 :   An array of `\SAML2\XML\Chunk`s to include in the IdP metadata extensions, at the same level as `EntityAttributes`.
 
-Examples
---------
+`Examples`:
 
 These are some examples of IdP metadata
 
-### Minimal SAML 2.0 IdP ###
+### Minimal SAML 2.0 IdP
 
-    <?php
+```php
+<?php
 
-    $metadata['https://example.org/saml-idp'] = [
-        /*
-         * We use '__DEFAULT__' as the hostname so we won't have to
-         * enter a hostname.
-         */
-        'host' => '__DEFAULT__',
+$metadata['https://example.org/saml-idp'] = [
+    /*
+     * We use '__DEFAULT__' as the hostname so we won't have to
+     * enter a hostname.
+     */
+    'host' => '__DEFAULT__',
 
-        /* The private key and certificate used by this IdP. */
-        'certificate' => 'example.org.crt',
-        'privatekey' => 'example.org.pem',
+    /* The private key and certificate used by this IdP. */
+    'certificate' => 'example.org.crt',
+    'privatekey' => 'example.org.pem',
 
-        /*
-         * The authentication source for this IdP. Must be one
-         * from config/authsources.php.
-         */
-        'auth' => 'example-userpass',
-    ];
+    /*
+     * The authentication source for this IdP. Must be one
+     * from config/authsources.php.
+     */
+    'auth' => 'example-userpass',
+];
+```
 
-### A custom metadata extension (eduGAIN republish request) ###
+### A custom metadata extension (eduGAIN republish request)
 
-```
+```php
 <?php
 
 $dom = \SAML2\DOMDocumentFactory::create();
@@ -445,7 +442,7 @@ $metadata['https://example.org/saml-idp'] = [
 
 this generates the following metadata:
 
-```
+```xml
 <EntityDescriptor entityID="...">
   <Extensions xmlns="urn:oasis:names:tc:SAML:2.0:metadata">
     <eduidmd:RepublishRequest xmlns:eduidmd="http://eduid.cz/schema/metadata/1.0">
diff --git a/docs/simplesamlphp-reference-idp-remote.md b/docs/simplesamlphp-reference-idp-remote.md
index 0fff6e88ceb558256e34b4d389f039eeedad2842..e4b8b09278597b17132767d4e7b45f47c29061f7 100644
--- a/docs/simplesamlphp-reference-idp-remote.md
+++ b/docs/simplesamlphp-reference-idp-remote.md
@@ -1,26 +1,25 @@
-IdP remote metadata reference
-=============================
+# IdP remote metadata reference
 
 [TOC]
 
 This is a reference for metadata options available for `metadata/saml20-idp-remote.php`. The file has the following format:
 
-    <?php
-    /* The index of the array is the entity ID of this IdP. */
-    $metadata['entity-id-1'] = [
-        /* Configuration options for the first IdP. */
-    ];
-    $metadata['entity-id-2'] = [
-        /* Configuration options for the second IdP. */
-    ];
-    /* ... */
+```php
+<?php
+/* The index of the array is the entity ID of this IdP. */
+$metadata['entity-id-1'] = [
+    /* Configuration options for the first IdP. */
+];
+$metadata['entity-id-2'] = [
+    /* Configuration options for the second IdP. */
+];
+/* ... */
+```
 
-
-Options
--------
+## Options
 
 `AuthnContextClassRef`
-:    The AuthnContextClassRef that will be sent in the login request.
+:   The AuthnContextClassRef that will be sent in the login request.
 
 :   Note that this option also exists in the SP configuration. This
     entry in the IdP-remote metadata overrides the option in the
@@ -28,12 +27,12 @@ Options
 
 `AuthnContextComparison`
 
-:    The Comparison attribute of the AuthnContext that will be sent in the login request. This parameter won't be used unless AuthnContextClassRef is set and contains one or more values. Possible values:
+:   The Comparison attribute of the AuthnContext that will be sent in the login request. This parameter won't be used unless AuthnContextClassRef is set and contains one or more values. Possible values:
 
-        SAML2\Constants::COMPARISON_EXACT (default)
-        SAML2\Constants::COMPARISON_BETTER
-        SAML2\Constants::COMPARISON_MINIMUM
-        SAML2\Constants::COMPARISON_MAXIMUM
+* SAML2\Constants::COMPARISON_EXACT (default)
+* SAML2\Constants::COMPARISON_BETTER
+* SAML2\Constants::COMPARISON_MINIMUM
+* SAML2\Constants::COMPARISON_MAXIMUM
 
 :   Note that this option also exists in the SP configuration. This
     entry in the IdP-remote metadata overrides the option in the
@@ -57,9 +56,9 @@ Options
 :   This option can be translated into multiple languages in the same way as the `name`-option.
 
 `disable_scoping`
-:    Whether sending of samlp:Scoping elements in authentication requests should be suppressed. The default value is `FALSE`.
-     When set to `TRUE`, no scoping elements will be sent. This does not comply with the SAML2 specification, but allows 
-     interoperability with ADFS which [does not support Scoping elements](https://docs.microsoft.com/en-za/azure/active-directory/develop/active-directory-single-sign-on-protocol-reference#scoping).
+:   Whether sending of samlp:Scoping elements in authentication requests should be suppressed. The default value is `FALSE`.
+    When set to `TRUE`, no scoping elements will be sent. This does not comply with the SAML2 specification, but allows
+    interoperability with ADFS which [does not support Scoping elements](https://docs.microsoft.com/en-za/azure/active-directory/develop/active-directory-single-sign-on-protocol-reference#scoping).
 
 :   Note that this option also exists in the SP configuration. This
     entry in the IdP-remote metadata overrides the option in the
@@ -81,7 +80,6 @@ Options
 `hide.from.discovery`
 :   Whether to hide hide this IdP from the local discovery or not. Set to true to hide it. Defaults to false.
 
-
 `icon`
 :   A logo which will be shown next to this IdP in the discovery service.
 
@@ -95,10 +93,12 @@ Options
 
 :   This option can be translated into multiple languages by specifying the value as an array of language-code to translated name:
 
-        'name' => [
-            'en' => 'A service',
-            'no' => 'En tjeneste',
-        ],
+```php
+'name' => [
+    'en' => 'A service',
+    'no' => 'En tjeneste',
+],
+```
 
 `nameid.encryption`
 :   Whether NameIDs sent to this IdP should be encrypted. The default
@@ -123,10 +123,12 @@ Options
 
 :   This option can be translated into multiple languages by specifying the value as an array of language-code to translated name:
 
-        'OrganizationName' => [
-            'en' => 'Example organization',
-            'no' => 'Eksempel organisation',
-        ],
+```php
+'OrganizationName' => [
+   'en' => 'Example organization',
+    'no' => 'Eksempel organisation',
+],
+```
 
 :   *Note*: If you specify this option, you must also specify the `OrganizationURL` option.
 
@@ -160,12 +162,12 @@ Options
     This value in the IdP remote metadata overrides the value in the SP configuration.
 :   Possible values:
 
-    * `http://www.w3.org/2000/09/xmldsig#rsa-sha1`
-       *Note*: the use of SHA1 is **deprecated** and will be disallowed in the future.
-    * `http://www.w3.org/2001/04/xmldsig-more#rsa-sha256`
-      The default.
-    * `http://www.w3.org/2001/04/xmldsig-more#rsa-sha384`
-    * `http://www.w3.org/2001/04/xmldsig-more#rsa-sha512`
+* `http://www.w3.org/2000/09/xmldsig#rsa-sha1`
+  *Note*: the use of SHA1 is **deprecated** and will be disallowed in the future.
+* `http://www.w3.org/2001/04/xmldsig-more#rsa-sha256`
+  The default.
+* `http://www.w3.org/2001/04/xmldsig-more#rsa-sha384`
+* `http://www.w3.org/2001/04/xmldsig-more#rsa-sha512`
 
 `sign.authnrequest`
 :   Whether to sign authentication requests sent to this IdP.
@@ -201,7 +203,6 @@ Options
 :   Note that this option also exists in the SP configuration.
     This value in the IdP remote metadata overrides the value in the SP configuration.
 
-
 ### Decrypting assertions
 
 It is possible to decrypt the assertions received from an IdP. Currently the only algorithm supported is `AES128_CBC` or `RIJNDAEL_128`.
@@ -221,12 +222,12 @@ There are two modes of encryption supported by SimpleSAMLphp. One is symmetric e
 `sharedkey_algorithm`
 :   Algorithm which should be used for decryption. Possible values are:
 
-    * http://www.w3.org/2001/04/xmlenc#aes128-cbc
-    * http://www.w3.org/2001/04/xmlenc#aes192-cbc
-    * http://www.w3.org/2001/04/xmlenc#aes256-cbc
-    * http://www.w3.org/2009/xmlenc11#aes128-gcm
-    * http://www.w3.org/2009/xmlenc11#aes192-gcm
-    * http://www.w3.org/2009/xmlenc11#aes256-gcm
+* `http://www.w3.org/2001/04/xmlenc#aes128-cbc`
+* `http://www.w3.org/2001/04/xmlenc#aes192-cbc`
+* `http://www.w3.org/2001/04/xmlenc#aes256-cbc`
+* `http://www.w3.org/2009/xmlenc11#aes128-gcm`
+* `http://www.w3.org/2009/xmlenc11#aes192-gcm`
+* `http://www.w3.org/2009/xmlenc11#aes256-gcm`
 
 ### Fields for signing and validating messages
 
@@ -238,7 +239,9 @@ SimpleSAMLphp only signs authentication responses by default. Signing of authent
 `redirect.validate`
 :   Whether logout requests and logout responses received from this IdP should be validated. The default is `FALSE`.
 
-**Example: Configuration for validating messages**
+**Example: Configuration for validating messages**:
 
-    'redirect.validate' => TRUE,
-    'certificate' => 'example.org.crt',
+```php
+'redirect.validate' => true,
+'certificate' => 'example.org.crt',
+```
diff --git a/docs/simplesamlphp-reference-sp-remote.md b/docs/simplesamlphp-reference-sp-remote.md
index 0cdf090d2967de3b57fc5195cd280836753065e8..3231b3d6317d8bb46bc376b04fb2ab60107b2b5e 100644
--- a/docs/simplesamlphp-reference-sp-remote.md
+++ b/docs/simplesamlphp-reference-sp-remote.md
@@ -1,12 +1,10 @@
-SP remote metadata reference
-============================
+# SP remote metadata reference
 
 [TOC]
 
 This is a reference for metadata options available for `metadata/saml20-sp-remote.php`.
 Both files have the following format:
 
-
 ```php
 <?php
 /* The index of the array is the entity ID of this SP. */
@@ -19,9 +17,7 @@ $metadata['entity-id-2'] = [
 /* ... */
 ```
 
-
-Common options
---------------
+## Common options
 
 The following options can be set:
 
@@ -55,10 +51,12 @@ The following options can be set:
 :   This option can be translated into multiple languages by specifying
     the value as an array of language-code to translated name:
 
-        'name' => [
-            'en' => 'A service',
-            'no' => 'En tjeneste',
-        ],
+```php
+'name' => [
+    'en' => 'A service',
+    'no' => 'En tjeneste',
+],
+```
 
 `OrganizationName`
 :   The name of the organization responsible for this SPP.
@@ -66,10 +64,12 @@ The following options can be set:
 
 :   This option can be translated into multiple languages by specifying the value as an array of language-code to translated name:
 
-        'OrganizationName' => [
-            'en' => 'Example organization',
-            'no' => 'Eksempel organisation',
-        ],
+```php
+'OrganizationName' => [
+    'en' => 'Example organization',
+    'no' => 'Eksempel organisation',
+],
+```
 
 :   *Note*: If you specify this option, you must also specify the `OrganizationURL` option.
 
@@ -138,7 +138,7 @@ The following options can be set:
     IdP-hosted metadata.
 
 `audience`
-:   An array of additional entities to be added to the AudienceRestriction. By default the only audience is the SP's entityID. 
+:   An array of additional entities to be added to the AudienceRestriction. By default the only audience is the SP's entityID.
 
 `certData`
 :   The base64 encoded certificate for this SP. This is an alternative to storing the certificate in a file on disk and specifying the filename in the `certificate`-option.
@@ -213,12 +213,12 @@ The following options can be set:
     The value in the SP-remote metadata overrides the value in the IdP-hosted metadata.
 :   Possible values:
 
-:    * `http://www.w3.org/2000/09/xmldsig#rsa-sha1`
-       *Note*: the use of SHA1 is **deprecated** and will be disallowed in the future.
-:    * `http://www.w3.org/2001/04/xmldsig-more#rsa-sha256`
-      The default.
-:    * `http://www.w3.org/2001/04/xmldsig-more#rsa-sha384`
-:    * `http://www.w3.org/2001/04/xmldsig-more#rsa-sha512`
+* `http://www.w3.org/2000/09/xmldsig#rsa-sha1`
+  *Note*: the use of SHA1 is **deprecated** and will be disallowed in the future.
+* `http://www.w3.org/2001/04/xmldsig-more#rsa-sha256`
+  The default.
+* `http://www.w3.org/2001/04/xmldsig-more#rsa-sha384`
+* `http://www.w3.org/2001/04/xmldsig-more#rsa-sha512`
 
 `signature.privatekey`
 :   Location of private key data for this IdP, in PEM format.
@@ -280,7 +280,7 @@ The following options can be set:
 :   Whether to skip validating that the AssertionConsumerServiceURL sent in authentication
     requests exist in SP metadata.  Only allowed for signed requests.
     This option must be a simple boolean (true/false - although a value of false essentially has
-    no effect) or a callable.  When used as a callable, the static class method must accept the 
+    no effect) or a callable.  When used as a callable, the static class method must accept the
     SP metadata config as a parameter and return a boolean.
 
 ### Encrypting assertions
@@ -310,12 +310,12 @@ of the SP.
 `sharedkey_algorithm`
 :   Algorithm which should be used for encryption. Possible values are:
 
-:    * `http://www.w3.org/2001/04/xmlenc#aes128-cbc`
-:    * `http://www.w3.org/2001/04/xmlenc#aes192-cbc`
-:    * `http://www.w3.org/2001/04/xmlenc#aes256-cbc`
-:    * `http://www.w3.org/2009/xmlenc11#aes128-gcm`
-:    * `http://www.w3.org/2009/xmlenc11#aes192-gcm`
-:    * `http://www.w3.org/2009/xmlenc11#aes256-gcm`
+* `http://www.w3.org/2001/04/xmlenc#aes128-cbc`
+* `http://www.w3.org/2001/04/xmlenc#aes192-cbc`
+* `http://www.w3.org/2001/04/xmlenc#aes256-cbc`
+* `http://www.w3.org/2009/xmlenc11#aes128-gcm`
+* `http://www.w3.org/2009/xmlenc11#aes192-gcm`
+* `http://www.w3.org/2009/xmlenc11#aes256-gcm`
 
 ### Fields for signing and validating messages
 
@@ -335,10 +335,12 @@ These options overrides the options set in `saml20-idp-hosted`.
     responses received from this SP should be validated. The default is
     `FALSE`
 
-**Example: Configuration for validating messages**
+#### Example: Configuration for validating messages
 
-    'redirect.validate' => TRUE,
-    'certificate' => 'example.org.crt',
+```php
+'redirect.validate' => true,
+'certificate' => 'example.org.crt',
+```
 
 ### Fields for scoping
 
@@ -350,7 +352,8 @@ sp can use.
 relevant for this SP. It will override any list set in the IdP's
 metadata.
 
-**Example: Configuration for scoping**
-
+#### Example: Configuration for scoping
 
-     'IDPList' => ['https://idp1.wayf.dk', 'https://idp2.wayf.dk'],
+```php
+'IDPList' => ['https://idp1.wayf.dk', 'https://idp2.wayf.dk'],
+```
diff --git a/docs/simplesamlphp-scoping.md b/docs/simplesamlphp-scoping.md
index 7a248b3331a3d01a51c6a4a35ab128d952310322..adb9b88998020e159862395e4ef7b4ac68360c64 100644
--- a/docs/simplesamlphp-scoping.md
+++ b/docs/simplesamlphp-scoping.md
@@ -1,5 +1,4 @@
-Scoping
-========================
+# Scoping
 
 <!-- 
     This file is written in Markdown syntax. 
@@ -7,43 +6,39 @@ Scoping
     http://daringfireball.net/projects/markdown/syntax
 -->
 
-
 [TOC]
 
 Scoping allows a service provider to specify a list of identity providers in an
-authnRequest to a proxying identity provider. This is an indication to the 
+authnRequest to a proxying identity provider. This is an indication to the
 proxying identity provider that the service will only deal with the identity
 providers specified.
 
-A common use is for a service provider in a hub-and-spoke architecture to 
-manage its own discovery service and being able to tell the hub/proxy-IdP which 
-(backend-end) identity provider to use. The standard discovery service in 
-SimpleSAMLphp will show the intersection of all the known IdPs and the IdPs 
-specified in the scoping element. If this intersection only contains one IdP, 
+A common use is for a service provider in a hub-and-spoke architecture to
+manage its own discovery service and being able to tell the hub/proxy-IdP which
+(backend-end) identity provider to use. The standard discovery service in
+SimpleSAMLphp will show the intersection of all the known IdPs and the IdPs
+specified in the scoping element. If this intersection only contains one IdP,
 then the request is automatically forwarded to that IdP.
 
 Scoping is a SAML 2.0 specific option.
 
-Options
--------
+## Options
 
 SimpleSAMLphp supports scoping by allowing the following options:
 
 `ProxyCount`
 : Specifies the number of proxying indirections permissible
-between the identity provider receiving the request and the identity provider 
-who ultimately authenticates the user. A count of zero permits no proxying. If 
+between the identity provider receiving the request and the identity provider
+who ultimately authenticates the user. A count of zero permits no proxying. If
 ProxyCount is unspecified the number of proxy indirections is not limited.
 
 `IDPList`
 : The list of trusted IdPs, i.e. the list of entityIDs for identity providers
-that are relevant for a service provider in an authnRequest. 
+that are relevant for a service provider in an authnRequest.
 
-### Note ###
-SimpleSAMLphp does not support specifying the GetComplete option.
+**Note**: SimpleSAMLphp does not support specifying the GetComplete option.
 
-Usage
------
+### Usage
 
 The ProxyCount and IDPList option can be specified in the following places:
 
@@ -64,12 +59,11 @@ Example configuration:
     # Set ProxyCount
     'ProxyCount' => 2,
 
-RequesterID element
--------------------
+## RequesterID element
 
-To allow an identity provider to identify the original requester and the 
-proxying identity providers, SimpleSAMLphp adds the RequesterID element to 
-the request and if necessary the scoping element even if explicit scoping is 
+To allow an identity provider to identify the original requester and the
+proxying identity providers, SimpleSAMLphp adds the RequesterID element to
+the request and if necessary the scoping element even if explicit scoping is
 not used.
 
 The RequesterId elements are available from the state array as an array, for
@@ -77,14 +71,13 @@ instance the authenticate method in an authentication source
 
     $requesterIDs = $state['saml:RequesterID'];
 
-AuthenticatingAuthority element
--------------------------------
+## AuthenticatingAuthority element
 
-To allow a service provider to identify the authentication authorities that 
-were involved in the authentication of the user, SimpleSAMLphp adds the 
+To allow a service provider to identify the authentication authorities that
+were involved in the authentication of the user, SimpleSAMLphp adds the
 AuthenticatingAuthority elements.
 
-The list of authenticating authorities (the AuthenticatingAuthority element) 
+The list of authenticating authorities (the AuthenticatingAuthority element)
 can be retrieved as an array from the authentication data.
 
     # Get the authentication source.
@@ -93,12 +86,10 @@ can be retrieved as an array from the authentication data.
     # Get the AuthenticatingAuthority
     $aa = $as->getAuthData('saml:AuthenticatingAuthority');
 
-Support
--------
+### Support
 
 If you need help to make this work, or want to discuss SimpleSAMLphp with other users of the software, you are fortunate: Around SimpleSAMLphp there is a great Open source community, and you are welcome to join! The forums are open for you to ask questions, contribute answers other further questions, request improvements or contribute with code or plugins of your own.
 
 - [SimpleSAMLphp homepage](https://simplesamlphp.org)
 - [List of all available SimpleSAMLphp documentation](https://simplesamlphp.org/docs/)
 - [Join the SimpleSAMLphp user's mailing list](https://simplesamlphp.org/lists)
-
diff --git a/docs/simplesamlphp-sp-api.md b/docs/simplesamlphp-sp-api.md
index c87ddeb56112ff5f36ce12f3ef14c714ee685bc8..a4ea60368664f004fff754ce40207e81fa0b82de 100644
--- a/docs/simplesamlphp-sp-api.md
+++ b/docs/simplesamlphp-sp-api.md
@@ -1,13 +1,11 @@
-SimpleSAMLphp SP API reference
-==============================
+# SimpleSAMLphp SP API reference
 
 [TOC]
 
 This document describes the \SimpleSAML\Auth\Simple API.
 This is the preferred API for integrating SimpleSAMLphp with other applications.
 
-### Note on PHP sessions and SimpleSAMLphp API calls
-
+**Note on PHP sessions and SimpleSAMLphp API calls**:
 Some SimpleSAMLphp calls replace the current active PHP session. If you previously started a session and wish to write to it, then you must cleanup the SimpleSAMLphp session before you can write to your session. If you do not need to modify your own session, then you can leave the cleanup call out; however, forgetting to call cleanup is a common source of hard to find bugs.
 
 ```php
@@ -21,8 +19,7 @@ SimpleSAML_Session::getSessionFromRequest()->cleanup(); // Reverts to our PHP se
 $_SESSION['key'] = 'value';
 ```
 
-Constructor
------------
+## Constructor
 
 ```php
 new \SimpleSAML\Auth\Simple(string $authSource)
@@ -30,19 +27,18 @@ new \SimpleSAML\Auth\Simple(string $authSource)
 
 The constructor initializes a \SimpleSAML\Auth\Simple object.
 
-### Parameters
+`Parameters`:
 
 It has a single parameter, which is the ID of the authentication source that should be used.
 This authentication source must exist in `config/authsources.php`.
 
-### Example
+`Example`:
 
 ```php
 $auth = new \SimpleSAML\Auth\Simple('default-sp');
 ```
 
-`isAuthenticated`
------------------
+### isAuthenticated
 
 ```php
 bool isAuthenticated()
@@ -51,7 +47,7 @@ bool isAuthenticated()
 Check whether the user is authenticated with this authentication source.
 `TRUE` is returned if the user is authenticated, `FALSE` if not.
 
-### Example
+`Example`:
 
 ```php
 if (!$auth->isAuthenticated()) {
@@ -61,8 +57,7 @@ if (!$auth->isAuthenticated()) {
 }
 ```
 
-`requireAuth`
--------------
+### requireAuth
 
 ```php
 void requireAuth(array $params = [])
@@ -72,13 +67,12 @@ Make sure that the user is authenticated.
 This function will only return if the user is authenticated.
 If the user isn't authenticated, this function will start the authentication process.
 
-### Parameters
+`Parameters`:
 
 `$params` is an associative array with named parameters for this function.
 See the documentation for the `login`-function for a description of the parameters.
 
-
-### Example 1
+`Example 1`:
 
 ```php
 $auth->requireAuth();
@@ -86,7 +80,7 @@ SimpleSAML_Session::getSessionFromRequest()->cleanup();
 print("Hello, authenticated user!");
 ```
 
-### Example 2
+`Example 2`:
 
 ```php
 /*
@@ -101,8 +95,7 @@ SimpleSAML_Session::getSessionFromRequest()->cleanup();
 print("Hello, authenticated user!");
 ```
 
-`login`
--------------
+### login
 
 ```php
 void login(array $params = [])
@@ -111,7 +104,7 @@ void login(array $params = [])
 Start a login operation.
 This function will always start a new authentication process.
 
-### Parameters
+`Parameters`:
 
 The following global parameters are supported:
 
@@ -135,46 +128,44 @@ The following global parameters are supported:
 
 The [`saml:SP`](./saml:sp) authentication source also defines some parameters.
 
-
-### Example
+`Example`:
 
 ```php
 # Send a passive authentication request.
 $auth->login([
-    'isPassive' => TRUE,
-     'ErrorURL' => 'https://.../error_handler.php',
- ]);
- SimpleSAML_Session::getSessionFromRequest()->cleanup();
+    'isPassive' => true,
+    'ErrorURL' => 'https://.../error_handler.php',
+]);
+SimpleSAML_Session::getSessionFromRequest()->cleanup();
 ```
 
-`logout`
---------
+### logout
 
 ```php
-void logout(mixed $params = NULL)
+void logout(mixed $params = null)
 ```
 
 Log the user out.
 After logging out, the user will either be redirected to another page, or a function will be called.
 This function never returns.
 
-### Parameters
+`Parameters`:
 
 `$params`
 :   Parameters for the logout operation.
-    This can either be a simple string, in which case it is interpreted as the URL the user should be redirected to after logout, or an associative array with logout parameters.
-    If this parameter isn't specified, we will redirect the user to the current URL after logout.
+:   This can either be a simple string, in which case it is interpreted as the URL the user should be redirected to after logout, or an associative array with logout parameters.
+:   If this parameter isn't specified, we will redirect the user to the current URL after logout.
 
-    If the parameter is an an array, it can have the following options:
+:   If the parameter is an an array, it can have the following options:
 
-    - `ReturnTo`: The URL the user should be returned to after logout.
-    - `ReturnCallback`: The function that should be called after logout.
-    - `ReturnStateParam`: The parameter we should return the state in when redirecting.
-    - `ReturnStateStage`: The stage the state array should be saved with.
+- `ReturnTo`: The URL the user should be returned to after logout.
+- `ReturnCallback`: The function that should be called after logout.
+- `ReturnStateParam`: The parameter we should return the state in when redirecting.
+- `ReturnStateStage`: The stage the state array should be saved with.
 
     The `ReturnState` parameters allow access to the result of the logout operation after it completes.
 
-### Example 1
+`Example 1`:
 
 Logout, and redirect to the specified URL.
 
@@ -183,7 +174,7 @@ $auth->logout('https://sp.example.org/logged_out.php');
 SimpleSAML_Session::getSessionFromRequest()->cleanup();
 ```
 
-### Example 2
+`Example 2`:
 
 Same as the previous, but check the result of the logout operation afterwards.
 
@@ -210,8 +201,7 @@ if ($ls['Code'] === 'urn:oasis:names:tc:SAML:2.0:status:Success' && !isset($ls['
 }
 ```
 
-`getAttributes`
----------------
+### getAttributes
 
 ```php
 array getAttributes()
@@ -229,7 +219,7 @@ The attributes will be returned as an associative array with the name of the att
 ]
 ```
 
-### Example
+`Example`:
 
 ```php
 $attrs = $auth->getAttributes();
@@ -241,8 +231,7 @@ $name = $attrs['displayName'][0];
 print('Hello, ' . htmlspecialchars($name));
 ```
 
-`getAuthData`
----------------
+### getAuthData
 
 ```php
 mixed getAuthData(string $name)
@@ -254,7 +243,7 @@ NULL is returned if the user isn't authenticated.
 The available authentication data depends on the module used for authentication.
 See the [`saml:SP`](./saml:sp) reference for information about available SAML authentication data.
 
-### Example
+`Example`:
 
 ```php
 $idp = $auth->getAuthData('saml:sp:IdP');
@@ -262,23 +251,22 @@ $nameID = $auth->getAuthData('saml:sp:NameID')->getValue();
 printf('You are %s, logged in from %s', htmlspecialchars($nameID), htmlspecialchars($idp));
 ```
 
-`getLoginURL`
--------------
+### getLoginURL
 
 ```php
-string getLoginURL(string $returnTo = NULL)
+string getLoginURL(string $returnTo = null)
 ```
 
 Retrieve a URL that can be used to start authentication.
 
-### Parameters
+`Parameters`:
 
 `$returnTo`
 
 :   The URL the user should be returned to after authentication.
     The default is the current page.
 
-### Example
+`Example`:
 
 ```php
 $url = $auth->getLoginURL();
@@ -286,17 +274,14 @@ $url = $auth->getLoginURL();
 print('<a href="' . htmlspecialchars($url) . '">Login</a>');
 ```
 
-### Note
-
+**Note**:
 The URL returned by this function is static, and will not change.
 You can easily create your own links without using this function.
 The URL should be:
 
-     .../simplesaml/module.php/core/login/<authentication source>?ReturnTo=<return URL>
+`.../simplesaml/module.php/core/login/<authentication source>?ReturnTo=<return URL>`
 
-
-`getLogoutURL`
---------------
+### getLogoutURL
 
 ```php
 string getLogoutURL(string $returnTo = NULL)
@@ -304,14 +289,14 @@ string getLogoutURL(string $returnTo = NULL)
 
 Retrieve a URL that can be used to trigger logout.
 
-### Parameters
+`Parameters`:
 
 `$returnTo`
 
 :   The URL the user should be returned to after logout.
     The default is the current page.
 
-### Example
+`Example`:
 
 ```php
 $url = $auth->getLogoutURL();
@@ -319,10 +304,9 @@ $url = $auth->getLogoutURL();
 print('<a href="' . htmlspecialchars($url) . '">Logout</a>');
 ```
 
-### Note
-
+**Note**:
 The URL returned by this function is static, and will not change.
 You can easily create your own links without using this function.
 The URL should be:
 
-     .../simplesaml/module.php/core/logout/<authentication source>?ReturnTo=<return URL>
+`.../simplesaml/module.php/core/logout/<authentication source>?ReturnTo=<return URL>`
diff --git a/docs/simplesamlphp-sp.md b/docs/simplesamlphp-sp.md
index 1b819465f3a1fb5da014b61d39a59853d7f9b2b6..a0428681d182561decf34dc29be6a0771a7f2dd7 100644
--- a/docs/simplesamlphp-sp.md
+++ b/docs/simplesamlphp-sp.md
@@ -8,8 +8,7 @@ described in the [SimpleSAMLphp installation instructions](installation).
 
 [installation]: simplesamlphp-install
 
-Configuring the SP
-------------------
+## Configuring the SP
 
 The SP is configured by an entry in `config/authsources.php`.
 
@@ -26,6 +25,7 @@ $config = [
     ],
 ];
 ```
+
 The entity ID must be a URI, that is unlikely to change for technical or
 political reasons. We recommend it to be a domain name that you own.
 Like above, if your organization's main domain is `example.org` and this SP is
@@ -80,8 +80,7 @@ Then edit your `authsources.php` entry, and add references to your certificate:
     ],
 ```
 
-Adding IdPs to the SP
----------------------
+## Adding IdPs to the SP
 
 The service provider you are configuring needs to know about the identity
 providers you are going to connect to it. This is configured by metadata
@@ -113,9 +112,7 @@ your SimpleSAMLphp installation.
 Note that the idp-remote file lists all IdPs you trust.
 You should remove all IdPs that you don't use.
 
-
-Setting the default IdP
------------------------
+## Setting the default IdP
 
 An option in the authentication source allows you to configure which IdP should
 be used. This is the `idp` option.
@@ -136,8 +133,7 @@ $config = [
 ];
 ```
 
-Exchange metadata with the IdP
-------------------------------
+## Exchange metadata with the IdP
 
 In order to complete the connection between your SP and an IdP, you must
 exchange the metadata of your SP with the IdP. The metadata of your SP can be
@@ -159,11 +155,9 @@ provide the *SAML 2.0 metadata of your SP*, and register that with the
 federation administration. You will probably be required too to consume
 the federation metadata periodically. Read more about
 [automated metadata management](/docs/contrib_modules/metarefresh/simplesamlphp-automated_metadata)
-to learn more about that. 
+to learn more about that.
 
-
-Test the SP
------------
+## Test the SP
 
 After the metadata is configured on the IdP, you should be able to test the
 configuration. The admin module of SimpleSAMLphp has a tab to test
@@ -180,8 +174,7 @@ The test page should contain a list of your attributes:
 For a better looking, more advanced Discovery Service with tabs and live
 search, you may want to use the `discopower` module.
 
-Integrating authentication with your own application
-----------------------------------------------------
+## Integrating authentication with your own application
 
 The API is documented in [the SP API reference](simplesamlphp-sp-api).
 
@@ -275,9 +268,7 @@ session_set_save_handler($handler);
 session_start();
 ```
 
-
-Support
--------
+## Support
 
 If you need help to make this work, or want to discuss SimpleSAMLphp with other
 users of the software, you are fortunate: Around SimpleSAMLphp there is a great
@@ -285,6 +276,6 @@ Open source community, and you are welcome to join! The forums are open for you
 to ask questions, contribute answers other further questions, request
 improvements or contribute with code or plugins of your own.
 
--  [SimpleSAMLphp homepage](https://simplesamlphp.org)
--  [List of all available SimpleSAMLphp documentation](https://simplesamlphp.org/docs/)
--  [Join the SimpleSAMLphp user's mailing list](https://simplesamlphp.org/lists)
+- [SimpleSAMLphp homepage](https://simplesamlphp.org)
+- [List of all available SimpleSAMLphp documentation](https://simplesamlphp.org/docs/)
+- [Join the SimpleSAMLphp user's mailing list](https://simplesamlphp.org/lists)
diff --git a/docs/simplesamlphp-theming.md b/docs/simplesamlphp-theming.md
index dee523d0adbc928f240cc0070e94adf6e62eaa9c..af53a17aa788e18d172e302d4f67c9bc4bf87eae 100644
--- a/docs/simplesamlphp-theming.md
+++ b/docs/simplesamlphp-theming.md
@@ -1,12 +1,4 @@
-Theming the user interface in SimpleSAMLphp
-===========================================
-
-<!--
-	This file is written in Markdown syntax.
-	For more information about how to use the Markdown syntax, read here:
-	http://daringfireball.net/projects/markdown/syntax
--->
-
+# Theming the user interface in SimpleSAMLphp
 
 [TOC]
 
@@ -14,9 +6,7 @@ In SimpleSAMLphp every part that needs to interact with the user by using a web
 
 You may create your own theme, where you add one or more template files that will override the default ones. This document explains how to achieve that.
 
-
-How themes work
-----------------
+## How themes work
 
 If you want to customize the UI, the right way to do that is to create a new **theme**. A theme is a set of templates that can be configured to override the default templates. Themes are a special type of SimpleSAMLphp module.
 
@@ -24,12 +14,14 @@ If you want to customize the UI, the right way to do that is to create a new **t
 
 In `config.php` there is a configuration option that controls theming. You need to set that option and enable the module that contains the theme. Here is an example:
 
-     'module.enable' => [
-         ...
-         'fancymodule' => true,
-     ],
+```php
+'module.enable' => [
+    ...
+    'fancymodule' => true,
+],
 
-     'theme.use' => 'fancymodule:fancytheme',
+'theme.use' => 'fancymodule:fancytheme',
+```
 
 The `theme.use` parameter points to which theme that will be used. If some functionality in SimpleSAMLphp needs to present UI in example with the `logout.twig` template, it will first look for `logout.twig` in the `theme.use` theme, and if not found it will all fallback to look for the base templates.
 
@@ -38,38 +30,42 @@ The `theme.use` parameter points to which theme that will be used. If some funct
 The SimpleSAMLphp templates are derived from a base template and include other templates as building blocks. You only need to override the templates or building blocks needed for your change.
 SimpleSAMLphp allows themes to override the included templates files only, if needed. That means you can create a new theme `fancytheme` that includes only a header and footer template. These templates may refer to your own CSS files, which means that a simple way of making a new look on SimpleSAMLphp is to create a new theme, and copy the existing header, but point to your own CSS instead of the default CSS. This means that for many theme requirements, you only need to specify a new header and footer template, and leave all other templates to SimpleSAMLphp's base versions.
 
-
-Creating your first theme
--------------------------
+## Creating your first theme
 
 The first thing you need to do is having a SimpleSAMLphp module to place your theme in. If you do not have a module already, create a new one:
 
-	cd modules
-	mkdir mymodule
+```bash
+cd modules
+mkdir mymodule
+```
 
-	Enable the module by setting `$config['module.enable' => ['mymodule' => true]]`
+Enable the module by setting `$config['module.enable' => ['mymodule' => true]]`
 
 Then within this module, you can create a new theme named `fancytheme`.
 
-	cd modules/mymodule
-	mkdir -p themes/fancytheme/default/
+```bash
+cd modules/mymodule
+mkdir -p themes/fancytheme/default/
+```
 
 Now, configure SimpleSAMLphp to use your new theme in `config.php`:
 
-	'theme.use' 		=> 'mymodule:fancytheme',
+```php
+'theme.use' => 'mymodule:fancytheme',
+```
 
 Next, we copy the header file from the base theme:
 
-	cp templates/_header.twig modules/mymodule/themes/fancytheme/default/
+```bash
+cp templates/_header.twig modules/mymodule/themes/fancytheme/default/
+```
 
 In the `modules/mymodule/themes/fancytheme/default/_header.twig` file, type in something and go to the SimpleSAMLphp front page to see that your new theme is in use.
 
-Adding resource files
----------------------
+## Adding resource files
 
 You can put resource files within the `www/assets` folder of your module, to make your module completely independent with included css, icons etc.
 
-```
 modules
 └───mymodule
     └───lib
@@ -78,42 +74,46 @@ modules
         └───assets
             └───logo.svg
             └───style.css
-```
 
 Reference these resources in your custom templates under `themes/fancytheme` by using a generator for the URL.
 Example for a custom CSS stylesheet file:
-```
+
+```twig
 {% block preload %}
 <link rel="stylesheet" href="{{ asset('style.css', 'mymodule') }}">
 {% endblock %}
 ```
 
-A custom theme controller
--------------------------
+## A custom theme controller
 
 If you have very specific requirements for your theme, you can define a custom theme controller
 in `config.php`:
 
-    'theme.controller' => '\SimpleSAML\Module\mymodule\FancyThemeController',
+```php
+'theme.controller' => '\SimpleSAML\Module\mymodule\FancyThemeController',
+```
 
 This requires you to implement `\SimpleSAML\XHTML\TemplateControllerInterface.php` in your module's `lib`-directory.
 The class can then modify the Twig Environment and the variables passed to the theme's templates. In short, this allows you to set additional global variables and to write your own Twig filters and functions.
 
 See the [Twig documentation](https://twig.symfony.com/doc/2.x/templates.html) for more information on using variables and expressions in Twig templates, and the SimpleSAMLphp wiki for [our conventions](https://github.com/simplesamlphp/simplesamlphp/wiki/Twig-conventions).
 
-Migrating to Twig templates
----------------------------
+## Migrating to Twig templates
 
 For existing themes that have been created before SimpleSAMLphp 2.0, you may need to upgrade them to the Twig
 templating enging to be compatible with SimpleSAMLphp 2.0.
 
 Twig works by extending a base template, which can itself include other partial templates. Some of the content of the old `includes/header.php` template is now located in a separate `_header.twig` file. This can be customized by copying it from the base template:
 
-	cp templates/_header.twig modules/mymodule/themes/fancytheme/default/
+```bash
+cp templates/_header.twig modules/mymodule/themes/fancytheme/default/
+```
 
 If you need to make more extensive customizations to the base template, you should copy it from the base theme:
 
-	cp templates/base.twig modules/mymodule/themes/fancytheme/default/
+```bash
+cp templates/base.twig modules/mymodule/themes/fancytheme/default/
+```
 
 Any references to `$this->data['baseurlpath']` in old-style templates can be replaced with `{{baseurlpath}}` in Twig templates. Likewise, references to `\SimpleSAML\Module::getModuleURL()` can be replaced with `{{baseurlpath}}module.php/mymodule/...` or the `asset()` function like shown above.
 If you want to use the `asset()` function, you need to move the asserts from `www/` to `www/assets/`.
diff --git a/docs/simplesamlphp-upgrade-notes-1.10.md b/docs/simplesamlphp-upgrade-notes-1.10.md
index 0e17ec0f11a16cea578774a693f5494c6f12147f..277a0169ef010e97cae9df65da7ad659fb61f4eb 100644
--- a/docs/simplesamlphp-upgrade-notes-1.10.md
+++ b/docs/simplesamlphp-upgrade-notes-1.10.md
@@ -1,4 +1,3 @@
-Upgrade notes for SimpleSAMLphp 1.10
-====================================
+# Upgrade notes for SimpleSAMLphp 1.10
 
-  * The default encryption key padding scheme has been changed to `http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p`. This may cause problems if the recipient of messages do not support this padding scheme.
+* The default encryption key padding scheme has been changed to `http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p`. This may cause problems if the recipient of messages do not support this padding scheme.
diff --git a/docs/simplesamlphp-upgrade-notes-1.11.md b/docs/simplesamlphp-upgrade-notes-1.11.md
index 7761eafa554c26aa5071cfca69ff3e5d61bff997..928e7a4127fd216976b32eb01131f615c6e932f2 100644
--- a/docs/simplesamlphp-upgrade-notes-1.11.md
+++ b/docs/simplesamlphp-upgrade-notes-1.11.md
@@ -1,6 +1,4 @@
-Upgrade notes for SimpleSAMLphp 1.11
-====================================
-
-  * Support for the Holder-of-Key profile in the SAML 2.0 SP has been disabled by default.
-    To enable it, set `saml20.hok.assertion` to `TRUE` in `config/authsources.php`.
+# Upgrade notes for SimpleSAMLphp 1.11
 
+* Support for the Holder-of-Key profile in the SAML 2.0 SP has been disabled by default.
+  To enable it, set `saml20.hok.assertion` to `TRUE` in `config/authsources.php`.
diff --git a/docs/simplesamlphp-upgrade-notes-1.12.md b/docs/simplesamlphp-upgrade-notes-1.12.md
index 0c645879387b0cd722320ab41ee51a06a714e074..6e110279f2dbaa2826854c28a4764f9f933a110d 100644
--- a/docs/simplesamlphp-upgrade-notes-1.12.md
+++ b/docs/simplesamlphp-upgrade-notes-1.12.md
@@ -1,4 +1,3 @@
-Upgrade notes for SimpleSAMLphp 1.12
-====================================
+# Upgrade notes for SimpleSAMLphp 1.12
 
-  * PHP version 5.3 is now required.
+* PHP version 5.3 is now required.
diff --git a/docs/simplesamlphp-upgrade-notes-1.13.md b/docs/simplesamlphp-upgrade-notes-1.13.md
index 4816c18643679d433b5afdef2f4894c61c913809..46b1e6f259da8b0d9d1e4552dc4b9d6f5110ea59 100644
--- a/docs/simplesamlphp-upgrade-notes-1.13.md
+++ b/docs/simplesamlphp-upgrade-notes-1.13.md
@@ -1,7 +1,6 @@
-Upgrade notes for SimpleSAMLphp 1.13
-====================================
+# Upgrade notes for SimpleSAMLphp 1.13
 
-  * The RSA_1.5 (RSA with PKCS#1 v1.5 padding) algorithm is now longer allowed by default. This means messages received
+* The RSA_1.5 (RSA with PKCS#1 v1.5 padding) algorithm is now longer allowed by default. This means messages received
   that use this algorithm will fail to decrypt.
-  * Several functions, classes and interfaces are now deprecated. Please check your code if you are using the API.
-  * A workaround related to performance issues when processing large metadata sets was included in **1.13.2**. **This workaround is experimental and could have unexpected side effects**.
\ No newline at end of file
+* Several functions, classes and interfaces are now deprecated. Please check your code if you are using the API.
+* A workaround related to performance issues when processing large metadata sets was included in **1.13.2**. **This workaround is experimental and could have unexpected side effects**.
diff --git a/docs/simplesamlphp-upgrade-notes-1.14.md b/docs/simplesamlphp-upgrade-notes-1.14.md
index fdabcdb247f102d9e4538295ff2d3b26b233e3c9..0d38b86c0144e710036d5c74f4affa4b30836fc3 100644
--- a/docs/simplesamlphp-upgrade-notes-1.14.md
+++ b/docs/simplesamlphp-upgrade-notes-1.14.md
@@ -1,5 +1,4 @@
-Upgrade notes for SimpleSAMLphp 1.14
-====================================
+# Upgrade notes for SimpleSAMLphp 1.14
 
 The `mcrypt` extension is no longer required by SimpleSAMLphp, so if no signatures or encryption are being used, it
 can be skipped. It is still a requirement for `xmlseclibs` though, so for those verifying or creating signed
@@ -19,7 +18,7 @@ The jQuery version in use has been bumped to the latest 1.8.X version.
 Service Providers using the eduPersonTargetedID attribute, will get a DOMNodeList object instead of the NameID value. In
 order to process the NameID, a SAML2_XML_saml_NameID object can be used:
 
-```
+```php
 $attributes = $as->getAttributes();
 $eptid = $attributes['eduPersonTargetedID'][0]->item(0);
 $nameID = new SAML2_XML_saml_NameID($eptid);
diff --git a/docs/simplesamlphp-upgrade-notes-1.15.md b/docs/simplesamlphp-upgrade-notes-1.15.md
index f540193fb4e3891b0ab1d67bfaf1d4418590ee99..17636ca52e898b8ee6fd4c04efb6f6a19e8f08a7 100644
--- a/docs/simplesamlphp-upgrade-notes-1.15.md
+++ b/docs/simplesamlphp-upgrade-notes-1.15.md
@@ -1,5 +1,4 @@
-Upgrade notes for SimpleSAMLphp 1.15
-====================================
+# Upgrade notes for SimpleSAMLphp 1.15
 
 The minimum required PHP version is now 5.4. The dependency on mcrypt has been
 dropped.
diff --git a/docs/simplesamlphp-upgrade-notes-1.16.md b/docs/simplesamlphp-upgrade-notes-1.16.md
index 50c21084e539fdc49a8f437d42e00fc8c43a5772..f4566c9b14fbce60ab89afd8b800b5d04bb10128 100644
--- a/docs/simplesamlphp-upgrade-notes-1.16.md
+++ b/docs/simplesamlphp-upgrade-notes-1.16.md
@@ -1,5 +1,4 @@
-Upgrade notes for SimpleSAMLphp 1.16
-====================================
+# Upgrade notes for SimpleSAMLphp 1.16
 
 The default signature algorithm is now SHA-256 (SHA-1 has been considered
 obsolete since 2014). For entities that need it, you can switch back to
@@ -14,12 +13,13 @@ The class `SimpleSAML_Error_BadUserInnput` has been renamed to
 `SimpleSAML_Error_BadUserInput`.
 
 The `authmyspace` module has been removed since the service is no longer
-available. 
+available.
 
 The `casserver` module has been removed because it was an outdated version,
 the up to date module is maintained in the
 [simplesamlphp-module-casserver](https://github.com/simplesamlphp/simplesamlphp-module-casserver)
 repository. It can be installed with composer:
-```
+
+```bash
 composer require simplesamlphp/simplesamlphp-module-casserver
 ```
diff --git a/docs/simplesamlphp-upgrade-notes-1.17.md b/docs/simplesamlphp-upgrade-notes-1.17.md
index 61590c25549a964336e10b35b56000364c561d7f..d7c8880957d572d44c18639076daa630dcbee160 100644
--- a/docs/simplesamlphp-upgrade-notes-1.17.md
+++ b/docs/simplesamlphp-upgrade-notes-1.17.md
@@ -1,5 +1,4 @@
-Upgrade notes for SimpleSAMLphp 1.17
-====================================
+# Upgrade notes for SimpleSAMLphp 1.17
 
 The minimum PHP version required is now PHP 5.5.
 
@@ -19,18 +18,20 @@ array syntax. This should not have an impact as both will remain working
 equally, but the code examples and config templates look slightly different.
 The following are equivalent:
 
-    // Old style array syntax
-    $config = array(
-        'authproc' => array(
-            60 => 'class:etc'
-        ),
-        'other example' => 1
-    );
+```php
+// Old style array syntax
+$config = array(
+    'authproc' => array(
+        60 => 'class:etc'
+    ),
+    'other example' => 1
+);
 
-    // Current style array syntax
-    $config = [
-        'authproc' => [
-            60 => 'class:etc'
-        ],
-        'other example' => 1
-    ];
+// Current style array syntax
+$config = [
+    'authproc' => [
+        60 => 'class:etc'
+    ],
+    'other example' => 1
+];
+```
diff --git a/docs/simplesamlphp-upgrade-notes-1.18.md b/docs/simplesamlphp-upgrade-notes-1.18.md
index 785563c8ebd00d94c2fe1c8ab0a9a929d35d8df0..297be62353a22706b2e6facb51038e26ae6cb5ee 100644
--- a/docs/simplesamlphp-upgrade-notes-1.18.md
+++ b/docs/simplesamlphp-upgrade-notes-1.18.md
@@ -1,26 +1,29 @@
-Upgrade notes for SimpleSAMLphp 1.18
-====================================
+# Upgrade notes for SimpleSAMLphp 1.18
 
 The minimum PHP version required is now PHP 5.6.
 
-### Deprecations
+## Deprecations
 
 * The use of the PHP `memcache` extension was deprecated in favour of `memcached`.
 In order to keep using memcache functionality you have to move to the PHP `memcached` extension,
-which is available from PECL; see https://pecl.php.net/package/memcached. The former is considered abandoned
+which is available from PECL; see [memcached][1]. The former is considered abandoned
 and it's safe use can no longer be guaranteed.
 
   There are a few options here:
-   - Depending on your distribution, the package may just be available for you to install
-   - You could use the package from the REMI repository if you're on RHEL; https://rpms.remirepo.net/
-   - Download the source from https://pecl.php.net/package/memcached and compile the source as a PHP-extension manually;
-     https://www.php.net/manual/en/install.pecl.phpize.php
- 
+
+  * Depending on your distribution, the package may just be available for you to install
+  * You could use the package from the [REMI repository][2] if you're on RHEL.
+  * Download the source from [memcached][1] and [compile][3] the source as a PHP-extension manually.
+
 * Support for SAML1.1 / Shibboleth 1.3 will be discontinued in a future release.
 * The class `SimpleSAML\Auth\TimeLimitedToken` is now deprecated and will be removed in a future release
   If your custom module relies on this class, be sure to make a copy into your repository and
   make sure to also copy the unit tests that come along.
 * Setting `privacypolicy` in metadata files will be removed in a future release. It was only used
   by the consent module, which supports `UIInfo`'s `PrivacyStatementURL`.
-  See https://simplesamlphp.org/docs/stable/simplesamlphp-metadata-extensions-ui on how to configure this.
+  See [Metadata extensions][4] on how to configure this.
 
+[1]: https://pecl.php.net/package/memcached
+[2]: https://rpms.remirepo.net
+[3]: https://www.php.net/manual/en/install.pecl.phpize.php
+[4]: https://simplesamlphp.org/docs/stable/simplesamlphp-metadata-extensions-ui
diff --git a/docs/simplesamlphp-upgrade-notes-1.19.md b/docs/simplesamlphp-upgrade-notes-1.19.md
index 5e039e97425c0b960fc1c7880fef4d83299303d5..264ded1f98a1530ed1deb16edd2e9eef75d66bd3 100644
--- a/docs/simplesamlphp-upgrade-notes-1.19.md
+++ b/docs/simplesamlphp-upgrade-notes-1.19.md
@@ -1,4 +1,3 @@
-Upgrade notes for SimpleSAMLphp 1.19
-====================================
+# Upgrade notes for SimpleSAMLphp 1.19
 
 The minimum PHP version required is now PHP 7.0.
diff --git a/docs/simplesamlphp-upgrade-notes-1.5.md b/docs/simplesamlphp-upgrade-notes-1.5.md
index b836d7de965938fb570e688c62f57e9be5042d02..204dc52d96b8ad525c4b8278f1256c1585ef4730 100644
--- a/docs/simplesamlphp-upgrade-notes-1.5.md
+++ b/docs/simplesamlphp-upgrade-notes-1.5.md
@@ -1,23 +1,21 @@
-Upgrade notes for SimpleSAMLphp 1.5
-===================================
+# Upgrade notes for SimpleSAMLphp 1.5
 
-  * `SimpleSAML_Session::isValid()`
+* `SimpleSAML_Session::isValid()`
 
-    If your code calls `$session->isValid()` without an argument, you will now have to update it to pass an argument (probably `saml2`).
-    The reason for this change is that calling `$session->isValid()` without an argument can easily create a security hole.
+  If your code calls `$session->isValid()` without an argument, you will now have to update it to pass an argument (probably `saml2`).
+  The reason for this change is that calling `$session->isValid()` without an argument can easily create a security hole.
 
+* We have introduced a new module for SAML authentication.
+  This authentication module supports both SAML 1.1 and SAML 2.0 IdPs.
 
-  * We have introduced a new module for SAML authentication.
-    This authentication module supports both SAML 1.1 and SAML 2.0 IdPs.
+  We have also added a new authentication framework which should replace the previous redirects to the initSSO-scripts.
+  Relating to this change, we have also deprecated the `initSSO`-scripts for SAML 1.1 and SAML 2.0 authentication.
+  The old methods will still be supported for a while, but new code should probably use the new code.
 
-    We have also added a new authentication framework which should replace the previous redirects to the initSSO-scripts.
-    Relating to this change, we have also deprecated the `initSSO`-scripts for SAML 1.1 and SAML 2.0 authentication.
-    The old methods will still be supported for a while, but new code should probably use the new code.
+  See the [migration guide](simplesamlphp-sp-migration) for more information about this.
 
-    See the [migration guide](simplesamlphp-sp-migration) for more information about this.
+* The `request.signing` option has been removed.
+  That option was replaced with the `redirect.sign` and `redirect.validate` options, and has been deprecated for one year.
 
-  * The `request.signing` option has been removed.
-    That option was replaced with the `redirect.sign` and `redirect.validate` options, and has been deprecated for one year.
-
-  * The `aggregator` module's configuration file has changed name.
-    It was changed from `aggregator.php` to `module_aggregator.php`.
+* The `aggregator` module's configuration file has changed name.
+  It was changed from `aggregator.php` to `module_aggregator.php`.
diff --git a/docs/simplesamlphp-upgrade-notes-1.6.md b/docs/simplesamlphp-upgrade-notes-1.6.md
index f790d676513c5c58c2eca3be623c25f31550c498..d873020ec97234019d3e1e8882a2a80c655c3ce6 100644
--- a/docs/simplesamlphp-upgrade-notes-1.6.md
+++ b/docs/simplesamlphp-upgrade-notes-1.6.md
@@ -1,22 +1,21 @@
-Upgrade notes for SimpleSAMLphp 1.6
-===================================
+# Upgrade notes for SimpleSAMLphp 1.6
 
-  * This release requires PHP version >= 5.2.0, as that was the first version to include `json_decode()`.
-    It is possible that it may work with version of PHP >= 5.1.2 if the [JSON PECL extension](http://pecl.php.net/package/json) is enabled, but this is untested.
+* This release requires PHP version >= 5.2.0, as that was the first version to include `json_decode()`.
+  It is possible that it may work with version of PHP >= 5.1.2 if the [JSON PECL extension](http://pecl.php.net/package/json) is enabled, but this is untested.
 
-  * The secure-flag is no longer automatically set on the session cookie.
-    This was changed to avoid hard to diagnose session problems.
-    There is a new option `session.cookie.secure` in `config.php`, which can be used to enable secure cookies.
+* The secure-flag is no longer automatically set on the session cookie.
+  This was changed to avoid hard to diagnose session problems.
+  There is a new option `session.cookie.secure` in `config.php`, which can be used to enable secure cookies.
 
-  * Dictionaries have moved to JSON format.
-    The PHP format is still supported, but all dictionaries included with SimpleSAMLphp are in JSON format.
+* Dictionaries have moved to JSON format.
+  The PHP format is still supported, but all dictionaries included with SimpleSAMLphp are in JSON format.
 
-  * The iframe-specific logout endpoints on the IdP have been merged into the normal logout endpoints.
-    This means that the metadata no longer needs to be changed when switching between logout handlers.
-    The old iframe logout endpoints are now deprecated, and the generated metadata will only include the normal logout endpoint.
+* The iframe-specific logout endpoints on the IdP have been merged into the normal logout endpoints.
+  This means that the metadata no longer needs to be changed when switching between logout handlers.
+  The old iframe logout endpoints are now deprecated, and the generated metadata will only include the normal logout endpoint.
 
-  * As a result of the changed metadata classes, all metadata elements now have a `md:`-prefix.
-    This does not change the content of the metadata, just its expression.
+* As a result of the changed metadata classes, all metadata elements now have a `md:`-prefix.
+  This does not change the content of the metadata, just its expression.
 
-  * The deprecated functions `init(...)` and `setAuthenticated(...)` in the `SimpleSAML_Session` class have been removed.
-    Code which relies on those functions should move to using `SimpleSAML_Session::getInstance()` and `$session->doLogin(...)`.
+* The deprecated functions `init(...)` and `setAuthenticated(...)` in the `SimpleSAML_Session` class have been removed.
+  Code which relies on those functions should move to using `SimpleSAML_Session::getInstance()` and `$session->doLogin(...)`.
diff --git a/docs/simplesamlphp-upgrade-notes-1.7.md b/docs/simplesamlphp-upgrade-notes-1.7.md
index fa4ce087fc13d1b1ea41434a01be7323b4a376a5..71ab230119719f1fe2d7eb7d36648cf1acc4d232 100644
--- a/docs/simplesamlphp-upgrade-notes-1.7.md
+++ b/docs/simplesamlphp-upgrade-notes-1.7.md
@@ -1,12 +1,11 @@
-Upgrade notes for SimpleSAMLphp 1.7
-===================================
+# Upgrade notes for SimpleSAMLphp 1.7
 
-  * The attribute names generated by the twitter and facebook authentication sources have changed.
-  * Several new options have been added to config.php, and some have been renamed.
-    The old options should still work, but it is suggested that you look at the config.php file in config-templates, and compare it to your own.
-  * There have been several changes to the internal API.
-    Most of the changes will not be noticed by the application using SimpleSAMLphp.
-    See the changelog for more details about the changes.
-  * Relative redirects are no longer supported.
-    If your application passes relative URL's to the `SimpleSAML_Utilities::redirect()`-function, it will no longer work.
-    This also applies if you pass relative URL's to other functions that do redirects.
+* The attribute names generated by the twitter and facebook authentication sources have changed.
+* Several new options have been added to config.php, and some have been renamed.
+  The old options should still work, but it is suggested that you look at the config.php file in config-templates, and compare it to your own.
+* There have been several changes to the internal API.
+  Most of the changes will not be noticed by the application using SimpleSAMLphp.
+  See the changelog for more details about the changes.
+* Relative redirects are no longer supported.
+  If your application passes relative URL's to the `SimpleSAML_Utilities::redirect()`-function, it will no longer work.
+  This also applies if you pass relative URL's to other functions that do redirects.
diff --git a/docs/simplesamlphp-upgrade-notes-1.8.md b/docs/simplesamlphp-upgrade-notes-1.8.md
index 50e5986330a17bac203a408ccc6c1156673b7793..49d9e0ba67af5a33136ec9e13bbc85a1c394a229 100644
--- a/docs/simplesamlphp-upgrade-notes-1.8.md
+++ b/docs/simplesamlphp-upgrade-notes-1.8.md
@@ -1,9 +1,7 @@
-Upgrade notes for SimpleSAMLphp 1.8
-===================================
-
-  * The IdP now sends the NotOnOrAfter attribute in LogoutRequest messages.
-  * We now have full support for selecting the correct AssertionConsumerService endpoint based on parameters in the authentication request.
-    As a side effect of this, an IdP may start sending responses to a new AssertionConsumerService endpoint after upgrade.
-    (This should only happen in the case where it sent the response to the wrong endpoint before.)
-  * The SP no longer incorrectly returns PartialLogout as a status code in a LogoutResponse after the local session has expired.
+# Upgrade notes for SimpleSAMLphp 1.8
 
+* The IdP now sends the NotOnOrAfter attribute in LogoutRequest messages.
+* We now have full support for selecting the correct AssertionConsumerService endpoint based on parameters in the authentication request.
+  As a side effect of this, an IdP may start sending responses to a new AssertionConsumerService endpoint after upgrade.
+  (This should only happen in the case where it sent the response to the wrong endpoint before.)
+* The SP no longer incorrectly returns PartialLogout as a status code in a LogoutResponse after the local session has expired.
diff --git a/docs/simplesamlphp-upgrade-notes-1.9.md b/docs/simplesamlphp-upgrade-notes-1.9.md
index 08a71468127458b07b63c79e4d1b6a3b6c6613ce..95042d6bae0d50b7fdc5d9bcc1476a3833697773 100644
--- a/docs/simplesamlphp-upgrade-notes-1.9.md
+++ b/docs/simplesamlphp-upgrade-notes-1.9.md
@@ -1,11 +1,10 @@
-Upgrade notes for SimpleSAMLphp 1.9
-===================================
+# Upgrade notes for SimpleSAMLphp 1.9
 
-  * The OpenID client "linkback" URL has changed from `.../module.php/openid/consumer.php` to `.../module.php/openid/linkback.php`.
-  * Support for CA path validation has been removed from SAML 2.0.
-  * The X-Frame-Options has been added to the default templates, to prevent the pages from being loaded in iframes.
-  * Access permissions of generated files are now restricted to the current user.
-  * The code to set cookies now requires PHP version >= 5.2. (PHP version 5.2.0 or newer has been the only supported version for a while, but it has in some cases been possible to run SimpleSAMLphp with older versions.)
-  * It used to be possible to set an array of endpoints for the SingleSignOnService in `saml20-idp-hosted.php`. That is no longer supported.
-  * The `aselect` module has been replaced with a new module. The new module gives us better error handling and support for request signing, but we lose support for A-Select Cross.
-  * There has been various fixes in the session expiration handling. As a result of this, sessions may get a shorter lifetime (if the IdP places a limit on the lifetime, this limit will now be honored).
+* The OpenID client "linkback" URL has changed from `.../module.php/openid/consumer.php` to `.../module.php/openid/linkback.php`.
+* Support for CA path validation has been removed from SAML 2.0.
+* The X-Frame-Options has been added to the default templates, to prevent the pages from being loaded in iframes.
+* Access permissions of generated files are now restricted to the current user.
+* The code to set cookies now requires PHP version >= 5.2. (PHP version 5.2.0 or newer has been the only supported version for a while, but it has in some cases been possible to run SimpleSAMLphp with older versions.)
+* It used to be possible to set an array of endpoints for the SingleSignOnService in `saml20-idp-hosted.php`. That is no longer supported.
+* The `aselect` module has been replaced with a new module. The new module gives us better error handling and support for request signing, but we lose support for A-Select Cross.
+* There has been various fixes in the session expiration handling. As a result of this, sessions may get a shorter lifetime (if the IdP places a limit on the lifetime, this limit will now be honored).
diff --git a/docs/simplesamlphp-upgrade-notes-2.0.md b/docs/simplesamlphp-upgrade-notes-2.0.md
index 6832a1ad828ad14a934b590516d561bca08c771c..9b83543ccc0a1e633d1c1023725f5d0d5e29f7d3 100644
--- a/docs/simplesamlphp-upgrade-notes-2.0.md
+++ b/docs/simplesamlphp-upgrade-notes-2.0.md
@@ -1,25 +1,26 @@
-Upgrade notes for SimpleSAMLphp 2.0
-====================================
+# Upgrade notes for SimpleSAMLphp 2.0
 
 SimpleSAMLphp 2.0 is a major new release which has cleaned up support for a
 lot of things that have been marked deprecated in previous SimpleSAMLphp
 releases. The following changes are relevant for installers and/or developers.
 
-Software requirements
----------------------
+## Software requirements
+
 - The minimum PHP version required is now PHP 7.4.
 - Dropped support for Symfony 4 and Twig 2.
 
-Not all modules included by default
------------------------------------
+## Not all modules included by default
+
 The set of modules included in the base installation has been reduced.
 If you used some of the modules that were shipped with SimpleSAMLphp, you now have to manually install them using Composer.
 For example, to use the LDAP module:
 
-  composer require simplesamlphp/simplesamlphp-module-ldap --update-no-dev
+```bash
+composer require simplesamlphp/simplesamlphp-module-ldap --update-no-dev
+```
+
+## Functional changes
 
-Functional changes
-------------------
 - Modules must be enabled through the `module.enable` option in `config.php`. Modules can no longer be enabled by having
   a file named `enable` or `default-enable` in the module's root directory.
 - SAML AuthnRequests that are signed will have their signature validated unless specifically disabled
@@ -37,8 +38,8 @@ Functional changes
   If you are using a database to store metadata, make sure to replace any __DYNAMIC% entityID's with
   a real value manually. Dynamic records are no longer loaded from the database.
 
-Configuration changes
----------------------
+## Configuration changes
+
 Quite some options have been changed or removed. We recommend to start with a fresh
 template from `config-templates/` and migrate the settings you require to the new
 config file manually.
@@ -47,50 +48,53 @@ The date formatting when specifying a custom logging string has been changed fro
 deprecated `strftime()` format to PHP's `date()` format.
 
 Configuration options that have been removed:
- - simplesaml.nameidattribute. Use the appropriate authproc-filters instead
- - languages[priorities]
- - attributes.extradictionaries. Add an attributes.po to your configured theme instead.
- - admin.protectindexpage. Replaced by the admin module which always requires login.
 
-Changes relevant for (module) developers
-----------------------------------------
+- simplesaml.nameidattribute. Use the appropriate authproc-filters instead
+- languages[priorities]
+- attributes.extradictionaries. Add an attributes.po to your configured theme instead.
+- admin.protectindexpage. Replaced by the admin module which always requires login.
+
+## Changes relevant for (module) developers
+
 The following changes are relevant for those having custom developed modules, authentication
 processing filters or interface with the SimpleSAMLphp development API.
 
-- Old JSON-formatted dictionaries have been replaced by gettext / .po-files;
-    You can find a migration guide here: https://github.com/simplesamlphp/simplesamlphp/wiki/Migrating-translations-(pre-migration)
-- Old PHP templates have been replaced by Twig-templates; you can find a migration
-    guide here: https://github.com/simplesamlphp/simplesamlphp/wiki/Twig:-Migrating-templates
-- The source was completely typehinted; if you have custom authsources or authproc filters, 
+- Old JSON-formatted dictionaries have been replaced by gettext / .po-files; see [migration guide][1]
+- Old PHP templates have been replaced by Twig-templates; see [migration guide][2]
+- The source was completely typehinted; if you have custom authsources or authproc filters,
     make sure you change them to reflect the method signatures of the base classes.
 - Some hooks are no longer called:
   - `frontpage`: replace with `configpage`
   - `htmlinject`: use a Twig template override instead.
   - `metadata_hosted`: no replacement
 - The following classes have been migrated to non-static:
-  + \SimpleSAML\Utils\Arrays
-  + \SimpleSAML\Utils\Attributes
-  + \SimpleSAML\Utils\Auth
-  + \SimpleSAML\Utils\Config
-  + \SimpleSAML\Utils\Crypto
-  + \SimpleSAML\Utils\EMail
-  + \SimpleSAML\Utils\HTTP
-  + \SimpleSAML\Utils\Net
-  + \SimpleSAML\Utils\Random
-  + \SimpleSAML\Utils\System
-  + \SimpleSAML\Utils\Time
-  + \SimpleSAML\Utils\XML
+  - \SimpleSAML\Utils\Arrays
+  - \SimpleSAML\Utils\Attributes
+  - \SimpleSAML\Utils\Auth
+  - \SimpleSAML\Utils\Config
+  - \SimpleSAML\Utils\Crypto
+  - \SimpleSAML\Utils\EMail
+  - \SimpleSAML\Utils\HTTP
+  - \SimpleSAML\Utils\Net
+  - \SimpleSAML\Utils\Random
+  - \SimpleSAML\Utils\System
+  - \SimpleSAML\Utils\Time
+  - \SimpleSAML\Utils\XML
 
   If you use any of these classes in your modules or themes, you will now have to instantiate them so that:
 
-  // Old style
-  $x = \SimpleSAML\Utils\Arrays::arrayize($someVar)
+```php
+// Old style
+$x = \SimpleSAML\Utils\Arrays::arrayize($someVar)
+```
 
   becomes:
 
+```php
   // New style
   $arrayUtils = new \SimpleSAML\Utils\Arrays();
   $x = $arrayUtils->arrayize($someVar);
+```
 
 - Database table schemes have been flattened. Upgrade paths are:
   - Generic KVStore:  1.16+ > 2.0
@@ -117,3 +121,6 @@ processing filters or interface with the SimpleSAMLphp development API.
   - Configuration::getLocalizedString
 
   All of these methods no longer accept a default as their last parameter. Use their getOptional* counterparts instead.
+
+[1]: https://github.com/simplesamlphp/simplesamlphp/wiki/Migrating-translations-(pre-migration)
+[2]: https://github.com/simplesamlphp/simplesamlphp/wiki/Twig:-Migrating-templates
diff --git a/docs/simplesamlphp-upgrade-notes.md b/docs/simplesamlphp-upgrade-notes.md
index 0f8e63ad97e2c5934fe60ba5d50473964ded41e7..8b0756b4b89d6ea51f4d0c0c6ad0aa895aeb74df 100644
--- a/docs/simplesamlphp-upgrade-notes.md
+++ b/docs/simplesamlphp-upgrade-notes.md
@@ -1,5 +1,4 @@
-SimpeSAMLphp Upgrade Notes
-==========================
+# SimpeSAMLphp Upgrade Notes
 
 See the following pages for important information for users upgrading
 from older versions of SimpleSAMLphp:
@@ -22,5 +21,3 @@ from older versions of SimpleSAMLphp:
 
 A detailed list of changes in each release can be found in the
 [Changelog](simplesamlphp-changelog).
-
-
diff --git a/modules/core/docs/authproc_attributeadd.md b/modules/core/docs/authproc_attributeadd.md
index a63452c522b21425cc8ebd57e5f0ddabdc02b108..149e52bfa4d03bbd8524e79b4a6d795207eea134 100644
--- a/modules/core/docs/authproc_attributeadd.md
+++ b/modules/core/docs/authproc_attributeadd.md
@@ -6,7 +6,6 @@ Filter that adds attributes to the user.
 If the attribute already exists, the values added will be merged into a multi-valued attribute.
 If you instead want to replace the existing attribute, you may add the `'%replace'` option.
 
-
 Examples
 --------
 
diff --git a/modules/core/docs/authproc_attributealter.md b/modules/core/docs/authproc_attributealter.md
index 53fe5744a3e09d925db579b5696fa27ba5518263..a77599ad65c2a5e20dc90730ce42d3fbc9662bde 100644
--- a/modules/core/docs/authproc_attributealter.md
+++ b/modules/core/docs/authproc_attributealter.md
@@ -16,16 +16,16 @@ Parameters
 :   The attribute in which the search is performed.
     This parameter is REQUIRED and the filter will throw an exception if it is not set. The filter will
     stop quietly if the attribute specified here is empty or not found.
-    
+
 `pattern`
 :   The pattern to look for inside the subject. Supports full Perl Compatible Regular Expressions (PCRE).
     This parameter is REQUIRED and the filter will throw an exception if it is not set.
-    
+
 `replacement`
 :   The value used to replace the match. Back references are not supported.
     This parameter is REQUIRED, except when using the `%replace` or `%remove` options. If `%replace` is used and
     `replacement` is not set, then the match is used as a replacement.
-    
+
 `target`
 :   The attribute where the replaced value will be placed.
     This parameter is OPTIONAL, and if not set, `subject` is used as `target`.
@@ -43,7 +43,7 @@ Parameters
 :   Indicates whether the altered values must be merged with the target attribute values. The default
     behaviour is to overwrite the target attribute completely.
     This parameter is OPTIONAL.
-    
+
 Examples
 --------
 
@@ -64,7 +64,7 @@ Change the domain on the `mail` attribute (when new domain is known):
         'pattern' => '/(?:[A-Za-z0-9-]+\.)+[A-Za-z]{2,6}$/',
         'replacement' => 'newdomain.com',
     ],
-    
+
 Set the eduPersonPrimaryAffiliation based on users' distinguishedName:
 
     10 => [
@@ -74,7 +74,7 @@ Set the eduPersonPrimaryAffiliation based on users' distinguishedName:
         'replacement' => 'staff',
         'target' => 'eduPersonPrimaryAffiliation',
     ],
-    
+
 Normalize the eduPersonPrimaryAffiliation:
 
     10 => [
@@ -84,7 +84,7 @@ Normalize the eduPersonPrimaryAffiliation:
         'replacement' => 'student',
         '%replace',
     ],
-    
+
 Get the domain of the emailaddress and put it in a separate attribute:
 
     10 => [
@@ -109,7 +109,7 @@ unless another attribute meets a condition:
         'target' => 'myAttribute',
         '%replace',
     ],
- 
+
 Remove internal, private values from eduPersonEntitlement:
 
     10 => [
diff --git a/modules/core/docs/authproc_attributecopy.md b/modules/core/docs/authproc_attributecopy.md
index 4dfc5c7fa9fd8cd7ca81a77ec87a69b39a90bbc0..c61a3b17c6abd47b22de96c772c35e098af9fb7b 100644
--- a/modules/core/docs/authproc_attributecopy.md
+++ b/modules/core/docs/authproc_attributecopy.md
@@ -3,7 +3,6 @@
 
 Filter that copies attributes.
 
-
 Examples
 --------
 
diff --git a/modules/core/docs/authproc_attributelimit.md b/modules/core/docs/authproc_attributelimit.md
index 90bf2a738f2bdfcf91c0204c2e6826408dffe90b..34274cc12fda14d9d21e21dbb9cac8a9348162a6 100644
--- a/modules/core/docs/authproc_attributelimit.md
+++ b/modules/core/docs/authproc_attributelimit.md
@@ -52,7 +52,7 @@ Only allow specific values for an attribute ignoring case.
              ]
         ],
     ],
-    
+
 Only allow specific values for an attribute that match a regex pattern
 
     'authproc' => [
@@ -65,8 +65,7 @@ Only allow specific values for an attribute that match a regex pattern
             ]
         ],
     ],
-    
-    
+
 Don't allow any attributes by default, but allow the metadata to override it.
 
     'authproc' => [
diff --git a/modules/core/docs/authproc_attributevaluemap.md b/modules/core/docs/authproc_attributevaluemap.md
index a3925495d2e16d95700eef580ed6cc5b1276422d..57d22b4957a4329b10b30910c01b3d71f9867057 100644
--- a/modules/core/docs/authproc_attributevaluemap.md
+++ b/modules/core/docs/authproc_attributevaluemap.md
@@ -1,16 +1,16 @@
-`core:AttributeValueMap`
-========================
+# `core:AttributeValueMap`
 
 Filter that creates a target attribute based on one or more value(s) in source attribute.
 
 Besides the mapping of source values to target values, the filter has the following options:
+
 * `%replace` can be used to replace all existing values in target with new ones (any existing values will be lost)
 * `%keep` can be used to keep the source attribute, otherwise it will be removed.
 
-Examples
---------
+**Examples**:
+
+## Add student affiliation based on LDAP groupmembership
 
-### Add student affiliation based on LDAP groupmembership
 Will add eduPersonAffiliation containing value "`student`" if the `memberOf` attribute contains
 either '`cn=student,o=some,o=organization,dc=org`' or '`cn=student,o=other,o=organization,dc=org`'.
 The '`memberOf`' attribute will be removed (use `%keep`, to keep it) and existing values in
@@ -30,7 +30,8 @@ The '`memberOf`' attribute will be removed (use `%keep`, to keep it) and existin
         ],
     ],
 
-### Multiple assignments
+## Multiple assignments
+
 Add `student`, `employee` and `both` affiliation based on LDAP groupmembership in the `memberOf` attribute.
 
     'authproc' => [
@@ -59,9 +60,10 @@ Add `student`, `employee` and `both` affiliation based on LDAP groupmembership i
         ],
     ],
 
-### Replace and Keep
+## Replace and Keep
+
 Replace any existing '`affiliation`' attribute values and keep the '`groups`' attribute.
-    
+
     'authproc' => [
         50 => [
             'class' => 'core:AttributeValueMap',
diff --git a/modules/core/docs/authproc_cardinalitysingle.md b/modules/core/docs/authproc_cardinalitysingle.md
index 0242ee1b0d289cf19444d4dbeeea200389417023..996e3c4540272b96cceb6761e0991a9935be67a5 100644
--- a/modules/core/docs/authproc_cardinalitysingle.md
+++ b/modules/core/docs/authproc_cardinalitysingle.md
@@ -83,6 +83,6 @@ Construct a single, comma-separated value version of `eduPersonAffiliation`:
         51 => [
             'class' => 'core:CardinalitySingle',
             'flatten' => ['eduPersonAffiliationWithCommas'],
-			'flattenWith' => ',',
+            'flattenWith' => ',',
         ],
     ],
diff --git a/modules/core/docs/authproc_generategroups.md b/modules/core/docs/authproc_generategroups.md
index 4d472eccae3cb3dc2dedcebca2ed3a8e0ff26212..deb06e7cbd33c0b17cf4824ceb757610910cd1a5 100644
--- a/modules/core/docs/authproc_generategroups.md
+++ b/modules/core/docs/authproc_generategroups.md
@@ -27,7 +27,6 @@ The following groups will be created:
 * `eduPersonAffiliation-example.org-student`
 * `eduPersonAffiliation-example.org-member`
 
-
 Examples
 --------
 
@@ -48,4 +47,3 @@ Custom attributes:
             'someOtherAttribute',
         ],
     ],
-
diff --git a/modules/core/docs/authproc_languageadaptor.md b/modules/core/docs/authproc_languageadaptor.md
index b6806a0d397b59b03a4547b717fd8c95e1af632b..f494a23a41df538300babb6dbe900b212beb966b 100644
--- a/modules/core/docs/authproc_languageadaptor.md
+++ b/modules/core/docs/authproc_languageadaptor.md
@@ -20,7 +20,6 @@ Now, the LanguageAdaptor will read the preferred language from the cookie and ad
 
 The name of the attribute can be changed from the default by adding the `attributename` option.
 
-
 Examples
 --------
 
diff --git a/modules/core/docs/authproc_php.md b/modules/core/docs/authproc_php.md
index eaef2d7e6ac5c22c7eb43f4c343402ab50c7cfa1..b9c5f1b7c7f15f38697b6a18af0b5fb8e038b0fc 100644
--- a/modules/core/docs/authproc_php.md
+++ b/modules/core/docs/authproc_php.md
@@ -11,11 +11,11 @@ Parameters
     It must be `'core:PHP'`.
 
 `code`
-:   The PHP code that should be run. This code will have two variables available: 
+:   The PHP code that should be run. This code will have two variables available:
 
 * `$attributes`.
     This is an associative array of attributes, and can be modified to add or remove attributes.
-    
+
 * `$state`.
     This is an associative array of request state. It can be modified to adjust data related to the authentication
     such as desired NameId, requested Attributes, authnContextRef and many more.
@@ -38,7 +38,6 @@ Add the `mail` attribute based on the user's `uid` attribute:
         ',
     ],
 
-
 Create a random number variable:
 
     10 => [
diff --git a/modules/core/docs/authproc_scopeattribute.md b/modules/core/docs/authproc_scopeattribute.md
index c495044e2c1cf06872d92182acdee03d760b987c..8ed127cd3f59299b5715a02372bc52e2f5a1cbec 100644
--- a/modules/core/docs/authproc_scopeattribute.md
+++ b/modules/core/docs/authproc_scopeattribute.md
@@ -15,7 +15,6 @@ Parameters
 
 :   If the attribute is multi-valued, we will add all the scopes to the target.
 
-
 `sourceAttribute`
 :   The attribute that contains the values we shall add the scope to.
 
@@ -27,11 +26,11 @@ Parameters
 :   If the attribute already exists, the new values will be merged into the existing attribute.
 
 `onlyIfEmpty`
-:	Only replace the targetAttribute if it is empty to begin with.
+:   Only replace the targetAttribute if it is empty to begin with.
 
-:	If `true`, then the targetAttribute will only be created if it didn't already contain values. Defaults to `false`.
+:   If `true`, then the targetAttribute will only be created if it didn't already contain values. Defaults to `false`.
 
-:	This is useful if, for instance, you want to create eduPersonScopedAffiliation from eduPersonAffiliation _only_ if eduPersonScopedAffiliation was not returned by the authenticaton source.
+:   This is useful if, for instance, you want to create eduPersonScopedAffiliation from eduPersonAffiliation _only_ if eduPersonScopedAffiliation was not returned by the authenticaton source.
 
 Example
 -------
diff --git a/modules/core/docs/authproc_scopefromattribute.md b/modules/core/docs/authproc_scopefromattribute.md
index f768bc0b318123e795c019882dd21a631d9a8eae..b16b76c512c03a70acc5baeb6f3f3cc93c59796a 100644
--- a/modules/core/docs/authproc_scopefromattribute.md
+++ b/modules/core/docs/authproc_scopefromattribute.md
@@ -3,7 +3,6 @@
 
 This filter creates a new attribute based on the scope from a different attribute.
 
-
 Parameters
 ----------
 
@@ -15,8 +14,6 @@ This filter has two parameters, where both parameters are mandatory.
 `targetAttribute`
 :   The name of the new attribute.
 
-
-
 Example
 -------
 
diff --git a/modules/core/docs/authproc_statisticswithattribute.md b/modules/core/docs/authproc_statisticswithattribute.md
index 22baa0420666caa8b5f4f6dc0a56fc18931d24e3..7df9d3d10a5fd6681fa4f15ecde00a199a3d5d95 100644
--- a/modules/core/docs/authproc_statisticswithattribute.md
+++ b/modules/core/docs/authproc_statisticswithattribute.md
@@ -15,7 +15,6 @@ Parameters
 `skipPassive`
 :   A boolean indicating whether passive requests should be skipped. Defaults to `false`, in which case the type tag is prefixed with 'passive-'.
 
-
 Example
 -------
 
@@ -26,4 +25,3 @@ Log the realm of the user:
         'attributename' => 'realm',
         'type' => 'saml20-idp-SSO',
     ],
-
diff --git a/modules/core/docs/authproc_targetedid.md b/modules/core/docs/authproc_targetedid.md
index deb00c725499af42be9d36c73625ce2e8bba741b..a5931b58488f3eca80547ea627553f8a2bcb353c 100644
--- a/modules/core/docs/authproc_targetedid.md
+++ b/modules/core/docs/authproc_targetedid.md
@@ -18,7 +18,6 @@ Parameters
     This can be used to generate an Internet2 compatible `eduPersonTargetedID` attribute.
     Optional, defaults to `false`.
 
-
 Examples
 --------
 
diff --git a/modules/core/docs/authproc_warnshortssointerval.md b/modules/core/docs/authproc_warnshortssointerval.md
index 3ab8cf6ff926ddabff9379bfdcb446d9d00c150b..ed0f1932dd11597c63d0f5d4e968e0e598ae862c 100644
--- a/modules/core/docs/authproc_warnshortssointerval.md
+++ b/modules/core/docs/authproc_warnshortssointerval.md
@@ -4,7 +4,6 @@
 Give a warning to the user when authenticating twice in a short time.
 This is mainly intended to prevent redirect loops between the IdP and the SP.
 
-
 Example
 -------
 
@@ -13,4 +12,3 @@ Example
             'class' => 'core:WarnShortSSOInterval',
         ],
     ],
-
diff --git a/modules/cron/docs/cron.md b/modules/cron/docs/cron.md
index ac65bf4892d7c1e5404fae01d7f861ffdda8333c..586898ab31675aca6388efee447b95782426128e 100644
--- a/modules/cron/docs/cron.md
+++ b/modules/cron/docs/cron.md
@@ -1,10 +1,8 @@
-Cron
-=============================
+# Cron
 
 [TOC]
 
-Introduction
-------------
+## Introduction
 
 The cron module allows you to do tasks regularly, by setting up a cron
 job that calls a hook in SimpleSAMLphp.  This will invoke
@@ -18,28 +16,28 @@ will be executed at that time. This module also takes care of reporting
 back the result and provides an interface in SimpleSAMLphp's admin
 panel to trigger jobs manually.
 
-Preparations
-------------
+## Preparations
 
 You need to enable the module and copy the `config-templates` files of the module into the global `config/` directory.
 
-	[root@simplesamlphp] cd /var/simplesamlphp
-	[root@simplesamlphp simplesamlphp] touch modules/cron/enable
-	[root@simplesamlphp simplesamlphp] cp modules/cron/config-templates/*.php config/
-
+```shell
+[root@simplesamlphp] cd /var/simplesamlphp
+[root@simplesamlphp simplesamlphp] touch modules/cron/enable
+[root@simplesamlphp simplesamlphp] cp modules/cron/config-templates/*.php config/
+```
 
-Configuring the cron module
----------------------------
+## Configuring the cron module
 
 The configuration (`config/module_cron.php`) should look similar to this:
 
-	$config = [
-	       'key' => 'RANDOM_KEY',
-	       'allowed_tags' => ['daily', 'hourly', 'frequent'],
-	       'debug_message' => TRUE,
-	       'sendemail' => TRUE,
-	
-	];
+```php
+$config = [
+   'key' => 'RANDOM_KEY',
+   'allowed_tags' => ['daily', 'hourly', 'frequent'],
+   'debug_message' => true,
+   'sendemail' => true,
+];
+```
 
 Bear in mind that the key is used as a security feature, to restrict
 access to your cron. Therefore, you need to make sure that the string
@@ -47,8 +45,7 @@ here is a random key available to no one but you. Additionally, make
 sure that you include here the appropriate tags - for example any tags
 that you previously told metarefresh to use in the `cron` directive.
 
-Triggering Cron
----------------------------
+## Triggering Cron
 
 You can trigger the cron hooks through HTTP or CLI.  The HTTP method
 is the original technique, and it is recommended if you don't need to
@@ -67,32 +64,37 @@ your SimpleSAMLphp installation.
 
 Now, copy the cron configuration suggested on that page:
 
-	# Run cron [daily]
-	02 0 * * * curl --silent "https://YOUR_SERVER/simplesaml/module.php/cron/cron.php?key=RANDOM_KEY&tag=daily" > /dev/null 2>&1
-	# Run cron [hourly]
-	01 * * * * curl --silent "https://YOUR_SERVER/simplesaml/module.php/cron/cron.php?key=RANDOM_KEY&tag=hourly" > /dev/null 2>&1
+```text
+# Run cron [daily]
+02 0 * * * curl --silent "https://YOUR_SERVER/simplesaml/module.php/cron/cron.php?key=RANDOM_KEY&tag=daily" > /dev/null 2>&1
+# Run cron [hourly]
+01 * * * * curl --silent "https://YOUR_SERVER/simplesaml/module.php/cron/cron.php?key=RANDOM_KEY&tag=hourly" > /dev/null 2>&1
+```
 
 Finally, add it to your crontab by going back to the terminal, and editing with:
 
-	[root@simplesamlphp config]# crontab -e
+```shell
+[root@simplesamlphp config]# crontab -e
+```
 
 This will open up your favourite editor. If an editor different than
 the one you use normally appears, exit, and configure the `EDITOR`
 variable to tell the command line which editor it should use:
 
-	[root@simplesamlphp config]# export EDITOR=emacs
+```shell
+[root@simplesamlphp config]# export EDITOR=emacs
+```
 
 If you want to trigger a job manually, you can do
 so by going back to the cron page in the web interface. Then, just
 follow the appropriate links to execute the cron jobs you want. The
 page will take a while loading, and eventually show a blank page.
 
-
 ### With CLI
 
 You can invoke cron functionality by running
 `/var/simplesamlphp/modules/cron/bin/cron.php` and providing a tag
-with the `-t ` argument.
+with the `-t` argument.
 
 It is strongly recommended that you run the cron cli script as the
 same user as the web server.  Several cron hooks created files and
@@ -105,13 +107,13 @@ logging configuration from `config.php`
 Below is an example of invoking the script. It will:
 
 * Run a command as the `apache` user
-   * `-s` specifies `apache` user's shell, since the default is non-interactive
+  * `-s` specifies `apache` user's shell, since the default is non-interactive
 * Override INI entries to increase memory and execution time.
-    * This allows for processing large metadata files in metarefresh
+  * This allows for processing large metadata files in metarefresh
 * Run the `cron.php` script with the `hourly` tag
 * Use `nice` to lower the priority below that of web server processes
 
-```
+```shell
 su -s "/bin/sh" \
    -c "nice -n 10 \
        php -d max_execution_time=120 -d memory_limit=600M \
@@ -119,4 +121,3 @@ su -s "/bin/sh" \
     apache
     
 ```
-
diff --git a/modules/multiauth/docs/multiauth.md b/modules/multiauth/docs/multiauth.md
index 4b68bdecbebce2e910c146e28be0c7d002271f56..058ac3b58b062065a1c2d63fb9349582a07bf26e 100644
--- a/modules/multiauth/docs/multiauth.md
+++ b/modules/multiauth/docs/multiauth.md
@@ -8,7 +8,6 @@ module:
 `multiauth:MultiAuth`
 : Authenticate the user against a list of authentication sources.
 
-
 `multiauth:MultiAuth`
 ---------------------
 
@@ -98,19 +97,19 @@ filtered to only those containing context class refs that are part of the list s
 If a single authsource results from this filtering the user will be taken directly to the
 authentication page for that source, and will never be shown the multiauth select page.
 
-It is possible to add the parameter `source` to the calling URL, 
+It is possible to add the parameter `source` to the calling URL,
 when accessing a service, to allow the user to preselect the
 authsource to be used. This can be handy if you support different
-authentication types for different types of users and you want the 
-users to have a direct link to the service and not want them to 
+authentication types for different types of users and you want the
+users to have a direct link to the service and not want them to
 select the correct authentication source.
 
 For example:
 
-    htttps://example.com/service/?source=saml
-    
-will take you directly to the SAML authentication source, instead 
-of hitting the multiauth select page, but this works only if you 
+`https://example.com/service/?source=saml`
+
+will take you directly to the SAML authentication source, instead
+of hitting the multiauth select page, but this works only if you
 don't have redirections during the authentication process.
 
 You can also use the multiauth:preselect parameter to the login call:
@@ -138,8 +137,8 @@ Or add the `preselect` option in the filter:
             ],
         ],
         'preselect' => 'example-saml',
-    ),
+    ],
 
-The order of priority, in case more than one option was used is: 
+The order of priority, in case more than one option was used is:
 `source` url parameter, `multiauth:preselect` login state and
 `preselect` filter option.
diff --git a/modules/saml/docs/filterscopes.md b/modules/saml/docs/filterscopes.md
index 3f17db73897fca519d8311b961bc02746b635294..06e661ca94e88015f1e1a55fba90146db23aca87 100644
--- a/modules/saml/docs/filterscopes.md
+++ b/modules/saml/docs/filterscopes.md
@@ -31,12 +31,12 @@ Here are the options available for the filter:
 :   An array containing a list of attributes that are scoped and therefore should be evaluated.
     Defaults to _eduPersonPrincipalName_ and _eduPersonScopedAffiliation_.
 
-
 Examples
 --------
 
 Basic configuration:
-```
+
+```php
     'authproc' => [
         90 => [
             'class' => 'saml:FilterScopes',
@@ -45,7 +45,8 @@ Basic configuration:
 ```
 
 Specify `mail` and `eduPersonPrincipalName` as scoped attributes:
-```
+
+```php
     'authproc' => [
         90 => [
             'class' => 'saml:FilterScopes',
@@ -58,7 +59,8 @@ Specify `mail` and `eduPersonPrincipalName` as scoped attributes:
 ```
 
 Specify the same attributes in OID format:
-```
+
+```php
     'authproc' => [
         90 => [
             'class' => 'saml:FilterScopes',
diff --git a/modules/saml/docs/keyrollover.md b/modules/saml/docs/keyrollover.md
index e211960c8619a4b7668b1d796c7b4b935240436a..711df8b76eda82f5b7d173cc19086234cb17789c 100644
--- a/modules/saml/docs/keyrollover.md
+++ b/modules/saml/docs/keyrollover.md
@@ -1,11 +1,8 @@
-Key rollover with SimpleSAMLphp
-===============================
+# Key rollover with SimpleSAMLphp
 
 This document gives a quick guide to doing key rollover with a SimpleSAMLphp service provider or identity provider.
 
-
-Create the new key and certificate
-----------------------------------
+## Create the new key and certificate
 
 First you must create the new key that you are going to use.
 To create a self signed certificate, you may use the following command:
@@ -13,9 +10,7 @@ To create a self signed certificate, you may use the following command:
     cd cert
     openssl req -newkey rsa:3072 -new -x509 -days 3652 -nodes -out new.crt -keyout new.pem
 
-
-Add the new key to SimpleSAMLphp
---------------------------------
+## Add the new key to SimpleSAMLphp
 
 Where you add the new key depends on whether you are doing key rollover for a service provider or an identity provider.
 If you are doing key rollover for a service provider, the new key must be added to `config/authsources.php`.
@@ -28,8 +23,7 @@ When the new key is added, SimpleSAMLphp will attempt to use both the new key an
 The metadata will be updated to list the new key for signing and encryption, and the old key will no longer listed as available for encryption.
 This ensures that both those entities that use your old metadata and those that use your new metadata will be able to send and receive messages from you.
 
-
-### Examples
+**Examples**:
 
 In `config/authsources.php`:
 
@@ -62,9 +56,7 @@ In `metadata/saml20-idp-hosted.php`:
         'new_privatekey_pass' => '<new-secret>',
     ];
 
-
-Distribute your new metadata
-----------------------------
+## Distribute your new metadata
 
 Now, you need to make sure that all your peers are using your new metadata.
 How you go about this depends on how your peers have added your metadata.
@@ -74,15 +66,13 @@ If you are part of an federation, you would probably either send it to the feder
 Once the peers are using your new metadata, they will accept messages from you signed with either your old or your new key.
 If they send encrypted messages to you, they will use your new key for encryption.
 
-
-Remove the old key
-------------------
+## Remove the old key
 
 Once you are certain that all your peers are using the new metadata, you must remove the old key.
 Replace the existing `privatekey`, `privatekey_pass` and `certificate` options in your configuration with the `new_privatekey`, `new_privatekey_pass` and `new_certificate` options.
 This will cause your old key to be removed from your metadata.
 
-### Examples
+**Examples**:
 
 In `config/authsources.php`:
 
@@ -105,10 +95,7 @@ In `metadata/saml20-idp-hosted.php`:
         'privatekey_pass' => '<new-secret>',
     ];
 
-
-
-Distribute your final metadata
-------------------------------
+## Distribute your final metadata
 
 Now you need to update the metadata of all your peers again, so that your old signing certificate is removed.
 This will cause those entities to no longer accept messages signed using your old key.
diff --git a/modules/saml/docs/nameid.md b/modules/saml/docs/nameid.md
index f0b3f77d858459a52de838672cd640088ab78238..1b3d0aa9cce9eff7bbf067c167fa4dd4a1e11e0a 100644
--- a/modules/saml/docs/nameid.md
+++ b/modules/saml/docs/nameid.md
@@ -1,11 +1,8 @@
-NameID generation filters
-=========================
+# NameID generation filters
 
 This document describes the NameID generation filters in the saml module.
 
-
-Common options
---------------
+## Common options
 
 `NameQualifier`
 :   The NameQualifier attribute for the generated NameID.
@@ -23,13 +20,11 @@ Common options
 
 :   The default is `true`, which means that we will use the SP entity ID.
 
-
-`saml:AttributeNameID`
-----------------------
+## `saml:AttributeNameID`
 
 Uses the value of an attribute to generate a NameID.
 
-### Options
+**Options**:
 
 `attribute`
 :   The name of the attribute we should use as the unique user ID.
@@ -37,31 +32,24 @@ Uses the value of an attribute to generate a NameID.
 `Format`
 :   The `Format` attribute of the generated NameID.
 
-
-
-`saml:PersistentNameID`
------------------------
+## `saml:PersistentNameID`
 
 Generates a persistent NameID with the format `urn:oasis:names:tc:SAML:2.0:nameid-format:persistent`.
 The filter will take the user ID from the attribute described in the `attribute` option, and hash it with the `secretsalt` from `config.php`, and the SP and IdP entity ID.
 The resulting hash is sent as the persistent NameID.
 
-### Options
+**Options**:
 
 `attribute`
 :   The name of the attribute we should use as the unique user ID.
 
-
-`saml:TransientNameID`
-----------------------
+## `saml:TransientNameID`
 
 Generates a transient NameID with the format `urn:oasis:names:tc:SAML:2.0:nameid-format:transient`.
 
 No extra options are available for this filter.
 
-
-`saml:SQLPersistentNameID`
---------------------------
+## `saml:SQLPersistentNameID`
 
 Generates and stores persistent NameIDs in a SQL database.
 
@@ -70,7 +58,7 @@ To use this filter, either specify the `store` option and a database,
 or configure SimpleSAMLphp to use a SQL datastore.
 See the `store.type` configuration option in `config.php`.
 
-### Options
+**Options**:
 
 `attribute`
 :   The name of the attribute we should use as the unique user ID.
@@ -93,9 +81,7 @@ See the `store.type` configuration option in `config.php`.
 
 Setting both `allowUnspecified` and `alwaysCreate` to `true` causes `saml:SQLPersistentNameID` to behave like `saml:PersistentNameID` (and other NameID generation filters), at the expense of creating unnecessary entries in the SQL datastore.
 
-
-`saml:PersistentNameID2TargetedID`
-----------------------------------
+## `saml:PersistentNameID2TargetedID`
 
 Stores a persistent NameID in the `eduPersonTargetedID`-attribute.
 
@@ -103,7 +89,7 @@ This filter is not actually a NameID generation filter.
 Instead, it takes a persistent NameID and adds it as an attribute in the assertion.
 This can be used to set the `eduPersonTargetedID`-attribute to the same value as the persistent NameID.
 
-### Options
+**Options**:
 
 `attribute`
 :   The name of the attribute we should store the result in.
@@ -113,10 +99,7 @@ This can be used to set the `eduPersonTargetedID`-attribute to the same value as
 :   Whether the generated attribute should be an saml:NameID element.
     The default is `true`.
 
-
-
-Example
--------
+**Example**:
 
 This example makes three NameIDs available:
 
diff --git a/modules/saml/docs/nameidattribute.md b/modules/saml/docs/nameidattribute.md
index 584d9e4fc8aa1cfb68e4728ce4592cb63d99866e..917d1b59ec9f990f455fdf8e2fef05a0c612c470 100644
--- a/modules/saml/docs/nameidattribute.md
+++ b/modules/saml/docs/nameidattribute.md
@@ -63,5 +63,5 @@ Only extract the value of the NameID.
 See also
 --------
 
- * [The description of the `saml:SP` authentication source.](./saml:sp)
- * [How to generate various NameIDs on the IdP.](./saml:nameid)
+* [The description of the `saml:SP` authentication source.](./saml:sp)
+* [How to generate various NameIDs on the IdP.](./saml:nameid)
diff --git a/modules/saml/docs/sp.md b/modules/saml/docs/sp.md
index ed133bc69cebaf731865e49084c94425fafdbbb7..0c9bd02b163efbe84842244815e30447b2f12690 100644
--- a/modules/saml/docs/sp.md
+++ b/modules/saml/docs/sp.md
@@ -1,24 +1,19 @@
-`saml:SP`
-=========
+# `saml:SP`
 
 This authentication source is used to authenticate against SAML 2 IdPs.
 
-
-Metadata
---------
+## Metadata
 
 The metadata for your SP will be available from the federation page on your SimpleSAMLphp installation.
 
 SimpleSAMLphp supports generating metadata with the MDUI and MDRPI metadata extensions
 and with entity attributes. See the documentation for those extensions for more details:
 
-  * [MDUI extension](./simplesamlphp-metadata-extensions-ui)
-  * [MDRPI extension](./simplesamlphp-metadata-extensions-rpi)
-  * [Attributes extension](./simplesamlphp-metadata-extensions-attributes)
-
+* [MDUI extension](./simplesamlphp-metadata-extensions-ui)
+* [MDRPI extension](./simplesamlphp-metadata-extensions-rpi)
+* [Attributes extension](./simplesamlphp-metadata-extensions-attributes)
 
-Parameters
-----------
+**Parameters**:
 
 These are parameters that can be used at runtime to control the authentication.
 All these parameters override the equivalent option from the configuration.
@@ -26,22 +21,19 @@ All these parameters override the equivalent option from the configuration.
 `saml:AuthnContextClassRef`
 :   The AuthnContextClassRef that will be sent in the login request.
 
-
 `saml:AuthnContextComparison`
 :   The Comparison attribute of the AuthnContext that will be sent in the login request.
     This parameter won't be used unless `saml:AuthnContextClassRef` is set and contains one or more values.
     Possible values:
-    
+
     * `SAML2\Constants::COMPARISON_EXACT` (default)
     * `SAML2\Constants::COMPARISON_BETTER`
     * `SAML2\Constants::COMPARISON_MINIMUM`
     * `SAML2\Constants::COMPARISON_MAXIMUM`
-    
 
 `ForceAuthn`
 :   Force authentication allows you to force re-authentication of users even if the user has a SSO session at the IdP.
 
-
 `saml:idp`
 :   The entity ID of the IdP we should send an authentication request to.
 
@@ -55,16 +47,13 @@ All these parameters override the equivalent option from the configuration.
 `saml:Extensions`
 :   The samlp:Extensions (an XML chunk) that will be sent in the login request.
 
-
 `saml:logout:Extensions`
 :   The samlp:Extensions (an XML chunk) that will be sent in the logout request.
 
-
 `saml:NameID`
 :   Add a Subject element with a NameID to the SAML AuthnRequest for the IdP.
     This must be a \SAML2\XML\saml\NameID object.
 
-
 `saml:NameIDPolicy`
 :   The format of the NameID we request from the IdP: an array in the form of
     `[ 'Format' => the format, 'AllowCreate' => true or false ]`.
@@ -74,15 +63,11 @@ All these parameters override the equivalent option from the configuration.
 :   For compatibility purposes, `null` is equivalent to transient and a format
     can be defined as a string instead of an array. These variants are deprecated.
 
-
 `saml:Audience`
 :   Add a Conditions element to the SAML AuthnRequest containing an
     AudienceRestriction with one or more audiences.
 
-
-
-Authentication data
--------------------
+## Authentication data
 
 Some SAML-specific attributes are available to the application after authentication.
 To retrieve these attributes, the application can use the `getAuthData()`-function from the [SP API](./simplesamlphp-sp-api).
@@ -98,9 +83,7 @@ The following attributes are available:
 `saml:sp:SessionIndex`
 :   The SessionIndex we received from the IdP.
 
-
-Options
--------
+**Options**:
 
 `acs.Bindings`
 : List of bindings the SP should support. If it is unset, all will be added.
@@ -116,7 +99,6 @@ Options
 
 :   Note that this option can be overridden for a specific IdP in saml20-idp-remote.
 
-
 `AssertionConsumerService`
 :   List of Assertion Consumer Services in the generated metadata. Specified in the array of
     arrays format as seen in the [Metadata endpoints](./simplesamlphp-metadata-endpoints)
@@ -159,17 +141,15 @@ Options
 :   The SP can request authentication with a specific authentication context class.
     One example of usage could be if the IdP supports both username/password authentication as well as software-PKI.
 
-
 `AuthnContextComparison`
 :   The Comparison attribute of the AuthnContext that will be sent in the login request.
     This parameter won't be used unless `saml:AuthnContextClassRef` is set and contains one or more values.
     Possible values:
-    
+
     * `SAML2\Constants::COMPARISON_EXACT` (default)
     * `SAML2\Constants::COMPARISON_BETTER`
     * `SAML2\Constants::COMPARISON_MINIMUM`
     * `SAML2\Constants::COMPARISON_MAXIMUM`
-    
 
 `authproc`
 :   Processing filters that should be run after SP authentication.
@@ -235,7 +215,6 @@ Options
 
 :   Note that this option can be set for each IdP in the [IdP-remote metadata](./simplesamlphp-reference-idp-remote).
 
-
 `entityID`
 :   The entity ID this SP should use.
 
@@ -253,7 +232,6 @@ Options
 `ForceAuthn`
 :   Force authentication allows you to force re-authentication of users even if the user has a SSO session at the IdP.
 
-
 `idp`
 :   The entity ID this SP should connect to.
 
@@ -285,7 +263,6 @@ Options
 
 :   Note that this option can be set for each IdP in the [IdP-remote metadata](./simplesamlphp-reference-idp-remote).
 
-
 `NameIDPolicy`
 :   The format of the NameID we request from the idp: an array in the form of
     `[ 'Format' => the format, 'AllowCreate' => true or false ]`.
@@ -297,7 +274,7 @@ Options
 
 `OrganizationName`, `OrganizationDisplayName`, `OrganizationURL`
 :   The name and URL of the organization responsible for this IdP.
-    You need to either specify _all three_ or none of these options.
+    You need to either specify *all three* or none of these options.
 
 :   The Name does not need to be suitable for display to end users, the DisplayName should be.
     The URL is a website the user can access for more information about the organization.
@@ -320,31 +297,25 @@ Options
 `privatekey`
 :   File name of private key to be used for signing messages and decrypting messages from the IdP. This option is only required if you use encrypted assertions or if you enable signing of messages.
 
-
 `privatekey_pass`
 :   The passphrase for the private key, if it is encrypted. If the private key is unencrypted, this can be left out.
 
-
 `ProviderName`
 :   Human readable name of the local SP sent with the authentication request.
 
-
 `ProtocolBinding`
 :   The binding that should be used for SAML2 authentication responses.
     This option controls the binding that is requested through the AuthnRequest message to the IdP.
     By default the HTTP-Post binding is used.
 
-
 `redirect.sign`
 :   Whether authentication requests, logout requests and logout responses sent from this SP should be signed. The default is `false`.
     If set, the `AuthnRequestsSigned` attribute of the `SPSSODescriptor` element in SAML 2.0 metadata will contain its value. This
     option takes precedence over the `sign.authnrequest` option in any metadata generated for this SP.
 
-
 `redirect.validate`
 :   Whether logout requests and logout responses received by this SP should be validated. The default is `false`.
 
-
 `RegistrationInfo`
 :   Allows to specify information about the registrar of this SP. Please refer to the
     [MDRPI extension](./simplesamlphp-metadata-extensions-rpi) document for further information.
@@ -352,9 +323,8 @@ Options
 `RelayState`
 :   The page the user should be redirected to after an IdP initiated SSO.
 
-
 `saml.SOAPClient.certificate`
-:   A file with a certificate _and_ private key that should be used when issuing SOAP requests from this SP.
+:   A file with a certificate *and* private key that should be used when issuing SOAP requests from this SP.
     If this option isn't specified, the SP private key and certificate will be used.
 
 :   This option can also be set to `false`, in which case no client certificate will be used.
@@ -374,7 +344,6 @@ Options
     any value in the IdP-remote metadata overrides the one configured
     in the SP configuration.
 
-
 `sign.logout`
 :   Whether to sign logout messages sent from this SP.
 
@@ -382,7 +351,6 @@ Options
     any value in the IdP-remote metadata overrides the one configured
     in the SP configuration.
 
-
 `signature.algorithm`
 :   The algorithm to use when signing any message generated by this service provider. Defaults to RSA-SHA256.
 :   Possible values:
@@ -395,8 +363,8 @@ Options
     * `http://www.w3.org/2001/04/xmldsig-more#rsa-sha512`
 
 `SingleLogoutServiceBinding`
-:	List of SingleLogoutService bindings the SP will claim support for (can be empty).
-:	Possible values:
+:   List of SingleLogoutService bindings the SP will claim support for (can be empty).
+:   Possible values:
 
     * `urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect`
     * `urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST`
@@ -412,15 +380,12 @@ Options
     any value in the IdP-remote metadata overrides the one configured
     in the IdP metadata.
 
-
 `WantAssertionsSigned`
 :   Whether assertions received by this SP must be signed. The default value is `false`.
     The value set for this option will be used to set the `WantAssertionsSigned` attribute of the `SPSSODescriptor` element in
     the exported SAML 2.0 metadata.
 
-
-Examples
---------
+**Examples**:
 
 Here we will list some examples for this authentication source.
 
@@ -454,7 +419,6 @@ Here we will list some examples for this authentication source.
         'redirect.validate' => true,
     ],
 
-
 ### Specifying attributes and required attributes
 
     An SP that wants eduPersonPrincipalName and mail, where eduPersonPrincipalName should be listed as required:
@@ -479,7 +443,6 @@ Here we will list some examples for this authentication source.
         'attributes.NameFormat' => 'urn:oasis:names:tc:SAML:2.0:attrname-format:basic',
     ],
 
-
 ### Limiting supported AssertionConsumerService endpoint bindings
 
     'example-acs-limit' => [
@@ -490,8 +453,7 @@ Here we will list some examples for this authentication source.
         ],
     ],
 
-
-### Requesting a specific authentication method.
+### Requesting a specific authentication method
 
     $auth = new \SimpleSAML\Auth\Simple('default-sp');
     $auth->login([
diff --git a/tests/modules/unittest/README.md b/tests/modules/unittest/README.md
index 52b5ff5a2fcf33a12173a6da26846b8a2d139f4c..ef7265584f72c63d53e34afcfea21392baa11011 100644
--- a/tests/modules/unittest/README.md
+++ b/tests/modules/unittest/README.md
@@ -1 +1,3 @@
+# Dummy module
+
 For some unit tests we need a module that has a specific setup or issues.