From 2ec3828f5b5b98ba5ac4b983b50edd1b3a24c61f Mon Sep 17 00:00:00 2001 From: Florent Morselli Date: Sun, 25 Oct 2026 21:08:54 +0100 Subject: [PATCH 1/7] chore: the pages move to docs/ MkDocs reads its pages from a directory of their own, and GitBook follows them there through .gitbook.yaml. --- README.md => docs/README.md | 0 SUMMARY.md => docs/SUMMARY.md | 0 {advanced-topics => docs/advanced-topics}/custom-algorithm.md | 0 .../advanced-topics}/encrypted-tokens-and/README.md | 0 .../encrypted-tokens-and/additional-authentication-data-aad.md | 0 .../advanced-topics}/encrypted-tokens-and/multiple-recipients.md | 0 .../advanced-topics}/encrypted-tokens-and/unprotected-headers.md | 0 {advanced-topics => docs/advanced-topics}/nested-tokens.md | 0 {advanced-topics => docs/advanced-topics}/serialization.md | 0 .../advanced-topics}/signed-tokens-and/README.md | 0 .../advanced-topics}/signed-tokens-and/detached-payload.md | 0 .../advanced-topics}/signed-tokens-and/multiple-signatures.md | 0 .../advanced-topics}/signed-tokens-and/unencoded-payload.md | 0 .../advanced-topics}/signed-tokens-and/unprotected-header.md | 0 {benchmark => docs/benchmark}/benchmarks.md | 0 {benchmark => docs/benchmark}/result-table.md | 0 {console-command => docs/console-command}/console.md | 0 {console-command => docs/console-command}/phar-application.md | 0 {console-command => docs/console-command}/standalone.md | 0 {console-command => docs/console-command}/symfony-console.md | 0 {introduction => docs/introduction}/contributing.md | 0 {introduction => docs/introduction}/pre-requisite.md | 0 {introduction => docs/introduction}/provided-features.md | 0 {introduction => docs/introduction}/security-recommendations.md | 0 {introduction => docs/introduction}/the-framework.md | 0 {migration => docs/migration}/from-v1.x-to-v2.0-1.md | 0 {migration => docs/migration}/from-v1.x-to-v2.0-2.md | 0 {migration => docs/migration}/from-v1.x-to-v2.0.md | 0 .../the-components}/algorithm-management-jwa.md | 0 {the-components => docs/the-components}/claim-checker.md | 0 .../the-components}/encrypted-tokens-jwe/README.md | 0 .../the-components}/encrypted-tokens-jwe/encryption-algorithms.md | 0 .../the-components}/encrypted-tokens-jwe/jwe-creation.md | 0 .../the-components}/encrypted-tokens-jwe/jwe-loading.md | 0 {the-components => docs/the-components}/examples.md | 0 {the-components => docs/the-components}/header-checker.md | 0 .../the-components}/key-jwk-and-key-set-jwkset/README.md | 0 .../the-components}/key-jwk-and-key-set-jwkset/key-management.md | 0 .../key-jwk-and-key-set-jwkset/key-set-management.md | 0 .../the-components}/signed-tokens-jws/README.md | 0 .../the-components}/signed-tokens-jws/jws-creation.md | 0 .../the-components}/signed-tokens-jws/jws-loading.md | 0 .../the-components}/signed-tokens-jws/signature-algorithms.md | 0 .../the-symfony-bundle}/algorithm-management.md | 0 .../the-symfony-bundle}/configuration-helper.md | 0 .../the-symfony-bundle}/encrypted-tokens/README.md | 0 .../the-symfony-bundle}/encrypted-tokens/jwe-creation.md | 0 .../the-symfony-bundle}/encrypted-tokens/jwe-decryption.md | 0 .../the-symfony-bundle}/encrypted-tokens/jwe-serializers.md | 0 {the-symfony-bundle => docs/the-symfony-bundle}/events.md | 0 .../the-symfony-bundle}/header-and-claim-checker-management.md | 0 .../the-symfony-bundle}/key-and-key-set-management/README.md | 0 .../key-and-key-set-management/key-management-jwk.md | 0 .../key-and-key-set-management/key-set-management-jwkset.md | 0 .../the-symfony-bundle}/signed-tokens/README.md | 0 .../the-symfony-bundle}/signed-tokens/jws-creation.md | 0 .../the-symfony-bundle}/signed-tokens/jws-serializers.md | 0 .../the-symfony-bundle}/signed-tokens/jws-verification.md | 0 {the-symfony-bundle => docs/the-symfony-bundle}/symfony-bundle.md | 0 59 files changed, 0 insertions(+), 0 deletions(-) rename README.md => docs/README.md (100%) rename SUMMARY.md => docs/SUMMARY.md (100%) rename {advanced-topics => docs/advanced-topics}/custom-algorithm.md (100%) rename {advanced-topics => docs/advanced-topics}/encrypted-tokens-and/README.md (100%) rename {advanced-topics => docs/advanced-topics}/encrypted-tokens-and/additional-authentication-data-aad.md (100%) rename {advanced-topics => docs/advanced-topics}/encrypted-tokens-and/multiple-recipients.md (100%) rename {advanced-topics => docs/advanced-topics}/encrypted-tokens-and/unprotected-headers.md (100%) rename {advanced-topics => docs/advanced-topics}/nested-tokens.md (100%) rename {advanced-topics => docs/advanced-topics}/serialization.md (100%) rename {advanced-topics => docs/advanced-topics}/signed-tokens-and/README.md (100%) rename {advanced-topics => docs/advanced-topics}/signed-tokens-and/detached-payload.md (100%) rename {advanced-topics => docs/advanced-topics}/signed-tokens-and/multiple-signatures.md (100%) rename {advanced-topics => docs/advanced-topics}/signed-tokens-and/unencoded-payload.md (100%) rename {advanced-topics => docs/advanced-topics}/signed-tokens-and/unprotected-header.md (100%) rename {benchmark => docs/benchmark}/benchmarks.md (100%) rename {benchmark => docs/benchmark}/result-table.md (100%) rename {console-command => docs/console-command}/console.md (100%) rename {console-command => docs/console-command}/phar-application.md (100%) rename {console-command => docs/console-command}/standalone.md (100%) rename {console-command => docs/console-command}/symfony-console.md (100%) rename {introduction => docs/introduction}/contributing.md (100%) rename {introduction => docs/introduction}/pre-requisite.md (100%) rename {introduction => docs/introduction}/provided-features.md (100%) rename {introduction => docs/introduction}/security-recommendations.md (100%) rename {introduction => docs/introduction}/the-framework.md (100%) rename {migration => docs/migration}/from-v1.x-to-v2.0-1.md (100%) rename {migration => docs/migration}/from-v1.x-to-v2.0-2.md (100%) rename {migration => docs/migration}/from-v1.x-to-v2.0.md (100%) rename {the-components => docs/the-components}/algorithm-management-jwa.md (100%) rename {the-components => docs/the-components}/claim-checker.md (100%) rename {the-components => docs/the-components}/encrypted-tokens-jwe/README.md (100%) rename {the-components => docs/the-components}/encrypted-tokens-jwe/encryption-algorithms.md (100%) rename {the-components => docs/the-components}/encrypted-tokens-jwe/jwe-creation.md (100%) rename {the-components => docs/the-components}/encrypted-tokens-jwe/jwe-loading.md (100%) rename {the-components => docs/the-components}/examples.md (100%) rename {the-components => docs/the-components}/header-checker.md (100%) rename {the-components => docs/the-components}/key-jwk-and-key-set-jwkset/README.md (100%) rename {the-components => docs/the-components}/key-jwk-and-key-set-jwkset/key-management.md (100%) rename {the-components => docs/the-components}/key-jwk-and-key-set-jwkset/key-set-management.md (100%) rename {the-components => docs/the-components}/signed-tokens-jws/README.md (100%) rename {the-components => docs/the-components}/signed-tokens-jws/jws-creation.md (100%) rename {the-components => docs/the-components}/signed-tokens-jws/jws-loading.md (100%) rename {the-components => docs/the-components}/signed-tokens-jws/signature-algorithms.md (100%) rename {the-symfony-bundle => docs/the-symfony-bundle}/algorithm-management.md (100%) rename {the-symfony-bundle => docs/the-symfony-bundle}/configuration-helper.md (100%) rename {the-symfony-bundle => docs/the-symfony-bundle}/encrypted-tokens/README.md (100%) rename {the-symfony-bundle => docs/the-symfony-bundle}/encrypted-tokens/jwe-creation.md (100%) rename {the-symfony-bundle => docs/the-symfony-bundle}/encrypted-tokens/jwe-decryption.md (100%) rename {the-symfony-bundle => docs/the-symfony-bundle}/encrypted-tokens/jwe-serializers.md (100%) rename {the-symfony-bundle => docs/the-symfony-bundle}/events.md (100%) rename {the-symfony-bundle => docs/the-symfony-bundle}/header-and-claim-checker-management.md (100%) rename {the-symfony-bundle => docs/the-symfony-bundle}/key-and-key-set-management/README.md (100%) rename {the-symfony-bundle => docs/the-symfony-bundle}/key-and-key-set-management/key-management-jwk.md (100%) rename {the-symfony-bundle => docs/the-symfony-bundle}/key-and-key-set-management/key-set-management-jwkset.md (100%) rename {the-symfony-bundle => docs/the-symfony-bundle}/signed-tokens/README.md (100%) rename {the-symfony-bundle => docs/the-symfony-bundle}/signed-tokens/jws-creation.md (100%) rename {the-symfony-bundle => docs/the-symfony-bundle}/signed-tokens/jws-serializers.md (100%) rename {the-symfony-bundle => docs/the-symfony-bundle}/signed-tokens/jws-verification.md (100%) rename {the-symfony-bundle => docs/the-symfony-bundle}/symfony-bundle.md (100%) diff --git a/README.md b/docs/README.md similarity index 100% rename from README.md rename to docs/README.md diff --git a/SUMMARY.md b/docs/SUMMARY.md similarity index 100% rename from SUMMARY.md rename to docs/SUMMARY.md diff --git a/advanced-topics/custom-algorithm.md b/docs/advanced-topics/custom-algorithm.md similarity index 100% rename from advanced-topics/custom-algorithm.md rename to docs/advanced-topics/custom-algorithm.md diff --git a/advanced-topics/encrypted-tokens-and/README.md b/docs/advanced-topics/encrypted-tokens-and/README.md similarity index 100% rename from advanced-topics/encrypted-tokens-and/README.md rename to docs/advanced-topics/encrypted-tokens-and/README.md diff --git a/advanced-topics/encrypted-tokens-and/additional-authentication-data-aad.md b/docs/advanced-topics/encrypted-tokens-and/additional-authentication-data-aad.md similarity index 100% rename from advanced-topics/encrypted-tokens-and/additional-authentication-data-aad.md rename to docs/advanced-topics/encrypted-tokens-and/additional-authentication-data-aad.md diff --git a/advanced-topics/encrypted-tokens-and/multiple-recipients.md b/docs/advanced-topics/encrypted-tokens-and/multiple-recipients.md similarity index 100% rename from advanced-topics/encrypted-tokens-and/multiple-recipients.md rename to docs/advanced-topics/encrypted-tokens-and/multiple-recipients.md diff --git a/advanced-topics/encrypted-tokens-and/unprotected-headers.md b/docs/advanced-topics/encrypted-tokens-and/unprotected-headers.md similarity index 100% rename from advanced-topics/encrypted-tokens-and/unprotected-headers.md rename to docs/advanced-topics/encrypted-tokens-and/unprotected-headers.md diff --git a/advanced-topics/nested-tokens.md b/docs/advanced-topics/nested-tokens.md similarity index 100% rename from advanced-topics/nested-tokens.md rename to docs/advanced-topics/nested-tokens.md diff --git a/advanced-topics/serialization.md b/docs/advanced-topics/serialization.md similarity index 100% rename from advanced-topics/serialization.md rename to docs/advanced-topics/serialization.md diff --git a/advanced-topics/signed-tokens-and/README.md b/docs/advanced-topics/signed-tokens-and/README.md similarity index 100% rename from advanced-topics/signed-tokens-and/README.md rename to docs/advanced-topics/signed-tokens-and/README.md diff --git a/advanced-topics/signed-tokens-and/detached-payload.md b/docs/advanced-topics/signed-tokens-and/detached-payload.md similarity index 100% rename from advanced-topics/signed-tokens-and/detached-payload.md rename to docs/advanced-topics/signed-tokens-and/detached-payload.md diff --git a/advanced-topics/signed-tokens-and/multiple-signatures.md b/docs/advanced-topics/signed-tokens-and/multiple-signatures.md similarity index 100% rename from advanced-topics/signed-tokens-and/multiple-signatures.md rename to docs/advanced-topics/signed-tokens-and/multiple-signatures.md diff --git a/advanced-topics/signed-tokens-and/unencoded-payload.md b/docs/advanced-topics/signed-tokens-and/unencoded-payload.md similarity index 100% rename from advanced-topics/signed-tokens-and/unencoded-payload.md rename to docs/advanced-topics/signed-tokens-and/unencoded-payload.md diff --git a/advanced-topics/signed-tokens-and/unprotected-header.md b/docs/advanced-topics/signed-tokens-and/unprotected-header.md similarity index 100% rename from advanced-topics/signed-tokens-and/unprotected-header.md rename to docs/advanced-topics/signed-tokens-and/unprotected-header.md diff --git a/benchmark/benchmarks.md b/docs/benchmark/benchmarks.md similarity index 100% rename from benchmark/benchmarks.md rename to docs/benchmark/benchmarks.md diff --git a/benchmark/result-table.md b/docs/benchmark/result-table.md similarity index 100% rename from benchmark/result-table.md rename to docs/benchmark/result-table.md diff --git a/console-command/console.md b/docs/console-command/console.md similarity index 100% rename from console-command/console.md rename to docs/console-command/console.md diff --git a/console-command/phar-application.md b/docs/console-command/phar-application.md similarity index 100% rename from console-command/phar-application.md rename to docs/console-command/phar-application.md diff --git a/console-command/standalone.md b/docs/console-command/standalone.md similarity index 100% rename from console-command/standalone.md rename to docs/console-command/standalone.md diff --git a/console-command/symfony-console.md b/docs/console-command/symfony-console.md similarity index 100% rename from console-command/symfony-console.md rename to docs/console-command/symfony-console.md diff --git a/introduction/contributing.md b/docs/introduction/contributing.md similarity index 100% rename from introduction/contributing.md rename to docs/introduction/contributing.md diff --git a/introduction/pre-requisite.md b/docs/introduction/pre-requisite.md similarity index 100% rename from introduction/pre-requisite.md rename to docs/introduction/pre-requisite.md diff --git a/introduction/provided-features.md b/docs/introduction/provided-features.md similarity index 100% rename from introduction/provided-features.md rename to docs/introduction/provided-features.md diff --git a/introduction/security-recommendations.md b/docs/introduction/security-recommendations.md similarity index 100% rename from introduction/security-recommendations.md rename to docs/introduction/security-recommendations.md diff --git a/introduction/the-framework.md b/docs/introduction/the-framework.md similarity index 100% rename from introduction/the-framework.md rename to docs/introduction/the-framework.md diff --git a/migration/from-v1.x-to-v2.0-1.md b/docs/migration/from-v1.x-to-v2.0-1.md similarity index 100% rename from migration/from-v1.x-to-v2.0-1.md rename to docs/migration/from-v1.x-to-v2.0-1.md diff --git a/migration/from-v1.x-to-v2.0-2.md b/docs/migration/from-v1.x-to-v2.0-2.md similarity index 100% rename from migration/from-v1.x-to-v2.0-2.md rename to docs/migration/from-v1.x-to-v2.0-2.md diff --git a/migration/from-v1.x-to-v2.0.md b/docs/migration/from-v1.x-to-v2.0.md similarity index 100% rename from migration/from-v1.x-to-v2.0.md rename to docs/migration/from-v1.x-to-v2.0.md diff --git a/the-components/algorithm-management-jwa.md b/docs/the-components/algorithm-management-jwa.md similarity index 100% rename from the-components/algorithm-management-jwa.md rename to docs/the-components/algorithm-management-jwa.md diff --git a/the-components/claim-checker.md b/docs/the-components/claim-checker.md similarity index 100% rename from the-components/claim-checker.md rename to docs/the-components/claim-checker.md diff --git a/the-components/encrypted-tokens-jwe/README.md b/docs/the-components/encrypted-tokens-jwe/README.md similarity index 100% rename from the-components/encrypted-tokens-jwe/README.md rename to docs/the-components/encrypted-tokens-jwe/README.md diff --git a/the-components/encrypted-tokens-jwe/encryption-algorithms.md b/docs/the-components/encrypted-tokens-jwe/encryption-algorithms.md similarity index 100% rename from the-components/encrypted-tokens-jwe/encryption-algorithms.md rename to docs/the-components/encrypted-tokens-jwe/encryption-algorithms.md diff --git a/the-components/encrypted-tokens-jwe/jwe-creation.md b/docs/the-components/encrypted-tokens-jwe/jwe-creation.md similarity index 100% rename from the-components/encrypted-tokens-jwe/jwe-creation.md rename to docs/the-components/encrypted-tokens-jwe/jwe-creation.md diff --git a/the-components/encrypted-tokens-jwe/jwe-loading.md b/docs/the-components/encrypted-tokens-jwe/jwe-loading.md similarity index 100% rename from the-components/encrypted-tokens-jwe/jwe-loading.md rename to docs/the-components/encrypted-tokens-jwe/jwe-loading.md diff --git a/the-components/examples.md b/docs/the-components/examples.md similarity index 100% rename from the-components/examples.md rename to docs/the-components/examples.md diff --git a/the-components/header-checker.md b/docs/the-components/header-checker.md similarity index 100% rename from the-components/header-checker.md rename to docs/the-components/header-checker.md diff --git a/the-components/key-jwk-and-key-set-jwkset/README.md b/docs/the-components/key-jwk-and-key-set-jwkset/README.md similarity index 100% rename from the-components/key-jwk-and-key-set-jwkset/README.md rename to docs/the-components/key-jwk-and-key-set-jwkset/README.md diff --git a/the-components/key-jwk-and-key-set-jwkset/key-management.md b/docs/the-components/key-jwk-and-key-set-jwkset/key-management.md similarity index 100% rename from the-components/key-jwk-and-key-set-jwkset/key-management.md rename to docs/the-components/key-jwk-and-key-set-jwkset/key-management.md diff --git a/the-components/key-jwk-and-key-set-jwkset/key-set-management.md b/docs/the-components/key-jwk-and-key-set-jwkset/key-set-management.md similarity index 100% rename from the-components/key-jwk-and-key-set-jwkset/key-set-management.md rename to docs/the-components/key-jwk-and-key-set-jwkset/key-set-management.md diff --git a/the-components/signed-tokens-jws/README.md b/docs/the-components/signed-tokens-jws/README.md similarity index 100% rename from the-components/signed-tokens-jws/README.md rename to docs/the-components/signed-tokens-jws/README.md diff --git a/the-components/signed-tokens-jws/jws-creation.md b/docs/the-components/signed-tokens-jws/jws-creation.md similarity index 100% rename from the-components/signed-tokens-jws/jws-creation.md rename to docs/the-components/signed-tokens-jws/jws-creation.md diff --git a/the-components/signed-tokens-jws/jws-loading.md b/docs/the-components/signed-tokens-jws/jws-loading.md similarity index 100% rename from the-components/signed-tokens-jws/jws-loading.md rename to docs/the-components/signed-tokens-jws/jws-loading.md diff --git a/the-components/signed-tokens-jws/signature-algorithms.md b/docs/the-components/signed-tokens-jws/signature-algorithms.md similarity index 100% rename from the-components/signed-tokens-jws/signature-algorithms.md rename to docs/the-components/signed-tokens-jws/signature-algorithms.md diff --git a/the-symfony-bundle/algorithm-management.md b/docs/the-symfony-bundle/algorithm-management.md similarity index 100% rename from the-symfony-bundle/algorithm-management.md rename to docs/the-symfony-bundle/algorithm-management.md diff --git a/the-symfony-bundle/configuration-helper.md b/docs/the-symfony-bundle/configuration-helper.md similarity index 100% rename from the-symfony-bundle/configuration-helper.md rename to docs/the-symfony-bundle/configuration-helper.md diff --git a/the-symfony-bundle/encrypted-tokens/README.md b/docs/the-symfony-bundle/encrypted-tokens/README.md similarity index 100% rename from the-symfony-bundle/encrypted-tokens/README.md rename to docs/the-symfony-bundle/encrypted-tokens/README.md diff --git a/the-symfony-bundle/encrypted-tokens/jwe-creation.md b/docs/the-symfony-bundle/encrypted-tokens/jwe-creation.md similarity index 100% rename from the-symfony-bundle/encrypted-tokens/jwe-creation.md rename to docs/the-symfony-bundle/encrypted-tokens/jwe-creation.md diff --git a/the-symfony-bundle/encrypted-tokens/jwe-decryption.md b/docs/the-symfony-bundle/encrypted-tokens/jwe-decryption.md similarity index 100% rename from the-symfony-bundle/encrypted-tokens/jwe-decryption.md rename to docs/the-symfony-bundle/encrypted-tokens/jwe-decryption.md diff --git a/the-symfony-bundle/encrypted-tokens/jwe-serializers.md b/docs/the-symfony-bundle/encrypted-tokens/jwe-serializers.md similarity index 100% rename from the-symfony-bundle/encrypted-tokens/jwe-serializers.md rename to docs/the-symfony-bundle/encrypted-tokens/jwe-serializers.md diff --git a/the-symfony-bundle/events.md b/docs/the-symfony-bundle/events.md similarity index 100% rename from the-symfony-bundle/events.md rename to docs/the-symfony-bundle/events.md diff --git a/the-symfony-bundle/header-and-claim-checker-management.md b/docs/the-symfony-bundle/header-and-claim-checker-management.md similarity index 100% rename from the-symfony-bundle/header-and-claim-checker-management.md rename to docs/the-symfony-bundle/header-and-claim-checker-management.md diff --git a/the-symfony-bundle/key-and-key-set-management/README.md b/docs/the-symfony-bundle/key-and-key-set-management/README.md similarity index 100% rename from the-symfony-bundle/key-and-key-set-management/README.md rename to docs/the-symfony-bundle/key-and-key-set-management/README.md diff --git a/the-symfony-bundle/key-and-key-set-management/key-management-jwk.md b/docs/the-symfony-bundle/key-and-key-set-management/key-management-jwk.md similarity index 100% rename from the-symfony-bundle/key-and-key-set-management/key-management-jwk.md rename to docs/the-symfony-bundle/key-and-key-set-management/key-management-jwk.md diff --git a/the-symfony-bundle/key-and-key-set-management/key-set-management-jwkset.md b/docs/the-symfony-bundle/key-and-key-set-management/key-set-management-jwkset.md similarity index 100% rename from the-symfony-bundle/key-and-key-set-management/key-set-management-jwkset.md rename to docs/the-symfony-bundle/key-and-key-set-management/key-set-management-jwkset.md diff --git a/the-symfony-bundle/signed-tokens/README.md b/docs/the-symfony-bundle/signed-tokens/README.md similarity index 100% rename from the-symfony-bundle/signed-tokens/README.md rename to docs/the-symfony-bundle/signed-tokens/README.md diff --git a/the-symfony-bundle/signed-tokens/jws-creation.md b/docs/the-symfony-bundle/signed-tokens/jws-creation.md similarity index 100% rename from the-symfony-bundle/signed-tokens/jws-creation.md rename to docs/the-symfony-bundle/signed-tokens/jws-creation.md diff --git a/the-symfony-bundle/signed-tokens/jws-serializers.md b/docs/the-symfony-bundle/signed-tokens/jws-serializers.md similarity index 100% rename from the-symfony-bundle/signed-tokens/jws-serializers.md rename to docs/the-symfony-bundle/signed-tokens/jws-serializers.md diff --git a/the-symfony-bundle/signed-tokens/jws-verification.md b/docs/the-symfony-bundle/signed-tokens/jws-verification.md similarity index 100% rename from the-symfony-bundle/signed-tokens/jws-verification.md rename to docs/the-symfony-bundle/signed-tokens/jws-verification.md diff --git a/the-symfony-bundle/symfony-bundle.md b/docs/the-symfony-bundle/symfony-bundle.md similarity index 100% rename from the-symfony-bundle/symfony-bundle.md rename to docs/the-symfony-bundle/symfony-bundle.md From eb1eb934a310532492ceb6e483e3f97fc9cbf13e Mon Sep 17 00:00:00 2001 From: Florent Morselli Date: Sun, 25 Oct 2026 21:09:50 +0100 Subject: [PATCH 2/7] docs: the GitBook syntax becomes the syntax of Material for MkDocs The hints become admonitions, the code blocks carry their title on the fence, the tables GitBook wrote in HTML become Markdown tables, and the coloured marks lose their colour: the Slabs guidelines never let a colour carry a meaning, so a red mark keeps its insistence in bold. Converted by tools/gitbook2material.py of Spomky-Labs/docs, then read page by page. --- docs/console-command/phar-application.md | 6 +- docs/introduction/pre-requisite.md | 2 +- docs/introduction/provided-features.md | 66 +++++++++---------- docs/introduction/security-recommendations.md | 6 +- docs/migration/from-v1.x-to-v2.0-1.md | 12 ++-- docs/migration/from-v1.x-to-v2.0-2.md | 12 ++-- .../algorithm-management-jwa.md | 6 +- docs/the-components/claim-checker.md | 6 +- .../encryption-algorithms.md | 46 ++++++++----- .../encrypted-tokens-jwe/jwe-creation.md | 6 +- .../encrypted-tokens-jwe/jwe-loading.md | 6 +- docs/the-components/examples.md | 18 ++--- docs/the-components/header-checker.md | 46 +++++++------ .../key-jwk-and-key-set-jwkset/README.md | 6 +- .../key-management.md | 18 ++--- .../key-set-management.md | 6 +- .../signed-tokens-jws/jws-loading.md | 6 +- .../signed-tokens-jws/signature-algorithms.md | 11 +++- .../encrypted-tokens/jwe-decryption.md | 6 +- docs/the-symfony-bundle/events.md | 4 +- .../signed-tokens/jws-verification.md | 6 +- docs/the-symfony-bundle/symfony-bundle.md | 10 ++- 22 files changed, 163 insertions(+), 148 deletions(-) diff --git a/docs/console-command/phar-application.md b/docs/console-command/phar-application.md index 875c4cb..c2b2530 100644 --- a/docs/console-command/phar-application.md +++ b/docs/console-command/phar-application.md @@ -12,6 +12,6 @@ To use it, just execute the following line: ./jose.phar ``` -{% hint style="info" %} -You may need to set it as executable: `chmod +x jose.phar` -{% endhint %} +!!! info + + You may need to set it as executable: `chmod +x jose.phar` diff --git a/docs/introduction/pre-requisite.md b/docs/introduction/pre-requisite.md index d8c08bf..4327f8a 100644 --- a/docs/introduction/pre-requisite.md +++ b/docs/introduction/pre-requisite.md @@ -9,4 +9,4 @@ This framework needs at least: Depending on the algorithms you using, other PHP extensions may be required (e.g. OpenSSL, Sodium). -Please note that cypher operation may be really slow, especially RSA functions. It is highly recommended to enable GMP or BCMath. +Please note that cypher operation may be really slow, especially RSA functions. It is highly recommended to enable GMP or BCMath. diff --git a/docs/introduction/provided-features.md b/docs/introduction/provided-features.md index e206d20..3de44f6 100644 --- a/docs/introduction/provided-features.md +++ b/docs/introduction/provided-features.md @@ -19,9 +19,9 @@ The [detached payload](../advanced-topics/signed-tokens-and/detached-payload.md) ## Supported Compression Methods -{% hint style="danger" %} -Compression is not recommended. For 4.0.0, the support of compression is no longer available. See [RFC8725](https://datatracker.ietf.org/doc/html/rfc8725#section-3.6) for more information. -{% endhint %} +!!! danger + + Compression is not recommended. For 4.0.0, the support of compression is no longer available. See [RFC8725](https://datatracker.ietf.org/doc/html/rfc8725#section-3.6) for more information. ## Supported Key Types (JWK) @@ -34,9 +34,9 @@ Compression is not recommended. For 4.0.0, the support of compression is no long JWK objects support JSON Web Key Thumbprint ([RFC 7638](https://tools.ietf.org/html/rfc7638)). -{% hint style="info" %} -A `none` key type for the `none` algorithm. It is used to explicitly allow this unsecured algorithm. -{% endhint %} +!!! info + + A `none` key type for the `none` algorithm. It is used to explicitly allow this unsecured algorithm. ## Key Sets (JWKSet) @@ -46,47 +46,47 @@ JWKSet is fully supported. | Signature Algorithm | Supported | Comment | | ------------------------------------ | --------- | ---------------------------------------------------------------------------------------------------------- | -|

HS256

HS384

HS512

| YES | | -|

ES256

ES384

ES512

| YES | | -|

RS256

RS384

RS512

| YES | | -|

PS256

PS384

PS512

| YES | GMP or BCMath extension is highly recommended | -| EdDSA with Ed25519 curve | YES | SODIUM extension is required | +|HS256
HS384
HS512| YES | | +|ES256
ES384
ES512| YES | | +|RS256
RS384
RS512| YES | | +|PS256
PS384
PS512| YES | GMP or BCMath extension is highly recommended | +| EdDSA with Ed25519 curve | YES | SODIUM extension is required | | EdDSA with Ed448 curve | NO | No extension or built-in implementation available | -| none | YES | **Please note that this is not a secured algorithm. USE IT WITH CAUTION!** | +| none | YES | **Please note that this is not a secured algorithm. USE IT WITH CAUTION!** | + +!!! info -{% hint style="info" %} -Other signature algorithms like `RS1`, `HS1` or `HS256/64` are also available. These algorithms should be used for testing purpose only or for compatibility with old systems -{% endhint %} + Other signature algorithms like `RS1`, `HS1` or `HS256/64` are also available. These algorithms should be used for testing purpose only or for compatibility with old systems ## Supported Key Encryption Algorithms | Key Encryption Algorithm | Supported | | | ----------------------------------------------------------------------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | | dir | YES | | -|

RSA1_5

RSA-OAEP

RSA-OAEP-256

| YES |

GMP or BCMath extension is highly recommended

Read note below!

| -|

ECDH-ES

ECDH-ES+A128KW

ECDH-ES+A192KW

ECDH-ES+A256KW

| YES | `spomky-labs/aes-key-wrap` is required for \*KW algorithms | -|

ECDH-SS

ECDH-SS+A128KW

ECDH-SS+A192KW

ECDH-SS+A256KW

| YES | `spomky-labs/aes-key-wrap` is required for \*KW algorithms | -|

A128KW

A192KW

A256KW

| YES | `spomky-labs/aes-key-wrap` is required | -|

PBES2-HS256+A128KW

PBES2-HS384+A192KW

PBES2-HS512+A256KW

| YES | `spomky-labs/aes-key-wrap` is required | -|

A128GCMKW

A192GCMKW

A256GCMKW

| YES | `spomky-labs/aes-key-wrap` is required | -| ECDH-ES with X25519 curve | YES | SODIUM extension is required | +|RSA1_5
RSA-OAEP
RSA-OAEP-256| YES |GMP or BCMath extension is highly recommended

Read note below!| +|ECDH-ES
ECDH-ES+A128KW
ECDH-ES+A192KW
ECDH-ES+A256KW| YES | `spomky-labs/aes-key-wrap` is required for \*KW algorithms | +|ECDH-SS
ECDH-SS+A128KW
ECDH-SS+A192KW
ECDH-SS+A256KW| YES | `spomky-labs/aes-key-wrap` is required for \*KW algorithms | +|A128KW
A192KW
A256KW| YES | `spomky-labs/aes-key-wrap` is required | +|PBES2-HS256+A128KW
PBES2-HS384+A192KW
PBES2-HS512+A256KW| YES | `spomky-labs/aes-key-wrap` is required | +|A128GCMKW
A192GCMKW
A256GCMKW| YES | `spomky-labs/aes-key-wrap` is required | +| ECDH-ES with X25519 curve | YES | SODIUM extension is required | | ECDH-ES with X448 curve | NO | No extension or built-in implementation available | -{% hint style="info" %} -Other encryption algorithms like `RSA-OEAP-384` or `ChaCha20-Poly1305` are also available. These algorithms should be used for testing purpose only or for compatibility with old systems -{% endhint %} +!!! info -{% hint style="danger" %} -The algorithms `RSA1_5` and `RSA-OAEP` are now deprecated. Please use with caution. -{% endhint %} + Other encryption algorithms like `RSA-OEAP-384` or `ChaCha20-Poly1305` are also available. These algorithms should be used for testing purpose only or for compatibility with old systems + +!!! danger + + The algorithms `RSA1_5` and `RSA-OAEP` are now deprecated. Please use with caution. ## Supported Content Encryption Algorithms | Content Encryption Algorithm | Supported | | ------------------------------------------------------------ | --------- | -|

A128CBC+HS256

A192CBC+HS384

A256CBC+HS512

| YES | -|

A128GCM

A192GCM

A256GCM

| YES | +|A128CBC+HS256
A192CBC+HS384
A256CBC+HS512| YES | +|A128GCM
A192GCM
A256GCM| YES | + +!!! info -{% hint style="info" %} -Other encryption algorithms like `A128CTR`, `A192CTR` and `A256CTR` are also available. These algorithms should be used for testing purpose only or for compatibility with old systems -{% endhint %} + Other encryption algorithms like `A128CTR`, `A192CTR` and `A256CTR` are also available. These algorithms should be used for testing purpose only or for compatibility with old systems diff --git a/docs/introduction/security-recommendations.md b/docs/introduction/security-recommendations.md index 8351ebd..3d4897b 100644 --- a/docs/introduction/security-recommendations.md +++ b/docs/introduction/security-recommendations.md @@ -93,9 +93,9 @@ When you receive a token, the following steps should be followed in this order. 2. Verify the signature (JWS) or decrypt the token (JWE) 3. Check the claims in the payload (if any) -{% hint style="warning" %} -Regarding header verification, it is important to verify **ALL** of them. There are known vulnerabilities on e.g. algorithm swapping (`alg` changed to `none`) or Denial Of Service (`p2c` set to a very high value for overloading the server). -{% endhint %} +!!! warning + + Regarding header verification, it is important to verify **ALL** of them. There are known vulnerabilities on e.g. algorithm swapping (`alg` changed to `none`) or Denial Of Service (`p2c` set to a very high value for overloading the server). ### Unserialize The Token diff --git a/docs/migration/from-v1.x-to-v2.0-1.md b/docs/migration/from-v1.x-to-v2.0-1.md index d4f9a33..9189a40 100644 --- a/docs/migration/from-v1.x-to-v2.0-1.md +++ b/docs/migration/from-v1.x-to-v2.0-1.md @@ -26,9 +26,9 @@ It is highly recommended to declare this server within your application `compose composer config --json extra.symfony.endpoint '["https://api.github.com/repos/web-token/recipes/contents/index.json?ref=main", "flex://defaults"]' ``` -{% hint style="info" %} -You can adapt this command line depending on the other Flex servers you are using. -{% endhint %} +!!! info + + You can adapt this command line depending on the other Flex servers you are using. ## Upgrade the dependencies and the libraries @@ -40,6 +40,6 @@ It is now time to upgrade the libraries. In your composer.json, change all `web- You can also update all other dependencies if needed. You can list upgradable libraries by calling `composer outdated`. This step is not mandatory, but highly recommended. -{% hint style="success" %} -[Rector](https://github.com/rectorphp/rector) is a very nice tool from code upgrade. We highly recommend it. -{% endhint %} +!!! success + + [Rector](https://github.com/rectorphp/rector) is a very nice tool from code upgrade. We highly recommend it. diff --git a/docs/migration/from-v1.x-to-v2.0-2.md b/docs/migration/from-v1.x-to-v2.0-2.md index f008fd7..d97a940 100644 --- a/docs/migration/from-v1.x-to-v2.0-2.md +++ b/docs/migration/from-v1.x-to-v2.0-2.md @@ -16,9 +16,9 @@ Next, you have to verify you don’t use any deprecated class, interface, method The following packages are deprecated. Please install `web-token/jwt-library` or `web-token/jwt-experimental` instead. -{% hint style="info" %} -In addtion to the new library or experimental packages, you may need to require third party dependencies such as `ext-sodium`, `ext-openssl` or . -{% endhint %} +!!! info + + In addtion to the new library or experimental packages, you may need to require third party dependencies such as `ext-sodium`, `ext-openssl` or . * `web-token/jwt-util-ecc` * `web-token/jwt-key-mgmt` @@ -63,6 +63,6 @@ It is now time to upgrade the libraries. In your composer.json, change all `web- You can also update all other dependencies if needed. You can list upgradable libraries by calling `composer outdated`. This step is not mandatory, but highly recommended. -{% hint style="success" %} -[Rector](https://github.com/rectorphp/rector) is a very nice tool from code upgrade. We highly recommend it. -{% endhint %} +!!! success + + [Rector](https://github.com/rectorphp/rector) is a very nice tool from code upgrade. We highly recommend it. diff --git a/docs/the-components/algorithm-management-jwa.md b/docs/the-components/algorithm-management-jwa.md index 22fc5e7..c0c9413 100644 --- a/docs/the-components/algorithm-management-jwa.md +++ b/docs/the-components/algorithm-management-jwa.md @@ -19,9 +19,9 @@ $algorithmManager = new AlgorithmManager([ ]); ``` -{% hint style="warning" %} -It is not possible to set the same algorithm twice in the same algorithm manager. -{% endhint %} +!!! warning + + It is not possible to set the same algorithm twice in the same algorithm manager. ## Algorithm Manager Factory diff --git a/docs/the-components/claim-checker.md b/docs/the-components/claim-checker.md index 06f1764..d519580 100644 --- a/docs/the-components/claim-checker.md +++ b/docs/the-components/claim-checker.md @@ -6,9 +6,9 @@ JSON Web Tokens can be used to transport any kind of data. They are mainly used In the following example, we will create a manager able to check the `aud` (Audience), `iat` (Issued At), `nbf` (Not Before) and `exp` (Expiration) claims. -{% hint style="info" %} -Time-based checkers require a [PSR-20 clock](https://www.php-fig.org/psr/psr-20/). -{% endhint %} +!!! info + + Time-based checkers require a [PSR-20 clock](https://www.php-fig.org/psr/psr-20/). ```php AlgorithmAdditional header parameter

A128KW

A192KW

A256KW

No

A128GCMKW

A192GCMKW

A256GCMKW

iv: (initialization vector) this value is the base64url-encoded representation of the 96-bit IV value used for the key encryption operation.
tag: (authentication tag) the value is the base64url-encoded representation of the 128-bit Authentication Tag value resulting from the key encryption operation.dirNo

ECDH-ES

ECDH-ES+A128KW

ECDH-ES+A192KW

ECDH-ES+A256KW

epk: (ephemeral public key) value created by the originator.

ECDH-SS

ECDH-SS+A128KW

ECDH-SS+A192KW

ECDH-SS+A256KW

No

PBES2-HS256+A128KW

PBES2-HS384+A192KW

PBES2-HS512+A256KW

p2s: (PBES2 salt input) encodes a Salt Input value, which is used as part of the PBKDF2 salt value.
p2c: (PBES2 count) contains the PBKDF2 iteration count, represented as a positive JSON integer.

RSA1_5

RSA-OAEP

RSA-OAEP-256

+ `spomky-labs/aes-key-wrap` is required for \*KW algorithms -{% hint style="warning" %} -Please note that the additional header parameters **MUST** be present and **MUST** be understood. Depending on the algorithm you use, you may be required to check headers BEFORE the decryption operation. Please create a [custom Header Checker](../header-checker.md) for theses parameters. -{% endhint %} +| Algorithm | Additional header parameter | +|---|---| +| A128KW
A192KW
A256KW | No | +| A128GCMKW
A192GCMKW
A256GCMKW | `iv`: (initialization vector) this value is the base64url-encoded representation of the 96-bit IV value used for the key encryption operation.
`tag`: (authentication tag) the value is the base64url-encoded representation of the 128-bit Authentication Tag value resulting from the key encryption operation. | +| dir | No | +| ECDH-ES
ECDH-ES+A128KW
ECDH-ES+A192KW
ECDH-ES+A256KW | `epk`: (ephemeral public key) value created by the originator. | +| ECDH-SS
ECDH-SS+A128KW
ECDH-SS+A192KW
ECDH-SS+A256KW | No | +| PBES2-HS256+A128KW
PBES2-HS384+A192KW
PBES2-HS512+A256KW | `p2s`: (PBES2 salt input) encodes a Salt Input value, which is used as part of the PBKDF2 salt value.
`p2c`: (PBES2 count) contains the PBKDF2 iteration count, represented as a positive JSON integer. | +| RSA1_5
RSA-OAEP
RSA-OAEP-256 | | + +!!! warning + + Please note that the additional header parameters **MUST** be present and **MUST** be understood. Depending on the algorithm you use, you may be required to check headers BEFORE the decryption operation. Please create a [custom Header Checker](../header-checker.md) for theses parameters. ### Content Encryption | Algorithm | Package | | ------------------------------------------------------------ | ------------------------------------------- | -|

A128GCM

A192GCM

A256GCM

| `web-token/jwt-encryption-algorithm-aesgcm` | -|

A128CBC-HS256

A192CBC-HS384

A256CBC-HS512

| `web-token/jwt-encryption-algorithm-aescbc` | +|A128GCM
A192GCM
A256GCM| `web-token/jwt-encryption-algorithm-aesgcm` | +|A128CBC-HS256
A192CBC-HS384
A256CBC-HS512| `web-token/jwt-encryption-algorithm-aescbc` | + +!!! danger -{% hint style="danger" %} -The algorithm `RSA1_5` is deprecated due to known [security vulnerability](https://en.wikipedia.org/wiki/Adaptive_chosen-ciphertext_attack). + The algorithm `RSA1_5` is deprecated due to known [security vulnerability](https://en.wikipedia.org/wiki/Adaptive_chosen-ciphertext_attack). -The algorithms `ECDH-ES*` are not recommended unless used with the `OKP` key type. -{% endhint %} + The algorithms `ECDH-ES*` are not recommended unless used with the `OKP` key type. ## Experimental Algorithms -The following algorithms are experimental and must not be used in production unless you know what you are doing. They are proposed for testing purpose only. +The following algorithms are experimental and must not be used in production unless you know what you are doing. **They are proposed for testing purpose only.** ### Key Encryption -
AlgorithmDescription

A128CTR

A192CTR

A256CTR

AES CTR based encryption
Chacha20+Poly1305Please note that this algorithm requires OpenSSL 1.1

RSA-OAEP-384

RSA-OAEP-512

Same algorithm as RSA-OAEP-256 but with SHA-384 and SHA-512 hashing functions
+| Algorithm | Description | +|---|---| +| A128CTR
A192CTR
A256CTR | AES CTR based encryption | +| Chacha20+Poly1305 | *Please note that this algorithm requires OpenSSL 1.1* | +| RSA-OAEP-384
RSA-OAEP-512 | Same algorithm as RSA-OAEP-256 but with SHA-384 and SHA-512 hashing functions | ### Content Encryption -
AlgorithmDescription

A128CCM-16-128

A128CCM-16-64

A128CCM-64-128

A128CCM-64-64

A256CCM-16-128

A256CCM-16-64

A256CCM-64-128

A256CCM-64-64

AES-CCM based algorithms
+| Algorithm | Description | +|---|---| +| A128CCM-16-128
A128CCM-16-64
A128CCM-64-128
A128CCM-64-64
A256CCM-16-128
A256CCM-16-64
A256CCM-64-128
A256CCM-64-64 | AES-CCM based algorithms | ## How To Use diff --git a/docs/the-components/encrypted-tokens-jwe/jwe-creation.md b/docs/the-components/encrypted-tokens-jwe/jwe-creation.md index 1179a4d..33c67b5 100644 --- a/docs/the-components/encrypted-tokens-jwe/jwe-creation.md +++ b/docs/the-components/encrypted-tokens-jwe/jwe-creation.md @@ -30,9 +30,9 @@ $jweBuilder = new JWEBuilder( ); ``` -{% hint style="danger" %} -Compression is not recommended. Please avoid its use. See [RFC8725](https://datatracker.ietf.org/doc/html/rfc8725#section-3.6) for more information. -{% endhint %} +!!! danger + + Compression is not recommended. Please avoid its use. See [RFC8725](https://datatracker.ietf.org/doc/html/rfc8725#section-3.6) for more information. Now let's create our first JWE object. diff --git a/docs/the-components/encrypted-tokens-jwe/jwe-loading.md b/docs/the-components/encrypted-tokens-jwe/jwe-loading.md index 6be444a..8e61c95 100644 --- a/docs/the-components/encrypted-tokens-jwe/jwe-loading.md +++ b/docs/the-components/encrypted-tokens-jwe/jwe-loading.md @@ -35,9 +35,9 @@ $jweDecrypter = new JWEDecrypter( Now we can try to deserialize and decrypt the input we receive. We will continue with the result we got during the JWE creation section. -{% hint style="danger" %} -We do not check header parameters here, but it is very important to do it. This step is described in the [Header Checker](../header-checker.md) section. -{% endhint %} +!!! danger + + We do not check header parameters here, but it is very important to do it. This step is described in the [Header Checker](../header-checker.md) section. ```php create() ->withPayload($payload) ->addSignature($jwk, ['alg' => 'ES256', 'kid' => 'my-key-id']) @@ -43,12 +41,10 @@ $token = $serializer->serialize($jws); var_dump($token); ``` -{% endcode %} ## JWS Loading and Verification -{% code lineNumbers="true" %} -```php +```php linenums="1" create() ->withPayload($payload) ->withSharedProtectedHeader(['alg' => 'ECDH-ES', 'enc' => 'A128GCM']) @@ -157,12 +150,10 @@ $token = $serializer->serialize($jwe, 0); var_dump($token); ``` -{% endcode %} ## JWE Loading and Verification -{% code lineNumbers="true" %} -```php +```php linenums="1" check($jwt, 0, ['alg', 'enc', 'crit']); The library provides several header checker classes you can instantiate and use at will. They are all located in the namespace `Jose\Component\Checker`. -{% hint style="info" %} -For time-based parameter checker classes, a PSR-20 clock object is mandatory. -{% endhint %} +!!! info + + For time-based parameter checker classes, a PSR-20 clock object is mandatory. -
ClassHeaderTime-based
AlgorithmCheckeralgNo
AudienceCheckeraud
This is a replicated claim as per the RFC7516 section 5.3
No
ExpirationTimeCheckerexpYes
IssuedAtCheckeriatYes
IssuerCheckerissNo
NotBeforeCheckernbfYes
UnencodedPayloadCheckerb64
See unencoded payload for more information.
No
CallableCheckerGeneric object that can execute a callable for checking a particular parameterNo
IsEqualCheckerGeneric object that can compare a particular parameter to a predefined valueNo
+| Class | Header | Time-based | +|---|---|---| +| AlgorithmChecker | `alg` | No | +| AudienceChecker | `aud`
This is a replicated claim as per the [RFC7516 section 5.3](https://tools.ietf.org/html/rfc7519#section-5.3) | No | +| ExpirationTimeChecker | `exp` | **Yes** | +| IssuedAtChecker | `iat` | **Yes** | +| IssuerChecker | `iss` | No | +| NotBeforeChecker | `nbf` | **Yes** | +| UnencodedPayloadChecker | `b64`
See [unencoded payload](../advanced-topics/signed-tokens-and/unencoded-payload.md) for more information. | No | +| CallableChecker | Generic object that can execute a callable for checking a particular parameter | No | +| IsEqualChecker | Generic object that can compare a particular parameter to a predefined value | No | ## Header Checker Manager Factory @@ -100,8 +110,7 @@ With the previous examples, we will only check the `alg` (algorithm) header para If you need, you can create you own header checker. It must implement the interface `Jose\Component\Checker\HeaderChecker`. In the following example, we will check that the protected header parameter `custom` is an array with value `foo` or `bar`. -{% code title="Acme\Checker\CustomChecker.php" %} -```php +```php title="Acme\Checker\CustomChecker.php" AlgorithmDescription

HS256

HS384

HS512

HMAC with SHA-2 Functions

ES256

ES384

ES512

Elliptic Curve Digital Signature Algorithm (ECDSA)

RS256

RS384

RS512

RSASSA-PKCS1 v1_5

PS256

PS384

PS512

RSASSA-PSSEdDSA (only with the Ed25519 curve)Edwards-curve Digital Signature Algorithm (EdDSA)noneNot a secure algorithm. Please use with caution +| Algorithm | Description | +|---|---| +| HS256
HS384
HS512 | HMAC with SHA-2 Functions | +| ES256
ES384
ES512 | Elliptic Curve Digital Signature Algorithm (ECDSA) | +| RS256
RS384
RS512 | RSASSA-PKCS1 v1_5 | +| PS256
PS384
PS512 | RSASSA-PSS | +| EdDSA (*only with the* Ed25519 *curve*) | Edwards-curve Digital Signature Algorithm (EdDSA) | +| none | **Not a secure algorithm. Please use with caution** | ### Experimental Algorithms -The following signature algorithms are experimental and must not be used in production unless you know what you are doing. They are proposed for testing purpose only. +The following signature algorithms are experimental and must not be used in production unless you know what you are doing. **They are proposed for testing purpose only.** They are provided throught the package `web-token/jwt-experimental`. diff --git a/docs/the-symfony-bundle/encrypted-tokens/jwe-decryption.md b/docs/the-symfony-bundle/encrypted-tokens/jwe-decryption.md index 76bc870..f974e0b 100644 --- a/docs/the-symfony-bundle/encrypted-tokens/jwe-decryption.md +++ b/docs/the-symfony-bundle/encrypted-tokens/jwe-decryption.md @@ -19,9 +19,9 @@ $jweDecrypter = $jweDecrypterFactory->create(['HS256']); You can now use the JWEDecrypter as explained in the JWE Creation section. -{% hint style="info" %} -Reminder: it is important to check the token headers. See the checker section of this documentation. -{% endhint %} +!!! info + + Reminder: it is important to check the token headers. See the checker section of this documentation. ## JWE Decrypter As Service diff --git a/docs/the-symfony-bundle/events.md b/docs/the-symfony-bundle/events.md index aa8bae5..2576414 100644 --- a/docs/the-symfony-bundle/events.md +++ b/docs/the-symfony-bundle/events.md @@ -33,8 +33,7 @@ All events can be found in the class `Jose\Bundle\JoseFramework\Event\Events`. ## Example: -{% code title="App\EventSubscriber\JwsSubscriber.php" %} -```php +```php title="App\EventSubscriber\JwsSubscriber.php" create(['HS256']); You can now use the JWSVerifier as explained in the JWS Creation section. -{% hint style="info" %} -Reminder: it is important to check the token headers. See the checker section of this documentation. -{% endhint %} +!!! info + + Reminder: it is important to check the token headers. See the checker section of this documentation. ## JWS Verifier As Service diff --git a/docs/the-symfony-bundle/symfony-bundle.md b/docs/the-symfony-bundle/symfony-bundle.md index 64dbc43..c877431 100644 --- a/docs/the-symfony-bundle/symfony-bundle.md +++ b/docs/the-symfony-bundle/symfony-bundle.md @@ -6,16 +6,15 @@ This framework provides a Symfony bundle that will help you to use the component The bundle is automatically detected when Flex is available. -{% hint style="info" %} -As the recipes are third party ones not officially supported by Symfony, you will be asked to execute the recipe or not. When applied, the recipes will prompt a message such as `Web Token Framework is ready.` -{% endhint %} +!!! info + + As the recipes are third party ones not officially supported by Symfony, you will be asked to execute the recipe or not. When applied, the recipes will prompt a message such as `Web Token Framework is ready.` ## Without Symfony Flex If you don't use Symfony Flex, you must register the bundle manually. -{% code title="config/bundles.php" %} -```php +```php title="config/bundles.php" Date: Sun, 25 Oct 2026 21:09:58 +0100 Subject: [PATCH 3/7] docs: every title in sentence case The Slabs guidelines set every title on the web in sentence case. The names keep their capitals: JWT Framework, Symfony, Symfony Flex, the acronyms (JWS, JWE, JWK, JWA, PHAR, PSR-20) and the class names. --- docs/advanced-topics/custom-algorithm.md | 2 +- .../additional-authentication-data-aad.md | 2 +- .../multiple-recipients.md | 8 ++-- .../unprotected-headers.md | 2 +- docs/advanced-topics/nested-tokens.md | 10 ++--- docs/advanced-topics/serialization.md | 20 ++++----- .../signed-tokens-and/detached-payload.md | 6 +-- .../signed-tokens-and/multiple-signatures.md | 2 +- .../signed-tokens-and/unencoded-payload.md | 2 +- .../signed-tokens-and/unprotected-header.md | 2 +- docs/benchmark/benchmarks.md | 6 +-- docs/console-command/console.md | 30 ++++++------- docs/console-command/phar-application.md | 2 +- docs/console-command/standalone.md | 2 +- docs/introduction/provided-features.md | 18 ++++---- docs/introduction/security-recommendations.md | 44 +++++++++---------- docs/introduction/the-framework.md | 2 +- docs/migration/from-v1.x-to-v2.0-2.md | 8 ++-- .../algorithm-management-jwa.md | 4 +- docs/the-components/claim-checker.md | 10 ++--- .../encrypted-tokens-jwe/README.md | 2 +- .../encryption-algorithms.md | 16 +++---- .../encrypted-tokens-jwe/jwe-creation.md | 2 +- .../encrypted-tokens-jwe/jwe-loading.md | 6 +-- docs/the-components/examples.md | 8 ++-- docs/the-components/header-checker.md | 10 ++--- .../key-jwk-and-key-set-jwkset/README.md | 2 +- .../key-management.md | 22 +++++----- .../key-set-management.md | 2 +- .../signed-tokens-jws/README.md | 2 +- .../signed-tokens-jws/jws-creation.md | 2 +- .../signed-tokens-jws/jws-loading.md | 8 ++-- .../signed-tokens-jws/signature-algorithms.md | 6 +-- .../algorithm-management.md | 8 ++-- .../configuration-helper.md | 2 +- .../encrypted-tokens/README.md | 2 +- .../encrypted-tokens/jwe-creation.md | 6 +-- .../encrypted-tokens/jwe-decryption.md | 8 ++-- .../encrypted-tokens/jwe-serializers.md | 6 +-- .../header-and-claim-checker-management.md | 10 ++--- .../key-and-key-set-management/README.md | 2 +- .../key-management-jwk.md | 18 ++++---- .../key-set-management-jwkset.md | 16 +++---- .../signed-tokens/README.md | 2 +- .../signed-tokens/jws-creation.md | 6 +-- .../signed-tokens/jws-serializers.md | 6 +-- .../signed-tokens/jws-verification.md | 8 ++-- docs/the-symfony-bundle/symfony-bundle.md | 4 +- 48 files changed, 187 insertions(+), 187 deletions(-) diff --git a/docs/advanced-topics/custom-algorithm.md b/docs/advanced-topics/custom-algorithm.md index 4bcf351..9c14b56 100644 --- a/docs/advanced-topics/custom-algorithm.md +++ b/docs/advanced-topics/custom-algorithm.md @@ -1,4 +1,4 @@ -# Custom Algorithm +# Custom algorithm This framework provides dozens of signature or encryption algorithms. If your application uses a custom algorithm or if another algorithm has been recently approved in the JWT context, it may be interesting to use it with this framework. diff --git a/docs/advanced-topics/encrypted-tokens-and/additional-authentication-data-aad.md b/docs/advanced-topics/encrypted-tokens-and/additional-authentication-data-aad.md index 04e6655..e4cce14 100644 --- a/docs/advanced-topics/encrypted-tokens-and/additional-authentication-data-aad.md +++ b/docs/advanced-topics/encrypted-tokens-and/additional-authentication-data-aad.md @@ -1,4 +1,4 @@ -# Additional Authentication Data (AAD) +# Additional authentication data (AAD) The Additional Authenticated Data (AAD) is an input to an Authenticated Encryption operation. The AAD is integrity protected but not encrypted. diff --git a/docs/advanced-topics/encrypted-tokens-and/multiple-recipients.md b/docs/advanced-topics/encrypted-tokens-and/multiple-recipients.md index ffc4f25..ef26da1 100644 --- a/docs/advanced-topics/encrypted-tokens-and/multiple-recipients.md +++ b/docs/advanced-topics/encrypted-tokens-and/multiple-recipients.md @@ -1,4 +1,4 @@ -# Multiple Recipients +# Multiple recipients When you need to encrypt the same payload for several audiences, you may want to do it at once. The JWE Builder supports multiple recipients. @@ -21,11 +21,11 @@ $jweBuilder **Note: when an unprotected header is set, the Compact Serialization mode is not available.** -## Key Management Modes +## Key management modes Each Key Encryption Algorithm has its own Key Management Mode. -### Key Encryption Algorithms And Associated Key Management Mode. +### Key encryption algorithms and associated key management mode. | Algorithm Key Management Mode | Key Encryption | Key Wrapping | Direct Key Agreement | Key Agreement with Key Wrapping | Direct Encryption | | ------------------------------ | -------------- | ------------ | -------------------- | ------------------------------- | ----------------- | @@ -47,7 +47,7 @@ Each Key Encryption Algorithm has its own Key Management Mode. | A192GCMKW | | X | | | | | A256GCMKW | | X | | | | -### Compatibility table between Key Management Modes: +### Compatibility table between key management modes: | Key Management Mode | Key Encryption | Key Wrapping | Direct Key Agreement | Key Agreement with Key Wrapping | Direct Encryption | | ------------------------------- | -------------- | ------------ | -------------------- | ------------------------------- | ----------------- | diff --git a/docs/advanced-topics/encrypted-tokens-and/unprotected-headers.md b/docs/advanced-topics/encrypted-tokens-and/unprotected-headers.md index 6bff81f..b0c0927 100644 --- a/docs/advanced-topics/encrypted-tokens-and/unprotected-headers.md +++ b/docs/advanced-topics/encrypted-tokens-and/unprotected-headers.md @@ -1,4 +1,4 @@ -# Unprotected Headers +# Unprotected headers As well as the [signed tokens](../signed-tokens-and/unprotected-header.md), the encrypted tokens also have unprotected header. But with one difference: there are two unprotected headers: diff --git a/docs/advanced-topics/nested-tokens.md b/docs/advanced-topics/nested-tokens.md index 4adb0e0..87c5618 100644 --- a/docs/advanced-topics/nested-tokens.md +++ b/docs/advanced-topics/nested-tokens.md @@ -1,10 +1,10 @@ -# Nested Tokens +# Nested tokens JWT can be signed or encrypted and both. A nested token is a signed token enclosed in an encrypted one. This order is very important: signed then encrypted. The `NestedTokenLoader` and `NestedTokenBuilder` classes will help you to create nested tokens with ease. Just instal the package `web-token/jwt-nested-token`. It contains all the classes and dependencies will be directly managed by composer. You can install it if needed. -## Nested Token Loading +## Nested token loading To instantiate the `NestedTokenLoader`, you need a `JWSLoader` and a `JWELoader`. @@ -22,7 +22,7 @@ The last argument (`$signature` in the following example) will represents the si $jws = $nestedTokenLoader->load($token, $encryptionKeySet, $signatureKeySet, $signature); ``` -## Nested Token Building +## Nested token building To instantiate the `NestedTokenBuilder`, you will need the following components: @@ -66,7 +66,7 @@ As a reminder, if one of the following parameter is set, the compact serializati * recipient unprotected header, * Additional Authenticated Data. -## Symfony Bundle +## Symfony bundle ### Configuration @@ -102,7 +102,7 @@ This configuration will create two public services: These services can be called from the container (unless private) or injected in your services. -### Configuration Helper +### Configuration helper As any other services, you can create a nested token loader or builder from another bundle extension. The following bundle extension class will create the same configuration and services as above. diff --git a/docs/advanced-topics/serialization.md b/docs/advanced-topics/serialization.md index 167e3dc..fe6b214 100644 --- a/docs/advanced-topics/serialization.md +++ b/docs/advanced-topics/serialization.md @@ -8,9 +8,9 @@ The [RFC7515](https://tools.ietf.org/html/rfc7515) (JWS) and [RFC7516](https://t The _Compact_ mode is most know and commonly used as it is compact and URL safe i.e. it is designed for web context. JSON Flattened and General are not URL safe, but provides features that may fit on your application context. -## JWS Serialization +## JWS serialization -### JWS Compact +### JWS compact This serialization mode is probably the one you know the most. It it a string composed of three parts encoded in Base64 Url Safe and separated by a dot (`.`). @@ -27,7 +27,7 @@ There are some limitations when you use this serialization mode: * Unprotected header not supported. * Unencoded payload must contain characters within the following range of ASCII characters: 0x20-0x2d and 0x2f-0x7e -### JWS JSON Flattened +### JWS JSON flattened This serialization mode is useful when you need to use the unprotected header. It it a simple JSON object. @@ -46,7 +46,7 @@ Example: } ``` -### JWS JSON General +### JWS JSON general This serialization mode is similar to the JWS JSON Flattened, but may contain more than one signature. It it a JSON object. @@ -83,7 +83,7 @@ Example: } ``` -### JWS Serializer Manager +### JWS serializer manager The serializer manager can be helpful when your application deals more than one serialization mode. @@ -107,9 +107,9 @@ $token = $manager->serialize('jws_json_flattened', $jws, 1); $jws = $manager->unserialize($token); ``` -## JWE Serialization +## JWE serialization -### JWE Compact +### JWE compact This serialization mode is probably the one you know the most. It it a string composed of five parts encoded in Base64 Url Safe and separated by a dot (`.`). @@ -126,7 +126,7 @@ There are some limitations when you use this serialization mode: * No Additional Authentication Data can be used. * No shared unprotected header or per-recipient header can be used. -### JWE JSON Flattened +### JWE JSON flattened This serialization mode is useful when you need to use the unprotected header. It it a simple JSON object. @@ -146,7 +146,7 @@ Example: } ``` -### JWE JSON General +### JWE JSON general This serialization mode is similar to the JWE JSON Flattened, but may contain more than one recipient. It it a JSON object. @@ -174,7 +174,7 @@ Example: } ``` -### JWE Serializer Manager +### JWE serializer manager The serializer manager can be helpful when your application deals more than one serialization mode. diff --git a/docs/advanced-topics/signed-tokens-and/detached-payload.md b/docs/advanced-topics/signed-tokens-and/detached-payload.md index b79ff05..a4f6153 100644 --- a/docs/advanced-topics/signed-tokens-and/detached-payload.md +++ b/docs/advanced-topics/signed-tokens-and/detached-payload.md @@ -1,8 +1,8 @@ -# Detached Payload +# Detached payload As per the [RFC7519](https://tools.ietf.org/html/rfc7515#appendix-F),the payload of a JWS may be detached. This framework supports this feature. -## JWS Creation +## JWS creation There is not much difference between the creation of a JWS with or without detached payload. The following example comes from the [JWS Creation page](../../the-components/signed-tokens-jws/jws-creation.md). There is only one argument that will change during the call of `withPayload`. @@ -48,7 +48,7 @@ $jws = $jwsBuilder And voilà! When you will serialize this token, the payload will not be present. -## JWS Loading +## JWS loading The loading of a signed token with a detached payload is as easy as when the payload is attached. The only difference is that you have to pass the payload to the JWS Verifier when you want to check the signature. diff --git a/docs/advanced-topics/signed-tokens-and/multiple-signatures.md b/docs/advanced-topics/signed-tokens-and/multiple-signatures.md index 02d1618..f924b14 100644 --- a/docs/advanced-topics/signed-tokens-and/multiple-signatures.md +++ b/docs/advanced-topics/signed-tokens-and/multiple-signatures.md @@ -1,4 +1,4 @@ -# Multiple Signatures +# Multiple signatures When you need to sign the same payload for several audiences, you may want to do it at once. The JWS Builder supports multiple signatures. diff --git a/docs/advanced-topics/signed-tokens-and/unencoded-payload.md b/docs/advanced-topics/signed-tokens-and/unencoded-payload.md index 15de895..daddc4f 100644 --- a/docs/advanced-topics/signed-tokens-and/unencoded-payload.md +++ b/docs/advanced-topics/signed-tokens-and/unencoded-payload.md @@ -1,4 +1,4 @@ -# Unencoded Payload +# Unencoded payload The [RFC7797](https://tools.ietf.org/html/rfc7797) allows the use of an unencoded payload for the signed tokens. This behaviour is interesting when your tokens have a detached payload and may reduce the token computation. diff --git a/docs/advanced-topics/signed-tokens-and/unprotected-header.md b/docs/advanced-topics/signed-tokens-and/unprotected-header.md index 306c692..9c50784 100644 --- a/docs/advanced-topics/signed-tokens-and/unprotected-header.md +++ b/docs/advanced-topics/signed-tokens-and/unprotected-header.md @@ -1,4 +1,4 @@ -# Unprotected Header +# Unprotected header You may want to set data in a token header that are not important for your application (e.g. general information). The integrity protection of the data is therefore not needed at all. diff --git a/docs/benchmark/benchmarks.md b/docs/benchmark/benchmarks.md index 926f967..0bbd6c7 100644 --- a/docs/benchmark/benchmarks.md +++ b/docs/benchmark/benchmarks.md @@ -1,4 +1,4 @@ -# How To +# How to You can easily check if an algorithm is fast enough on your platform. This project has tests for all operations with (almost) all algorithms. @@ -12,7 +12,7 @@ To run those tests, you must install the library with all dev dependencies. When **The previous command will test ALL algorithms and may take more than 7 hours.** -## Algorithm Selection +## Algorithm selection We recommend you to run tests only for the algorithm(s) you want to use. Just run the following command: @@ -83,7 +83,7 @@ Test the RSA1\_5 algorithm: ./vendor/bin/phpbench run --group RSA1_5 --store ``` -## Benchmark Details +## Benchmark details The result of the following command will only give you partial result. For example: diff --git a/docs/console-command/console.md b/docs/console-command/console.md index 44ba68e..0553e2a 100644 --- a/docs/console-command/console.md +++ b/docs/console-command/console.md @@ -7,7 +7,7 @@ They are available: * [through the dedicated Symfony console command](symfony-console.md) * [as a PHAR (PHP Archive)](phar-application.md) -## Available Commands +## Available commands In the following example, we will call commands using `./jose.phar`. If you need more information about a command, call the command with the option `--help`. @@ -17,9 +17,9 @@ You can save the output in a file e.g. when you want to store a key or keyset in ./jose.phar key:convert:pkcs1 '{"kty":"EC","crv":"P-256","d":"kiNCxSbRjlAbHrEbrwVKS8vIXUh6URChrmw","x":"-wdLWDWCZP6oFYl8aGVfU0MsFlckjaSVrO7hEsc8lgk","y":"rt8XDTalLMCRB5Tu9WQc2d0TOVwXXHkVDbI7cIig6r4"}' > key.pem ``` -### Key Management Commands +### Key management commands -#### Private Key To Public Key Converter +#### Private key to public key converter This command will convert a private key into a public key. It has no effect on shared keys (e.g. `oct` keys). @@ -29,7 +29,7 @@ This command will convert a private key into a public key. It has no effect on s {"kty":"EC","crv":"P-256","x":"-wdLWDWCZP6oFYl8aGVfU0MsFlckjaSVrO7hEsc8lgk","y":"rt8XDTalLMCRB5Tu9WQc2d0TOVwXXHkVDbI7cIig6r4"} ``` -#### Key Analyze +#### Key analyze The following command will analyze the key passed as argument and find issues. @@ -42,7 +42,7 @@ The parameter "kid" should be added. The key length is less than 128 bits. ``` -#### PKCS#1 Key Converter +#### PKCS#1 key converter This command will convert a RSA or EC key into PKCS#1 key. @@ -56,7 +56,7 @@ wJEHlO71ZBzZ3RM5XBdceRUNsjtwiKDqvg== -----END EC PRIVATE KEY----- ``` -#### Key Generators +#### Key generators The key generator commands will generate a private or shared key. The following options are available: @@ -127,7 +127,7 @@ In case your secret is binary string, you will have to encode it first (Base64) ./jose.phar key:generate:from_secret "VGhpcyBpcyBteSBzZWNyZXQ=" --is_b64 ``` -#### Key Loaders +#### Key loaders The key loader commands will loader keys from various sources. The following options are available: @@ -164,7 +164,7 @@ This command can load and convert a X.509 key file into a JWK. {"kty":"OKP","crv":"X25519","x":"TgTD7RS0KF3eU8HdTM6ACxu365uco3x2Cee9SBXiu2I"} ``` -#### RSA Key Optimization +#### RSA key optimization This command optimizes a RSA key by calculating additional primes (CRT). The following option is available: @@ -176,7 +176,7 @@ This command optimizes a RSA key by calculating additional primes (CRT). The fol _RSA keys generated by this framework are already optimized. This command may be needed when you import RSA keys from external sources._ _The optimization is not mandatory but highly recommended. cryptographic operations are up to 10 times faster._ -#### Key Thumbprint +#### Key thumbprint This command will calculate the key thumbprint as per the [RFC7638](https://tools.ietf.org/html/rfc7638). The following options are available: @@ -188,9 +188,9 @@ This command will calculate the key thumbprint as per the [RFC7638](https://tool gNur2UtA8NMAoxJfgMYhJqnuWR8u-60aeRbKtZwj4DE ``` -### Keyset Management Commands +### Keyset management commands -#### Private Keys To Public Keys Converter +#### Private keys to public keys converter This command has the same affect as `key:convert:public` except that it will convert all keys in the keyset. It has no effect on shared keys (e.g. `oct` keys). @@ -200,7 +200,7 @@ This command has the same affect as `key:convert:public` except that it will con ``` -#### Key Analyze +#### Key analyze This command has the same behaviour as `key:analyze` except that it will analize all keys in the keyset. @@ -210,7 +210,7 @@ This command has the same behaviour as `key:analyze` except that it will analize ``` -#### Keyset Generators +#### Keyset generators The key set generator commands will generate key sets with random keys of the same type. @@ -227,13 +227,13 @@ Examples: The result of these commands is a JWKSet object. -#### Key Set Modification +#### Key set modification * `keyset:add:key`: Add a key into a key set. * `keyset:merge`: Merge several key sets into one. * `keyset:rotate`: Rotate a key set. -#### Distant Key Set Loading +#### Distant key set loading * `keyset:load:jku`: Loads a key set from an url. * `keyset:load:x5u`: Loads a key set from an url. diff --git a/docs/console-command/phar-application.md b/docs/console-command/phar-application.md index c2b2530..bdee355 100644 --- a/docs/console-command/phar-application.md +++ b/docs/console-command/phar-application.md @@ -1,4 +1,4 @@ -# PHAR Application +# PHAR application ## Installation diff --git a/docs/console-command/standalone.md b/docs/console-command/standalone.md index ed2a7a0..002650d 100644 --- a/docs/console-command/standalone.md +++ b/docs/console-command/standalone.md @@ -1,4 +1,4 @@ -# Standalone Application +# Standalone application ## Installation diff --git a/docs/introduction/provided-features.md b/docs/introduction/provided-features.md index 3de44f6..563fe4e 100644 --- a/docs/introduction/provided-features.md +++ b/docs/introduction/provided-features.md @@ -1,6 +1,6 @@ -# Provided Features +# Provided features -## Supported Input Types: +## Supported input types: JWS or JWE objects support every input that can be encoded into JSON: @@ -9,7 +9,7 @@ JWS or JWE objects support every input that can be encoded into JSON: The [detached payload](../advanced-topics/signed-tokens-and/detached-payload.md) is supported. -## Supported Serialization Modes +## Supported serialization modes | Serialization syntax | JWS | JWE | | -------------------- | --- | --- | @@ -17,13 +17,13 @@ The [detached payload](../advanced-topics/signed-tokens-and/detached-payload.md) | Flattened JSON | YES | YES | | General JSON | YES | YES | -## Supported Compression Methods +## Supported compression methods !!! danger Compression is not recommended. For 4.0.0, the support of compression is no longer available. See [RFC8725](https://datatracker.ietf.org/doc/html/rfc8725#section-3.6) for more information. -## Supported Key Types (JWK) +## Supported key types (JWK) | Key Type | Supported | Comment | | -------- | --------- | ------------------------------------- | @@ -38,11 +38,11 @@ JWK objects support JSON Web Key Thumbprint ([RFC 7638](https://tools.ietf.org/h A `none` key type for the `none` algorithm. It is used to explicitly allow this unsecured algorithm. -## Key Sets (JWKSet) +## Key sets (JWKSet) JWKSet is fully supported. -## Supported Signature Algorithms +## Supported signature algorithms | Signature Algorithm | Supported | Comment | | ------------------------------------ | --------- | ---------------------------------------------------------------------------------------------------------- | @@ -58,7 +58,7 @@ JWKSet is fully supported. Other signature algorithms like `RS1`, `HS1` or `HS256/64` are also available. These algorithms should be used for testing purpose only or for compatibility with old systems -## Supported Key Encryption Algorithms +## Supported key encryption algorithms | Key Encryption Algorithm | Supported | | | ----------------------------------------------------------------------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | @@ -80,7 +80,7 @@ JWKSet is fully supported. The algorithms `RSA1_5` and `RSA-OAEP` are now deprecated. Please use with caution. -## Supported Content Encryption Algorithms +## Supported content encryption algorithms | Content Encryption Algorithm | Supported | | ------------------------------------------------------------ | --------- | diff --git a/docs/introduction/security-recommendations.md b/docs/introduction/security-recommendations.md index 3d4897b..3c107ea 100644 --- a/docs/introduction/security-recommendations.md +++ b/docs/introduction/security-recommendations.md @@ -1,4 +1,4 @@ -# Security Recommendations +# Security recommendations Signed or Encrypted Tokens are not just the next trendy/popular way to authenticate users. They provide great features but when used incorrectly they can expose your application to major security issues. @@ -6,32 +6,32 @@ Please read the following recommendations carefully. ## Algorithms -### Algorithm Choice +### Algorithm choice If all parties are able to protect their keys (e.g. private applications), symmetric algorithms are a good choice as they are faster in general. If you use public clients, you should prefer asymmetric algorithms. -### Available Algorithms +### Available algorithms This framework provides dozen of signature and encryption algorithms, but you do not need all of them. Most applications only support 1 or 2 algorithms. You should only use necessary algorithms. For example, HS384 algorithm may be avoided if you already have HS256 and HS512. -### Avoid Weak Algorithms +### Avoid weak algorithms Some algorithms are not recommended as there are known security issues: * `none`: this algorithm is not a real algorithm. It should only be used when other security means exist. An encrypted connection is certainly not enough! * `RSA1_5`: there are known attacks using this algorithm. If you can avoid its use, then do it. -## Keys And Key Sets +## Keys and key sets -### Key Size +### Key size A small key size is as secured as a password like `123456789`. You should use at least 256 bits symmetric keys and at lease 2048 bits RSA keys. In any case, you MUST use a true random number generator. -### Additional Information +### Additional information It is highly recommended to set the following parameters to your key: @@ -39,31 +39,31 @@ It is highly recommended to set the following parameters to your key: * `use`: indicates the usage of the key. Either `sig` (signature/verification) or `enc` (encryption/decryption). * `alg`: the algorithm allowed to be used with this key. -### Key Rotation +### Key rotation A key is fine but may be cracked e.g. by bruteforce. Changing your keys after several days or weeks is encouraged. -## Token Creation +## Token creation -### Header Parameters +### Header parameters Broadly speaking, you should set your header parameter in the protected header. The use of the unprotected header should be limited to specific use cases. When using encrypted tokens, the claims `iss` and `aud` should be duplicated into the header. This will avoid unwanted decryption when tokens are sent to a wrong audience. -### Payload And Claims +### Payload and claims There is no size constraint for the payload, but when tokens are used in a web context, it should be as small as possible. When used, claims should be limited to the minimum. Does your application really need to get all the information about a user? For each context, you should choose carefully the claims you want to use. -#### Token Unique ID +#### Token unique ID A unique token ID should be set to all tokens you create. The associated claim is `jti`. This claim is highly recommended as it can prevent replay attacks. -#### Time Indicators +#### Time indicators The JWT specification introduces several claims to limit the period of validity of the tokens: @@ -73,17 +73,17 @@ The JWT specification introduces several claims to limit the period of validity These claims are not mandatory, but it is recommended to define a period of time for the token validity. When used, the expiration time should be appropriate to its context in your application. A security token with 2 weeks lifetime is something you should avoid. -#### Issuer And Audience +#### Issuer and audience The claims `iss` (issuer) and `aud` (audience) should always be set. When duplicated in the header, their values MUST be identical. -## Application Communication +## Application communication -### Secured Connection +### Secured connection Unless you use encrypted tokens, you should use a secured connection when transmitting tokens between parties. A secured communication is not only needed when transmitting tokens, but also when you exchange keys and key sets with other applications. -## Loading Process +## Loading process When you receive a token, the following steps should be followed in this order. If one failed, you **must** reject the whole token. @@ -97,11 +97,11 @@ When you receive a token, the following steps should be followed in this order. Regarding header verification, it is important to verify **ALL** of them. There are known vulnerabilities on e.g. algorithm swapping (`alg` changed to `none`) or Denial Of Service (`p2c` set to a very high value for overloading the server). -### Unserialize The Token +### Unserialize the token You should only use the serialization mode(s) you need. If you intend to use your tokens in a web context, then use only the Compact Serialization. If an error occurred during this process, you should consider the token as invalid. -### Check The Header +### Check the header It is strongly recommended that all header parameters are checked before the cryptographic operations (signature verification or content decryption) @@ -109,17 +109,17 @@ Please note that unknown header parameters must be ignored. If your token is ver When used, unprotected header parameters should be handled with care. -### Signature Verification / Payload Decryption +### Signature verification / payload decryption Let the component do its job. The most important step for developers is to ensure that the right key/ket set is used. -### Check The Claims +### Check the claims This step is only required if the payload contains claims. When present, you should always check the `exp`, `iat`, `nbf`, `iss` and `aud` claims. Application specific claims should also always checked. The whole token should be rejected in case of failure. Unknown claims should be ignored. -## Stay Tuned +## Stay tuned You should subscribe to security forums of similar websites and have a continuous technological watch. The tokens may be compromised because of malicious attacks on the algorithms, keys or other components related to the JWT (directly or indirectly). diff --git a/docs/introduction/the-framework.md b/docs/introduction/the-framework.md index e2cc9f4..14f90f0 100644 --- a/docs/introduction/the-framework.md +++ b/docs/introduction/the-framework.md @@ -1,4 +1,4 @@ -# The Framework +# The framework The JWT Framework is the main package and contains all features and components described in this documentation. It is split in several sub-packages depending on your needs. diff --git a/docs/migration/from-v1.x-to-v2.0-2.md b/docs/migration/from-v1.x-to-v2.0-2.md index d97a940..9093e48 100644 --- a/docs/migration/from-v1.x-to-v2.0-2.md +++ b/docs/migration/from-v1.x-to-v2.0-2.md @@ -12,7 +12,7 @@ Next, you have to verify you don’t use any deprecated class, interface, method ### List of deprecations: -#### Deprecated Packages +#### Deprecated packages The following packages are deprecated. Please install `web-token/jwt-library` or `web-token/jwt-experimental` instead. @@ -33,7 +33,7 @@ The following packages are deprecated. Please install `web-token/jwt-library` or * `web-token/jwt-encryption-algorithm-*` * `web-token/jwt-nested-token` -#### PSR-20 Clock +#### PSR-20 clock In previous versions, the classes that requires time used the PHP time function directly. It is now required to use a PSR-20 Clock implementation and pass it to the classes. @@ -43,11 +43,11 @@ In previous versions, the classes that requires time used the PHP time function For version 3.2.0+ and the Symfony Bundle, an internal implementation service named `jose.internal_clock` existed and is removed. -#### Simplified Algorithm Manager +#### Simplified algorithm manager Classes `Jose\Component\Encryption\JWEBuilder` and `Jose\Component\Encryption\JWEDecrypter` no longer need the Key Encryption and Content Encryption Algorithm Managers. You pass only one Algorithm Manager to the contructor. -#### Version Bumped +#### Version bumped All previous major release of the following packages are not supported anymore. Please make sure your platform can use them. diff --git a/docs/the-components/algorithm-management-jwa.md b/docs/the-components/algorithm-management-jwa.md index c0c9413..1ee0fb4 100644 --- a/docs/the-components/algorithm-management-jwa.md +++ b/docs/the-components/algorithm-management-jwa.md @@ -1,4 +1,4 @@ -# Algorithm Management (JWA) +# Algorithm management (JWA) For each cryptographic operation, you will need at least one algorithm and one key. @@ -23,7 +23,7 @@ $algorithmManager = new AlgorithmManager([ It is not possible to set the same algorithm twice in the same algorithm manager. -## Algorithm Manager Factory +## Algorithm manager factory Your application may need several algorithm managers for several use cases. For example you application may use JWT for: diff --git a/docs/the-components/claim-checker.md b/docs/the-components/claim-checker.md index d519580..dc5df2a 100644 --- a/docs/the-components/claim-checker.md +++ b/docs/the-components/claim-checker.md @@ -1,8 +1,8 @@ -# Claim Checker +# Claim checker JSON Web Tokens can be used to transport any kind of data. They are mainly used to transport claims. When you receive a tokens that contains claims, it is important to check the values of these claims. -## Claim Checker Manager +## Claim checker manager In the following example, we will create a manager able to check the `aud` (Audience), `iat` (Issued At), `nbf` (Not Before) and `exp` (Expiration) claims. @@ -43,7 +43,7 @@ In the following example, an exception will be thrown if the `iss`, `sub` or `au $claimCheckerManager->check($claims, ['iss', 'sub', 'aud']); ``` -## Custom Claim Checker +## Custom claim checker Your application may use other claims that you will have to check therefore custom claim checkers have to be created. @@ -89,7 +89,7 @@ final class FooChecker implements ClaimChecker All done! Now you can instantiate your class and add it to your Claim Checker Manager. -## Replicating Claims as Header Parameters +## Replicating claims as header parameters The [RFC7516 section 5.3](https://tools.ietf.org/html/rfc7519#section-5.3) allows to replicate some claims in the header. This behaviour is very useful with encrypted tokens as it helps to reject invalid tokens without decryption of the payload. @@ -97,7 +97,7 @@ The Claim Checker Manager cannot check those replicated claims, you have to crea Have a look at the `IssuedAtChecker` or the `NotBeforeChecker` classes. These checkers can be used for claim and header checks. -## Claim Checker Manager Factory +## Claim checker manager factory Your application may use JSON Web Tokens in different contexts and thus the meaning of a claim may be different. You will need several Claim Checker Managers with dedicated claim checkers. diff --git a/docs/the-components/encrypted-tokens-jwe/README.md b/docs/the-components/encrypted-tokens-jwe/README.md index a3745a9..a2ea27f 100644 --- a/docs/the-components/encrypted-tokens-jwe/README.md +++ b/docs/the-components/encrypted-tokens-jwe/README.md @@ -1,4 +1,4 @@ -# Encrypted Tokens (JWE) +# Encrypted tokens (JWE) A very large number of key and content encryption algorithms is provided by the library. Please refer to [this encryption algorithm table](encryption-algorithms.md) to know what algorithms are available. diff --git a/docs/the-components/encrypted-tokens-jwe/encryption-algorithms.md b/docs/the-components/encrypted-tokens-jwe/encryption-algorithms.md index 89a30ba..4f9ab44 100644 --- a/docs/the-components/encrypted-tokens-jwe/encryption-algorithms.md +++ b/docs/the-components/encrypted-tokens-jwe/encryption-algorithms.md @@ -1,13 +1,13 @@ -# Encryption Algorithms +# Encryption algorithms This framework comes with several encryption algorithms. These algorithms are in the following namespaces: * `Jose\Component\Encryption\Algorithm\KeyEncryption`: key encryption algorithms * `Jose\Component\Encryption\Algorithm\ContentEncryption`: content encryption algorithms -## Main Algorithms +## Main algorithms -### Key Encryption +### Key encryption !!! info @@ -27,7 +27,7 @@ This framework comes with several encryption algorithms. These algorithms are in Please note that the additional header parameters **MUST** be present and **MUST** be understood. Depending on the algorithm you use, you may be required to check headers BEFORE the decryption operation. Please create a [custom Header Checker](../header-checker.md) for theses parameters. -### Content Encryption +### Content encryption | Algorithm | Package | | ------------------------------------------------------------ | ------------------------------------------- | @@ -40,11 +40,11 @@ This framework comes with several encryption algorithms. These algorithms are in The algorithms `ECDH-ES*` are not recommended unless used with the `OKP` key type. -## Experimental Algorithms +## Experimental algorithms The following algorithms are experimental and must not be used in production unless you know what you are doing. **They are proposed for testing purpose only.** -### Key Encryption +### Key encryption | Algorithm | Description | |---|---| @@ -52,13 +52,13 @@ The following algorithms are experimental and must not be used in production unl | Chacha20+Poly1305 | *Please note that this algorithm requires OpenSSL 1.1* | | RSA-OAEP-384
RSA-OAEP-512 | Same algorithm as RSA-OAEP-256 but with SHA-384 and SHA-512 hashing functions | -### Content Encryption +### Content encryption | Algorithm | Description | |---|---| | A128CCM-16-128
A128CCM-16-64
A128CCM-64-128
A128CCM-64-64
A256CCM-16-128
A256CCM-16-64
A256CCM-64-128
A256CCM-64-64 | AES-CCM based algorithms | -## How To Use +## How to use These algorithms have to be used with the [Algorithm Manager](../algorithm-management-jwa.md). diff --git a/docs/the-components/encrypted-tokens-jwe/jwe-creation.md b/docs/the-components/encrypted-tokens-jwe/jwe-creation.md index 33c67b5..a581e8a 100644 --- a/docs/the-components/encrypted-tokens-jwe/jwe-creation.md +++ b/docs/the-components/encrypted-tokens-jwe/jwe-creation.md @@ -1,4 +1,4 @@ -# JWE Creation +# JWE creation The computation of a JWE is done by the `JWEBuilder` object. This object requires the following services: diff --git a/docs/the-components/encrypted-tokens-jwe/jwe-loading.md b/docs/the-components/encrypted-tokens-jwe/jwe-loading.md index 8e61c95..f77df17 100644 --- a/docs/the-components/encrypted-tokens-jwe/jwe-loading.md +++ b/docs/the-components/encrypted-tokens-jwe/jwe-loading.md @@ -1,4 +1,4 @@ -# JWE Loading +# JWE loading Encrypted tokens are loaded by a serializer or the serializer manager and decrypted by the `JWEDecrypter` object. This JWEDecrypter object requires several services for the process: @@ -69,7 +69,7 @@ $success = $jweDecrypter->decryptUsingKey($jwe, $jwk, 0); OK so if not exception is thrown, then your token is loaded and the payload correctly decrypted. -## JWELoader Object +## JWELoader object To avoid duplication of code lines, you can create a `JWELoader` object. This object contains a serializer, a decrypter and an optional header checker (highly recommended). @@ -93,7 +93,7 @@ $jwe = $jweLoader->loadAndDecryptWithKey($token, $key, $recipient); In case you use a key set, you can use the method `loadAndDecryptWithKeySet`. -## JWELoaderFactory Object +## JWELoaderFactory object > This feature was introduced in version 1.1. diff --git a/docs/the-components/examples.md b/docs/the-components/examples.md index 4dd9e17..96d7a02 100644 --- a/docs/the-components/examples.md +++ b/docs/the-components/examples.md @@ -1,6 +1,6 @@ # Examples -## JWS Creation +## JWS creation ```php linenums="1" serialize($jws); var_dump($token); ``` -## JWS Loading and Verification +## JWS loading and verification ```php linenums="1" serialize($jwe, 0); var_dump($token); ``` -## JWE Loading and Verification +## JWE loading and verification ```php linenums="1" check($jwt, 0, ['alg', 'enc', 'crit']); ``` -## Provided Header Checker Objects +## Provided header checker objects The library provides several header checker classes you can instantiate and use at will. They are all located in the namespace `Jose\Component\Checker`. @@ -82,7 +82,7 @@ The library provides several header checker classes you can instantiate and use | CallableChecker | Generic object that can execute a callable for checking a particular parameter | No | | IsEqualChecker | Generic object that can compare a particular parameter to a predefined value | No | -## Header Checker Manager Factory +## Header checker manager factory The Header Checker Manager Factory will help you to create as many Header Checker Manager as you want to fit on your application requirements. @@ -104,7 +104,7 @@ $headerCheckerManagerForSignatures = $headerCheckerManagerFactory->create(['sign $headerCheckerManagerForEncryption = $headerCheckerManagerFactory->create(['key_encryption_alg']); ``` -## Custom Header Checker +## Custom header checker With the previous examples, we will only check the `alg` (algorithm) header parameter. But your application may use other header parameters e.g. `cty`, `typ`... diff --git a/docs/the-components/key-jwk-and-key-set-jwkset/README.md b/docs/the-components/key-jwk-and-key-set-jwkset/README.md index 761fdf7..7816701 100644 --- a/docs/the-components/key-jwk-and-key-set-jwkset/README.md +++ b/docs/the-components/key-jwk-and-key-set-jwkset/README.md @@ -1,4 +1,4 @@ -# Key (JWK) and Key Set (JWKSet) +# Key (JWK) and key set (JWKSet) To perform cryptographic operations (signature/verification and encryption/decryption), you will need cryptographic keys. diff --git a/docs/the-components/key-jwk-and-key-set-jwkset/key-management.md b/docs/the-components/key-jwk-and-key-set-jwkset/key-management.md index 5ce60cc..7eed97a 100644 --- a/docs/the-components/key-jwk-and-key-set-jwkset/key-management.md +++ b/docs/the-components/key-jwk-and-key-set-jwkset/key-management.md @@ -32,7 +32,7 @@ $public_key = $jwk->toPublic(); json_encode($jwk); ``` -## Generate A New Key +## Generate a new key This framework is able to create private and public keys on the fly using the `JWKFactory`. 4 types of keys are supported: @@ -47,7 +47,7 @@ This framework is able to create private and public keys on the fly using the `J The `none` algorithm needs a key of type `none`. This is a specific key type that must only be used with this algorithm. -### Octet String +### Octet string The following example will show you how to create an `oct` key. @@ -83,7 +83,7 @@ $jwk = JWKFactory::createFromSecret( ); ``` -### RSA Key Pair +### RSA key pair The following example will show you how to create a `RSA` key. @@ -102,7 +102,7 @@ $private_key = JWKFactory::createRSAKey( ]); ``` -### Elliptic Curve Key Pair +### Elliptic curve key pair The following example will show you how to create a `EC` key. @@ -120,7 +120,7 @@ The supported curves are: * `P-384` * `P-521` (note that this is **521** and not 512) -#### Octet Key Pair +#### Octet key pair The following example will show you how to create a `OKP` key. @@ -137,7 +137,7 @@ The supported curves are: * `Ed25519` for signature/verification only * `X25519` for encryption/decryption only -### None Key +### None key The `none` key type is a special type used only for the `none` algorithm. @@ -149,9 +149,9 @@ use Jose\Component\KeyManagement\JWKFactory; $key = JWKFactory::createNoneKey(); ``` -## Create Key From External Sources +## Create key from external sources -### From Values +### From values In case you already have key values, you can create a key by passing those values as an argument: @@ -170,7 +170,7 @@ $key = JWKFactory::createFromValues([ ]); ``` -### From A Key File +### From a key file You can convert a PKCS#1 or PKCS#8 key file into a JWK. The following method supports PEM and DER formats. Encrypted keys are also supported. @@ -188,7 +188,7 @@ $key = JWKFactory::createFromKeyFile( ); ``` -### From A PKCS#12 Certificate +### From a PKCS#12 certificate You can convert a PKCS#12 Certificate into a JWK. Encrypted certificates are also supported. @@ -206,7 +206,7 @@ $key = JWKFactory::createFromPKCS12CertificateFile( ); ``` -### From A X.509 Certificate +### From a X.509 certificate You can convert a X.509 Certificate into a JWK. diff --git a/docs/the-components/key-jwk-and-key-set-jwkset/key-set-management.md b/docs/the-components/key-jwk-and-key-set-jwkset/key-set-management.md index 4180851..825bc32 100644 --- a/docs/the-components/key-jwk-and-key-set-jwkset/key-set-management.md +++ b/docs/the-components/key-jwk-and-key-set-jwkset/key-set-management.md @@ -1,4 +1,4 @@ -# Key Set (JWKSet) +# Key set (JWKSet) You can create a JWKSet object using three static methods: diff --git a/docs/the-components/signed-tokens-jws/README.md b/docs/the-components/signed-tokens-jws/README.md index 1dc0336..117c85c 100644 --- a/docs/the-components/signed-tokens-jws/README.md +++ b/docs/the-components/signed-tokens-jws/README.md @@ -1,4 +1,4 @@ -# Signed Tokens (JWS) +# Signed tokens (JWS) A very large number of signature algorithms is provided by the library. Please refer to [this signature algorithm table](signature-algorithms.md) to know what algorithms are available. diff --git a/docs/the-components/signed-tokens-jws/jws-creation.md b/docs/the-components/signed-tokens-jws/jws-creation.md index 8330fa3..bbf047d 100644 --- a/docs/the-components/signed-tokens-jws/jws-creation.md +++ b/docs/the-components/signed-tokens-jws/jws-creation.md @@ -1,4 +1,4 @@ -# JWS Creation +# JWS creation Now that you have an algorithm manager and a key, it is time to create your first signed token. diff --git a/docs/the-components/signed-tokens-jws/jws-loading.md b/docs/the-components/signed-tokens-jws/jws-loading.md index 11393e6..46c59da 100644 --- a/docs/the-components/signed-tokens-jws/jws-loading.md +++ b/docs/the-components/signed-tokens-jws/jws-loading.md @@ -1,8 +1,8 @@ -# JWS Loading +# JWS loading Signed tokens are loaded by a serializer or the serializer manager and verified by the `JWSVerifier` object. This JWSVerifier object just requires an algorithm manager. -## Serializer And Verifier +## Serializer and verifier In the following example, we will try to load a signed token. We will only use the `HS256` algorithm. @@ -64,7 +64,7 @@ $isVerified = $jwsVerifier->verifyWithKey($jws, $jwk, 0); The method `verifyWithKey` returns a boolean. If true, then your token signature is valid. You can then check the claims (if any) using the claim checker manager. -## JWSLoader Object +## JWSLoader object To avoid duplication of code lines, you can create a `JWSLoader` object. This object contains a serializer, a verifier and an optional header checker (highly recommended). @@ -88,7 +88,7 @@ $jws = $jwsLoader->loadAndVerifyWithKey($token, $jwk, $signature, $payload); In case you use a key set, you can use the method `loadAndVerifyWithKeySet`. -## JWSLoaderFactory Object +## JWSLoaderFactory object > This feature was introduced in version 1.1. diff --git a/docs/the-components/signed-tokens-jws/signature-algorithms.md b/docs/the-components/signed-tokens-jws/signature-algorithms.md index c651d45..ace618c 100644 --- a/docs/the-components/signed-tokens-jws/signature-algorithms.md +++ b/docs/the-components/signed-tokens-jws/signature-algorithms.md @@ -1,4 +1,4 @@ -# Signature Algorithms +# Signature algorithms This framework comes with several signature algorithms. These algorithms are in the following namespace: `Jose\Component\Signature\Algorithm`. @@ -11,7 +11,7 @@ This framework comes with several signature algorithms. These algorithms are in | EdDSA (*only with the* Ed25519 *curve*) | Edwards-curve Digital Signature Algorithm (EdDSA) | | none | **Not a secure algorithm. Please use with caution** | -### Experimental Algorithms +### Experimental algorithms The following signature algorithms are experimental and must not be used in production unless you know what you are doing. **They are proposed for testing purpose only.** @@ -23,7 +23,7 @@ They are provided throught the package `web-token/jwt-experimental`. | HS1 | HMAC with SHA-1 hashing function | | ES256K | Elliptic curve secp256k1 support | -## How To Use +## How to use These algorithms have to be used with the [Algorithm Manager](../algorithm-management-jwa.md). They do not need any arguments. diff --git a/docs/the-symfony-bundle/algorithm-management.md b/docs/the-symfony-bundle/algorithm-management.md index 84ee1bc..bbd8510 100644 --- a/docs/the-symfony-bundle/algorithm-management.md +++ b/docs/the-symfony-bundle/algorithm-management.md @@ -1,6 +1,6 @@ -# Algorithm Management +# Algorithm management -## Algorithm Manager Factory Service +## Algorithm manager factory service The Symfony Bundle provides an Algorithm Manager Factory service. The available algorithms depends on the components installed on your application. @@ -13,7 +13,7 @@ $algorithmManagerFactory = $container->get(AlgorithmManagerFactory::class); $algorithmManager = $algorithmManagerFactory->create(['RS256', 'HS512']); ``` -## Custom Algorithm +## Custom algorithm This factory handles all algorithms services tagged with `jose.algorithm`. @@ -28,7 +28,7 @@ services: Your algorithm will be available through the algorithm manager factory service and the alias `FOO`. -## PBES2-\* Algorithms +## PBES2-\* algorithms When installed, the `PBES2-*` algorithms available throught the algorithm manager factory. They have the default configuration i.e. salt size = 62 bits and count = 4096. If these values does not fit on your needs, you can create a new algorithm service with your own values: diff --git a/docs/the-symfony-bundle/configuration-helper.md b/docs/the-symfony-bundle/configuration-helper.md index b6c3d96..25b21b3 100644 --- a/docs/the-symfony-bundle/configuration-helper.md +++ b/docs/the-symfony-bundle/configuration-helper.md @@ -1,4 +1,4 @@ -# Configuration Helper +# Configuration helper When you want to create keys/key sets, JWS loader/verifier... services, you have to create a dedicated `jose` section in your configuration. It may confuse your users to configure your bundle and the Jose Framework bundle. Sometimes, you may also want to be sure that the configuration is correctly defined. Lastly, the configuration size increases with numerous details, options or service IDs and it becomes difficult to read or modify. diff --git a/docs/the-symfony-bundle/encrypted-tokens/README.md b/docs/the-symfony-bundle/encrypted-tokens/README.md index 25b860d..bb295ce 100644 --- a/docs/the-symfony-bundle/encrypted-tokens/README.md +++ b/docs/the-symfony-bundle/encrypted-tokens/README.md @@ -1,4 +1,4 @@ -# Encrypted Tokens +# Encrypted tokens Encryption algorithms are automatically handled by the Algorithm Manager Factory. diff --git a/docs/the-symfony-bundle/encrypted-tokens/jwe-creation.md b/docs/the-symfony-bundle/encrypted-tokens/jwe-creation.md index 123bef5..4620d6d 100644 --- a/docs/the-symfony-bundle/encrypted-tokens/jwe-creation.md +++ b/docs/the-symfony-bundle/encrypted-tokens/jwe-creation.md @@ -1,6 +1,6 @@ # JWE creation -## JWE Builder Factory Service +## JWE builder factory service A `JWEBuilderFactory` is available as a service in your application container: @@ -19,7 +19,7 @@ $jweBuilder = $jweBuilderFactory->create(['A256GCMKW', 'A256CBC-HS256']); You can now use the JWEBuilder as explained in the JWE Creation section. -## JWE Builder As Service +## JWE builder as service There is also another way to create a JWEBuilder object: using the bundle configuration. @@ -39,7 +39,7 @@ With the previous configuration, the bundle will create a public JWE Builder ser $jweBuilder = $container->get('jose.jwe_builder.builder1'); ``` -## Custom Tags +## Custom tags You can add custom tags and attributes to the services you create. diff --git a/docs/the-symfony-bundle/encrypted-tokens/jwe-decryption.md b/docs/the-symfony-bundle/encrypted-tokens/jwe-decryption.md index f974e0b..f897b0c 100644 --- a/docs/the-symfony-bundle/encrypted-tokens/jwe-decryption.md +++ b/docs/the-symfony-bundle/encrypted-tokens/jwe-decryption.md @@ -1,6 +1,6 @@ # JWE decryption -## JWE Decrypter Factory Service +## JWE decrypter factory service A `JWEDecrypterFactory` is available as a service in your application container: @@ -23,7 +23,7 @@ You can now use the JWEDecrypter as explained in the JWE Creation section. Reminder: it is important to check the token headers. See the checker section of this documentation. -## JWE Decrypter As Service +## JWE decrypter as service There is also another way to create a JWEDecrypter object: using the bundle configuration. @@ -43,7 +43,7 @@ With the previous configuration, the bundle will create a public JWE Decrypter s $jweDecrypter = $container->get('jose.jwe_decrypter.decrypter1'); ``` -## Custom Tags +## Custom tags You can add custom tags and attributes to the services you create. @@ -58,7 +58,7 @@ jose: tag_name2: {attribute1: 'foo'} ``` -## JWE Loader Service +## JWE loader service The [`JWELoaderFactory`](../../the-components/encrypted-tokens-jwe/jwe-loading.md) is available as a public service. You can retrieve it using the container or inject it into your services. It will help you to create `JWELoader` objects on demand. diff --git a/docs/the-symfony-bundle/encrypted-tokens/jwe-serializers.md b/docs/the-symfony-bundle/encrypted-tokens/jwe-serializers.md index f74f4b3..d97d734 100644 --- a/docs/the-symfony-bundle/encrypted-tokens/jwe-serializers.md +++ b/docs/the-symfony-bundle/encrypted-tokens/jwe-serializers.md @@ -1,6 +1,6 @@ # JWE serializers -## JWE Serializer Manager Factory Service +## JWE serializer manager factory service A `JWESerializerManagerFactory` is available as a service in your application container: @@ -25,7 +25,7 @@ Available JWE serialization modes are: * `jwe_json_general` * `jwe_json_flattened` -## JWE Serializer Manager As Service +## JWE serializer manager as service There is also another way to create a JWESerializerManager object: using the bundle configuration. @@ -45,7 +45,7 @@ With the previous configuration, the bundle will create a public JWE Serializer $jweSerializerManager = $container->get('jose.jwe_serializer.serializer1'); ``` -## Custom Tags +## Custom tags You can add custom tags and attributes to the services you create. diff --git a/docs/the-symfony-bundle/header-and-claim-checker-management.md b/docs/the-symfony-bundle/header-and-claim-checker-management.md index d00fce2..47ac907 100644 --- a/docs/the-symfony-bundle/header-and-claim-checker-management.md +++ b/docs/the-symfony-bundle/header-and-claim-checker-management.md @@ -1,6 +1,6 @@ -# Header and Claim Checker Management +# Header and claim checker management -## Checker Manager Factory Services +## Checker manager factory services The Symfony Bundle provides Header and Claim Checker Manager Factory services. @@ -17,7 +17,7 @@ $claimCheckerManagerFactory = $container->get(ClaimCheckerManagerFactory::class) $claimCheckerManager = $claimCheckerManagerFactory->create([...]); ``` -## Checker Manager Services +## Checker manager services You can create Header and Claim Checker Managers using the bundle configuration. @@ -36,7 +36,7 @@ jose: With the previous configuration, the bundle will create public Header and Claim Checker Managers named `jose.header_checker.checker1` and `jose.claim_checker.checker1` with selected checkers. -## Custom Header Or Claim Checker +## Custom header or claim checker Some claim or header checkers are provided by this framework, but it is important to create custom checkers that fit on your application requirements. @@ -56,7 +56,7 @@ services These checkers will be loaded by the factories and you will be able to create a header or a claim checker manager using the aliases `foo` or `bar`. -## Custom Tags +## Custom tags You can add custom tags and attributes to the header and claim checker managers. diff --git a/docs/the-symfony-bundle/key-and-key-set-management/README.md b/docs/the-symfony-bundle/key-and-key-set-management/README.md index 51f9913..8c8b3ee 100644 --- a/docs/the-symfony-bundle/key-and-key-set-management/README.md +++ b/docs/the-symfony-bundle/key-and-key-set-management/README.md @@ -1,4 +1,4 @@ -# Key and Key Set Management +# Key and key set management We recommend you to load these objects through environment variables. With Symfony, an environment variables processor is provided: diff --git a/docs/the-symfony-bundle/key-and-key-set-management/key-management-jwk.md b/docs/the-symfony-bundle/key-and-key-set-management/key-management-jwk.md index 79b23f8..98f8598 100644 --- a/docs/the-symfony-bundle/key-and-key-set-management/key-management-jwk.md +++ b/docs/the-symfony-bundle/key-and-key-set-management/key-management-jwk.md @@ -1,6 +1,6 @@ -# Key Management (JWK) +# Key management (JWK) -## Keys As Services +## Keys as services When the component is installed, you will be able to define your keys in your application configuration and load your keys from several sources or formats. All these methods have the following option: @@ -21,7 +21,7 @@ The key will be available as a container service with the ID `jose.key.key_name` As any other configuration values, you can use environment variables. -### From A Shared Secret +### From a shared secret This method will directly get a shared secret. @@ -36,7 +36,7 @@ jose: alg: 'RS512' ``` -### From A JWK Object +### From a JWK object This method will directly load a JWK object. @@ -48,7 +48,7 @@ jose: value: '{"kty":"oct","k":"dzI6nbW4OcNF-AtfxGAmuyz7IpHRudBI0WgGjZWgaRJt6prBn3DARXgUR8NVwKhfL43QBIU2Un3AvCGCHRgY4TbEqhOi8-i98xxmCggNjde4oaW6wkJ2NgM3Ss9SOX9zS3lcVzdCMdum-RwVJ301kbin4UtGztuzJBeg5oVN00MGxjC2xWwyI0tgXVs-zJs5WlafCuGfX1HrVkIf5bvpE0MQCSjdJpSeVao6-RSTYDajZf7T88a2eVjeW31mMAg-jzAWfUrii61T_bYPJFOXW8kkRWoa1InLRdG6bKB9wQs9-VdXZP60Q4Yuj_WZ-lO7qV9AEFrUkkjpaDgZT86w2g"}' ``` -### From A X509 Certificate File +### From a X509 certificate file This method will load a X509 Certificate file. @@ -63,7 +63,7 @@ jose: alg: 'RS256' ``` -### From A X509 Certificate +### From a X509 certificate This method will load a key from a X509 Certificate. @@ -78,7 +78,7 @@ jose: alg: 'RS256' ``` -### From A PKCS#1/PKCS#8 Key File +### From a PKCS#1/PKCS#8 key file This method will load a key from a PKCS#1 or PKCS#8 key file. @@ -94,7 +94,7 @@ jose: alg: 'RS256' ``` -### From A Key In A Key Set +### From a key in a key set This method will retrieve a key from a JWKSet service. @@ -107,7 +107,7 @@ jose: index: 0 # Use key at index 0 ``` -## Custom Tags +## Custom tags You can add custom tags and attributes to the services you create. diff --git a/docs/the-symfony-bundle/key-and-key-set-management/key-set-management-jwkset.md b/docs/the-symfony-bundle/key-and-key-set-management/key-set-management-jwkset.md index 01011cc..c4ff234 100644 --- a/docs/the-symfony-bundle/key-and-key-set-management/key-set-management-jwkset.md +++ b/docs/the-symfony-bundle/key-and-key-set-management/key-set-management-jwkset.md @@ -1,6 +1,6 @@ -# Key Set Management (JWKSet) +# Key set management (JWKSet) -## Key Sets As Services +## Key sets as services All these methods have the following common option: @@ -21,7 +21,7 @@ The key set will be available as a container service with the ID `jose.key_set.k As any other configuration values, you can use environment variables. -### From A JWKSet Object +### From a JWKSet object This method will directly get a JWKSet object. @@ -33,7 +33,7 @@ jose: value: '{"keys":[{"kty":"oct","k":"dzI6nbW4OcNF-AtfxGAmuyz7IpHRudBI0WgGjZWgaRJt6prBn3DARXgUR8NVwKhfL43QBIU2Un3AvCGCHRgY4TbEqhOi8-i98xxmCggNjde4oaW6wkJ2NgM3Ss9SOX9zS3lcVzdCMdum-RwVJ301kbin4UtGztuzJBeg5oVN00MGxjC2xWwyI0tgXVs-zJs5WlafCuGfX1HrVkIf5bvpE0MQCSjdJpSeVao6-RSTYDajZf7T88a2eVjeW31mMAg-jzAWfUrii61T_bYPJFOXW8kkRWoa1InLRdG6bKB9wQs9-VdXZP60Q4Yuj_WZ-lO7qV9AEFrUkkjpaDgZT86w2g"},{"kty":"oct","k":"bwIAv5Nn-fo8p4LCEvM4IR9eLXgzJRs8jXCLb3xR0tDJGiZ46KheO4ip6htFKyN2aqJqlNi9-7hB6I1aLLy1IRT9-vcBoCSGu977cNAUuRLkRp7vo8s6MsxhB8WvQBDRZghV7jIYaune-3vbE7iDU2AESr8BUtorckLoO9uW__fIabaa3hJMMQIHCzYQbJKZvlCRCKWMk2H_zuS4JeDFTvyZH1skJYF_TET1DrCZHMPicw-Yk3_m2P-ilC-yidPPoVzeU8Jj3tQ6gtX3975qiQW7pt2qbgjKAuq2wsz_9hxLBtMB5rQPafFoxop7O4BklvZ9-ECcK6dfI2CAx9_tjQ"}]}' ``` -### Distant Key Sets +### Distant key sets You can load key sets shared by a distant service (e.g. Google, Microsoft, Okta...). You must install and enable the [Symfony Http Client](https://symfony.com/doc/current/http_client.html). @@ -51,7 +51,7 @@ jose: * It is **highly recommended** to use a cache plugin for your HTTP client and thus avoid unnecessary calls to the key set endpoint. * The **connection must be secured** and certificate verification should not be disabled. -#### From A JKU (JWK Url) +#### From a JKU (JWK URL) The following example will allow you tu load a key set from a distant URI. The key set must be a JWKSet object. @@ -63,7 +63,7 @@ jose: url: 'https://login.microsoftonline.com/common/discovery/keys' ``` -#### From A X5U (X509 Certificates Url) +#### From a X5U (X509 certificates URL) The following example will allow you tu load a key set from a distant URI. The key set must be a list of X509 certificates. @@ -75,7 +75,7 @@ jose: url: 'https://www.googleapis.com/oauth2/v1/certs' ``` -## Shared Key Sets +## Shared key sets It can be interesting to share your key sets through an Url. This can easily achieved by adding a dedicated controller. This controller is automatically created by the bundle. @@ -103,7 +103,7 @@ jose: Now when you go to the URL `http://128.0.0.1:8000/certs`, you will get your key set. -## Custom Tags +## Custom tags You can add custom tags and attributes to the services you create. diff --git a/docs/the-symfony-bundle/signed-tokens/README.md b/docs/the-symfony-bundle/signed-tokens/README.md index 161708f..e15834e 100644 --- a/docs/the-symfony-bundle/signed-tokens/README.md +++ b/docs/the-symfony-bundle/signed-tokens/README.md @@ -1,4 +1,4 @@ -# Signed Tokens +# Signed tokens Signature algorithms are automatically handled by the Algorithm Manager Factory. diff --git a/docs/the-symfony-bundle/signed-tokens/jws-creation.md b/docs/the-symfony-bundle/signed-tokens/jws-creation.md index 616c21a..f14d1ad 100644 --- a/docs/the-symfony-bundle/signed-tokens/jws-creation.md +++ b/docs/the-symfony-bundle/signed-tokens/jws-creation.md @@ -1,6 +1,6 @@ # JWS creation -## JWS Builder Factory Service +## JWS builder factory service A `JWSBuilderFactory` is available as a service in your application container: @@ -19,7 +19,7 @@ $jwsBuilder = $jwsBuilderFactory->create(['HS256']); You can now use the JWSBuilder as explained in the JWS Creation section. -## JWS Builder As Service +## JWS builder as service There is also another way to create a JWSBuilder object: using the bundle configuration. @@ -39,7 +39,7 @@ With the previous configuration, the bundle will create a public JWS Builder ser $jwsBuilder = $container->get('jose.jws_builder.builder1'); ``` -## Custom Tags +## Custom tags You can add custom tags and attributes to the services you create. diff --git a/docs/the-symfony-bundle/signed-tokens/jws-serializers.md b/docs/the-symfony-bundle/signed-tokens/jws-serializers.md index 17f1deb..cc1fb39 100644 --- a/docs/the-symfony-bundle/signed-tokens/jws-serializers.md +++ b/docs/the-symfony-bundle/signed-tokens/jws-serializers.md @@ -1,6 +1,6 @@ # JWS serializers -## JWS Serializer Manager Factory Service +## JWS serializer manager factory service A `JWSSerializerManagerFactory` is available as a service in your application container: @@ -25,7 +25,7 @@ Available JWS serialization modes are: * `jws_json_general` * `jws_json_flattened` -## JWS Serializer Manager As Service +## JWS serializer manager as service There is also another way to create a JWSSerializerManager object: using the bundle configuration. @@ -45,7 +45,7 @@ With the previous configuration, the bundle will create a public JWS Serializer $jwsSerializerManager = $container->get('jose.jws_serializer.serializer1'); ``` -## Custom Tags +## Custom tags You can add custom tags and attributes to the services you create. diff --git a/docs/the-symfony-bundle/signed-tokens/jws-verification.md b/docs/the-symfony-bundle/signed-tokens/jws-verification.md index e037fb9..f605828 100644 --- a/docs/the-symfony-bundle/signed-tokens/jws-verification.md +++ b/docs/the-symfony-bundle/signed-tokens/jws-verification.md @@ -1,6 +1,6 @@ # JWS verification -## JWS Verifier Factory Service +## JWS verifier factory service A `JWSVerifierFactory` is available as a service in your application container: @@ -23,7 +23,7 @@ You can now use the JWSVerifier as explained in the JWS Creation section. Reminder: it is important to check the token headers. See the checker section of this documentation. -## JWS Verifier As Service +## JWS verifier as service There is also another way to create a JWSVerifier object: using the bundle configuration. @@ -43,7 +43,7 @@ With the previous configuration, the bundle will create a public JWS Verifier se $jwsVerifier = $container->get('jose.jws_verifier.verifier1'); ``` -## Custom Tags +## Custom tags You can add custom tags and attributes to the services you create. @@ -58,7 +58,7 @@ jose: tag_name2: {attribute1: 'foo'} ``` -## JWS Loader Service +## JWS loader service The [`JWSLoaderFactory`](../../the-components/signed-tokens-jws/jws-loading.md) is available as a public service. You can retrieve it using the container or inject it into your services. It will help you to create `JWSLoader` objects on demand. diff --git a/docs/the-symfony-bundle/symfony-bundle.md b/docs/the-symfony-bundle/symfony-bundle.md index c877431..3f97f52 100644 --- a/docs/the-symfony-bundle/symfony-bundle.md +++ b/docs/the-symfony-bundle/symfony-bundle.md @@ -1,4 +1,4 @@ -# Symfony Bundle +# Symfony bundle This framework provides a Symfony bundle that will help you to use the components within your Symfony application. @@ -24,7 +24,7 @@ return [ ``` -## Bundle Features +## Bundle features The bundle capabilities will depend on the components installed in your application. From e346d6cab2203188a23fad3c3e6bbe4285042abc Mon Sep 17 00:00:00 2001 From: Florent Morselli Date: Sun, 25 Oct 2026 21:11:52 +0100 Subject: [PATCH 4/7] docs: a link to a section leads to the page of the section GitBook resolved a link to a directory to the README.md it holds; MkDocs wants the page itself. --- docs/the-symfony-bundle/symfony-bundle.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/the-symfony-bundle/symfony-bundle.md b/docs/the-symfony-bundle/symfony-bundle.md index 3f97f52..d4b58d7 100644 --- a/docs/the-symfony-bundle/symfony-bundle.md +++ b/docs/the-symfony-bundle/symfony-bundle.md @@ -30,6 +30,6 @@ The bundle capabilities will depend on the components installed in your applicat * [Algorithm Management](algorithm-management.md) * [Header and Claim Checkers](header-and-claim-checker-management.md) -* [Keys and key sets](key-and-key-set-management/) -* [Signed tokens](signed-tokens/) -* [Encrypted tokens](encrypted-tokens/) +* [Keys and key sets](key-and-key-set-management/README.md) +* [Signed tokens](signed-tokens/README.md) +* [Encrypted tokens](encrypted-tokens/README.md) From 892c5ece325fe1c0d85c127f9f4c47950d4ec71b Mon Sep 17 00:00:00 2001 From: Florent Morselli Date: Sun, 25 Oct 2026 21:11:52 +0100 Subject: [PATCH 5/7] chore: the documentation site, its toolchain, its look and its domain The pages are built by MkDocs and Material for MkDocs, one version per branch through mike, on GitHub Pages under web-token.spomky-labs.com, in the look of the Slabs brand guidelines v2.0, with the project mark of JWT Framework in the header. The toolchain, the workflows, the stylesheets and the theme partials come from the documentation of Web Push Framework, recorded in Spomky-Labs/docs. Only the versions 4.0 to 4.3 are published. site-root/404.html sends the GitBook variants v4.0, v4.1 and v4.3 to their version, the root and every older variant (v3.3-1, v3.0-1, 3.2, 2.x, 1.x) to the same page of the latest version. docs/SUMMARY.md and .gitbook.yaml keep the GitBook space working until the domain moves. --- .editorconfig | 14 + .gitbook.yaml | 7 + .github/workflows/check.yml | 38 + .github/workflows/default-branch.yml | 73 ++ .github/workflows/pages.yml | 111 ++ .gitignore | 6 + Makefile | 44 + README.md | 51 + docs/assets/brand/apple-touch-icon.png | Bin 0 -> 2710 bytes docs/assets/brand/favicon.ico | Bin 0 -> 2629 bytes docs/assets/brand/favicon.svg | 1 + .../brand/marque-jwt-framework-couleur.svg | 1 + .../brand/marque-jwt-framework-inverse.svg | 1 + docs/assets/brand/og-slabs-1200x630.png | Bin 0 -> 28751 bytes .../slabs-logotype-signature-inverse.svg | 1 + docs/assets/fonts/IBMPlexMono-Italic.woff2 | Bin 0 -> 43768 bytes docs/assets/fonts/IBMPlexMono-Regular.woff2 | Bin 0 -> 39212 bytes docs/assets/fonts/IBMPlexMono-SemiBold.woff2 | Bin 0 -> 41136 bytes docs/assets/fonts/OFL-IBMPlexMono.txt | 93 ++ docs/assets/fonts/OFL-SpaceGrotesk.txt | 93 ++ docs/assets/fonts/SpaceGrotesk-Variable.woff2 | Bin 0 -> 49184 bytes docs/assets/stylesheets/slabs-tokens.css | 86 ++ docs/assets/stylesheets/slabs.css | 1120 +++++++++++++++++ docs/overrides/main.html | 24 + docs/overrides/partials/copyright.html | 22 + docs/overrides/partials/logo.html | 8 + docs/overrides/partials/source.html | 13 + mkdocs.yml | 248 ++++ requirements.txt | 10 + site-root/404.html | 95 ++ site-root/CNAME | 1 + 31 files changed, 2161 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitbook.yaml create mode 100644 .github/workflows/check.yml create mode 100644 .github/workflows/default-branch.yml create mode 100644 .github/workflows/pages.yml create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 README.md create mode 100644 docs/assets/brand/apple-touch-icon.png create mode 100644 docs/assets/brand/favicon.ico create mode 100644 docs/assets/brand/favicon.svg create mode 100644 docs/assets/brand/marque-jwt-framework-couleur.svg create mode 100644 docs/assets/brand/marque-jwt-framework-inverse.svg create mode 100644 docs/assets/brand/og-slabs-1200x630.png create mode 100644 docs/assets/brand/slabs-logotype-signature-inverse.svg create mode 100644 docs/assets/fonts/IBMPlexMono-Italic.woff2 create mode 100644 docs/assets/fonts/IBMPlexMono-Regular.woff2 create mode 100644 docs/assets/fonts/IBMPlexMono-SemiBold.woff2 create mode 100644 docs/assets/fonts/OFL-IBMPlexMono.txt create mode 100644 docs/assets/fonts/OFL-SpaceGrotesk.txt create mode 100644 docs/assets/fonts/SpaceGrotesk-Variable.woff2 create mode 100644 docs/assets/stylesheets/slabs-tokens.css create mode 100644 docs/assets/stylesheets/slabs.css create mode 100644 docs/overrides/main.html create mode 100644 docs/overrides/partials/copyright.html create mode 100644 docs/overrides/partials/logo.html create mode 100644 docs/overrides/partials/source.html create mode 100644 mkdocs.yml create mode 100644 requirements.txt create mode 100644 site-root/404.html create mode 100644 site-root/CNAME diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..6337909 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,14 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +indent_style = space + +[*.{md,yml,yaml,css,json}] +indent_size = 2 + +[Makefile] +indent_style = tab diff --git a/.gitbook.yaml b/.gitbook.yaml new file mode 100644 index 0000000..3b0a865 --- /dev/null +++ b/.gitbook.yaml @@ -0,0 +1,7 @@ +# GitBook serves the domain until it points to GitHub Pages. The pages moved to docs/ for MkDocs, and this +# tells GitBook where they are. It goes away with the GitBook space. +root: ./docs/ + +structure: + readme: README.md + summary: SUMMARY.md diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml new file mode 100644 index 0000000..aab53ac --- /dev/null +++ b/.github/workflows/check.yml @@ -0,0 +1,38 @@ +name: Check + +on: + pull_request: + workflow_dispatch: + +# MkDocs 2.0 is announced as backward incompatible with every plugin and theme, so the toolchain is pinned +# to the 1.x line in requirements.txt and the two notices about it are silenced: they are news about the +# ecosystem, not findings about this site. +env: + NO_MKDOCS_2_WARNING: 'true' + DISABLE_MKDOCS_2_WARNING: 'true' + +permissions: + contents: read + +jobs: + build: + name: Strict build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - uses: actions/setup-python@v6 + with: + python-version: '3.13' + cache: pip + cache-dependency-path: requirements.txt + + - name: Install the toolchain + run: pip install -r requirements.txt + + # --strict turns every warning into an error: a broken internal link, an anchor that does not + # exist, a page absent from the navigation or a page in the navigation that does not exist. + - name: Build + run: mkdocs build --strict diff --git a/.github/workflows/default-branch.yml b/.github/workflows/default-branch.yml new file mode 100644 index 0000000..fdee05b --- /dev/null +++ b/.github/workflows/default-branch.yml @@ -0,0 +1,73 @@ +name: Default branch + +# A new version branch becomes the default branch of the repository, so that a clone and the "edit this +# page" links land on the newest documentation. Changing the default branch is an administration +# permission, which the token of Actions cannot be granted: it needs a personal access token with the +# "repo" scope, in the DEFAULT_BRANCH_TOKEN secret. Without it the workflow does nothing. +on: + create: + workflow_dispatch: + +jobs: + switch: + if: github.event_name == 'workflow_dispatch' || github.event.ref_type == 'branch' + runs-on: ubuntu-latest + permissions: + contents: read + env: + GH_TOKEN: ${{ secrets.DEFAULT_BRANCH_TOKEN }} + steps: + - name: Is the token available? + id: token + run: | + if [ -z "${GH_TOKEN}" ]; then + echo "DEFAULT_BRANCH_TOKEN is not set, nothing to do." + echo "available=false" >> "$GITHUB_OUTPUT" + else + echo "available=true" >> "$GITHUB_OUTPUT" + fi + + - name: The version of the branch that was created + id: created + if: steps.token.outputs.available == 'true' + run: | + ref="${GITHUB_REF#refs/heads/}" + version="${ref#v}" + version="${version%.x}" + if [[ ! "$version" =~ ^([0-9]+)\.([0-9]+)$ ]]; then + echo "The branch '$ref' is not a version, nothing to do." + echo "valid=false" >> "$GITHUB_OUTPUT" + exit 0 + fi + echo "valid=true" >> "$GITHUB_OUTPUT" + echo "branch=$ref" >> "$GITHUB_OUTPUT" + echo "major=${BASH_REMATCH[1]}" >> "$GITHUB_OUTPUT" + echo "minor=${BASH_REMATCH[2]}" >> "$GITHUB_OUTPUT" + + - name: Is it newer than the default branch? + id: decide + if: steps.created.outputs.valid == 'true' + run: | + current=$(gh repo view "${GITHUB_REPOSITORY}" --json defaultBranchRef --jq .defaultBranchRef.name) + clean="${current#v}" + clean="${clean%.x}" + if [[ ! "$clean" =~ ^([0-9]+)\.([0-9]+)$ ]]; then + echo "The current default branch '$current' is not a version, nothing to do." + echo "switch=false" >> "$GITHUB_OUTPUT" + exit 0 + fi + major="${{ steps.created.outputs.major }}" + minor="${{ steps.created.outputs.minor }}" + if [ "$major" -gt "${BASH_REMATCH[1]}" ] || { [ "$major" -eq "${BASH_REMATCH[1]}" ] && [ "$minor" -gt "${BASH_REMATCH[2]}" ]; }; then + echo "${major}.${minor} is newer than $clean, switching." + echo "switch=true" >> "$GITHUB_OUTPUT" + else + echo "${major}.${minor} is not newer than $clean, nothing to do." + echo "switch=false" >> "$GITHUB_OUTPUT" + fi + + - name: Switch it + if: steps.decide.outputs.switch == 'true' + run: | + gh api -X PATCH "repos/${GITHUB_REPOSITORY}" \ + -f default_branch="${{ steps.created.outputs.branch }}" diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml new file mode 100644 index 0000000..6971ddc --- /dev/null +++ b/.github/workflows/pages.yml @@ -0,0 +1,111 @@ +name: Pages + +# One version of the site per branch, published by mike into gh-pages: 4.0 is served at /4.0/, and the +# alias "latest" follows the highest version, which is what the root of the site redirects to. A branch is +# named 4.0, or 4.0.x like the maintenance branches of a library; 4.x is the next minor. Pages is +# configured to deploy from the gh-pages branch, root folder. +on: + push: + branches: + - '[0-9]*.[0-9]*' + - '[0-9]*.x' + paths-ignore: + - '.github/workflows/check.yml' + workflow_dispatch: + +# MkDocs 2.0 is announced as backward incompatible with every plugin and theme, so the toolchain is pinned +# to the 1.x line in requirements.txt and the two notices about it are silenced: they are news about the +# ecosystem, not findings about this site. +env: + NO_MKDOCS_2_WARNING: 'true' + DISABLE_MKDOCS_2_WARNING: 'true' + +permissions: + contents: write + +# Two branches pushed at once must not write gh-pages at the same time, and a queued run is never +# cancelled: it carries a version the other does not. +concurrency: + group: gh-pages + cancel-in-progress: false + +jobs: + deploy: + name: Deploy ${{ github.ref_name }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - uses: actions/setup-python@v6 + with: + python-version: '3.13' + cache: pip + cache-dependency-path: requirements.txt + + - name: Install the toolchain + run: pip install -r requirements.txt + + - name: Identify the committer + run: | + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + + # The version a branch publishes: 4.0.x publishes 4.0, any other name publishes itself. + - name: The version of this branch + id: version + run: | + version="${GITHUB_REF_NAME}" + if [[ "$version" =~ ^[0-9]+\.[0-9]+\.x$ ]]; then + version="${version%.x}" + fi + echo "The branch '${GITHUB_REF_NAME}' publishes the version '$version'." + echo "name=$version" >> "$GITHUB_OUTPUT" + + # The highest version branch of the repository, by version order, in which a "1.x" branch comes + # after "1.2" and "1.2.x": it is where the next minor is written. sort -V alone puts "1.x" first, + # so each name is sorted by a key where "x" is a large number. Only that branch carries "latest". + - name: Is this the newest version? + id: newest + run: | + git fetch --quiet origin '+refs/heads/*:refs/remotes/origin/*' + newest=$(git for-each-ref --format='%(refname:lstrip=3)' 'refs/remotes/origin/*' \ + | grep -E '^[0-9]+\.([0-9]+(\.x)?|x)$' \ + | awk '{ key = $0; if (key ~ /^[0-9]+\.x$/) sub(/x$/, "999999", key); else sub(/\.x$/, "", key); print key " " $0 }' \ + | sort -V -k1,1 \ + | tail -n 1 \ + | cut -d' ' -f2) + echo "The newest version branch is '$newest', this one is '${GITHUB_REF_NAME}'." + if [ "$newest" = "${GITHUB_REF_NAME}" ]; then + echo "latest=true" >> "$GITHUB_OUTPUT" + else + echo "latest=false" >> "$GITHUB_OUTPUT" + fi + + - name: Publish this version + if: steps.newest.outputs.latest == 'false' + run: mike deploy --push --update-aliases "${{ steps.version.outputs.name }}" + + - name: Publish this version as the latest one + if: steps.newest.outputs.latest == 'true' + run: | + mike deploy --push --update-aliases "${{ steps.version.outputs.name }}" latest + mike set-default --push latest + + # The root of gh-pages is not a version: mike leaves it alone, and it holds what GitHub Pages reads + # there. site-root/ in this branch is copied over it: CNAME, the domain of the site, and 404.html, + # which sends the addresses of the former GitBook site to the latest version. + - name: Publish the root of the site + run: | + git fetch --quiet origin gh-pages + git worktree add "${RUNNER_TEMP}/gh-pages" origin/gh-pages + cp -R site-root/. "${RUNNER_TEMP}/gh-pages/" + cd "${RUNNER_TEMP}/gh-pages" + git add --all + if git diff --cached --quiet; then + echo "The root of the site is up to date." + else + git commit --quiet -m "Publish the root of the site from ${GITHUB_REF_NAME}" + git push origin HEAD:gh-pages + fi diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f576159 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +/site/ +/.venv/ +/.cache/ +__pycache__/ +.idea/ +.claude/ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..80eb70b --- /dev/null +++ b/Makefile @@ -0,0 +1,44 @@ +# The documentation of Beffroi. "make install" once, "make serve" to write, "make check" before a pull +# request. Every target runs in .venv, created from requirements.txt, with uv when it is installed. + +VENV := .venv +BIN := $(VENV)/bin +UV := $(shell command -v uv 2>/dev/null) + +# News about the MkDocs ecosystem, not findings about this site. requirements.txt pins the 1.x line. +export NO_MKDOCS_2_WARNING := true +export DISABLE_MKDOCS_2_WARNING := true + +.DEFAULT_GOAL := help +.PHONY: help install serve build check versions clean + +help: ## Show this help + @grep -E '^[a-z-]+:.*?## ' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-10s\033[0m %s\n", $$1, $$2}' + +$(BIN)/mkdocs: requirements.txt +ifdef UV + uv venv --allow-existing $(VENV) + VIRTUAL_ENV=$(VENV) uv pip install -r requirements.txt +else + python3 -m venv $(VENV) + $(BIN)/pip install --upgrade pip + $(BIN)/pip install -r requirements.txt +endif + @touch $(BIN)/mkdocs + +install: $(BIN)/mkdocs ## Install the toolchain in .venv + +serve: install ## Serve the site on http://127.0.0.1:8000, rebuilt as you save + $(BIN)/mkdocs serve + +build: install ## Build the site into site/ + $(BIN)/mkdocs build + +check: install ## Build strictly: a broken link, a missing anchor or a page outside the navigation fails + $(BIN)/mkdocs build --strict + +versions: install ## List the versions published on gh-pages + $(BIN)/mike list + +clean: ## Remove the build and the virtual environment + rm -rf site $(VENV) diff --git a/README.md b/README.md new file mode 100644 index 0000000..b979d4b --- /dev/null +++ b/README.md @@ -0,0 +1,51 @@ +# The documentation of JWT Framework + +The public documentation of [JWT Framework](https://github.com/web-token/jwt-framework), JSON Web Tokens for +PHP and Symfony: signature (JWS), encryption (JWE), keys (JWK) and algorithms (JWA), the components, the +Symfony bundle and the console commands. + +Published with [MkDocs](https://www.mkdocs.org/) and +[Material for MkDocs](https://squidfunk.github.io/mkdocs-material/) on GitHub Pages: +**** + +## Writing + +```bash +make install # the toolchain, in .venv, from requirements.txt +make serve # http://127.0.0.1:8000, rebuilt as you save +make check # the strict build continuous integration runs +``` + +`make check` is the gate: a broken internal link, an anchor that does not exist, a page absent from the +navigation or a navigation entry without a page fails the build. + +## Where things are + +| Path | What it is | +|---|---| +| `mkdocs.yml` | The site: theme, extensions, plugins, and the whole navigation | +| `docs/` | The pages, one directory per section of the navigation | +| `docs/assets/stylesheets/` | The look: `slabs-tokens.css`, copied as it is from the Slabs design kit, and `slabs.css`, which applies the guidelines to the theme | +| `docs/assets/brand/`, `docs/assets/fonts/` | The project mark, the signature, the favicons and the share image of the design kit, and its typefaces (SIL Open Font License) | +| `docs/overrides/` | Theme partials: the logo, the footer, the link to the repository | +| `site-root/` | The root of the published site, copied to the root of the `gh-pages` branch: `CNAME`, and the `404.html` that sends the addresses of the former GitBook site to their version | +| `requirements.txt` | The toolchain, pinned. Continuous integration installs exactly this | +| `.github/workflows/check.yml` | The strict build, on every pull request | +| `.github/workflows/pages.yml` | The publication: one version per branch, through mike | +| `.github/workflows/default-branch.yml` | A new version branch becomes the default branch | +| `docs/SUMMARY.md`, `.gitbook.yaml` | The GitBook space, until the domain points to GitHub Pages | + +How the documentation left GitBook, and the rules every documentation site of Slabs follows, are in +[Spomky-Labs/docs](https://github.com/Spomky-Labs/docs/blob/main/MIGRATING.md). + +## One branch per version + +A branch of this repository is a version of the packages: `4.0`, `4.1`, `4.2`, `4.3`. A push to one of +them publishes it under its own name, and the newest one also carries the `latest` alias, which the root +of the site redirects to. A fix that applies to several versions is merged forward. + +```bash +git switch -c 4.4 4.3 # from the version it continues +# in mkdocs.yml, point edit_uri at the new branch +git push -u origin 4.4 # publishes it, and moves "latest" and the default branch +``` diff --git a/docs/assets/brand/apple-touch-icon.png b/docs/assets/brand/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..e384e06b5293e0a77751be4960cf71bce558970c GIT binary patch literal 2710 zcmcImc{CeX7uQnz5{$7WwNxqfp^8KagLE{V)>bukwZu*vT4D)R6cuYNt$oBY_KK!W zDzu11ZPCV7dqONl7bbQ!neY4e`*+?u@7;6X@4eqU=bn4-`K8%dS&9hC33739iNLSH z>^S!2Ka2k~XUDbVAUKBC>o-dn*U3M#qNDaH7nk5~aG04rs$_FE$i{vJME$;^xe6V<(W?NA zvx*%4p)!9u?8}A7NjIJXgfubOV-@fqR(Z*AV|$})eg#U~zc~M?tpvRTREMI^o6gG(IqlDX%FK4vP&n#`I)?E^a9xO`au8eJw>+r6D;6bpv=A)B2Tk938x2jS{O=EEA{F91tKA!aU8oCkB8Jhl;{;&0q?lWsK z5gmOog4L3jGV5;j#6>Ovv{J&=nA!{9x{kZLo<>=pV)o|b6NA53?vrY{%wg$0H0$jK zbUVuW)NYy-^|E|;ckN9U^vsN!4Nxv4dOe)>t?YCs$FW8<@e2uYkXY*qh`~}L3wqiZ zmItX6c|-mrK&pM1lDgG3jYFg(T!##GY+PNP-ER5eBi<7>&K0>htA!%PQzfX~`vJJd zMWD>y54&k@IBXY2|A`%H-O{wE2+l zdW+cEOT|q%3=b?DT!q^ZMt{wUH<#U#P!{db%0(tW>aJww>N-76ur()(i=Q1PbQgM* z79b>0*#IQZnKP|NdwqS^;A!w?&pUaX6P~@+BLaRsvu7{oDdg-7MJ!XXpjsGOJ76Le%aXh zQNnIeJHw09REB^2cwR_fE~Ad*<>Lcu{*-qk6~eECq)ZYZ=N6T7RnF7kuKA^FVZ_0o zgG{Ft%oM9@X^T*9rKH9|$B4gX!7Mj=;3h6&7D;p!P3iGnU)OUfDt3_%)pu|hyK`~G zk-xP(5nzX674@tMf7>lY4!w9WLJjp(kd>`#3L=Ez_n6g3^`D((vsMu>!zN)7k*n+M z?}L5?t=TH-nwom&4UrbZMH`L6_+P^hBj~g3k+b*wY0B4uNr3d;t^31rUx>Y2 z9V8VOS9Dcqg;oxp@Tp(j#DABw06yyd;F+0qnL?I<3TYuY1pxoJWp#`dINu7E5l&EV6zQNhm(aqMv0j(s|*>eVzpL0 zY=afLd(HUk8tb3u>(DD!OrL##Kvh)_nANd}9VIWIR^fV}?fd>gme~}XUq>fmV*Y@pkNgim z>aOffUk-|TdomKJ7JyGUlRUAP$*`)Vn(?oF`SO0K9iZShx>mVorF+>#>+M24eqD6_ z(hP;0sh9*QdKCeEisW`*6hpD~VS9NlQ6}bu?lv#J}Evs%FMShrF603Ds-~y4m}{c-AAg<4YFacSX&|4zNZ-mpzd) z^zrfU?C0TECz^xw?L= zj<4K-GRz8laQ~UMyH=kz;R;yasX*;`bPPN?Zt$YzoUT%*=$gTp{)3oZh5DwajOoI( zHosPFWe9?k6s?~Q=3>`(4O|o!uUuaA>(kBZ`$?Klsfr%Fzn(&skxok+AJE10<;n0V zEsd_ZQlzuqy?a-o*yOsM3jYH+(_!R@N@j15jf|+{gwJUvQ#fhn+o_%!A#vh{k-Sbs z-jCeXX|8YxKa8D(=Eja#s=_3FOpKd2f~Z(ZY_T+;}pqBi;Vyn?!c6{ zi|`AlZJ+G|0jLCh{nrHr`P*gP|2U;b%y~iL2Qj9MLIZxC6Ro*h1OcW@c~&M!LB^)v zEmNEd866*sXS1C+2W|BF_O~JjF;> zEb#N~bO4{#MN_g@Yv<0vbW_MCiI2gJw9(hclfo8WXJiaE<4_EbZ!@u+ z#WJ8&?BmCeO^#OSw9In*?vyQ4VWe>tu73Gg?1%Dzh%t$aNoc{+k6ve)8igB(Y0F>% zd;$K1!VqUU|;SbZ#eW>*F4~^rt7spd=K_ zKQNR5eH6^=Rz=YwpJ*7l@^JsV>goS0G{v8~| literal 0 HcmV?d00001 diff --git a/docs/assets/brand/favicon.ico b/docs/assets/brand/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..901a26c931a4d2e4456af6ca9375a5e049d847d6 GIT binary patch literal 2629 zcmah}X*3ji8~=}qrVLp|hLmNP#*!sWBReBmGoF$ zOKB2aTa3msAu**paV@WIU)~SzIq&n~S00@8r0RgZlQeYGU0QRRR^((f9 z0>H-wfU4@RcxfL14%`6Tv9UJgJ1Bl|FUx0k7H_*}e@+m9@$6~IZ@X>)K=RG-hUX(_ zd1+P_4u*)^1!6&0Z5@$i&50wSsbTli&k{8J79S$2V9av@=AlJn@tAZf<|fHRz!8&} zWu&maAK{1-C#2RhjVAn9_aYwaWexM3>Erjgi*j<&IpWLxUUl%hN%zh3KwwbhQcf3SEeCA` zdzTH*&2^AXOQ`8p?B9|h2maZxI{Bl;dBLkZ(Zt)wH`*Qt3LnR$cs{2FO#ayJ329v} zJT0Lh5g0-%ei2UT%^XyU+JqYz->6n>XY(A2(yORA29=5{{7T>k-Yix;WMDw@BzAL1 zE$|xI>D96Zbm~gtBd@P?k}O5R~HgI2cI0RPwCerEiwq(}q^Lt?V6FoVW)V zFf*~n*BH6p{2#DN?Ukkeg*7-bavcDu$S+uXGPf=42*^Ht)|G{U`tB6x3~3W-M0JRv zqWsfD3!w5BPeshBby7BD<+t)IRS zN+Ml;ML);UqX*MD*9(GiEawi41b^m~$H5D*j>E1H)w^>ucGL^K1o_9 ze&j75ZaODlk%ke!(_kJS7NL_risIR!j+Xuwp}{Cc#OFLD$9H{vnmgDLX1lv^*_UtM z7QgRFZbh`AgcRMqRwB*lNvKfwu8jF>15(wzMdn;;o4eNdI1wh@^_8=HY^j2(pqo!%H#91FFyc0C_$#~V3iN<{D*RI(>G{J92L1E83xci|#w5F(KC$`3R`^(7?c1qg zi}&-(z{Bc5Z9oPiW%bi36OEKLapc2A6ZQE%1@?xJHtIFy(35+apI5dmr*0j0V;2>< ztbhOhkrZv_pL=b(4Q{@qcjQp5a!mJ`Wf^@2QDtAHuxbI^*+ROz+DvHwh_M)KtA*>C z)y-z*GM(eC&Z~t22qq*3T*SI)y5X@J!5&t2Q1=LU|9kpsoNhIb}cUhTxP|YIZE91w1>- z1}}U|g}CKz8RD>T6JC!yT%Xjln6CC9Dd=}W>>%>YHJikD(g^am{Mm$|ftmVN&fgi# zRR=ox4S9!7enHo5jRPLu-V8&0G9*NWf&j08jnwr#HxMpNIK|pRQf?Jvn&;sx*g$_j zk@qbL96?pvatni)QLj3CO-;?a^r}WQ<@4tjcbS)x6teTYe4iX_y>NK(Ge_hHH0!X- z?;8&2ON)p14RE*(DKX=;uFj(y#J5C>2(=g|XDRx*clV4ASbKph&xBBF^07u1=_0;v z7%bMS%)nzzJU~v|EQ>}{It-iz0^}x&WKfj(k6|bn*So8Zu_Ngou$uxS8Nv4+F06Kj zE~18EQfB`CmG7x(Oc|Z^cC;)SjqyX73FTl(LrXze`7@v+K?yWeIo%o<4R`Ao8e}iW zx{kbCs&}Yc+tI$-;X!@xkm7efIoilbXSxdGBEW?3L3Em`@$ATgL+4KvnV^NSR~6vD z>Fellh3^`?)k9wPbG(hW2SnnjF82&N&Tn~%-TxArB5Nk;EZ!uK>^5C=i+K>zgDH*$Pxi729QV z!HT`34?J#VV literal 0 HcmV?d00001 diff --git a/docs/assets/brand/favicon.svg b/docs/assets/brand/favicon.svg new file mode 100644 index 0000000..4b601fb --- /dev/null +++ b/docs/assets/brand/favicon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/assets/brand/marque-jwt-framework-couleur.svg b/docs/assets/brand/marque-jwt-framework-couleur.svg new file mode 100644 index 0000000..29c11c2 --- /dev/null +++ b/docs/assets/brand/marque-jwt-framework-couleur.svg @@ -0,0 +1 @@ + diff --git a/docs/assets/brand/marque-jwt-framework-inverse.svg b/docs/assets/brand/marque-jwt-framework-inverse.svg new file mode 100644 index 0000000..47d88ad --- /dev/null +++ b/docs/assets/brand/marque-jwt-framework-inverse.svg @@ -0,0 +1 @@ + diff --git a/docs/assets/brand/og-slabs-1200x630.png b/docs/assets/brand/og-slabs-1200x630.png new file mode 100644 index 0000000000000000000000000000000000000000..4c3d9fdcb5435d1486cc53ff852af21e616f054b GIT binary patch literal 28751 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 \ No newline at end of file diff --git a/docs/assets/fonts/IBMPlexMono-Italic.woff2 b/docs/assets/fonts/IBMPlexMono-Italic.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..3948c828c31bd1b34f0946e744b2d203223da44e GIT binary patch literal 43768 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 D9A^tA literal 0 HcmV?d00001 diff --git a/docs/assets/fonts/IBMPlexMono-SemiBold.woff2 b/docs/assets/fonts/IBMPlexMono-SemiBold.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..7134ce096a30700e5a3de89c2ac4b810caa07cc1 GIT binary patch literal 41136 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 K^8eMZeoqFD=uQs+ literal 0 HcmV?d00001 diff --git a/docs/assets/stylesheets/slabs-tokens.css b/docs/assets/stylesheets/slabs-tokens.css new file mode 100644 index 0000000..2bbe80e --- /dev/null +++ b/docs/assets/stylesheets/slabs-tokens.css @@ -0,0 +1,86 @@ +/* + * Slabs design tokens, brand guidelines v2.0 (October 2026). + * Source: Charte Graphique.pdf; page numbers in comments. + * Use these values as they are: no new color, no tint of orange, no other radius. + */ +:root { + /* Brand colors (p. 17) */ + --slabs-anthracite: #333334; /* logo, text, dark grounds */ + --slabs-beton: #B3AEA6; /* secondary grounds, rules, text on dark */ + --slabs-calcaire: #F5F1E8; /* light grounds, logo on dark */ + --slabs-orange: #ED6A20; /* the cursor, the slab, the main action; never text on light, never a text background */ + + /* Complementary colors (p. 19): small surfaces, always with a word, text on light grounds only */ + --slabs-acier: #4A5D6E; /* information, notes, neutral data series */ + --slabs-patine: #3E7268; /* success, validation, second data series */ + --slabs-brique: #A6452C; /* errors, alerts, negative values; never a button */ + + /* Utility colors (p. 20): screen only, never brand colors */ + --slabs-schiste: #5E5B56; /* secondary text, link underline, field borders */ + --slabs-calcaire-clair: #FBF9F4; /* cards, panels, menus, state notes */ + --slabs-calcaire-ombre: #ECE7DD; /* notes, tags, inline code, disabled controls */ + --slabs-platre: #DCD5C6; /* rules on light grounds; types and properties in code */ + --slabs-sable: #E8C9A8; /* strings and numbers in code on Anthracite only */ + + /* Chart series, in order (p. 21): orange for the series the chart is about, Brique for negative values only */ + --slabs-series-1: var(--slabs-orange); + --slabs-series-2: var(--slabs-anthracite); + --slabs-series-3: var(--slabs-acier); + --slabs-series-4: var(--slabs-patine); + --slabs-series-5: var(--slabs-schiste); + --slabs-series-negative: var(--slabs-brique); + + /* Code on Anthracite (p. 34) */ + --slabs-code-bg: var(--slabs-anthracite); + --slabs-code-text: var(--slabs-calcaire); /* text, variables; keywords in SemiBold */ + --slabs-code-type: var(--slabs-platre); /* types, properties */ + --slabs-code-string: var(--slabs-sable); /* strings, numbers */ + --slabs-code-comment: var(--slabs-beton); /* comments, italic */ + + /* Typefaces (p. 22) */ + --slabs-font-sans: "Space Grotesk", Arial, sans-serif; + --slabs-font-mono: "IBM Plex Mono", Consolas, monospace; /* 400 and 600 only on the web */ + + /* Web type scale (p. 34): desktop, then mobile */ + --slabs-h1: 42px; --slabs-h1-mobile: 32px; --slabs-h1-lh: 1.1; /* Bold 700 */ + --slabs-h2: 32px; --slabs-h2-mobile: 26px; --slabs-h2-lh: 1.2; /* Bold 700 */ + --slabs-h3: 26px; --slabs-h3-mobile: 22px; --slabs-h3-lh: 1.3; /* SemiBold 600 */ + --slabs-h4: 22px; --slabs-h4-mobile: 18px; --slabs-h4-lh: 1.4; /* SemiBold 600 */ + --slabs-h5: 15px; --slabs-h5-mobile: 14px; --slabs-h5-tracking: 0.08em; /* Plex Mono 600, capitals */ + --slabs-h6: 13px; --slabs-h6-tracking: 0.12em; /* Plex Mono 600, capitals */ + --slabs-body-reading: 18px; --slabs-body-reading-mobile: 16px; + --slabs-body: 16px; + --slabs-code-size: 14px; + --slabs-caption: 12px; + --slabs-label-tracking: 0.12em; /* Plex Mono 600 capitals */ + --slabs-nav: 15px; /* Space Grotesk 500 */ + + /* Line heights (p. 34) */ + --slabs-lh-ui: 1.5; + --slabs-lh-reading: 1.6; + --slabs-lh-code: 1.55; + + /* Layout (p. 31) */ + --slabs-content-max: 1200px; /* measured in the frame: the window minus the side band */ + --slabs-reading-max: 864px; /* about 80 characters, at least 72 % of the content area */ + --slabs-side-band: 288px; + --slabs-gutter: 24px; + --slabs-gutter-mobile: 16px; + --slabs-space-base: 4px; /* spacing in multiples of 4 px, from 4 to 96 px */ + --slabs-space-max: 96px; + --slabs-radius-card: 6px; + --slabs-radius-control: 4px; + --slabs-header-logo: 32px; /* logotype height in the header */ + /* Breakpoints, where the layout stops fitting: 640px and 1024px with a header, about 1100px with a side band */ + + /* Lines and focus (p. 33) */ + --slabs-link-underline: 1px; /* Schiste; 2px orange on hover and active */ + --slabs-focus-width: 2px; /* Anthracite on light grounds, orange on dark */ + --slabs-focus-offset: 2px; + --slabs-field-border: 1px; /* Schiste; 2px Brique in error */ + + /* Icons (Icones library) */ + --slabs-icon-size: 24px; + --slabs-icon-stroke: 2px; + /* --slabs-icon-accent: #ED6A20; set on an icon or a parent to turn the accent on */ +} diff --git a/docs/assets/stylesheets/slabs.css b/docs/assets/stylesheets/slabs.css new file mode 100644 index 0000000..eb9fe9b --- /dev/null +++ b/docs/assets/stylesheets/slabs.css @@ -0,0 +1,1120 @@ +/* + * The Slabs brand guidelines v2.0, applied to Material for MkDocs. + * + * Every value comes from slabs-tokens.css, loaded before this file and copied from the design kit as it is. + * This file only says which token goes where. The pages of the guidelines it follows are cited by number: + * p. 30 for documentation, p. 31 for the frame, p. 33 for components, p. 34 for reading and code. + * + * Two schemes. The light one is the guidelines: Calcaire ground, Anthracite text. The dark one keeps the + * same rules on an Anthracite ground, as the guidelines do for every dark surface: Calcaire text, Béton + * for what is secondary, notes on Calcaire clair (p. 19), focus in orange (p. 33). + * + * Signal orange marks the cursor of the logo, the slab of a note, the cursor of a primary button and the + * hovered link. Never text, never a background, never a tint. + */ + +/* ---------------------------------------------------------------- Typefaces (p. 22) */ + +@font-face { + font-display: swap; + font-family: "Space Grotesk"; + font-style: normal; + font-weight: 300 700; + src: url("../fonts/SpaceGrotesk-Variable.woff2") format("woff2"); +} + +/* IBM Plex Mono is served in 400 and 600 only on the web; the italic is for comments in code. */ +@font-face { + font-display: swap; + font-family: "IBM Plex Mono"; + font-style: normal; + font-weight: 400; + src: url("../fonts/IBMPlexMono-Regular.woff2") format("woff2"); +} + +@font-face { + font-display: swap; + font-family: "IBM Plex Mono"; + font-style: italic; + font-weight: 400; + src: url("../fonts/IBMPlexMono-Italic.woff2") format("woff2"); +} + +@font-face { + font-display: swap; + font-family: "IBM Plex Mono"; + font-style: normal; + font-weight: 600; + src: url("../fonts/IBMPlexMono-SemiBold.woff2") format("woff2"); +} + +/* ---------------------------------------------------------------- The two schemes */ + +[data-md-color-scheme="default"] { + --doc-ground: var(--slabs-calcaire); + --doc-raised: var(--slabs-calcaire-clair); + --doc-tint: var(--slabs-calcaire-ombre); + --doc-text: var(--slabs-anthracite); + --doc-text-secondary: var(--slabs-schiste); + --doc-rule: var(--slabs-platre); + --doc-rule-strong: var(--slabs-anthracite); + --doc-link-underline: var(--slabs-schiste); + --doc-focus: var(--slabs-anthracite); + --doc-code-edge: var(--slabs-anthracite); + --doc-field: #ffffff; + --doc-field-border: var(--slabs-schiste); + --doc-note-ground: var(--slabs-calcaire-ombre); +} + +[data-md-color-scheme="slate"] { + --doc-ground: var(--slabs-anthracite); + --doc-raised: var(--slabs-anthracite); + --doc-tint: var(--slabs-schiste); + --doc-text: var(--slabs-calcaire); + --doc-text-secondary: var(--slabs-beton); + --doc-rule: var(--slabs-schiste); + --doc-rule-strong: var(--slabs-calcaire); + --doc-link-underline: var(--slabs-beton); + --doc-focus: var(--slabs-orange); + /* A code block is Anthracite on an Anthracite ground: a Schiste line keeps its edge. */ + --doc-code-edge: var(--slabs-schiste); + --doc-field: var(--slabs-anthracite); + --doc-field-border: var(--slabs-beton); + --doc-note-ground: var(--slabs-calcaire-clair); +} + +[data-md-color-scheme="default"], +[data-md-color-scheme="slate"] { + --md-text-font: "Space Grotesk"; + --md-code-font: "IBM Plex Mono"; + + --md-default-fg-color: var(--doc-text); + --md-default-fg-color--light: var(--doc-text-secondary); + --md-default-fg-color--lighter: var(--doc-text-secondary); + --md-default-fg-color--lightest: var(--doc-rule); + --md-default-bg-color: var(--doc-ground); + --md-default-bg-color--light: var(--doc-ground); + --md-default-bg-color--lighter: var(--doc-ground); + --md-default-bg-color--lightest: var(--doc-ground); + + --md-primary-fg-color: var(--doc-text); + --md-primary-fg-color--light: var(--doc-text); + --md-primary-fg-color--dark: var(--doc-text); + --md-primary-bg-color: var(--doc-ground); + --md-primary-bg-color--light: var(--doc-text-secondary); + --md-accent-fg-color: var(--doc-text); + --md-accent-fg-color--transparent: var(--doc-tint); + --md-accent-bg-color: var(--doc-ground); + + --md-typeset-color: var(--doc-text); + --md-typeset-a-color: var(--doc-text); + --md-typeset-mark-color: var(--doc-tint); + --md-typeset-table-color: var(--doc-rule); + + --md-code-fg-color: var(--slabs-code-text); + --md-code-bg-color: var(--slabs-code-bg); + --md-code-hl-color: var(--slabs-schiste); + --md-code-hl-number-color: var(--slabs-code-string); + --md-code-hl-string-color: var(--slabs-code-string); + --md-code-hl-special-color: var(--slabs-code-string); + --md-code-hl-constant-color: var(--slabs-code-type); + --md-code-hl-name-color: var(--slabs-code-text); + --md-code-hl-function-color: var(--slabs-code-text); + --md-code-hl-keyword-color: var(--slabs-code-text); + --md-code-hl-operator-color: var(--slabs-code-text); + --md-code-hl-punctuation-color: var(--slabs-code-text); + --md-code-hl-variable-color: var(--slabs-code-text); + --md-code-hl-generic-color: var(--slabs-code-text); + --md-code-hl-comment-color: var(--slabs-code-comment); + --md-code-hl-color--light: var(--slabs-schiste); + + --md-footer-fg-color: var(--slabs-calcaire); + --md-footer-fg-color--light: var(--slabs-beton); + --md-footer-fg-color--lighter: var(--slabs-beton); + --md-footer-bg-color: var(--slabs-anthracite); + --md-footer-bg-color--dark: var(--slabs-anthracite); + + --md-shadow-z1: none; + --md-shadow-z2: none; + --md-shadow-z3: none; +} + +body { + -webkit-font-smoothing: antialiased; + background-color: var(--doc-ground); + text-rendering: optimizeLegibility; +} + +/* Focus, always visible (p. 33). */ +:focus-visible, +.md-typeset :focus-visible { + outline: var(--slabs-focus-width) solid var(--doc-focus); + outline-offset: var(--slabs-focus-offset); +} + +/* ---------------------------------------------------------------- Header (p. 31) */ + +.md-header, +.md-header--shadow { + background-color: var(--doc-raised); + border-bottom: 1px solid var(--doc-rule); + box-shadow: none; + color: var(--doc-text); +} + +/* The logo, 32 px high: the project mark, or the Slabs logotype for a project that has none yet. The + colour version on light grounds, the reversed one on dark. */ +.md-header__button.md-logo { + margin: 0 0 0 var(--slabs-gutter-mobile); + padding: 0; +} + +.md-logo .sl-logo, +.md-header__button.md-logo img { + display: block; + height: var(--slabs-header-logo); + width: auto; +} + +/* In the drawer of a narrow screen, the mark takes the width of the drawer. */ +.md-nav__button.md-logo .sl-logo { + height: auto; + max-width: 100%; +} + +[data-md-color-scheme="default"] .sl-logo--dark, +[data-md-color-scheme="slate"] .sl-logo--light { + display: none !important; +} + +/* The title of the page, after a rule, once the reader has scrolled past its heading. A project mark + already names the project: on a screen wide enough to show it, the name is not written a second time. + Beside the Slabs logotype, the name stays. */ +.md-header__title { + font-size: var(--slabs-nav); + font-weight: 600; + margin-left: var(--slabs-gutter); +} + +.md-header__title .md-header__ellipsis { + border-left: 1px solid var(--doc-rule); + padding-left: var(--slabs-gutter); +} + +@media screen and (min-width: 76.25em) { + .md-header:has(.sl-logo--mark) .md-header__title:not(.md-header__title--active) .md-header__ellipsis { + border-left-color: transparent; + } + + .md-header:has(.sl-logo--mark) .md-header__title .md-header__topic:first-child { + visibility: hidden; + } +} + +.md-header__button, +.md-header__topic, +.md-header__option, +.md-header__source { + color: var(--doc-text); +} + +.md-header__source { + font-family: var(--md-code-font-family); + font-size: var(--slabs-caption); +} + +.md-source__repository, +.md-source__facts { + font-family: var(--md-code-font-family); +} + +/* The search field is a field (p. 33): the ground of a field, a 1 px border, the radius of a control. */ +.md-search__form { + background-color: var(--doc-field); + border: var(--slabs-field-border) solid var(--doc-field-border); + border-radius: var(--slabs-radius-control); + box-shadow: none; +} + +.md-search__form:hover { + background-color: var(--doc-field); +} + +[data-md-toggle="search"]:checked ~ .md-header .md-search__form { + background-color: var(--doc-field); + border-radius: var(--slabs-radius-control) var(--slabs-radius-control) 0 0; +} + +.md-search__input, +.md-search__icon, +.md-search__options .md-icon { + color: var(--doc-text); +} + +.md-search__input { + font-size: var(--slabs-body); +} + +.md-search__input::placeholder { + color: var(--doc-text-secondary); +} + +.md-search__output { + border: var(--slabs-field-border) solid var(--doc-field-border); + border-radius: 0 0 var(--slabs-radius-control) var(--slabs-radius-control); + border-top: 0; +} + +.md-search__scrollwrap, +.md-search-result { + background-color: var(--doc-raised); +} + +.md-search-result__meta { + background-color: var(--doc-tint); + color: var(--doc-text-secondary); + font-family: var(--md-code-font-family); + font-size: var(--slabs-caption); +} + +.md-search-result__link:is(:focus, :hover) { + background-color: var(--doc-tint); +} + +.md-search-result mark { + color: var(--doc-text); + text-decoration: underline var(--slabs-orange) 2px; + text-underline-offset: 0.2em; +} + +/* The version is a control: Plex Mono, a 1 px rule, the radius of a control. */ +.md-version { + font-family: var(--md-code-font-family); +} + +.md-version__current { + border: 1px solid var(--doc-rule); + border-radius: var(--slabs-radius-control); + color: var(--doc-text-secondary); + font-size: var(--slabs-caption); + margin-left: var(--slabs-gutter-mobile); + padding: 0 calc(var(--slabs-space-base) * 2); +} + +.md-version__current::after { + background-color: var(--doc-text-secondary); +} + +.md-version__list { + background-color: var(--doc-raised); + border: 1px solid var(--doc-rule); + border-radius: var(--slabs-radius-card); + box-shadow: none; +} + +.md-version__link { + font-size: var(--slabs-caption); +} + +.md-version__link:is(:focus, :hover) { + background-color: var(--doc-tint); + color: var(--doc-text); +} + +/* ---------------------------------------------------------------- Layout (p. 31) */ + +/* The navigation takes the width of the side band, 288 px: the 168 px the guidelines leave beside the + reading column broke a title in two on most pages. The contents of the page keep those 168 px, and the + reading column its 864 px. */ +.md-grid { + max-width: calc(var(--slabs-side-band) + var(--slabs-reading-max) + 168px + 3 * var(--slabs-gutter)); +} + +@media screen and (min-width: 76.25em) { + .md-sidebar--primary { + width: var(--slabs-side-band); + } + + .md-sidebar--secondary { + width: calc(168px + var(--slabs-gutter)); + } +} + +@media screen and (min-width: 60em) { + .md-content__inner { + margin-left: auto; + margin-right: auto; + max-width: var(--slabs-reading-max); + } +} + +.md-main { + background-color: var(--doc-ground); +} + +/* ---------------------------------------------------------------- Navigation (p. 31) */ + +.md-nav { + font-size: var(--slabs-nav); + line-height: var(--slabs-lh-ui); +} + +.md-nav__link { + color: var(--doc-text); + font-weight: 500; + margin-top: calc(var(--slabs-space-base) * 2); +} + +.md-nav__link:is(:focus, :hover), +.md-nav__link[for]:is(:focus, :hover) { + color: var(--doc-text); +} + +/* The current page: SemiBold and a 2 px underline in the colour of the text. */ +.md-nav__link--active, +.md-nav__item .md-nav__link--active:hover { + color: var(--doc-text); + font-weight: 600; +} + +/* The underline is drawn on the text of the link only: drawn on the link as well, it doubles. */ +.md-nav--primary .md-nav__link { + text-decoration: none; +} + +.md-nav--primary .md-nav__link--active > .md-ellipsis { + text-decoration: underline 2px var(--doc-rule-strong); + text-underline-offset: 0.35em; +} + +/* Under the pointer, a link of the navigation behaves as a link of the text (p. 33): a 2 px orange + underline, on the current page as on the others. */ +.md-nav--primary a.md-nav__link:is(:hover, :focus-visible) > .md-ellipsis { + text-decoration: underline 2px var(--slabs-orange); + text-underline-offset: 0.35em; +} + +/* A section title is a label: Plex Mono SemiBold capitals, 12 px, tracked, in the secondary colour. */ +.md-nav--primary .md-nav__item--section > .md-nav__link, +.md-nav--primary .md-nav__item--section > .md-nav__container > .md-nav__link { + color: var(--doc-text-secondary); + cursor: default; + font-family: var(--md-code-font-family); + font-size: var(--slabs-caption); + font-weight: 600; + letter-spacing: var(--slabs-label-tracking); + margin-top: calc(var(--slabs-space-base) * 6); + text-decoration: none; + text-transform: uppercase; +} + +.md-nav--primary .md-nav__item--section > .md-nav__link .md-nav__icon { + display: none; +} + +@media screen and (min-width: 76.25em) { + .md-nav--primary > .md-nav__title { + display: none; + } +} + +/* The drawer of a narrow screen opens on the same band as the header. */ +.md-nav--primary > .md-nav__title, +.md-nav--primary > .md-nav__title .md-nav__button { + background-color: var(--doc-raised); + color: var(--doc-text); +} + +.md-nav--primary .md-nav__title { + box-shadow: none; + font-weight: 600; +} + +.md-sidebar { + background-color: var(--doc-ground); +} + +@media screen and (max-width: 76.234375em) { + .md-nav--primary .md-nav__title, + .md-nav--primary .md-nav__item { + border-top: 0; + } + + .md-nav--primary .md-nav__link { + margin-top: 0; + padding: calc(var(--slabs-space-base) * 2) var(--slabs-gutter-mobile); + } +} + +/* The contents of the page, on the right: the same label, then the headings. */ +.md-nav--secondary .md-nav__title { + background: transparent; + box-shadow: none; + color: var(--doc-text-secondary); + font-family: var(--md-code-font-family); + font-size: var(--slabs-caption); + font-weight: 600; + letter-spacing: var(--slabs-label-tracking); + text-transform: uppercase; +} + +.md-nav--secondary .md-nav__link { + color: var(--doc-text-secondary); + font-weight: 400; +} + +.md-nav--secondary .md-nav__link--active, +.md-nav--secondary .md-nav__link:is(:hover, :focus-visible) { + color: var(--doc-text); +} + +.md-nav--secondary a.md-nav__link:is(:hover, :focus-visible) { + text-decoration: underline 2px var(--slabs-orange); + text-underline-offset: 0.35em; +} + +/* ---------------------------------------------------------------- Reading (p. 34) */ + +/* The body of a page reads as an article: 18 px, 16 px on a phone, line height 1.6. Interface text, the + navigation, the fields and the buttons, keeps its own sizes. */ +.md-typeset { + color: var(--doc-text); + font-size: var(--slabs-body-reading); + line-height: var(--slabs-lh-reading); +} + +@media screen and (max-width: 640px) { + .md-typeset { + font-size: var(--slabs-body-reading-mobile); + } +} + +.md-typeset :is(h1, h2, h3, h4) { + color: var(--doc-text); + font-family: var(--md-text-font-family); + letter-spacing: 0; +} + +.md-typeset h1 { + font-size: var(--slabs-h1); + font-weight: 700; + line-height: var(--slabs-h1-lh); + margin: 0 0 calc(var(--slabs-space-base) * 6); +} + +.md-typeset h2 { + font-size: var(--slabs-h2); + font-weight: 700; + line-height: var(--slabs-h2-lh); + margin: calc(var(--slabs-space-base) * 12) 0 calc(var(--slabs-space-base) * 4); +} + +.md-typeset h3 { + font-size: var(--slabs-h3); + font-weight: 600; + line-height: var(--slabs-h3-lh); + margin: calc(var(--slabs-space-base) * 10) 0 calc(var(--slabs-space-base) * 3); +} + +.md-typeset h4 { + font-size: var(--slabs-h4); + font-weight: 600; + line-height: var(--slabs-h4-lh); + margin: calc(var(--slabs-space-base) * 8) 0 calc(var(--slabs-space-base) * 2); +} + +/* H5 and H6 are labels: Plex Mono SemiBold capitals. */ +.md-typeset h5, +.md-typeset h6 { + color: var(--doc-text); + font-family: var(--md-code-font-family); + font-weight: 600; + text-transform: uppercase; +} + +.md-typeset h5 { + font-size: var(--slabs-h5); + letter-spacing: var(--slabs-h5-tracking); +} + +.md-typeset h6 { + font-size: var(--slabs-h6); + letter-spacing: var(--slabs-h6-tracking); +} + +@media screen and (max-width: 640px) { + .md-typeset h1 { font-size: var(--slabs-h1-mobile); } + .md-typeset h2 { font-size: var(--slabs-h2-mobile); } + .md-typeset h3 { font-size: var(--slabs-h3-mobile); } + .md-typeset h4 { font-size: var(--slabs-h4-mobile); } + .md-typeset h5 { font-size: var(--slabs-h5-mobile); } +} + +.md-typeset .headerlink { + color: var(--doc-text-secondary); +} + +.md-typeset p, +.md-typeset li { + text-align: left; +} + +.md-typeset hr { + border-bottom: 1px solid var(--doc-rule); +} + +.md-typeset blockquote { + border-left: 0; + color: var(--doc-text-secondary); + padding-left: var(--slabs-gutter); +} + +/* The date of the last change and the pencil that edits a page: secondary, in Plex Mono. */ +.md-source-file, +.md-typeset .md-source-file__fact { + color: var(--doc-text-secondary); + font-family: var(--md-code-font-family); + font-size: var(--slabs-caption); +} + +.md-content__button { + color: var(--doc-text-secondary); +} + +.md-content__button:hover { + color: var(--doc-text); +} + +/* ---------------------------------------------------------------- Links (p. 33) */ + +.md-typeset a { + color: var(--doc-text); + text-decoration: underline var(--slabs-link-underline) var(--doc-link-underline); + text-underline-offset: 0.2em; +} + +.md-typeset a:is(:hover, :active) { + color: var(--doc-text); + text-decoration-color: var(--slabs-orange); + text-decoration-thickness: 2px; +} + +.md-typeset a.headerlink, +.md-typeset a.md-button, +.md-typeset a.md-content__button { + text-decoration: none; +} + +/* ---------------------------------------------------------------- Code (p. 30, 34) */ + +.md-typeset code, +.md-typeset kbd, +.md-typeset pre { + font-feature-settings: "kern"; +} + +/* Inline code, on Calcaire ombré. */ +.md-typeset :not(pre) > code { + background-color: var(--doc-tint); + border-radius: var(--slabs-radius-control); + color: var(--doc-text); + font-size: var(--slabs-code-size); + padding: 0.1em 0.35em; + word-break: normal; +} + +/* In a heading, inline code follows the size of the heading. */ +.md-typeset :is(h1, h2, h3, h4) code { + font-size: 0.85em; +} + +/* A code block: Plex Mono 14 px on Anthracite, the radius of a card. */ +.md-typeset .highlight { + background-color: var(--slabs-code-bg); + border: 1px solid var(--doc-code-edge); + border-radius: var(--slabs-radius-card); + overflow: hidden; +} + +/* A numbered block is a table inside the block: the block already draws the edge. */ +.md-typeset .highlight .highlighttable, +.md-typeset .highlighttable { + background-color: var(--slabs-code-bg); + border: 0; + border-radius: 0; + margin: 0; +} + +.md-typeset .highlighttable :is(.linenos, .code) { + vertical-align: top; +} + +.md-typeset pre { + margin: 0; +} + +.md-typeset pre > code, +.md-typeset .highlighttable code { + background-color: var(--slabs-code-bg); + color: var(--slabs-code-text); + font-size: var(--slabs-code-size); + line-height: var(--slabs-lh-code); + padding: calc(var(--slabs-space-base) * 4) calc(var(--slabs-space-base) * 5); +} + +.md-typeset .highlight + .highlight, +.md-typeset .highlight + p, +.md-typeset p + .highlight { + margin-top: calc(var(--slabs-space-base) * 4); +} + +.md-typeset .highlight { + margin: calc(var(--slabs-space-base) * 4) 0; +} + +/* The filename of a block, a caption above the code. */ +.md-typeset .highlight span.filename { + background-color: var(--slabs-code-bg); + border-bottom: 1px solid var(--slabs-schiste); + color: var(--slabs-beton); + font-family: var(--md-code-font-family); + font-size: var(--slabs-caption); + font-weight: 400; + margin: 0; + padding: calc(var(--slabs-space-base) * 2) calc(var(--slabs-space-base) * 5); +} + +.md-typeset .highlight span.filename::before { + display: none; +} + +/* Line numbers, at the start of each line, in Béton behind a Schiste rule. */ +.md-typeset .highlight [data-linenos]::before { + background-color: var(--slabs-code-bg); + box-shadow: -1px 0 var(--slabs-schiste) inset; + color: var(--slabs-code-comment); + margin-right: calc(var(--slabs-space-base) * 4); + padding-right: calc(var(--slabs-space-base) * 3); +} + +/* The line numbers are anchors: they are not links of the text. */ +.md-typeset .highlighttable .linenos a, +.md-typeset .highlight .linenos a { + color: var(--slabs-code-comment); + text-decoration: none; +} + +.md-typeset .highlight .hll { + background-color: var(--md-code-hl-color); +} + +/* The copy button sits on the code, in Béton, with no box of its own. */ +.md-code__nav, +:hover > .md-code__nav { + background-color: transparent; +} + +.md-code__button, +.md-clipboard { + background-color: transparent; + color: var(--slabs-beton); +} + +:hover > * > .md-code__button { + color: var(--slabs-beton); +} + +.md-code__button:is(.focus-visible, :hover), +.md-clipboard:is(:focus, :hover) { + color: var(--slabs-calcaire); + outline-color: var(--slabs-orange); +} + +/* The five token styles: text and variables Calcaire, keywords Calcaire SemiBold, types and properties + Plâtre, strings and numbers Sable, comments Béton italic. Operators and punctuation are text. */ +.md-typeset .highlight :is(.n, .nv, .vc, .vg, .vi, .vm, .nf, .fm, .nl, .ni, .ne, .o, .p, .w, .x, .err) { + color: var(--slabs-code-text); + font-style: normal; + font-weight: 400; +} + +.md-typeset .highlight :is(.k, .kc, .kd, .kn, .kp, .kr, .ow) { + color: var(--slabs-code-text); + font-style: normal; + font-weight: 600; +} + +.md-typeset .highlight :is(.kt, .nc, .nn, .nx, .na, .nb, .bp, .nt, .nd, .no, .py) { + color: var(--slabs-code-type); + font-style: normal; + font-weight: 400; +} + +.md-typeset .highlight :is(.l, .ld, .s, .s1, .s2, .sa, .sb, .sc, .sd, .se, .sh, .si, .sr, .ss, .sx, .dl, + .m, .mb, .mf, .mh, .mi, .il, .mo) { + color: var(--slabs-code-string); + font-style: normal; + font-weight: 400; +} + +.md-typeset .highlight :is(.c, .c1, .ch, .cm, .cp, .cpf, .cs) { + color: var(--slabs-code-comment); + font-style: italic; + font-weight: 400; +} + +.md-typeset .highlight :is(.gd, .gi, .gh, .gu, .go, .gp) { + color: var(--slabs-code-text); +} + +/* The orange cursor marks the prompt of a console session (p. 30). */ +.md-typeset .highlight .gp { + color: var(--slabs-orange); +} + +/* Tabs, for alternatives the reader chooses between: labels in Plex Mono, the current one underlined. */ +.md-typeset .tabbed-labels > label { + color: var(--doc-text-secondary); + font-family: var(--md-code-font-family); + font-size: var(--slabs-caption); + font-weight: 600; + letter-spacing: var(--slabs-label-tracking); + text-transform: uppercase; +} + +/* The theme turns each label into an anchor, to link to a tab: it is not a link of the text. */ +.md-typeset .tabbed-labels a { + color: inherit; + text-decoration: none; +} + +.md-typeset .tabbed-labels > label:hover, +.md-typeset .tabbed-set > input:checked + label { + color: var(--doc-text); +} + +.md-typeset .tabbed-labels::before { + background-color: var(--doc-rule-strong); +} + +/* ---------------------------------------------------------------- Notes (p. 30) */ + +/* A tinted box with a slab on top, never a coloured side border. Every kind of note looks the same: the + word of its title says what it is, colour never does (p. 19). On a dark ground the box is Calcaire + clair and its text Anthracite, as a message on Anthracite always is (p. 19). */ +.md-typeset .admonition, +.md-typeset details { + --md-typeset-a-color: var(--slabs-anthracite); + + background-color: var(--doc-note-ground); + border: 0; + border-radius: var(--slabs-radius-card); + box-shadow: none; + color: var(--slabs-anthracite); + font-size: inherit; + margin: calc(var(--slabs-space-base) * 6) 0; + padding: calc(var(--slabs-space-base) * 5) calc(var(--slabs-space-base) * 5) calc(var(--slabs-space-base) * 4); + position: relative; +} + +/* The slab: a quarter of the size of an H4 high, 1.2 times as wide, flat, square ends, on the top edge. */ +.md-typeset .admonition::before, +.md-typeset details::before { + background-color: var(--slabs-orange); + content: ""; + height: calc(var(--slabs-h4) / 4); + left: calc(var(--slabs-space-base) * 5); + position: absolute; + top: 0; + width: calc(var(--slabs-h4) * 1.2); +} + +.md-typeset :is(.admonition, details) > :is(.admonition-title, summary) { + background-color: transparent !important; + border: 0; + color: var(--slabs-anthracite); + font-family: var(--md-code-font-family); + font-size: var(--slabs-h6); + font-weight: 600; + letter-spacing: var(--slabs-h6-tracking); + margin: 0 0 calc(var(--slabs-space-base) * 2); + padding: 0; + text-transform: uppercase; +} + +/* The icons of the theme are not the Slabs set: the word is enough. */ +.md-typeset :is(.admonition, details) > :is(.admonition-title, summary)::before { + display: none; +} + +.md-typeset details > summary { + cursor: pointer; + padding-right: calc(var(--slabs-space-base) * 6); +} + +.md-typeset details > summary::after { + background-color: var(--slabs-anthracite); + top: 0; +} + +.md-typeset .admonition > :last-child, +.md-typeset details > :last-child { + margin-bottom: 0; +} + +.md-typeset :is(.admonition, details) :is(a, a:hover) { + color: var(--slabs-anthracite); +} + +.md-typeset :is(.admonition, details) a { + text-decoration-color: var(--slabs-schiste); +} + +.md-typeset :is(.admonition, details) a:hover { + text-decoration-color: var(--slabs-orange); +} + +.md-typeset :is(.admonition, details) :not(pre) > code { + background-color: var(--slabs-calcaire-ombre); + color: var(--slabs-anthracite); +} + +[data-md-color-scheme="default"] .md-typeset :is(.admonition, details) :not(pre) > code { + background-color: var(--slabs-calcaire-clair); +} + +/* ---------------------------------------------------------------- Tables (p. 33) */ + +.md-typeset table:not([class]) { + background-color: transparent; + border: 0; + border-collapse: collapse; + border-radius: 0; + box-shadow: none; + display: table; + font-size: inherit; + width: 100%; +} + +/* The header: Plex Mono capitals over a rule in the colour of the text. */ +.md-typeset table:not([class]) th { + background-color: transparent; + border-bottom: 1px solid var(--doc-rule-strong); + color: var(--doc-text); + font-family: var(--md-code-font-family); + font-size: var(--slabs-caption); + font-weight: 600; + letter-spacing: var(--slabs-label-tracking); + text-transform: uppercase; + vertical-align: bottom; +} + +.md-typeset table:not([class]) :is(th, td) { + padding: calc(var(--slabs-space-base) * 3) calc(var(--slabs-space-base) * 4) calc(var(--slabs-space-base) * 3) 0; +} + +.md-typeset table:not([class]) :is(th, td):last-child { + padding-right: 0; +} + +/* Plâtre between the rows. */ +.md-typeset table:not([class]) td { + border-top: 0; + border-bottom: 1px solid var(--doc-rule); + vertical-align: top; +} + +.md-typeset table:not([class]) tbody tr:hover { + background-color: transparent; + box-shadow: none; +} + +.md-typeset__scrollwrap { + margin: calc(var(--slabs-space-base) * 6) 0; +} + +.md-typeset__table { + padding: 0; +} + +/* ---------------------------------------------------------------- Buttons (p. 33) */ + +.md-typeset .md-button { + border: 1px solid var(--doc-text); + border-radius: var(--slabs-radius-control); + color: var(--doc-text); + font-size: var(--slabs-body); + font-weight: 500; + padding: calc(var(--slabs-space-base) * 2) calc(var(--slabs-space-base) * 4); + position: relative; +} + +.md-typeset .md-button:is(:focus, :hover) { + background-color: transparent; + border-color: var(--doc-text); + color: var(--doc-text); +} + +/* The primary button: Anthracite, Calcaire text, the orange cursor after the label. On hover the cursor + stretches under the label. */ +.md-typeset .md-button--primary, +.md-typeset .md-button--primary:is(:focus, :hover) { + background-color: var(--slabs-anthracite); + border-color: var(--slabs-anthracite); + color: var(--slabs-calcaire); + padding-right: calc(var(--slabs-space-base) * 8); +} + +[data-md-color-scheme="slate"] .md-typeset .md-button--primary, +[data-md-color-scheme="slate"] .md-typeset .md-button--primary:is(:focus, :hover) { + background-color: var(--slabs-calcaire); + border-color: var(--slabs-calcaire); + color: var(--slabs-anthracite); +} + +.md-typeset .md-button--primary::after { + background-color: var(--slabs-orange); + bottom: calc(var(--slabs-space-base) * 2 + 0.2em); + content: ""; + height: 0.25em; + position: absolute; + right: calc(var(--slabs-space-base) * 4); + transition: left 150ms, right 150ms, bottom 150ms; + width: auto; + left: calc(100% - var(--slabs-space-base) * 4 - 0.6em); +} + +.md-typeset .md-button--primary:hover::after { + bottom: calc(var(--slabs-space-base) * 1); + left: calc(var(--slabs-space-base) * 4); + right: calc(var(--slabs-space-base) * 8); +} + +/* ---------------------------------------------------------------- Footer (p. 31) */ + +/* Anthracite, whatever the scheme: the previous and next pages, then the reversed signature, the links in + Calcaire and the legal line in Béton. */ +.md-footer { + background-color: var(--slabs-anthracite); + color: var(--slabs-calcaire); +} + +.md-footer__inner { + border-bottom: 1px solid var(--slabs-schiste); + max-width: calc(var(--slabs-content-max) + 2 * var(--slabs-gutter)); + padding: calc(var(--slabs-space-base) * 4) var(--slabs-gutter); +} + +.md-footer__link { + color: var(--slabs-calcaire); + opacity: 1; +} + +.md-footer__link:is(:focus, :hover) { + opacity: 1; +} + +.md-footer__link:hover .md-footer__title { + text-decoration: underline 2px var(--slabs-orange); + text-underline-offset: 0.2em; +} + +.md-footer__link:focus-visible { + outline-color: var(--slabs-orange); +} + +.md-footer__direction { + color: var(--slabs-beton); + font-family: var(--md-code-font-family); + font-size: var(--slabs-caption); + letter-spacing: var(--slabs-label-tracking); + text-transform: uppercase; +} + +.md-footer__title { + font-size: var(--slabs-body); + font-weight: 600; +} + +.md-footer-meta { + background-color: var(--slabs-anthracite); +} + +.md-footer-meta__inner { + max-width: calc(var(--slabs-content-max) + 2 * var(--slabs-gutter)); + padding: calc(var(--slabs-space-base) * 8) var(--slabs-gutter); +} + +.sl-footer { + display: grid; + gap: calc(var(--slabs-space-base) * 6); + grid-template-columns: auto 1fr; + width: 100%; +} + +/* The signature: the S at 40 px at least, which makes the file 60 px high. */ +.sl-footer__signature img { + display: block; + height: 60px; + width: auto; +} + +.md-typeset ul.sl-footer__links > li { + list-style: none; + margin: 0; +} + +.md-typeset ul.sl-footer__links:not([hidden]) { + align-self: start; + display: flex; + justify-content: flex-end; + flex-wrap: wrap; + gap: calc(var(--slabs-space-base) * 2) calc(var(--slabs-space-base) * 6); + list-style: none; + margin: 0; + padding: 0; +} + +.sl-footer__links a, +.md-footer-meta .sl-footer__links a { + color: var(--slabs-calcaire); + font-size: var(--slabs-nav); + text-decoration: underline var(--slabs-link-underline) var(--slabs-beton); + text-underline-offset: 0.2em; +} + +.sl-footer__legal { + border-top: 1px solid var(--slabs-schiste); + color: var(--slabs-beton); + font-family: var(--md-code-font-family); + font-size: var(--slabs-caption); + grid-column: 1 / -1; + margin: 0; + padding-top: calc(var(--slabs-space-base) * 4); +} + +.sl-footer__legal a, +.md-footer-meta .sl-footer__legal a { + color: var(--slabs-beton); + text-decoration: none; +} + +.md-footer-meta :is(.sl-footer__links, .sl-footer__legal) a:is(:focus, :hover) { + color: var(--slabs-calcaire); + text-decoration: underline 2px var(--slabs-orange); + text-underline-offset: 0.2em; +} + +.md-footer-meta a:focus-visible { + outline-color: var(--slabs-orange); +} + +@media screen and (max-width: 640px) { + .sl-footer { + grid-template-columns: 1fr; + } + + .md-typeset ul.sl-footer__links:not([hidden]) { + justify-content: flex-start; + } +} diff --git a/docs/overrides/main.html b/docs/overrides/main.html new file mode 100644 index 0000000..8de097c --- /dev/null +++ b/docs/overrides/main.html @@ -0,0 +1,24 @@ +{% extends "base.html" %} + +{#- + The favicons and the share image of the design kit (4-Web/icones, 4-Web/partage). The SVG favicon is + theme.favicon; the ICO and the Apple touch icon complete it. +-#} +{% block extrahead %} + + + + + {% set title = (page.title ~ " · " ~ config.site_name) if page and page.title and not page.is_homepage else config.site_name %} + {% set description = (page.meta.description if page and page.meta and page.meta.description else config.site_description) %} + + + + + {% if page and page.canonical_url %}{% endif %} + + + + + +{% endblock %} diff --git a/docs/overrides/partials/copyright.html b/docs/overrides/partials/copyright.html new file mode 100644 index 0000000..7fe0bb4 --- /dev/null +++ b/docs/overrides/partials/copyright.html @@ -0,0 +1,22 @@ +{#- + The footer of the Slabs guidelines: the reversed signature, the links in Calcaire, the legal line in Béton. + The signature is the drawing of the design kit, never retyped. Its links and the legal line are in + extra.slabs of mkdocs.yml. +-#} +{% set slabs = config.extra.slabs %} + diff --git a/docs/overrides/partials/logo.html b/docs/overrides/partials/logo.html new file mode 100644 index 0000000..ea4e744 --- /dev/null +++ b/docs/overrides/partials/logo.html @@ -0,0 +1,8 @@ +{#- + The project mark of JWT Framework: the Slabs monogram, the name of the project and "by Slabs". The + colour version on a light ground, the reversed one on a dark ground, from the web set of the design kit + without their metadata (tools/web-svg.py of Spomky-Labs/docs). The link around them carries the + accessible name, so the images say nothing. +-#} + + diff --git a/docs/overrides/partials/source.html b/docs/overrides/partials/source.html new file mode 100644 index 0000000..3d8f7f0 --- /dev/null +++ b/docs/overrides/partials/source.html @@ -0,0 +1,13 @@ +{#- + The link to the repository, without the stars and the forks: the theme would ask the API of GitHub for + them from the browser of the reader, and this site sends nothing to a third party. +-#} + +
+ {% set icon = config.theme.icon.repo or "fontawesome/brands/git-alt" %} + {% include ".icons/" ~ icon ~ ".svg" %} +
+
+ {{ config.repo_name }} +
+
diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..77abb09 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,248 @@ +site_name: JWT Framework +site_description: JSON Web Tokens for PHP and Symfony. Signature (JWS), encryption (JWE) and keys (JWK), after RFC 7515 to RFC 7519. +site_url: https://web-token.spomky-labs.com/ +site_author: Spomky-Labs +repo_url: https://github.com/web-token/jwt-framework +repo_name: web-token/jwt-framework +edit_uri: https://github.com/web-token/jwt-doc/edit/4.0/docs/ + +docs_dir: docs +site_dir: site + +# The GitBook table of contents. It stays while GitBook serves the domain, and the navigation below says the +# same thing in the words of MkDocs. +exclude_docs: | + SUMMARY.md + +theme: + name: material + custom_dir: docs/overrides + language: en + # Space Grotesk and IBM Plex Mono are served from assets/fonts, declared in slabs.css: the theme loads + # no font of its own. + font: false + icon: + repo: fontawesome/brands/github + edit: material/pencil-outline + annotation: material/plus-circle + favicon: assets/brand/favicon.svg + palette: + - media: "(prefers-color-scheme)" + toggle: + icon: material/brightness-auto + name: Follow the system theme + - media: "(prefers-color-scheme: light)" + scheme: default + primary: custom + accent: custom + toggle: + icon: material/weather-sunny + name: Switch to the dark theme + - media: "(prefers-color-scheme: dark)" + scheme: slate + primary: custom + accent: custom + toggle: + icon: material/weather-night + name: Switch to the light theme + features: + - navigation.instant + - navigation.instant.progress + - navigation.tracking + - navigation.sections + - navigation.indexes + - navigation.top + - navigation.footer + - toc.follow + - search.suggest + - search.highlight + - search.share + - content.code.copy + - content.code.annotate + - content.tabs.link + - content.tooltips + - content.action.edit + +# The tokens of the Slabs design kit, as they are, then the rules that apply them. +extra_css: + - assets/stylesheets/slabs-tokens.css + - assets/stylesheets/slabs.css + +plugins: + - search + # Every asset is served from this site. Should a page ever reference an external one, it is downloaded + # at build time: nothing a reader loads reaches a third party. + - privacy + - git-revision-date-localized: + enable_creation_date: false + type: date + fallback_to_build_date: true + - redirects: + redirect_maps: {} + +markdown_extensions: + - abbr + - admonition + - attr_list + - def_list + - footnotes + - md_in_html + - tables + - toc: + title: On this page + permalink: true + permalink_title: Link to this section + toc_depth: 3 + - pymdownx.betterem + - pymdownx.caret + - pymdownx.details + - pymdownx.emoji: + emoji_index: !!python/name:material.extensions.emoji.twemoji + emoji_generator: !!python/name:material.extensions.emoji.to_svg + - pymdownx.highlight: + anchor_linenums: true + # A PHP block of these pages starts without " + + + + + + Page not found · JWT Framework + + + + + + + +
+

Looking for this page in the latest version…

+
+ +

Page not found

+

This page has moved or never existed. Search, or start from one of these:

+
+ + +
+ +
+
+ + diff --git a/site-root/CNAME b/site-root/CNAME new file mode 100644 index 0000000..163ae4e --- /dev/null +++ b/site-root/CNAME @@ -0,0 +1 @@ +web-token.spomky-labs.com From 392acf64ada2afdd1ed78814821b7f7467ca717d Mon Sep 17 00:00:00 2001 From: Florent Morselli Date: Sun, 25 Oct 2026 21:26:52 +0100 Subject: [PATCH 6/7] style: the contents of the page as wide as the navigation, and old addresses that land somewhere The contents of the page, on the right, take the 288 px of the side band, as the navigation does on the left; the reading column keeps its 864 px. An address of the former GitBook site whose page does not exist in the version it is sent to now lands on the home page of that version instead of on "page not found": the variants that are not published (1.x to 3.3) had another tree of pages. --- docs/assets/stylesheets/slabs.css | 10 +++++----- site-root/404.html | 21 +++++++++++++++++---- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/docs/assets/stylesheets/slabs.css b/docs/assets/stylesheets/slabs.css index eb9fe9b..0255cef 100644 --- a/docs/assets/stylesheets/slabs.css +++ b/docs/assets/stylesheets/slabs.css @@ -323,11 +323,11 @@ body { /* ---------------------------------------------------------------- Layout (p. 31) */ -/* The navigation takes the width of the side band, 288 px: the 168 px the guidelines leave beside the - reading column broke a title in two on most pages. The contents of the page keep those 168 px, and the - reading column its 864 px. */ +/* The navigation and the contents of the page take the width of the side band, 288 px each: the 168 px + the guidelines leave beside the reading column broke a title in two on most pages. The reading column + keeps its 864 px. */ .md-grid { - max-width: calc(var(--slabs-side-band) + var(--slabs-reading-max) + 168px + 3 * var(--slabs-gutter)); + max-width: calc(2 * var(--slabs-side-band) + var(--slabs-reading-max) + 2 * var(--slabs-gutter)); } @media screen and (min-width: 76.25em) { @@ -336,7 +336,7 @@ body { } .md-sidebar--secondary { - width: calc(168px + var(--slabs-gutter)); + width: var(--slabs-side-band); } } diff --git a/site-root/404.html b/site-root/404.html index e799715..b08c5b1 100644 --- a/site-root/404.html +++ b/site-root/404.html @@ -8,8 +8,8 @@ From 6ef6d3ab1f035e0b6cb07473b4eb6b65d8b3b532 Mon Sep 17 00:00:00 2001 From: Florent Morselli Date: Sun, 25 Oct 2026 21:27:06 +0100 Subject: [PATCH 7/7] chore: the addresses of the console commands and the benchmarks on GitBook keep leading to them GitBook published them under console-commands/ and benchmarks/ from 4.1 on; the directories are console-command/ and benchmark/. --- mkdocs.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/mkdocs.yml b/mkdocs.yml index c668043..52d8ce8 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -77,8 +77,16 @@ plugins: enable_creation_date: false type: date fallback_to_build_date: true + # GitBook published the console commands under console-commands/ and the benchmarks under benchmarks/; + # the directories are console-command/ and benchmark/. - redirects: - redirect_maps: {} + redirect_maps: + console-commands/console.md: console-command/console.md + console-commands/standalone.md: console-command/standalone.md + console-commands/phar-application.md: console-command/phar-application.md + console-commands/symfony-console.md: console-command/symfony-console.md + benchmarks/benchmarks.md: benchmark/benchmarks.md + benchmarks/result-table.md: benchmark/result-table.md markdown_extensions: - abbr