diff --git a/.asciidoctorconfig b/.asciidoctorconfig deleted file mode 100644 index d35a12c24..000000000 --- a/.asciidoctorconfig +++ /dev/null @@ -1,6 +0,0 @@ -:icons: font -:idprefix: -:idseparator: - -:project_buildType: latest -ifndef::asciidoctorconfigdir[:asciidoctorconfigdir: .] -include::{asciidoctorconfigdir}/topics/templates/document-attributes.adoc[] diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 2b70adf8d..000000000 --- a/.gitattributes +++ /dev/null @@ -1,20 +0,0 @@ -* text=auto - -*.html text eol=lf -*.java text eol=lf -*.js text eol=lf -*.json text eol=lf -*.jsp text eol=lf -*.md text eol=lf -*.properties text eol=lf -*.svg text auto -*.xml text eol=lf -*.xsl text eol=lf - -*.png binary -*.jpg binary -*.gif binary -*.ttf binary -*.eot binary -*.otf binary -*.woff binary diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml deleted file mode 100644 index 7fb2a5f59..000000000 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: Bug Report -description: Report a non-security sensitive bug in Keycloak -labels: ["kind/bug", "status/triage"] -body: - - type: textarea - attributes: - label: Describe the bug - description: Provide a clear and concise description of what the problem is. - validations: - required: true - - type: input - attributes: - label: Version - description: What version of Keycloak are you running? - validations: - required: true - - type: textarea - attributes: - label: Expected behavior - description: Describe the expected behavior clearly and concisely. - validations: - required: false - - type: textarea - attributes: - label: Actual behavior - description: Describe the actual behavior clearly and concisely. - validations: - required: false - - type: textarea - attributes: - label: How to Reproduce? - description: Provide clear and concise steps to reproduce the problem. - validations: - required: false - - type: textarea - attributes: - label: Anything else? - description: Links? References? Anything that will give us more context about the issue you are encountering! - validations: - required: false \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml deleted file mode 100644 index 14eeec14b..000000000 --- a/.github/ISSUE_TEMPLATE/config.yml +++ /dev/null @@ -1,11 +0,0 @@ -blank_issues_enabled: false -contact_links: - - name: Discussions - url: https://github.com/keycloak/keycloak/discussions - about: Propose new ideas, provide feedback, or ask for help here - - name: User mailing list - url: https://groups.google.com/forum/#!forum/keycloak-user - about: Ask and answer questions here - - name: Developer mailing list - url: https://groups.google.com/forum/#!forum/keycloak-dev - about: Propose new features and join in design discussions here diff --git a/.github/ISSUE_TEMPLATE/enhancement.yml b/.github/ISSUE_TEMPLATE/enhancement.yml deleted file mode 100644 index 70033aecb..000000000 --- a/.github/ISSUE_TEMPLATE/enhancement.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: Enhancement Request -description: Request an enhancement to an existing feature -labels: ["kind/enhancement", "status/triage"] -body: - - type: textarea - attributes: - label: Description - description: Describe the enhancement at a high-level. - validations: - required: true - - type: input - attributes: - label: Discussion - description: | - If there has been a discussion around the enhancement, provide a link to the discussion. - - Please note that larger enhancements should be discussed through [GitHub Discussion](https://github.com/keycloak/keycloak/discussions/categories/ideas). - validations: - required: false - - type: textarea - attributes: - label: Motivation - description: Describe why the feature should be added. - validations: - required: false - - type: textarea - attributes: - label: Details - description: More details? Implementation ideas? Anything that will give us more context about the enhancement you are proposing! - validations: - required: false \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/epic.yml b/.github/ISSUE_TEMPLATE/epic.yml deleted file mode 100644 index 7198406c6..000000000 --- a/.github/ISSUE_TEMPLATE/epic.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: Epic -description: A large feature that is broken down into multiple linked issues. -labels: ["kind/epic", "status/triage"] -body: - - type: textarea - attributes: - label: Description - description: Describe the feature at a high-level. - validations: - required: true - - type: input - attributes: - label: Discussion - description: | - Provide a link to the GitHub Discussion for the feature. - validations: - required: true - - type: textarea - attributes: - label: Issues - description: List the issues related to this epic. - placeholder: | - - #1 - - #2 - validations: - required: false - - type: textarea - attributes: - label: Motivation - description: Provide a brief explanation of why the feature should be added. - validations: - required: false \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/feature.yml b/.github/ISSUE_TEMPLATE/feature.yml deleted file mode 100644 index 1be4eb862..000000000 --- a/.github/ISSUE_TEMPLATE/feature.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: Feature Request -description: Request a new feature to be added to Keycloak -labels: ["kind/feature", "status/triage"] -body: - - type: textarea - attributes: - label: Description - description: Describe the feature at a high-level. - validations: - required: true - - type: input - attributes: - label: Discussion - description: | - If there has been a discussion around the feature, provide a link to the discussion. - - Please note that all, except small requests, should be discussed through [GitHub Discussion](https://github.com/keycloak/keycloak/discussions/categories/ideas). - validations: - required: false - - type: textarea - attributes: - label: Motivation - description: Describe why the feature should be added. - validations: - required: false - - type: textarea - attributes: - label: Details - description: Design ideas? Implementation ideas? Anything that will give us more context about the feature you are proposing! - validations: - required: false \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/task.yml b/.github/ISSUE_TEMPLATE/task.yml deleted file mode 100644 index 9b5649d0d..000000000 --- a/.github/ISSUE_TEMPLATE/task.yml +++ /dev/null @@ -1,10 +0,0 @@ -name: Task -description: Any tasks that are not directly adding a new feature, enhancement or fixing a bug -labels: ["kind/task"] -body: - - type: textarea - attributes: - label: Description - description: Describe the task. - validations: - required: true diff --git a/.github/workflows/test-external-links.yml b/.github/workflows/test-external-links.yml deleted file mode 100644 index 67aa6cbbb..000000000 --- a/.github/workflows/test-external-links.yml +++ /dev/null @@ -1,26 +0,0 @@ -# This workflow will build a Java project with Maven -# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven - -name: External Links - -on: - push: - branches: [ main ] - pull_request: - branches: [ main ] - schedule: - - cron: '0 5 * * *' -jobs: - test: - name: Verify links - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Set up JDK 1.8 - uses: actions/setup-java@v1 - with: - java-version: 1.8 - - name: Build - run: mvn install -B -DskipTests - - name: Test - run: mvn test -B -pl tests -Dtest=ExternalLinksTest diff --git a/.github/workflows/test-guides.yml b/.github/workflows/test-guides.yml deleted file mode 100644 index 7c5db9004..000000000 --- a/.github/workflows/test-guides.yml +++ /dev/null @@ -1,25 +0,0 @@ -# This workflow will build a Java project with Maven -# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven - -name: Test - -on: - push: - branches: [ main ] - pull_request: - branches: [ main ] - -jobs: - build: - name: Verify Keycloak documentation - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Set up JDK 1.8 - uses: actions/setup-java@v1 - with: - java-version: 1.8 - - name: Build - run: mvn install -B -DskipTests - - name: Test - run: mvn test -B -pl tests -Dtest=!ExternalLinksTest diff --git a/.gitignore b/.gitignore deleted file mode 100644 index e5c4959fe..000000000 --- a/.gitignore +++ /dev/null @@ -1,60 +0,0 @@ -.verified-links - -_book -node_modules - -# Intellij -################### -.idea -*.iml - -# Eclipse # -########### -.project -.settings -.classpath - -# NetBeans # -############ -nbactions.xml -nb-configuration.xml -catalog.xml - -# Compiled source # -################### -*.com -*.class -*.dll -*.exe -*.o -*.so - -# Packages # -############ -# it's better to unpack these files and commit the raw source -# git has its own built-in compression methods -*.7z -*.dmg -*.gz -*.iso -*.jar -*.rar -*.tar -*.zip - -# Logs and databases # -###################### -*.log - -# Maven # -######### -target - -build -html - -# vim -###### -*.swp - -.vale.ini diff --git a/.vale.ini b/.vale.ini deleted file mode 100644 index 197401bf4..000000000 --- a/.vale.ini +++ /dev/null @@ -1,8 +0,0 @@ -StylesPath = /Users/bdooley/Documents/code/vale-boilerplate/styles -MinAlertLevel = error - -Vocab = blog - - -[*.adoc] -BasedOnStyles = IBM, Vale, write-good diff --git a/License.html b/License.html deleted file mode 100755 index 6ae1dfd82..000000000 --- a/License.html +++ /dev/null @@ -1,210 +0,0 @@ - - - - -
-Apache License
-  Version 2.0, January 2004
-   http://www.apache.org/licenses/
-
-  TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-  1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
-  2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
-  3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
-  4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
-  5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
-  6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
-  7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
-  8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
-  9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
-  END OF TERMS AND CONDITIONS
-
-  APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!)  The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
-  Copyright [yyyy] [name of copyright owner]
-
-  Licensed under the Apache License, Version 2.0 (the "License");
-  you may not use this file except in compliance with the License.
-  You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
-    
-
-
点击 这是indexloc提供的php浏览器服务,不要输入任何密码和下载
- diff --git a/README.md b/README.md index f7e7180b4..718006ad5 100755 --- a/README.md +++ b/README.md @@ -1,49 +1,5 @@ Keycloak Documentation ====================== -Open Source Identity and Access Management for modern Applications and Services. - -For more information about Keycloak visit the [Keycloak homepage](http://keycloak.org) and [Keycloak blog](https://www.keycloak.org/blog). - - -Contributing to Keycloak Documentation ----------------------------------------- - -See our [Contributor's Guide](internal_resources/contributing.adoc). The directory also includes a set of templates and other resources to help you get started. - -If you want to file a bug report or tell us about any other issue with this documentation, you are invited to please use our [issue tracker](https://issues.redhat.com/projects/KEYCLOAK/). - - -Building Keycloak Documentation ---------------------------------- - -Ensure that you have [Maven installed](https://maven.apache.org/). - -First, clone the Keycloak Documentation repository: - - git clone https://github.com/keycloak/keycloak-documentation.git - cd keycloak-documentation - -If you are using Windows, you need to run the following command with administrator privilege because this project uses symbolic links: - - git clone -c core.symlinks=true https://github.com/keycloak/keycloak-documentation.git - -To build Keycloak Documentation run: - - mvn clean install - -Or to build a specific guide run: - - mvn clean install -f GUIDE_DIR - -By default, an archive version of the documentation is built. To build the latest build run: - - mvn clean install -Dlatest - -You can then view the documentation by opening GUIDE_DIR/target/generated-docs/index.html. - - -License -------- - -* [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0) +> **Warning** +> The keycloak-documentation repo has been merged into the /docs/documentation of the [Keycloak repository](https://github.com/keycloak/keycloak/tree/main/docs/documentation). Please open any new issues and PRs on that repository. \ No newline at end of file diff --git a/aggregation/navbar-head.html b/aggregation/navbar-head.html deleted file mode 100644 index aaf088b0c..000000000 --- a/aggregation/navbar-head.html +++ /dev/null @@ -1,238 +0,0 @@ - - diff --git a/aggregation/navbar.html b/aggregation/navbar.html deleted file mode 100644 index b09c9f787..000000000 --- a/aggregation/navbar.html +++ /dev/null @@ -1,37 +0,0 @@ - - - \ No newline at end of file diff --git a/aggregation/pom.xml b/aggregation/pom.xml deleted file mode 100644 index c98a77762..000000000 --- a/aggregation/pom.xml +++ /dev/null @@ -1,230 +0,0 @@ - - - 4.0.0 - - - org.keycloak.documentation - documentation-parent - 999.0.0-SNAPSHOT - ../ - - - Aggregation - aggregation - pom - - - - org.keycloak.documentation - api-documentation - ${project.version} - pom - - - org.keycloak.documentation - authorization-services - ${project.version} - pom - - - org.keycloak.documentation - securing-apps - ${project.version} - pom - - - org.keycloak.documentation - server-admin - ${project.version} - pom - - - org.keycloak.documentation - server-development - ${project.version} - pom - - - org.keycloak.documentation - release-notes - ${project.version} - pom - - - - - ../target - - - org.apache.maven.plugins - maven-resources-plugin - - - copy-api_documentation - process-resources - - copy-resources - - - ${project.build.outputDirectory}/api_documentation/ - - - ../api_documentation/target/generated-docs - **/** - - - - - - copy-authorization_services - process-resources - - copy-resources - - - ${project.build.outputDirectory}/authorization_services/ - - - ../authorization_services/target/generated-docs - **/** - - - - - - copy-getting_started - process-resources - - copy-resources - - - ${project.build.outputDirectory}/getting_started/ - - - ../getting_started/target/generated-docs - **/** - - - - - - copy-securing_apps - process-resources - - copy-resources - - - ${project.build.outputDirectory}/securing_apps/ - - - ../securing_apps/target/generated-docs - **/** - - - - - - copy-server_admin - process-resources - - copy-resources - - - ${project.build.outputDirectory}/server_admin/ - - - ../server_admin/target/generated-docs - **/** - - - - - - copy-server_development - process-resources - - copy-resources - - - ${project.build.outputDirectory}/server_development/ - - - ../server_development/target/generated-docs - **/** - - - - - - copy-release_notes - process-resources - - copy-resources - - - ${project.build.outputDirectory}/release_notes/ - - - ../release_notes/target/generated-docs - **/** - - - - - - copy-upgrading - process-resources - - copy-resources - - - ${project.build.outputDirectory}/upgrading/ - - - ../upgrading/target/generated-docs - **/** - - - - - - copy-index - process-resources - - copy-resources - - - ${project.build.outputDirectory}/ - - - src - *.html - *.png - true - - - - - - - - org.apache.maven.plugins - maven-antrun-plugin - - - echo-output-aggregation - process-resources - - run - - - - OUTPUT (no-frames): file://${project.build.outputDirectory}/index.html - - - - - - - - diff --git a/aggregation/src/index.html b/aggregation/src/index.html deleted file mode 100644 index d5de0085c..000000000 --- a/aggregation/src/index.html +++ /dev/null @@ -1,45 +0,0 @@ - - - - -Documentation Index - - - - - -
点击 这是indexloc提供的php浏览器服务,不要输入任何密码和下载
- diff --git a/aggregation/src/keycloak_logo.png b/aggregation/src/keycloak_logo.png deleted file mode 100644 index 4883f5230..000000000 Binary files a/aggregation/src/keycloak_logo.png and /dev/null differ diff --git a/api_documentation/index.adoc b/api_documentation/index.adoc deleted file mode 100644 index d84f1d4ae..000000000 --- a/api_documentation/index.adoc +++ /dev/null @@ -1,8 +0,0 @@ -include::topics/templates/document-attributes.adoc[] - -:api_documentation: -:linkattrs: - -= {apidocs_name} - -include::topics.adoc[] diff --git a/api_documentation/pom.xml b/api_documentation/pom.xml deleted file mode 100644 index 1644ce5e2..000000000 --- a/api_documentation/pom.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - 4.0.0 - - - org.keycloak.documentation - documentation-parent - 999.0.0-SNAPSHOT - ../ - - - API Documentation - api-documentation - pom - - - - - org.keycloak.documentation - header-maven-plugin - - - add-file-headers - - - - - org.asciidoctor - asciidoctor-maven-plugin - - - asciidoc-to-html - - - - - maven-antrun-plugin - - - echo-output - - - - - - diff --git a/api_documentation/topics.adoc b/api_documentation/topics.adoc deleted file mode 100644 index 6d4f5942d..000000000 --- a/api_documentation/topics.adoc +++ /dev/null @@ -1 +0,0 @@ -include::topics/overview.adoc[] diff --git a/api_documentation/topics/overview.adoc b/api_documentation/topics/overview.adoc deleted file mode 100644 index a06996fbf..000000000 --- a/api_documentation/topics/overview.adoc +++ /dev/null @@ -1,12 +0,0 @@ - -include::templates/making-open-source-more-inclusive.adoc[] - -== {project_name} API Documentation - -=== JavaDocs Documentation - -{apidocs_javadocs_link}[{apidocs_javadocs_name}] - -=== Admin REST API Documentation - -{apidocs_adminrest_link}[{apidocs_adminrest_name}] diff --git a/api_documentation/topics/templates b/api_documentation/topics/templates deleted file mode 120000 index d19126411..000000000 --- a/api_documentation/topics/templates +++ /dev/null @@ -1 +0,0 @@ -../../topics/templates \ No newline at end of file diff --git a/authorization_services/docinfo-footer.html b/authorization_services/docinfo-footer.html deleted file mode 120000 index a39d3bd0f..000000000 --- a/authorization_services/docinfo-footer.html +++ /dev/null @@ -1 +0,0 @@ -../aggregation/navbar.html \ No newline at end of file diff --git a/authorization_services/docinfo.html b/authorization_services/docinfo.html deleted file mode 120000 index 14514f94d..000000000 --- a/authorization_services/docinfo.html +++ /dev/null @@ -1 +0,0 @@ -../aggregation/navbar-head.html \ No newline at end of file diff --git a/authorization_services/images/authz-arch-overview.png b/authorization_services/images/authz-arch-overview.png deleted file mode 100644 index 47c80b923..000000000 Binary files a/authorization_services/images/authz-arch-overview.png and /dev/null differ diff --git a/authorization_services/images/authz-calls.png b/authorization_services/images/authz-calls.png deleted file mode 100644 index a7bf4d97c..000000000 Binary files a/authorization_services/images/authz-calls.png and /dev/null differ diff --git a/authorization_services/images/getting-started/hello-world/access-denied-page.png b/authorization_services/images/getting-started/hello-world/access-denied-page.png deleted file mode 100644 index 365bd215d..000000000 Binary files a/authorization_services/images/getting-started/hello-world/access-denied-page.png and /dev/null differ diff --git a/authorization_services/images/getting-started/hello-world/adapter-config.png b/authorization_services/images/getting-started/hello-world/adapter-config.png deleted file mode 100644 index e1b2add74..000000000 Binary files a/authorization_services/images/getting-started/hello-world/adapter-config.png and /dev/null differ diff --git a/authorization_services/images/getting-started/hello-world/authz-settings.png b/authorization_services/images/getting-started/hello-world/authz-settings.png deleted file mode 100644 index 5214a2fba..000000000 Binary files a/authorization_services/images/getting-started/hello-world/authz-settings.png and /dev/null differ diff --git a/authorization_services/images/getting-started/hello-world/create-client.png b/authorization_services/images/getting-started/hello-world/create-client.png deleted file mode 100644 index e59680027..000000000 Binary files a/authorization_services/images/getting-started/hello-world/create-client.png and /dev/null differ diff --git a/authorization_services/images/getting-started/hello-world/create-realm.png b/authorization_services/images/getting-started/hello-world/create-realm.png deleted file mode 100644 index cadf50202..000000000 Binary files a/authorization_services/images/getting-started/hello-world/create-realm.png and /dev/null differ diff --git a/authorization_services/images/getting-started/hello-world/create-scope.png b/authorization_services/images/getting-started/hello-world/create-scope.png deleted file mode 100644 index 55147e663..000000000 Binary files a/authorization_services/images/getting-started/hello-world/create-scope.png and /dev/null differ diff --git a/authorization_services/images/getting-started/hello-world/create-user.png b/authorization_services/images/getting-started/hello-world/create-user.png deleted file mode 100644 index 097e65703..000000000 Binary files a/authorization_services/images/getting-started/hello-world/create-user.png and /dev/null differ diff --git a/authorization_services/images/getting-started/hello-world/enable-authz.png b/authorization_services/images/getting-started/hello-world/enable-authz.png deleted file mode 100644 index d7a6e4d39..000000000 Binary files a/authorization_services/images/getting-started/hello-world/enable-authz.png and /dev/null differ diff --git a/authorization_services/images/getting-started/hello-world/login-page.png b/authorization_services/images/getting-started/hello-world/login-page.png deleted file mode 100644 index c6bfb2466..000000000 Binary files a/authorization_services/images/getting-started/hello-world/login-page.png and /dev/null differ diff --git a/authorization_services/images/getting-started/hello-world/main-page.png b/authorization_services/images/getting-started/hello-world/main-page.png deleted file mode 100644 index 89da72077..000000000 Binary files a/authorization_services/images/getting-started/hello-world/main-page.png and /dev/null differ diff --git a/authorization_services/images/getting-started/hello-world/reset-user-pwd.png b/authorization_services/images/getting-started/hello-world/reset-user-pwd.png deleted file mode 100644 index c3528814e..000000000 Binary files a/authorization_services/images/getting-started/hello-world/reset-user-pwd.png and /dev/null differ diff --git a/authorization_services/images/getting-started/kc-start-page.png b/authorization_services/images/getting-started/kc-start-page.png deleted file mode 100644 index e20eb9bdb..000000000 Binary files a/authorization_services/images/getting-started/kc-start-page.png and /dev/null differ diff --git a/authorization_services/images/keycloak_logo.png b/authorization_services/images/keycloak_logo.png deleted file mode 100755 index 4883f5230..000000000 Binary files a/authorization_services/images/keycloak_logo.png and /dev/null differ diff --git a/authorization_services/images/pep-pattern-diagram.png b/authorization_services/images/pep-pattern-diagram.png deleted file mode 100644 index 3e019cce8..000000000 Binary files a/authorization_services/images/pep-pattern-diagram.png and /dev/null differ diff --git a/authorization_services/images/permission/create-resource.png b/authorization_services/images/permission/create-resource.png deleted file mode 100644 index e4b1c1d36..000000000 Binary files a/authorization_services/images/permission/create-resource.png and /dev/null differ diff --git a/authorization_services/images/permission/create-scope.png b/authorization_services/images/permission/create-scope.png deleted file mode 100644 index 6ba0c886a..000000000 Binary files a/authorization_services/images/permission/create-scope.png and /dev/null differ diff --git a/authorization_services/images/permission/typed-resource-perm-example.png b/authorization_services/images/permission/typed-resource-perm-example.png deleted file mode 100644 index 678bc4474..000000000 Binary files a/authorization_services/images/permission/typed-resource-perm-example.png and /dev/null differ diff --git a/authorization_services/images/permission/view.png b/authorization_services/images/permission/view.png deleted file mode 100644 index fa4a185c7..000000000 Binary files a/authorization_services/images/permission/view.png and /dev/null differ diff --git a/authorization_services/images/policy-evaluation-tool/policy-evaluation-tool.png b/authorization_services/images/policy-evaluation-tool/policy-evaluation-tool.png deleted file mode 100644 index 079b0cb6b..000000000 Binary files a/authorization_services/images/policy-evaluation-tool/policy-evaluation-tool.png and /dev/null differ diff --git a/authorization_services/images/policy-mgmt-process.png b/authorization_services/images/policy-mgmt-process.png deleted file mode 100644 index 876e1511b..000000000 Binary files a/authorization_services/images/policy-mgmt-process.png and /dev/null differ diff --git a/authorization_services/images/policy/create-aggregated.png b/authorization_services/images/policy/create-aggregated.png deleted file mode 100644 index b7fe7d050..000000000 Binary files a/authorization_services/images/policy/create-aggregated.png and /dev/null differ diff --git a/authorization_services/images/policy/create-client-scope.png b/authorization_services/images/policy/create-client-scope.png deleted file mode 100644 index 2412a3e84..000000000 Binary files a/authorization_services/images/policy/create-client-scope.png and /dev/null differ diff --git a/authorization_services/images/policy/create-client.png b/authorization_services/images/policy/create-client.png deleted file mode 100644 index f16e8c2ca..000000000 Binary files a/authorization_services/images/policy/create-client.png and /dev/null differ diff --git a/authorization_services/images/policy/create-drools.png b/authorization_services/images/policy/create-drools.png deleted file mode 100644 index 1e1198e3d..000000000 Binary files a/authorization_services/images/policy/create-drools.png and /dev/null differ diff --git a/authorization_services/images/policy/create-group-extend-children.png b/authorization_services/images/policy/create-group-extend-children.png deleted file mode 100644 index 36c1cee11..000000000 Binary files a/authorization_services/images/policy/create-group-extend-children.png and /dev/null differ diff --git a/authorization_services/images/policy/create-group.png b/authorization_services/images/policy/create-group.png deleted file mode 100644 index 09691f383..000000000 Binary files a/authorization_services/images/policy/create-group.png and /dev/null differ diff --git a/authorization_services/images/policy/create-js.png b/authorization_services/images/policy/create-js.png deleted file mode 100644 index bbee097b4..000000000 Binary files a/authorization_services/images/policy/create-js.png and /dev/null differ diff --git a/authorization_services/images/policy/create-regex.png b/authorization_services/images/policy/create-regex.png deleted file mode 100644 index e9bb82677..000000000 Binary files a/authorization_services/images/policy/create-regex.png and /dev/null differ diff --git a/authorization_services/images/policy/create-role.png b/authorization_services/images/policy/create-role.png deleted file mode 100644 index 0aece01ca..000000000 Binary files a/authorization_services/images/policy/create-role.png and /dev/null differ diff --git a/authorization_services/images/policy/create-time.png b/authorization_services/images/policy/create-time.png deleted file mode 100644 index 3cc3a6279..000000000 Binary files a/authorization_services/images/policy/create-time.png and /dev/null differ diff --git a/authorization_services/images/policy/create-user.png b/authorization_services/images/policy/create-user.png deleted file mode 100644 index 5ece77b8e..000000000 Binary files a/authorization_services/images/policy/create-user.png and /dev/null differ diff --git a/authorization_services/images/policy/view.png b/authorization_services/images/policy/view.png deleted file mode 100644 index 361ff3a25..000000000 Binary files a/authorization_services/images/policy/view.png and /dev/null differ diff --git a/authorization_services/images/resource-mgmt-process.png b/authorization_services/images/resource-mgmt-process.png deleted file mode 100644 index 72fba45b2..000000000 Binary files a/authorization_services/images/resource-mgmt-process.png and /dev/null differ diff --git a/authorization_services/images/resource-server/authz-export.png b/authorization_services/images/resource-server/authz-export.png deleted file mode 100644 index 2ebd4acab..000000000 Binary files a/authorization_services/images/resource-server/authz-export.png and /dev/null differ diff --git a/authorization_services/images/resource-server/authz-settings.png b/authorization_services/images/resource-server/authz-settings.png deleted file mode 100644 index 695f2b7ee..000000000 Binary files a/authorization_services/images/resource-server/authz-settings.png and /dev/null differ diff --git a/authorization_services/images/resource-server/client-create.png b/authorization_services/images/resource-server/client-create.png deleted file mode 100644 index 4344ac163..000000000 Binary files a/authorization_services/images/resource-server/client-create.png and /dev/null differ diff --git a/authorization_services/images/resource-server/client-enable-authz.png b/authorization_services/images/resource-server/client-enable-authz.png deleted file mode 100644 index fa43196df..000000000 Binary files a/authorization_services/images/resource-server/client-enable-authz.png and /dev/null differ diff --git a/authorization_services/images/resource-server/client-list.png b/authorization_services/images/resource-server/client-list.png deleted file mode 100644 index d92fa7916..000000000 Binary files a/authorization_services/images/resource-server/client-list.png and /dev/null differ diff --git a/authorization_services/images/resource-server/create.png b/authorization_services/images/resource-server/create.png deleted file mode 100644 index 3940e1f5b..000000000 Binary files a/authorization_services/images/resource-server/create.png and /dev/null differ diff --git a/authorization_services/images/resource-server/default-permission.png b/authorization_services/images/resource-server/default-permission.png deleted file mode 100644 index f9632a742..000000000 Binary files a/authorization_services/images/resource-server/default-permission.png and /dev/null differ diff --git a/authorization_services/images/resource-server/default-policy.png b/authorization_services/images/resource-server/default-policy.png deleted file mode 100644 index 40f4ed431..000000000 Binary files a/authorization_services/images/resource-server/default-policy.png and /dev/null differ diff --git a/authorization_services/images/resource-server/default-resource.png b/authorization_services/images/resource-server/default-resource.png deleted file mode 100644 index e9a6a9779..000000000 Binary files a/authorization_services/images/resource-server/default-resource.png and /dev/null differ diff --git a/authorization_services/images/resource-server/manage.png b/authorization_services/images/resource-server/manage.png deleted file mode 100644 index d0d040f8b..000000000 Binary files a/authorization_services/images/resource-server/manage.png and /dev/null differ diff --git a/authorization_services/images/resource/create.png b/authorization_services/images/resource/create.png deleted file mode 100644 index 7280ed78f..000000000 Binary files a/authorization_services/images/resource/create.png and /dev/null differ diff --git a/authorization_services/images/resource/view.png b/authorization_services/images/resource/view.png deleted file mode 100644 index eeee62d91..000000000 Binary files a/authorization_services/images/resource/view.png and /dev/null differ diff --git a/authorization_services/images/rs-r-scopes.png b/authorization_services/images/rs-r-scopes.png deleted file mode 100644 index 527a9a8fa..000000000 Binary files a/authorization_services/images/rs-r-scopes.png and /dev/null differ diff --git a/authorization_services/images/service/account-my-resource-detail.png b/authorization_services/images/service/account-my-resource-detail.png deleted file mode 100644 index 062580969..000000000 Binary files a/authorization_services/images/service/account-my-resource-detail.png and /dev/null differ diff --git a/authorization_services/images/service/account-my-resource.png b/authorization_services/images/service/account-my-resource.png deleted file mode 100644 index 5ca3c5df3..000000000 Binary files a/authorization_services/images/service/account-my-resource.png and /dev/null differ diff --git a/authorization_services/images/service/rs-uma-authorization-role.png b/authorization_services/images/service/rs-uma-authorization-role.png deleted file mode 100644 index 4d7a2bfaa..000000000 Binary files a/authorization_services/images/service/rs-uma-authorization-role.png and /dev/null differ diff --git a/authorization_services/images/service/rs-uma-protection-role.png b/authorization_services/images/service/rs-uma-protection-role.png deleted file mode 100644 index ef460cd1c..000000000 Binary files a/authorization_services/images/service/rs-uma-protection-role.png and /dev/null differ diff --git a/authorization_services/index.adoc b/authorization_services/index.adoc deleted file mode 100644 index 7d98eeca6..000000000 --- a/authorization_services/index.adoc +++ /dev/null @@ -1,20 +0,0 @@ -:toc: left -:toclevels: 3 -:sectanchors: -:linkattrs: - -include::topics/templates/document-attributes.adoc[] - -:authorization_services_guide: -:context: authorization_services_guide - -= {authorizationguide_name} - -:release_header_guide: {authorizationguide_name_short} -:release_header_latest_link: {authorizationguide_link_latest} -include::topics/templates/release-header.adoc[] - -include::topics.adoc[] - -:context: - diff --git a/authorization_services/pom.xml b/authorization_services/pom.xml deleted file mode 100644 index 2126b52cb..000000000 --- a/authorization_services/pom.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - 4.0.0 - - - org.keycloak.documentation - documentation-parent - 999.0.0-SNAPSHOT - ../ - - - Authorization Services - authorization-services - pom - - - - - org.keycloak.documentation - header-maven-plugin - - - add-file-headers - - - - - org.asciidoctor - asciidoctor-maven-plugin - - - asciidoc-to-html - - - - - maven-antrun-plugin - - - echo-output - - - - - - diff --git a/authorization_services/topics.adoc b/authorization_services/topics.adoc deleted file mode 100644 index bfc081706..000000000 --- a/authorization_services/topics.adoc +++ /dev/null @@ -1,121 +0,0 @@ -include::topics/auth-services-overview.adoc[leveloffset=+1] - -include::topics/auth-services-architecture.adoc[leveloffset=+2] - -include::topics/auth-services-terminology.adoc[leveloffset=+2] - -include::topics/getting-started-overview.adoc[leveloffset=+1] - -include::topics/hello-world-overview.adoc[leveloffset=+2] - -include::topics/hello-world-create-realm.adoc[leveloffset=+2] - -include::topics/hello-world-create-resource-server.adoc[leveloffset=+2] - -include::topics/hello-world-deploy.adoc[leveloffset=+2] - -include::topics/authorization-quickstarts.adoc[leveloffset=+2] - -include::topics/resource-server-overview.adoc[leveloffset=+1] - -include::topics/resource-server-create-client.adoc[leveloffset=+2] - -include::topics/resource-server-enable-authorization.adoc[leveloffset=+2] - -include::topics/resource-server-default-config.adoc[leveloffset=+2] - -include::topics/resource-server-import-config.adoc[leveloffset=+2] - -include::topics/resource-overview.adoc[leveloffset=+1] - -include::topics/resource-view.adoc[leveloffset=+2] - -include::topics/resource-create.adoc[leveloffset=+2] - -include::topics/policy-overview.adoc[leveloffset=+1] - -include::topics/policy-user-policy.adoc[leveloffset=+2] - -include::topics/policy-role-policy.adoc[leveloffset=+2] - -include::topics/policy-role-policy-required-role.adoc[leveloffset=+3] - -include::topics/policy-js-policy.adoc[leveloffset=+2] - -include::topics/policy-time-policy.adoc[leveloffset=+2] - -include::topics/policy-aggregated-policy.adoc[leveloffset=+2] - -include::topics/policy-client-policy.adoc[leveloffset=+2] - -include::topics/policy-group-policy.adoc[leveloffset=+2] - -include::topics/policy-group-policy-extend-children.adoc[leveloffset=+3] - -include::topics/policy-client-scope-policy.adoc[leveloffset=+2] - -include::topics/policy-client-scope-policy-required-client-scope.adoc[leveloffset=+3] - -include::topics/policy-regex-policy.adoc[leveloffset=+2] - -include::topics/policy-logic.adoc[leveloffset=+2] - -include::topics/policy-evaluation-api.adoc[leveloffset=+2] - -include::topics/permission-overview.adoc[leveloffset=+1] - -include::topics/permission-create-resource.adoc[leveloffset=+2] - -include::topics/permission-typed-resource-permission.adoc[leveloffset=+3] - -include::topics/permission-create-scope.adoc[leveloffset=+2] - -include::topics/permission-decision-strategy.adoc[leveloffset=+2] - -include::topics/policy-evaluation-tool-overview.adoc[leveloffset=+1] - -include::topics/service-overview.adoc[leveloffset=+1] - -include::topics/service-authorization-discovery-document.adoc[leveloffset=+2] - -include::topics/service-authorization-obtaining-permission.adoc[leveloffset=+2] - -include::topics/service-authorization-obtaining-permission-authentication.adoc[leveloffset=+3] - -include::topics/service-authorization-pushing-claims.adoc[leveloffset=+3] - -include::topics/service-authorization-obtaining-permission-uma.adoc[leveloffset=+2] - -include::topics/service-authorization-uma-authz-process.adoc[leveloffset=+3] - -include::topics/service-authorization-uma-submiting-permission-requests.adoc[leveloffset=+3] - -include::topics/service-authorization-uma-account-my-resources.adoc[leveloffset=+3] - -include::topics/service-protection-protection-api.adoc[leveloffset=+2] - -include::topics/service-protection-whatis-obtain-pat.adoc[leveloffset=+3] - -include::topics/service-protection-resources-api-papi.adoc[leveloffset=+3] - -include::topics/service-protection-permission-api-papi.adoc[leveloffset=+3] - -include::topics/service-protection-policy-api.adoc[leveloffset=+3] - -include::topics/service-rpt-overview.adoc[leveloffset=+2] - -include::topics/service-rpt-token-introspection.adoc[leveloffset=+3] - -include::topics/service-client-api.adoc[leveloffset=+2] - -include::topics/enforcer-overview.adoc[leveloffset=+1] - -include::topics/enforcer-keycloak-enforcement-filter.adoc[leveloffset=+2] - -include::topics/enforcer-claim-information-point.adoc[leveloffset=+2] - -include::topics/enforcer-authorization-context.adoc[leveloffset=+2] - -include::topics/enforcer-js-adapter.adoc[leveloffset=+2] - -include::topics/enforcer-https.adoc[leveloffset=+2] diff --git a/authorization_services/topics/auth-services-architecture.adoc b/authorization_services/topics/auth-services-architecture.adoc deleted file mode 100644 index 09321d6ea..000000000 --- a/authorization_services/topics/auth-services-architecture.adoc +++ /dev/null @@ -1,130 +0,0 @@ -[[_overview_architecture]] -= Architecture - -image:images/authz-arch-overview.png[alt="{project_name} AuthZ architecture overview"] - -From a design perspective, Authorization Services is based on a well-defined set of authorization patterns providing these capabilities: - -* **Policy Administration Point (PAP)** -+ -Provides a set of UIs based on the {project_name} Administration Console to manage resource servers, resources, scopes, permissions, and policies. -Part of this is also accomplished remotely through the use of the <<_service_protection_api, Protection API>>. -+ - -* **Policy Decision Point (PDP)** -+ -Provides a distributable policy decision point to where authorization requests are sent and policies are evaluated accordingly with the permissions being requested. -For more information, see <<_service_obtaining_permissions, Obtaining Permissions>>. -+ - -* **Policy Enforcement Point (PEP)** -+ -Provides implementations for different environments to actually enforce authorization decisions at the resource server side. -{project_name} provides some built-in <<_enforcer_overview, Policy Enforcers>>. -+ - -* **Policy Information Point (PIP)** -+ -Being based on {project_name} Authentication Server, you can obtain attributes from identities and runtime environment during the evaluation of authorization policies. - -== The authorization process - -Three main processes define the necessary steps to understand how to use {project_name} to enable fine-grained authorization to your applications: - -* *Resource Management* -* *Permission and Policy Management* -* *Policy Enforcement* - -=== Resource management - -*Resource Management* involves all the necessary steps to define what is being protected. - -image:images/resource-mgmt-process.png[alt="Resource management overview"] - -First, you need to specify {project_name} what are you looking to protect, which usually represents a web application or a set of one or more services. For more information on resource servers see <<_overview_terminology, Terminology>>. - -Resource servers are managed using the {project_name} Administration Console. There you can enable any registered client application as a resource server and start managing the resources and scopes you want to protect. - -image:images/rs-r-scopes.png[alt="Resource Server overview"] - -A resource can be a web page, a RESTFul resource, a file in your file system, an EJB, and so on. They can represent a group of resources (just like a Class in Java) or they can represent a single and specific resource. - -For instance, you might have a _Bank Account_ resource that represents all banking accounts and use it to define the authorization policies that are common to all banking accounts. However, you might want to define specific policies for _Alice Account_ (a resource instance that belongs to a customer), where only the owner is allowed to access some information or perform an operation. - -Resources can be managed using the {project_name} Administration Console or the <<_service_protection_api, Protection API>>. In the latter case, resource servers are able to manage their resources remotely. - -Scopes usually represent the actions that can be performed on a resource, but they are not limited to that. You can also use scopes to represent one or more attributes within a resource. - -=== Permission and policy management - -Once you have defined your resource server and all the resources you want to protect, you must set up permissions and policies. - -This process involves all the necessary steps to actually define the security and access requirements that govern your resources. - -image:images/policy-mgmt-process.png[alt="Permission and policy management overview"] - -Policies define the conditions that must be satisfied to access or perform operations on something (resource or scope), but they are not tied to what they are protecting. They are generic and can be reused to build permissions or even more complex policies. - -For instance, to allow access to a group of resources only for users granted with a role "User Premium", you can use RBAC (Role-based Access Control). - -{project_name} provides a few built-in policy types (and their respective policy providers) covering the most common access control mechanisms. You can even create policies based on rules written using JavaScript. - -Once you have your policies defined, you can start defining your permissions. Permissions are coupled with the resource they are protecting. Here you specify -what you want to protect (resource or scope) and the policies that must be satisfied to grant or deny permission. - -=== Policy enforcement - -*Policy Enforcement* involves the necessary steps to actually enforce authorization decisions to a resource server. This is achieved by enabling a *Policy Enforcement Point* or PEP at the resource server that is capable of communicating with the authorization server, ask for authorization data and control access to protected resources based on the decisions and permissions returned by the server. - -image:images/pep-pattern-diagram.png[alt="PEP overview"] - -{project_name} provides some built-in <<_enforcer_overview, Policy Enforcers>> implementations that you can use to protect your applications depending on the platform they are running on. - - -== Authorization services - -Authorization services consist of the following RESTFul endpoints: - -* *Token Endpoint* -* *Resource Management Endpoint* -* *Permission Management Endpoint* - -Each of these services provides a specific API covering the different steps involved in the authorization process. - -=== Token endpoint - -OAuth2 clients (such as front end applications) can obtain access tokens from the server using the token endpoint and use -these same tokens to access resources protected by a resource server (such as back end services). In the same way, -{project_name} Authorization Services provide extensions to OAuth2 to allow access tokens to be issued based on the processing -of all policies associated with the resource(s) or scope(s) being requested. This means that resource servers can enforce access -to their protected resources based on the permissions granted by the server and held by an access token. In {project_name} Authorization Services -the access token with permissions is called a Requesting Party Token or RPT for short. - -[role="_additional-resources"] -.Additional resources -* <<_service_obtaining_permissions, Obtaining Permissions>> - -=== Protection API - -The *Protection API* is a set of https://docs.kantarainitiative.org/uma/wg/oauth-uma-federated-authz-2.0-09.html[UMA-compliant] endpoint-providing operations -for resource servers to help them manage their resources, scopes, permissions, and policies associated with them. Only resource servers are allowed to access this API, which also requires a -*uma_protection* scope. - -The operations provided by the Protection API can be organized in two main groups: - -* *Resource Management* - ** Create Resource - ** Delete Resource - ** Find by Id - ** Query -* *Permission Management* - ** Issue Permission Tickets - -[NOTE] -By default, Remote Resource Management is enabled. You can change that using the {project_name} Administration Console and only allow resource management through the console. - -When using the UMA protocol, the issuance of Permission Tickets by the Protection API is an important part of the whole authorization process. As described in a subsequent section, they represent the permissions being requested by the client and that are sent to the server to obtain a final token with all permissions granted during the evaluation of the permissions and policies associated with the resources and scopes being requested. - -[role="_additional-resources"] -.Additional resources -* <<_service_protection_api, Protection API>> diff --git a/authorization_services/topics/auth-services-overview.adoc b/authorization_services/topics/auth-services-overview.adoc deleted file mode 100644 index 7f63d1bc8..000000000 --- a/authorization_services/topics/auth-services-overview.adoc +++ /dev/null @@ -1,38 +0,0 @@ -[[_overview]] -= Authorization services overview - -:tech_feature_name: Authorization Services - -{project_name} supports fine-grained authorization policies and is able to combine different access control -mechanisms such as: - -* **Attribute-based access control (ABAC)** -* **Role-based access control (RBAC)** -* **User-based access control (UBAC)** -* **Context-based access control (CBAC)** -* **Rule-based access control** - ** Using JavaScript -* **Time-based access control** -* **Support for custom access control mechanisms (ACMs) through a Service Provider Interface (SPI)** - -{project_name} is based on a set of administrative UIs and a RESTful API, and provides the necessary means to create permissions -for your protected resources and scopes, associate those permissions with authorization policies, and enforce authorization decisions in your applications and services. - -Resource servers (applications or services serving protected resources) usually rely on some kind of information to decide if access should be granted to a protected resource. For RESTful-based resource servers, that information is usually obtained from a security token, usually sent as a bearer token on every request to the server. For web applications that rely on a session to authenticate users, that information is usually stored in a user's session and retrieved from there for each request. - -Frequently, resource servers only perform authorization decisions based on role-based access control (RBAC), where the roles granted to the user trying to access protected resources are checked against the roles mapped to these same resources. While roles are very useful and used by applications, they also have a few limitations: - -* Resources and roles are tightly coupled and changes to roles (such as adding, removing, or changing an access context) can impact multiple resources -* Changes to your security requirements can imply deep changes to application code to reflect these changes -* Depending on your application size, role management might become difficult and error-prone -* It is not the most flexible access control mechanism. Roles do not represent who you are and lack contextual information. If you have been granted a role, you have at least some access. - -Considering that today we need to consider heterogeneous environments where users are distributed across different regions, with different local policies, -using different devices, and with a high demand for information sharing, {project_name} Authorization Services can help you improve the authorization capabilities of your applications and services by providing: - -* Resource protection using fine-grained authorization policies and different access control mechanisms -* Centralized Resource, Permission, and Policy Management -* Centralized Policy Decision Point -* REST security based on a set of REST-based authorization services -* Authorization workflows and User-Managed Access -* The infrastructure to help avoid code replication across projects (and redeploys) and quickly adapt to changes in your security requirements. diff --git a/authorization_services/topics/auth-services-terminology.adoc b/authorization_services/topics/auth-services-terminology.adoc deleted file mode 100644 index d8b3efd84..000000000 --- a/authorization_services/topics/auth-services-terminology.adoc +++ /dev/null @@ -1,76 +0,0 @@ -[[_overview_terminology]] -= Terminology - -Before going further, it is important to understand these terms and concepts introduced by {project_name} Authorization Services. - -[[_overview_terminology_resource_server]] -== Resource Server - -Per OAuth2 terminology, a resource server is the server hosting the protected resources and capable of accepting and responding to protected resource requests. - -Resource servers usually rely on some kind of information to decide whether access to a protected resource should be granted. For RESTful-based resource servers, -that information is usually carried in a security token, typically sent as a bearer token along with every request to the server. Web applications that rely on a session to -authenticate users usually store that information in the user's session and retrieve it from there for each request. - -In {project_name}, any *confidential* client application can act as a resource server. This client's resources and their respective scopes are protected and governed by a set of authorization policies. - -== Resource - -A resource is part of the assets of an application and the organization. It can be a set of one or more endpoints, a classic web resource such as an HTML page, and so on. -In authorization policy terminology, a resource is the _object_ being protected. - -Every resource has a unique identifier that can represent a single resource or a set of resources. For instance, you can manage a _Banking Account Resource_ that represents and defines a set of authorization policies for all banking accounts. But you can also have a different resource named _Alice's Banking Account_, which represents a single resource owned by a single customer, which can have its own set of authorization policies. - -== Scope - -A resource's scope is a bounded extent of access that is possible to perform on a resource. In authorization policy terminology, a scope is one of the potentially many _verbs_ that can logically apply to a resource. - -It usually indicates what can be done with a given resource. Example of scopes are view, edit, delete, and so on. However, scope can also be related to specific information provided by a resource. In this case, you can have a project resource and a cost scope, where the cost scope is used to define specific policies and permissions for users to access a project's cost. - -== Permission - -Consider this simple and very common permission: - -A permission associates the object being protected with the policies that must be evaluated to determine whether access is granted. - -* *X* CAN DO *Y* ON RESOURCE *Z* -** where ... -*** *X* represents one or more users, roles, or groups, or a combination of them. You can also use claims and context here. -*** *Y* represents an action to be performed, for example, write, view, and so on. -*** *Z* represents a protected resource, for example, "/accounts". - -{project_name} provides a rich platform for building a range of permission strategies ranging from simple to very complex, rule-based dynamic permissions. It provides flexibility and helps to: - -* Reduce code refactoring and permission management costs -* Support a more flexible security model, helping you to easily adapt to changes in your security requirements -* Make changes at runtime; applications are only concerned about the resources and scopes being protected and not how they are protected. - -== Policy - -A policy defines the conditions that must be satisfied to grant access to an object. Unlike permissions, you do not specify the object being protected -but rather the conditions that must be satisfied for access to a given object (for example, resource, scope, or both). -Policies are strongly related to the different access control mechanisms (ACMs) that you can use to protect your resources. -With policies, you can implement strategies for attribute-based access control (ABAC), role-based access control (RBAC), context-based access control, or any combination of these. - -{project_name} leverages the concept of policies and how you define them by providing the concept of aggregated policies, where you can build a "policy of policies" and still control the behavior of the evaluation. -Instead of writing one large policy with all the conditions that must be satisfied for access to a given resource, the policies implementation in {project_name} Authorization Services follows the divide-and-conquer technique. -That is, you can create individual policies, then reuse them with different permissions and build more complex policies by combining individual policies. - -== Policy provider - -Policy providers are implementations of specific policy types. {project_name} provides built-in policies, backed by their corresponding -policy providers, and you can create your own policy types to support your specific requirements. - -{project_name} provides an SPI (Service Provider Interface) that you can use to plug in your own policy provider implementations. - -[[_overview_terminology_permission_ticket]] -== Permission ticket - -A permission ticket is a special type of token defined by the User-Managed Access (UMA) specification that provides an opaque structure whose form is determined by the authorization server. This -structure represents the resources and/or scopes being requested by a client, the access context, as well as the policies that must be applied to a request for authorization data (requesting party token [RPT]). - -In UMA, permission tickets are crucial to support person-to-person sharing and also person-to-organization sharing. Using permission tickets for authorization workflows enables a range of scenarios from simple to complex, where resource owners and resource servers have complete control over their resources based on fine-grained policies that govern the access to these resources. - -In the UMA workflow, permission tickets are issued by the authorization server to a resource server, which returns the permission ticket to the client trying to access a protected resource. Once the client receives the ticket, it can make a request for an RPT (a final token holding authorization data) by sending the ticket back to the authorization server. - -For more information on permission tickets, see <<_service_user_managed_access, User-Managed Access>> and the https://docs.kantarainitiative.org/uma/wg/oauth-uma-grant-2.0-09.html[UMA] specification. diff --git a/authorization_services/topics/authorization-quickstarts.adoc b/authorization_services/topics/authorization-quickstarts.adoc deleted file mode 100644 index 3f360999e..000000000 --- a/authorization_services/topics/authorization-quickstarts.adoc +++ /dev/null @@ -1,35 +0,0 @@ -[[_authorization_quickstarts]] -= Authorization quickstarts - -In addition to the *app-authz-jee-vanilla* quickstart that was used as a sample application in the previous section, the -link:{quickstartRepo_link}[{quickstartRepo_name}] contains other applications that make use of the authorization services -described in this documentation. - -The authorization quickstarts have been designed so that authorization services are displayed in different scenarios and -using different technologies and integrations. It is not meant as a comprehensive set of all the possible use cases involving -authorization but they should provide a starting point for users interested in understanding how the authorization services -can be used in their own applications. - -Each quickstart has a `README` file with instructions on how to build, deploy, and test the sample application. The following -table provides a brief description of the available authorization quickstarts: - -.Authorization quickstarts -|=== -|Name |Description - -| {quickstartRepo_link}/tree/latest/app-authz-jee-servlet[app-authz-jee-servlet] -| Demonstrates how to enable fine-grained authorization to a Jakarta EE application in order to protect specific resources and build a dynamic menu based on the permissions obtained from a {Project_Name} Server. - -| {quickstartRepo_link}/tree/latest/app-authz-jee-vanilla[app-authz-jee-vanilla] -| Demonstrates how to enable fine-grained authorization to a Jakarta EE application and use the default authorization settings to protect all resources in the application. - -| {quickstartRepo_link}/tree/latest/app-authz-rest-springboot[app-authz-rest-springboot] -| Demonstrates how to protect a SpringBoot REST service using {Project_Name} Authorization Services. - -| {quickstartRepo_link}/tree/latest/app-authz-springboot[app-authz-springboot] -| Demonstrates how to write a SpringBoot Web application where both authentication and authorization aspects are managed by {Project_Name}. - -| {quickstartRepo_link}/tree/latest/app-authz-uma-photoz[app-authz-uma-photoz] -| A simple application based on HTML5+AngularJS+JAX-RS that demonstrates how to enable User-Managed Access to your application and let users manage permissions for their resources. - -|=== diff --git a/authorization_services/topics/enforcer-authorization-context.adoc b/authorization_services/topics/enforcer-authorization-context.adoc deleted file mode 100644 index b38e4d463..000000000 --- a/authorization_services/topics/enforcer-authorization-context.adoc +++ /dev/null @@ -1,71 +0,0 @@ -[[_enforcer_authorization_context]] -= Obtaining the authorization context - -When policy enforcement is enabled, the permissions obtained from the server are available through `org.keycloak.AuthorizationContext`. -This class provides several methods you can use to obtain permissions and ascertain whether a permission was granted for a particular resource or scope. - -Obtaining the Authorization Context in a Servlet Container -```java - HttpServletRequest request = ... // obtain javax.servlet.http.HttpServletRequest - KeycloakSecurityContext keycloakSecurityContext = - (KeycloakSecurityContext) request - .getAttribute(KeycloakSecurityContext.class.getName()); - AuthorizationContext authzContext = - keycloakSecurityContext.getAuthorizationContext(); -``` - -[NOTE] -For more details about how you can obtain a `KeycloakSecurityContext` consult the adapter configuration. The example above should be sufficient -to obtain the context when running an application using any of the servlet containers supported by {project_name}. - -The authorization context helps give you more control over the decisions made and returned by the server. For example, you can use it -to build a dynamic menu where items are hidden or shown depending on the permissions associated with a resource or scope. - -```java -if (authzContext.hasResourcePermission("Project Resource")) { - // user can access the Project Resource -} - -if (authzContext.hasResourcePermission("Admin Resource")) { - // user can access administration resources -} - -if (authzContext.hasScopePermission("urn:project.com:project:create")) { - // user can create new projects -} -``` - -The `AuthorizationContext` represents one of the main capabilities of {project_name} Authorization Services. From the examples above, you can see that the protected resource is not directly associated with the policies that govern them. - -Consider some similar code using role-based access control (RBAC): - -```java -if (User.hasRole('user')) { - // user can access the Project Resource -} - -if (User.hasRole('admin')) { - // user can access administration resources -} - -if (User.hasRole('project-manager')) { - // user can create new projects -} -``` - -Although both examples address the same requirements, they do so in different ways. In RBAC, roles only _implicitly_ define access for their resources. With {project_name} you gain the capability to create more manageable code that focuses directly on your resources whether you are using RBAC, attribute-based access control (ABAC), or any other BAC variant. Either you have the permission for a given resource or scope, or you don't. - -Now, suppose your security requirements have changed and in addition to project managers, PMOs can also create new projects. - -Security requirements change, but with {project_name} there is no need to change your application code to address the new requirements. Once your application is based on the resource and scope identifier, you need only change the configuration of the permissions or policies associated with a particular resource in the authorization server. In this case, the permissions and policies associated with the `Project Resource` and/or the scope `urn:project.com:project:create` would be changed. - -= Using the AuthorizationContext to obtain an Authorization Client Instance - -The ```AuthorizationContext``` can also be used to obtain a reference to the <<_service_client_api, Authorization Client API>> configured to your application: - -```java - ClientAuthorizationContext clientContext = ClientAuthorizationContext.class.cast(authzContext); - AuthzClient authzClient = clientContext.getClient(); -``` - -In some cases, resource servers protected by the policy enforcer need to access the APIs provided by the authorization server. With an ```AuthzClient``` instance in hands, resource servers can interact with the server in order to create resources or check for specific permissions programmatically. diff --git a/authorization_services/topics/enforcer-claim-information-point.adoc b/authorization_services/topics/enforcer-claim-information-point.adoc deleted file mode 100644 index 62eae6a14..000000000 --- a/authorization_services/topics/enforcer-claim-information-point.adoc +++ /dev/null @@ -1,165 +0,0 @@ -[[_enforcer_claim_information_point]] -= Claim Information Point - -A Claim Information Point (CIP) is responsible for resolving claims and pushing these claims to the {project_name} server -in order to provide more information about the access context to policies. They can be defined as a configuration option -to the policy-enforcer in order to resolve claims from different sources, such as: - -* HTTP Request (parameters, headers, body, etc) -* External HTTP Service -* Static values defined in configuration -* Any other source by implementing the Claim Information Provider SPI - -When pushing claims to the {project_name} server, policies can base decisions not only on who a user is but also by taking -context and contents into account, based on who, what, why, when, where, and which for a given transaction. It is all about -Contextual-based Authorization and how to use runtime information in order to support fine-grained authorization decisions. - -== Obtaining information from the HTTP request - -Here are several examples showing how you can extract claims from an HTTP request: - -.keycloak.json -```json -"policy-enforcer": { - "paths": [ - { - "path": "/protected/resource", - "claim-information-point": { - "claims": { - "claim-from-request-parameter": "{request.parameter['a']}", - "claim-from-header": "{request.header['b']}", - "claim-from-cookie": "{request.cookie['c']}", - "claim-from-remoteAddr": "{request.remoteAddr}", - "claim-from-method": "{request.method}", - "claim-from-uri": "{request.uri}", - "claim-from-relativePath": "{request.relativePath}", - "claim-from-secure": "{request.secure}", - "claim-from-json-body-object": "{request.body['/a/b/c']}", - "claim-from-json-body-array": "{request.body['/d/1']}", - "claim-from-body": "{request.body}", - "claim-from-static-value": "static value", - "claim-from-multiple-static-value": ["static", "value"], - "param-replace-multiple-placeholder": "Test {keycloak.access_token['/custom_claim/0']} and {request.parameter['a']} " - } - } - } - ] - } -``` - -== Obtaining information from an external HTTP service - -Here are several examples showing how you can extract claims from an external HTTP Service: - -.keycloak.json -```json -"policy-enforcer": { - "paths": [ - { - "path": "/protected/resource", - "claim-information-point": { - "http": { - "claims": { - "claim-a": "/a", - "claim-d": "/d", - "claim-d0": "/d/0", - "claim-d-all": ["/d/0", "/d/1"] - }, - "url": "http://mycompany/claim-provider", - "method": "POST", - "headers": { - "Content-Type": "application/x-www-form-urlencoded", - "header-b": ["header-b-value1", "header-b-value2"], - "Authorization": "Bearer {keycloak.access_token}" - }, - "parameters": { - "param-a": ["param-a-value1", "param-a-value2"], - "param-subject": "{keycloak.access_token['/sub']}", - "param-user-name": "{keycloak.access_token['/preferred_username']}", - "param-other-claims": "{keycloak.access_token['/custom_claim']}" - } - } - } - } - ] - } -``` - -== Static claims - -.keycloak.json -```json -"policy-enforcer": { - "paths": [ - { - "path": "/protected/resource", - "claim-information-point": { - "claims": { - "claim-from-static-value": "static value", - "claim-from-multiple-static-value": ["static", "value"], - } - } - } - ] - } -``` - -== Claim information provider SPI - -The Claim Information Provider SPI can be used by developers to support different claim information points in case none of the -built-ins providers are enough to address their requirements. - -For example, to implement a new CIP provider you need to implement `org.keycloak.adapters.authorization.ClaimInformationPointProviderFactory` -and `ClaimInformationPointProvider` and also provide the file `META-INF/services/org.keycloak.adapters.authorization.ClaimInformationPointProviderFactory` -in your application`s classpath. - -Example of `org.keycloak.adapters.authorization.ClaimInformationPointProviderFactory`: - -```java -public class MyClaimInformationPointProviderFactory implements ClaimInformationPointProviderFactory { - - @Override - public String getName() { - return "my-claims"; - } - - @Override - public void init(PolicyEnforcer policyEnforcer) { - - } - - @Override - public MyClaimInformationPointProvider create(Map config) { - return new MyClaimInformationPointProvider(config); - } -} -``` - -Every CIP provider must be associated with a name, as defined above in the `MyClaimInformationPointProviderFactory.getName` method. The name -will be used to map the configuration from the `claim-information-point` section in the `policy-enforcer` configuration to the implementation. - -When processing requests, the policy enforcer will call the MyClaimInformationPointProviderFactory.create method in order to obtain an -instance of MyClaimInformationPointProvider. When called, any configuration defined for this particular CIP provider -(via claim-information-point) is passed as a map. - -Example of `ClaimInformationPointProvider`: - -```java -public class MyClaimInformationPointProvider implements ClaimInformationPointProvider { - - private final Map config; - - public MyClaimInformationPointProvider(Map config) { - this.config = config; - } - - @Override - public Map> resolve(HttpFacade httpFacade) { - Map> claims = new HashMap<>(); - - // put whatever claim you want into the map - - return claims; - } -} -``` diff --git a/authorization_services/topics/enforcer-https.adoc b/authorization_services/topics/enforcer-https.adoc deleted file mode 100644 index a737df04a..000000000 --- a/authorization_services/topics/enforcer-https.adoc +++ /dev/null @@ -1,18 +0,0 @@ -[[_enforcer_filter_using_https]] -= Configuring TLS/HTTPS - -When the server is using HTTPS, ensure your adapter is configured as follows: - -.keycloak.json -```json -{ - "truststore": "path_to_your_trust_store", - "truststore-password": "trust_store_password" -} -``` - -The configuration above enables TLS/HTTPS to the Authorization Client, making possible to access a -{project_name} Server remotely using the HTTPS scheme. - -[NOTE] -It is strongly recommended that you enable TLS/HTTPS when accessing the {project_name} Server endpoints. diff --git a/authorization_services/topics/enforcer-js-adapter.adoc b/authorization_services/topics/enforcer-js-adapter.adoc deleted file mode 100644 index ad7a9dd62..000000000 --- a/authorization_services/topics/enforcer-js-adapter.adoc +++ /dev/null @@ -1,149 +0,0 @@ -[[_enforcer_js_adapter]] -= JavaScript integration - -The {project_name} Server comes with a JavaScript library you can use to interact with a resource server protected by a policy enforcer. -This library is based on the {project_name} JavaScript adapter, which can be integrated to allow your client to obtain permissions from a {project_name} Server. - -You can obtain this library from a running a {project_name} Server instance by including the following `script` tag in your web page: - -[source,html,subs="attributes+"] ----- - ----- -Once you do that, you can create a `KeycloakAuthorization` instance as follows: - -```javascript -const keycloak = ... // obtain a Keycloak instance from keycloak.js library -const authorization = new KeycloakAuthorization(keycloak); -``` -The *keycloak-authz.js* library provides two main features: - -* Obtain permissions from the server using a permission ticket, if you are accessing a UMA protected resource server. - -* Obtain permissions from the server by sending the resources and scopes the application wants to access. - -In both cases, the library allows you to easily interact with both resource server and {project_name} Authorization Services to obtain tokens with -permissions your client can use as bearer tokens to access the protected resources on a resource server. - -== Handling authorization responses from a UMA-Protected resource server - -If a resource server is protected by a policy enforcer, it responds to client requests based on the permissions carried along with a bearer token. -Typically, when you try to access a resource server with a bearer token that is lacking permissions to access a protected resource, the resource server -responds with a *401* status code and a `WWW-Authenticate` header. - -[source,bash,subs="attributes+"] ----- -HTTP/1.1 401 Unauthorized -WWW-Authenticate: UMA realm="${realm}", - as_uri="https://${host}:${port}{kc_realms_path}/${realm}", - ticket="016f84e8-f9b9-11e0-bd6f-0021cc6004de" ----- - -See <<_service_uma_authorization_process, UMA Authorization Process>> for more information. - -What your client needs to do is extract the permission ticket from the ```WWW-Authenticate``` header returned by the resource server -and use the library to send an authorization request as follows: - -```javascript -// prepare a authorization request with the permission ticket -const authorizationRequest = {}; -authorizationRequest.ticket = ticket; - -// send the authorization request, if successful retry the request -Identity.authorization.authorize(authorizationRequest).then(function (rpt) { - // onGrant -}, function () { - // onDeny -}, function () { - // onError -}); -``` - -The `authorize` function is completely asynchronous and supports a few callback functions to receive notifications from the server: - -* `onGrant`: The first argument of the function. If authorization was successful and the server returned an RPT with the requested permissions, the callback receives the RPT. -* `onDeny`: The second argument of the function. Only called if the server has denied the authorization request. -* `onError`: The third argument of the function. Only called if the server responds unexpectedly. - -Most applications should use the `onGrant` callback to retry a request after a 401 response. Subsequent requests should include the RPT as a bearer token for retries. - -== Obtaining entitlements - -The ```keycloak-authz.js``` library provides an `entitlement` function that you can use to obtain an RPT from the server by providing -the resources and scopes your client wants to access. - -.Example about how to obtain an RPT with permissions for all resources and scopes the user can access -```javascript -authorization.entitlement('my-resource-server-id').then(function (rpt) { - // onGrant callback function. - // If authorization was successful you'll receive an RPT - // with the necessary permissions to access the resource server -}); -``` - -.Example about how to obtain an RPT with permissions for specific resources and scopes -```javascript -authorization.entitlement('my-resource-server', { - "permissions": [ - { - "id" : "Some Resource" - } - ] -}).then(function (rpt) { - // onGrant -}); -``` - -When using the `entitlement` function, you must provide the _client_id_ of the resource server you want to access. - -The `entitlement` function is completely asynchronous and supports a few callback functions to receive notifications from the server: - -* `onGrant`: The first argument of the function. If authorization was successful and the server returned an RPT with the requested permissions, the callback receives the RPT. -* `onDeny`: The second argument of the function. Only called if the server has denied the authorization request. -* `onError`: The third argument of the function. Only called if the server responds unexpectedly. - -== Authorization request - -Both ```authorize``` and ```entitlement``` functions accept an authorization request object. This object can be set with the following -properties: - -* *permissions* -+ -An array of objects representing the resource and scopes. For instance: -+ -```javascript -const authorizationRequest = { - "permissions": [ - { - "id" : "Some Resource", - "scopes" : ["view", "edit"] - } - ] -} -``` -+ -* *metadata* -+ -An object where its properties define how the authorization request should be processed by the server. -+ -** *response_include_resource_name* -+ -A boolean value indicating to the server if resource names should be included in the RPT's permissions. If false, only the resource -identifier is included. -** *response_permissions_limit* -+ -An integer N that defines a limit for the amount of permissions an RPT can have. When used together with -`rpt` parameter, only the last N requested permissions will be kept in the RPT -+ -* *submit_request* -+ -A boolean value indicating whether the server should create permission requests to the resources and scopes referenced by a permission ticket. -This parameter will only take effect when used together with the `ticket` parameter as part of a UMA authorization process. - -== Obtaining the RPT - -If you have already obtained an RPT using any of the authorization functions provided by the library, you can always obtain the RPT as follows from the authorization object (assuming that it has been initialized by one of the techniques shown earlier): - -```javascript -const rpt = authorization.rpt; -``` diff --git a/authorization_services/topics/enforcer-keycloak-enforcement-filter.adoc b/authorization_services/topics/enforcer-keycloak-enforcement-filter.adoc deleted file mode 100644 index 9d6bca0bf..000000000 --- a/authorization_services/topics/enforcer-keycloak-enforcement-filter.adoc +++ /dev/null @@ -1,166 +0,0 @@ -[[_enforcer_filter]] -= Configuration - -To enable policy enforcement for your application, add the following property to your *keycloak.json* file: - -.keycloak.json -```json -{ - "policy-enforcer": {} -} -``` -Or a little more verbose if you want to manually define the resources being protected: - -```json -{ - "policy-enforcer": { - "user-managed-access" : {}, - "enforcement-mode" : "ENFORCING", - "paths": [ - { - "path" : "/someUri/*", - "methods" : [ - { - "method": "GET", - "scopes" : ["urn:app.com:scopes:view"] - }, - { - "method": "POST", - "scopes" : ["urn:app.com:scopes:create"] - } - ] - }, - { - "name" : "Some Resource", - "path" : "/usingPattern/{id}", - "methods" : [ - { - "method": "DELETE", - "scopes" : ["urn:app.com:scopes:delete"] - } - ] - }, - { - "path" : "/exactMatch" - }, - { - "name" : "Admin Resources", - "path" : "/usingWildCards/*" - } - ] - } -} -``` - -Here is a description of each configuration option: - -* *policy-enforcer* -+ -Specifies the configuration options that define how policies are actually enforced and optionally the paths you want to protect. If not specified, the policy enforcer queries the server -for all resources associated with the resource server being protected. In this case, you need to ensure the resources are properly configured with a <<_resource_create_uri, URIS>> property that matches the paths you want to protect. -+ -** *user-managed-access* -+ -Specifies that the adapter uses the UMA protocol. If specified, the adapter queries the server for permission tickets and returns them to clients according to the UMA specification. If not specified, the policy enforcer will be able to enforce permissions based on regular access tokens or RPTs. In this case, -before denying access to the resource when the token lacks permission, the policy enforcer will try to obtain permissions directly from the server. -+ -** *enforcement-mode* -+ -Specifies how policies are enforced. -+ -*** *ENFORCING* -+ -(default mode) Requests are denied by default even when there is no policy associated with a given resource. -+ -*** *PERMISSIVE* -+ -Requests are allowed even when there is no policy associated with a given resource. -+ -*** *DISABLED* -+ -Completely disables the evaluation of policies and allows access to any resource. When `enforcement-mode` is `DISABLED` -applications are still able to obtain all permissions granted by {project_name} through the <<_enforcer_authorization_context, Authorization Context>> -+ -** *on-deny-redirect-to* -+ -Defines a URL where a client request is redirected when an "access denied" message is obtained from the server. By default, the adapter responds with a 403 HTTP status code. -+ -** *path-cache* -+ -Defines how the policy enforcer should track associations between paths in your application and resources defined in {project_name}. The cache is needed to avoid -unnecessary requests to a {project_name} server by caching associations between paths and protected resources. -+ -*** *lifespan* -+ -Defines the time in milliseconds when the entry should be expired. If not provided, default value is *30000*. A value equal to 0 can be set to completely disable the cache. A value equal to -1 can be set to disable the expiry of the cache. -+ -*** *max-entries* -+ -Defines the limit of entries that should be kept in the cache. If not provided, default value is *1000*. -+ -** *paths* -+ -Specifies the paths to protect. This configuration is optional. If not defined, the policy enforcer will discover all paths by fetching the resources you defined to your application in {project_name}, where these resources are defined with `URIS` representing some paths in your application. -+ -*** *name* -+ -The name of a resource on the server that is to be associated with a given path. When used in conjunction with a *path*, the policy enforcer ignores the resource's *URIS* property and uses the path you provided instead. -*** *path* -+ -(required) A URI relative to the application's context path. If this option is specified, the policy enforcer queries the server for a resource with a *URI* with the same value. -Currently a very basic logic for path matching is supported. Examples of valid paths are: -+ -**** Wildcards: `/*` -**** Suffix: `/*.html` -**** Sub-paths: `/path/*` -**** Path parameters: /resource/{id} -**** Exact match: /resource -**** Patterns: /{version}/resource, /api/{version}/resource, /api/{version}/resource/* -+ -*** *methods* -+ -The HTTP methods (for example, GET, POST, PATCH) to protect and how they are associated with the scopes for a given resource in the server. -+ -**** *method* -+ -The name of the HTTP method. -+ -**** *scopes* -+ -An array of strings with the scopes associated with the method. When you associate scopes with a specific method, the client trying to access a protected resource (or path) must provide an RPT that grants permission to all scopes specified in the list. For example, if you define a method _POST_ with a scope _create_, the RPT must contain a permission granting access to the _create_ scope when performing a POST to the path. -+ -**** *scopes-enforcement-mode* -+ -A string referencing the enforcement mode for the scopes associated with a method. Values can be *ALL* or *ANY*. If *ALL*, -all defined scopes must be granted in order to access the resource using that method. If *ANY*, at least one scope should be -granted in order to gain access to the resource using that method. By default, enforcement mode is set to *ALL*. -+ -*** *enforcement-mode* -+ -Specifies how policies are enforced. -+ -**** *ENFORCING* -+ -(default mode) Requests are denied by default even when there is no policy associated with a given resource. -+ -**** *DISABLED* -+ -*** *claim-information-point* -+ -Defines a set of one or more claims that must be resolved and pushed to the {project_name} server in order to make these claims available to policies. See <<_enforcer_claim_information_point, Claim Information Point>> for more details. -+ -** *lazy-load-paths* -+ -Specifies how the adapter should fetch the server for resources associated with paths in your application. If *true*, the policy -enforcer is going to fetch resources on-demand accordingly with the path being requested. This configuration is specially useful -when you don't want to fetch all resources from the server during deployment (in case you have provided no `paths`) or in case -you have defined only a sub set of `paths` and want to fetch others on-demand. -+ -** *http-method-as-scope* -+ -Specifies how scopes should be mapped to HTTP methods. If set to *true*, the policy enforcer will use the HTTP method from the current request to -check whether or not access should be granted. When enabled, make sure your resources in {project_name} are associated with scopes representing each HTTP method you are protecting. -+ -** *claim-information-point* -+ -Defines a set of one or more *global* claims that must be resolved and pushed to the {project_name} server in order to make these claims available to policies. See <<_enforcer_claim_information_point, Claim Information Point>> for more details. diff --git a/authorization_services/topics/enforcer-overview.adoc b/authorization_services/topics/enforcer-overview.adoc deleted file mode 100644 index e9c108afa..000000000 --- a/authorization_services/topics/enforcer-overview.adoc +++ /dev/null @@ -1,32 +0,0 @@ -[[_enforcer_overview]] -= Policy enforcers - -Policy Enforcement Point (PEP) is a design pattern and as such you can implement it in different ways. {project_name} provides all the necessary means -to implement PEPs for different platforms, environments, and programming languages. {project_name} Authorization Services presents a RESTful API, -and leverages OAuth2 authorization capabilities for fine-grained authorization using a centralized authorization server. - -image:images/pep-pattern-diagram.png[alt="PEP overview"] - -A PEP is responsible for enforcing access decisions from the {project_name} server where these decisions are taken by evaluating the policies -associated with a protected resource. It acts as a filter or interceptor in your application in order to check whether or not a particular request -to a protected resource can be fulfilled based on the permissions granted by these decisions. - -Permissions are enforced depending on the protocol you are using. When using UMA, the policy enforcer always expects an RPT as a bearer token in order -to decide whether or not a request can be served. That means clients should first obtain an RPT from {project_name} before sending requests to the resource server. - -However, if you are not using UMA, you can also send regular access tokens to the resource server. In this case, the policy enforcer will try to obtain permissions directly from the server. - -If you are using any of the {project_name} OIDC adapters, you can easily enable the policy enforcer by adding the following property to your *keycloak.json* file: - -.keycloak.json -```json -{ - "policy-enforcer": {} -} -``` - -When you enable the policy enforcer all requests sent to your application are intercepted and access to protected resources will be granted -depending on the permissions granted by {project_name} to the identity making the request. - -Policy enforcement is strongly linked to your application's paths and the <<_resource_overview, resources>> you created for a resource server using the {project_name} Administration Console. By default, -when you create a resource server, {project_name} creates a <<_resource_server_default_config, default configuration>> for your resource server so you can enable policy enforcement quickly. diff --git a/authorization_services/topics/getting-started-overview.adoc b/authorization_services/topics/getting-started-overview.adoc deleted file mode 100644 index 2d5fb7b5c..000000000 --- a/authorization_services/topics/getting-started-overview.adoc +++ /dev/null @@ -1,26 +0,0 @@ -[[_getting_started_overview]] -= Getting started - -Before you can use this tutorial, you need to complete the installation of {project_name} and create the initial admin user as shown in the link:{gettingstarted_link}[{gettingstarted_name}] tutorial. -There is one caveat to this. You have to run a separate {appserver_name} instance on the same machine as {project_name} Server. This separate instance will run your Java Servlet application. Because of this you will have to run the {project_name} under a different port so that there are no port conflicts when running on the same machine. Use the `jboss.socket.binding.port-offset` system property on the command line. The value of this property is a number that will be added to the base value of every port opened by {project_name} Server. - -To boot {project_name} Server: - -.Linux/Unix -[source] ----- -$ .../bin/kc.sh start-dev --http-port 8180 ----- - -.Windows -[source] ----- -> ...\bin\kc.bat start-dev --http-port 8180 ----- - -After installing and booting both servers you should be able to access {project_name} Admin Console at http://localhost:8180/auth/admin/ and also the {appserver_name} instance at -http://localhost:8080. - -[role="_additional-resources"] -.Additional resources -* For more details about installing and configuring {appserver_name} instances, see link:{adapterguide_link}[{adapterguide_name}]. diff --git a/authorization_services/topics/hello-world-before-start.adoc b/authorization_services/topics/hello-world-before-start.adoc deleted file mode 100644 index ecc95b105..000000000 --- a/authorization_services/topics/hello-world-before-start.adoc +++ /dev/null @@ -1,15 +0,0 @@ -= Before you start - -This guide is based on the *{project_name} Demo Distribution*. Download the demo distribution before proceeding. - -[NOTE] -This guide assumes that you are already familiar with {project_name} and that you are able to install and boot a {project_name} Server. For more information, see https://keycloak.gitbooks.io/getting-started-tutorials/content/[the Getting Started tutorials]. - -Ensure you have a {project_name} instance running; the default configuration is http://localhost:8080/auth[http://localhost:8080/auth]. After logging in to the -Administration Console, a page similar to this one is displayed: - -.{project_name} Admin Console -image:images/getting-started/kc-start-page.png[alt="{project_name} Admin Console"] - -The source code for the getting started tutorials can be obtained from the demo distributions. The authorization-related examples -are located at *${KEYCLOAK_DEMO_SERVER_DIR}/examples/authz*. diff --git a/authorization_services/topics/hello-world-create-realm.adoc b/authorization_services/topics/hello-world-create-realm.adoc deleted file mode 100644 index 4fa336586..000000000 --- a/authorization_services/topics/hello-world-create-realm.adoc +++ /dev/null @@ -1,33 +0,0 @@ -[[_getting_started_hello_world_create_realm]] -= Creating a realm and a user - -The first step in this tutorial is to create a realm and a user in that realm. Then, within the realm we will create a single client application, which then becomes a <<_overview_terminology, resource server>> for which you need to enable authorization services. - -.Procedure - -. Create a realm with a name *hello-world-authz*. Once created, a page similar to the following is displayed: -+ -.Realm hello-world-authz -image:images/getting-started/hello-world/create-realm.png[alt="Realm hello-world-authz"] - -. Click *Users*. -+ -The user list page displays where you can create a user. - -. Click *Create user*. -. Complete the *Username*, *Email*, *First Name*, and *Last Name* fields. -. Toggle *User Enabled* to *ON*. -. Click *Create*. -+ -.Add User -image:images/getting-started/hello-world/create-user.png[alt="Add User"] - -. Set a password for the user by clicking the *Credentials* tab. -+ -.Set user password -image:images/getting-started/hello-world/reset-user-pwd.png[alt="Set user password"] - -. Complete the *New Password* and *Password Confirmation* fields and toggle *Temporary* to *OFF*. - -. Click *Save*. -. Click *Save password*. diff --git a/authorization_services/topics/hello-world-create-resource-server.adoc b/authorization_services/topics/hello-world-create-resource-server.adoc deleted file mode 100644 index ad608b29a..000000000 --- a/authorization_services/topics/hello-world-create-resource-server.adoc +++ /dev/null @@ -1,39 +0,0 @@ -[[_getting_started_hello_world_enabling_authz_services]] -= Enabling authorization services - -You can enable authorization services in an existing client application configured to use the OpenID Connect Protocol. You can also create a client using the following procedure. - -.Procedure - -. Click *Clients* in the menu. - -. Fill in the *Client type*. -. Click *Next*. -. Toggle *Client authentication* to *ON*. -. Toggle *Authorization* to *ON*. -. Click *Save*. -. Scroll down to the *Capability config* section. -. Fill in the *Root URL* field. -. Click *Save*. -+ -.Create client application -image:images/getting-started/hello-world/create-client.png[alt="Create client application"] -+ -A new *Authorization* tab is displayed for the client. -+ -.Client Settings -image:images/getting-started/hello-world/enable-authz.png[alt="Client Settings"] - -. Click the *Authorization* tab. -+ -An Authorization Settings page similar to the following is displayed: -+ -.Authorization settings -image:images/getting-started/hello-world/authz-settings.png[alt="Authorization settings"] - -When you enable authorization services for a client application, {project_name} automatically creates several default settings for your client authorization configuration. - -[role="_additional-resources"] -.Additional resources -* <<_resource_server_enable_authorization, Enabling authorization services>> -* <<_resource_server_default_config, Default configuration>> diff --git a/authorization_services/topics/hello-world-deploy.adoc b/authorization_services/topics/hello-world-deploy.adoc deleted file mode 100644 index d7f6635b6..000000000 --- a/authorization_services/topics/hello-world-deploy.adoc +++ /dev/null @@ -1,129 +0,0 @@ -[[_getting_started_hello_world_deploy]] -= Build, deploy, and test your application - -Now that the *app-authz-vanilla* resource server (or client) is properly configured and authorization services are enabled, it can be deployed to the server. - -The project and code for the application you are going to deploy is available in link:{quickstartRepo_link}[{quickstartRepo_name}]. You will need the following -installed on your machine and available in your PATH before you can continue: - -* Java JDK 8 -* Apache Maven 3.1.1 or higher -* Git - -ifeval::[{project_community}==true] -You can obtain the code by cloning the repository at {quickstartRepo_link}. The quickstarts are designed to work with the most recent Keycloak release. -endif::[] - -ifeval::[{project_product}==true] -You can obtain the code by cloning the repository at {quickstartRepo_link}. Use the branch matching the version of {project_name} in use. -endif::[] - -Follow these steps to download the code. - -.Clone Project -[source, subs="attributes"] ----- -$ git clone {quickstartRepo_link} ----- - -The application we are about to build and deploy is located at - -[source, subs="attributes"] ----- -$ cd {quickstartRepo_dir}/app-authz-jee-vanilla ----- - -== Obtaining the adapter configuration - -You must first obtain the adapter configuration before building and deploying the application. - -.Procedure - -. Log into the Admin Console. - -. Click *Clients* in the menu. - -. In the client listing, click the *app-authz-vanilla* client application. The Client Settings page opens. -+ -.Client Settings -image:images/getting-started/hello-world/enable-authz.png[alt="Client Settings"] - -. From the *Action* list, select *Download adapter config*. -. From the Format Option list, select *Keycloak OIDC JSON*. -+ -The adapter configuration is displayed in JSON format. - -. Click *Download*. -+ -.Adapter configuration -image:images/getting-started/hello-world/adapter-config.png[alt="Adapter configuration"] - -. Move the file `keycloak.json` to the `app-authz-jee-vanilla/config` directory. - -. Optionally, specify a redirection URL. -+ -By default, the policy enforcer responds with a `403` status code when the user lacks permission to access protected resources on the resource server. However, you can also specify a redirection URL for unauthorized users. To specify a redirection URL, edit the *keycloak.json* file that you updated and replace the `policy-enforcer` configuration with the following: -+ -```json -"policy-enforcer": { - "on-deny-redirect-to" : "/app-authz-vanilla/error.jsp" -} -``` -+ -This change specifies to the policy enforcer to redirect users to a `/app-authz-vanilla/error.jsp` page if a user does not have the necessary permissions to access a protected resource, rather than an unhelpful `403 Unauthorized` message. - -== Building and deploying the application - -To build and deploy the application execute the following command: - -[source, subs="attributes"] ----- -$ cd {quickstartRepo_dir}/app-authz-jee-vanilla -$ mvn clean package wildfly:deploy ----- - -== Testing the application - -If your application was successfully deployed, you can access it at http://localhost:8080/app-authz-vanilla[http://localhost:8080/app-authz-vanilla]. The {project_name} Login page opens. - -.Login page -image:images/getting-started/hello-world/login-page.png[alt="Login page"] - -.Procedure - -. Log in as *alice* using the password you specified for that user. The following page is displayed: -+ -.Hello World Authz main page -image:images/getting-started/hello-world/main-page.png[alt="Hello World Authz main page"] -+ -The <<_resource_server_default_config, default settings>> defined by {project_name} when you enable authorization services for a client application provide a simple -policy that always grants access to the resources protected by this policy. - -You can start by changing the default permissions and policies and test how your application responds, or even create new policies using the different -<<_policy_overview, policy types>> provided by {project_name}. - -There are a plenty of things you can do now to test this application. For example, you can change the default policy by clicking -the `Authorization` tab for the client, then client on the `Policies` tab, then click on the `Default Policy` in the list. -Now we are going to change the `Logic` to `Negative` using the dropdown list in this page. - -. Log out of the demo application and log in again. -+ -You can no longer access the application. -+ -image:images/getting-started/hello-world/access-denied-page.png[alt="Access Denied page"] - -[role="_additional-resources"] -.Additional resources -* <<_policy_overview, Policy types>> - -== Next steps - -There are additional things you can do, such as: - -* Create a scope, define a policy and permission for it, and test it on the application side. Can the user perform an action (or anything else represented by the scope you created)? -* Create different types of policies and associate these policies with the `Default Permission`. -* Apply multiple policies to the `Default Permission` and test the behavior. For example, combine multiple policies and change the `Decision Strategy` accordingly. - -[role="_additional-resources"] -.Additional resources -* For more information about how to view and test permissions inside your application see <<_enforcer_authorization_context, Obtaining the authorization context>>. diff --git a/authorization_services/topics/hello-world-overview.adoc b/authorization_services/topics/hello-world-overview.adoc deleted file mode 100644 index 472ec7272..000000000 --- a/authorization_services/topics/hello-world-overview.adoc +++ /dev/null @@ -1,14 +0,0 @@ -[[_getting_started_hello_world_overview]] -= Securing a servlet application - -The purpose of this getting started guide is to get you up and running as quickly as possible so that you can experiment with and test various authorization features provided by {project_name}. -This quick tour relies heavily on the default database and server configurations and does not cover complex deployment options. -For more information on features or configuration options, see the appropriate sections in this documentation. - -This guide explains key concepts about {project_name} Authorization Services: - -* Enabling fine-grained authorization for a client application -* Configuring a client application to be a resource server, with protected resources -* Defining permissions and authorization policies to govern access to protected resources -* Enabling policy enforcement in your applications. - diff --git a/authorization_services/topics/permission-create-resource.adoc b/authorization_services/topics/permission-create-resource.adoc deleted file mode 100644 index b547d5d89..000000000 --- a/authorization_services/topics/permission-create-resource.adoc +++ /dev/null @@ -1,42 +0,0 @@ -[[_permission_create_resource]] -= Creating resource-based permission - -A resource-based permission defines a set of one or more resources to protect using a set of one or more authorization policies. - -To create a new resource-based permission, select *Create resource-based permission* from the *Create permission* dropdown. - -.Add Resource Permission -image:images/permission/create-resource.png[alt="Add Resource Permission"] - -== Configuration - -* *Name* -+ -A human-readable and unique string describing the permission. A best practice is to use names that are closely related to your business and security requirements, so you -can identify them more easily. -+ -* *Description* -+ -A string containing details about this permission. - -[[_permission_create_resource_apply_resource_type]] -* *Apply To Resource Type* -+ -Specifies if the permission is applied to all resources with a given type. When selecting this field, you are prompted to enter the resource type to protect. -+ -** Resource Type -+ -Defines the resource type to protect. When defined, this permission is evaluated for all resources matching that type. -+ -* *Resources* -+ -Defines a set of one or more resources to protect. - -* *Policy* -+ -Defines a set of one or more policies to associate with a permission. To associate a policy you can either select an existing policy -or create a new one by selecting the type of the policy you want to create. - -* *Decision Strategy* -+ -The <<_permission_decision_strategies, Decision Strategy>> for this permission. diff --git a/authorization_services/topics/permission-create-scope.adoc b/authorization_services/topics/permission-create-scope.adoc deleted file mode 100644 index 3991e362a..000000000 --- a/authorization_services/topics/permission-create-scope.adoc +++ /dev/null @@ -1,37 +0,0 @@ -[[_permission_create_scope]] -= Creating scope-based permissions - -A scope-based permission defines a set of one or more scopes to protect using a set of one or more authorization policies. Unlike resource-based permissions, you can use this permission type to create permissions not only for a resource, but also for the scopes associated with it, providing more granularity when defining the permissions that govern your resources and the actions that can be performed on them. - -To create a new scope-based permission, select *Create scope-based permission* from the *Create permission* dropdown. - -.Add Scope Permission -image:images/permission/create-scope.png[alt="Add Scope Permission"] - -== Configuration - -* *Name* -+ -A human-readable and unique string describing the permission. A best practice is to use names that are closely related to your business and security requirements, so you -can identify them more easily. -+ -* *Description* -+ -A string containing details about this permission. -+ -* *Resource* -+ -Restricts the scopes to those associated with the selected resource. If none is selected, all scopes are available. -+ -* *Scopes* -+ -Defines a set of one or more scopes to protect. - -* *Policy* -+ -Defines a set of one or more policies to associate with a permission. To associate a policy you can either select an existing policy -or create a new one by selecting the type of the policy you want to create. - -* *Decision Strategy* -+ -The <<_permission_decision_strategies, Decision Strategy>> for this permission. diff --git a/authorization_services/topics/permission-decision-strategy.adoc b/authorization_services/topics/permission-decision-strategy.adoc deleted file mode 100644 index e862cf9a0..000000000 --- a/authorization_services/topics/permission-decision-strategy.adoc +++ /dev/null @@ -1,16 +0,0 @@ -[[_permission_decision_strategies]] -= Policy decision strategies - -When associating policies with a permission, you can also define a decision strategy to specify how to evaluate the outcome of the associated policies to determine access. - -* *Unanimous* -+ -The default strategy if none is provided. In this case, _all_ policies must evaluate to a positive decision for the final decision to be also positive. -+ -* *Affirmative* -+ -In this case, _at least one_ policy must evaluate to a positive decision for the final decision to be also positive. -+ -* *Consensus* -+ -In this case, the number of positive decisions must be greater than the number of negative decisions. If the number of positive and negative decisions is equal, the final decision will be negative. diff --git a/authorization_services/topics/permission-overview.adoc b/authorization_services/topics/permission-overview.adoc deleted file mode 100644 index 41b2abcad..000000000 --- a/authorization_services/topics/permission-overview.adoc +++ /dev/null @@ -1,17 +0,0 @@ -[[_permission_overview]] -= Managing permissions - -A permission associates the object being protected and the policies that must be evaluated to decide whether access should be granted. - -After creating the resources you want to protect and the policies you want to use to protect these resources, -you can start managing permissions. To manage permissions, click the *Permissions* tab when editing a resource server. - -.Permissions -image:images/permission/view.png[alt="Permissions"] - -Permissions can be created to protect two main types of objects: - -* *Resources* -* *Scopes* - -To create a permission, select the permission type you want to create from the item list in the upper right corner of the permission listing. The following sections describe these two types of objects in more detail. diff --git a/authorization_services/topics/permission-typed-resource-permission.adoc b/authorization_services/topics/permission-typed-resource-permission.adoc deleted file mode 100644 index da0cd9fa0..000000000 --- a/authorization_services/topics/permission-typed-resource-permission.adoc +++ /dev/null @@ -1,16 +0,0 @@ -[[_permission_typed_resource]] -= Typed resource permission - -Resource permissions can also be used to define policies that are to be applied to all resources with a given <<_resource_create_type, type>>. This form of resource-based permission can be useful when you have resources sharing common access requirements and constraints. - -Frequently, resources within an application can be categorized (or typed) based on the data they encapsulate or the functionality they provide. For example, a financial application can manage different banking accounts where each one belongs to a specific customer. Although they are different banking accounts, they share common security requirements and constraints that are globally defined by the banking organization. With typed resource permissions, you can define common policies to apply to all banking accounts, such as: - -* Only the owner can manage his account -* Only allow access from the owner's country and/or region -* Enforce a specific authentication method - -To create a typed resource permission, click <<_permission_create_resource_apply_resource_type, Apply to Resource Type>> when creating a new resource-based permission. With `Apply to Resource Type` set to `On`, -you can specify the type that you want to protect as well as the policies that are to be applied to govern access to all resources with type you have specified. - -.Example of a typed resource permission -image:images/permission/typed-resource-perm-example.png[alt="Example of a typed resource permission"] diff --git a/authorization_services/topics/policy-aggregated-policy.adoc b/authorization_services/topics/policy-aggregated-policy.adoc deleted file mode 100644 index 7c5f76814..000000000 --- a/authorization_services/topics/policy-aggregated-policy.adoc +++ /dev/null @@ -1,66 +0,0 @@ -[[_policy_aggregated]] -= Aggregated policy - -As mentioned previously, {project_name} allows you to build a policy of policies, a concept referred to as policy aggregation. You can use policy aggregation to reuse existing policies to build more complex ones and keep your permissions even more decoupled from the policies that are evaluated during the processing of authorization requests. - -ifeval::[{project_community}==true] -To create a new aggregated policy, select *Aggregated* from the policy type list. -endif::[] -ifeval::[{project_product}==true] -To create a new aggregated policy, select *Aggregated* in the item list located in the right upper corner of the policy listing. -endif::[] - -.Add an aggregated policy -image:images/policy/create-aggregated.png[alt="Add aggregated policy"] - -Let's suppose you have a resource called _Confidential Resource_ that can be accessed only by users from the _keycloak.org_ domain and from a certain range of IP addresses. -You can create a single policy with both conditions. However, you want to reuse the domain part of this policy to apply to permissions that operates regardless of the originating network. - -You can create separate policies for both domain and network conditions and create a third policy based on the combination of these two policies. With an aggregated policy, you can freely combine other policies and then apply the new aggregated policy to any permission you want. - -[NOTE] -When creating aggregated policies, be mindful that you are not introducing a circular reference or dependency between policies. If a circular dependency is detected, you cannot create or update the policy. - -== Configuration - -* *Name* -+ -A human-readable and unique string describing the policy. We strongly suggest that you use names that are closely related with your business and security requirements, so you -can identify them more easily and also know what they mean. -+ -* *Description* -+ -A string with more details about this policy. -+ -* *Apply Policy* -+ -Defines a set of one or more policies to associate with the aggregated policy. To associate a policy you can either select an existing policy -or create a new one by selecting the type of the policy you want to create. -+ -* *Decision Strategy* -+ -The decision strategy for this permission. -+ -* *Logic* -+ -The logic of this policy to apply after the other conditions have been evaluated. - -[role="_additional-resources"] -.Additional resources -* <<_policy_logic, Positive and negative logic>> - -== Decision strategy for aggregated policies - -When creating aggregated policies, you can also define the decision strategy that will be used to determine the final decision based on the outcome from each policy. - -* *Unanimous* -+ -The default strategy if none is provided. In this case, _all_ policies must evaluate to a positive decision for the final decision to be also positive. -+ -* *Affirmative* -+ -In this case, _at least one_ policy must evaluate to a positive decision in order for the final decision to be also positive. -+ -* *Consensus* -+ -In this case, the number of positive decisions must be greater than the number of negative decisions. If the number of positive and negative decisions is the same, the final decision will be negative. diff --git a/authorization_services/topics/policy-client-policy.adoc b/authorization_services/topics/policy-client-policy.adoc deleted file mode 100644 index aa9a7095c..000000000 --- a/authorization_services/topics/policy-client-policy.adoc +++ /dev/null @@ -1,32 +0,0 @@ -[[_policy_client]] -= Client-based policy - -You can use this type of policy to define conditions for your permissions where a set of one or more clients is permitted to access an object. - -To create a new client-based policy, select *Client* from the policy type list. - -.Add a Client Policy -image:images/policy/create-client.png[alt="Add a Client Policy"] - -== Configuration - -* *Name* -+ -A human-readable and unique string identifying the policy. A best practice is to use names that are closely related to your business and security requirements, so you -can identify them more easily. -+ -* *Description* -+ -A string containing details about this policy. -+ -* *Clients* -+ -Specifies which clients have givenGroup-based policy access by this policy. -+ -* *Logic* -+ -The logic of this policy to apply after the other conditions have been evaluated. - -[role="_additional-resources"] -.Additional resources -* <<_policy_logic, Positive and negative logic>> diff --git a/authorization_services/topics/policy-client-scope-policy-required-client-scope.adoc b/authorization_services/topics/policy-client-scope-policy-required-client-scope.adoc deleted file mode 100644 index dd07fed24..000000000 --- a/authorization_services/topics/policy-client-scope-policy-required-client-scope.adoc +++ /dev/null @@ -1,11 +0,0 @@ -[[_policy_client_scope_required]] -= Defining a client scope as required - -When creating a client scope-based policy, you can specify a specific client scope as `Required`. When you do that, the policy will grant access only if the client requesting access has been granted *all* the *required* client scopes. - -.Example of required client scope -image:images/policy/create-client-scope.png[alt="Example of required client scope"] - -To specify a client scope as required, select the `Required` checkbox for the client scope you want to configure as required. - -Required client scopes can be useful when your policy defines multiple client scopes but only a subset of them are mandatory. diff --git a/authorization_services/topics/policy-client-scope-policy.adoc b/authorization_services/topics/policy-client-scope-policy.adoc deleted file mode 100644 index 18f6db629..000000000 --- a/authorization_services/topics/policy-client-scope-policy.adoc +++ /dev/null @@ -1,33 +0,0 @@ -[[_policy_client_scope]] -= Client scope-based policy - -You can use this type of policy to define conditions for your permissions where a set of one or more client scopes is permitted to access an object. - -By default, client scopes added to this policy are not specified as required and the policy will grant access if the client requesting access has been granted any of these client scopes. However, you can specify a specific client scope as <<_policy_client_scope_required, required>> if you want to enforce a specific client scope. - -To create a new client scope-based policy, select *Client Scope* from the policy type list. - -.Add Client Scope Policy -image:images/policy/create-client-scope.png[alt="Add Client Scope Policy"] - -== Configuration - -* *Name* -+ -A human-readable and unique string describing the policy. A best practice is to use names that are closely related to your business and security requirements, so you can identify them more easily. -+ -* *Description* -+ -A string containing details about this policy. -+ -* *Client Scopes* -+ -Specifies which client scopes are permitted by this policy. -+ -* *Logic* -+ -The logic of this policy to apply after the other conditions have been evaluated. - -[role="_additional-resources"] -.Additional resources -* <<_policy_logic, Positive and negative logic>> diff --git a/authorization_services/topics/policy-evaluation-api.adoc b/authorization_services/topics/policy-evaluation-api.adoc deleted file mode 100644 index 5fbacbe7b..000000000 --- a/authorization_services/topics/policy-evaluation-api.adoc +++ /dev/null @@ -1,121 +0,0 @@ -[[_policy_evaluation_api]] -= Policy evaluation API - -When writing rule-based policies using JavaScript, {project_name} provides an Evaluation API that provides useful information to help determine whether a permission should be granted. - -This API consists of a few interfaces that provide you access to information, such as - -* The permission being evaluated, representing both the resource and scopes being requested. -* The attributes associated with the resource being requested -* Runtime environment and any other attribute associated with the execution context -* Information about users such as group membership and roles - -The main interface is *org.keycloak.authorization.policy.evaluation.Evaluation*, which defines the following contract: - -```java -public interface Evaluation { - - /** - * Returns the {@link ResourcePermission} to be evaluated. - * - * @return the permission to be evaluated - */ - ResourcePermission getPermission(); - - /** - * Returns the {@link EvaluationContext}. Which provides access to the whole evaluation runtime context. - * - * @return the evaluation context - */ - EvaluationContext getContext(); - - /** - * Returns a {@link Realm} that can be used by policies to query information. - * - * @return a {@link Realm} instance - */ - Realm getRealm(); - - /** - * Grants the requested permission to the caller. - */ - void grant(); - - /** - * Denies the requested permission. - */ - void deny(); -} -``` - -When processing an authorization request, {project_name} creates an `Evaluation` instance before evaluating any policy. This instance is then passed to each policy to determine whether access is *GRANT* or *DENY*. - -Policies determine this by invoking the `grant()` or `deny()` methods on an `Evaluation` instance. By default, the state of the `Evaluation` instance is denied, which means that your policies must explicitly invoke the `grant()` method to indicate to the policy evaluation engine that permission should be granted. - -.Additional resources - -* {apidocs_link}[JavaDocs Documentation]. - -== The evaluation context - -The evaluation context provides useful information to policies during their evaluation. - -```java -public interface EvaluationContext { - - /** - * Returns the {@link Identity} that represents an entity (person or non-person) to which the permissions must be granted, or not. - * - * @return the identity to which the permissions must be granted, or not - */ - Identity getIdentity(); - - /** - * Returns all attributes within the current execution and runtime environment. - * - * @return the attributes within the current execution and runtime environment - */ - Attributes getAttributes(); -} -``` - -From this interface, policies can obtain: - -* The authenticated `Identity` -* Information about the execution context and runtime environment - -The `Identity` is built based on the OAuth2 Access Token that was sent along with the authorization request, and this construct has access to all claims -extracted from the original token. For example, if you are using a _Protocol Mapper_ to include a custom claim in an OAuth2 Access Token you can also access this claim -from a policy and use it to build your conditions. - -The `EvaluationContext` also gives you access to attributes related to both the execution and runtime environments. For now, there only a few built-in attributes. - -.Execution and Runtime Attributes -|=== -|Name |Description | Type - -| kc.time.date_time -| Current date and time -| String. Format `MM/dd/yyyy hh:mm:ss` - -| kc.client.network.ip_address -| IPv4 address of the client -| String - -| kc.client.network.host -| Client's host name -| String - -| kc.client.id -| The client id -| String - -| kc.client.user_agent -| The value of the 'User-Agent' HTTP header -| String[] - -| kc.realm.name -| The name of the realm -| String - -|=== diff --git a/authorization_services/topics/policy-evaluation-tool-overview.adoc b/authorization_services/topics/policy-evaluation-tool-overview.adoc deleted file mode 100644 index d93948089..000000000 --- a/authorization_services/topics/policy-evaluation-tool-overview.adoc +++ /dev/null @@ -1,24 +0,0 @@ -[[_policy_evaluation_overview]] -= Evaluating and testing policies - -When designing your policies, you can simulate authorization requests to test how your policies are being evaluated. - -You can access the Policy Evaluation Tool by clicking the `Evaluate` tab when editing a resource server. There you can specify different inputs to simulate real authorization requests and test the effect of your policies. - -.Policy evaluation tool -image:images/policy-evaluation-tool/policy-evaluation-tool.png[alt="Policy evaluation tool"] - -== Providing identity information - -The *Identity Information* filters can be used to specify the user requesting permissions. - -== Providing contextual information - -The *Contextual Information* filters can be used to define additional attributes to the evaluation context, so that policies can obtain these same attributes. - -== Providing the permissions - -The *Permissions* filters can be used to build an authorization request. You can request permissions for a set of one or more resources and scopes. If you want -to simulate authorization requests based on all protected resources and scopes, click *Add* without specifying any `Resources` or `Scopes`. - -When you've specified your desired values, click *Evaluate*. diff --git a/authorization_services/topics/policy-group-policy-extend-children.adoc b/authorization_services/topics/policy-group-policy-extend-children.adoc deleted file mode 100644 index 952b0f8f0..000000000 --- a/authorization_services/topics/policy-group-policy-extend-children.adoc +++ /dev/null @@ -1,12 +0,0 @@ -[[_policy_group_extend_access_children]] -= Extending access to child groups - -By default, when you add a group to this policy, access restrictions will only apply to members of the selected group. - -Under some circumstances, it might be necessary to allow access not only to the group itself but to any child group in the hierarchy. For any group -added you can mark a checkbox *Extend to Children* in order to extend access to child groups. - -.Extending access to child groups -image:images/policy/create-group-extend-children.png[alt="Extending access to child groups"] - -In the example above, the policy is granting access for any user member of *IT* or any of its children. diff --git a/authorization_services/topics/policy-group-policy.adoc b/authorization_services/topics/policy-group-policy.adoc deleted file mode 100644 index 9efaead26..000000000 --- a/authorization_services/topics/policy-group-policy.adoc +++ /dev/null @@ -1,39 +0,0 @@ -[[_policy_group]] -= Group-based policy - -You can use this type of policy to define conditions for your permissions where a set of one or more groups (and their hierarchies) is permitted to access an object. - -To create a new group-based policy, select *Group* from the policy type list. - -.Group Policy -image:images/policy/create-group.png[alt="Add Group Policy"] - -== Configuration - -* *Name* -+ -A human-readable and unique string describing the policy. A best practice is to use names that are closely related to your business and security requirements, so you -can identify them more easily. -+ -* *Description* -+ -A string containing details about this policy. -+ -* *Groups Claim* -+ -Specifies the name of the claim in the token holding the group names and/or paths. Usually, authorization requests are processed based on an ID Token or Access Token -previously issued to a client acting on behalf of some user. If defined, the token must include a claim from where this policy is going to obtain the groups -the user is a member of. If not defined, user's groups are obtained from your realm configuration. -+ -* *Groups* -+ -Allows you to select the groups that should be enforced by this policy when evaluating permissions. After adding a group, you can extend access to children of the group -by marking the checkbox *Extend to Children*. If left unmarked, access restrictions only applies to the selected group. -+ -* *Logic* -+ -The logic of this policy to apply after the other conditions have been evaluated. - -[role="_additional-resources"] -.Additional resources -* <<_policy_logic, Positive and negative logic>> diff --git a/authorization_services/topics/policy-js-policy.adoc b/authorization_services/topics/policy-js-policy.adoc deleted file mode 100644 index 248d6533c..000000000 --- a/authorization_services/topics/policy-js-policy.adoc +++ /dev/null @@ -1,152 +0,0 @@ -[[_policy_js]] -= JavaScript-based policy - -WARNING: If your policy implementation is using Attribute based access control (ABAC) as in the examples below, then please make sure that -users are not able to edit the protected attributes and the corresponding attributes are read-only. See the details in the link:{adminguide_link}#_read_only_user_attributes[Threat model mitigation chapter]. - -You can use this type of policy to define conditions for your permissions using JavaScript. It is one of the rule-based policy types -supported by {project_name}, and provides flexibility to write any policy based on the <<_policy_evaluation_api, Evaluation API>>. - -To create a new JavaScript-based policy, select *JavaScript* in the item list in the upper right corner of the policy listing. - -NOTE: By default, JavaScript Policies can not be uploaded to the server. You should prefer deploying your JS Policies directly to -the server as described in link:{developerguide_jsproviders_link}[{developerguide_jsproviders_name}]. - -== Creating a JS policy from a deployed JAR file - -{project_name} allows you to deploy a JAR file in order to deploy scripts to the server. Please, take a look at link:{developerguide_jsproviders_link}[{developerguide_jsproviders_name}] -for more details. - -Once you have your scripts deployed, you should be able to select the scripts you deployed from the list of available policy providers. - -== Examples - -=== Checking for attributes from the evaluation context -Here is a simple example of a JavaScript-based policy that uses attribute-based access control (ABAC) to define a condition based on an attribute -obtained from the execution context: - -```javascript -const context = $evaluation.getContext(); -const contextAttributes = context.getAttributes(); - -if (contextAttributes.containsValue('kc.client.network.ip_address', '127.0.0.1')) { - $evaluation.grant(); -} -``` - -=== Checking for attributes from the current identity -Here is a simple example of a JavaScript-based policy that uses attribute-based access control (ABAC) to define a condition based on an attribute -obtained associated with the current identity: - -```javascript -const context = $evaluation.getContext(); -const identity = context.getIdentity(); -const attributes = identity.getAttributes(); -const email = attributes.getValue('email').asString(0); - -if (email.endsWith('@keycloak.org')) { - $evaluation.grant(); -} -``` - -Where these attributes are mapped from whatever claim is defined in the token that was used in the authorization request. - -=== Checking for roles granted to the current identity -You can also use Role-Based Access Control (RBAC) in your policies. In the example below, we check if a user is granted with a `keycloak_user` *realm* role: - -```javascript -const context = $evaluation.getContext(); -const identity = context.getIdentity(); - -if (identity.hasRealmRole('keycloak_user')) { - $evaluation.grant(); -} -``` - -Or you can check if a user is granted with a `my-client-role` *client* role, where `my-client` is the client id of the client application: - -```javascript -const context = $evaluation.getContext(); -const identity = context.getIdentity(); - -if (identity.hasClientRole('my-client', 'my-client-role')) { - $evaluation.grant(); -} -``` - -=== Checking for roles granted to a user -To check for realm roles granted to a user: - -```javascript -const realm = $evaluation.getRealm(); - -if (realm.isUserInRealmRole('marta', 'role-a')) { - $evaluation.grant(); -} -``` - -Or for client roles granted to a user: - -```javascript -const realm = $evaluation.getRealm(); - -if (realm.isUserInClientRole('marta', 'my-client', 'some-client-role')) { - $evaluation.grant(); -} -``` - -=== Checking for roles granted to a group -To check for realm roles granted to a group: - -```javascript -const realm = $evaluation.getRealm(); - -if (realm.isGroupInRole('/Group A/Group D', 'role-a')) { - $evaluation.grant(); -} -``` - -=== Pushing arbitrary claims to the resource server -To push arbitrary claims to the resource server in order to provide additional information on how permissions should be -enforced: - -```javascript -const permission = $evaluation.getPermission(); - -// decide if permission should be granted - -if (granted) { - permission.addClaim('claim-a', 'claim-a'); - permission.addClaim('claim-a', 'claim-a1'); - permission.addClaim('claim-b', 'claim-b'); -} - -``` - -=== Checking for group membership - -```javascript -const realm = $evaluation.getRealm(); - -if (realm.isUserInGroup('marta', '/Group A/Group B')) { - $evaluation.grant(); -} -``` - -=== Mixing different access control mechanisms -You can also use a combination of several access control mechanisms. The example below shows how roles(RBAC) and -claims/attributes(ABAC) checks can be used within the same policy. In this case we check if user is granted with `admin` role -or has an e-mail from `keycloak.org` domain: - -```javascript -const context = $evaluation.getContext(); -const identity = context.getIdentity(); -const attributes = identity.getAttributes(); -const email = attributes.getValue('email').asString(0); - -if (identity.hasRealmRole('admin') || email.endsWith('@keycloak.org')) { - $evaluation.grant(); -} -``` - -NOTE: When writing your own rules, keep in mind that the *$evaluation* object is an object implementing *org.keycloak.authorization.policy.evaluation.Evaluation*. For more information about what you can access from this interface, see the <<_policy_evaluation_api, Evaluation API>>. diff --git a/authorization_services/topics/policy-logic.adoc b/authorization_services/topics/policy-logic.adoc deleted file mode 100644 index cfdd88e79..000000000 --- a/authorization_services/topics/policy-logic.adoc +++ /dev/null @@ -1,8 +0,0 @@ -[[_policy_logic]] -= Positive and negative logic - -Policies can be configured with positive or negative logic. Briefly, you can use this option to define whether the policy result should be kept as it is or be negated. - -For example, suppose you want to create a policy where only users *not* granted with a specific role should be given access. In this case, -you can create a role-based policy using that role and set its *Logic* field to *Negative*. If you keep *Positive*, which -is the default behavior, the policy result will be kept as it is. diff --git a/authorization_services/topics/policy-overview.adoc b/authorization_services/topics/policy-overview.adoc deleted file mode 100644 index 5bb8fc27b..000000000 --- a/authorization_services/topics/policy-overview.adoc +++ /dev/null @@ -1,17 +0,0 @@ -[[_policy_overview]] -= Managing policies - -As mentioned previously, policies define the conditions that must be satisfied before granting access to an object. - -.Procedure - -. Click the *Policy* tab to view all policies associated with a resource server. -+ -.Policies -image:images/policy/view.png[alt="Policies"] -+ -On this tab, you can view the list of previously created policies as well as create and edit a policy. - -To create a new policy, click *Create policy*, then select a policy type from the list. - -Details about each policy type are described in this section. diff --git a/authorization_services/topics/policy-regex-policy.adoc b/authorization_services/topics/policy-regex-policy.adoc deleted file mode 100644 index a3fa5f6bc..000000000 --- a/authorization_services/topics/policy-regex-policy.adoc +++ /dev/null @@ -1,34 +0,0 @@ -[[_policy_regex]] -= Regex-Based Policy - -You can use this type of policy to define regex conditions for your permissions. - -To create a new regex-based policy, select *Regex* from the policy type list. - -This policy resolves attributes available from the current identity. - -.Add Regex Policy -image:images/policy/create-regex.png[alt="Add Regex Policy"] - -== Configuration - -* *Name* -+ -A human-readable and unique string describing the policy. A best practice is to use names that are closely related to your business and security requirements, so you can identify them more easily. -+ -* *Description* -+ -A string containing details about this policy. -+ -* *Target Claim* -+ -Specifies the name of the target claim in the token. For JSON-based claims, you can use dot notation for nesting and square brackets to access array fields by index. For example, contact.address[0].country. If the target claim references a JSON -object, the first path (for example, `contact`) should map to the attribute name holding the JSON object. -+ -* *Regex Pattern* -+ -Specifies the regex pattern. -+ -* *Logic* -+ -The <<_policy_logic, Logic>> of this policy to apply after the other conditions have been evaluated. diff --git a/authorization_services/topics/policy-role-policy-required-role.adoc b/authorization_services/topics/policy-role-policy-required-role.adoc deleted file mode 100644 index 3a4aecba7..000000000 --- a/authorization_services/topics/policy-role-policy-required-role.adoc +++ /dev/null @@ -1,13 +0,0 @@ -[[_policy_rbac_required]] -= Defining a role as required - -When creating a role-based policy, you can specify a specific role as `Required`. When you do that, the policy will grant access -only if the user requesting access has been granted *all* the *required* roles. Both realm and client roles can be configured as such. - -.Example of a required role -image:images/policy/create-role.png[alt="Example of a required role"] - -To specify a role as required, select the `Required` checkbox for the role you want to configure as required. - -Required roles can be useful when your policy defines multiple roles but only a subset of them are mandatory. In this case, you can combine realm and client roles to enable an -even more fine-grained role-based access control (RBAC) model for your application. For example, you can have policies specific for a client and require a specific client role associated with that client. Or you can enforce that access is granted only in the presence of a specific realm role. You can also combine both approaches within the same policy. diff --git a/authorization_services/topics/policy-role-policy.adoc b/authorization_services/topics/policy-role-policy.adoc deleted file mode 100644 index 06510d3be..000000000 --- a/authorization_services/topics/policy-role-policy.adoc +++ /dev/null @@ -1,40 +0,0 @@ -[[_policy_rbac]] -= Role-based policy - -You can use this type of policy to define conditions for your permissions where a set of one or more roles is permitted to access an object. - -By default, roles added to this policy are not specified as required and the policy will grant access if the user requesting access has been granted any of these roles. However, you can specify a specific role as <<_policy_rbac_required, required>> if you want to enforce a specific role. You can also combine required and non-required roles, regardless of whether they are realm or client roles. - -Role policies can be useful when you need more restricted role-based access control (RBAC), where specific roles must be enforced to grant access to an object. For instance, you can enforce that a user must consent to allowing a client application (which is acting on the user's behalf) to access the user's resources. You can use {project_name} Client Scope Mapping to enable consent pages or even enforce clients to explicitly provide a scope when obtaining access tokens from a {project_name} server. - -To create a new role-based policy, select *Role* from the policy type list. - -.Add Role Policy -image:images/policy/create-role.png[alt="Add Role Policy"] - -== Configuration - -* *Name* -+ -A human-readable and unique string describing the policy. A best practice is to use names that are closely related to your business and security requirements, so you -can identify them more easily. -+ -* *Description* -+ -A string containing details about this policy. -+ -* *Realm Roles* -+ -Specifies which *realm* roles are permitted by this policy. -+ -* *Client Roles* -+ -Specifies which *client* roles are permitted by this policy. To enable this field must first select a `Client`. -+ -* *Logic* -+ -The logic of this policy to apply after the other conditions have been evaluated. - -[role="_additional-resources"] -.Additional resources -* <<_policy_logic, Positive and negative logic>> diff --git a/authorization_services/topics/policy-time-policy.adoc b/authorization_services/topics/policy-time-policy.adoc deleted file mode 100644 index 6acd14ab9..000000000 --- a/authorization_services/topics/policy-time-policy.adoc +++ /dev/null @@ -1,52 +0,0 @@ -[[_policy_time]] -= Time-based policy - -You can use this type of policy to define time conditions for your permissions. - -To create a new time-based policy, select *Time* in the item list in the upper right corner of the policy listing. - -.Add Time Policy -image:images/policy/create-time.png[alt="Add Time Policy"] - -== Configuration - -* *Name* -+ -A human-readable and unique string describing the policy. A best practice is to use names that are closely related to your business and security requirements, so you -can identify them more easily. -+ -* *Description* -+ -A string containing details about this policy. -+ -* *Start time* -+ -Defines the time before which access must *not* be granted. Permission is granted only if the current date/time is later than or equal to this value. -* *Expire time* -+ -Defines the time after which access must *not* be granted. Permission is granted only if the current date/time is earlier than or equal to this value. Select *Repeat* to repeat access being granted on a specific *Day of Month*, *Month*, *Year*, *Hour* or *Minute*. - -* *Day of Month* -+ -Defines the day of month that access must be granted. You can also specify a range of dates. In this case, permission is granted only if the current day of the month is between or equal to the two values specified. -* *Month* -+ -Defines the month that access must be granted. You can also specify a range of months. In this case, permission is granted only if the current month is between or equal to the two values specified. -* *Year* -+ -Defines the year that access must be granted. You can also specify a range of years. In this case, permission is granted only if the current year is between or equal to the two values specified. -* *Hour* -+ -Defines the hour that access must be granted. You can also specify a range of hours. In this case, permission is granted only if current hour is between or equal to the two values specified. -* *Minute* -+ -Defines the minute that access must be granted. You can also specify a range of minutes. In this case, permission is granted only if the current minute is between or equal to the two values specified. -* *Logic* -+ -The logic of this policy to apply after the other conditions have been evaluated. - -Access is only granted if all conditions are satisfied. {project_name} will perform an _AND_ based on the outcome of each condition. - -[role="_additional-resources"] -.Additional resources -* <<_policy_logic, Positive and negative logic>> diff --git a/authorization_services/topics/policy-user-policy.adoc b/authorization_services/topics/policy-user-policy.adoc deleted file mode 100644 index ec4e5cc18..000000000 --- a/authorization_services/topics/policy-user-policy.adoc +++ /dev/null @@ -1,32 +0,0 @@ -[[_policy_user]] -= User-based policy - -You can use this type of policy to define conditions for your permissions where a set of one or more users is permitted to access an object. - -To create a new user-based policy, select *User* in the item list in the upper right corner of the policy listing. - -.Add a User Policy -image:images/policy/create-user.png[alt="Add User Policy"] - -== Configuration - -* *Name* -+ -A human-readable and unique string identifying the policy. A best practice is to use names that are closely related to your business and security requirements, so you -can identify them more easily. -+ -* *Description* -+ -A string containing details about this policy. -+ -* *Users* -+ -Specifies which users are given access by this policy. -+ -* *Logic* -+ -The logic of this policy to apply after the other conditions have been evaluated. - -[role="_additional-resources"] -.Additional resources -* <<_policy_logic, Positive and negative logic>> diff --git a/authorization_services/topics/resource-create.adoc b/authorization_services/topics/resource-create.adoc deleted file mode 100644 index 3c1e34a1c..000000000 --- a/authorization_services/topics/resource-create.adoc +++ /dev/null @@ -1,61 +0,0 @@ -[[_resource_create]] -= Creating resources - -Creating a resource is straightforward and generic. Your main concern is the granularity of the resources you create. In other words, resources can -be created to represent a set of one or more resources and the way you define them is crucial to managing permissions. - -To create a new resource, click *Create resource*. - -.Add resource -image:images/resource/create.png[alt="Add resource"] - -In {project_name}, a resource defines a small set of information that is common to different types of resources, such as: - -* *Name* -+ -A human-readable and unique string describing this resource. - -[[_resource_create_type]] -* *Type* -+ -A string uniquely identifying the type of a set of one or more resources. The type is a _string_ used to group different resource instances. -For example, the default type for the default resource that is automatically created is `urn:resource-server-name:resources:default` - -[[_resource_create_uri]] -* *URIS* -+ -URIS that provides the locations/addresses for the resource. For HTTP resources, the URIS -are usually the relative paths used to serve these resources. -+ -* *Scopes* -+ -One or more scopes to associate with the resource. - -== Resource attributes - -Resources may have attributes associated with them. These attributes can be used to provide additional information about -a resource and to provide additional information to policies when evaluating permissions associated with a resource. - -Each attribute is a key and value pair where the value can be a set of one or many strings. Multiple values can be defined for an attribute by separating each value with a comma. - - -== Typed resources - -The type field of a resource can be used to group different resources together, so they can be protected using a common set of permissions. - -== Resource owners - -Resources also have an owner. By default, resources are owned by the resource server. - -However, resources can also be associated with users, so you can create permissions based on the resource owner. For example, only the resource owner is allowed to delete or update a given resource. - -== Managing resources remotely - -Resource management is also exposed through the <<_service_protection_api, Protection API>> to allow resource servers to remotely manage their resources. - -When using the Protection API, resource servers can be implemented to manage resources owned by their users. In this case, you can -specify the user identifier to configure a resource as belonging to a specific user. - -[NOTE] -{project_name} provides resource servers complete control over their resources. In the future, we should be able to -allow users to control their own resources as well as approve authorization requests and manage permissions, especially when using the UMA protocol. diff --git a/authorization_services/topics/resource-overview.adoc b/authorization_services/topics/resource-overview.adoc deleted file mode 100644 index f52b1ddb6..000000000 --- a/authorization_services/topics/resource-overview.adoc +++ /dev/null @@ -1,5 +0,0 @@ -[[_resource_overview]] -= Managing resources and scopes - -Resource management is straightforward and generic. After creating a resource server, you can start creating the resources and scopes that you want to protect. -Resources and scopes can be managed by navigating to the *Resource* and *Authorization Scopes* tabs, respectively. diff --git a/authorization_services/topics/resource-server-create-client.adoc b/authorization_services/topics/resource-server-create-client.adoc deleted file mode 100644 index 6e296f4d8..000000000 --- a/authorization_services/topics/resource-server-create-client.adoc +++ /dev/null @@ -1,38 +0,0 @@ -[[_resource_server_create_client]] -= Creating a client application - -The first step to enable {project_name} Authorization Services is to create the client application that you want to turn into a resource server. - -.Procedure - -. Click *Clients*. -+ -.Clients -image:images/resource-server/client-list.png[Clients] - -ifeval::[{project_community}==true] -. On this page, click *Create client*. -endif::[] -ifeval::[{project_product}==true] -. On this page, click *Create*. -endif::[] -+ -.Add Client -image:images/resource-server/client-create.png[Add Client] - -. Type the `Client ID` of the client. For example, _my-resource-server_. -ifeval::[{project_community}==true] -. Click *Next*. -. Toggle *Client authentication* to ON. -. Click *Save*. -endif::[] -. Type the `Root URL` for your application. For example: -+ -``` -http://${host}:${port}/my-resource-server -``` - -. Click *Save*. The client is created and the client Settings page opens. A page similar to the following is displayed: -+ -.Client Settings -image:images/resource-server/client-enable-authz.png[alt="Client Settings"] diff --git a/authorization_services/topics/resource-server-default-config.adoc b/authorization_services/topics/resource-server-default-config.adoc deleted file mode 100644 index 66fcebb5a..000000000 --- a/authorization_services/topics/resource-server-default-config.adoc +++ /dev/null @@ -1,52 +0,0 @@ -[[_resource_server_default_config]] -= Default Configuration - -When you create a resource server, {project_name} creates a default configuration for your newly created resource server. - -The default configuration consists of: - -* A default protected resource representing all resources in your application. -* A policy that always grants access to the resources protected by this policy. -* A permission that governs access to all resources based on the default policy. - -The default protected resource is referred to as the *default resource* and you can view it if you navigate to the *Resources* tab. - -.Default resource -image:images/resource-server/default-resource.png[alt="Default resource"] - -This resource defines a `Type`, namely `urn:my-resource-server:resources:default` and a `URI` `/*`. Here, the `URI` field defines a -wildcard pattern that indicates to {project_name} that this resource represents all the paths in your application. In other words, -when enabling <<_enforcer_overview, policy enforcement>> for your application, all the permissions associated with the resource -will be examined before granting access. - -The `Type` mentioned previously defines a value that can be used to create <<_permission_typed_resource, typed resource permissions>> that must be applied -to the default resource or any other resource you create using the same type. - -The default policy is referred to as the *only from realm policy* and you can view it if you navigate to the *Policies* tab. - -.Default policy -image:images/resource-server/default-policy.png[alt="Default policy"] - -This policy is a <<_policy_js, JavaScript-based policy>> defining a condition that always grants access to the resources protected by this policy. If you click this policy you can see that it defines a rule as follows: - -```js -// by default, grants any permission associated with this policy -$evaluation.grant(); -``` - -Lastly, the default permission is referred to as the *default permission* and you can view it if you navigate to the *Permissions* tab. - -.Default Permission -image:images/resource-server/default-permission.png[alt="Default Permission"] - -This permission is a <<_permission_create_resource, resource-based permission>>, defining a set of one or more policies that are applied to all resources with a given type. - -== Changing the default configuration - -You can change the default configuration by removing the default resource, policy, or permission definitions and creating your own. - -The default resource is created with a **URI** that maps to any resource or path in your application using a **/*** pattern. Before creating your own resources, permissions and policies, make -sure the default configuration doesn't conflict with your own settings. - -[NOTE] -The default configuration defines a resource that maps to all paths in your application. If you are about to write permissions to your own resources, be sure to remove the *Default Resource* or change its ```URIS``` fields to a more specific paths in your application. Otherwise, the policy associated with the default resource (which by default always grants access) will allow {project_name} to grant access to any protected resource. diff --git a/authorization_services/topics/resource-server-enable-authorization.adoc b/authorization_services/topics/resource-server-enable-authorization.adoc deleted file mode 100644 index 3659e7bb2..000000000 --- a/authorization_services/topics/resource-server-enable-authorization.adoc +++ /dev/null @@ -1,75 +0,0 @@ -[[_resource_server_enable_authorization]] -= Enabling authorization services - -You can turn your OIDC client into a resource server and enable fine-grained authorization. - -.Procedure -. Toggle *Authorization Enabled* to *`On*. -. Click *Save*. -+ -.Enabling authorization services -image:images/resource-server/client-enable-authz.png[Enabling authorization services] -+ -A new Authorization tab is displayed for this client. Click the *Authorization* tab and a page similar to the following is displayed: -+ -.Resource server settings -image:images/resource-server/authz-settings.png[alt="Resource server settings"] - -The Authorization tab contains additional sub-tabs covering the different steps that you must follow to actually protect your application's resources. Each tab is covered separately by a specific topic in this documentation. But here is a quick description about each one: - -* *Settings* -+ -General settings for your resource server. For more details about this page see the xref:resource_server_settings[Resource Server Settings] section. - -* *Resource* -+ -From this page, you can manage your application's <<_resource_overview, resources>>. - -* *Authorization Scopes* -+ -From this page, you can manage <<_resource_overview, scopes>>. - -* *Policies* -+ -From this page, you can manage <<_policy_overview, authorization policies>> and define the conditions that must be met to grant a permission. - -* *Permissions* -+ -From this page, you can manage the <<_permission_overview, permissions>> for your protected resources and scopes by linking them with the policies you created. - -* *Evaluate* -+ -From this page, you can <<_policy_evaluation_overview, simulate authorization requests>> and view the result of the evaluation of the permissions and authorization policies you have defined. - -* *Export Settings* -+ -From this page, you can <<_resource_server_import_config, export>> the authorization settings to a JSON file. - -[[resource_server_settings]] -== Resource server settings - -On the Resource Server Settings page, you can configure the policy enforcement mode, allow remote resource management, and export the authorization configuration settings. - -* *Policy Enforcement Mode* -+ -Specifies how policies are enforced when processing authorization requests sent to the server. -+ -** *Enforcing* -+ -(default mode) Requests are denied by default even when there is no policy associated with a given resource. -+ -** *Permissive* -+ -Requests are allowed even when there is no policy associated with a given resource. -+ -** *Disabled* -+ -Disables the evaluation of all policies and allows access to all resources. -+ -* *Decision Strategy* -+ -This configurations changes how the policy evaluation engine decides whether or not a resource or scope should be granted based on the outcome from all evaluated permissions. `Affirmative` means that at least one permission must evaluate to a positive decision in order grant access to a resource and its scopes. `Unanimous` means that all permissions must evaluate to a positive decision in order for the final decision to be also positive. As an example, if two permissions for a same resource or scope are in conflict (one of them is granting access and the other is denying access), the permission to the resource or scope will be granted if the chosen strategy is `Affirmative`. Otherwise, a single deny from any permission will also deny access to the resource or scope. -+ -* *Remote Resource Management* -+ -Specifies whether resources can be managed remotely by the resource server. If false, resources can be managed only from the administration console. diff --git a/authorization_services/topics/resource-server-import-config.adoc b/authorization_services/topics/resource-server-import-config.adoc deleted file mode 100644 index 085ab435d..000000000 --- a/authorization_services/topics/resource-server-import-config.adoc +++ /dev/null @@ -1,34 +0,0 @@ -[[_resource_server_import_config]] -= Export and import authorization configuration - -The configuration settings for a resource server (or client) can be exported and downloaded. You can also import an existing configuration file for a resource server. Importing and exporting a configuration file is helpful when you want to create an initial configuration for a resource server or to update an existing configuration. The configuration file contains definitions for: - -* Protected resources and scopes -* Policies -* Permissions - -== Exporting a configuration file - -.Procedure - -. Click *Clients* in the menu. -. Click the client you created as a resource server. -. Click the *Export* tab. -+ -.Export Settings -image:images/resource-server/authz-export.png[Export Settings] - -The configuration file is exported in JSON format and displayed in a text area, from which you can copy and paste. You can also click *Download* to download the configuration file and save it. - -== Importing a configuration file - -You can import a configuration file for a resource server. - -.Procedure - -. Navigate to the *Resource Server Settings* page. -+ -.Import Settings -image:images/resource-server/authz-settings.png[Import Settings] - -. Click *Import* and choose a file containing the configuration that you want to import. diff --git a/authorization_services/topics/resource-server-overview.adoc b/authorization_services/topics/resource-server-overview.adoc deleted file mode 100644 index 52ef538b9..000000000 --- a/authorization_services/topics/resource-server-overview.adoc +++ /dev/null @@ -1,8 +0,0 @@ -[[_resource_server_overview]] -= Managing resource servers - -According to the OAuth2 specification, a resource server is a server hosting the protected resources and capable of accepting and responding to protected resource requests. - -In {project_name}, resource servers are provided with a rich platform for enabling fine-grained authorization for their protected resources, where authorization decisions can be made based on different access control mechanisms. - -Any client application can be configured to support fine-grained permissions. In doing so, you are conceptually turning the client application into a resource server. diff --git a/authorization_services/topics/resource-view.adoc b/authorization_services/topics/resource-view.adoc deleted file mode 100644 index 3cf8433c8..000000000 --- a/authorization_services/topics/resource-view.adoc +++ /dev/null @@ -1,20 +0,0 @@ -[[_resource_view]] -= Viewing resources - -On the *Resource* page, you see a list of the resources associated with a resource server. - -.Resources -image:images/resource/view.png[alt="Resources"] - -The resource list provides information about the protected resources, such as: - -* Type -* URIS -* Owner -* Associated scopes, if any -* Associated permissions - -From this list, you can also directly create a permission by clicking *Create Permission* for the resource for which you want to create the permission. - -[NOTE] -Before creating permissions for your resources, be sure you have already defined the policies that you want to associate with the permission. diff --git a/authorization_services/topics/service-authorization-discovery-document.adoc b/authorization_services/topics/service-authorization-discovery-document.adoc deleted file mode 100644 index ec96c73a9..000000000 --- a/authorization_services/topics/service-authorization-discovery-document.adoc +++ /dev/null @@ -1,55 +0,0 @@ -[[_service_authorization_api]] -= Discovering authorization services endpoints and metadata - -{project_name} provides a discovery document from which clients can obtain all necessary information to interact with -{project_name} Authorization Services, including endpoint locations and capabilities. - -The discovery document can be obtained from: - -[source,bash,subs="attributes+"] ----- -curl -X GET \ - http://${host}:${port}{kc_realms_path}/${realm}/.well-known/uma2-configuration ----- - -Where `${host}:${port}` is the hostname (or IP address) and port where {project_name} is running and `${realm}` is the name of -a realm in {project_name}. - -As a result, you should get a response as follows: - -[source,json,subs="attributes+"] ----- -{ - - // some claims are expected here - - // these are the main claims in the discovery document about Authorization Services endpoints location - "token_endpoint": "http://${host}:${port}{kc_realms_path}/${realm}/protocol/openid-connect/token", - "token_introspection_endpoint": "http://${host}:${port}{kc_realms_path}/${realm}/protocol/openid-connect/token/introspect", - "resource_registration_endpoint": "http://${host}:${port}{kc_realms_path}/${realm}/authz/protection/resource_set", - "permission_endpoint": "http://${host}:${port}{kc_realms_path}/${realm}/authz/protection/permission", - "policy_endpoint": "http://${host}:${port}{kc_realms_path}/${realm}/authz/protection/uma-policy" -} ----- - -Each of these endpoints expose a specific set of capabilities: - -* **token_endpoint** -+ -A OAuth2-compliant Token Endpoint that supports the `urn:ietf:params:oauth:grant-type:uma-ticket` grant type. Through this -endpoint clients can send authorization requests and obtain an RPT with all permissions granted by {project_name}. -+ -* **token_introspection_endpoint** -+ -A OAuth2-compliant Token Introspection Endpoint which clients can use to query the server to determine the active state of an RPT -and to determine any other information associated with the token, such as the permissions granted by {project_name}. -+ -* **resource_registration_endpoint** -+ -A UMA-compliant Resource Registration Endpoint which resource servers can use to manage their protected resources and scopes. This endpoint provides -operations create, read, update and delete resources and scopes in {project_name}. -+ -* **permission_endpoint** -+ -A UMA-compliant Permission Endpoint which resource servers can use to manage permission tickets. This endpoint provides -operations create, read, update, and delete permission tickets in {project_name}. diff --git a/authorization_services/topics/service-authorization-obtaining-permission-authentication.adoc b/authorization_services/topics/service-authorization-obtaining-permission-authentication.adoc deleted file mode 100644 index cd3885644..000000000 --- a/authorization_services/topics/service-authorization-obtaining-permission-authentication.adoc +++ /dev/null @@ -1,37 +0,0 @@ -[[_authentication_methods]] -= Client authentication methods - -Clients need to authenticate to the token endpoint in order to obtain an RPT. When using the `urn:ietf:params:oauth:grant-type:uma-ticket` -grant type, clients can use any of these authentication methods: - -* *Bearer Token* -+ -Clients should send an access token as a Bearer credential in an HTTP Authorization header to the token endpoint. -+ -.Example: an authorization request using an access token to authenticate to the token endpoint -[source,bash,subs="attributes+"] ----- -curl -X POST \ - http://${host}:${port}{kc_realms_path}/${realm}/protocol/openid-connect/token \ - -H "Authorization: Bearer ${access_token}" \ - --data "grant_type=urn:ietf:params:oauth:grant-type:uma-ticket" ----- -+ -This method is especially useful when the client is acting on behalf of a user. -In this case, the bearer token is an access token previously issued by {project_name} to some client acting on behalf -of a user (or on behalf of itself). Permissions will be evaluated considering the access context represented by the access token. -For instance, if the access token was issued to Client A acting on behalf of User A, permissions will be granted depending on -the resources and scopes to which User A has access. - -* *Client Credentials* -+ -Clients can use any of the client authentication methods supported by {project_name}. For instance, client_id/client_secret or JWT. -+ -.Example: an authorization request using client id and client secret to authenticate to the token endpoint -[source,bash,subs="attributes+"] ----- -curl -X POST \ - http://${host}:${port}{kc_realms_path}/${realm}/protocol/openid-connect/token \ - -H "Authorization: Basic cGhvdGg6L7Jl13RmfWgtkk==pOnNlY3JldA==" \ - --data "grant_type=urn:ietf:params:oauth:grant-type:uma-ticket" ----- diff --git a/authorization_services/topics/service-authorization-obtaining-permission-uma.adoc b/authorization_services/topics/service-authorization-obtaining-permission-uma.adoc deleted file mode 100644 index 334bcf125..000000000 --- a/authorization_services/topics/service-authorization-obtaining-permission-uma.adoc +++ /dev/null @@ -1,42 +0,0 @@ -[[_service_user_managed_access]] -= User-managed access - -{project_name} Authorization Services is based on User-Managed Access or UMA for short. UMA is a specification that -enhances OAuth2 capabilities in the following ways: - -* *Privacy* -+ -Nowadays, user privacy is becoming a huge concern, as more and more data and devices are available and connected to the cloud. With -UMA and {project_name}, resource servers can enhance their capabilities in order to improve how their resources are protected in respect -to user privacy where permissions are granted based on policies defined by the user. -+ -* *Party-to-Party Authorization* -+ -Resource owners (e.g.: regular end-users) can manage access to their resources and authorize other parties (e.g: regular end-users) -to access these resources. This is different than OAuth2 where consent is given to a client application acting on behalf of a user, with UMA -resource owners are allowed to consent access to other users, in a completely asynchronous manner. -+ -* *Resource Sharing* -+ -Resource owners are allowed to manage permissions to their resources and decide who can access a particular resource and how. -{project_name} can then act as a sharing management service from which resource owners can manage their resources. - -{project_name} is a UMA 2.0 compliant authorization server that provides most UMA capabilities. - -As an example, consider a user Alice (resource owner) using an Internet Banking Service (resource server) to manage her Bank Account (resource). One day, Alice decides -to open her bank account to Bob (requesting party), an accounting professional. However, Bob should only have access to view (scope) Alice's account. - -As a resource server, the Internet Banking Service must be able to protect Alice's Bank Account. For that, it relies on {project_name} -Resource Registration Endpoint to create a resource in the server representing Alice's Bank Account. - -At this moment, if Bob tries to access Alice's Bank Account, access will be denied. The Internet Banking Service defines a few default -policies for banking accounts. One of them is that only the owner, in this case Alice, is allowed to access her bank account. - -However, Internet Banking Service in respect to Alice's privacy also allows her to change specific policies for the banking account. One of these -policies that she can change is to define which people are allowed to view her bank account. For that, Internet Banking Service relies on {project_name} -to provide to Alice a space where she can select individuals and the operations (or data) they are allowed to access. At any time, Alice -can revoke access or grant additional permissions to Bob. - - - - diff --git a/authorization_services/topics/service-authorization-obtaining-permission.adoc b/authorization_services/topics/service-authorization-obtaining-permission.adoc deleted file mode 100644 index 6e98e8993..000000000 --- a/authorization_services/topics/service-authorization-obtaining-permission.adoc +++ /dev/null @@ -1,158 +0,0 @@ -[[_service_obtaining_permissions]] -= Obtaining permissions - -To obtain permissions from {project_name} you send an authorization request to the token endpoint. As a result, {project_name} will -evaluate all policies associated with the resource(s) and scope(s) being requested and issue an RPT with all permissions -granted by the server. - -Clients are allowed to send authorization requests to the token endpoint using the following parameters: - -* *grant_type* -+ -This parameter is *required*. Must be `urn:ietf:params:oauth:grant-type:uma-ticket`. -+ -* **ticket** -+ -This parameter is *optional*. The most recent permission ticket received by the client as part of the UMA authorization process. -+ -* **claim_token** -+ -This parameter is *optional*. A string representing additional claims that should be considered by the server when evaluating -permissions for the resource(s) and scope(s) being requested. This parameter allows clients to push claims to {project_name}. For more details about all supported token formats see `claim_token_format` parameter. -+ -* **claim_token_format** -+ -This parameter is *optional*. A string indicating the format of the token specified in the `claim_token` parameter. {project_name} supports two token -formats: `urn:ietf:params:oauth:token-type:jwt` and `https://openid.net/specs/openid-connect-core-1_0.html#IDToken`. The `urn:ietf:params:oauth:token-type:jwt` format -indicates that the `claim_token` parameter references an access token. The `https://openid.net/specs/openid-connect-core-1_0.html#IDToken` indicates that the -`claim_token` parameter references an OpenID Connect ID Token. -+ -* **rpt** -+ -This parameter is *optional*. A previously issued RPT which permissions should also be evaluated and added in a new one. This parameter -allows clients in possession of an RPT to perform incremental authorization where permissions are added on demand. -+ -* **permission** -+ -This parameter is *optional*. A string representing a set of one or more resources and scopes the client is seeking access. This parameter can be defined multiple times -in order to request permission for multiple resource and scopes. This parameter is an extension to `urn:ietf:params:oauth:grant-type:uma-ticket` grant type in order to allow clients to send authorization requests without a -permission ticket. The format of the string must be: `RESOURCE_ID#SCOPE_ID`. For instance: `Resource A#Scope A`, `Resource A#Scope A, Scope B, Scope C`, `Resource A`, `#Scope A`. -+ -* **audience** -+ -This parameter is *optional*. The client identifier of the resource server to which the client is seeking access. This parameter is mandatory -in case the `permission` parameter is defined. It serves as a hint to {project_name} to indicate the context in which permissions should be evaluated. -+ -* **response_include_resource_name** -+ -This parameter is *optional*. A boolean value indicating to the server whether resource names should be included in the RPT's permissions. If false, only the resource -identifier is included. -+ -* **response_permissions_limit** -+ -This parameter is *optional*. An integer N that defines a limit for the amount of permissions an RPT can have. When used together with -`rpt` parameter, only the last N requested permissions will be kept in the RPT. -+ -* **submit_request** -+ -This parameter is *optional*. A boolean value indicating whether the server should create permission requests to the resources and scopes referenced by a permission ticket. -This parameter only has effect if used together with the `ticket` parameter as part of a UMA authorization process. -+ -* **response_mode** -+ -This parameter is *optional*. A string value indicating how the server should respond to authorization requests. This parameter is specially useful when -you are mainly interested in either the overall decision or the permissions granted by the server, instead of a standard OAuth2 response. Possible values are: -+ -*** `decision` -+ -Indicates that responses from the server should only represent the overall decision by returning a JSON with the following format: -+ -```json -{ - 'result': true -} -``` -+ -If the authorization request does not map to any permission, a `403` HTTP status code is returned instead. -+ -*** `permissions` -+ -Indicates that responses from the server should contain any permission granted by the server by returning a JSON with the following format: -+ -```json -[ - { - 'rsid': 'My Resource' - 'scopes': ['view', 'update'] - }, - - ... -] -``` -+ -If the authorization request does not map to any permission, a `403` HTTP status code is returned instead. - -Example of an authorization request when a client is seeking access to two resources protected by a resource server. - -[source,bash,subs="attributes+"] ----- -curl -X POST \ - http://${host}:${port}{kc_realms_path}/${realm}/protocol/openid-connect/token \ - -H "Authorization: Bearer ${access_token}" \ - --data "grant_type=urn:ietf:params:oauth:grant-type:uma-ticket" \ - --data "audience={resource_server_client_id}" \ - --data "permission=Resource A#Scope A" \ - --data "permission=Resource B#Scope B" ----- - -Example of an authorization request when a client is seeking access to any resource and scope protected by a resource server. -NOTE: This will not evaluate the permissions for all resources. Instead, the permissions for resources owned by the resource server, owned by the requesting user, -and explicitly granted to the requesting user by other owners are evaluated. - -[source,bash,subs="attributes+"] ----- -curl -X POST \ - http://${host}:${port}{kc_realms_path}/${realm}/protocol/openid-connect/token \ - -H "Authorization: Bearer ${access_token}" \ - --data "grant_type=urn:ietf:params:oauth:grant-type:uma-ticket" \ - --data "audience={resource_server_client_id}" ----- - -Example of an authorization request when a client is seeking access to a UMA protected resource after receiving a permission ticket from -the resource server as part of the authorization process: - -[source,bash,subs="attributes+"] ----- -curl -X POST \ - http://${host}:${port}{kc_realms_path}/${realm}/protocol/openid-connect/token \ - -H "Authorization: Bearer ${access_token}" \ - --data "grant_type=urn:ietf:params:oauth:grant-type:uma-ticket" \ - --data "ticket=${permission_ticket} ----- - -If {project_name} assessment process results in issuance of permissions, it issues the RPT with which it has associated -the permissions: - -.{project_name} responds to the client with the RPT -```bash -HTTP/1.1 200 OK -Content-Type: application/json -... -{ - "access_token": "${rpt}", -} -``` - -The response from the server is just like any other response from the token endpoint when using some other grant type. The RPT can be obtained from -the `access_token` response parameter. If the client is not authorized, {project_name} responds with a `403` HTTP status code: - -.{project_name} denies the authorization request -```bash -HTTP/1.1 403 Forbidden -Content-Type: application/json -... -{ - "error": "access_denied", - "error_description": "request_denied" -} -``` diff --git a/authorization_services/topics/service-authorization-pushing-claims.adoc b/authorization_services/topics/service-authorization-pushing-claims.adoc deleted file mode 100644 index a943f938a..000000000 --- a/authorization_services/topics/service-authorization-pushing-claims.adoc +++ /dev/null @@ -1,34 +0,0 @@ -[[_service_pushing_claims]] -= Pushing claims - -When obtaining permissions from the server you can push arbitrary claims in order to have these -claims available to your policies when evaluating permissions. - -If you are obtaining permissions from the server *without* using a permission ticket (UMA flow), you can send -an authorization request to the token endpoint as follows: - -[source,bash,subs="attributes+"] ----- -curl -X POST \ - http://${host}:${port}{kc_realms_path}/${realm}/protocol/openid-connect/token \ - --data "grant_type=urn:ietf:params:oauth:grant-type:uma-ticket" \ - --data "claim_token=ewogICAib3JnYW5pemF0aW9uIjogWyJhY21lIl0KfQ==" \ - --data "claim_token_format=urn:ietf:params:oauth:token-type:jwt" \ - --data "client_id={resource_server_client_id}" \ - --data "client_secret={resource_server_client_secret}" \ - --data "audience={resource_server_client_id}" ----- - -The `claim_token` parameter expects a BASE64 encoded JSON with a format similar to the example below: - -```json -{ - "organization" : ["acme"] -} -``` - -The format expects one or more claims where the value for each claim must be an array of strings. - -== Pushing claims Using UMA - -For more details about how to push claims when using UMA and permission tickets, please take a look at <<_service_protection_permission_api_papi, Permission API>> diff --git a/authorization_services/topics/service-authorization-uma-account-my-resources.adoc b/authorization_services/topics/service-authorization-uma-account-my-resources.adoc deleted file mode 100644 index 2f10032f4..000000000 --- a/authorization_services/topics/service-authorization-uma-account-my-resources.adoc +++ /dev/null @@ -1,42 +0,0 @@ -[[_service_authorization_my_resources]] -= Managing access to users resources - -Users can manage access to their resources using the {project_name} Account Console. To enable -this functionality, you must first enable User-Managed Access for your realm. - -.Procedure - -. Log into the Admin Console. - -. Click *Realm Settings* in the menu. - -. Toggle *User-Managed Access* to *ON*. - -. Click the user name at the top right of the Admin Console and select *Manage Account*. -+ -image:images/service/account-my-resource.png[alt="My Resources"] - -. Click *My Resources* in the menu option. A page displays with the following options. -* Manage *My resources* -+ -This section contains a list of all resources owned by the user. Users can click on a resource for more details -and share the resource with others. -When there is a permission requests awaiting approval an icon is put next to the name of the resource. -These requests are connected to the parties (users) requesting access to a particular resource. -Users are allowed to approve or deny these requests. You can do so by clicking the icon -+ -image:images/service/account-my-resource-detail.png[alt="Resource Detail"] -+ -* Manage *Resources shared with me* -+ -This section contains a list of all resources shared with the user. -+ - -* Manage *People with access to this resource* -+ -This section contains a list of people with access to this resource. Users are allowed to revoke access by clicking -on the `Revoke` button or by removing a specific `Permission`. -+ -* Share the resource with others -+ -By typing the username or e-mail of another user, the user is able to share the resource and select the permissions he wants to grant access. diff --git a/authorization_services/topics/service-authorization-uma-authz-process.adoc b/authorization_services/topics/service-authorization-uma-authz-process.adoc deleted file mode 100644 index 7991c0852..000000000 --- a/authorization_services/topics/service-authorization-uma-authz-process.adoc +++ /dev/null @@ -1,68 +0,0 @@ -[[_service_uma_authorization_process]] -= Authorization process - -In UMA, the authorization process starts when a client tries to access a UMA protected resource server. - -A UMA protected resource server expects a bearer token in the request where the token is an RPT. When a client requests -a resource at the resource server without an RPT: - -.Client requests a protected resource without sending an RPT -```bash -curl -X GET \ - http://${host}:${port}/my-resource-server/resource/1bfdfe78-a4e1-4c2d-b142-fc92b75b986f -``` - -The resource server sends a response back to the client with a permission `ticket` and a `as_uri` parameter with the location -of a {project_name} server to where the ticket should be sent in order to obtain an RPT. - -.Resource server responds with a permission ticket -[source,bash,subs="attributes+"] ----- -HTTP/1.1 401 Unauthorized -WWW-Authenticate: UMA realm="${realm}", - as_uri="https://${host}:${port}{kc_realms_path}/${realm}", - ticket="016f84e8-f9b9-11e0-bd6f-0021cc6004de" ----- - -The permission ticket is a special type of token issued by {project_name} Permission API. They represent the permissions being requested (e.g.: resources and scopes) -as well any other information associated with the request. Only resource servers are allowed to create those tokens. - -Now that the client has a permission ticket and also the location of a {project_name} server, the client can use the discovery document -to obtain the location of the token endpoint and send an authorization request. - -.Client sends an authorization request to the token endpoint to obtain an RPT -[source,bash,subs="attributes+"] ----- -curl -X POST \ - http://${host}:${port}{kc_realms_path}/${realm}/protocol/openid-connect/token \ - -H "Authorization: Bearer ${access_token}" \ - --data "grant_type=urn:ietf:params:oauth:grant-type:uma-ticket" \ - --data "ticket=${permission_ticket} ----- - -If {project_name} assessment process results in issuance of permissions, it issues the RPT with which it has associated -the permissions: - -.{project_name} responds to the client with the RPT -```bash -HTTP/1.1 200 OK -Content-Type: application/json -... -{ - "access_token": "${rpt}", -} -``` - -The response from the server is just like any other response from the token endpoint when using some other grant type. The RPT can be obtained from -the `access_token` response parameter. In case the client is not authorized to have permissions {project_name} responds with a `403` HTTP status code: - -.{project_name} denies the authorization request -```bash -HTTP/1.1 403 Forbidden -Content-Type: application/json -... -{ - "error": "access_denied", - "error_description": "request_denied" -} -``` diff --git a/authorization_services/topics/service-authorization-uma-submiting-permission-requests.adoc b/authorization_services/topics/service-authorization-uma-submiting-permission-requests.adoc deleted file mode 100644 index ebc1e53a5..000000000 --- a/authorization_services/topics/service-authorization-uma-submiting-permission-requests.adoc +++ /dev/null @@ -1,39 +0,0 @@ -[[_service_authorization_aat]] -= Submitting permission requests - -As part of the authorization process, clients need first to obtain a permission ticket from a UMA protected resource server in order -to exchange it with an RPT at the {project_name} Token Endpoint. - -By default, {project_name} responds with a `403` HTTP status code and a `request_denied` error in case the client can not be issued with an RPT. - -.{project_name} denies the authorization request -```bash -HTTP/1.1 403 Forbidden -Content-Type: application/json -... -{ - "error": "access_denied", - "error_description": "request_denied" -} -``` - -Such response implies that {project_name} could not issue an RPT with the permissions represented by a permission ticket. - -In some situations, client applications may want to start an asynchronous authorization flow and let the owner of the resources -being requested decide whether or not access should be granted. For that, clients can use the `submit_request` request parameter along -with an authorization request to the token endpoint: - -[source,bash,subs="attributes+"] ----- -curl -X POST \ - http://${host}:${port}{kc_realms_path}/${realm}/protocol/openid-connect/token \ - -H "Authorization: Bearer ${access_token}" \ - --data "grant_type=urn:ietf:params:oauth:grant-type:uma-ticket" \ - --data "ticket=${permission_ticket} \ - --data "submit_request=true" ----- - -When using the `submit_request` parameter, {project_name} will persist a permission request for each resource to which access was denied. -Once created, resource owners can check their account and manage their permissions requests. - -You can think about this functionality as a `Request Access` button in your application, where users can ask other users for access to their resources. \ No newline at end of file diff --git a/authorization_services/topics/service-client-api.adoc b/authorization_services/topics/service-client-api.adoc deleted file mode 100644 index 7d3b1d81b..000000000 --- a/authorization_services/topics/service-client-api.adoc +++ /dev/null @@ -1,158 +0,0 @@ -[[_service_client_api]] -= Authorization client java API - -Depending on your requirements, a resource server should be able to manage resources remotely or even check for permissions programmatically. -If you are using Java, you can access the {project_name} Authorization Services using the Authorization Client API. - -It is targeted for resource servers that want to access the different endpoints provided by the server such as the Token Endpoint, Resource, and Permission management endpoints. - -== Maven dependency - -```xml - - - org.keycloak - keycloak-authz-client - ${KEYCLOAK_VERSION} - - -``` - -== Configuration - -The client configuration is defined in a ``keycloak.json`` file as follows: - -[source,json,subs="attributes+"] ----- -{ - "realm": "hello-world-authz", - "auth-server-url" : "http://localhost:8080{kc_base_path}", - "resource" : "hello-world-authz-service", - "credentials": { - "secret": "secret" - } -} ----- - -* *realm* (required) -+ -The name of the realm. - -* *auth-server-url* (required) -+ -The base URL of the {project_name} server. All other {project_name} pages and REST service endpoints are derived from this. It is usually in the form https://host:port{kc_base_path}. - -* *resource* (required) -+ -The client-id of the application. Each application has a client-id that is used to identify the application. - -* *credentials* (required) -+ -Specifies the credentials of the application. This is an object notation where the key is the credential type and the value is the value of the credential type. - -The configuration file is usually located in your application's classpath, the default location from where the client is going to try to find a ```keycloak.json``` file. - -== Creating the authorization client - -Considering you have a ```keycloak.json``` file in your classpath, you can create a new ```AuthzClient``` instance as follows: - -```java - // create a new instance based on the configuration defined in a keycloak.json located in your classpath - AuthzClient authzClient = AuthzClient.create(); -``` - -== Obtaining user entitlements - -Here is an example illustrating how to obtain user entitlements: - -```java -// create a new instance based on the configuration defined in keycloak.json -AuthzClient authzClient = AuthzClient.create(); - -// create an authorization request -AuthorizationRequest request = new AuthorizationRequest(); - -// send the entitlement request to the server in order to -// obtain an RPT with all permissions granted to the user -AuthorizationResponse response = authzClient.authorization("alice", "alice").authorize(request); -String rpt = response.getToken(); - -System.out.println("You got an RPT: " + rpt); - -// now you can use the RPT to access protected resources on the resource server -``` - -Here is an example illustrating how to obtain user entitlements for a set of one or more resources: - -```java -// create a new instance based on the configuration defined in keycloak.json -AuthzClient authzClient = AuthzClient.create(); - -// create an authorization request -AuthorizationRequest request = new AuthorizationRequest(); - -// add permissions to the request based on the resources and scopes you want to check access -request.addPermission("Default Resource"); - -// send the entitlement request to the server in order to -// obtain an RPT with permissions for a single resource -AuthorizationResponse response = authzClient.authorization("alice", "alice").authorize(request); -String rpt = response.getToken(); - -System.out.println("You got an RPT: " + rpt); - -// now you can use the RPT to access protected resources on the resource server -``` - -== Creating a resource using the protection API - -```java -// create a new instance based on the configuration defined in keycloak.json -AuthzClient authzClient = AuthzClient.create(); - -// create a new resource representation with the information we want -ResourceRepresentation newResource = new ResourceRepresentation(); - -newResource.setName("New Resource"); -newResource.setType("urn:hello-world-authz:resources:example"); - -newResource.addScope(new ScopeRepresentation("urn:hello-world-authz:scopes:view")); - -ProtectedResource resourceClient = authzClient.protection().resource(); -ResourceRepresentation existingResource = resourceClient.findByName(newResource.getName()); - -if (existingResource != null) { - resourceClient.delete(existingResource.getId()); -} - -// create the resource on the server -ResourceRepresentation response = resourceClient.create(newResource); -String resourceId = response.getId(); - -// query the resource using its newly generated id -ResourceRepresentation resource = resourceClient.findById(resourceId); - -System.out.println(resource); -``` - -== Introspecting an RPT - -```java -// create a new instance based on the configuration defined in keycloak.json -AuthzClient authzClient = AuthzClient.create(); - -// send the authorization request to the server in order to -// obtain an RPT with all permissions granted to the user -AuthorizationResponse response = authzClient.authorization("alice", "alice").authorize(); -String rpt = response.getToken(); - -// introspect the token -TokenIntrospectionResponse requestingPartyToken = authzClient.protection().introspectRequestingPartyToken(rpt); - -System.out.println("Token status is: " + requestingPartyToken.getActive()); -System.out.println("Permissions granted by the server: "); - -for (Permission granted : requestingPartyToken.getPermissions()) { - System.out.println(granted); -} -``` diff --git a/authorization_services/topics/service-overview.adoc b/authorization_services/topics/service-overview.adoc deleted file mode 100644 index 55dc27d78..000000000 --- a/authorization_services/topics/service-overview.adoc +++ /dev/null @@ -1,14 +0,0 @@ -[[_service_overview]] -= Authorization services - -{project_name} Authorization Services are built on top of well-known standards such as the OAuth2 and User-Managed Access specifications. - -OAuth2 clients (such as front end applications) can obtain access tokens from the server using the token endpoint and use -these same tokens to access resources protected by a resource server (such as back end services). In the same way, -{project_name} Authorization Services provide extensions to OAuth2 to allow access tokens to be issued based on the processing -of all policies associated with the resource(s) or scope(s) being requested. This means that resource servers can enforce access -to their protected resources based on the permissions granted by the server and held by an access token. In {project_name} Authorization Services -the access token with permissions is called a Requesting Party Token or RPT for short. - -In addition to the issuance of RPTs, {project_name} Authorization Services also provides a set of RESTful endpoints that allow resources servers to manage their protected -resources, scopes, permissions and policies, helping developers to extend or integrate these capabilities into their applications in order to support fine-grained authorization. \ No newline at end of file diff --git a/authorization_services/topics/service-protection-permission-api-papi.adoc b/authorization_services/topics/service-protection-permission-api-papi.adoc deleted file mode 100644 index 58155d19e..000000000 --- a/authorization_services/topics/service-protection-permission-api-papi.adoc +++ /dev/null @@ -1,140 +0,0 @@ -[[_service_protection_permission_api_papi]] -= Managing permission requests - -Resource servers using the UMA protocol can use a specific endpoint to manage permission requests. This endpoint provides a UMA-compliant flow for registering permission requests and obtaining a permission ticket. - -[source,subs="attributes+"] ----- -http://${host}:${port}{kc_realms_path}/${realm_name}/authz/protection/permission ----- - -A <<_overview_terminology_permission_ticket, permission ticket>> is a special security token type representing a permission request. Per the UMA specification, a permission ticket is: - -`A correlation handle that is conveyed from an authorization server to a resource server, from a resource server to a client, and ultimately from a client back to an authorization server, to enable the authorization server to assess the correct policies to apply to a request for authorization data.` - -In most cases, you won't need to deal with this endpoint directly. {project_name} provides a <<_enforcer_overview, policy enforcer>> that enables UMA for your -resource server so it can obtain a permission ticket from the authorization server, return this ticket to client application, and enforce authorization decisions based on a final requesting party token (RPT). - -The process of obtaining permission tickets from {project_name} is performed by resource servers and not regular client applications, -where permission tickets are obtained when a client tries to access a protected resource without the necessary grants to access the resource. The issuance of -permission tickets is an important aspects when using UMA as it allows resource servers to: - -* Abstract from clients the data associated with the resources protected by the resource server -* Register in the {project_name} authorization requests which in turn can be used later in workflows to grant access based on the resource's owner consent -* Decouple resource servers from authorization servers and allow them to protect and manage their resources using different authorization servers - -Client wise, a permission ticket has also important aspects that its worthy to highlight: - -* Clients don't need to know about how authorization data is associated with protected resources. A permission ticket is completely opaque to clients. -* Clients can have access to resources on different resource servers and protected by different authorization servers - -These are just some of the benefits brought by UMA where other aspects of UMA are strongly based on permission tickets, specially regarding -privacy and user controlled access to their resources. - -== Creating permission ticket - -To create a permission ticket, send an HTTP POST request as follows: - -[source,bash,subs="attributes+"] ----- -curl -X POST \ - http://${host}:${port}{kc_realms_path}/${realm_name}/authz/protection/permission \ - -H 'Authorization: Bearer '$pat \ - -H 'Content-Type: application/json' \ - -d '[ - { - "resource_id": "{resource_id}", - "resource_scopes": [ - "view" - ] - } -]' ----- - -When creating tickets you can also push arbitrary claims and associate these claims with the ticket: - -[source,bash,subs="attributes+"] ----- -curl -X POST \ - http://${host}:${port}{kc_realms_path}/${realm_name}/authz/protection/permission \ - -H 'Authorization: Bearer '$pat \ - -H 'Content-Type: application/json' \ - -d '[ - { - "resource_id": "{resource_id}", - "resource_scopes": [ - "view" - ], - "claims": { - "organization": ["acme"] - } - } -]' ----- - -Where these claims will be available to your policies when evaluating permissions for the resource and scope(s) associated -with the permission ticket. - -== Other non UMA-compliant endpoints - -=== Creating permission ticket - -To grant permissions for a specific resource with id {resource_id} to a user with id {user_id}, as an owner of the resource send an HTTP POST request as follows: - -[source,bash,subs="attributes+"] ----- -curl -X POST \ - http://${host}:${port}{kc_realms_path}/${realm_name}/authz/protection/permission/ticket \ - -H 'Authorization: Bearer '$access_token \ - -H 'Content-Type: application/json' \ - -d '{ - "resource": "{resource_id}", - "requester": "{user_id}", - "granted": true, - "scopeName": "view" - }' ----- - -=== Getting permission tickets - -[source,bash,subs="attributes+"] ----- -curl http://${host}:${port}{kc_realms_path}/${realm_name}/authz/protection/permission/ticket \ - -H 'Authorization: Bearer '$access_token ----- - -You can use any of these query parameters: - -* `scopeId` -* `resourceId` -* `owner` -* `requester` -* `granted` -* `returnNames` -* `first` -* `max` - -=== Updating permission ticket - -[source,bash,subs="attributes+"] ----- -curl -X PUT \ - http://${host}:${port}{kc_realms_path}/${realm_name}/authz/protection/permission/ticket \ - -H 'Authorization: Bearer '$access_token \ - -H 'Content-Type: application/json' \ - -d '{ - "id": "{ticket_id}" - "resource": "{resource_id}", - "requester": "{user_id}", - "granted": false, - "scopeName": "view" - }' ----- - -=== Deleting permission ticket - -[source,bash,subs="attributes+"] ----- -curl -X DELETE http://${host}:${port}{kc_realms_path}/${realm_name}/authz/protection/permission/ticket/{ticket_id} \ - -H 'Authorization: Bearer '$access_token ----- \ No newline at end of file diff --git a/authorization_services/topics/service-protection-policy-api.adoc b/authorization_services/topics/service-protection-policy-api.adoc deleted file mode 100644 index 91902a059..000000000 --- a/authorization_services/topics/service-protection-policy-api.adoc +++ /dev/null @@ -1,167 +0,0 @@ -[[_service_authorization_uma_policy_api]] -= Managing resource permissions using the Policy API - -{project_name} leverages the UMA Protection API to allow resource servers to manage permissions for their users. In addition -to the Resource and Permission APIs, {project_name} provides a Policy API from where permissions can be set to resources by resource -servers on behalf of their users. - -The Policy API is available at: - -[source,subs="attributes+"] ----- -http://${host}:${port}{kc_realms_path}/${realm_name}/authz/protection/uma-policy/{resource_id} ----- - -This API is protected by a bearer token that must represent a consent granted by the user to the resource server to manage permissions on his behalf. The bearer token can be a regular access token obtained from the -token endpoint using: - -* Resource Owner Password Credentials Grant Type -* Token Exchange, in order to exchange an access token granted to some client (public client) for a token -where audience is the resource server - -== Associating a permission with a resource - -To associate a permission with a specific resource you must send a HTTP POST request as follows: - -[source,bash,subs="attributes+"] ----- -curl -X POST \ - http://localhost:8180{kc_realms_path}/photoz/authz/protection/uma-policy/{resource_id} \ - -H 'Authorization: Bearer '$access_token \ - -H 'Cache-Control: no-cache' \ - -H 'Content-Type: application/json' \ - -d '{ - "name": "Any people manager", - "description": "Allow access to any people manager", - "scopes": ["read"], - "roles": ["people-manager"] -}' ----- - -In the example above we are creating and associating a new permission to a resource represented by `resource_id` where -any user with a role `people-manager` should be granted with the `read` scope. - -You can also create policies using other access control mechanisms, such as using groups: - -[source,bash,subs="attributes+"] ----- -curl -X POST \ - http://localhost:8180{kc_realms_path}/photoz/authz/protection/uma-policy/{resource_id} \ - -H 'Authorization: Bearer '$access_token \ - -H 'Cache-Control: no-cache' \ - -H 'Content-Type: application/json' \ - -d '{ - "name": "Any people manager", - "description": "Allow access to any people manager", - "scopes": ["read"], - "groups": ["/Managers/People Managers"] -}' ----- - -Or a specific client: - -[source,bash,subs="attributes+"] ----- -curl -X POST \ - http://localhost:8180{kc_realms_path}/photoz/authz/protection/uma-policy/{resource_id} \ - -H 'Authorization: Bearer '$access_token \ - -H 'Cache-Control: no-cache' \ - -H 'Content-Type: application/json' \ - -d '{ - "name": "Any people manager", - "description": "Allow access to any people manager", - "scopes": ["read"], - "clients": ["my-client"] -}' ----- - -Or even using a custom policy using JavaScript: - -:tech_feature_name: Upload Scripts -:tech_feature_setting: -Dkeycloak.profile.feature.upload_scripts=enabled -include::./templates/deprecated.adoc[] - -[source,bash,subs="attributes+"] ----- -curl -X POST \ - http://localhost:8180{kc_realms_path}/photoz/authz/protection/uma-policy/{resource_id} \ - -H 'Authorization: Bearer '$access_token \ - -H 'Cache-Control: no-cache' \ - -H 'Content-Type: application/json' \ - -d '{ - "name": "Any people manager", - "description": "Allow access to any people manager", - "scopes": ["read"], - "condition": "my-deployed-script.js" -}' ----- - -It is also possible to set any combination of these access control mechanisms. - -To update an existing permission, send an HTTP PUT request as follows: - -[source,bash,subs="attributes+"] ----- -curl -X PUT \ - http://localhost:8180{kc_realms_path}/photoz/authz/protection/uma-policy/{permission_id} \ - -H 'Authorization: Bearer '$access_token \ - -H 'Content-Type: application/json' \ - -d '{ - "id": "21eb3fed-02d7-4b5a-9102-29f3f09b6de2", - "name": "Any people manager", - "description": "Allow access to any people manager", - "type": "uma", - "scopes": [ - "album:view" - ], - "logic": "POSITIVE", - "decisionStrategy": "UNANIMOUS", - "owner": "7e22131a-aa57-4f5f-b1db-6e82babcd322", - "roles": [ - "user" - ] -}' ----- - -== Removing a permission - -To remove a permission associated with a resource, send an HTTP DELETE request as follows: - -[source,bash,subs="attributes+"] ----- -curl -X DELETE \ - http://localhost:8180{kc_realms_path}/photoz/authz/protection/uma-policy/{permission_id} \ - -H 'Authorization: Bearer '$access_token ----- - -== Querying permission - -To query the permissions associated with a resource, send an HTTP GET request as follows: - -[source,subs="attributes+"] ----- -http://${host}:${port}{kc_realms_path}/${realm}/authz/protection/uma-policy?resource={resource_id} ----- - -To query the permissions given its name, send an HTTP GET request as follows: - -[source,bash,subs="attributes+"] ----- -http://${host}:${port}{kc_realms_path}/${realm}/authz/protection/uma-policy?name=Any people manager ----- - -To query the permissions associated with a specific scope, send an HTTP GET request as follows: - -[source,subs="attributes+"] ----- -http://${host}:${port}{kc_realms_path}/${realm}/authz/protection/uma-policy?scope=read ----- - -To query all permissions, send an HTTP GET request as follows: - -[source,subs="attributes+"] ----- -http://${host}:${port}{kc_realms_path}/${realm}/authz/protection/uma-policy ----- - -When querying the server for permissions use parameters `first` and `max` results to limit the result. diff --git a/authorization_services/topics/service-protection-protection-api.adoc b/authorization_services/topics/service-protection-protection-api.adoc deleted file mode 100644 index e13540878..000000000 --- a/authorization_services/topics/service-protection-protection-api.adoc +++ /dev/null @@ -1,22 +0,0 @@ -[[_service_protection_api]] -= Protection API - -The Protection API provides a UMA-compliant set of endpoints providing: - -* *Resource Management* -+ -With this endpoint, resource servers can manage their resources remotely and enable <<_enforcer_overview, policy enforcers>> to query the server for the resources that need protection. - -* *Permission Management* -+ -In the UMA protocol, resource servers access this endpoint to create permission tickets. {project_name} also provides -endpoints to manage the state of permissions and query permissions. - -* *Policy API* -+ -{project_name} leverages the UMA Protection API to allow resource servers to manage permissions for their users. In addition -to the Resource and Permission APIs, {project_name} provides a Policy API from where permissions can be set to resources by resource -servers on behalf of their users. - -An important requirement for this API is that _only_ resource servers are allowed to access its endpoints using a special OAuth2 access token called a protection API token (PAT). -In UMA, a PAT is a token with the scope *uma_protection*. diff --git a/authorization_services/topics/service-protection-resources-api-papi.adoc b/authorization_services/topics/service-protection-resources-api-papi.adoc deleted file mode 100644 index cfcea104a..000000000 --- a/authorization_services/topics/service-protection-resources-api-papi.adoc +++ /dev/null @@ -1,161 +0,0 @@ -[[_service_protection_resources_api]] -= Managing resources - -Resource servers can manage their resources remotely using a UMA-compliant endpoint. - -[source,subs="attributes+"] ----- -http://${host}:${port}{kc_realms_path}/${realm_name}/authz/protection/resource_set ----- - -This endpoint provides operations outlined as follows (entire path omitted for clarity): - -* Create resource set description: POST /resource_set -* Read resource set description: GET /resource_set/{_id} -* Update resource set description: PUT /resource_set/{_id} -* Delete resource set description: DELETE /resource_set/{_id} -* List resource set descriptions: GET /resource_set - -For more information about the contract for each of these operations, see https://docs.kantarainitiative.org/uma/wg/oauth-uma-federated-authz-2.0-09.html#reg-api[UMA Resource Registration API]. - -== Creating a resource - -To create a resource you must send an HTTP POST request as follows: - -[source,bash,subs="attributes+"] ----- -curl -v -X POST \ - http://${host}:${port}{kc_realms_path}/${realm_name}/authz/protection/resource_set \ - -H 'Authorization: Bearer '$pat \ - -H 'Content-Type: application/json' \ - -d '{ - "name":"Tweedl Social Service", - "type":"http://www.example.com/rsrcs/socialstream/140-compatible", - "icon_uri":"http://www.example.com/icons/sharesocial.png", - "resource_scopes":[ - "read-public", - "post-updates", - "read-private", - "http://www.example.com/scopes/all" - ] - }' ----- - -By default, the owner of a resource is the resource server. If you want to define a different owner, such as a -specific user, you can send a request as follows: - -[source,bash,subs="attributes+"] ----- -curl -v -X POST \ - http://${host}:${port}{kc_realms_path}/${realm_name}/authz/protection/resource_set \ - -H 'Authorization: Bearer '$pat \ - -H 'Content-Type: application/json' \ - -d '{ - "name":"Alice Resource", - "owner": "alice" - }' ----- - -Where the property `owner` can be set with the username or the identifier of the user. - -== Creating user-managed resources - -By default, resources created via Protection API can not be managed by resource owners through the <<_service_authorization_my_resources, Account Console>>. - -To create resources and allow resource owners to manage these resources, you must set `ownerManagedAccess` property as follows: - -[source,bash,subs="attributes+"] ----- -curl -v -X POST \ - http://${host}:${port}{kc_realms_path}/${realm_name}/authz/protection/resource_set \ - -H 'Authorization: Bearer '$pat \ - -H 'Content-Type: application/json' \ - -d '{ - "name":"Alice Resource", - "owner": "alice", - "ownerManagedAccess": true - }' ----- - -== Updating resources - -To update an existing resource, send an HTTP PUT request as follows: - -[source,bash,subs="attributes+"] ----- -curl -v -X PUT \ - http://${host}:${port}{kc_realms_path}/${realm_name}/authz/protection/resource_set/{resource_id} \ - -H 'Authorization: Bearer '$pat \ - -H 'Content-Type: application/json' \ - -d '{ - "_id": "Alice Resource", - "name":"Alice Resource", - "resource_scopes": [ - "read" - ] - }' ----- - -== Deleting resources - -To delete an existing resource, send an HTTP DELETE request as follows: - -[source,bash,subs="attributes+"] ----- -curl -v -X DELETE \ - http://${host}:${port}{kc_realms_path}/${realm_name}/authz/protection/resource_set/{resource_id} \ - -H 'Authorization: Bearer '$pat ----- - -== Querying resources - -To query the resources by `id`, send an HTTP GET request as follows: - -[source,bash,subs="attributes+"] ----- -http://${host}:${port}{kc_realms_path}/${realm_name}/authz/protection/resource_set/{resource_id} ----- - -To query resources given a `name`, send an HTTP GET request as follows: - -[source,bash,subs="attributes+"] ----- -http://${host}:${port}{kc_realms_path}/${realm_name}/authz/protection/resource_set?name=Alice Resource ----- - -By default, the `name` filter will match any resource with the given pattern. To restrict the query to only return resources with an exact match, use: - -[source,bash,subs="attributes+"] ----- -http://${host}:${port}{kc_realms_path}/${realm_name}/authz/protection/resource_set?name=Alice Resource&exactName=true ----- - -To query resources given an `uri`, send an HTTP GET request as follows: - -[source,bash,subs="attributes+"] ----- -http://${host}:${port}{kc_realms_path}/${realm_name}/authz/protection/resource_set?uri=/api/alice ----- - -To query resources given an `owner`, send an HTTP GET request as follows: - -[source,bash,subs="attributes+"] ----- -http://${host}:${port}{kc_realms_path}/${realm_name}/authz/protection/resource_set?owner=alice ----- - -To query resources given an `type`, send an HTTP GET request as follows: - -[source,bash,subs="attributes+"] ----- -http://${host}:${port}{kc_realms_path}/${realm_name}/authz/protection/resource_set?type=albums ----- - -To query resources given an `scope`, send an HTTP GET request as follows: - -[source,bash,subs="attributes+"] ----- -http://${host}:${port}{kc_realms_path}/${realm_name}/authz/protection/resource_set?scope=read ----- - -When querying the server for permissions use parameters `first` and `max` results to limit the result. \ No newline at end of file diff --git a/authorization_services/topics/service-protection-whatis-obtain-pat.adoc b/authorization_services/topics/service-protection-whatis-obtain-pat.adoc deleted file mode 100644 index aec60533c..000000000 --- a/authorization_services/topics/service-protection-whatis-obtain-pat.adoc +++ /dev/null @@ -1,37 +0,0 @@ -[[_service_protection_whatis_obtain_pat]] -= What is a PAT and how to obtain it - -A *protection API token* (PAT) is a special OAuth2 access token with a scope defined as *uma_protection*. When you create a resource server, {project_name} automatically -creates a role, _uma_protection_, for the corresponding client application and associates it with the client's service account. - -.Service Account granted with *uma_protection* role -image:images/service/rs-uma-protection-role.png[alt="Service Account granted with uma_protection role"] - -Resource servers can obtain a PAT from {project_name} like any other OAuth2 access token. For example, using curl: - -[source,bash,subs="attributes+"] ----- -curl -X POST \ - -H "Content-Type: application/x-www-form-urlencoded" \ - -d 'grant_type=client_credentials&client_id=${client_id}&client_secret=${client_secret}' \ - "http://localhost:8080{kc_realms_path}/${realm_name}/protocol/openid-connect/token" ----- - -The example above is using the *client_credentials* grant type to obtain a PAT from the server. As a result, the server returns a response similar to the following: - -```json -{ - "access_token": ${PAT}, - "expires_in": 300, - "refresh_expires_in": 1800, - "refresh_token": ${refresh_token}, - "token_type": "bearer", - "id_token": ${id_token}, - "not-before-policy": 0, - "session_state": "ccea4a55-9aec-4024-b11c-44f6f168439e" -} -``` - -[NOTE] -{project_name} can authenticate your client application in different ways. For simplicity, the *client_credentials* grant type is used here, -which requires a _client_id_ and a _client_secret_. You can choose to use any supported authentication method. diff --git a/authorization_services/topics/service-rpt-overview.adoc b/authorization_services/topics/service-rpt-overview.adoc deleted file mode 100644 index 2c1ddc39c..000000000 --- a/authorization_services/topics/service-rpt-overview.adoc +++ /dev/null @@ -1,32 +0,0 @@ -[[_service_rpt_overview]] -= Requesting party token - -A requesting party token (RPT) is a https://datatracker.ietf.org/doc/html/rfc7519[JSON web token (JWT)] digitally signed using https://datatracker.ietf.org/doc/html/rfc7515[JSON web signature (JWS)]. The token is built based on the OAuth2 access token previously issued by {project_name} to a specific client acting on behalf of a user -or on its own behalf. - -When you decode an RPT, you see a payload similar to the following: - -```json -{ - "authorization": { - "permissions": [ - { - "resource_set_id": "d2fe9843-6462-4bfc-baba-b5787bb6e0e7", - "resource_set_name": "Hello World Resource" - } - ] - }, - "jti": "d6109a09-78fd-4998-bf89-95730dfd0892-1464906679405", - "exp": 1464906971, - "nbf": 0, - "iat": 1464906671, - "sub": "f1888f4d-5172-4359-be0c-af338505d86c", - "typ": "kc_ett", - "azp": "hello-world-authz-service" -} -``` - -From this token you can obtain all permissions granted by the server from the *permissions* claim. - -Also note that permissions are directly related with the resources/scopes you are protecting and completely decoupled from -the access control methods that were used to actually grant and issue these same permissions. diff --git a/authorization_services/topics/service-rpt-token-introspection.adoc b/authorization_services/topics/service-rpt-token-introspection.adoc deleted file mode 100644 index 672cceabc..000000000 --- a/authorization_services/topics/service-rpt-token-introspection.adoc +++ /dev/null @@ -1,86 +0,0 @@ -[[_service_protection_token_introspection]] -= Introspecting a requesting party token - -Sometimes you might want to introspect a requesting party token (RPT) to check its validity or obtain the permissions within the token to enforce authorization decisions on the resource server side. - -There are two main use cases where token introspection can help you: - -* When client applications need to query the token validity to obtain a new one with the same or additional permissions -* When enforcing authorization decisions at the resource server side, especially when none of the built-in <<_enforcer_overview, policy enforcers>> fits your application - -= Obtaining Information about an RPT - -The token introspection is essentially a https://datatracker.ietf.org/doc/html/rfc7662[OAuth2 token introspection]-compliant endpoint from which you can obtain information about an RPT. - -[source,subs="attributes+"] ----- -http://${host}:${port}{kc_realms_path}/${realm_name}/protocol/openid-connect/token/introspect ----- - -To introspect an RPT using this endpoint, you can send a request to the server as follows: - -[source,bash,subs="attributes+"] ----- -curl -X POST \ - -H "Authorization: Basic aGVsbG8td29ybGQtYXV0aHotc2VydmljZTpzZWNyZXQ=" \ - -H "Content-Type: application/x-www-form-urlencoded" \ - -d 'token_type_hint=requesting_party_token&token=${RPT}' \ - "http://localhost:8080{kc_realms_path}/hello-world-authz/protocol/openid-connect/token/introspect" ----- - -[NOTE] -The request above is using HTTP BASIC and passing the client's credentials (client ID and secret) to authenticate the client attempting to introspect the token, but you can use any other client authentication method supported by {project_name}. - -The introspection endpoint expects two parameters: - -* *token_type_hint* -+ -Use *requesting_party_token* as the value for this parameter, which indicates that you want to introspect an RPT. -+ -* *token* -+ -Use the token string as it was returned by the server during the authorization process as the value for this parameter. - -As a result, the server response is: - -```json -{ - "permissions": [ - { - "resource_id": "90ccc6fc-b296-4cd1-881e-089e1ee15957", - "resource_name": "Hello World Resource" - } - ], - "exp": 1465314139, - "nbf": 0, - "iat": 1465313839, - "aud": "hello-world-authz-service", - "active": true -} -``` - -If the RPT is not active, this response is returned instead: - -```json -{ - "active": false -} -``` - -= Do I need to invoke the server every time I want to introspect an RPT? - -No. Just like a regular access token issued by a {project_name} server, RPTs also use the -JSON web token (JWT) specification as the default format. - -If you want to validate these tokens without a call to the remote introspection endpoint, you can decode the RPT and query for its validity locally. Once you decode the token, -you can also use the permissions within the token to enforce authorization decisions. - -This is essentially what the policy enforcers do. Be sure to: - -* Validate the signature of the RPT (based on the realm's public key) -* Query for token validity based on its _exp_, _iat_, and _aud_ claims - -[role="_additional-resources"] -.Additional resources -* https://datatracker.ietf.org/doc/html/rfc7519[JSON web token (JWT)] -* <<_enforcer_overview, policy enforcers>> diff --git a/authorization_services/topics/templates b/authorization_services/topics/templates deleted file mode 120000 index d19126411..000000000 --- a/authorization_services/topics/templates +++ /dev/null @@ -1 +0,0 @@ -../../topics/templates \ No newline at end of file diff --git a/build-auto.sh b/build-auto.sh deleted file mode 100755 index 35a1dd55a..000000000 --- a/build-auto.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash - -OPTS=$1 - -while true; do - CHANGED=`inotifywait -r -e modify,move,create,delete authorization_services getting_started securing_apps server_admin server_development server_installation upgrading --format %w` - GUIDE=`echo $CHANGED | cut -d '/' -f 1` - mvn clean install -f $GUIDE $OPTS -done diff --git a/dist/assembly.xml b/dist/assembly.xml deleted file mode 100644 index 9c27b6728..000000000 --- a/dist/assembly.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - docs-dist - - - zip - - - true - - - - ../target - - - - - \ No newline at end of file diff --git a/dist/pom.xml b/dist/pom.xml deleted file mode 100644 index 915bb047c..000000000 --- a/dist/pom.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - 4.0.0 - - - org.keycloak.documentation - documentation-parent - 999.0.0-SNAPSHOT - ../ - - - Keycloak Documentation dist - keycloak-documentation - pom - - - - - maven-assembly-plugin - - - assemble - package - - single - - - - assembly.xml - - false - - - - - - - diff --git a/get-version.sh b/get-version.sh deleted file mode 100755 index 805d9269b..000000000 --- a/get-version.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -e - -awk '/:project_version:/ { print $2 }' topics/templates/document-attributes.adoc diff --git a/header-maven-plugin/pom.xml b/header-maven-plugin/pom.xml deleted file mode 100644 index 13fc1f635..000000000 --- a/header-maven-plugin/pom.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - 4.0.0 - - documentation-parent - org.keycloak.documentation - 999.0.0-SNAPSHOT - - - org.keycloak.documentation - header-maven-plugin - 999.0.0-SNAPSHOT - maven-plugin - - github-maven-plugin - - - UTF-8 - - - - - org.apache.maven - maven-project - 2.2.1 - - - org.apache.maven - maven-plugin-api - 3.0 - - - org.apache.maven.plugin-tools - maven-plugin-annotations - 3.1 - provided - - - org.codehaus.plexus - plexus-utils - 3.0.24 - - - - - - - org.apache.maven.plugins - maven-plugin-plugin - 3.4 - - header - true - - - - mojo-descriptor - - descriptor - - - - header-goal - - helpmojo - - - - - - - diff --git a/header-maven-plugin/src/main/java/sample/plugin/HeaderMojo.java b/header-maven-plugin/src/main/java/sample/plugin/HeaderMojo.java deleted file mode 100644 index aa5dc0a1d..000000000 --- a/header-maven-plugin/src/main/java/sample/plugin/HeaderMojo.java +++ /dev/null @@ -1,133 +0,0 @@ -package sample.plugin; - -/* - * Copyright 2001-2005 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import org.apache.maven.plugin.AbstractMojo; -import org.apache.maven.plugin.MojoExecutionException; -import org.apache.maven.plugins.annotations.LifecyclePhase; -import org.apache.maven.plugins.annotations.Mojo; -import org.apache.maven.plugins.annotations.Parameter; -import org.apache.maven.project.MavenProject; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileOutputStream; -import java.io.FileReader; -import java.io.IOException; -import java.io.PrintStream; -import java.nio.file.Files; -import java.nio.file.StandardCopyOption; - -/** - * Goal which touches a timestamp file. - */ -@Mojo(name = "header", defaultPhase = LifecyclePhase.PROCESS_SOURCES) -public class HeaderMojo extends AbstractMojo { - - @Parameter(defaultValue = "${project}", readonly = true) - private MavenProject mavenProject; - - @Parameter(defaultValue = "index", property = "masterFile", required = true) - private String masterFileName; - - @Parameter(defaultValue = "${project.build.directory}/sources", property = "outputDir", required = true) - private File outputDir; - - private File baseDir; - - private File topicsDir; - - public void execute() throws MojoExecutionException { - try { - baseDir = mavenProject.getBasedir(); - - copy(new File(baseDir, masterFileName + ".adoc")); - copy(new File(baseDir, "topics.adoc")); - - File docInfo = new File(baseDir, "docinfo.html"); - if (docInfo.isFile()) { - copy(docInfo); - copy(new File(baseDir, "docinfo-footer.html")); - } - - topicsDir = new File(baseDir, "topics"); - - processTopics(topicsDir); - } catch (IOException e) { - e.printStackTrace(); - throw new MojoExecutionException(e.getMessage(), e); - } - } - - private void copy(File file) throws IOException { - File out = new File(outputDir, file.getName()); - out.mkdirs(); - Files.copy(file.toPath(), out.toPath(), StandardCopyOption.REPLACE_EXISTING); - } - - private void processTopics(File f) throws IOException { - String topicsAbsolutePath = f.getAbsolutePath(); - String topicsParentDirPath = topicsDir.getParentFile().getAbsolutePath(); - if (isWindows()) { - topicsAbsolutePath = topicsAbsolutePath.replace("\\", "/"); - topicsParentDirPath = topicsParentDirPath.replace("\\", "/"); - } - File out = new File(outputDir, topicsAbsolutePath.replaceFirst(topicsParentDirPath, "")); - - if (f.isFile() && topicsAbsolutePath.contains("/templates/")) { - out.getParentFile().mkdirs(); - Files.copy(f.toPath(), out.toPath(), StandardCopyOption.REPLACE_EXISTING); - } else if (f.isDirectory()) { - File[] files = f.listFiles(); - if(files != null){ - for (File c : files) { - processTopics(c); - } - } - } else if (f.getName().endsWith(".adoc")) { - out.getParentFile().mkdirs(); - - String filePath = f.getAbsolutePath().replace(baseDir.getParent(), "").substring(1); - if (isWindows()) { - filePath = filePath.replace("\\", "/"); - } - String includeHeaderPath = filePath.substring(baseDir.getName().length() + 7); - includeHeaderPath = includeHeaderPath.substring(0, includeHeaderPath.lastIndexOf('/')); - includeHeaderPath = includeHeaderPath.replaceAll("/[^/]+", "../"); - includeHeaderPath = includeHeaderPath + "templates/header.adoc"; - - String header = "\n\n:include_filename: " + filePath + "\ninclude::" + includeHeaderPath + "[]\n\n"; - try(PrintStream ps = new PrintStream(new FileOutputStream(out));BufferedReader br = new BufferedReader(new FileReader(f));){ - for (String l = br.readLine(); l != null; l = br.readLine()) { - ps.println(l); - if (l.startsWith("=")) { - break; - } - } - ps.print(header); - - for (String l = br.readLine(); l != null; l = br.readLine()) { - ps.println(l); - } - } - } - } - private boolean isWindows(){ - String osName = System.getProperty("os.name"); - return osName != null && osName.toLowerCase().startsWith("windows"); - } -} diff --git a/internal_resources/README.md b/internal_resources/README.md deleted file mode 100644 index efc41c8c0..000000000 --- a/internal_resources/README.md +++ /dev/null @@ -1,26 +0,0 @@ -Keycloak Documentation Guidelines -====================== - -This folder contains guidelines for writers. - -Contributor's Guide -------------------- - -See our [Contributor's Guide](contributing.adoc) to learn the procedure for making contributions to documentation. - -Templates ---------- - -We have templates that we ask you to please use for your new content. When: - -* I want to do X - * Use the [brief task template](template_task_brief.adoc). The [detailed task template](template_task.adoc) has a wealth of resources and tips that you may find useful. -* I want to understand X - * Use the [Concept Template](template_concept.adoc) -* I want to know X - * Use the [Reference Template](template_reference.adoc) - -Styles ------- - -When writing content we use the IBM Style Guide. \ No newline at end of file diff --git a/internal_resources/contributing.adoc b/internal_resources/contributing.adoc deleted file mode 100644 index 0d247eb9d..000000000 --- a/internal_resources/contributing.adoc +++ /dev/null @@ -1,84 +0,0 @@ -[[contributing]] -= Contributor's Guide - -This guide will help new contributors use `git` and GitHub for Keycloak documentation submissions and suggestions. - -Before you start, please take a look at our writing templates contained in the link:https://github.com/keycloak/keycloak-documentation/tree/main/internal_resources[internal resources directory], which also describes each template file with information about when to use which. We are working to update our documentation to put procedural content, conceptual content, and reference content into separate .adoc files, and we kindly request that new contributions please use these templates. - -There are two ways to start. The first is the easiest, but it is less flexible. The second is more powerful, but requires setting up. For either method, you must already have a GitHub account, as described in link:https://github.com/join[Join GitHub]. - -[[simple]] -== Simple and Infrequent Contributions (Method One) - -This method is useful for quick fixes or simple additions. - -. Find the file you want to edit in the GitHub web interface. -. Click the file name to open it in GitHub. -. Click the edit icon near the top right of the page contents. The icon looks like a pencil. -. Make your edits. -. Enter a title and description of your changes in the *Commit Changes* section at the bottom of the page. Enter enough detail for reviewers to know what you have changed and why. -. Select *Create a new branch for this commit and start a pull request*. -. Click *Commit changes*. - -[[sustained]] -== Larger and Sustained Contributions (Method Two) - -This method is useful for any type of contribution, but necessary for larger and more complex ones. If you expect to participate often, this is the recommended method. - -[[initialsetup]] -=== Initial Setup - -You only need to perform these tasks once, when preparing to contribute. - -. Fork the link:https://github.com/keycloak/keycloak-documentation[Keycloak documentation repository]. This will create your own version of the repository which you can find at `https://github.com/{yourusername}/keycloak-documentation` where `{yourusername}` is the username you created in GitHub. -. Install `git` on your local machine. The procedure differs by operating system as described in link:https://git-scm.com/book/en/v2/Getting-Started-Installing-Git[Installing Git]. Follow up with initial Git setup tasks, as described in link:https://git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup[First Time Git Setup]. -. Clone from your fork to create a copy on your local machine and then navigate to the new directory by entering the following from the command line on your local machine: -+ -[source,bash] ----- -$ git clone https://github.com/{yourusername}/keycloak-documentation -$ cd keycloak-documentation ----- -+ -. Add a git remote to your local repository to link to the upstream version of the documentation. This makes it easier to update your fork and local version of the documentation. -+ -[source,bash] ----- -$ git remote add upstream https://github.com/keycloak/keycloak-documentation ----- -+ -. Check your settings. -+ -[source,bash] ----- -$ git remote -v -origin https://github.com/{yourusername}/keycloak-documentation.git (fetch) -origin https://github.com/{yourusername}/keycloak-documentation.git (push) -upstream https://github.com/keycloak/keycloak-documentation (fetch) -upstream https://github.com/keycloak/keycloak-documentation (push) ----- -+ - -NOTE: It is possible to clone using SSH so you don't have to enter a username/password every time you push. Find instructions at link:https://help.github.com/articles/connecting-to-github-with-ssh/[Connecting to GitHub with SSH] and link:https://help.github.com/articles/which-remote-url-should-i-use/[Which Remote URL Should I Use]. When using SSH, the origin lines will appear like this: -`git@github.com:{yourusername}/keycloak-documentation.git` - -[[workflow]] -=== Typical Workflow for Keycloak Documentation Contributions - -When contributing, follow this procedure. Enter commands from the command line on your local machine in the `keycloak-documentation` directory created earlier when cloning the repository. - -. Enter `git checkout main` to checkout the main branch locally. -. Enter `git fetch upstream` to download the current files from the upstream repository. -. Enter `git rebase upstream/main` to update your cloned branch on your local machine with the most current content from the upstream repository. -. Enter `git push origin main` to update your fork in GitHub with the most current content from the upstream repository. -. Enter `git checkout -b {branchname}` where you create a `{branchname}` that describes the work you are about to do. -. Make your changes -. (Optional) Enter `git status` now or at any time to see what branch you are on, what files you have changed, and whether those files are staged to be committed. -. Enter `git add -A` to stage your changes to the commit you are about to make. -. Enter `git commit -m 'KEYCLOAK-XXXX include meaningful information about changes'` where `KEYCLOAK-XXXX` refers to the link:https://issues.redhat.com/projects/KEYCLOAK/issues[Jira issue] being fixed in this commit (if any) and where you add a short sentence that clearly describes what the commit contains. -. Follow the steps in the link:https://github.com/keycloak/keycloak-documentation/blob/main/README.md[README] to create a test build locally and confirm that your changes look correct. Make more changes and repeat steps to here, as needed. -. Enter `git push origin {branchname}` to push your changes to your fork in GitHub. -. Use the GitHub web interface to create a pull request. First, navigate to your branch in the web UI and click *Compare*. This will show you a diff of the changes. Examine them one more time. If necessary, make more changes locally and repeat the steps to here. When you are ready, click *Create a pull request*. Enter a title and a description with enough detail for reviewers to know what you have changed and why. Click *Submit*. -. Wait. The documentation team will usually review pull requests within a few days. Often suggestions and changes are requested of you to help the contribution better fit within the style guidelines for the project or to fill in information that may have been missed. If this happens, repeat the steps from making your changes to `git push origin {branchname}`. No need to create another PR as the existing one will be updated automatically. - -Once the PR has been merged or rejected, you can remove your feature branch `{newbranchname}` from both the remote fork and your local machine. GitHub provides a button for removing from the fork in the UI of the PR once it is merged. Remove from your local machine with `git branch -d {branchname}`. diff --git a/internal_resources/screenshots.adoc b/internal_resources/screenshots.adoc deleted file mode 100644 index fd379bc67..000000000 --- a/internal_resources/screenshots.adoc +++ /dev/null @@ -1,140 +0,0 @@ -[[screenshot_guidelines]] -= Documentation Screenshots Guidelines - -[[summary]] -== Summary -* Images should be saved as *PNG* or *JPG*, with a width of at least *660 px*, at *110 dpi*. Try to keep file size less than *300 KB*. -* Screenshots supplement the text, not replace it. *Do not rely on images to provide information or context*. -* *Do not include any testing/pre-release labels*. -* *Do not include any personally identifying information*. -* Capture just the part of the screen or window that users must focus on; *do not include window headers in the final screenshots unless completely necessary*. -* Manipulate your screenshots to *condense important information* in them and limit empty GUI space and other inconsequential parts. - -[[general]] -== General Guidelines -* Screen captures can be useful and successful when they achieve one or more of these objectives: -** Illustrate a user interface that is fairly complex or difficult to explain in text -** Help the user find a small element in a complex user interface -** Show the results of a series of steps or user actions -** Orient readers who are reading the publication without the user interface in front of them -* Use the smallest number of screenshots possible. -* Use screenshots to provide verification for the reader, rather than instruction. In other words, screenshots supplement the text, not replace it. *Do not rely on images to provide information or context*. Instead, use them only to provide the reader with orientation. - -[NOTE] -===================================================================== -Example 1: Do not tell the reader to fill out a form according to the image; instead list the values needed for the form in text. -===================================================================== - -[NOTE] -===================================================================== -Example 2: Do not include an image of the directory tree; instead tell the user exactly where to find the file in running text (…​/standalone/configuration/standalone.xml). -===================================================================== -* Bearing in mind the impact on localization and accessibility, you should aim to write your document so that, were you to remove all screenshots from the book, the text would still make sense. - -[NOTE] -===================================================================== -For example: Do not write "see image below" or "as is shown in the image" -===================================================================== -* When you are snapping a GUI form, fill it with relevant input first. -* Make sure the screenshots *do not include any testing/pre-release labels*. -* Make sure the screenshots *do not include any personally identifying information*. - -[NOTE] -===================================================================== -For example: Always use 'test' as the username or fake contact information. If including the browser title bar hide your bookmarks and use a default browser theme. -===================================================================== - -[TIP] -===================================================================== -Use Chrome Dev Tools to select elements on the page and rewrite their contents. -===================================================================== -* Include the cursor, mouse pointer, or menus only when their presence is significant. -* Increase font size in the browser if it is hard to read before snapping the image. -* Capture just the part of the screen or window that users must focus on. - -[NOTE] -===================================================================== -For example: Unless necessary, *do not include window headers in the final screenshots* to indicate your currently used window manager or desktop environment. -===================================================================== -* If possible, try not to cut any elements on the screen. -* Show the user interface elements exactly as they are displayed for most users for quick recognition. - -[NOTE] -===================================================================== -For example: If you have a custom theme on your system, disable it and take the screenshot using the default theme. -===================================================================== -* Do not add borders around or drop shadows to your screenshots. -* Do not use rounded corners. If the screenshot contains rounded corners, then that's ok, of course. But, the screenshot itself should remain squared. - -[[specs]] -== Tech Specs -* Image width should be at least *660 px* (internal tools will automatically resize the image to a max width of 660 px). -* The preferred format is *PNG* or *JPG* . -* The output resolution of images should be *110 dpi* to ensure good quality in the generated PDF. - -[TIP] -===================================================================== -In GIMP, select Image/Scale Image... to set resolution -===================================================================== -* If possible, try to keep screenshot size less than *300 KB*. -* If possible, avoid snapping images in various terminals with 8-bit color scale or less. -* Manipulate your screenshots to condense important information in them and limit empty GUI space and other inconsequential parts. - -[NOTE] -===================================================================== -For example: You can do this by setting a low screen resolution or resizing your browser window to a smaller size. Keep in mind that you should only do this if it does not adversely affect the readability of the image. -===================================================================== - -[NOTE] -===================================================================== -If you need to take a screenshot of the entire window, use a tool such as the https://chrome.google.com/webstore/detail/window-resizer/kkelicaakdanhinjdeammmilcgefonfh?hl=en[_Window Resizer_] Google Chrome extension to ensure the browser window is a set size before taking the screenshot. This helps ensure that all full window screenshots are of standard dimensions. -===================================================================== -* If necessary, call attention to hard to find parts of the screenshot with red outlines (border: #C00, width:1px) or with a transparent gray (#ECECEC) layer over unimportant parts of the picture. - -[[accessibility]] -== Accessibility -* Section 508 compliance requires that all of the information is available in a text format for accessibility reasons (for instance, screen readers can not extract information from images). -* Also, a large number of screenshots can possibly slow download of docs for those on very slow connections (rarer for most enterprises these days). - -[[asciidoc]] -== AsciiDoc Syntax -* Insert a block-level image, which uses a double colon (::). Good for screenshots, diagrams, etc. - -** Example 1: Include an image title in title case (which automatically appends a Figure #). -+ ----- -.Image Title -image::icon.png[Alt text, 50, 50] ----- - -** Example 2: Insert an inline image. Note, there is only one colon (:) used here. -+ ----- -This is an inline image. image:icon.png[Alt text] Cool! ----- - -[[questions]] -== Additional Questions -* When should I add a screenshot to my book? -** When introducing a new part of the UI. -** When the UI is suboptimal and some elements are difficult to find, located in unusual places, hidden, or somehow less visible. -* When, in the development cycle, should I add my screenshots? -** Add them as late in the cycle as possible, preferably during the review process. At this late stage, hopefully there will be fewer UI changes to the product. - -[TIP] -===================================================================== -Add a placeholder for the screenshot early on in the development cycle. This way it will not be forgotten. -===================================================================== -* What image editor should I use? -** The recommended graphical editor is GIMP. - -[[extensions]] -== Browser Extensions - -[[resizing]] -=== Resizing -There are a couple simple browser extensions that can assist in resizing your browser to the appropriate dimensions. - -* Google Chrome extension: https://chrome.google.com/webstore/detail/window-resizer/kkelicaakdanhinjdeammmilcgefonfh?hl=en[_Window Resizer_] -* Firefox add-on: https://addons.mozilla.org/en-US/firefox/addon/firesizer/[_Firesizer_] -** You will also need to install the Addon Bar: https://addons.mozilla.org/en-US/firefox/addon/the-addon-bar/[_The Addon Bar (Restored)_] diff --git a/internal_resources/styleguide.adoc b/internal_resources/styleguide.adoc deleted file mode 100644 index bbca32ef7..000000000 --- a/internal_resources/styleguide.adoc +++ /dev/null @@ -1,52 +0,0 @@ -= Documentation Style Guide - -== Style Guides to Follow - -. IBM Style Guide (printed) -. This document - -Writers will also refer to these: -. link:https://www.ibm.com/developerworks/library/styleguidelines/[IBM DeveloperWorks Editorial Style Guide] -. link:http://brand.redhat.com/elements/[RH Corporate] - - -== Style Guidelines - -* Use title case for headings. -** Unsure of the proper capitalization? See link:http://titlecase.com/[http://titlecase.com/] -* Write clear, short sentences. -* Use definite and indefinite articles like _an_ and _the_. -+ -*Incorrect:* Create project. Delete object from editor. + -*Correct:* Create a project. Delete an object from the editor. -+ -* Start steps with an active verb, such as *Enter*, *Edit*, and *Click*. -* Start headings with gerunds (verbs that end in -ing), such as *Configuring*, *Creating*, and *Installing*. -* Use *bold* for GUI items. Match the capitalization you see in the GUI. -* End entries in bulleted and numbered lists with periods when the entries are complete sentences. -* Use `$ sudo`, not `#` for superuser terminal commands. -* Don't use contractions. -+ -*Incorrect:* Don't use contractions. + -*Correct:* Do not use contractions. -+ -* Use `++_italics_++` for emphasis, not `++*bold*++`. -* Spell out integers that are less than 10, such as "four", not "4". -** Always use numerals in ranges, even when either or both of the numbers are less than 10. -* Do not use Latin abbreviations, such as e.g., etc., and i.e. -** Instead, use "and so on" when you list a clear sequence of elements, such as "1, 2, 3, and -so on". Otherwise, rewrite the sentence to replace etc. with something more descriptive, -such as "and other output". -** Instead of i.e. use "that is". -** Instead of e.g. use "for example" or "such as". -* Do not use "&" in place of "and". -* Do not use "and/or". Pick one. - - -== See Also - -* link:http://asciidoctor.org/docs/asciidoc-syntax-quick-reference/[AsciiDoc Syntax Quick Reference] -* link:screenshots.adoc[Screenshot Guide] -* link:terms_conventions.adoc[RH-SSO Terms and Conventions] -* link:http://ccs-jenkins.gsslab.brq.redhat.com:8080/job/glossary-of-terms-and-conventions-for-product-documentation-branch-master/lastSuccessfulBuild/artifact/index.html[Red Hat Glossary of Terms and Conventions] -* link:https://mojo.redhat.com/docs/DOC-1136272[Red Hat Style Guide and Writers Checklist] \ No newline at end of file diff --git a/internal_resources/template_concept.adoc b/internal_resources/template_concept.adoc deleted file mode 100644 index bc1c1a295..000000000 --- a/internal_resources/template_concept.adoc +++ /dev/null @@ -1,17 +0,0 @@ -[[concept_module]] - -= Concept Template and Guidelines - -_In the title, include nouns that are used in the body text -- this helps readers and search engines find information quickly._ - -A concept module describes and explains things such as a product, subsystem, or feature -- what a customer needs to understand to do a task. A concept module may also explain how things relate and interact with other things. The use of graphics and diagrams can speed up understanding of a concept. - -* Look at nouns and noun phrases in related task modules and user story assemblies to find the concepts to explain to users. - -* A concept module in product documentation should explain only things that are visible to users. - -* If a product concept is interesting, but not visible to users, the concept probably does not require explanation in a concept module. - -* A concept module should NOT include numbered steps or other wording that instructs a user to execute a command or perform an action. Instead, put that information in a separate task module or user story assembly. - - diff --git a/internal_resources/template_reference.adoc b/internal_resources/template_reference.adoc deleted file mode 100644 index b137278dc..000000000 --- a/internal_resources/template_reference.adoc +++ /dev/null @@ -1,13 +0,0 @@ -[[reference_module]] - -= Reference Template and Guidelines - -_In the title, include nouns that are used in the body text — this helps readers and search engines find information quickly._ - -A reference module lists things (such as a list of commands) or has a very regimented structure (such as the consistent structure of man pages). A reference module explains the details that a customer needs to know to do a task. A reference module is well-organized if users can scan it to quickly find the details they want. - -* A reference module that is a list of things may be made easier to scan if its content is organized alphabetically or formatted as a table. Think of an alphabetical list of commands that can be used with an application, or of an alphabetical list of system components with brief definitions formatted as a 2-column table. - -* If you have a large volume of the same type of information to document, figure out a consistent structure that the information details can fit into and then document each logical unit of information as 1 reference module. Think of man pages, which document very different information details, but that use consistent titles and formats to present those details in a consistent information structure. - - diff --git a/internal_resources/template_task.adoc b/internal_resources/template_task.adoc deleted file mode 100644 index 5ecbfbc4c..000000000 --- a/internal_resources/template_task.adoc +++ /dev/null @@ -1,59 +0,0 @@ -[[task_module]] - -= Do One Task - -_Start title with verb form such as Creating. Use the gerund form (noun form of verb) for titles, not the imperative form._ - -_Avoid using the word 'Configuring' over and over. Other words might include:_ - -* _Specifying_ -* _Adding_ -* _Constructing_ -* _Arranging_ -* _Building_ -* _Setting_ -* _Managing_ -* _Defining_ -* _Customizing_ -* _Or instead of using synonyms (which becomes obvious) 'verb-alize' a word and refactor the heading - limiting (instead of 'setting resource limits')_ - -_The standard for all Red Hat documentation is title case for all headings and titles._ - -_A task module is a procedure written with numbered steps -- what a customer needs to do to accomplish a goal successfully._ - -This paragraph explains why the user performs the task, sets the context of the task, and may explain or list special considerations specific to this task. Keep the information brief and focused on what is needed for this specific task. Suggested length is 1 to 3 sentences, can be longer if needed. - - -.Prerequisites _(if needed)_ - -* Sentence or a bulleted list of prerequisites that must be in place or done before the user starts this task. - -* Delete section title and bullets if the task has no required prerequisites. - -* Text can be a link to a prerequisite task that the user must do before starting this task. - - -.Procedure - -_Start title with verb form such as Creating. Use the gerund form (noun form of verb) for titles, not the imperative form._ - -_Put steps in a numbered list. The step sequence is important to a repeatable successful outcome._ - -. Start each step with an active verb, because each step corresponds to one user action. - -. Include one command or action per step. - -. Format the step line as an unnumbered bullet if the procedure includes only 1 step (exception to numbering the steps). - -. Include one command or action per step. - -. Include one command or action per step. - - -.Related Information _(if needed)_ - -* Bulleted list of links to concepts, reference, or other tasks closely related to this task. - -* Include only the most relevant items as links, not every possible related item. - -* Delete section title and bullets if no related information is needed. diff --git a/internal_resources/template_task_brief.adoc b/internal_resources/template_task_brief.adoc deleted file mode 100644 index 2e41865a2..000000000 --- a/internal_resources/template_task_brief.adoc +++ /dev/null @@ -1,20 +0,0 @@ -[[task_module]] - -= Do One Task - -This paragraph explains why the user performs the task, sets the context of the task, and may explain or list special considerations specific to this task. Keep the information brief and focused on what is needed for this specific task. Suggested length is 1 to 3 sentences, can be longer if needed. - - -.Prerequisites _(if needed)_ - -* List - - -.Procedure - -. List - - -.Related Information _(if needed)_ - -* List diff --git a/internal_resources/terms_conventions.adoc b/internal_resources/terms_conventions.adoc deleted file mode 100644 index 4e35074ab..000000000 --- a/internal_resources/terms_conventions.adoc +++ /dev/null @@ -1,146 +0,0 @@ -[[red-hat-single-sign-on-conventions]] -=== Red Hat Single Sign-On Terms and Conventions - -[discrete] -==== ID (noun) -[[ssoID]] -*Description*: as in, service ID - -*Use it*: with caution - -*Incorrect forms*: id - -*See also*: - - -[discrete] -==== identity management (noun) -[[identitymanage]] -*Description*: - -*Use it*: yes - -*Incorrect forms*: - -*See also*: xref:idm[IdM] - -[discrete] -==== IdM (noun) -[[idm]] -*Description*: acceptable abbreviation for identity management - -*Use it*: yes - -*Incorrect forms*: IDM, idm - -*See also*: xref:identitymanage[identity management] - -[discrete] -==== identity provider (noun) -[[identityprovider]] -*Description*: - -*Use it*: yes - -*Incorrect forms*: - -*See also*: xref:idp[IdP] - -[discrete] -==== IdP (noun) -[[idp]] -*Description*: acceptable abbreviation for identity provider - -*Use it*: yes - -*Incorrect forms*: IDP, idp - -*See also*: xref:identityprovider[identity provider] - -[discrete] -==== Red Hat Single Sign-On (noun) -[[redhatsinglesignon]] -*Description*: Product name for Red Hat Single Sign-On - -*Use it*: yes - -*Incorrect forms*: Red Hat single sign-on, Red Hat Single Sign-on, single sign-on - -*See also*: xref:rhsso[RH-SSO] - -[discrete] -==== Red Hat Single Sign-On Server (noun) -[[redhatsinglesignonserver]] -*Description*: Product name for Red Hat Single Sign-On Server - -*Use it*: yes - -*Incorrect forms*: Red Hat single sign-on server, Red Hat Single Sign-on server, single sign-on server - -*See also*: - -[discrete] -==== RH-SSO (noun) -[[rhsso]] -*Description*: Product abbreviation for Red Hat Single Sign-On - -*Use it*: yes - -*Incorrect forms*: RHSSO, SSO - -*See also*: xref:redhatsinglesignon[Red Hat Single Sign-On] - -[discrete] -==== SAML (noun) -[[saml]] -*Description*: Abbreviation for Security Assertion Markup Language - -*Use it*: yes - -*Incorrect forms*: saml - -*See also*: - -[discrete] -==== service provider (noun) -[[serviceprovider]] -*Description*: - -*Use it*: yes - -*Incorrect forms*: Service Provider - -*See also*: xref:sp[SP] - -[discrete] -==== single sign-on (noun) -[[sso]] -*Description*: Generic term for single sign-on - -*Use it*: yes - -*Incorrect forms*: sso - -*See also*: - -[discrete] -==== SP (noun) -[[sp]] -*Description*: Acceptable abbreviation for service provider - -*Use it*: yes - -*Incorrect forms*: sp - -*See also*: xref:serviceprovider[service provider] - -[discrete] -==== SSSD (noun) -[[sssd]] -*Description*: Abbreviation for system security services daemon - -*Use it*: yes - -*Incorrect forms*: sssd - -*See also*: diff --git a/internal_resources/testing.adoc b/internal_resources/testing.adoc deleted file mode 100644 index ce998977c..000000000 --- a/internal_resources/testing.adoc +++ /dev/null @@ -1,110 +0,0 @@ -= Testing - -The `tests` directory contains a testsuite for the documentation. It has a separate test for each guide. - -Currently we are testing the following: - -* Variables - check if there are variables that are not resolved -* Includes - check if there are includes where the included file is not found -* Images - check if there are images included that are not missing -* Internal links - check that all internal links (HTML anchors) point to a valid id -* External links - check that all external links work, including HTML anchors - -More details about each test below and what to do if the tests are not working. - -By default the tests run against the locally built documentation. It is also possible to run the test against an -externally built and hosted version of the documentation. - - -== Running the tests - -The tests are ran with a regular build: - -[source,bash] ----- -# mvn clean install ----- - -The tests are also ran when building the product documentation: - -[source,bash] ----- -# mvn clean install -Dproduct ----- - -You can also run the tests from within your IDE, but you have to manually build the guides first. - -== Testing externally built and hosted - -The tests can check externally built and hosted documentation instead of the locally built version. To do this set -the `guideBaseUrl` system property to the base URL of the externally hosted documentation. - -For example to test Keycloak documentation run: -[source,bash] ----- -mvn -f test test -DguideBaseUrl=http:///docs/{version} ----- - -Or for example to test RH-SSO documentation run: -[source,bash] ----- -mvn -f test test -DguideBaseUrl=https:///documentation/en-us/red_hat_single_sign-on/{version}/html-single/ ----- - -NOTE: `{version}` is replaced with `{project_versionDoc}` from document-attributes. - -== Travis - -Travis will run the tests both for community and product versions of the documentation for every PR and against -branches when they are updated. - - -== Tests - -=== Variables - -Missing variables are detected by looking for '{name}' in the built documentation. There are some cases where we -want to have these though, so the following are excluded: - -* If prefixed with `$` (for example `${name}`) -* If prefixed with `/` (for example `http://localhost:8080/{realm-name}`) -* If listed in `tests/src/resources/ignored-variables` - -=== Includes - -Checking for missing includes is pretty simple as AsciiDoctor will output _Unresolved directive..._ in the generated -HTML so we're just searching for that. - -=== Images - -Missing images are checked by searching for `` tags and checking that they src attribute refers to an existing -image. - -=== Internal links - -Internal links are checked by searching for `` and checking that the built documentation contains a -corresponding `` element. - -=== External links - -External links are checked by searching for `` then a connection is opened to verify if the link -is valid. If the returned status is 200 we're all good and we also check the returned document to see if it contains -a corresponding `` element or `` element. - -Specific URLs can be excluded by adding them to `tests/src/resources/ignored-links`. This is used for example for -`http://localhost:8080` which won't be available unless Keycloak is running on the machine where the tests are ran. - -For 302 redirects there is some special handling. The returned `Location` header needs to be added to -`tests/src/resources/ignored-link-redirects` otherwise the link will be marked as failed. It's important to verify the -redirected link before you add it to this file though as in some cases it redirects to some generic moved or unavailable -page. - -To prevent the checking of links being to slow to execute there is a cache file with valid links. This is stored in -`.verified-links`. The first time you run the tests you will notice that the checking links is fairly slow, but this -will be faster the second time you run it. Entries are purged from the cache after 1 day. - -Links to other guides within the documentation are handled specially. When testing local builds the link to the guide as -specified within document-attributes is replaced with the link to the locally built HTML file. When testing externally -built and hosted guides the base part of the links are replaced with `guideBaseUrl`. This allows leaving the links -in document-attributes to point to the location the documentation will eventually be published to while also allowing -testing cross referencing between guides. \ No newline at end of file diff --git a/pom.xml b/pom.xml deleted file mode 100644 index df016822b..000000000 --- a/pom.xml +++ /dev/null @@ -1,208 +0,0 @@ - - - 4.0.0 - - Keycloak Documentation Parent - org.keycloak.documentation - documentation-parent - 999.0.0-SNAPSHOT - pom - - - index - keycloak-images - - UTF-8 - 1.5.5 - 3.0.0 - 3.0.2 - 3.0.1 - 1.8 - 3.6.1 - 3.0.2 - 2.5.2 - 2.22.2 - - 1.8 - 1.8 - - archive - - - - header-maven-plugin - api_documentation - authorization_services - securing_apps - server_admin - server_development - release_notes - upgrading - aggregation - dist - - - - - tests - - - !skipProjectTests - - - - tests - - - - latest - - - latest - - - - latest - - - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - ${version.compiler.plugin} - - ${maven.compiler.target} - ${maven.compiler.source} - - - - org.apache.maven.plugins - maven-jar-plugin - ${version.jar.plugin} - - - org.apache.maven.plugins - maven-install-plugin - ${version.install.plugin} - - - org.apache.maven.plugins - maven-antrun-plugin - ${version.plugin.antrun} - - - echo-output - generate-resources - - run - - - - OUTPUT: file://${project.build.directory}/generated-docs/${masterFile}.html ${projectLatestBuild} - - - - - - - org.apache.maven.plugins - maven-dependency-plugin - ${version.plugin.dependency} - - - org.apache.maven.plugins - maven-surefire-plugin - ${version.surefire.plugin} - - - org.keycloak.documentation - header-maven-plugin - 999.0.0-SNAPSHOT - - - add-file-headers - - header - - - ${masterFile} - - - - - - org.asciidoctor - asciidoctor-maven-plugin - ${version.plugin.asciidoctor} - - - asciidoc-to-html - generate-resources - - process-asciidoc - - - ${basedir}/target/sources - ${masterFile}.adoc - html5 - coderay - - - ./ - left - left - font - true - - - - true - ${masterFile} - ${buildType} - - - - ${project.basedir} - - images/**/*.png - ${imagesDir}/**/*.png - - - - - - - - - - org.apache.maven.plugins - maven-resources-plugin - ${version.plugin.resources} - - - asciidoc-copy-resources - process-resources - - copy-resources - - - - - target/generated-docs - - - - - - - org.apache.maven.plugins - maven-assembly-plugin - ${version.plugin.assembly} - - - - - diff --git a/release-details b/release-details deleted file mode 100644 index 791d78ebf..000000000 --- a/release-details +++ /dev/null @@ -1,3 +0,0 @@ -VERSION=15.0.2 -SHORT_VERSION=15.0 -NPM_VERSION=15.0.2 diff --git a/release_notes/.asciidoctorconfig b/release_notes/.asciidoctorconfig deleted file mode 100644 index acb09a095..000000000 --- a/release_notes/.asciidoctorconfig +++ /dev/null @@ -1 +0,0 @@ -:imagesdir: {asciidoctorconfigdir} diff --git a/release_notes/docinfo-footer.html b/release_notes/docinfo-footer.html deleted file mode 120000 index a39d3bd0f..000000000 --- a/release_notes/docinfo-footer.html +++ /dev/null @@ -1 +0,0 @@ -../aggregation/navbar.html \ No newline at end of file diff --git a/release_notes/docinfo.html b/release_notes/docinfo.html deleted file mode 120000 index 14514f94d..000000000 --- a/release_notes/docinfo.html +++ /dev/null @@ -1 +0,0 @@ -../aggregation/navbar-head.html \ No newline at end of file diff --git a/release_notes/index.adoc b/release_notes/index.adoc deleted file mode 100644 index e7de48672..000000000 --- a/release_notes/index.adoc +++ /dev/null @@ -1,115 +0,0 @@ -:toc: left -:toclevels: 3 -:sectanchors: -:linkattrs: - -include::topics/templates/document-attributes.adoc[] - -:release_notes: - -= {releasenotes_name} - -:release_header_guide: {releasenotes_name_short} -:release_header_latest_link: {releasenotes_link_latest} -include::topics/templates/release-header.adoc[] - -== {project_name_full} 21.0.0 -include::topics/21_0_0.adoc[leveloffset=2] - - -== {project_name_full} 20.0.0 -include::topics/20_0_0.adoc[leveloffset=2] - -== {project_name_full} 19.0.0 -include::topics/19_0_0.adoc[leveloffset=2] - -== {project_name_full} 18.0.0 -include::topics/18_0_0.adoc[leveloffset=2] - -== {project_name_full} 17.0.0 -include::topics/17_0_0.adoc[leveloffset=2] - -== {project_name_full} 16.1.0 -include::topics/16_1_0.adoc[leveloffset=2] - -== {project_name_full} 16.0.0 -include::topics/16_0_0.adoc[leveloffset=2] - -== {project_name_full} 15.1.0 -include::topics/15_1_0.adoc[leveloffset=2] - -== {project_name_full} 15.0.1 -include::topics/15_0_1.adoc[leveloffset=2] - -== {project_name_full} 15.0.0 -include::topics/15_0_0.adoc[leveloffset=2] - -== {project_name_full} 14.0.0 -include::topics/14_0_0.adoc[leveloffset=2] - -== {project_name_full} 13.0.0 -include::topics/13_0_0.adoc[leveloffset=2] - -== {project_name_full} 12.0.0 -include::topics/12_0_0.adoc[leveloffset=2] - -== {project_name_full} 11.0.0 -include::topics/11_0_0.adoc[leveloffset=2] - -== {project_name_full} 10.0.0 -include::topics/10_0_0.adoc[leveloffset=2] - -== {project_name_full} 9.0.1 -include::topics/9_0_1.adoc[leveloffset=2] - -== {project_name_full} 9.0.0 -include::topics/9_0_0.adoc[leveloffset=2] - -== {project_name_full} 8.0.2 -include::topics/8_0_2.adoc[leveloffset=2] - -== {project_name_full} 8.0.1 -include::topics/8_0_1.adoc[leveloffset=2] - -== {project_name_full} 8.0.0 -include::topics/8_0_0.adoc[leveloffset=2] - -== {project_name_full} 7.0.1 -include::topics/7_0_1.adoc[leveloffset=2] - -== {project_name_full} 7.0.0 -include::topics/7_0_0.adoc[leveloffset=2] - -== {project_name_full} 6.0.0 -include::topics/6_0_0.adoc[leveloffset=2] - -== {project_name_full} 5.0.0 -include::topics/5_0_0.adoc[leveloffset=2] - -== {project_name_full} 4.8.0.Final -include::topics/4_8_0_final.adoc[leveloffset=2] - -== {project_name_full} 4.7.0.Final -include::topics/4_7_0_final.adoc[leveloffset=2] - -== {project_name_full} 4.6.0.Final -include::topics/4_6_0_final.adoc[leveloffset=2] - -== {project_name_full} 4.5.0.Final -include::topics/4_5_0_final.adoc[leveloffset=2] - -== {project_name_full} 4.4.0.Final -include::topics/4_4_0_final.adoc[leveloffset=2] - -== {project_name_full} 4.3.0.Final -include::topics/4_3_0_final.adoc[leveloffset=2] - -== {project_name_full} 4.2.0.Final -include::topics/4_2_0_final.adoc[leveloffset=2] - -== {project_name_full} 4.1.0.Final -include::topics/4_1_0_final.adoc[leveloffset=2] - -== {project_name_full} 4.0.0.Final -include::topics/4_0_0_final.adoc[leveloffset=2] -include::topics/4_0_0_beta3.adoc[leveloffset=2] diff --git a/release_notes/pom.xml b/release_notes/pom.xml deleted file mode 100644 index 9387b1307..000000000 --- a/release_notes/pom.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - 4.0.0 - - - org.keycloak.documentation - documentation-parent - 999.0.0-SNAPSHOT - ../ - - - Release Notes - release-notes - pom - - - - - org.asciidoctor - asciidoctor-maven-plugin - - - asciidoc-to-html - - ${basedir} - - - - - - maven-antrun-plugin - - - echo-output - - - - - - diff --git a/release_notes/topics/10_0_0.adoc b/release_notes/topics/10_0_0.adoc deleted file mode 100644 index 3f4fea782..000000000 --- a/release_notes/topics/10_0_0.adoc +++ /dev/null @@ -1,44 +0,0 @@ -= Highlights - -== Identity Brokering Sync Mode - -With Identity Brokering Sync Mode it is now possible to control if user profiles are updated on first login, or -every login from an external Identity Provider. It is also possible to override this behaviour on individual mappers. - -Thanks to https://github.com/Martin-Idel-SI[Martin Idel] - - -== Client Session Timeout for OpenID Connect / OAuth 2.0 - -Typically, an SSO session last for days if not months, while individual client sessions should ideally be a lot shorter. -With the introduction of client session timeout it is now possible to configure a separate timeout for individual clients, -as well as a default for all clients within a realm. - -Thanks to https://github.com/y-tabata[Yoshiyuki Tabata] - - -== OAuth 2.0 Token Revocation (RFC 7009) - -For applications that use Keycloak as an OAuth 2.0 Authorization Server there is now support to revoke refresh tokens -through the token revocation endpoint. - -Thanks to https://github.com/y-tabata[Yoshiyuki Tabata] - - -== Security Headers SPI and Response Filter - -A new SPI was introduced to allow better flexibility when setting security related headers on responses. This provides -a cleaner implementation within Keycloak, but also allows full customisation if needed. Security headers are now set -by a response filter instead of within the code itself, which makes it less error-prone, removing the chance that -some response are missing headers. - - -== Upgrade to WildFly 19 - -Keycloak server was upgraded to use WildFly 19 under the covers. - - -== Other improvements - -* Support for invoking Application Initiated Actions added to Keycloak JavaScript adapter -* Performance improvements to fetching resources and policies during evaluation \ No newline at end of file diff --git a/release_notes/topics/11_0_0.adoc b/release_notes/topics/11_0_0.adoc deleted file mode 100644 index 22bfd5ab6..000000000 --- a/release_notes/topics/11_0_0.adoc +++ /dev/null @@ -1,40 +0,0 @@ -= Highlights - -== LDAPv3 password modify operation - -Support for LDAPv3 password modify operation was added. Also the ability in the admin console to request metadata from the configured -LDAP server to see if it supports LDAPv3 password modify operation. - -Thanks to https://github.com/cachescrubber[cachescrubber] - -== Namespace support for LDAP group mapper - -Namespace support for LDAP group mapper allows you to map groups from LDAP under specified branch (namespace) of the Keycloak groups tree. -Previously groups from LDAP were always added as the top level groups in Keycloak. - -Thanks to https://github.com/tjuerge[Torsten Juergeleit] - - -== Upgrade to WildFly 20 - -Keycloak server was upgraded to use WildFly 20.0.1.Final under the covers. For more details, -please take a look at link:{upgradingguide_link_latest}[{upgradingguide_name}]. - - -== SAML POST binding is broken in the latest versions of browsers - -The `SameSite` value `None` for `JSESSIONID` cookie is necessary for correct behavior of the {project_name} SAML adapter. -Usage of a different value is causing resetting of the container's session with each request to {project_name}, when -the SAML POST binging is used. Refer to the following steps for -link:{adapterguide_link}#_saml-jboss-adapter-samesite-setting[Wildfly] and -link:{adapterguide_link}#_saml-tomcat-adapter-samesite-setting[Tomcat] to keep the correct behavior. Notice, that this -workaround should be working also with the previous versions of the adapter. - -== Other improvements - - -* Support for client offline session lifespan. Thanks to https://github.com/y-tabata[Yoshiyuki Tabata] -* Czech translation. Thanks to https://github.com/jakubknejzlik[Jakub Knejzlík] -* Possibility to fetch additional fields from the Facebook identity provider. Thanks to https://github.com/BartoszSiemienczuk[Bartosz Siemieńczuk] -* Support for AES 192 and AES 256 algorithms used for signed and encrypted ID tokens. Thanks to https://github.com/tnorimat[Takashi Norimatsu] -* Ability to specify signature algorithm in Signed JWT Client Authentication. Thanks to https://github.com/tnorimat[Takashi Norimatsu] \ No newline at end of file diff --git a/release_notes/topics/12_0_0.adoc b/release_notes/topics/12_0_0.adoc deleted file mode 100644 index 981373dc5..000000000 --- a/release_notes/topics/12_0_0.adoc +++ /dev/null @@ -1,50 +0,0 @@ -= Highlights - -== Keycloak.X distribution preview - -Introduction a preview of the new and upcoming Keycloak.X distribution. This distribution is powered by Quarkus, bringing -significant improvements to startup time and memory consumption, as well as making it a lot easier to configure Keycloak. - -== New Account console is now the default - -The new account console is no longer a preview feature and is now the default account console in Keycloak. The old account -console will stay around for a while. For those that have a custom theme for the old account console the old console -will be used by default, giving you the time to update your custom theme to the new account console. - -== OpenID Connect Back-Channel Logout - -Support for OpenID Connect Back-Channel Logout is now available, thanks to https://github.com/DaSmoo[DaSmoo] and -https://github.com/benjamin37[benjamin37]. - -== Upgrade to Wildfly 21 - -The {project_name} server was upgraded to use Wildfly 21 as the underlying container. - -== Ability to request AuthnContext in SAML identity provider - -Support for specification of AuthnContext section in authentication requests issued by SAML identity provider has been added. - -Thanks to https://github.com/lscorcia[lscorcia] - -== FAPI RW support and initial support to Client policies - -There was lots of the work done to have support for Financial-grade API Read and Write API Security Profile (FAPI RW). This is available -with the usage of Client policies and it is still in the preview state. You can expect more polishing in the next releases. -Thanks to https://github.com/tnorimat[Takashi Norimatsu] and all the members of the https://github.com/keycloak/kc-sig-fapi[FAPI Special interest group]. - -== Upgrade login theme to PatternFly 4 - -The {project_name} login theme components have been upgraded to PatternFly 4. -The old PatternFly 3 runs simultaneously with the new one, so it's possible to have PF3 components there. - -There are also design changes in the login theme for better user experience. -You can even define an icon for your custom Identity providers. -For details, please refer to the link:{developerguide_link}#custom-identity-providers-icons[docs]. - -== Gatekeeper EOL -Gatekeeper reached end of life, in November 21. This means that we no longer support, or update it. The announcement is available https://www.keycloak.org/2020/08/sunsetting-louketo-project.adoc[here]. - -== Other improvements - -* Support for OAuth2 Client Credentials grant without refresh token and without user session. Thanks to https://github.com/thomasdarimont[Thomas Darimont] -* Support for send access tokens to the OAuth2 Revocation endpoint diff --git a/release_notes/topics/13_0_0.adoc b/release_notes/topics/13_0_0.adoc deleted file mode 100644 index 9aed3c0e8..000000000 --- a/release_notes/topics/13_0_0.adoc +++ /dev/null @@ -1,43 +0,0 @@ -= Highlights - -== Upgrade to Wildfly 23 - -The {project_name} server was upgraded to use Wildfly 23.0.2.Final as the underlying container. - -== OAuth 2.0 Device Authorization Grant (RFC 8628) - -Support for OAuth 2.0 Device Authorization Grant is now available. - -Thanks to -// https://github.com/wadahiro [Hiroyuki Wada] <-- URL fails -Hiroyuki Wada, https://github.com/splatch[Łukasz Dywicki] -and https://github.com/Michito-Okai[Michito Okai]. - -== OpenID Connect Client Initiated Backchannel Authentication (CIBA) - -Support for OpenID Connect Client Initiated Backchannel Authentication (CIBA) is now available. - -Thanks to https://github.com/tnorimat[Takashi Norimatsu], -https://github.com/andriimurashkin[Andrii Murashkin], https://github.com/c4r1570p4e[Christophe Lannoy] and members of the FAPI WG for the implementation and feedback. - -== SAML Artifact binding in server to client communication - -Keycloak now supports communication with clients using SAML _Artifact_ binding. A new `Force Artifact Binding` option -was introduced in the client configuration, that forces communication with the client using artifact messages. For more -details proceed to link:{adminguide_link}#_client-saml-configuration[{adminguide_name}]. Please note, that with -this version, Keycloak SAML client adapter does NOT support Artifact binding. - -Thanks to https://github.com/AlistairDoswald[AlistairDoswald] and https://github.com/harture[harture]. - -== Support PKCE for identity brokering - -Keycloak can now leverage PKCE when brokering to an external OpenID Connect IdP. - -Thanks to https://github.com/thomasdarimont[thomasdarimont]. - -== Default roles processing improvement - -Default roles are now internally stored as composite roles of a new role usually named `default-roles-`. Instead of assigning -both realm and all client default roles directly to newly created users or users imported through Identity Brokering, just the role is -assigned to them and the rest of default roles are assigned as effective roles. This change improves performance of default roles processing, -especially with larger number of clients, because it is no longer necessary to go through all clients. diff --git a/release_notes/topics/14_0_0.adoc b/release_notes/topics/14_0_0.adoc deleted file mode 100644 index 7a750d8dd..000000000 --- a/release_notes/topics/14_0_0.adoc +++ /dev/null @@ -1,33 +0,0 @@ -= Highlights - -== Client Policies and Financial-grade API (FAPI) Support - -The {project_name} server has now official support for client policies and Financial-grade API (FAPI). This capability was previewed in earlier versions, but now -it is more polished and properly documented. Thanks to https://github.com/tnorimat[Takashi Norimatsu], who did most of the work on this. Also thanks -to https://github.com/DmitryMishchuk[Dmytro Mishchuk], https://github.com/andriimurashkin[Andrii Murashkin] and https://github.com/HryhoriiHevorkian[Hryhorii Hevorkian], who did a great deal of the work on this feature as well. -Finally thanks to all the members of the https://github.com/keycloak/kc-sig-fapi/blob/main/members.adoc[FAPI Special interest group] for their help and feedback. - -== Improvements to User Profile SPI and support for declarative configuration - -In this version, there were several improvements to the User Profile SPI in order -to prepare the ground on how users profiles are managed in {project_name}. - -One of these improvements is the support for configuring user profiles through the administration console. For more -details proceed to link:{adminguide_link}#user-profile[{adminguide_name}] - -Thanks to the community and all the individuals involved in this effort. - -== Improvements to offline sessions - -Offline session preloading has been improved and should be faster thanks to https://github.com/Flintholm[Peter Flintholm]. - -ifeval::[{project_community}==true] -As a preview feature, offline session preloading can be skipped in favor of lazy loading thanks -to https://github.com/thomasdarimont[Thomas Darimont]'s efforts. This feature has to be explicitly -activated in the server configuration, see Server administration guide for details. -endif::[] - - -== Other improvements - -* The support for configuring maximum number of active authentication sessions. The default value is set to 300 authentication sessions (browser tabs) per a browser's session diff --git a/release_notes/topics/15_0_0.adoc b/release_notes/topics/15_0_0.adoc deleted file mode 100644 index cbc348822..000000000 --- a/release_notes/topics/15_0_0.adoc +++ /dev/null @@ -1,9 +0,0 @@ -= Highlights - -== Financial-grade API (FAPI) Improvements, FAPI CIBA and Open Banking Brasil - -The {project_name} server has improved support for the Financial-grade API (FAPI). More specifically, {project_name} is now compliant with FAPI CIBA and with OpenBanking Brasil. -We also have support for CIBA ping mode. Thanks to https://github.com/tnorimat[Takashi Norimatsu], who did most of the work on FAPI CIBA and who is -continually doing a really awesome job for the {project_name} project. Also thanks to https://github.com/DmitryMishchuk[Dmytro Mishchuk], -https://github.com/andriimurashkin[Andrii Murashkin], https://github.com/HryhoriiHevorkian[Hryhorii Hevorkian] and https://github.com/leandrobortoli[Leandro José de Bortoli], who did a great deal of -the work on the FAPI compliance as well. Finally thanks to all the members of the https://github.com/keycloak/kc-sig-fapi/blob/main/members.adoc[FAPI Special interest group] for their help and feedback. diff --git a/release_notes/topics/15_0_1.adoc b/release_notes/topics/15_0_1.adoc deleted file mode 100644 index b42ea8e5b..000000000 --- a/release_notes/topics/15_0_1.adoc +++ /dev/null @@ -1,4 +0,0 @@ -= Highlights - -This release contains some important bug fixes. In addition, We would like to thank https://github.com/leandrobortoli[Leandro José de Bortoli] for his contributions to the -FAPI related functionalities such as JARM support and improvements in CIBA. \ No newline at end of file diff --git a/release_notes/topics/15_1_0.adoc b/release_notes/topics/15_1_0.adoc deleted file mode 100644 index bb801ab41..000000000 --- a/release_notes/topics/15_1_0.adoc +++ /dev/null @@ -1,44 +0,0 @@ -= Highlights - -== Quarkus distribution preview - -Without comparison the biggest highlight of this release is all the improvements that have been made to the Quarkus distribution. So many in fact, that it will be hard to list them all. - -The CLI has been polished to hell and back, and we believe it now provides a very simple and convenient approach to configuring and running Keycloak. It's almost so simple that documentation shouldn't be needed. - -To get started, just unpack the distribution, then type `bin/kc.[sh|bat] -h` to discover awesomeness! - -That doesn't mean we don't plan to provide documentation for configuring Keycloak, but it didn't quite make it this time around. In lack of documentation expect a blog post to follow the release introducing all the changes to the Quarkus distribution, as well as an overview on how to use it. - -We are rapidly moving towards making the Quarkus distribution our default distribution, and will soon deprecate the WildFly distribution. With this in mind it is important that as many people as possible give it a test-run and provide us with feedback if you find any usability issues, are not able to configure something with it, or if you discover any bugs. - -We'd love to hear your thoughts and get your feedback in https://github.com/keycloak/keycloak/discussions/8654[GitHub Discussions]! - -== New Admin Console preview - -The new admin console is shaping up really nicely, and a preview is included in the main distribution. It is not quite feature complete yet, but there are still loads of things to try out. - -== WildFly update - -Upgrading from WildFly 23 to WildFly 25 has taken a lot longer than we would have liked. We're still working hard on this and are hoping to release Keycloak 16 as soon as possible with the upgrade, but as we wanted to get the updates to the Quarkus distribution out there we are doing this release in the meantime. - -== WildFly adapter deprecation - -In WildFly 25 there is now excellent native OpenID Connect support without the need for the Keycloak adapter. With this in mind we are deprecating our WildFly adapter and will not support WildFly 25, but it will be around for a while for older WildFly versions and Red Hat JBoss Enterprise Application Platform 7.y. - -== Spring Security and Boot adapter deprecation - -A long time ago, with Spring Security 5.0, there is now native support for OAuth 2.0 and OpenID Connect in Spring. With this in mind now is the time to start deprecating our Spring Boot and Security adapters. - -== OpenID Connect Front-Channel Logout Support - -{project_name} now supports https://openid.net/specs/openid-connect-frontchannel-1_0.html[OpenID Connect Front-Channel Logout 1.0]. - -For more details, take a look at link:{adminguide_link}#_oidc-logout[{adminguide_name}]. - -Thanks to https://github.com/rhyamada[Ronaldo Yamada] for the contribution. - -== Deprecated features in the {project_operator} - -With this release, we have deprecated and/or marked as unsupported some features in the {project_operator}. This -concerns the Backup CRD and the operator managed Postgres Database. diff --git a/release_notes/topics/16_0_0.adoc b/release_notes/topics/16_0_0.adoc deleted file mode 100644 index fdbd3772b..000000000 --- a/release_notes/topics/16_0_0.adoc +++ /dev/null @@ -1,13 +0,0 @@ -= Highlights - -== Upgrade to Wildfly 25.0.1 - -Keycloak server was upgraded to use Wildfly 25.0.1.Final as the underlying container. - -WildFly 25 drops support for the legacy security subsystem, which is being replaced fully by Elytron. This requires significant changes to how Keycloak is configured. Please, refer to the migration guide for more details. - -For more information on WildFly 25 refer to the https://www.wildfly.org/news/2021/10/05/WildFly25-Final-Released/[WildFly 25 release notes]. - -== Upgrade to Quarkus 2.5.3 - -Keycloak.X Quarkus preview distribution was upgraded to Quarkus 2.5.3. \ No newline at end of file diff --git a/release_notes/topics/16_1_0.adoc b/release_notes/topics/16_1_0.adoc deleted file mode 100644 index ae35abafd..000000000 --- a/release_notes/topics/16_1_0.adoc +++ /dev/null @@ -1,7 +0,0 @@ -= Highlights - -== Upgrade to Wildfly 26.0.0 - -Keycloak server was upgraded to use Wildfly 26.0.0.Final as the underlying container. - -For more information on WildFly 26 refer to the https://www.wildfly.org/news/2021/12/16/WildFly26-Final-Released/[WildFly 26 release notes]. \ No newline at end of file diff --git a/release_notes/topics/17_0_0.adoc b/release_notes/topics/17_0_0.adoc deleted file mode 100644 index 99b71242a..000000000 --- a/release_notes/topics/17_0_0.adoc +++ /dev/null @@ -1,37 +0,0 @@ -= Highlights - -== Quarkus distribution is now fully supported - -The default Keycloak distribution is now based on Quarkus. The new distribution is faster, leaner, and a lot easier to configure! - -We appreciate migrating from the WildFly distribution is not going to be straightforward for everyone, since how you start and configure Keycloak has radically changed. With that in mind we will continue to support the WildFly distribution until June 2022. - -For information on how to migrate to the new distribution check out the https://www.keycloak.org/migration/migrating-to-quarkus[Quarkus Migration Guide]. - -== Quarkus distribution updates - -A lot of effort went into polishing and improving the Quarkus distribution to make it as good as an experience as possible. A few highlights include: - -* A new approach to documentation in form of server guides to help you install and configure Keycloak -* Upgraded Quarkus to 2.7.0.Final -* Configuration file is no longer Java specific, and aligns configuration keys with CLI arguments -* Clearer separation between `build options` and `runtime configuration`. -* `h2-mem` and `h2-file` databases renamed to `dev-mem` and `dev-file`. -* Simplified enabling and disabling features -* Custom, and unsupported, Quarkus configuration is done through `conf/quarkus.properties`. -* Ability to add custom Java Options via JAVA_OPTS_APPEND (thanks to https://github.com/dasniko[dasniko]) -* Initial logging capabilities -* Initial support for Cross-DC -* User-defined profiles are no longer supported but using different configuration files to achieve the same goal -* Quickstarts updated to use the new distribution -== Other improvements - -=== Offline sessions lazy loaded - -The offline sessions are now lazily fetched from the database by default instead of preloading during the server startup. -To change the default behavior, see link:{adminguide_link}#offline-sessions-preloading[{adminguide_name}]. - -=== Improved User Search - -{project_name} now supports a glob-like syntax for the user search when listing users in the Admin Console, -which allows for three different types of searches: prefix (`foo*` which became the default search), infix (`\*foo*`), and exact `"foo"`) diff --git a/release_notes/topics/18_0_0.adoc b/release_notes/topics/18_0_0.adoc deleted file mode 100644 index a9ca945e1..000000000 --- a/release_notes/topics/18_0_0.adoc +++ /dev/null @@ -1,118 +0,0 @@ -= New Operator preview - -With this release, we're introducing a brand new {project_operator} as a preview. Apart from being rewritten from -scratch, the main user-facing change from the legacy Operator is the used {project_name} distribution – the new Operator -uses the Quarkus distribution of {project_name}. With that, the API (in form of Custom Resource Definitions) has changed. -For details, incl. installation and migration instructions, see the https://www.keycloak.org/guides#operator[Operator related guides]. - -The link:{operatorRepo_link}[legacy Operator] will receive updates until Keycloak 20 when the {project_name} WildFly -distribution reaches EOL. - -== OperatorHub versioning scheme -To avoid version conflicts with the legacy Operator, the 18.0.0 version of the new Operator is released as version -`20.0.0-alpha.1` on OperatorHub. The legacy Operator versioning scheme remains the same, i.e. it is released as 18.0.0. - -The same pattern will apply for future {project_name} 18 and 19 releases, until version 20 where the legacy Operator -reaches EOL. - -= New Admin Console preview - -The new Admin Console is now graduated to preview, with the plan for it to become the default admin console in Keycloak 19. - -If you find any issues with the new console, or have some suggestions for improvements, please let us know through https://github.com/keycloak/keycloak/discussions/categories/new-admin-console[GitHub Discussions]. - -= Step-up authentication - -{project_name} now supports Step-up authentication. This feature was added in Keycloak 17, and was further polished in this version. - -For more details, see link:{adminguide_link}#_step-up-flow[{adminguide_name}]. - -Thanks to https://github.com/CorneliaLahnsteiner[Cornelia Lahnsteiner] and https://github.com/romge[Georg Romstorfer] for the contribution. - -= Client secret rotation - -{project_name} now supports Client Secret Rotation through customer policies. This feature is now available as a preview feature and allows that confidential clients can be provided with realm policies allowing the use up to two secrets simultaneously. - -For more details, see link:{adminguide_link}#_secret_rotation[{adminguide_name}]. - -= Recovery Codes - -Recovery Codes as another way to do two-factor authentication is now available as a preview feature. - -= OpenID Connect Logout Improvements - -Some fixes and improvements were made to make sure that {project_name} is now fully compliant with all the OpenID Connect logout specifications: - -* OpenID Connect RP-Initiated Logout 1.0 -* OpenID Connect Front-Channel Logout 1.0 -* OpenID Connect Back-Channel Logout 1.0 -* OpenID Connect Session Management 1.0 - -For more details, see link:{adminguide_link}#_oidc-logout[{adminguide_name}]. - -= WebAuthn improvements - -{project_name} now supports WebAuthn id-less authentication. This feature allows that WebAuthn Security Key will identify the user during authentication as long as the -security key supports Resident Keys. For more details, see link:{adminguide_link}#_webauthn_loginless[{adminguide_name}]. -Thanks to https://github.com/vanrar68[Joaquim Fellmann] for the contribution. - -There are more WebAuthn improvements and fixes in addition to that. - -= The deprecated `upload-script` feature was removed - -The `upload-script` feature has been marked as deprecated for a very long time. In this release, it was completely removed, and it is no longer supported. - -If you are using any of these capabilities: - -* OpenID Connect Script Mapper -* Script Authenticator (Authentication Execution) -* JavaScript Policies - -You should consider reading this https://www.keycloak.org/docs/latest/server_development/#_script_providers[documentation] in order to understand how to still rely -on these capabilities but deploying your scripts to the server rather than managing them through the management interfaces. - -= Session limits - -{project_name} now supports limits on the number of sessions a user can have. Limits can be placed at the realm level or at the client level. - -For more details, see link:{adminguide_link}#_user_session_limits[{adminguide_name}]. -Thanks to https://github.com/mfdewit[Mauro de Wit] for the contribution. - -= SAML ECP Profile is disabled by default - -To mitigate the risk of abusing SAML ECP Profile, {project_name} now blocks -this flow for all SAML clients that do not allow it explicitly. The profile -can be enabled using _Allow ECP Flow_ flag within client configuration, -see link:{adminguide_link}#_client-saml-configuration[{adminguide_name}]. - -= Quarkus distribution - -== Import realms at startup - -The {project_name} Quarkus distribution now supports importing your realms directly at start-up. For more information, check the corresponding https://www.keycloak.org/server/importExport[guide]. - -== JSON and File Logging improvements - -The {project_name} Quarkus distribution now initially supports logging to a File and logging structured data using JSON. - -For more information on the improvements, check the corresponding https://www.keycloak.org/server/logging[guide]. - -=== Environment variable expansion for values in keycloak.conf - -The {project_name} Quarkus distribution now supports expanding values in keycloak.conf from environment variables. - -For more information, check the corresponding https://www.keycloak.org/server/configuration[guide]. - -== New Option db-url-port - -You can now change the port of your jdbc connection string explicitly by setting the new `db-url-port` configuration option. As for the other convenience options, this option will be overridden by the value of a full `db-url`, if set. - -== Split metrics-enabled option into health-enabled and metrics-enabled -The `metrics-enabled` option now only enables the metrics for {project_name}. To enable the readiness and liveness probe, there's the new build option `health-enabled`. This allows more fine-grained usage of these options. - -= Other improvements - -* Account console alignments with latest PatternFly release. -* Support for encrypted User Info endpoint response. Thanks to https://github.com/giacomoa[Giacomo Altiero] -* Support for the algorithm RSA-OAEP with A256GCM used for encryption keys. Thanks to https://github.com/fbrissi[Filipe Bojikian Rissi] -* Support for login with GitHub Enterprise server. Thanks to https://github.com/nngo[Neon Ngo] diff --git a/release_notes/topics/19_0_0.adoc b/release_notes/topics/19_0_0.adoc deleted file mode 100644 index 431090a27..000000000 --- a/release_notes/topics/19_0_0.adoc +++ /dev/null @@ -1,95 +0,0 @@ -= OpenID Connect and SAML Adapters End-of-life - -Some Keycloak OpenID Connect adapters have reached end-of-life and are not included in this release. - -== Fuse 6 and 7 (OpenID Connect) - -Keycloak will no longer be providing adapters for Fuse 6 or 7. If you need adapters for Fuse please leverage https://access.redhat.com/products/red-hat-single-sign-on[Red Hat Single Sign-On] 7.x adapters. - -== JBoss AS 7 and EAP 6 (OpenID Connect and SAML) - -JBoss AS 7 has been unmaintained for a very long time. If you are still using JBoss AS 7 we recommend migrating to WildFly and leveraging the native OIDC support in WildFly. - -Red Hat customers using Red Hat JBoss Enterprise Application Platform 6.x should use https://access.redhat.com/products/red-hat-single-sign-on[Red Hat Single Sign-On] 7.x adapters. These can be used in combination with the Keycloak server. - -== Jetty 9.2 and 9.3 (OpenID Connect and SAML) - -Jetty 9.2 reached end of life in 2018, while Jetty 9.3 reached end of life in 2020. If you are still using these versions we recommend upgrading to Jetty 9.4 as soon as possible. - -== Spring Boot 1 (OpenID Connect) - -Spring Boot 1.x reached end of life in 2019. If you are still using Spring Boot 1 we recommend upgrading to Spring Boot 2 as soon as possible. - -== WildFly legacy security layer (OpenID Connect and SAML) - -In WildFly 25 the legacy security layer was removed, going forward only Elytron will be supported. We recommend anyone using an older version of WildFly to upgrade and leverage native OIDC support in WildFly. - -Red Hat customers using Red Hat JBoss Enterprise Application Platform 7.x should use https://access.redhat.com/products/red-hat-single-sign-on[Red Hat Single Sign-On] 7.x adapters. These can be used in combination with the Keycloak server. - -= New Admin Console graduation - -The new Admin Console is now graduated to the default admin console, with the old console now deprecated. The old console will be removed in Keycloak 21. - -= Changes in Keycloak storage - -The Keycloak storage is changing, and the current storage, while still supported, will eventually be replaced with a brand-new implementation. -This change brings better support for cloud-native storages, no-downtime abilities, and better support for implementing custom storages for additional areas apart from users. - -It means several deep changes in the supported features of the current store will become _legacy_ features. -The legacy store and the new store cannot be used simultaneously; only one store can be active at a time. - -The most visible change is that the User Storage SPI is incompatible with the new storage API, the Map Storage API. -Thus, the User Storage SPI will be deprecated with legacy store and will move to a separate module called `keycloak-model-legacy`. -This change impacts several areas, especially areas related to user federation and custom user providers. - -Furthermore, APIs have been consolidated so that the details of the storage layer will be transparent to the REST service layer. -Specifically, the services will not be able to differentiate cached and non-cached objects, nor specifically access federated versus local storage. - -Hence, custom extensions that access objects in local storage or cache through `KeycloakSession` -methods must be reviewed. -See link:{upgradingguide_link}[{upgradingguide_name}] for details. - -= OIDC Logout changes - -In the previous release, we added support for OIDC logout. This release contains a few other fixes and polishing. The highlights include: - -- Support for the `client_id` parameter, which was added in recent draft of the OIDC RP-Initiated Logout specification. As a result, no need exists to use the `Consent Required` flag of the -client to show the logout confirmation screen. -- Configuration option `Valid Post Logout Redirect URIs` added to the OIDC client. This change is aligned with the OIDC specification, which allows you to use a different set of redirect URIs for redirect after login and logout. -Value `+` used for `Valid Post Logout Redirect URIs` means that the logout will use the same set of redirect URIs as specified by the option of `Valid Redirect URIs`. This change also matches the default behavior when migrating -from a previous version due to backwards compatibility. - -For more details, see the link:{adminguide_link}#_oidc-logout[{adminguide_name}]. - -= Update Email Workflow - -There is new preview feature `UPDATE_EMAIL`. When it is enabled and corresponding flag enabled in the realm, the users will be required -to confirm updating their email by clicking the link, which will be sent to their new email address. For more details, see the link:{adminguide_link}#_update-email-workflow[{adminguide_name}]. -Thanks to https://github.com/reda-alaoui[Réda Housni Alaoui] for the contribution. - -= Deprecated `podDisruptionBudget` in the legacy {project_operator} - -With this release, we have deprecated `podDisruptionBudget` field in the Keycloak CR of the https://github.com/keycloak/keycloak-operator[legacy {project_operator}]. -This optional field will be ignored when the Operator is deployed on Kubernetes version 1.25 and higher. - -As a workaround, you can manually create the Pod Disruption Budget in your cluster, for example: -```yaml -apiVersion: policy/v1 -kind: PodDisruptionBudget -metadata: - labels: - app: keycloak - name: keycloak -spec: - maxUnavailable: 1 - selector: - matchLabels: - component: keycloak -``` -See also the https://kubernetes.io/docs/tasks/run-application/configure-pdb/[Kubernetes Documentation]. - -= Initial Support for centralized logging - -Starting with version 19, Keycloak supports sending logs using GELF to centralized logging solutions like ELK, EFK or Graylog out of the box. - -You can find the documentation and examples to get you up and running quickly in the https://www.keycloak.org/server/logging#_centralized_logging_using_gelf[logging guide] \ No newline at end of file diff --git a/release_notes/topics/20_0_0.adoc b/release_notes/topics/20_0_0.adoc deleted file mode 100644 index c1fc63a83..000000000 --- a/release_notes/topics/20_0_0.adoc +++ /dev/null @@ -1,93 +0,0 @@ -= WildFly distribution removed - -In Keycloak 17.0.0 the new Quarkus based distribution of Keycloak, while the WildFly based distribution was deprecated. -With this release the WildFly distribution has been removed, and is no longer supported. - -If you are still using the WildFly distribution we highly encourage migrating to the Quarkus distribution as soon as -possible, see the https://www.keycloak.org/migration/migrating-to-quarkus[Migration Guide] for more details. - -= New Keycloak Operator upgrade - -We are happy to announce that the new Keycloak Operator for the Quarkus based distribution is no longer a preview -feature. We added new functionality as well as a number of improvements, some which has resulted in breaking changes. - -== Realm Operator - -As the new Operator currently lacks some of the CRs (e.g. Client and User), we're introducing a temporary workaround in -the form of a Realm Operator. Please see its https://github.com/keycloak/keycloak-realm-operator[GitHub Repository] for -more details. See also https://www.keycloak.org/2022/09/operator-crs["The future of Keycloak Operator CRs" blogpost]. - -= Supported OpenJDK versions - -Keycloak now supports OpenJDK 17 both for the server and adapters. - -With the removal of the WildFly based distribution there is no longer support for running the Keycloak server on OpenJDK 8. -We also plan to remove support for Keycloak adapters on OpenJDK 8 in Keycloak 21. - -Starting with Keycloak 22 we plan to only support the latest OpenJDK LTS release and aiming to quickly also support the -latest OpenJDK release. That means we will be also removing OpenJDK 11 support for the Keycloak server in Keycloak 22. - -= Hostname provider now supports configuring the complete base URL - -In this release, we are introducing two additional server options to set the base URL for frontend request and the Admin -Console: - -* `hostname-url` -* `hostname-admin-url` - -More details can be found at the https://www.keycloak.org/server/hostname[Configuring the Hostname Guide]. - -= Improvements to `kc.bat` when running Keycloak on Windows - -In this release, we are making important changes to `kc.bat` to give the same experience as when running on Linux. - -= Upgrade of embedded H2 database - -{project_name} ships for development purposes with an H2 database driver. As it is intended for development purposes -only, it should never be used in a production environment. - -In this release, the H2 driver has been upgraded from version 1.x to version 2.x. - -= Feature guard for hosting the Keycloak JavaScript adapter - -Applications are able to load `keycloak.js` directly from the Keycloak server. As it's not considered a best-practice -to load JavaScript libraries this way there is now a feature guard that allows disabling this ability. - -In Keycloak 21 we will deprecate this option, and in Keycloak 22 we plan to completely remove the ability to load -`keycloak.js` from the Keycloak server. - -= OTP Application SPI - -In previous releases the list of OTP applications displayed to users was hard-coded in Keycloak. With the introduction of -the OTP Application SPI it is now possible to disable built-in OTP applications, as well as adding custom OTP Applications. - -= Custom Identity Providers can now set an icon for the provider - -A custom identity provider can now set the icon used on the login pages. Thanks to https://github.com/klausbetz[Klaus Betz], -who happens also to maintain -https://github.com/klausbetz/apple-identity-provider-keycloak[an extension to Keycloak to support log in with AppleID]. - -= FIPS 140-2 experimental support - -There is now experimental support for deploying Keycloak into a FIPS 140-2 enabled environment. There will be a blog post -with the details shortly after the release with the details how you can try it. Feedback is welcome! - -Thanks to https://github.com/david-rh[David Anderson], who contributed parts of this feature. Also, thanks to -https://github.com/sudeepd[Sudeep Das] and https://github.com/isaacjensen[Isaac Jensen] for their initial prototype - effort, which was used as an inspiration. - -= Search groups by attribute - -It is now possible to search groups by attribute through the Admin REST API. Thanks to -https://github.com/Redhat-Alice[Alice] for this contribution. - -= View group membership in the account console - -It is now possible to allow users to view their group memberships in the account console. Thanks to -https://github.com/cgeorgilakis[cgeorgilakis] for this contribution. - -= Deprecated methods from data providers and models were removed - -Several deprecated methods were removed from data providers and models. If not done already, their usage needs to be -replaced with the corresponding replacement documented in Javadoc of Keycloak 19 release. See -link:{upgradingguide_link}[{upgradingguide_name}] for more details. diff --git a/release_notes/topics/21_0_0.adoc b/release_notes/topics/21_0_0.adoc deleted file mode 100644 index 520812b26..000000000 --- a/release_notes/topics/21_0_0.adoc +++ /dev/null @@ -1,91 +0,0 @@ -= Old Admin Console removed - -In Keycloak 19 the new admin console was graduated to the new default admin console, and the old admin console was -deprecated. In this release the old admin console has been removed completely. - -= Keycloak uses Micrometer for metrics - -Keycloak provides an optional a metrics endpoint which exports metrics in the Prometheus format. -In this release the implementation to provide this data switched from SmallRye to Micrometer. -Due to this change, metrics have been renamed. - -See the migration guide for details. - -= Java 11 support for Keycloak server deprecated - -Running the Keycloak server with Java 11 is now deprecated, and planned to be removed in Keycloak 22. - -Adapters remain supported on Java 8, Java 11, and Java 17. However, we are planning to remove support for Java 8 in the -not too distant future. - -= Hashicop Vault no longer supported - -We removed the out-of-box support for Hashicorp vault in this release. - -See this https://github.com/keycloak/keycloak/discussions/16446[discussion] for more details. - -= SAML SP metadata changes - -Prior to this release, SAML SP metadata contained the same key for both -signing and encryption use. Starting with this version of Keycloak, -we include only encryption intended realm keys for encryption use -in SP metadata. For each encryption key descriptor we also specify -the algorithm that it is supposed to be used with. The following table shows -the supported XML-Enc algorithms with the mapping to Keycloak realm keys. -See the link:{upgradingguide_link}[{upgradingguide_name}] for more details. - -[cols="1,1"] -|=== -|*XML-Enc algorithm* -|*Keycloak realm key algorithm* - -|https://www.w3.org/TR/2002/REC-xmlenc-core-20021210/Overview.html#rsa-oaep-mgf1p[rsa-oaep-mgf1p] -|RSA-OAEP - -|https://www.w3.org/TR/2002/REC-xmlenc-core-20021210/Overview.html#rsa-1_5[rsa-1_5] -|RSA1_5 -|=== - -= Deprecated methods from user session provider were removed - -Several deprecated methods were removed from user session provider. If not done already, -their usage needs to be replaced with the corresponding replacement documented in Javadoc -of Keycloak 20 release. See link:{upgradingguide_link}[{upgradingguide_name}] for more details. - -= New storage: `IS_CLIENT_ROLE` searchable field was deprecated - -The `IS_CLIENT_ROLE` searchable field from the `RoleModel` was deprecated. It -should be replaced with the `CLIENT_ID` searchable field used with the operators -`EXISTS` or `NOT_EXISTS`. See JavaDoc of Keycloak 21 for more details. - -= FIPS 140-2 preview support - -FIPS 140-2 support in Keycloak, which was experimental in the previous release, is now promoted to preview. There were many fixes and improvements to create this preview version. -For the details, see the https://www.keycloak.org/guides#server[FIPS documentation]. Feedback is welcome! - -Thanks again to https://github.com/david-rh[David Anderson], https://github.com/sudeepd[Sudeep Das] and https://github.com/isaacjensen[Isaac Jensen] -for their huge help with this feature. - -= Support for the standard `Forwarded` header when running behind a reverse proxy - -In addition to recognize the non-standard `X-Forwarded-*` to fetch information -added by proxies that would otherwise be altered or lost when proxy servers are involved in the path of the request, Keycloak -can now leverage the standard `Forwarded` header for the same purpose. - -For more details, see the https://www.keycloak.org/server/reverseproxy[Using a reverse proxy] guide. - -Please, make sure your proxy is also overriding the `Forwarded` header when making requests to Keycloak nodes. - -= The container image is now based on ubi9-micro - -To enhance security, the https://quay.io/repository/keycloak/keycloak?tab=info[Keycloak Container Image] has been modified in two ways: First, it is now based on UBI9, rather than UBI8. Second, we have switched to `+-micro+`, whereas `+-minimal+` was used before. - -The change to UBI9 will not have any impact on most users. In rare cases the glibc error https://github.com/keycloak/keycloak/issues/17290[CPU does not support x86-64-v2] may appear. `+x86-64-v2+` has been available from processors since 2009. You're most likely to encounter this issue when your virtualization environment is misconfigured. - -The change from `+-minimal+` to `+-micro+` has more potential impact. Users making simple customizations to the image won't notice any difference, however any user that installs RPMs will need to change how they do that. The https://www.keycloak.org/server/containers[container guide] has been updated to show you how. - -As a result of these changes, there has been an 82% reduction in known CVEs affecting the Keycloak Container Image! - -= Other improvements - -* Option to disable client registration access token rotation. Thanks to https://github.com/reda-alaoui[Réda Housni Alaoui] diff --git a/release_notes/topics/4_0_0_beta3.adoc b/release_notes/topics/4_0_0_beta3.adoc deleted file mode 100644 index 9a422b2c0..000000000 --- a/release_notes/topics/4_0_0_beta3.adoc +++ /dev/null @@ -1,49 +0,0 @@ -= Authorization Services - -== UMA 2.0 - -UMA 2.0 is now supported for Authorization Services, including support for users to manage user access through -the account management console. There are also other additions and improvements to authorization services. - -== Pushed Claims - -Clients can now push additional claims and have them used by policies when evaluating permissions. - -== Resource Attributes - -It is now possible to define attributes on resources in order to have them used by policies when evaluating permissions. - -= Themes and Theme Resources - -It is now possible to hot-deploy themes to Keycloak through a regular provider deployment. We have also added support for theme resources, which allows adding additional templates and resources without creating a theme. This is useful for custom authenticators that require additional pages to be added to the authentication flow. - -We have also added support to override the theme for specific clients. If that is not adequate for your needs, then there is also a new Theme Selector SPI that allows you to implement custom logic to select the theme. - -= Instagram Identity Provider - -We have added support to login with Instagram. Thanks to https://github.com/hguerrero[hguerrero] for the contribution. - -= Search by User ID in Admin Console - -To search for a user by id in the admin console you previously had to edit the URL. It is now possible to search -directly in the user search field. - -= Adapters - -== Spring Boot 2 - -We now have support for Spring Boot 2. - -== Fuse 7 - -We now have support for Fuse 7. - -== JavaScript - Native Promise Support - -The JavaScript adapter now supports native promises. It retains support for the old style promises as well. -Both can be used interchangeably. - -== JavaScript - Cordova Options - -It is now possible to pass Cordova-specific options to login and other methods in the JavaScript adapter. -Thanks to https://github.com/looorent[loorent] for the contribution. diff --git a/release_notes/topics/4_0_0_final.adoc b/release_notes/topics/4_0_0_final.adoc deleted file mode 100644 index 9606955f9..000000000 --- a/release_notes/topics/4_0_0_final.adoc +++ /dev/null @@ -1,88 +0,0 @@ -= Client Scopes and support for OAuth 2 scope parameter - -We added support for Client Scopes, which replaces Client Templates. Client Scopes are a more flexible approach and also provides -better support for the OAuth `scope` parameter. - -There are changes related to Client Scopes to the consent screen. The list on the consent screen is now linked to client scopes -instead of protocol mappers and roles. - -See the documentation and migration guide for more details. - -= OAuth 2 Certificate Bound Access Tokens - -We now have a partial implementation of the specification -https://datatracker.ietf.org/doc/html/draft-ietf-oauth-mtls-08[OAuth 2.0 Mutual TLS Client Authentication and Certificate Bound Access Tokens] . -More accurately we have support for the Certificate Bound Access Tokens. If your confidential client is able to use 2-way SSL, -{project_name} will be able to add the hash of the client certificate into the tokens issued for the client. At this moment, -it's just the {project_name} itself, which verifies the token hashes (for example during `refresh token` requests). -We plan to add support to adapters as well. We also plan to add support for Mutual TLS Client Authentication. - -Thanks to https://github.com/tnorimat[tnorimat] for the contribution. - -= Authorization Services - -== UMA 2.0 Support - -UMA 2.0 is now supported for Authorization Services. Check the documentation for more details -if you are coming from previous versions of {project_name}. - -=== User-Managed Access through the {project_name} Account Service - -Now end-users are able to manage their resources and the permissions associated with them through the {project_name} Account Service. -From there, resource owners can now check their resources, share resources with another users as well approve requests from other users. - -=== Asynchronous Authorization Flow - -When using UMA, client applications can now choose whether or not an authorization request should start an authorization flow -to ask for the resource owner approval. This functionality allows applications to ask for resource owner -approval when trying to access one of his resources on behalf of another user. - -=== User-Managed Permission API - -Resource servers are now capable of associating additional policies to resources owned by a particular user. The new API provides -operations to manage these permissions using different policy types such as role, group, user, client or a condition using JavaScript. - -== Pushed Claims - -Clients applications are now able to send arbitrary claims to {project_name} along with an authorization request in order to -evaluate permissions based on these claims. This is a very handy addition when access -should be granted (or denied) in the scope of a specific transaction or based on information about the runtime. - -== Resource Attributes - -It is now possible to associated attributes with resources protected by {project_name} and use these same attributes to evaluate permissions -from your policies. - -== Policy enforcer now accepts regular access tokens - -In some situations, you may want to just send regular access tokens to a resource server but still be able to enforce policies on these resources. - -One of the main changes introduced by this release is that you are no longer required to exchange access tokens with RPTs in -order to access resources protected by a resource server (when not using UMA). Depending on how the policy enforcer is configured on the resource server side, you can just send regular -access tokens as a bearer token and permissions will still be enforced. - -== Policy enforcer can now load resources from the server on-demand - -Until now, when deploying an application configured with a `policy-enforcer`, the policy enforcer would either load all protected paths -from the server or just map these paths from the adapter configuration. Users can now decide to load paths on-demand from the server and avoid -map these resources in the adapter configuration. Depending on how many protected resources you have this functionality can also improve the time to -deploy an application. - -== Policy enforcer now supports configuring the resource cache - -In order to avoid unnecessary hits to the server, the policy enforcer caches the mapping between protected resources and their corresponding paths -in your application. Users can now configure the behaviour of the cache or even completely disable it. - -== Claim Information Points - -The `policy-enforcer` definition on the adapters (`keycloak.json`) was also updated to support the concept of pushed claims. There -you have the concept of a `claim-information-point` which can be set to push claims from different sources such as the HTTP request or even -from an external HTTP service. - -== Improvements to the Evaluation API - -The Evaluation API used to implement policies in {project_name}, especially JavaScript and Drools policies, provides now methods to: - -* Access information from the current realm such as check for user roles, groups and attributes -* Push back arbitrary claims to the resource server in order to provide additional information on how a specific permissions should -be enforced \ No newline at end of file diff --git a/release_notes/topics/4_1_0_final.adoc b/release_notes/topics/4_1_0_final.adoc deleted file mode 100644 index 8e68ada79..000000000 --- a/release_notes/topics/4_1_0_final.adoc +++ /dev/null @@ -1,3 +0,0 @@ -= Making Spring Boot 2 the default starter - -Starting with release 4.1, the Spring Boot starter will be based on the Spring Boot 2 adapter. If you are using an older Spring Boot version, the keycloak-legacy-spring-boot-starter is available. \ No newline at end of file diff --git a/release_notes/topics/4_2_0_final.adoc b/release_notes/topics/4_2_0_final.adoc deleted file mode 100644 index 3f4b5427e..000000000 --- a/release_notes/topics/4_2_0_final.adoc +++ /dev/null @@ -1,17 +0,0 @@ -= Browser tab support for Cordova - -We now have support for using browser tab and universal links in the JavaScript adapter for Cordova. This enables SSO -between multiple applications as well as increases security. - -Thanks to https://github.com/gtudan[gtudan] for the contribution. - - -= SAML adapter multitenancy support - -The SAML adapter can support multi-tenancy now just like the built-in adapter for OpenID Connect. - - -= An option to create claims with dots (.) in them - -In previous versions, it was not possible to create claims in the token using a claim name containing a dot (.) character. Now it is -possible to escape the dot character in the configuration, so a claim name with the dot character can be used. \ No newline at end of file diff --git a/release_notes/topics/4_3_0_final.adoc b/release_notes/topics/4_3_0_final.adoc deleted file mode 100644 index fb8c65dcc..000000000 --- a/release_notes/topics/4_3_0_final.adoc +++ /dev/null @@ -1,59 +0,0 @@ -= Hostname SPI - -The hostname SPI introduces a more flexible way to configure the hostname for {project_name}. There are two -built-in providers. The first is request, which uses the request headers to determine the hostname. The second -is fixed, which allows configuring a fixed hostname. The latter makes sure that only valid hostnames can be -used and also allows internal applications to invoke {project_name} through an alternative URL. - -For more details refer to the threat mitigation section in the link:{adminguide_link}[{adminguide_name}]. - -= X509 Client Authenticator - -The newly added Client Authenticator uses X509 Client Certificates and Mutual TLS to secure a connection from the client. In addition to that -the Keycloak Server validates Subject DN field of the client's certificate. - -= Performance improvements to Authorization Services - -For this release, we improved policy evaluation performance across the board, increasing reliability and throughput. The main -changes we did were related with trying to optimize the policy evaluation path by avoiding unnecessary flows and collect decisions -as soon as they happen. We also introduced a policy decision cache on a per-request basis, avoiding redundant decisions from policies -previously evaluated. - -We are also working on other layers of cache which should give a much better experience. See https://issues.redhat.com/browse/KEYCLOAK-7952[KEYCLOAK-7952]. - -= Choosing the response mode when obtaining permissions from the server - -In previous versions, permissions were always returned from the server using standard OAuth2 response, containing the access and refresh tokens. In this release, -clients can use a `response_mode` parameter to specify how the server should respond to an authorization request. This parameter accepts two values: - -* `decision` -+ -Indicating that responses should only contain a flag indicating whether or not permissions were granted by the server. Otherwise a `403` HTTP status code is returned. -+ -* `permissions` -+ -Indicating that a response should contain every single permission granted by the server using a JSON format. - -= NodeJS Policy Enforcer - -The https://github.com/keycloak/keycloak-nodejs-connect[keycloak-nodejs-connect], an adapter for NodeJS, now supports constructs to protect -resources based on decisions taken from the server. The new construct allows users to protect their resources using fine-grained permissions as follows: - -```js -app.get('/protected/resource', keycloak.enforcer('resource:view'), function (req, res) { - res.json({message: 'access granted'}); -}); -``` - -= Support hosted domain for Google logins - -Login with Google now supports the `hd` parameter to restrict Google logins to a specific hosted domain at Google. When -this is specified in the identity provider any login from a different domain is rejected. - -Thanks to https://github.com/brushmate[brushmate] for the contribution. - -= Escape unsafe tags in HTML output - -Most HTML output is already escaped for HTML tags, but there are some places where HTML tags are permitted. -These are only where admin access is needed to update the value. Even though it would require admin access to update such -fields we have added an extra layer of defence and are now escaping unsafe elements like ` - - - - - - ----- - -If the `keycloak.json` file is in a different location you can specify it: - -[source,javascript] ----- -const keycloak = new Keycloak('http://localhost:8080/myapp/keycloak.json'); ----- - -Alternatively, you can pass in a JavaScript object with the required configuration instead: - -[source,javascript,subs="attributes+"] ----- -const keycloak = new Keycloak({ - url: 'http://keycloak-server${kc_base_path}', - realm: 'myrealm', - clientId: 'myapp' -}); ----- - -By default to authenticate you need to call the `login` function. However, there are two options available to make the adapter automatically authenticate. You -can pass `login-required` or `check-sso` to the init function. `login-required` will authenticate the client if the user is logged-in to {project_name} -or display the login page if not. `check-sso` will only authenticate the client if the user is already logged-in, if the user is not logged-in the browser will be -redirected back to the application and remain unauthenticated. - -You can configure a _silent_ `check-sso` option. -With this feature enabled, your browser won't do a full redirect to the {project_name} server and back to your application, but this action will be performed in a hidden iframe, so your application resources only need to be loaded and parsed once by the browser when the app is initialized and not again after the redirect back from {project_name} to your app. -This is particularly useful in case of SPAs (Single Page Applications). - -To enable the _silent_ `check-sso`, you have to provide a `silentCheckSsoRedirectUri` attribute in the init method. -This URI needs to be a valid endpoint in the application (and of course it must be configured as a valid redirect for the client in the {project_name} Admin Console): - -[source,javascript] ----- -keycloak.init({ - onLoad: 'check-sso', - silentCheckSsoRedirectUri: window.location.origin + '/silent-check-sso.html' -}) ----- - -The page at the silent check-sso redirect uri is loaded in the iframe after successfully checking your authentication state and retrieving the tokens from the {project_name} server. -It has no other task than sending the received tokens to the main application and should only look like this: - -[source,html] ----- - - - - - ----- - -Please keep in mind that this page at the specified location must be provided by the application itself and is _not_ part of the JavaScript adapter! - -WARNING: _Silent_ `check-sso` functionality is limited in some modern browsers. Please see the <<_modern_browsers,Modern Browsers with Tracking Protection Section>>. - -To enable `login-required` set `onLoad` to `login-required` and pass to the init method: - -[source,javascript] ----- -keycloak.init({ - onLoad: 'login-required' -}) ----- - -After the user is authenticated the application can make requests to RESTful services secured by {project_name} by including the bearer token in the -`Authorization` header. For example: - -[source,javascript] ----- -const loadData = function () { - document.getElementById('username').innerText = keycloak.subject; - - const url = 'http://localhost:8080/restful-service'; - - const req = new XMLHttpRequest(); - req.open('GET', url, true); - req.setRequestHeader('Accept', 'application/json'); - req.setRequestHeader('Authorization', 'Bearer ' + keycloak.token); - - req.onreadystatechange = function () { - if (req.readyState == 4) { - if (req.status == 200) { - alert('Success'); - } else if (req.status == 403) { - alert('Forbidden'); - } - } - } - - req.send(); -}; ----- - -One thing to keep in mind is that the access token by default has a short life expiration so you may need to refresh the access token prior to sending the -request. You can do this by the `updateToken` method. The `updateToken` method returns a promise which makes it easy to invoke the service only if the -token was successfully refreshed and display an error to the user if it wasn't. For example: - -[source,javascript] ----- -keycloak.updateToken(30).then(function() { - loadData(); -}).catch(function() { - alert('Failed to refresh token'); -}); ----- - -==== Session Status iframe - -By default, the JavaScript adapter creates a hidden iframe that is used to detect if a Single-Sign Out has occurred. -This does not require any network traffic, instead the status is retrieved by looking at a special status cookie. -This feature can be disabled by setting `checkLoginIframe: false` in the options passed to the `init` method. - -You should not rely on looking at this cookie directly. Its format can change and it's also associated with the URL of the {project_name} server, not -your application. - -WARNING: Session Status iframe functionality is limited in some modern browsers. Please see <<_modern_browsers,Modern Browsers with Tracking Protection Section>>. - -[[_javascript_implicit_flow]] -==== Implicit and hybrid flow - -By default, the JavaScript adapter uses the https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth[Authorization Code] flow. - -With this flow the {project_name} server returns an authorization code, not an authentication token, to the application. The JavaScript adapter exchanges -the `code` for an access token and a refresh token after the browser is redirected back to the application. - -{project_name} also supports the https://openid.net/specs/openid-connect-core-1_0.html#ImplicitFlowAuth[Implicit] flow where an access token -is sent immediately after successful authentication with {project_name}. This may have better performance than standard flow, as there is no additional -request to exchange the code for tokens, but it has implications when the access token expires. - -However, sending the access token in the URL fragment can be a security vulnerability. For example the token could be leaked through web server logs and or -browser history. - -To enable implicit flow, you need to enable the `Implicit Flow Enabled` flag for the client in the {project_name} Admin Console. -You also need to pass the parameter `flow` with value `implicit` to `init` method: - -[source,javascript] ----- -keycloak.init({ - flow: 'implicit' -}) ----- - -One thing to note is that only an access token is provided and there is no refresh token. This means that once the access token has expired the application -has to do the redirect to the {project_name} again to obtain a new access token. - -{project_name} also supports the https://openid.net/specs/openid-connect-core-1_0.html#HybridFlowAuth[Hybrid] flow. - -This requires the client to have both the `Standard Flow Enabled` and `Implicit Flow Enabled` flags enabled in the admin console. -The {project_name} server will then send both the code and tokens to your application. -The access token can be used immediately while the code can be exchanged for access and refresh tokens. -Similar to the implicit flow, the hybrid flow is good for performance because the access token is available immediately. -But, the token is still sent in the URL, and the security vulnerability mentioned earlier may still apply. - -One advantage in the Hybrid flow is that the refresh token is made available to the application. - -For the Hybrid flow, you need to pass the parameter `flow` with value `hybrid` to the `init` method: - -[source,javascript] ----- -keycloak.init({ - flow: 'hybrid' -}) ----- - -[#hybrid-apps-with-cordova] -==== Hybrid Apps with Cordova - -Keycloak support hybrid mobile apps developed with https://cordova.apache.org/[Apache Cordova]. The JavaScript adapter has two modes for this: `cordova` and `cordova-native`: - -The default is cordova, which the adapter will automatically select if no adapter type has been configured and window.cordova is present. -When logging in, it will open an https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-inappbrowser/[InApp Browser] that lets the user interact with {project_name} and afterwards returns to the app by redirecting to `http://localhost`. Because of this, you must whitelist this URL as a valid redirect-uri in the client configuration section of the Admin Console. - -While this mode is easy to set up, it also has some disadvantages: - -* The InApp-Browser is a browser embedded in the app and is not the phone's default browser. Therefore it will have different settings and stored credentials will not be available. -* The InApp-Browser might also be slower, especially when rendering more complex themes. -* There are security concerns to consider, before using this mode, such as that it is possible for the app to gain access to the credentials of the user, as it has full control of the browser rendering the login page, so do not allow its use in apps you do not trust. - -Use this example app to help you get started: https://github.com/keycloak/keycloak/tree/master/examples/cordova - -The alternative mode `cordova-native` takes a different approach. -It opens the login page using the system's browser. -After the user has authenticated, the browser redirects back into the app using a special URL. -From there, the {project_name} adapter can finish the login by reading the code or token from the URL. - -You can activate the native mode by passing the adapter type `cordova-native` to the `init` method: - -[source,javascript] ----- -keycloak.init({ - adapter: 'cordova-native' -}) ----- - -This adapter required two additional plugins: - -* https://github.com/google/cordova-plugin-browsertab[cordova-plugin-browsertab]: allows the app to open webpages in the system's browser -* https://github.com/e-imaxina/cordova-plugin-deeplinks[cordova-plugin-deeplinks]: allow the browser to redirect back to your app by special URLs - -The technical details for linking to an app differ on each platform and special setup is needed. -Please refer to the Android and iOS sections of the https://github.com/e-imaxina/cordova-plugin-deeplinks/blob/master/README.md[deeplinks plugin documentation] for further instructions. - -There are different kinds of links for opening apps: custom schemes (i.e. `myapp://login` or `android-app://com.example.myapp/https/example.com/login`) and https://developer.apple.com/ios/universal-links/[Universal Links (iOS)]) / https://developer.android.com/training/app-links/deep-linking[Deep Links (Android)]. -While the former are easier to set up and tend to work more reliably, the later offer extra security as they are unique and only the owner of a domain can register them. -Custom-URLs are deprecated on iOS. -We recommend that you use universal links, combined with a fallback site with a custom-url link on it for best reliability. - -Furthermore, we recommend the following steps to improve compatibility with the Keycloak Adapter: - -* Universal Links on iOS seem to work more reliably with `response-mode` set to `query` -* To prevent Android from opening a new instance of your app on redirect add the following snippet to `config.xml`: - -[source,xml] ----- - ----- - -There is an example app that shows how to use the native-mode: https://github.com/keycloak/keycloak/tree/master/examples/cordova-native - -[#custom-adapters] -==== Custom Adapters - -Sometimes it's necessary to run the JavaScript client in environments that are not supported by default (such as Capacitor). To make it possible to use the JavasScript client in these kind of unknown environments is possible to pass a custom adapter. For example a 3rd party library could provide such an adapter to make it possible to run the JavaScript client without issues: - -[source,javascript] ----- -import Keycloak from 'keycloak-js'; -import KeycloakCapacitorAdapter from 'keycloak-capacitor-adapter'; - -const keycloak = new Keycloak(); - -keycloak.init({ - adapter: KeycloakCapacitorAdapter, -}); ----- - -This specific package does not exist, but it gives a pretty good example of how such an adapter could be passed into the client. - -It's also possible to make your own adapter, to do so you will have to implement the methods described in the `KeycloakAdapter` interface. For example the following TypeScript code ensures that all the methods are properly implemented: - -[source,typescript] ----- -import Keycloak, { KeycloakAdapter } from 'keycloak-js'; - -// Implement the 'KeycloakAdapter' interface so that all required methods are guaranteed to be present. -const MyCustomAdapter: KeycloakAdapter = { - login(options) { - // Write your own implementation here. - } - - // The other methods go here... -}; - -const keycloak = new Keycloak(); - -keycloak.init({ - adapter: MyCustomAdapter, -}); ----- - -Naturally you can also do this without TypeScript by omitting the type information, but ensuring implementing the interface properly will then be left entirely up to you. - -==== Earlier Browsers - -The JavaScript adapter depends on Base64 (window.btoa and window.atob), HTML5 History API and optionally the Promise API. -If you need to support browsers that do not have these available (for example, IE9) you need to add polyfillers. - -Example polyfill libraries: - -* Base64 - https://github.com/davidchambers/Base64.js -* HTML5 History - https://github.com/devote/HTML5-History-API -* Promise - https://github.com/stefanpenner/es6-promise - -[[_modern_browsers]] -==== Modern Browsers with Tracking Protection -In the latest versions of some browsers various cookies policies are applied to prevent tracking of the users by third-parties, -like SameSite in Chrome or completely blocked third-party cookies. It is expected that those policies will become even -more restrictive and adopted by other browsers over time, eventually leading to cookies in third-party contexts to be -completely unsupported and blocked by the browsers. The adapter features affected by this might get deprecated in the -future. - -Javascript adapter relies on third-party cookies for Session Status iframe, _silent_ `check-sso` and partially also for -regular (non-silent) `check-sso`. Those features have limited functionality or are completely disabled based on how -the browser is restrictive regarding cookies. The adapter tries to detect this setting and reacts accordingly. - -===== Browsers with "SameSite=Lax by Default" Policy -All features are supported if SSL / TLS connection is configured on the {project_name} side as well as on the application -side. Affected is for example Chrome starting with -version 84. - -===== Browsers with Blocked Third-Party Cookies -Session Status iframe is not supported and is automatically disabled if such browser behavior is detected by the JS adapter. -This means the adapter cannot use session cookie for Single Sign-Out detection and have to rely purely on tokens. This -implies that when user logs out in another window, the application using JavaScript adapter won't be logged out until it -tries to refresh the Access Token. Therefore, it is recommended to set Access Token Lifespan to relatively short time, so -that the logout is detected rather sooner than later. Please see link:{adminguide_link}#_timeouts[Session and Token Timeouts]. - -_Silent_ `check-sso` is not supported and falls back to regular (non-silent) `check-sso` by default. This behaviour can -be changed by setting `silentCheckSsoFallback: false` in the options passed to the `init` method. In this case, `check-sso` -will be completely disabled if restrictive browser behavior is detected. - -Regular `check-sso` is affected as well. Since Session Status iframe is unsupported, an additional redirect to {project_name} -has to be made when the adapter is initialized to check user's login status. This is different from standard behavior when -the iframe is used to tell whether the user is logged in, and the redirect is performed only when logged out. - -An affected browser is for example Safari starting with version 13.1. - -==== JavaScript Adapter Reference - -===== Constructor - -[source,javascript,subs="attributes+"] ----- -new Keycloak(); -new Keycloak('http://localhost/keycloak.json'); -new Keycloak({ url: 'http://localhost{kc_base_path}', realm: 'myrealm', clientId: 'myApp' }); ----- - -===== Properties - -authenticated:: - Is `true` if the user is authenticated, `false` otherwise. - -token:: - The base64 encoded token that can be sent in the `Authorization` header in requests to services. - -tokenParsed:: - The parsed token as a JavaScript object. - -subject:: - The user id. - -idToken:: - The base64 encoded ID token. - -idTokenParsed:: - The parsed id token as a JavaScript object. - -realmAccess:: - The realm roles associated with the token. - -resourceAccess:: - The resource roles associated with the token. - -refreshToken:: - The base64 encoded refresh token that can be used to retrieve a new token. - -refreshTokenParsed:: - The parsed refresh token as a JavaScript object. - -timeSkew:: - The estimated time difference between the browser time and the {project_name} server in seconds. This value is just an estimation, but is accurate - enough when determining if a token is expired or not. - -responseMode:: - Response mode passed in init (default value is fragment). - -flow:: - Flow passed in init. - -adapter:: - Allows you to override the way that redirects and other browser-related functions will be handled by the library. - Available options: - * "default" - the library uses the browser api for redirects (this is the default) - * "cordova" - the library will try to use the InAppBrowser cordova plugin to load keycloak login/registration pages (this is used automatically when the library is working in a cordova ecosystem) - * "cordova-native" - the library tries to open the login and registration page using the phone's system browser using the BrowserTabs cordova plugin. This requires extra setup for redirecting back to the app (see <>). - * "custom" - allows you to implement a custom adapter (only for advanced use cases) - -responseType:: - Response type sent to {project_name} with login requests. This is determined based on the flow value used during initialization, but can be overridden by setting this value. - -===== Methods - -*init(options)* - -Called to initialize the adapter. - -Options is an Object, where: - -* useNonce - Adds a cryptographic nonce to verify that the authentication response matches the request (default is `true`). -* onLoad - Specifies an action to do on load. Supported values are `login-required` or `check-sso`. -* silentCheckSsoRedirectUri - Set the redirect uri for silent authentication check if onLoad is set to 'check-sso'. -* silentCheckSsoFallback - Enables fall back to regular `check-sso` when _silent_ `check-sso` is not supported by the browser (default is `true`). -* token - Set an initial value for the token. -* refreshToken - Set an initial value for the refresh token. -* idToken - Set an initial value for the id token (only together with token or refreshToken). -* scope - Set the default scope parameter to the {project_name} login endpoint. Use a space-delimited list of scopes. Those typically -reference link:{adminguide_link}#_client_scopes[Client scopes] defined on a particular client. Note that the scope `openid` will -always be added to the list of scopes by the adapter. For example, if you enter the scope options `address phone`, then the request -to {project_name} will contain the scope parameter `scope=openid address phone`. Note that the default scope specified here is overwritten if the `login()` options specify scope explicitly. -* timeSkew - Set an initial value for skew between local time and {project_name} server in seconds (only together with token or refreshToken). -* checkLoginIframe - Set to enable/disable monitoring login state (default is `true`). -* checkLoginIframeInterval - Set the interval to check login state (default is 5 seconds). -* responseMode - Set the OpenID Connect response mode send to {project_name} server at login request. Valid values are `query` or `fragment`. Default value is `fragment`, which means that after successful authentication will {project_name} redirect to JavaScript application with OpenID Connect parameters added in URL fragment. This is generally safer and recommended over `query`. -* flow - Set the OpenID Connect flow. Valid values are `standard`, `implicit` or `hybrid`. -* enableLogging - Enables logging messages from Keycloak to the console (default is `false`). -* pkceMethod - The method for Proof Key Code Exchange (https://datatracker.ietf.org/doc/html/rfc7636[PKCE]) to use. Configuring this value enables the PKCE mechanism. Available options: - - "S256" - The SHA256 based PKCE method -* scope - Used to forward the scope parameter to the {project_name} login endpoint. Use a space-delimited list of scopes. Those typically -reference link:{adminguide_link}#_client_scopes[Client scopes] defined on a particular client. Note that the scope `openid` is -always added to the list of scopes by the adapter. For example, if you enter the scope options `address phone`, then the request -to {project_name} will contain the scope parameter `scope=openid address phone`. -* messageReceiveTimeout - Set a timeout in milliseconds for waiting for message responses from the Keycloak server. This is used, for example, when waiting for a message during 3rd party cookies check. The default value is 10000. - -Returns a promise that resolves when initialization completes. - -*login(options)* - -Redirects to login form. - -Options is an optional Object, where: - -* redirectUri - Specifies the uri to redirect to after login. -* prompt - This parameter allows to slightly customize the login flow on the {project_name} server side. -For example enforce displaying the login screen in case of value `login`. See link:{adapterguide_link}#_params_forwarding[Parameters Forwarding Section] -for the details and all the possible values of the `prompt` parameter. -* maxAge - Used just if user is already authenticated. Specifies maximum time since the authentication of user happened. If user is already authenticated for longer time than `maxAge`, the SSO is ignored and he will need to re-authenticate again. -* loginHint - Used to pre-fill the username/email field on the login form. -* scope - Override the scope configured in `init` with a different value for this specific login. -* idpHint - Used to tell {project_name} to skip showing the login page and automatically redirect to the specified identity -provider instead. More info in the link:{adminguide_link}#_client_suggested_idp[Identity Provider documentation]. -* acr - Contains the information about `acr` claim, which will be sent inside `claims` parameter to the {project_name} server. Typical usage -is for step-up authentication. Example of use `{ values: ["silver", "gold"], essential: true }`. See OpenID Connect specification -and link:{adminguide_link}#_step-up-flow[Step-up authentication documentation] for more details. -* action - If value is `register` then user is redirected to registration page, if the value is `UPDATE_PASSWORD` then the user will be redirected to the reset password page (if not authenticated will send user to login page first and redirect after authenticated), otherwise to login page. -* locale - Sets the 'ui_locales' query param in compliance with https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest[section 3.1.2.1 of the OIDC 1.0 specification]. -* cordovaOptions - Specifies the arguments that are passed to the Cordova in-app-browser (if applicable). Options `hidden` and `location` are not affected by these arguments. All available options are defined at https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-inappbrowser/. Example of use: `{ zoom: "no", hardwareback: "yes" }`; - -*createLoginUrl(options)* - -Returns the URL to login form. - -Options is an optional Object, which supports same options as the function `login` . - -*logout(options)* - -Redirects to logout. - -Options is an Object, where: - -* redirectUri - Specifies the uri to redirect to after logout. - -*createLogoutUrl(options)* - -Returns the URL to log out the user. - -Options is an Object, where: - -* redirectUri - Specifies the uri to redirect to after logout. - -*register(options)* - -Redirects to registration form. Shortcut for login with option action = 'register' - -Options are same as for the login method but 'action' is set to 'register' - -*createRegisterUrl(options)* - -Returns the url to registration page. Shortcut for createLoginUrl with option action = 'register' - -Options are same as for the createLoginUrl method but 'action' is set to 'register' - -*accountManagement()* - -Redirects to the Account Management Console. - -*createAccountUrl(options)* - -Returns the URL to the Account Management Console. - -Options is an Object, where: - -* redirectUri - Specifies the uri to redirect to when redirecting back to the application. - -*hasRealmRole(role)* - -Returns true if the token has the given realm role. - -*hasResourceRole(role, resource)* - -Returns true if the token has the given role for the resource (resource is optional, if not specified clientId is used). - -*loadUserProfile()* - -Loads the users profile. - -Returns a promise that resolves with the profile. - -For example: - -[source,javascript] ----- -keycloak.loadUserProfile() - .then(function(profile) { - alert(JSON.stringify(profile, null, " ")) - }).catch(function() { - alert('Failed to load user profile'); - }); ----- - -*isTokenExpired(minValidity)* - -Returns true if the token has less than minValidity seconds left before it expires (minValidity is optional, if not specified 0 is used). - -*updateToken(minValidity)* - -If the token expires within minValidity seconds (minValidity is optional, if not specified 5 is used) the token is refreshed. -If -1 is passed as the minValidity, the token will be forcibly refreshed. -If the session status iframe is enabled, the session status is also checked. - -Returns a promise that resolves with a boolean indicating whether or not the token has been refreshed. - -For example: - -[source,javascript] ----- -keycloak.updateToken(5) - .then(function(refreshed) { - if (refreshed) { - alert('Token was successfully refreshed'); - } else { - alert('Token is still valid'); - } - }).catch(function() { - alert('Failed to refresh the token, or the session has expired'); - }); ----- - -*clearToken()* - -Clear authentication state, including tokens. -This can be useful if application has detected the session was expired, for example if updating token fails. - -Invoking this results in onAuthLogout callback listener being invoked. - -===== Callback Events - -The adapter supports setting callback listeners for certain events. Keep in mind that these have to be set before the call to the `init` function. - -For example: -[source,javascript] ----- -keycloak.onAuthSuccess = function() { alert('authenticated'); } ----- - -The available events are: - -* *onReady(authenticated)* - Called when the adapter is initialized. -* *onAuthSuccess* - Called when a user is successfully authenticated. -* *onAuthError* - Called if there was an error during authentication. -* *onAuthRefreshSuccess* - Called when the token is refreshed. -* *onAuthRefreshError* - Called if there was an error while trying to refresh the token. -* *onAuthLogout* - Called if the user is logged out (will only be called if the session status iframe is enabled, or in Cordova mode). -* *onTokenExpired* - Called when the access token is expired. If a refresh token is available the token can be refreshed with updateToken, or in cases where it is not (that is, with implicit flow) you can redirect to the login screen to obtain a new access token. diff --git a/securing_apps/topics/oidc/mod-auth-openidc.adoc b/securing_apps/topics/oidc/mod-auth-openidc.adoc deleted file mode 100644 index be964f144..000000000 --- a/securing_apps/topics/oidc/mod-auth-openidc.adoc +++ /dev/null @@ -1,49 +0,0 @@ -[[_mod_auth_openidc]] -=== mod_auth_openidc Apache HTTPD Module - -The https://github.com/OpenIDC/mod_auth_openidc[mod_auth_openidc] is an Apache HTTP plugin for OpenID Connect. If your language/environment supports using Apache HTTPD -as a proxy, then you can use _mod_auth_openidc_ to secure your web application with OpenID Connect. Configuration of this module -is beyond the scope of this document. Please see the _mod_auth_openidc_ GitHub repo for more details on configuration. - -To configure _mod_auth_openidc_ you'll need - -* The client_id. -* The client_secret. -* The redirect_uri to your application. -* The Keycloak openid-configuration url -* _mod_auth_openidc_ specific Apache HTTPD module config. - -An example configuration would look like the following. - -[source,subs="attributes+"] ----- -LoadModule auth_openidc_module modules/mod_auth_openidc.so - -ServerName ${HOSTIP} - - - - ServerAdmin webmaster@localhost - DocumentRoot /var/www/html - - #this is required by mod_auth_openidc - OIDCCryptoPassphrase a-random-secret-used-by-apache-oidc-and-balancer - - OIDCProviderMetadataURL ${KC_ADDR}{kc_realms_path}/${KC_REALM}/.well-known/openid-configuration - - OIDCClientID ${CLIENT_ID} - OIDCClientSecret ${CLIENT_SECRET} - OIDCRedirectURI http://${HOSTIP}/${CLIENT_APP_NAME}/redirect_uri - - # maps the preferred_username claim to the REMOTE_USER environment variable - OIDCRemoteUserClaim preferred_username - - - AuthType openid-connect - Require valid-user - - ----- - -Further information on how to configure mod_auth_openidc can be found on the https://github.com/OpenIDC/mod_auth_openidc[mod_auth_openidc] -project page. diff --git a/securing_apps/topics/oidc/nodejs-adapter.adoc b/securing_apps/topics/oidc/nodejs-adapter.adoc deleted file mode 100644 index a77f03e85..000000000 --- a/securing_apps/topics/oidc/nodejs-adapter.adoc +++ /dev/null @@ -1,373 +0,0 @@ -[[_nodejs_adapter]] -=== Node.js adapter - -{project_name} provides a Node.js adapter built on top of https://github.com/senchalabs/connect[Connect] to protect server-side JavaScript apps - the goal was to be flexible enough to integrate with frameworks like https://expressjs.com/[Express.js]. - -ifeval::[{project_community}==true] -The library can be downloaded directly from https://www.npmjs.com/package/keycloak-connect[ {project_name} organization] and the source is available at -https://github.com/keycloak/keycloak-nodejs-connect[GitHub]. -endif::[] - -To use the Node.js adapter, first you must create a client for your application in the {project_name} Admin Console. The adapter supports public, confidential, and bearer-only access type. Which one to choose depends on the use-case scenario. - -Once the client is created click the `Installation` tab, select `{project_name} OIDC JSON` for `Format Option`, and then click `Download`. The downloaded `keycloak.json` file should be at the root folder of your project. - -==== Installation - -Assuming you've already installed https://nodejs.org[Node.js], create a folder for your application: - - mkdir myapp && cd myapp - -Use `npm init` command to create a `package.json` for your application. Now add the {project_name} connect adapter in the dependencies list: - -ifeval::[{project_community}==true] - -[source,json,subs="attributes"] ----- - "dependencies": { - "keycloak-connect": "{project_versionNpm}" - } ----- - -endif::[] - -ifeval::[{project_product}==true] - -[source,json,subs="attributes"] ----- - "dependencies": { - "keycloak-connect": "file:keycloak-connect-{project_versionNpm}.tgz" - } ----- - -endif::[] - -==== Usage -Instantiate a Keycloak class:: - -The `Keycloak` class provides a central point for configuration -and integration with your application. The simplest creation -involves no arguments. - -In the root directory of your project create a file called `server.js` and add the following code: - -[source,javascript] ----- - const session = require('express-session'); - const Keycloak = require('keycloak-connect'); - - const memoryStore = new session.MemoryStore(); - const keycloak = new Keycloak({ store: memoryStore }); ----- - -Install the `express-session` dependency: - ----- - npm install express-session ----- - -To start the `server.js` script, add the following command in the 'scripts' section of the `package.json`: - ----- - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", - "start": "node server.js" - }, ----- - -Now we have the ability to run our server with following command: - ----- - npm run start ----- - -By default, this will locate a file named `keycloak.json` alongside -the main executable of your application, in our case on the root folder, to initialize keycloak-specific -settings such as public key, realm name, various URLs. - -In that case a Keycloak deployment is necessary to access Keycloak admin console. - -Please visit links on how to deploy a Keycloak admin console with -https://www.keycloak.org/getting-started/getting-started-podman[Podman] or https://www.keycloak.org/getting-started/getting-started-docker[Docker] - -Now we are ready to obtain the `keycloak.json` file by visiting the {project_name} Admin Console -> clients (left sidebar) -> choose your client -> Installation -> Format Option -> Keycloak OIDC JSON -> Download - -Paste the downloaded file on the root folder of our project. - -Instantiation with this method results in all the reasonable defaults -being used. As alternative, it's also possible to provide a configuration -object, rather than the `keycloak.json` file: - -[source,javascript,subs="attributes+"] ----- - const kcConfig = { - clientId: 'myclient', - bearerOnly: true, - serverUrl: 'http://localhost:8080{kc_base_path}', - realm: 'myrealm', - realmPublicKey: 'MIIBIjANB...' - }; - - const keycloak = new Keycloak({ store: memoryStore }, kcConfig); ----- - -Applications can also redirect users to their preferred identity provider by using: -[source,javascript] ----- - const keycloak = new Keycloak({ store: memoryStore, idpHint: myIdP }, kcConfig); ----- - -Configuring a web session store:: - -If you want to use web sessions to manage -server-side state for authentication, you need to initialize the -`Keycloak(...)` with at least a `store` parameter, passing in the actual -session store that `express-session` is using. -[source,javascript] ----- - const session = require('express-session'); - const memoryStore = new session.MemoryStore(); - - // Configure session - app.use( - session({ - secret: 'mySecret', - resave: false, - saveUninitialized: true, - store: memoryStore, - }) - ); - - const keycloak = new Keycloak({ store: memoryStore }); ----- -Passing a custom scope value:: - -By default, the scope value `openid` is passed as a query parameter to {project_name}'s login URL, but you can add an additional custom value: -[source,javascript] - const keycloak = new Keycloak({ scope: 'offline_access' }); - -==== Installing middleware - -Once instantiated, install the middleware into your connect-capable app: - -In order to do so, first we have to install Express: ----- - npm install express ----- - -then require Express in our project as outlined below: - -[source,javascript] ----- - const express = require('express'); - const app = express(); ----- - - -and configure Keycloak middleware in Express, by adding at the code below: - -[source,javascript] ----- - app.use( keycloak.middleware() ); ----- - -Last but not least, let's set up our server to listen for HTTP requests on port 3000 by adding the following code to `main.js`: - -[source,javascript] ----- - app.listen(3000, function () { - console.log('App listening on port 3000'); - }); ----- - -==== Configuration for proxies - -If the application is running behind a proxy that terminates an SSL connection -Express must be configured per the link:https://expressjs.com/en/guide/behind-proxies.html[express behind proxies] guide. -Using an incorrect proxy configuration can result in invalid redirect URIs -being generated. - -Example configuration: - -[source,javascript] ----- - const app = express(); - - app.set( 'trust proxy', true ); - - app.use( keycloak.middleware() ); ----- - -==== Protecting resources - -Simple authentication:: - -To enforce that a user must be authenticated before accessing a resource, -simply use a no-argument version of `keycloak.protect()`: - -[source,javascript] ----- - app.get( '/complain', keycloak.protect(), complaintHandler ); ----- - -Role-based authorization:: - -To secure a resource with an application role for the current app: - -[source,javascript] ----- - app.get( '/special', keycloak.protect('special'), specialHandler ); ----- - -To secure a resource with an application role for a *different* app: - -[source,javascript] - app.get( '/extra-special', keycloak.protect('other-app:special'), extraSpecialHandler ); - -To secure a resource with a realm role: - -[source,javascript] - app.get( '/admin', keycloak.protect( 'realm:admin' ), adminHandler ); - -Resource-Based Authorization:: - -Resource-Based Authorization allows you to protect resources, and their specific methods/actions,**** based on a set of policies defined in Keycloak, thus externalizing authorization from your application. This is achieved by exposing a `keycloak.enforcer` method which you can use to protect resources.* - -[source,javascript] ----- - app.get('/apis/me', keycloak.enforcer('user:profile'), userProfileHandler); ----- - -The `keycloak-enforcer` method operates in two modes, depending on the value of the `response_mode` configuration option. - -[source,javascript] ----- - app.get('/apis/me', keycloak.enforcer('user:profile', {response_mode: 'token'}), userProfileHandler); ----- - -If `response_mode` is set to `token`, permissions are obtained from the server on behalf of the subject represented by the bearer token that was sent to your application. In this case, a new access token is issued by Keycloak with the permissions granted by the server. If the server did not respond with a token with the expected permissions, the request is denied. When using this mode, you should be able to obtain the token from the request as follows: - -[source,javascript] ----- - app.get('/apis/me', keycloak.enforcer('user:profile', {response_mode: 'token'}), function (req, res) { - const token = req.kauth.grant.access_token.content; - const permissions = token.authorization ? token.authorization.permissions : undefined; - - // show user profile - }); ----- - -Prefer this mode when your application is using sessions and you want to cache previous decisions from the server, as well automatically handle refresh tokens. This mode is especially useful for applications acting as a client and resource server. - -If `response_mode` is set to `permissions` (default mode), the server only returns the list of granted permissions, without issuing a new access token. In addition to not issuing a new token, this method exposes the permissions granted by the server through the `request` as follows: - -[source,javascript] ----- - app.get('/apis/me', keycloak.enforcer('user:profile', {response_mode: 'permissions'}), function (req, res) { - const permissions = req.permissions; - - // show user profile - }); ----- - -Regardless of the `response_mode` in use, the `keycloak.enforcer` method will first try to check the permissions within the bearer token that was sent to your application. If the bearer token already carries the expected permissions, there is no need -to interact with the server to obtain a decision. This is specially useful when your clients are capable of obtaining access tokens from the server with the expected permissions before accessing a protected resource, so they can use some capabilities provided by Keycloak Authorization Services such as incremental authorization and avoid additional requests to the server when `keycloak.enforcer` is enforcing access to the resource. - -By default, the policy enforcer will use the `client_id` defined to the application (for instance, via `keycloak.json`) to - reference a client in Keycloak that supports Keycloak Authorization Services. In this case, the client can not be public given - that it is actually a resource server. - -If your application is acting as both a public client(frontend) and resource server(backend), you can use the following configuration to reference a different -client in Keycloak with the policies that you want to enforce: - -[source,javascript] ----- - keycloak.enforcer('user:profile', {resource_server_id: 'my-apiserver'}) ----- - -It is recommended to use distinct clients in Keycloak to represent your frontend and backend. - -If the application you are protecting is enabled with Keycloak authorization services and you have defined client credentials - in `keycloak.json`, you can push additional claims to the server and make them available to your policies in order to make decisions. -For that, you can define a `claims` configuration option which expects a `function` that returns a JSON with the claims you want to push: - -[source,javascript] ----- - app.get('/protected/resource', keycloak.enforcer(['resource:view', 'resource:write'], { - claims: function(request) { - return { - "http.uri": ["/protected/resource"], - "user.agent": // get user agent from request - } - } - }), function (req, res) { - // access granted ----- - -For more details about how to configure Keycloak to protected your application resources, please take a look at the link:{authorizationguide_link}[{authorizationguide_name}]. - -Advanced authorization:: - -To secure resources based on parts of the URL itself, assuming a role exists -for each section: - -[source,javascript] ----- - function protectBySection(token, request) { - return token.hasRole( request.params.section ); - } - - app.get( '/:section/:page', keycloak.protect( protectBySection ), sectionHandler ); ----- - -Advanced Login Configuration: - -By default, all unauthorized requests will be redirected to the {project_name} login page unless your client is bearer-only. -However, a confidential or public client may host both browsable and API endpoints. To prevent redirects on unauthenticated -API requests and instead return an HTTP 401, you can override the redirectToLogin function. - -For example, this override checks if the URL contains /api/ and disables login redirects: - -[source,javascript] ----- - Keycloak.prototype.redirectToLogin = function(req) { - const apiReqMatcher = /\/api\//i; - return !apiReqMatcher.test(req.originalUrl || req.url); - }; ----- - -==== Additional URLs - -Explicit user-triggered logout:: - -By default, the middleware catches calls to `/logout` to send the user through a -{project_name}-centric logout workflow. This can be changed by specifying a `logout` -configuration parameter to the `middleware()` call: - -[source,javascript] ----- - app.use( keycloak.middleware( { logout: '/logoff' } )); ----- - -When the user-triggered logout is invoked a query parameter `redirect_url` can be passed: - -[source] ----- -https://example.com/logoff?redirect_url=https%3A%2F%2Fexample.com%3A3000%2Flogged%2Fout ----- - -This parameter is then used as the redirect url of the OIDC logout endpoint and the user will be redirected to -`\https://example.com/logged/out`. - -{project_name} Admin Callbacks:: - -Also, the middleware supports callbacks from the {project_name} console to log out a single -session or all sessions. By default, these type of admin callbacks occur relative -to the root URL of `/` but can be changed by providing an `admin` parameter -to the `middleware()` call: -[source,javascript] - app.use( keycloak.middleware( { admin: '/callbacks' } ); - -==== Complete example - -A complete example using the Node.js adapter usage can be found in {quickstartRepo_link}/tree/latest/service-nodejs/[Keycloak quickstarts for Node.js] diff --git a/securing_apps/topics/oidc/oidc-generic.adoc b/securing_apps/topics/oidc/oidc-generic.adoc deleted file mode 100644 index 2bcff688a..000000000 --- a/securing_apps/topics/oidc/oidc-generic.adoc +++ /dev/null @@ -1,256 +0,0 @@ -=== Other OpenID Connect libraries - -{project_name} can be secured by supplied adapters that are usually easier to use and provide better integration with {project_name}. However, if an adapter is not available for your programming language, framework, or platform you might opt to use a generic OpenID Connect Relying Party (RP) library instead. This chapter describes details specific to {project_name} and does not contain specific protocol details. For more information see the https://openid.net/connect/[OpenID Connect specifications] and https://datatracker.ietf.org/doc/html/rfc6749[OAuth2 specification]. - -==== Endpoints - -The most important endpoint to understand is the `well-known` configuration endpoint. It lists endpoints and other configuration options relevant to the OpenID Connect implementation in {project_name}. The endpoint is: - -.... -/realms/{realm-name}/.well-known/openid-configuration -.... - -To obtain the full URL, add the base URL for {project_name} and replace `{realm-name}` with the name of your realm. For example: - -\http://localhost:8080{kc_realms_path}/master/.well-known/openid-configuration - -Some RP libraries retrieve all required endpoints from this endpoint, but for others you might need to list the endpoints individually. - -===== Authorization endpoint -.... -/realms/{realm-name}/protocol/openid-connect/auth -.... - -The authorization endpoint performs authentication of the end-user. This is done by redirecting the user agent to this endpoint. - -For more details see the https://openid.net/specs/openid-connect-core-1_0.html#AuthorizationEndpoint[Authorization Endpoint] section in the OpenID Connect specification. - -===== Token endpoint -.... -/realms/{realm-name}/protocol/openid-connect/token -.... - -The token endpoint is used to obtain tokens. Tokens can either be obtained by exchanging an authorization code or by supplying credentials directly depending on what flow is used. -The token endpoint is also used to obtain new access tokens when they expire. - -For more details see the https://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint[Token Endpoint] section in the OpenID Connect specification. - -===== Userinfo endpoint -.... -/realms/{realm-name}/protocol/openid-connect/userinfo -.... - -The userinfo endpoint returns standard claims about the authenticated user, and is protected by a bearer token. - -For more details see the https://openid.net/specs/openid-connect-core-1_0.html#UserInfo[Userinfo Endpoint] section in the OpenID Connect specification. - -===== Logout endpoint -.... -/realms/{realm-name}/protocol/openid-connect/logout -.... - -The logout endpoint logs out the authenticated user. - -The user agent can be redirected to the endpoint, in which case the active user session is logged out. Afterward the user agent is redirected back to the application. - -The endpoint can also be invoked directly by the application. To invoke this endpoint directly the refresh token needs to be included as well as the credentials required to authenticate the client. - -[[_certificate_endpoint]] -===== Certificate endpoint -.... -/realms/{realm-name}/protocol/openid-connect/certs -.... - -The certificate endpoint returns the public keys enabled by the realm, encoded as a JSON Web Key (JWK). Depending on the realm settings there can be one or more keys enabled for verifying tokens. For more information see the link:{adminguide_link}[{adminguide_name}] and the https://datatracker.ietf.org/doc/html/rfc7517[JSON Web Key specification]. - -[[_token_introspection_endpoint]] -===== Introspection endpoint -.... -/realms/{realm-name}/protocol/openid-connect/token/introspect -.... - -The introspection endpoint is used to retrieve the active state of a token. In other words, you can use it to validate an access or refresh token. -It can only be invoked by confidential clients. - -For more details on how to invoke on this endpoint, see https://datatracker.ietf.org/doc/html/rfc7662[OAuth 2.0 Token Introspection specification]. - -===== Dynamic Client Registration endpoint -.... -/realms/{realm-name}/clients-registrations/openid-connect -.... - -The dynamic client registration endpoint is used to dynamically register clients. - -For more details see the <<_client_registration,Client Registration chapter>> and the -https://openid.net/specs/openid-connect-registration-1_0.html[OpenID Connect Dynamic Client Registration specification]. - -[[_token_revocation_endpoint]] -===== Token Revocation endpoint -.... -/realms/{realm-name}/protocol/openid-connect/revoke -.... - -The token revocation endpoint is used to revoke tokens. Both refresh tokens and access tokens are supported by this endpoint. When revoking a refresh token the user consent for the corresponding client is also revoked. - -For more details on how to invoke on this endpoint, see https://datatracker.ietf.org/doc/html/rfc7009[OAuth 2.0 Token Revocation specification]. - -===== Device Authorization endpoint -.... -/realms/{realm-name}/protocol/openid-connect/auth/device -.... - -The device authorization endpoint is used to obtain a device code and a user code. It can be invoked by confidential or public clients. - -For more details on how to invoke on this endpoint, see https://datatracker.ietf.org/doc/html/rfc8628[OAuth 2.0 Device Authorization Grant specification]. - -[[_backchannel_authentication_endpoint]] -===== Backchannel Authentication endpoint -.... -/realms/{realm-name}/protocol/openid-connect/ext/ciba/auth -.... - -The backchannel authentication endpoint is used to obtain an auth_req_id that identifies the authentication request made by the client. It can only be invoked by confidential clients. - -For more details on how to invoke on this endpoint, see https://openid.net/specs/openid-client-initiated-backchannel-authentication-core-1_0.html[OpenID Connect Client Initiated Backchannel Authentication Flow specification]. - -Also please refer to other places of {project_name} documentation like <<_client_initiated_backchannel_authentication_grant,Client Initiated Backchannel Authentication Grant section of this guide>> and link:{adminguide_link}#_client_initiated_backchannel_authentication_grant[Client Initiated Backchannel Authentication Grant section] of {adminguide_name}. - -==== Validating access tokens - -If you need to manually validate access tokens issued by {project_name} you can invoke the <<_token_introspection_endpoint,Introspection Endpoint>>. -The downside to this approach is that you have to make a network invocation to the {project_name} server. This can be slow and possibly overload the -server if you have too many validation requests going on at the same time. {project_name} issued access tokens are https://datatracker.ietf.org/doc/html/rfc7519[JSON Web Tokens (JWT)] digitally signed and encoded using https://datatracker.ietf.org/doc/html/rfc7515[JSON Web Signature (JWS)]. -Because they are encoded in this way, this allows you to locally validate access tokens using the public key of the issuing realm. You can either hard code the -realm's public key in your validation code, or lookup and cache the public key using the <<_certificate_endpoint, certificate endpoint>> with the Key ID (KID) embedded within the -JWS. Depending on what language you code in, there are a multitude of third party libraries out there that can help you with JWS validation. - - -==== Flows - -===== Authorization code - -The Authorization Code flow redirects the user agent to {project_name}. Once the user has successfully authenticated with {project_name} an -Authorization Code is created and the user agent is redirected back to the application. The application then uses the authorization code along with its -credentials to obtain an Access Token, Refresh Token and ID Token from {project_name}. - -The flow is targeted towards web applications, but is also recommended for native applications, including mobile applications, where it is possible to embed -a user agent. - -For more details refer to the https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth[Authorization Code Flow] in the OpenID Connect specification. - -===== Implicit - -The Implicit flow redirects works similarly to the Authorization Code flow, but instead of returning an Authorization Code the Access Token and ID Token is -returned. This reduces the need for the extra invocation to exchange the Authorization Code for an Access Token. However, it does not include a Refresh -Token. This results in the need to either permit Access Tokens with a long expiration, which is problematic as it's very hard to invalidate these. Or -requires a new redirect to obtain new Access Token once the initial Access Token has expired. The Implicit flow is useful if the application only wants to -authenticate the user and deals with logout itself. - -There's also a Hybrid flow where both the Access Token and an Authorization Code is returned. - -One thing to note is that both the Implicit flow and Hybrid flow has potential security risks as the Access Token may be leaked through web server logs and -browser history. This is somewhat mitigated by using short expiration for Access Tokens. - -For more details refer to the https://openid.net/specs/openid-connect-core-1_0.html#ImplicitFlowAuth[Implicit Flow] in the OpenID Connect specification. - -[[_resource_owner_password_credentials_flow]] -===== Resource Owner Password Credentials - -Resource Owner Password Credentials, referred to as Direct Grant in {project_name}, allows exchanging user credentials for tokens. It's not recommended -to use this flow unless you absolutely need to. Examples where this could be useful are legacy applications and command-line interfaces. - -There are a number of limitations of using this flow, including: - -* User credentials are exposed to the application -* Applications need login pages -* Application needs to be aware of the authentication scheme -* Changes to authentication flow requires changes to application -* No support for identity brokering or social login -* Flows are not supported (user self-registration, required actions, etc.) - -For a client to be permitted to use the Resource Owner Password Credentials grant the client has to have the `Direct Access Grants Enabled` option enabled. - -This flow is not included in OpenID Connect, but is a part of the OAuth 2.0 specification. - -For more details refer to the https://datatracker.ietf.org/doc/html/rfc6749#section-4.3[Resource Owner Password Credentials Grant] chapter in the OAuth 2.0 specification. - -====== Example using CURL - -The following example shows how to obtain an access token for a user in the realm `master` with username `user` and password `password`. The example is using -the confidential client `myclient`: - -[source,bash,subs="attributes+"] ----- -curl \ - -d "client_id=myclient" \ - -d "client_secret=40cc097b-2a57-4c17-b36a-8fdf3fc2d578" \ - -d "username=user" \ - -d "password=password" \ - -d "grant_type=password" \ - "http://localhost:8080{kc_realms_path}/master/protocol/openid-connect/token" ----- - -===== Client credentials - -Client Credentials is used when clients (applications and services) wants to obtain access on behalf of themselves rather than on behalf of a user. This can -for example be useful for background services that applies changes to the system in general rather than for a specific user. - -{project_name} provides support for clients to authenticate either with a secret or with public/private keys. - -This flow is not included in OpenID Connect, but is a part of the OAuth 2.0 specification. - -For more details refer to the https://datatracker.ietf.org/doc/html/rfc6749#section-4.4[Client Credentials Grant] chapter in the OAuth 2.0 specification. - -===== Device Authorization Grant - -Device Authorization Grant is used by clients running on internet-connected devices that have limited input capabilities or lack a suitable browser. -The application requests {project_name} a device code and a user code. {project_name} creates a device code and a user code. -{project_name} returns a response including the device code and the user code to the application. -Then the application provides the user with the user code and the verification URI. The user accesses a verification URI to be authenticated by using another browser. -The application repeatedly polls {project_name} until {project_name} completes the user authorization. -If user authentication is complete, the application obtains the device code. Then the application uses the device code along with its credentials to obtain an Access Token, Refresh Token and ID Token from {project_name}. - -For more details refer to the https://datatracker.ietf.org/doc/html/rfc8628[OAuth 2.0 Device Authorization Grant specification]. - -[[_client_initiated_backchannel_authentication_grant]] -===== Client Initiated Backchannel Authentication Grant - -Client Initiated Backchannel Authentication Grant is used by clients who want to initiate the authentication flow by communicating with the OpenID Provider directly without redirect through the user's browser like OAuth 2.0's authorization code grant. - -The client requests {project_name} an auth_req_id that identifies the authentication request made by the client. {project_name} creates the auth_req_id. - -After receiving this auth_req_id, this client repeatedly needs to poll {project_name} to obtain an Access Token, Refresh Token and ID Token from {project_name} in return for the auth_req_id until the user is authenticated. - -In case that client uses `ping` mode, it does not need to repeatedly poll the token endpoint, but it can wait for the notification sent by {project_name} to the specified Client Notification Endpoint. -The Client Notification Endpoint can be configured in the {project_name} Admin Console. The details of the contract for Client Notification Endpoint are described in the CIBA specification. - -For more details refer to https://openid.net/specs/openid-client-initiated-backchannel-authentication-core-1_0.html[OpenID Connect Client Initiated Backchannel Authentication Flow specification]. - -Also please refer to other places of {project_name} documentation like <<_backchannel_authentication_endpoint,Backchannel Authentication Endpoint of this guide>> and link:{adminguide_link}#_client_initiated_backchannel_authentication_grant[Client Initiated Backchannel Authentication Grant section] of {adminguide_name}. -For the details about FAPI CIBA compliance, please refer to the <<_fapi-support,FAPI section of this guide>>. - -==== Redirect URIs - -When using the redirect based flows it's important to use valid redirect uris for your clients. The redirect uris should be as specific as possible. This -especially applies to client-side (public clients) applications. Failing to do so could result in: - -* Open redirects - this can allow attackers to create spoof links that looks like they are coming from your domain -* Unauthorized entry - when users are already authenticated with {project_name} an attacker can use a public client where redirect uris have not be configured correctly to gain access by redirecting the user without the users knowledge - -In production for web applications always use `https` for all redirect URIs. Do not allow redirects to http. - -There's also a few special redirect URIs: - -[[_installed_applications_url]] -`$$http://localhost$$`:: - - This redirect URI is useful for native applications and allows the native application to create a web server on a random port that can be used to obtain the - authorization code. This redirect uri allows any port. - -[[_installed_applications_urn]] -`urn:ietf:wg:oauth:2.0:oob`:: - - If its not possible to start a web server in the client (or a browser is not available) it is possible to use the special `urn:ietf:wg:oauth:2.0:oob` redirect uri. - When this redirect uri is used {project_name} displays a page with the code in the title and in a box on the page. - The application can either detect that the browser title has changed, or the user can copy/paste the code manually to the application. - With this redirect uri it is also possible for a user to use a different device to obtain a code to paste back to the application. diff --git a/securing_apps/topics/oidc/oidc-overview.adoc b/securing_apps/topics/oidc/oidc-overview.adoc deleted file mode 100644 index 7ba875d0b..000000000 --- a/securing_apps/topics/oidc/oidc-overview.adoc +++ /dev/null @@ -1,5 +0,0 @@ -[[_oidc]] -== Using OpenID Connect to secure applications and services - -This section describes how you can secure applications and services with OpenID Connect using either {project_name} adapters or generic OpenID Connect -Relying Party libraries. \ No newline at end of file diff --git a/securing_apps/topics/overview/basic-steps.adoc b/securing_apps/topics/overview/basic-steps.adoc deleted file mode 100644 index 9582430d8..000000000 --- a/securing_apps/topics/overview/basic-steps.adoc +++ /dev/null @@ -1,24 +0,0 @@ -=== Basic steps to secure applications and services - -These are the basic steps for securing an application or a service in {project_name}. - -. Configure a client using one of these options: - -* A {project_name} adapter - -* A generic OpenID connect or SAML library - -. Register a client using one of these options: - -* The {project_name} Admin Console - -* The client registration service - -* The CLI - -[role="_additional-resources"] - -.Additional resources - -* This guide provides the detailed instructions for these steps. Related information exists in the link:{adminguide_link}[Server Administration Guide]. That guide provides instructions for using Admin Console to create a client. Creating a client is the same task as registering a client using the {project_name} Client Registration Service. - diff --git a/securing_apps/topics/overview/overview.adoc b/securing_apps/topics/overview/overview.adoc deleted file mode 100644 index 6796e0059..000000000 --- a/securing_apps/topics/overview/overview.adoc +++ /dev/null @@ -1,9 +0,0 @@ -== Planning for securing applications and services - -{project_name} supports both OpenID Connect (an extension to OAuth 2.0) and SAML 2.0. When securing clients and services the first thing you need to -decide is which of the two you are going to use. If you want you can also choose to secure some with OpenID Connect and others with SAML. - -To secure clients and services you are also going to need an adapter or library for the protocol you've selected. {project_name} comes with its own -adapters for selected platforms, but it is also possible to use generic OpenID Connect Relying Party and SAML Service Provider libraries. - - diff --git a/securing_apps/topics/overview/supported-platforms.adoc b/securing_apps/topics/overview/supported-platforms.adoc deleted file mode 100644 index 96819307d..000000000 --- a/securing_apps/topics/overview/supported-platforms.adoc +++ /dev/null @@ -1,64 +0,0 @@ -=== Supported Platforms - -{project_name} enables you to protect applications running on different platforms and using different technology stacks using OpenID Connect and SAML protocols. - -==== OpenID Connect - -===== Java -* <<_jboss_adapter,JBoss EAP>> -ifeval::[{project_community}==true] - * <<_jboss_adapter,WildFly>> -endif::[] -ifeval::[{project_community}==true] - * <<_tomcat_adapter,Tomcat>> - * <<_jetty9_adapter,Jetty 9>> -endif::[] - -* <<_servlet_filter_adapter,Servlet Filter>> -* <<_spring_boot_adapter,Spring Boot>> - -ifeval::[{project_community}==true] - * <<_spring_security_adapter,Spring Security>> -endif::[] - -===== JavaScript (client-side) -* <<_javascript_adapter,JavaScript>> - -===== Node.js (server-side) -* <<_nodejs_adapter,Node.js>> - - -ifeval::[{project_community}==true] -===== C# -* https://github.com/dylanplecki/KeycloakOwinAuthentication[OWIN] (community) - -===== Python -* https://pypi.org/project/oic/[oidc] (generic) - -===== Android -* https://github.com/openid/AppAuth-Android[AppAuth] (generic) - -===== iOS -* https://github.com/openid/AppAuth-iOS[AppAuth] (generic) - -===== Apache HTTP Server -* https://github.com/OpenIDC/mod_auth_openidc[mod_auth_openidc] -endif::[] - -==== SAML - -===== Java - -* <<_saml_jboss_adapter,JBoss EAP>> -ifeval::[{project_community}==true] -* <<_saml_jboss_adapter,WildFly>> -* <<_saml-tomcat-adapter,Tomcat>> -endif::[] -* <<_java-servlet-filter-adapter,Servlet filter>> -ifeval::[{project_community}==true] -* <<_jetty_saml_adapter,Jetty>> -endif::[] - -===== Apache HTTP Server - -* <<_mod_auth_mellon,mod_auth_mellon>> diff --git a/securing_apps/topics/overview/supported-protocols.adoc b/securing_apps/topics/overview/supported-protocols.adoc deleted file mode 100644 index 52a363e41..000000000 --- a/securing_apps/topics/overview/supported-protocols.adoc +++ /dev/null @@ -1,59 +0,0 @@ -[[_supported_protocols]] - -=== Supported Protocols - -{project_name} supports both OpenID Connect and SAML protocols. - -==== OpenID Connect - -link:https://openid.net/connect/[OpenID Connect] (OIDC) is an authentication protocol that is an extension of link:https://datatracker.ietf.org/doc/html/rfc6749[OAuth 2.0]. -While OAuth 2.0 is only a framework for building authorization protocols and is mainly incomplete, OIDC is a full-fledged authentication and authorization -protocol. OIDC also makes heavy use of the link:https://jwt.io[Json Web Token] (JWT) set of standards. These standards define an -identity token JSON format and ways to digitally sign and encrypt that data in a compact and web-friendly way. - -There are really two types of use cases when using OIDC. The first is an application that asks the {project_name} server to authenticate -a user for them. After a successful login, the application will receive an _identity token_ and an _access token_. The _identity token_ -contains information about the user such as username, email, and other profile information. The _access token_ is digitally signed by -the realm and contains access information (like user role mappings) that the application can use to determine what resources the user -is allowed to access on the application. - -The second type of use cases is that of a client that wants to gain access to remote services. In this case, the client asks {project_name} -to obtain an _access token_ it can use to invoke on other remote services on behalf of the user. {project_name} authenticates the user -then asks the user for consent to grant access to the client requesting it. The client then receives the _access token_. This _access token_ -is digitally signed by the realm. The client can make REST invocations on remote services using this _access token_. The REST service -extracts the _access token_, verifies the signature of the token, then decides based on access information within the token whether or not to process -the request. - -==== SAML 2.0 - -link:http://saml.xml.org/saml-specifications[SAML 2.0] is a similar specification to OIDC but a lot older and more mature. It has its roots in SOAP and the plethora -of WS-* specifications so it tends to be a bit more verbose than OIDC. SAML 2.0 is primarily an authentication protocol -that works by exchanging XML documents between the authentication server and the application. XML signatures and encryption are used to verify requests and responses. - -In {project_name} SAML serves two types of use cases: browser applications and REST invocations. - -There are really two types of use cases when using SAML. The first is an application that asks the {project_name} server to authenticate -a user for them. After a successful login, the application will receive an XML document that contains -something called a SAML assertion that specifies various attributes about the user. This XML document is digitally signed by -the realm and contains access information (like user role mappings) that the application can use to determine what resources the user -is allowed to access on the application. - -The second type of use cases is that of a client that wants to gain access to remote services. In this case, the client asks {project_name} -to obtain a SAML assertion it can use to invoke on other remote services on behalf of the user. - -==== OpenID Connect vs. SAML - -Choosing between OpenID Connect and SAML is not just a matter of using a newer protocol (OIDC) instead of the older more mature protocol (SAML). - -In most cases {project_name} recommends using OIDC. - -SAML tends to be a bit more verbose than OIDC. - -Beyond verbosity of exchanged data, if you compare the specifications you'll find that OIDC was designed to work with the web while SAML was retrofitted to work on top of the web. For example, OIDC is also more suited for HTML5/JavaScript applications because it is -easier to implement on the client side than SAML. As tokens are in the JSON format, -they are easier to consume by JavaScript. You will also find several nice features that -make implementing security in your web applications easier. For example, check out the link:https://openid.net/specs/openid-connect-session-1_0.html#ChangeNotification[iframe trick] that the specification uses to easily determine if a user is still logged in or not. - -SAML has its uses though. As you see the OIDC specifications evolve you see they implement more and more features that SAML has had for years. What we often see is that people pick SAML over OIDC because of the perception that it is more mature and also because they already have existing applications that are secured with it. - - diff --git a/securing_apps/topics/overview/terminology.adoc b/securing_apps/topics/overview/terminology.adoc deleted file mode 100644 index cbf88ab8e..000000000 --- a/securing_apps/topics/overview/terminology.adoc +++ /dev/null @@ -1,14 +0,0 @@ -=== Terminology - -These terms are used in this guide: - -* `Clients` are entities that interact with {project_name} to authenticate users and obtain tokens. Most often, clients are applications and services acting on behalf of users that provide a single sign-on experience to their users and access other services using the tokens issued by the server. Clients can also be entities only interested in obtaining tokens and acting on their own behalf for accessing other services. - -* `Applications` include a wide range of applications that work for specific platforms for each protocol - -* `Client adapters` are libraries that make it easy to secure applications and services with {project_name}. They provide a tight integration to the underlying platform and framework. - -* `Creating a client` and `registering a client` are the same action. `Creating a Client` is the term used to create a client by using the Admin Console. `Registering a client` is the term used to register a client by using the {project_name} Client Registration Service. - -* `A service account` is a type of client that is able to obtain tokens on its own behalf. - diff --git a/securing_apps/topics/overview/what-are-client-adapters.adoc b/securing_apps/topics/overview/what-are-client-adapters.adoc deleted file mode 100644 index b981f813f..000000000 --- a/securing_apps/topics/overview/what-are-client-adapters.adoc +++ /dev/null @@ -1,8 +0,0 @@ -=== Client adapters - -{project_name} client adapters are libraries that make it very easy to secure applications and services with {project_name}. We call them -adapters rather than libraries as they provide a tight integration to the underlying platform and framework. This makes our adapters easy to use and they -require less boilerplate code than what is typically required by a library. - - - diff --git a/securing_apps/topics/saml/java/MigrationFromOlderVersions.adoc b/securing_apps/topics/saml/java/MigrationFromOlderVersions.adoc deleted file mode 100644 index 05cbfe216..000000000 --- a/securing_apps/topics/saml/java/MigrationFromOlderVersions.adoc +++ /dev/null @@ -1,11 +0,0 @@ -==== Migration from older versions - -===== Migrating to 1.9.0 - -====== SAML SP Client Adapter changes - -Keycloak SAML SP Client Adapter now requires a specific endpoint, `/saml` to be registered with your IdP. -The SamlFilter must also be bound to /saml in addition to any other binding it has. -This had to be done because SAML POST binding would eat the request input stream and this would be really bad for clients that relied on it. - - diff --git a/securing_apps/topics/saml/java/assertion-api.adoc b/securing_apps/topics/saml/java/assertion-api.adoc deleted file mode 100644 index cd1457ae0..000000000 --- a/securing_apps/topics/saml/java/assertion-api.adoc +++ /dev/null @@ -1,107 +0,0 @@ - -==== Obtaining assertion attributes - -After a successful SAML login, your application code may want to obtain attribute values passed with the SAML assertion. -`HttpServletRequest.getUserPrincipal()` returns a `Principal` object that you can typecast into a {project_name} specific class -called `org.keycloak.adapters.saml.SamlPrincipal`. -This object allows you to look at the raw assertion and also has convenience functions to look up attribute values. - - -[source,java] ----- -package org.keycloak.adapters.saml; - -public class SamlPrincipal implements Serializable, Principal { - /** - * Get full saml assertion - * - * @return - */ - public AssertionType getAssertion() { - ... - } - - /** - * Get SAML subject sent in assertion - * - * @return - */ - public String getSamlSubject() { - ... - } - - /** - * Subject nameID format - * - * @return - */ - public String getNameIDFormat() { - ... - } - - @Override - public String getName() { - ... - } - - /** - * Convenience function that gets Attribute value by attribute name - * - * @param name - * @return - */ - public List getAttributes(String name) { - ... - - } - - /** - * Convenience function that gets Attribute value by attribute friendly name - * - * @param friendlyName - * @return - */ - public List getFriendlyAttributes(String friendlyName) { - ... - } - - /** - * Convenience function that gets first value of an attribute by attribute name - * - * @param name - * @return - */ - public String getAttribute(String name) { - ... - } - - /** - * Convenience function that gets first value of an attribute by attribute name - * - * - * @param friendlyName - * @return - */ - public String getFriendlyAttribute(String friendlyName) { - ... - } - - /** - * Get set of all assertion attribute names - * - * @return - */ - public Set getAttributeNames() { - ... - } - - /** - * Get set of all assertion friendly attribute names - * - * @return - */ - public Set getFriendlyNames() { - ... - } -} ----- diff --git a/securing_apps/topics/saml/java/debugging.adoc b/securing_apps/topics/saml/java/debugging.adoc deleted file mode 100644 index d6de7c5c1..000000000 --- a/securing_apps/topics/saml/java/debugging.adoc +++ /dev/null @@ -1,4 +0,0 @@ - -==== Troubleshooting - -The best way to troubleshoot problems is to turn on debugging for SAML in both the client adapter and {project_name} Server. Using your logging framework, set the log level to `DEBUG` for the `org.keycloak.saml` package. Turning this on allows you to see the SAML requests and response documents being sent to and from the server. diff --git a/securing_apps/topics/saml/java/error_handling.adoc b/securing_apps/topics/saml/java/error_handling.adoc deleted file mode 100644 index e4220b6d6..000000000 --- a/securing_apps/topics/saml/java/error_handling.adoc +++ /dev/null @@ -1,42 +0,0 @@ - -==== Error Handling - -{project_name} has some error handling facilities for servlet based client adapters. -When an error is encountered in authentication, the client adapter will call `HttpServletResponse.sendError()`. -You can set up an `error-page` within your `web.xml` file to handle the error however you want. -The client adapter can throw 400, 401, 403, and 500 errors. - - -[source,xml] ----- - - 403 - /ErrorHandler - ----- - -The client adapter also sets an `HttpServletRequest` attribute that you can retrieve. -The attribute name is `org.keycloak.adapters.spi.AuthenticationError`. -Typecast this object to: `org.keycloak.adapters.saml.SamlAuthenticationError`. -This class can tell you exactly what happened. -If this attribute is not set, then the adapter was not responsible for the error code. - - -[source,java] ----- -public class SamlAuthenticationError implements AuthenticationError { - public static enum Reason { - EXTRACTION_FAILURE, - INVALID_SIGNATURE, - ERROR_STATUS - } - - public Reason getReason() { - return reason; - } - public StatusResponseType getStatus() { - return status; - } -} ----- - diff --git a/securing_apps/topics/saml/java/general-config.adoc b/securing_apps/topics/saml/java/general-config.adoc deleted file mode 100644 index bed98f929..000000000 --- a/securing_apps/topics/saml/java/general-config.adoc +++ /dev/null @@ -1,64 +0,0 @@ -[[_saml-general-config]] - -==== General Adapter Config - -Each SAML client adapter supported by {project_name} can be configured by a simple XML text file. -This is what one might look like: - -[source,xml,subs="attributes+"] ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ----- - -Some of these configuration switches may be adapter specific and some are common across all adapters. -For Java adapters you can use `${...}` enclosure as System property replacement. -For example `${jboss.server.config.dir}`. - - diff --git a/securing_apps/topics/saml/java/general-config/idp_allowedclockskew_subelement.adoc b/securing_apps/topics/saml/java/general-config/idp_allowedclockskew_subelement.adoc deleted file mode 100644 index 25c03ca2e..000000000 --- a/securing_apps/topics/saml/java/general-config/idp_allowedclockskew_subelement.adoc +++ /dev/null @@ -1,19 +0,0 @@ -[[_sp-idp-allowedclockskew]] - -===== IDP AllowedClockSkew sub element - -The `AllowedClockSkew` optional sub element defines the allowed clock skew between IDP and SP. -The default value is 0. - -[source,xml] ----- -3500 ----- - -unit:: - It is possible to define the time unit attached to the value for this element. - Allowed values are MICROSECONDS, MILLISECONDS, MINUTES, NANOSECONDS and SECONDS. - This is _OPTIONAL_. - The default value is `SECONDS`. - - diff --git a/securing_apps/topics/saml/java/general-config/idp_element.adoc b/securing_apps/topics/saml/java/general-config/idp_element.adoc deleted file mode 100644 index b264dcbab..000000000 --- a/securing_apps/topics/saml/java/general-config/idp_element.adoc +++ /dev/null @@ -1,37 +0,0 @@ - -===== IDP Element - -Everything in the IDP element describes the settings for the identity provider (authentication server) the SP is communicating with. - -[source,xml] ----- - -... - ----- - -Here are the attribute config options you can specify within the `IDP` element declaration. - -entityID:: - This is the issuer ID of the IDP. This setting is _REQUIRED_. - -signaturesRequired:: - If set to `true`, the client adapter will sign every document it sends to the IDP. - Also, the client will expect that the IDP will be signing any documents sent to it. - This switch sets the default for all request and response types, but you will see later that you have some fine grain control over this. - This setting is _OPTIONAL_ and will default to `false`. -signatureAlgorithm:: - This is the signature algorithm that the IDP expects signed documents to use. - Allowed values are: `RSA_SHA1`, `RSA_SHA256`, `RSA_SHA512`, and `DSA_SHA1`. - This setting is _OPTIONAL_ - and defaults to `RSA_SHA256`. Note that `SHA1` based algorithms are deprecated and can be removed in the future. - We recommend the use of some more secure algorithm instead of `*_SHA1`. Also, with `*_SHA1` algorithms, verifying signatures - do not work if the SAML server (usually {project_name}) runs on Java 17 or higher. -signatureCanonicalizationMethod:: - This is the signature canonicalization method that the IDP expects signed documents to use. This setting is _OPTIONAL_. - The default value is `\http://www.w3.org/2001/10/xml-exc-c14n#` and should be good for most IDPs. -metadataUrl:: - The URL used to retrieve the IDP metadata, currently this is only used to pick up signing and encryption keys periodically which allow cycling of these keys on the IDP without manual changes on the SP side. diff --git a/securing_apps/topics/saml/java/general-config/idp_httpclient_subelement.adoc b/securing_apps/topics/saml/java/general-config/idp_httpclient_subelement.adoc deleted file mode 100644 index 120dd510a..000000000 --- a/securing_apps/topics/saml/java/general-config/idp_httpclient_subelement.adoc +++ /dev/null @@ -1,91 +0,0 @@ -[[_sp-idp-httpclient]] - -===== IDP HttpClient sub element - -The `HttpClient` optional sub element defines the properties of HTTP client used -for automatic obtaining of certificates containing public keys for IDP signature -verification via SAML descriptor of the IDP when -<<_sp-idp-keys-automatic,enabled>>. - -[source,xml] ----- - ----- - -connectionPoolSize:: - This config option defines how many connections to the {project_name} server should be pooled. - This is _OPTIONAL_. - The default value is `10`. - -disableTrustManager:: - If the {project_name} server requires HTTPS and this config option is set to `true` you do not have to specify a truststore. - This setting should only be used during development and *never* in production as it will disable verification of SSL certificates. - This is _OPTIONAL_. - The default value is `false`. - -allowAnyHostname:: - If the {project_name} server requires HTTPS and this config option is set to `true` - the {project_name} server's certificate is validated via the truststore, - but host name validation is not done. - This setting should only be used during development and *never* in production - as it will partly disable verification of SSL certificates. - This setting may be useful in test environments. This is _OPTIONAL_. - The default value is `false`. - -truststore:: - The value is the file path to a truststore file. - If you prefix the path with `classpath:`, then the truststore will be obtained from the deployment's classpath instead. - Used for outgoing HTTPS communications to the {project_name} server. - Client making HTTPS requests need a way to verify the host of the server they are talking to. - This is what the truststore does. - The keystore contains one or more trusted host certificates or certificate authorities. - You can create this truststore by extracting the public certificate of the {project_name} server's SSL keystore. - This is _REQUIRED_ unless `disableTrustManager` is `true`. - -truststorePassword:: - Password for the truststore. - This is _REQUIRED_ if `truststore` is set and the truststore requires a password. - -clientKeystore:: - This is the file path to a keystore file. - This keystore contains client certificate for two-way SSL when the adapter makes HTTPS requests to the {project_name} server. - This is _OPTIONAL_. - -clientKeystorePassword:: - Password for the client keystore and for the client's key. - This is _REQUIRED_ if `clientKeystore` is set. - -proxyUrl:: - URL to HTTP proxy to use for HTTP connections. - This is _OPTIONAL_. - -socketTimeout:: - Timeout for socket waiting for data after establishing the connection in milliseconds. - Maximum time of inactivity between two data packets. - A timeout value of zero is interpreted as an infinite timeout. - A negative value is interpreted as undefined (system default if applicable). - The default value is `-1`. - This is _OPTIONAL_. - -connectionTimeout:: - Timeout for establishing the connection with the remote host in milliseconds. - A timeout value of zero is interpreted as an infinite timeout. - A negative value is interpreted as undefined (system default if applicable). - The default value is `-1`. - This is _OPTIONAL_. - -connectionTtl:: - Connection time-to-live for client in milliseconds. - A value less than or equal to zero is interpreted as an infinite value. - The default value is `-1`. - This is _OPTIONAL_. diff --git a/securing_apps/topics/saml/java/general-config/idp_keys_subelement.adoc b/securing_apps/topics/saml/java/general-config/idp_keys_subelement.adoc deleted file mode 100644 index af36c64d0..000000000 --- a/securing_apps/topics/saml/java/general-config/idp_keys_subelement.adoc +++ /dev/null @@ -1,45 +0,0 @@ -[[_sp-idp-keys]] - -===== IDP Keys sub element - -The Keys sub element of IDP is only used to define the certificate or public key to use to verify documents signed by the IDP. -It is defined in the same way as the <<_saml-sp-keys,SP's Keys element>>. -But again, you only have to define one certificate or public key reference. Note that, if both IDP and SP are realized by -{project_name} server and adapter, respectively, there is no need to specify the keys for signature validation, see below. - -[[_sp-idp-keys-automatic]] -It is possible to configure SP to obtain public keys for IDP signature validation -from published certificates automatically, provided both SP and IDP are -implemented by {project_name}. -This is done by removing all declarations of signature validation keys in Keys -sub element. If the Keys sub element would then remain empty, it can be omitted -completely. The keys are then automatically obtained by SP from SAML descriptor, -location of which is derived from SAML endpoint URL specified in the -<<_sp-idp-singlesignonservice,IDP SingleSignOnService sub element>>. -Settings of the HTTP client that is used for SAML descriptor retrieval usually -needs no additional configuration, however it can be configured in the -<<_sp-idp-httpclient,IDP HttpClient sub element>>. - -It is also possible to specify multiple keys for signature verification. This is done by declaring multiple Key elements -within Keys sub element that have `signing` attribute set to `true`. -This is useful for example in situation when the IDP signing keys are rotated: There is -usually a transition period when new SAML protocol messages and assertions are signed -with the new key but those signed by previous key should still be accepted. - -It is not possible to configure {project_name} to both obtain the keys -for signature verification automatically and define additional static signature -verification keys. - -[source,xml] ----- - - ... - - - - - - - - ----- diff --git a/securing_apps/topics/saml/java/general-config/idp_singlelogoutservice_subelement.adoc b/securing_apps/topics/saml/java/general-config/idp_singlelogoutservice_subelement.adoc deleted file mode 100644 index 863699957..000000000 --- a/securing_apps/topics/saml/java/general-config/idp_singlelogoutservice_subelement.adoc +++ /dev/null @@ -1,47 +0,0 @@ - -===== IDP SingleLogoutService sub element - -The `SingleLogoutService` sub element defines the logout SAML endpoint of the IDP. The client adapter will send requests -to the IDP formatted via the settings within this element when it wants to log out. - -[source,xml] ----- - ----- - -signRequest:: - Should the client sign logout requests it makes to the IDP? This setting is _OPTIONAL_. - Defaults to whatever the IDP `signaturesRequired` element value is. - -signResponse:: - Should the client sign logout responses it sends to the IDP requests? This setting is _OPTIONAL_. - Defaults to whatever the IDP `signaturesRequired` element value is. - -validateRequestSignature:: - Should the client expect signed logout request documents from the IDP? This setting is _OPTIONAL_. Defaults to whatever the IDP `signaturesRequired` element value is. - -validateResponseSignature:: - Should the client expect signed logout response documents from the IDP? This setting is _OPTIONAL_. Defaults to whatever the IDP `signaturesRequired` element value is. - -requestBinding:: - This is the SAML binding type used for communicating SAML requests to the IDP. This setting is _OPTIONAL_. - The default value is `POST`, but you can set it to REDIRECT as well. - -responseBinding:: - This is the SAML binding type used for communicating SAML responses to the IDP. The values of this can be `POST` or `REDIRECT`. This setting is _OPTIONAL_. - The default value is `POST`, but you can set it to `REDIRECT` as well. - -postBindingUrl:: - This is the URL for the IDP's logout service when using the POST binding. This setting is _REQUIRED_ if using the `POST` binding. - -redirectBindingUrl:: - This is the URL for the IDP's logout service when using the REDIRECT binding. This setting is _REQUIRED_ if using the REDIRECT binding. - - diff --git a/securing_apps/topics/saml/java/general-config/idp_singlesignonservice_subelement.adoc b/securing_apps/topics/saml/java/general-config/idp_singlesignonservice_subelement.adoc deleted file mode 100644 index 2ec113575..000000000 --- a/securing_apps/topics/saml/java/general-config/idp_singlesignonservice_subelement.adoc +++ /dev/null @@ -1,47 +0,0 @@ -[[_sp-idp-singlesignonservice]] - -===== IDP SingleSignOnService sub element - -The `SingleSignOnService` sub element defines the login SAML endpoint of the IDP. -The client adapter will send requests -to the IDP formatted via the settings within this element when it wants to log in. - -[source,xml] ----- - - ----- - -Here are the config attributes you can define on this element: - -signRequest:: - Should the client sign authn requests? This setting is _OPTIONAL_. - Defaults to whatever the IDP `signaturesRequired` element value is. - -validateResponseSignature:: - Should the client expect the IDP to sign the assertion response document sent back from an authn request? - This setting _OPTIONAL_. Defaults to whatever the IDP `signaturesRequired` element value is. - -requestBinding:: - This is the SAML binding type used for communicating with the IDP. This setting is _OPTIONAL_. - The default value is `POST`, but you can set it to `REDIRECT` as well. - -responseBinding:: - SAML allows the client to request what binding type it wants authn responses to use. - The values of this can be `POST` or `REDIRECT`. This setting is _OPTIONAL_. - The default is that the client will not request a specific binding type for responses. - -assertionConsumerServiceUrl:: - URL of the assertion consumer service (ACS) where the IDP login service should send responses to. - This setting is _OPTIONAL_. By default it is unset, relying on the configuration in the IdP. - When set, it must end in `/saml`, for example `\http://sp.domain.com/my/endpoint/for/saml`. The value - of this property is sent in `AssertionConsumerServiceURL` attribute of SAML `AuthnRequest` message. - This property is typically accompanied by the `responseBinding` attribute. - -bindingUrl:: - This is the URL for the IDP login service that the client will send requests to. This setting is _REQUIRED_. - - diff --git a/securing_apps/topics/saml/java/general-config/roleidentifiers_element.adoc b/securing_apps/topics/saml/java/general-config/roleidentifiers_element.adoc deleted file mode 100644 index 94eafcd4d..000000000 --- a/securing_apps/topics/saml/java/general-config/roleidentifiers_element.adoc +++ /dev/null @@ -1,21 +0,0 @@ - -===== RoleIdentifiers element - -The `RoleIdentifiers` element defines what SAML attributes within the assertion received from the user should be used -as role identifiers within the Jakarta EE Security Context for the user. - -[source,xml] ----- - - - - - - ----- - -By default `Role` attribute values are converted to Jakarta EE roles. -Some IdPs send roles using a `member` or `memberOf` attribute assertion. -You can define one or more `Attribute` elements to specify which SAML attributes must be converted into roles. - - diff --git a/securing_apps/topics/saml/java/general-config/sp-keys.adoc b/securing_apps/topics/saml/java/general-config/sp-keys.adoc deleted file mode 100644 index e56b6477f..000000000 --- a/securing_apps/topics/saml/java/general-config/sp-keys.adoc +++ /dev/null @@ -1,26 +0,0 @@ -[[_saml-sp-keys]] - -===== Service Provider keys and key elements - -If the IdP requires that the client application (or SP) sign all of its requests and/or if the IdP will encrypt assertions, you must define the keys used to do this. -For client-signed documents you must define both the private and public key or certificate that is used to sign documents. -For encryption, you only have to define the private key that is used to decrypt it. - -There are two ways to describe your keys. -They can be stored within a Java KeyStore or you can copy/paste the keys directly within `keycloak-saml.xml` in the PEM format. - -[source,xml] ----- - - - - ... - - ----- - -The `Key` element has two optional attributes `signing` and `encryption`. -When set to true these tell the adapter what the key will be used for. -If both attributes are set to true, then the key will be used for both signing documents and decrypting encrypted assertions. -You must set at least one of these attributes to true. - diff --git a/securing_apps/topics/saml/java/general-config/sp-keys/key_pems.adoc b/securing_apps/topics/saml/java/general-config/sp-keys/key_pems.adoc deleted file mode 100644 index 43446f2c6..000000000 --- a/securing_apps/topics/saml/java/general-config/sp-keys/key_pems.adoc +++ /dev/null @@ -1,21 +0,0 @@ - -====== Key PEMS - -Within the `Key` element you declare your keys and certificates directly using the sub elements -`PrivateKeyPem`, `PublicKeyPem`, and `CertificatePem`. -The values contained in these elements must conform to the PEM key format. -You usually use this option if you are generating keys using `openssl` or similar command line tool. - -[source,xml] ----- - - - - 2341251234AB31234==231BB998311222423522334 - - - 211111341251234AB31234==231BB998311222423522334 - - - ----- diff --git a/securing_apps/topics/saml/java/general-config/sp-keys/keystore_element.adoc b/securing_apps/topics/saml/java/general-config/sp-keys/keystore_element.adoc deleted file mode 100644 index f00f4ffd0..000000000 --- a/securing_apps/topics/saml/java/general-config/sp-keys/keystore_element.adoc +++ /dev/null @@ -1,37 +0,0 @@ -[[_saml-keystore]] - -====== KeyStore element - -Within the `Key` element you can load your keys and certificates from a Java Keystore. This is declared within -a `KeyStore` element. - -[source,xml] ----- - - - - - - - - - ----- - -Here are the XML config attributes that are defined with the `KeyStore` element. - -file:: - File path to the key store. This option is _OPTIONAL_. The file or resource attribute must be set. - -resource:: - WAR resource path to the KeyStore. - This is a path used in method call to ServletContext.getResourceAsStream(). This option is _OPTIONAL_. The file or resource attribute must be set. - -password:: - The password of the KeyStore. This option is _REQUIRED_. - -If you are defining keys that the SP will use to sign document, you must also specify references to your private keys -and certificates within the Java KeyStore. -The `PrivateKey` and `Certificate` elements in the above example define an `alias` that points to the key or cert -within the keystore. Keystores require an additional password to access private keys. -In the `PrivateKey` element you must define this password within a `password` attribute. diff --git a/securing_apps/topics/saml/java/general-config/sp_element.adoc b/securing_apps/topics/saml/java/general-config/sp_element.adoc deleted file mode 100644 index 9f6797c06..000000000 --- a/securing_apps/topics/saml/java/general-config/sp_element.adoc +++ /dev/null @@ -1,72 +0,0 @@ - -===== SP element - -Here is the explanation of the SP element attributes: - -[source,xml] ----- - - -... - ----- -entityID:: - This is the identifier for this client. - The IdP needs this value to determine who the client is that is communicating with it. This setting is _REQUIRED_. - -sslPolicy:: - This is the SSL policy the adapter will enforce. - Valid values are: `ALL`, `EXTERNAL`, and `NONE`. - For `ALL`, all requests must come in via HTTPS. - For `EXTERNAL`, only non-private IP addresses must come over the wire via HTTPS. - For `NONE`, no requests are required to come over via HTTPS. - This setting is _OPTIONAL_. Default value is `EXTERNAL`. - -nameIDPolicyFormat:: - SAML clients can request a specific NameID Subject format. - Fill in this value if you want a specific format. - It must be a standard SAML format identifier: `urn:oasis:names:tc:SAML:2.0:nameid-format:transient`. - This setting is _OPTIONAL_. - By default, no special format is requested. - -forceAuthentication:: - SAML clients can request that a user is re-authenticated even if they are already logged in at the IdP. - Set this to `true` to enable. This setting is _OPTIONAL_. - Default value is `false`. - -isPassive:: - SAML clients can request that a user is never asked to authenticate even if they are not logged in at the IdP. - Set this to `true` if you want this. - Do not use together with `forceAuthentication` as they are opposite. This setting is _OPTIONAL_. - Default value is `false`. - -turnOffChangeSessionIdOnLogin:: - The session ID is changed by default on a successful login on some platforms to plug a security attack vector. - Change this to `true` to disable this. It is recommended you do not turn it off. - Default value is `false`. - -autodetectBearerOnly:: - This should be set to __true__ if your application serves both a web application and web services (for example SOAP or REST). - It allows you to redirect unauthenticated users of the web application to the {project_name} login page, - but send an HTTP `401` status code to unauthenticated SOAP or REST clients instead as they would not understand a redirect to the login page. - {project_name} auto-detects SOAP or REST clients based on typical headers like `X-Requested-With`, `SOAPAction` or `Accept`. - The default value is _false_. - -logoutPage:: - This sets the page to display after logout. If the page is a full URL, such as `http://web.example.com/logout.html`, - the user is redirected after logout to that page using the HTTP `302` status code. If a link without scheme part is specified, - such as `/logout.jsp`, the page is displayed after logout, _regardless of whether it lies in a protected area according - to `security-constraint` declarations in web.xml_, and the page is resolved relative to the deployment context root. - -keepDOMAssertion:: - This attribute should be set to __true__ to make the adapter store the DOM representation of the assertion in its - original form inside the `SamlPrincipal` associated to the request. The assertion document can be retrieved using - the method `getAssertionDocument` inside the principal. This is specially useful when re-playing a signed assertion. - The returned document is the one that was generated parsing the SAML response received by the {project_name} server. - This setting is _OPTIONAL_ and its default value is __false__ (the document is not saved inside the principal). diff --git a/securing_apps/topics/saml/java/general-config/sp_principalname_mapping_element.adoc b/securing_apps/topics/saml/java/general-config/sp_principalname_mapping_element.adoc deleted file mode 100644 index 8fb3b1bf8..000000000 --- a/securing_apps/topics/saml/java/general-config/sp_principalname_mapping_element.adoc +++ /dev/null @@ -1,27 +0,0 @@ - -===== SP PrincipalNameMapping element - -This element is optional. -When creating a Java Principal object that you obtain from methods such as `HttpServletRequest.getUserPrincipal()`, you can define what name is returned by the `Principal.getName()` method. - -[source,xml] ----- - - - - - - - - ----- - - -The `policy` attribute defines the policy used to populate this value. -The possible values for this attribute are: - -FROM_NAME_ID:: - This policy just uses whatever the SAML subject value is. This is the default setting -FROM_ATTRIBUTE:: - This will pull the value from one of the attributes declared in the SAML assertion received from the server. - You'll need to specify the name of the SAML assertion attribute to use within the `attribute` XML attribute. diff --git a/securing_apps/topics/saml/java/general-config/sp_role_mappings_provider_element.adoc b/securing_apps/topics/saml/java/general-config/sp_role_mappings_provider_element.adoc deleted file mode 100644 index efbb698aa..000000000 --- a/securing_apps/topics/saml/java/general-config/sp_role_mappings_provider_element.adoc +++ /dev/null @@ -1,98 +0,0 @@ - -===== RoleMappingsProvider element - -The `RoleMappingsProvider` is an optional element that allows for the specification of the id and configuration of the -`org.keycloak.adapters.saml.RoleMappingsProvider` SPI implementation that is to be used by the SAML adapter. - -When {project_name} is used as the IDP, it is possible to use the built-in role mappers to map any roles before adding them to the -SAML assertion. However, the SAML adapters can be used to send SAML requests to third party IDPs and in this case it might be -necessary to map the roles extracted from the assertion into a different set of roles as required by the SP. The -`RoleMappingsProvider` SPI allows for the configuration of pluggable role mappers that can be used to perform the necessary -mappings. - -The configuration of the provider looks as follows: - -[source,xml] ----- -... - - ... - - - - - - ... - - ----- -The `id` attribute identifies which of the installed providers is to be used. The `Property` sub-element can be used multiple times -to specify configuration properties for the provider. - -====== Properties Based role mappings provider - -{project_name} includes a `RoleMappingsProvider` implementation that performs the role mappings using a `properties` file. This -provider is identified by the id `properties-based-role-mapper` and is implemented by the `org.keycloak.adapters.saml.PropertiesBasedRoleMapper` -class. - -This provider relies on two configuration properties that can be used to specify the location of the `properties` file -that will be used. First, it checks if the `properties.file.location` property has been specified, using the configured -value to locate the `properties` file in the filesystem. If the configured file is not located, the provider throws a -`RuntimeException`. The following snippet shows an example of provider using the `properties.file.configuration` -option to load the `roles.properties` file from the `/opt/mappers/` directory in the filesystem: - -[source,xml,subs="attributes+"] ----- - - - ----- - -If the `properties.file.location` configuration has not been set, the provider checks the `properties.resource.location` -property, using the configured value to load the `properties` file from the `WAR` resource. If this configuration property is -also not present, the provider attempts to load the file from `/WEB-INF/role-mappings.properties` by default. Failure to load the file -from the resource will result in the provider throwing a `RuntimeException`. The following snippet shows an example of provider -using the `properties.resource.location` to load the `roles.properties` file from the application's `/WEB-INF/conf/` directory: - -[source,xml,subs="attributes+"] ----- - - - ----- - -The `properties` file can contain both roles and principals as keys, and a list of zero or more roles separated by comma -as values. When invoked, the implementation iterates through the set of roles that were extracted from the assertion and checks, -for each role, if a mapping exists. If the role maps to an empty role, it is discarded. If it maps to a set of one or more -different roles, then these roles are set in the result set. If no mapping is found for the role then it is included as is -in the result set. - -Once the roles have been processed, the implementation checks if the principal extracted from the assertion contains an entry -`properties` file. If a mapping for the principal exists, any roles listed as value are added to the result set. This -allows the assignment of extra roles to a principal. - -As an example, let's assume the provider has been configured with the following properties file: -[source] ----- -roleA=roleX,roleY -roleB= - -kc_user=roleZ - ----- - -If the principal `kc_user` is extracted from the assertion with roles `roleA`, `roleB` and `roleC`, the final set of roles -assigned to the principal will be `roleC`, `roleX`, `roleY` and `roleZ` because `roleA` is being mapped into both `roleX` -and `roleY`, `roleB` was mapped into an empty role - thus being discarded, `roleC` is used as is and finally an additional role -was added to the `kc_user` principal (`roleZ`). - -Note: to use spaces in role names for mappings, use unicode replacements for space. For example, incoming 'role A' would appear as: -[source] ----- -role\u0020A=roleX,roleY ----- - -====== Adding your own role mappings provider - -To add a custom role mappings provider one simply needs to implement the `org.keycloak.adapters.saml.RoleMappingsProvider` SPI. -For more details see the `SAML Role Mappings SPI` section in link:{developerguide_link}[{developerguide_name}]. diff --git a/securing_apps/topics/saml/java/idp-registration.adoc b/securing_apps/topics/saml/java/idp-registration.adoc deleted file mode 100644 index 452850b69..000000000 --- a/securing_apps/topics/saml/java/idp-registration.adoc +++ /dev/null @@ -1,6 +0,0 @@ - -==== Registering with an Identity Provider - -For each servlet-based adapter, the endpoint you register for the assert consumer service URL and single logout service -must be the base URL of your servlet application with `/saml` appended to it, that is, `$$https://example.com/contextPath/saml$$`. - diff --git a/securing_apps/topics/saml/java/java-adapters.adoc b/securing_apps/topics/saml/java/java-adapters.adoc deleted file mode 100644 index 99c97d1df..000000000 --- a/securing_apps/topics/saml/java/java-adapters.adoc +++ /dev/null @@ -1,4 +0,0 @@ - -=== Java adapters - -{project_name} comes with a range of different adapters for Java application. Selecting the correct adapter depends on the target platform. diff --git a/securing_apps/topics/saml/java/jboss-adapter/jboss-adapter-rpms.adoc b/securing_apps/topics/saml/java/jboss-adapter/jboss-adapter-rpms.adoc deleted file mode 100644 index ecf284a8a..000000000 --- a/securing_apps/topics/saml/java/jboss-adapter/jboss-adapter-rpms.adoc +++ /dev/null @@ -1,95 +0,0 @@ -[[_jboss7_adapter_rpm_saml]] -==== Installing JBoss EAP 7 Adapters from an RPM - -NOTE: With Red Hat Enterprise Linux 7, the term channel was replaced with the term repository. In these instructions only the term repository is used. - -.Prerequisites - -You must subscribe to the JBoss EAP 7 repository before you can install the EAP 7 adapters from an RPM. - -* Ensure that your Red Hat Enterprise Linux system is registered to your account using Red Hat Subscription Manager. For more information see the link:https://access.redhat.com/documentation/en-us/red_hat_subscription_management/2022[Red Hat Subscription Management documentation]. - -* If you are already subscribed to another JBoss EAP repository, you must unsubscribe from that repository first. -+ -For Red Hat Enterprise Linux 6, 7: Using Red Hat Subscription Manager, subscribe to the {appserver_name} {appserver_version} repository using the following command. Replace with either 6 or 7 depending on your Red Hat Enterprise Linux version. -+ -[source,bash,subs="attributes+"] ----- -$ sudo subscription-manager repos --enable=jb-eap-7-for-rhel--server-rpms ----- -+ -For Red Hat Enterprise Linux 8: Using Red Hat Subscription Manager, subscribe to the {appserver_name} {appserver_version} repository using the following command: -+ -[source,bash,subs="attributes+"] ----- -$ sudo subscription-manager repos --enable=jb-eap-{appserver_version}-for-rhel-8-x86_64-rpms --enable=rhel-8-for-x86_64-baseos-rpms --enable=rhel-8-for-x86_64-appstream-rpms ----- - -.Procedure - -. Install the EAP 7 adapters for SAML based on your version of Red Hat Enterprise Linux. - -* Install on Red Hat Linux 7: -+ -[source,bash,subs="attributes+"] ----- -$ sudo yum install eap7-keycloak-saml-adapter-sso7_6 ----- - -* Install on Red Hat Enterprise Linux 8: -+ -[source,bash,subs="attributes+"] ----- -$ sudo dnf install eap7-keycloak-adapter-sso7_6 ----- -+ -NOTE: The default EAP_HOME path for the RPM installation is /opt/rh/eap7/root/usr/share/wildfly. - -. Run the installation script for the SAML module: -+ -[source,bash,subs="attributes+"] ----- -$ $EAP_HOME/bin/jboss-cli.sh -c --file=$EAP_HOME/bin/adapter-install-saml.cli ----- - -Your installation is complete. - -[[_jboss6_adapter_rpm_saml]] -==== Installing JBoss EAP 6 Adapters from an RPM - -NOTE: With Red Hat Enterprise Linux 7, the term channel was replaced with the term repository. In these instructions only the term repository is used. - -.Prerequisites - -You must subscribe to the JBoss EAP 6 repository before you can install the EAP 6 adapters from an RPM. - -* Ensure that your Red Hat Enterprise Linux system is registered to your account using Red Hat Subscription Manager. For more information see the link:https://access.redhat.com/documentation/en-us/red_hat_subscription_management/2022[Red Hat Subscription Management documentation]. - -* If you are already subscribed to another JBoss EAP repository, you must unsubscribe from that repository first. - -* Using Red Hat Subscription Manager, subscribe to the JBoss EAP 6 repository using the following command. Replace with either 6 or 7 depending on your Red Hat Enterprise Linux version. -+ -[source,bash,subs="attributes+"] ----- -$ sudo subscription-manager repos --enable=jb-eap-6-for-rhel--server-rpms ----- - -.Procedure - -. Install the EAP 6 adapters for SAML using the following command: -+ -[source,bash,subs="attributes+"] ----- -$ sudo yum install keycloak-saml-adapter-sso7_6-eap6 ----- -+ -NOTE: The default EAP_HOME path for the RPM installation is /opt/rh/eap6/root/usr/share/wildfly. - -. Run the installation script for the SAML module: -+ -[source,bash,subs="attributes+"] ----- -$ $EAP_HOME/bin/jboss-cli.sh -c --file=$EAP_HOME/bin/adapter-install-saml.cli ----- - -Your installation is complete. diff --git a/securing_apps/topics/saml/java/jboss-adapter/jboss-adapter-samesite-setting.adoc b/securing_apps/topics/saml/java/jboss-adapter/jboss-adapter-samesite-setting.adoc deleted file mode 100644 index 423e8955c..000000000 --- a/securing_apps/topics/saml/java/jboss-adapter/jboss-adapter-samesite-setting.adoc +++ /dev/null @@ -1,20 +0,0 @@ -[[_saml-jboss-adapter-samesite-setting]] -===== Setting SameSite value for JSESSIONID cookie - -Browsers are planning to set the default value for the `SameSite` attribute for cookies to `Lax`. This setting means -that cookies will be sent to applications only if the request originates in the same domain. This behavior can affect -the SAML POST binding which may become non-functional. To preserve full functionality of the SAML adapter, we recommend -setting the `SameSite` value to `None` for the `JSESSIONID` cookie created by your container. Not doing so may result in -resetting the container's session with each request to {project_name}. - -NOTE: To avoid setting the `SameSite` attribute to `None`, consider switching to the REDIRECT binding -if it is acceptable, or to OIDC protocol where this workaround is not necessary. - -To set the `SameSite` value to `None` for the `JSESSIONID` cookie in Wildfly/EAP, add a file `undertow-handlers.conf` -with the following content to the `WEB-INF` directory of your application. - - samesite-cookie(mode=None, cookie-pattern=JSESSIONID) - -The support for this configuration is available in Wildfly from version 19.1.0. - - diff --git a/securing_apps/topics/saml/java/jboss-adapter/jboss_adapter_installation.adoc b/securing_apps/topics/saml/java/jboss-adapter/jboss_adapter_installation.adoc deleted file mode 100644 index e58017632..000000000 --- a/securing_apps/topics/saml/java/jboss-adapter/jboss_adapter_installation.adoc +++ /dev/null @@ -1,128 +0,0 @@ - -[[_saml-jboss-adapter-installation]] -==== Installing adapters from a ZIP file - -Each adapter is a separate download on the {project_name} download site. - -ifeval::[{project_community}==true] - -NOTE: We only test and maintain adapter with the most recent version of WildFly available upon the release. Once the new version of WildFly is released, the current adapters become deprecated and support for them will be removed after the next WildFly release. -The other alternative is to switch your applications from WildFly to the JBoss EAP, as the JBoss EAP adapter is supported for a much longer period. - -.Procedure - -. Install the adapter that applies to your application server from the link:https://www.keycloak.org/downloads[Downloads] site. - -* Install on WildFly or on JBoss EAP 7: -+ -[source] ----- -$ cd $WILDFLY_HOME -$ unzip keycloak-saml-wildfly-adapter-dist.zip ----- -+ -These zip files create new JBoss Modules specific to the WildFly/JBoss EAP SAML Adapter within your WildFly or JBoss EAP distro. -endif::[] -ifeval::[{project_product}==true] -.Procedure - -. Install the adapter that applies to your application server from the link:https://access.redhat.com/jbossnetwork/restricted/listSoftware.html?downloadType=distributions&product=core.service.rhsso[Downloads] site. - -* Install on JBoss EAP 7.x: -+ -[source] ----- -$ cd $EAP_HOME -$ unzip rh-sso-saml-eap7-adapter.zip ----- - -* Install on JBoss EAP 6.x: -+ -[source] -+ ----- -$ cd $EAP_HOME -$ unzip rh-sso-saml-eap6-adapter.zip ----- -+ -These ZIP files create new JBoss Modules specific to the JBoss EAP SAML Adapter within your JBoss EAP distribution. -endif::[] - -. Use a CLI script to enable the {project_name} SAML Subsystem within your app server's server configuration: `domain.xml` or `standalone.xml`. -+ -Start the server and run the script that applies to your application server. -ifeval::[{project_community}==true] - -* Install on WildFly. -+ -[source] ----- -$ cd $JBOSS_HOME -$ ./bin/jboss-cli.sh -c --file=bin/adapter-elytron-install-saml.cli ----- - -endif::[] -ifeval::[{project_product}==true] -* Use this command for JBoss EAP 7.1 or newer -+ -[source] ----- -$ cd $JBOSS_HOME -$ ./bin/jboss-cli.sh -c --file=bin/adapter-elytron-install-saml.cli ----- - -* Use this command for JBoss EAP 7.0 and EAP 6.4 -+ -[source] ----- -$ cd $JBOSS_HOME -$ ./bin/jboss-cli.sh -c --file=bin/adapter-install-saml.cli ----- -+ -NOTE: It is possible to use the legacy non-Elytron adapter on JBoss EAP 7.1 or newer as well, meaning you can use `adapter-install-saml.cli` -even on those versions. However, we recommend to use the newer Elytron adapter. -+ -endif::[] -The script will add the extension, subsystem, and optional security-domain as described below. - -[source,xml] ----- - - - - - ... - - - - - ... - ----- - -The `keycloak` security domain should be used with EJBs and other components when you need the security context created -in the secured web tier to be propagated to the EJBs (other EE component) you are invoking. -Otherwise this configuration is optional. - -[source,xml] ----- - - - - -... - - - - - - ----- - -The security context is propagated to the EJB tier automatically. - -===== JBoss SSO - -{appserver_name} has built-in support for single sign-on for web applications deployed to the same {appserver_name} -instance. This should not be enabled when using {project_name}. diff --git a/securing_apps/topics/saml/java/jboss-adapter/required_per_war_configuration.adoc b/securing_apps/topics/saml/java/jboss-adapter/required_per_war_configuration.adoc deleted file mode 100644 index 1110f421e..000000000 --- a/securing_apps/topics/saml/java/jboss-adapter/required_per_war_configuration.adoc +++ /dev/null @@ -1,64 +0,0 @@ - -===== Securing a WAR - -This section describes how to secure a WAR directly by adding config and editing files within your WAR package. - -The first thing you must do is create a `keycloak-saml.xml` adapter config file within the `WEB-INF` directory of your WAR. -The format of this config file is described in the <<_saml-general-config,General Adapter Config>> section. - -Next you must set the `auth-method` to `KEYCLOAK-SAML` in `web.xml`. -You also have to use standard servlet security to specify role-base constraints on your URLs. -Here's an example _web.xml_ file: - -[source,xml] ----- - - - - customer-portal - - - - Admins - /admin/* - - - admin - - - CONFIDENTIAL - - - - - Customers - /customers/* - - - user - - - CONFIDENTIAL - - - - - KEYCLOAK-SAML - this is ignored currently - - - - admin - - - user - - ----- - -All standard servlet settings except the `auth-method` setting. - - diff --git a/securing_apps/topics/saml/java/jboss-adapter/securing_wars.adoc b/securing_apps/topics/saml/java/jboss-adapter/securing_wars.adoc deleted file mode 100644 index 11f1efb2e..000000000 --- a/securing_apps/topics/saml/java/jboss-adapter/securing_wars.adoc +++ /dev/null @@ -1,82 +0,0 @@ - -===== Securing WARs using the {project_name} SAML Subsystem - -You do not have to open a WAR to secure it with {project_name}. -Alternatively, you can externally secure it via the {project_name} SAML Adapter Subsystem. -While you don't have to specify KEYCLOAK-SAML as an `auth-method`, you still have to define the `security-constraints` in `web.xml`. -You do not, however, have to create a `WEB-INF/keycloak-saml.xml` file. -This metadata is instead defined within the XML in your server's `domain.xml` or `standalone.xml` subsystem configuration section. - -[source,xml,subs="attributes+"] ----- - - - - - - - - - - ... - - - - ----- - -The `secure-deployment` `name` attribute identifies the WAR you want to secure. -Its value is the `module-name` defined in `web.xml` with `.war` appended. -The rest of the configuration uses the same XML syntax as `keycloak-saml.xml` configuration defined in <<_saml-general-config,General Adapter Config>>. - -An example configuration: - -[source,xml,subs="attributes+"] ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ----- diff --git a/securing_apps/topics/saml/java/jetty-adapter.adoc b/securing_apps/topics/saml/java/jetty-adapter.adoc deleted file mode 100644 index c367563ed..000000000 --- a/securing_apps/topics/saml/java/jetty-adapter.adoc +++ /dev/null @@ -1,7 +0,0 @@ -[[_jetty_saml_adapter]] - -==== Jetty SAML adapters - -To be able to secure WAR apps deployed on Jetty you must install the {project_name} Jetty 9.4 SAML adapter into your Jetty installation. You then provide some extra configuration in each WAR you deploy to Jetty. - -Use the following installation and configuration procedures. diff --git a/securing_apps/topics/saml/java/jetty-adapter/jetty9_installation.adoc b/securing_apps/topics/saml/java/jetty-adapter/jetty9_installation.adoc deleted file mode 100644 index d3f898ba3..000000000 --- a/securing_apps/topics/saml/java/jetty-adapter/jetty9_installation.adoc +++ /dev/null @@ -1,30 +0,0 @@ -[[_jetty9_saml_adapter_installation]] - -===== Jetty 9 Installing the adapter - -{project_name} has a separate SAML adapter for Jetty 9.4. Adapters are no longer included with the appliance or war distribution. Each adapter is a separate download on the Keycloak download site. -They are also available as a maven artifact. - -.Procedure -. Download the {project_name} Jetty 9.4 adapter ZIP archive from the link:https://www.keycloak.org/downloads[Keycloak Downloads] site. - -. Unzip the Jetty 9.4 distro into Jetty 9.4's root directory. -+ -==== -[NOTE] -Including adapter's jars within your WEB-INF/lib directory will not work. -==== -+ -[source] ----- -$ cd $JETTY_HOME -$ unzip keycloak-saml-jetty94-adapter-dist.zip ----- - -. Enable the keycloak module for your jetty.base. -+ -[source] ----- -$ cd your-base -$ java -jar $JETTY_HOME/start.jar --add-to-startd=keycloak ----- diff --git a/securing_apps/topics/saml/java/jetty-adapter/jetty9_per_war_config.adoc b/securing_apps/topics/saml/java/jetty-adapter/jetty9_per_war_config.adoc deleted file mode 100644 index 2343749c9..000000000 --- a/securing_apps/topics/saml/java/jetty-adapter/jetty9_per_war_config.adoc +++ /dev/null @@ -1,64 +0,0 @@ - -[[_saml-jetty9-per-war]] -===== Jetty 9 WAR Configuration - -Use this procedure to secure a WAR directly. - -.Procedure -. Create a `WEB-INF/jetty-web.xml` file in your WAR package. -This is a Jetty specific config file and you must define a Keycloak specific authenticator within it. -+ -[source,xml] ----- - - - - - - - - - - ----- - -. Create a `keycloak-saml.xml` adapter config file within the `WEB-INF` directory of your WAR. -The format of this config file is described in the <<_saml-general-config,General Adapter Config>> section. - -. Specify both a `login-config` and use standard servlet security to specify role-base constraints on your URLs. Here's an example: -+ -[source,xml] ----- - - - customer-portal - - - - Customers - /* - - - user - - - CONFIDENTIAL - - - - - BASIC - this is ignored currently - - - - admin - - - user - - ----- diff --git a/securing_apps/topics/saml/java/logout.adoc b/securing_apps/topics/saml/java/logout.adoc deleted file mode 100644 index 15166c522..000000000 --- a/securing_apps/topics/saml/java/logout.adoc +++ /dev/null @@ -1,74 +0,0 @@ -==== Logout - -There are multiple ways you can log out from a web application. -For Jakarta EE servlet containers, you can call `HttpServletRequest.logout()`. For any other browser application, you can point -the browser at any url of your web application that has a security constraint and pass in a query parameter GLO, i.e. `$$http://myapp?GLO=true$$`. -This will log you out if you have an SSO session with your browser. - -[[_saml_logout_in_cluster]] -===== Logout in clustered environment - -Internally, the SAML adapter stores a mapping between the SAML session index, principal name (when known), and HTTP session ID. -This mapping can be maintained in JBoss application server family (WildFly 10/11, EAP 6/7) across cluster for distributable -applications. As a precondition, the HTTP sessions need to be distributed across cluster (i.e. application is marked with -`` tag in application's `web.xml`). - -To enable the functionality, add the following section to your `/WEB_INF/web.xml` file: - -For EAP 7, WildFly 10/11: - -[source,xml] ----- - - keycloak.sessionIdMapperUpdater.classes - org.keycloak.adapters.saml.wildfly.infinispan.InfinispanSessionCacheIdMapperUpdater - ----- - -For EAP 6: - -[source,xml] ----- - - keycloak.sessionIdMapperUpdater.classes - org.keycloak.adapters.saml.jbossweb.infinispan.InfinispanSessionCacheIdMapperUpdater - ----- - -If the session cache of the deployment is named `_deployment-cache_`, the cache used for SAML mapping will be named -as `_deployment-cache_.ssoCache`. The name of the cache can be overridden by a context parameter -`keycloak.sessionIdMapperUpdater.infinispan.cacheName`. The cache container containing the cache will be the same as -the one containing the deployment session cache, but can be overridden by a context parameter -`keycloak.sessionIdMapperUpdater.infinispan.containerName`. - -By default, the configuration of the SAML mapping cache will be derived from session cache. The configuration can -be manually overridden in cache configuration section of the server just the same as other caches. - -Currently, to provide reliable service, it is recommended to use replicated cache for the SAML session cache. -Using distributed cache may lead to results where the SAML logout request would land to a node with no access -to SAML session index to HTTP session mapping which would lead to unsuccessful logout. - -[[_saml_logout_in_cross_dc]] -===== Logout in cross-site scenario - -The cross-site scenario only applies to WildFly 10 and higher, and EAP 7 and higher. - -Special handling is needed for handling sessions that span multiple data centers. Imagine the following scenario: - -1. Login requests are handled within cluster in data center 1. - -2. Admin issues logout request for a particular SAML session, the request lands in data center 2. - -The data center 2 has to log out all sessions that are present in data center 1 (and all other data centers that -share HTTP sessions). - -To cover this case, the SAML session cache described <<_saml_logout_in_cluster,above>> needs to be replicated -not only within individual clusters but across all the data centers for example -https://access.redhat.com/documentation/en-us/red_hat_data_grid/6.6/html/administration_and_configuration_guide/chap-externalize_sessions#Externalize_HTTP_Session_from_JBoss_EAP_6.x_to_JBoss_Data_Grid[via standalone Infinispan/JDG server]: - -1. A cache has to be added to the standalone Infinispan/JDG server. - -2. The cache from previous item has to be added as a remote store for the respective SAML session cache. - -Once remote store is found to be present on SAML session cache during deployment, it is watched for changes -and the local SAML session cache is updated accordingly. diff --git a/securing_apps/topics/saml/java/multi-tenancy.adoc b/securing_apps/topics/saml/java/multi-tenancy.adoc deleted file mode 100644 index ed4106b84..000000000 --- a/securing_apps/topics/saml/java/multi-tenancy.adoc +++ /dev/null @@ -1,72 +0,0 @@ -[[_saml_multi_tenancy]] -==== Multi Tenancy - -SAML offers the same functionality as OIDC for <<_multi_tenancy,Multi Tenancy>>, meaning that a single target application (WAR) can be secured with multiple {project_name} realms. The realms can be located on the same {project_name} instance or on different instances. - -To do this, the application must have multiple `keycloak-saml.xml` adapter configuration files. - -While you could have multiple instances of your WAR with different adapter configuration files deployed to different context-paths, this may be inconvenient and you may also want to select the realm based on something other than context-path. - -{project_name} makes it possible to have a custom config resolver, so you can choose which adapter config is used for each request. In SAML, the configuration is only interesting in the login processing; once the user is logged in, the session is authenticated and it does not matter if the `keycloak-saml.xml` returned is different. For that reason, returning the same configuration for the same session is the correct way to go. - -To achieve this, create an implementation of `org.keycloak.adapters.saml.SamlConfigResolver`. The following example uses the `Host` header to locate the proper configuration and load it and the associated elements from the applications' Java classpath: - -[source,java] ----- -package example; - -import java.io.InputStream; -import org.keycloak.adapters.saml.SamlConfigResolver; -import org.keycloak.adapters.saml.SamlDeployment; -import org.keycloak.adapters.saml.config.parsers.DeploymentBuilder; -import org.keycloak.adapters.saml.config.parsers.ResourceLoader; -import org.keycloak.adapters.spi.HttpFacade; -import org.keycloak.saml.common.exceptions.ParsingException; - -public class SamlMultiTenantResolver implements SamlConfigResolver { - - @Override - public SamlDeployment resolve(HttpFacade.Request request) { - String host = request.getHeader("Host"); - String realm = null; - if (host.contains("tenant1")) { - realm = "tenant1"; - } else if (host.contains("tenant2")) { - realm = "tenant2"; - } else { - throw new IllegalStateException("Not able to guess the keycloak-saml.xml to load"); - } - - InputStream is = getClass().getResourceAsStream("/" + realm + "-keycloak-saml.xml"); - if (is == null) { - throw new IllegalStateException("Not able to find the file /" + realm + "-keycloak-saml.xml"); - } - - ResourceLoader loader = new ResourceLoader() { - @Override - public InputStream getResourceAsStream(String path) { - return getClass().getResourceAsStream(path); - } - }; - - try { - return new DeploymentBuilder().build(is, loader); - } catch (ParsingException e) { - throw new IllegalStateException("Cannot load SAML deployment", e); - } - } -} ----- - -You must also configure which `SamlConfigResolver` implementation to use with the `keycloak.config.resolver` context-param in your `web.xml`: - -[source,xml] ----- - - ... - - keycloak.config.resolver - example.SamlMultiTenantResolver - - ----- diff --git a/securing_apps/topics/saml/java/saml-jboss-adapter.adoc b/securing_apps/topics/saml/java/saml-jboss-adapter.adoc deleted file mode 100644 index 4fc0ca774..000000000 --- a/securing_apps/topics/saml/java/saml-jboss-adapter.adoc +++ /dev/null @@ -1,26 +0,0 @@ -[[_saml_jboss_adapter]] - -ifeval::[{project_community}==true] -==== JBoss EAP/WildFly adapter -endif::[] -ifeval::[{project_product}==true] -==== JBoss EAP adapter -endif::[] - -ifeval::[{project_community}==true] -To be able to secure WAR apps deployed on JBoss EAP or WildFly, you must install and configure the {project_name} SAML Adapter Subsystem. -endif::[] -ifeval::[{project_product}==true] -To be able to secure WAR apps deployed on JBoss EAP, you must install and configure the {project_name} SAML Adapter Subsystem. -endif::[] - -You then provide a keycloak config, `/WEB-INF/keycloak-saml.xml` file in your WAR and change the auth-method to KEYCLOAK-SAML within web.xml. - -ifeval::[{project_product}==true] -You install the adapters by using a ZIP file or an RPM. - -* <<_saml-jboss-adapter-installation, Installing adapters from a ZIP file>> -* <<_jboss7_adapter_rpm_saml, Installing JBoss EAP 7 Adapters from an RPM>> -* <<_jboss6_adapter_rpm_saml, Installing JBoss EAP 6 Adapters from an RPM>> -endif::[] - diff --git a/securing_apps/topics/saml/java/saml_adapter_overview.adoc b/securing_apps/topics/saml/java/saml_adapter_overview.adoc deleted file mode 100644 index 7cb067749..000000000 --- a/securing_apps/topics/saml/java/saml_adapter_overview.adoc +++ /dev/null @@ -1,6 +0,0 @@ -= Overview - -This document describes the Keycloak SAML client adapter and how it can be configured for a variety of platforms. -The Keycloak SAML client adapter is a standalone component that provides generic SAML 2.0 support for your web applications. -There are no Keycloak server extensions built into it. -As long as the Identity Provider (IdP) being communicated with supports standard SAML, the Keycloak SAML client adapter should be able to integrate with it. diff --git a/securing_apps/topics/saml/java/servlet-filter-adapter.adoc b/securing_apps/topics/saml/java/servlet-filter-adapter.adoc deleted file mode 100644 index f78252954..000000000 --- a/securing_apps/topics/saml/java/servlet-filter-adapter.adoc +++ /dev/null @@ -1,71 +0,0 @@ -[[_java-servlet-filter-adapter]] -==== Java Servlet filter adapter - -If you want to use SAML with a Java servlet application that doesn't have an adapter for that servlet platform, you can -opt to use the servlet filter adapter that {project_name} has. -This adapter works a little differently than the other adapters. -You still have to specify a `/WEB-INF/keycloak-saml.xml` file as defined in -the <<_saml-general-config,General Adapter Config>> section, but -you do not define security constraints in _web.xml_. -Instead you define a filter mapping using the {project_name} servlet filter adapter to secure the url patterns you want to secure. - -NOTE: Backchannel logout works a bit differently than the standard adapters. - Instead of invalidating the http session it instead marks the session ID as logged out. - There's just no way of arbitrarily invalidating an HTTP session based on a session ID. - -WARNING: Backchannel logout does not currently work when you have a clustered application that uses the SAML filter. - -[source,xml] ----- - - - customer-portal - - - Keycloak Filter - org.keycloak.adapters.saml.servlet.SamlFilter - - - Keycloak Filter - /* - - ----- - -The {project_name} filter has the same configuration parameters available as the other adapters except you must -define them as filter init params instead of context params. - -You can define multiple filter mappings if you have various different secure and unsecure url patterns. - -WARNING: You must have a filter mapping that covers `/saml`. - This mapping covers all server callbacks. - -When registering SPs with an IdP, you must register `http[s]://hostname/{context-root}/saml` as your Assert Consumer Service URL and Single Logout Service URL. - -To use this filter, include this maven artifact in your WAR poms: - -[source,xml,subs="attributes+"] ----- - - org.keycloak - keycloak-saml-servlet-filter-adapter - {project_versionMvn} - ----- - -In order to use <<_saml_multi_tenancy,Multi Tenancy>> the `keycloak.config.resolver` parameter should be passed as a filter parameter. - -[source,xml] ----- - - Keycloak Filter - org.keycloak.adapters.saml.servlet.SamlFilter - - keycloak.config.resolver - example.SamlMultiTenantResolver - - ----- diff --git a/securing_apps/topics/saml/java/tomcat-adapter.adoc b/securing_apps/topics/saml/java/tomcat-adapter.adoc deleted file mode 100644 index 31cf05b73..000000000 --- a/securing_apps/topics/saml/java/tomcat-adapter.adoc +++ /dev/null @@ -1,8 +0,0 @@ -[[_saml-tomcat-adapter]] - -==== Tomcat SAML adapters - -To be able to secure WAR apps deployed on Tomcat 8 or 9 you must install the Keycloak Tomcat SAML adapter into your Tomcat installation. -You then have to provide some extra configuration in each WAR you deploy to Tomcat. - - diff --git a/securing_apps/topics/saml/java/tomcat-adapter/tomcat-adapter-samesite-setting.adoc b/securing_apps/topics/saml/java/tomcat-adapter/tomcat-adapter-samesite-setting.adoc deleted file mode 100644 index 8861a0d14..000000000 --- a/securing_apps/topics/saml/java/tomcat-adapter/tomcat-adapter-samesite-setting.adoc +++ /dev/null @@ -1,24 +0,0 @@ -[[_saml-tomcat-adapter-samesite-setting]] -===== Setting SameSite value for JSESSIONID cookie - -Browsers are planning to set the default value for the `SameSite` attribute for cookies to `Lax`. This setting means -that cookies will be sent to applications only if the request originates in the same domain. This behavior can affect -the SAML POST binding which may become non-functional. To preserve full functionality of the SAML adapter, we recommend -setting the `SameSite` value to `None` for the `JSESSIONID` cookie created by your container. Not doing so may result in -resetting the container's session with each request to {project_name}. - -NOTE: To avoid setting the `SameSite` attribute to `None`, consider switching to the REDIRECT binding -if it is acceptable, or to OIDC protocol where this workaround is not necessary. - -To set the `SameSite` value to `None` for `JSESSIONID` cookie in Tomcat add following configuration to the`context.xml` -of your application. Note, this will set the `SameSite` value to `None` for all cookies created by Tomcat container. - -[source,xml] ----- - ----- - -WARNING: It is not possible to set the `SameSite` attribute only to a subset of cookies, therefore all cookies created -for your application will have this attribute set to `None`. - -The support for this feature is available in Tomcat from versions 9.0.29 and 8.5.49. diff --git a/securing_apps/topics/saml/java/tomcat-adapter/tomcat_adapter_installation.adoc b/securing_apps/topics/saml/java/tomcat-adapter/tomcat_adapter_installation.adoc deleted file mode 100644 index a5d3e9491..000000000 --- a/securing_apps/topics/saml/java/tomcat-adapter/tomcat_adapter_installation.adoc +++ /dev/null @@ -1,26 +0,0 @@ - -[[_saml-tomcat-adapter-installation]] -===== Installing the adapter - -Adapters are no longer included with the appliance or war distribution. -Each adapter is a separate download on the Keycloak Downloads site. -They are also available as a maven artifact. - -.Procedure - -. Download the adapter for the Tomcat version on your system from the link:https://www.keycloak.org/downloads[Keycloak Downloads] site: - -. Install on the Tomcat version on your system: - -* Install on Tomcat 8 or 9: -+ -[source] ----- -$ cd $TOMCAT_HOME/lib -$ unzip keycloak-saml-tomcat-adapter-dist.zip ----- - -==== -[NOTE] -Including the adapter's jars within your WEB-INF/lib directory will not work. The Keycloak SAML adapter is implemented as a Valve and valve code must reside in Tomcat's main lib/ directory. -==== diff --git a/securing_apps/topics/saml/java/tomcat-adapter/tomcat_adapter_per_war_config.adoc b/securing_apps/topics/saml/java/tomcat-adapter/tomcat_adapter_per_war_config.adoc deleted file mode 100644 index 3119addaf..000000000 --- a/securing_apps/topics/saml/java/tomcat-adapter/tomcat_adapter_per_war_config.adoc +++ /dev/null @@ -1,57 +0,0 @@ - -===== Securing a WAR - -Use this procedure to secure a WAR directly by adding config and editing files within your WAR package. - -.Procedure - -. Create a `META-INF/context.xml` file in your WAR package. -This is a Tomcat specific config file and you must define a Keycloak specific Valve. -+ -[source,xml] ----- - - - ----- - -. Create a `keycloak-saml.xml` adapter config file within the `WEB-INF` directory of your WAR. -The format of this config file is described in the <<_saml-general-config,General Adapter Config>> section. - -. Specify both a `login-config` and use standard servlet security to specify role-base constraints on your URLs. -Here's an example: -+ -[source,xml] ----- - - - customer-portal - - - - Customers - /* - - - user - - - - - BASIC - this is ignored currently - - - - admin - - - user - - ----- - -If the `keycloak-saml.xml` does not explicitly set `assertionConsumerServiceUrl`, the SAML adapter will implicitly listen for SAML assertions at the location `/my-context-path/saml`. This has to match `Master SAML Processing URL` in the IDP realm/client settings, for example `\http://sp.domain.com/my-context-path/saml`. If not, Tomcat will probably redirect infinitely to the IDP login service, as it does not receive the SAML assertion after the user logged in. diff --git a/securing_apps/topics/saml/mod-auth-mellon.adoc b/securing_apps/topics/saml/mod-auth-mellon.adoc deleted file mode 100644 index 10a79e2fd..000000000 --- a/securing_apps/topics/saml/mod-auth-mellon.adoc +++ /dev/null @@ -1,266 +0,0 @@ -[[_mod_auth_mellon]] - -=== mod_auth_mellon Apache HTTPD Module - -The https://github.com/latchset/mod_auth_mellon[mod_auth_mellon] module is an Apache HTTPD plugin for SAML. If your language/environment supports using Apache HTTPD as a proxy, then you can use mod_auth_mellon to secure your web application with SAML. For more details on this module see the _mod_auth_mellon_ GitHub repo. - -To configure mod_auth_mellon you need: - -* An Identity Provider (IdP) entity descriptor XML file, which describes the connection to {project_name} or another SAML IdP -* An SP entity descriptor XML file, which describes the SAML connections and configuration for the application you are securing. -* A private key PEM file, which is a text file in the PEM format that defines the private key the application uses to sign documents. -* A certificate PEM file, which is a text file that defines the certificate for your application. -* mod_auth_mellon-specific Apache HTTPD module configuration. - -ifeval::[{project_community}==true] -If you have already defined and registered the client application within a realm on the {project_name} application server, {project_name} can generate all the files you need except the Apache HTTPD module configuration. - -Perform the following procedure to generate the Apache HTTPD module configuration. - -.Procedure - -. Go to the Installation page of your SAML client. -. Select the *Mod Auth Mellon* files option. -+ -.mod_auth_mellon config download -image:images/mod-auth-mellon-config-download.png[] - -. Click *Download* to download a ZIP file that contains the XML descriptor and PEM files you need. -endif::[] - -==== Configuring mod_auth_mellon with {project_name} - -There are two hosts involved: - -* The host on which {project_name} is running, which will be referred to as $idp_host because {project_name} is a SAML identity provider (IdP). - -* The host on which the web application is running, which will be referred to as $sp_host. In SAML an application using an IdP is called a service provider (SP). - -All of the following steps need to performed on $sp_host with root privileges. - -===== Installing the packages - -To install the necessary packages, you will need: - -* Apache Web Server (httpd) -* Mellon SAML SP add-on module for Apache -* Tools to create X509 certificates - -To install the necessary packages, run this command: - - yum install httpd mod_auth_mellon mod_ssl openssl - -===== Creating a configuration directory for Apache SAML - -It is advisable to keep configuration files related to Apache's use of SAML in one location. - -Create a new directory named saml2 located under the Apache configuration root /etc/httpd: - - mkdir /etc/httpd/saml2 - -===== Configuring the Mellon Service Provider - -Configuration files for Apache add-on modules are located in the /etc/httpd/conf.d directory and have a file name extension of .conf. You need to create the /etc/httpd/conf.d/mellon.conf file and place Mellon's configuration directives in it. - -Mellon's configuration directives can roughly be broken down into two classes of information: - -* Which URLs to protect with SAML authentication -* What SAML parameters will be used when a protected URL is referenced. - -Apache configuration directives typically follow a hierarchical tree structure in the URL space, which are known as locations. You need to specify one or more URL locations for Mellon to protect. You have flexibility in how you add the configuration parameters that apply to each location. You can either add all the necessary parameters to the location block or you can add Mellon parameters to a common location high up in the URL location hierarchy that specific protected locations inherit (or some combination of the two). Since it is common for an SP to operate in the same way no matter which location triggers SAML actions, the example configuration used here places common Mellon configuration directives in the root of the hierarchy and then specific locations to be protected by Mellon can be defined with minimal directives. This strategy avoids duplicating the same parameters for each protected location. - -This example has just one protected location: \https://$sp_host/private. - -To configure the Mellon service provider, perform the following procedure. - -.Procedure - -. Create the file /etc/httpd/conf.d/mellon.conf with this content: - -[source,xml] ----- - - MellonEnable info - MellonEndpointPath /mellon/ - MellonSPMetadataFile /etc/httpd/saml2/mellon_metadata.xml - MellonSPPrivateKeyFile /etc/httpd/saml2/mellon.key - MellonSPCertFile /etc/httpd/saml2/mellon.crt - MellonIdPMetadataFile /etc/httpd/saml2/idp_metadata.xml - - - AuthType Mellon - MellonEnable auth - Require valid-user - ----- - -NOTE: Some of the files referenced in the code above are created in later steps. - -==== Setting the SameSite value for the cookie used by mod_auth_mellon - -Browsers are planning to set the default value for the `SameSite` attribute for cookies to `Lax`. This setting means -that cookies will be sent to applications only if the request originates in the same domain. This behavior can affect -the SAML POST binding which may become non-functional. To preserve full functionality of the _mod_auth_mellon_ module, -we recommend setting the `SameSite` value to `None` for the cookie created by _mod_auth_mellon_. Not doing so may result -in an inability to login using {project_name}. - -To set the `SameSite` value to `None`, add the following configuration to `` tag within your `mellon.conf` -file. - -[source,xml] ----- -MellonSecureCookie On -MellonCookieSameSite none ----- - -The support for this configuration is available in the _mod_auth_mellon_ module from version 0.16.0. - -===== Creating the Service Provider metadata - -In SAML IdPs and SPs exchange SAML metadata, which is in XML format. The schema for the metadata is a standard, thus assuring participating SAML entities can consume each other's metadata. You need: - -* Metadata for the IdP that the SP utilizes -* Metadata describing the SP provided to the IdP - -One of the components of SAML metadata is X509 certificates. These certificates are used for two purposes: - -* Sign SAML messages so the receiving end can prove the message originated from the expected party. -* Encrypt the message during transport (seldom used because SAML messages typically occur on TLS-protected transports) - -You can use your own certificates if you already have a Certificate Authority (CA) or you can generate a self-signed certificate. For simplicity in this example a self-signed certificate is used. - -Because Mellon's SP metadata must reflect the capabilities of the installed version of mod_auth_mellon, must be valid SP metadata XML, and must contain an X509 certificate (whose creation can be obtuse unless you are familiar with X509 certificate generation) the most expedient way to produce the SP metadata is to use a tool included in the mod_auth_mellon package (mellon_create_metadata.sh). The generated metadata can always be edited later because it is a text file. The tool also creates your X509 key and certificate. - -SAML IdPs and SPs identify themselves using a unique name known as an EntityID. To use the Mellon metadata creation tool you need: - -* The EntityID, which is typically the URL of the SP, and often the URL of the SP where the SP metadata can be retrieved -* The URL where SAML messages for the SP will be consumed, which Mellon calls the MellonEndPointPath. - -To create the SP metadata, perform the following procedure. - -.Procedure - -. Create a few helper shell variables: -+ -[source] ----- -fqdn=`hostname` -mellon_endpoint_url="https://${fqdn}/mellon" -mellon_entity_id="${mellon_endpoint_url}/metadata" -file_prefix="$(echo "$mellon_entity_id" | sed 's/[^A-Za-z.]/_/g' | sed 's/__*/_/g')" ----- - -. Invoke the Mellon metadata creation tool by running this command: -+ -[source] ----- -/usr/libexec/mod_auth_mellon/mellon_create_metadata.sh $mellon_entity_id $mellon_endpoint_url ----- - -. Move the generated files to their destination (referenced in the /etc/httpd/conf.d/mellon.conf file created above): -+ -[source] ----- -mv ${file_prefix}.cert /etc/httpd/saml2/mellon.crt -mv ${file_prefix}.key /etc/httpd/saml2/mellon.key -mv ${file_prefix}.xml /etc/httpd/saml2/mellon_metadata.xml ----- - -===== Adding the Mellon Service Provider to the {project_name} Identity Provider - -Assumption: The {project_name} IdP has already been installed on the $idp_host. - -{project_name} supports multiple tenancy where all users, clients, and so on are grouped in what is called a realm. Each realm is independent of other realms. You can use an existing realm in your {project_name}, but this example shows how to create a new realm called test_realm and use that realm. - -All these operations are performed using the {project_name} Admin Console. You must have the admin username and password for $idp_host to perform the following procedure. - -.Procedure - -. Open the Admin Console and log on by entering the admin username and password. -+ -After logging into the Admin Console, there will be an existing realm. When {project_name} is first set up a root realm, master, is created by default. Any previously created realms are listed in the upper left corner of the Admin Console in a drop-down list. - -. From the realm drop-down list select *Add realm*. - -. In the Name field type `test_realm` and click *Create*. - -====== Adding the Mellon Service Provider as a client of the realm - -In {project_name} SAML SPs are known as clients. To add the SP we must be in the Clients section of the realm. - -. Click the Clients menu item on the left and click *Create* in the upper right corner to create a new client. - -====== Adding the Mellon SP client - -To add the Mellon SP client, perform the following procedure. - -.Procedure -. Set the client protocol to SAML. -. From the Client Protocol drop down list, select *saml*. -. Provide the Mellon SP metadata file created above (/etc/httpd/saml2/mellon_metadata.xml). -+ -Depending on where your browser is running you might have to copy the SP metadata from $sp_host to the machine on which your browser is running so the browser can find the file. -. Click *Save*. - -====== Editing the Mellon SP client - -Use this procedure to set important client configuration parameters. - -.Procedure - -. Ensure "Force POST Binding" is On. -. Add paosResponse to the Valid Redirect URIs list: -. Copy the postResponse URL in "Valid Redirect URIs" and paste it into the empty add text fields just below the "+". -. Change "postResponse" to "paosResponse". (The paosResponse URL is needed for SAML ECP.) -. Click *Save* at the bottom. - -Many SAML SPs determine authorization based on a user's membership in a group. The {project_name} IdP can manage user group information but it does not supply the user's groups unless the IdP is configured to supply it as a SAML attribute. - -Perform the following procedure to configure the IdP to supply the user's groups as a SAML attribute. - -.Procedure - -. Click the Mappers tab of the client. -. In the upper right corner of the Mappers page, click *Create*. -. From the Mapper Type drop-down list select *Group list*. -. Set Name to "group list". -. Set the SAML attribute name to "groups". -. Click *Save*. - -The remaining steps are performed on $sp_host. - -====== Retrieving the Identity Provider metadata - -Now that you have created the realm on the IdP you need to retrieve the IdP metadata associated with it so the Mellon SP recognizes it. In the /etc/httpd/conf.d/mellon.conf file created previously, the MellonIdPMetadataFile is specified as /etc/httpd/saml2/idp_metadata.xml but until now that file has not existed on $sp_host. - -Use this procedure to retrieve that file from the IdP. - -.Procedure - -. Use this command, substituting with the correct value for $idp_host: -+ -[source,subs="attributes+"] ----- -curl -k -o /etc/httpd/saml2/idp_metadata.xml \ -https://$idp_host{kc_realms_path}/test_realm/protocol/saml/descriptor ----- -+ -Mellon is now fully configured. - -. To run a syntax check for Apache configuration files, use this command: -+ -[source] ----- -apachectl configtest ----- -+ -NOTE: Configtest is equivalent to the -t argument to apachectl. If the configuration test shows any errors, correct them before proceeding. - -. Restart the Apache server: -+ -[source] ----- -systemctl restart httpd.service ----- - -You have now set up both {project_name} as a SAML IdP in the test_realm and mod_auth_mellon as SAML SP protecting the URL $sp_host/protected (and everything beneath it) by authenticating against the ``$idp_host`` IdP. diff --git a/securing_apps/topics/saml/saml-overview.adoc b/securing_apps/topics/saml/saml-overview.adoc deleted file mode 100644 index 7dad2641f..000000000 --- a/securing_apps/topics/saml/saml-overview.adoc +++ /dev/null @@ -1,3 +0,0 @@ -== Using SAML to secure applications and services - -This section describes how you can secure applications and services with SAML using either {project_name} client adapters or generic SAML provider libraries. \ No newline at end of file diff --git a/securing_apps/topics/templates b/securing_apps/topics/templates deleted file mode 120000 index d19126411..000000000 --- a/securing_apps/topics/templates +++ /dev/null @@ -1 +0,0 @@ -../../topics/templates \ No newline at end of file diff --git a/securing_apps/topics/token-exchange/token-exchange.adoc b/securing_apps/topics/token-exchange/token-exchange.adoc deleted file mode 100644 index a9e0a8ee6..000000000 --- a/securing_apps/topics/token-exchange/token-exchange.adoc +++ /dev/null @@ -1,528 +0,0 @@ - -[[_token-exchange]] - -== Using token exchange - -:tech_feature_name: Token Exchange -:tech_feature_setting: -Dkeycloak.profile.feature.token_exchange=enabled -include::../templates/techpreview.adoc[] - -[NOTE] -==== -In order to use token exchange you should also enable the `token_exchange` feature. Please, take a look at the https://www.keycloak.org/server/features[Enabling and disabling features] guide. -==== - -=== How token exchange works - -In {project_name}, token exchange is the process of using a set of credentials or token to obtain an entirely different token. -A client may want to invoke on a less trusted application so it may want to downgrade the current token it has. -A client may want to exchange a {project_name} token for a token stored for a linked social provider account. -You may want to trust external tokens minted by other {project_name} realms or foreign IDPs. A client may have a need -to impersonate a user. Here's a short summary of the current capabilities of {project_name} around token exchange. - -* A client can exchange an existing {project_name} token created for a specific client for a new token targeted to a different client -* A client can exchange an existing {project_name} token for an external token, i.e. a linked Facebook account -* A client can exchange an external token for a {project_name} token. -* A client can impersonate a user - -Token exchange in {project_name} is a very loose implementation of the link:https://datatracker.ietf.org/doc/html/rfc8693[OAuth Token Exchange] specification at the IETF. -We have extended it a little, ignored some of it, and loosely interpreted other parts of the specification. It is -a simple grant type invocation on a realm's OpenID Connect token endpoint. - -[source,subs="attributes+"] ----- -{kc_realms_path}/{realm}/protocol/openid-connect/token ----- - -It accepts form parameters (`application/x-www-form-urlencoded`) as input and the output depends on the type of token you requested an exchange for. -Token exchange is a client endpoint so requests must provide authentication information for the calling client. -Public clients specify their client identifier as a form parameter. Confidential clients can also use form parameters -to pass their client id and secret, Basic Auth, or however your admin has configured the client authentication flow in your -realm. - -==== Form parameters - -client_id:: - _REQUIRED MAYBE._ This parameter is required for clients using form parameters for authentication. If you are using - Basic Auth, a client JWT token, or client cert authentication, then do not specify this parameter. -client_secret:: - _REQUIRED MAYBE_. This parameter is required for clients using form parameters for authentication and using a client secret as a credential. - Do not specify this parameter if client invocations in your realm are authenticated by a different means. - -grant_type:: - _REQUIRED._ The value of the parameter must be `urn:ietf:params:oauth:grant-type:token-exchange`. -subject_token:: - _OPTIONAL._ A security token that represents the identity of the party on behalf of whom the request is being made. It is required if you are exchanging an existing token for a new one. -subject_issuer:: - _OPTIONAL._ Identifies the issuer of the `subject_token`. It can be left blank if the token comes from the current realm or if the issuer - can be determined from the `subject_token_type`. Otherwise it is required to be specified. Valid values are the alias of an `Identity Provider` configured for your realm. Or an issuer claim identifier - configured by a specific `Identity Provider`. -subject_token_type:: - _OPTIONAL._ This parameter is the type of the token passed with the `subject_token` parameter. This defaults - to `urn:ietf:params:oauth:token-type:access_token` if the `subject_token` comes from the realm and is an access token. - If it is an external token, this parameter may or may not have to be specified depending on the requirements of the - `subject_issuer`. -requested_token_type:: - _OPTIONAL._ This parameter represents the type of token the client wants to exchange for. Currently only oauth - and OpenID Connect token types are supported. The default value for this depends on whether it - is `urn:ietf:params:oauth:token-type:refresh_token` in which case you will be returned both an access token and refresh - token within the response. Other appropriate values are `urn:ietf:params:oauth:token-type:access_token` and `urn:ietf:params:oauth:token-type:id_token` -audience:: - _OPTIONAL._ This parameter specifies the target client you want the new token minted for. -requested_issuer:: - _OPTIONAL._ This parameter specifies that the client wants a token minted by an external provider. It must - be the alias of an `Identity Provider` configured within the realm. -requested_subject:: - _OPTIONAL._ This specifies a username or user id if your client wants to impersonate a different user. -scope:: - _NOT IMPLEMENTED._ This parameter represents the target set of OAuth and OpenID Connect scopes the client - is requesting. It is not implemented at this time but will be once {project_name} has better support for - scopes in general. - -NOTE: We currently only support OpenID Connect and OAuth exchanges. Support for SAML based clients and identity providers may be added in the future depending on user demand. - -==== Responses from a token exchange request - -A successful response from an exchange invocation will return the HTTP 200 response code with a content type that -depends on the `requested-token-type` and `requested_issuer` the client asks for. OAuth requested token types will return -a JSON document as described in the link:https://datatracker.ietf.org/doc/html/draft-ietf-oauth-token-exchange-16[OAuth Token Exchange] specification. - -[source,json] ----- -{ - "access_token" : ".....", - "refresh_token" : ".....", - "expires_in" : "...." - } ----- - -Clients requesting a refresh token will get back both an access and refresh token in the response. Clients requesting only -access token type will only get an access token in the response. Expiration information may or may not be included for -clients requesting an external issuer through the `requested_issuer` parameter. - -Error responses generally fall under the 400 HTTP response code category, but other error status codes may be returned -depending on the severity of the error. Error responses may include content depending on the `requested_issuer`. -OAuth based exchanges may return a JSON document as follows: - -[source,json] ----- -{ - "error" : "...." - "error_description" : "...." -} ----- - -Additional error claims may be returned depending on the exchange type. For example, OAuth Identity Providers may include -an additional `account-link-url` claim if the user does not have a link to an identity provider. This link can be used -for a client initiated link request. - -NOTE: Token exchange setup requires knowledge of fine grain admin permissions (See the link:{adminguide_link}[{adminguide_name}] for more information). You will need to grant clients - permission to exchange. This is discussed more later in this chapter. - -The rest of this chapter discusses the setup requirements and provides examples for different exchange scenarios. -For simplicity's sake, let's call a token minted by the current realm as an _internal_ token and a token minted by -an external realm or identity provider as an _external_ token. - -=== Internal token to internal token exchange - -With an internal token to token exchange you have an existing token minted to a specific client and you want to exchange -this token for a new one minted for a different target client. Why would you want to do this? This generally happens -when a client has a token minted for itself, and needs to make additional requests to other applications that require different -claims and permissions within the access token. Other reasons this type of exchange might be required is if you -need to perform a "permission downgrade" where your app needs to invoke on a less trusted app and you don't want -to propagate your current access token. - -[[_client_to_client_permission]] -==== Granting permission for the exchange - -Clients that want to exchange tokens for a different client need to be authorized in the Admin Console. -You need to define a `token-exchange` fine grain permission in the target client you want permission to exchange to. - -.Target Client Permission -image:images/exchange-target-client-permission-unset.png[Target Client Permission] - -.Procedure - -. Toggle *Permissions Enabled* to *On*. -+ -.Target Client Permission -image:images/exchange-target-client-permission-set.png[Target Client Exchange Permission Set] -+ -That page displays a *token-exchange* link. - -. Click that link to start defining the permission. -+ -This setup page displays. -+ -.Target Client Exchange Permission Setup -image:images/exchange-target-client-permission-setup.png[Target Client Exchange Permission Setup] - -. Click *Client details* in the breadcrumbs at the top of the screen. -. Define a policy for this permission. -. Click *Authorization* in the breadcrumbs at the top of the screen. -. Define a policy for this permission. -. Click the *Policies* tab. -. Create a *Client* Policy by clicking *Create policy* button. -+ -.Client Policy Creation -image:images/exchange-target-client-policy.png[Client Policy Creation] - -. Enter in the starting client that is the authenticated client that is requesting a token exchange. - -. After you create this policy, go back to the target client's *token-exchange* permission and add the client policy you just defined. -+ -.Apply Client Policy -image:images/exchange-target-client-exchange-apply-policy.png[Apply Client Policy] - -Your client now has permission to invoke. If you do not do this correctly, you will get a 403 Forbidden response if you -try to make an exchange. - -[[_internal_internal_making_request]] -==== Making the request - -When your client is exchanging an existing token for a token targeting another client, you use the `audience` parameter. -This parameter must be the client identifier for the target client that you configured in the Admin Console. - -[source,bash,subs="attributes+"] ----- -curl -X POST \ - -d "client_id=starting-client" \ - -d "client_secret=the client secret" \ - --data-urlencode "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \ - -d "subject_token=...." \ - --data-urlencode "requested_token_type=urn:ietf:params:oauth:token-type:refresh_token" \ - -d "audience=target-client" \ - http://localhost:8080{kc_realms_path}/myrealm/protocol/openid-connect/token ----- - -The `subject_token` parameter must be an access token for the target realm. If your `requested_token_type` parameter -is a refresh token type, then the response will contain both an access token, refresh token, and expiration. Here's -an example JSON response you get back from this call. - -When the `audience` parameter is not set, the value of the parameter defaults to the client making the token exchange request. - -Unlike with confidential clients, public clients are not allowed to perform token exchanges using tokens from other clients. -If you are passing a `subject_token`, the (confidential) client that was issued the token should either match the client making the request or, if issued to a different client, -the client making the request should be among the audiences set to the token. - -If you are explicitly setting a target `audience` (with a client different from the client making the request), you should also make sure that the `token-exchange` scope permission is configured for the client set to the `audience` parameter to allow -the client making the request to successfully complete the exchange. - -[source,json] ----- -{ - "access_token" : "....", - "refresh_token" : "....", - "expires_in" : 3600 -} ----- - -=== Internal token to external token exchange - -You can exchange a realm token for an external token minted by an external identity provider. This external identity provider -must be configured within the `Identity Provider` section of the Admin Console. Currently only OAuth/OpenID Connect based external -identity providers are supported, this includes all social providers. {project_name} does not perform a backchannel exchange to the external provider. So if the account -is not linked, you will not be able to get the external token. To be able to obtain an external token one of -these conditions must be met: - -* The user must have logged in with the external identity provider at least once -* The user must have linked with the external identity provider through the User Account Service -* The user account was linked through the external identity provider using link:{developerguide_link}[Client Initiated Account Linking] API. - -Finally, the external identity provider must have been configured to store tokens, or, one of the above actions must -have been performed with the same user session as the internal token you are exchanging. - -If the account is not linked, the exchange response will contain a link you can use to establish it. This is -discussed more in the <<_internal_external_making_request, Making the Request>> section. - -[[_grant_permission_external_exchange]] -==== Granting permission for the exchange - -Internal to external token exchange requests will be denied with a 403, Forbidden response until you grant permission for the calling client to exchange tokens with the external identity provider. To grant permission to the client, you go to the identity provider's configuration page to the *Permissions* tab. - -.Identity Provider Permission -image:images/exchange-idp-permission-unset.png[Identity Provider Exchange Permission] - -.Procedure - -. Toggle *Permissions Enabled* to *On*. -+ -.Identity Provider Permission -image:images/exchange-idp-permission-set.png[Identity Provider Exchange Permission Set] -+ -The page displays *token-exchange* link. - -. Click the link to start defining the permission. -+ -This setup page appears. -+ -.Identity Provider Exchange Permission Setup -image:images/exchange-idp-permission-setup.png[Identity Provider Exchange Permission Setup] - -. Click *Client details* in the breadcrumbs at the top of the screen. - -. Click *Policies* tab to create a client policy. -+ -.Client Policy Creation -image:images/exchange-idp-client-policy.png[Client Policy Creation] - -. Enter the starting client that is the authenticated client that is requesting a token exchange. - -. Return to the identity provider's *token-exchange* permission and add the client policy you just defined. -+ -.Apply Client Policy -image:images/exchange-idp-apply-policy.png[Apply Client Policy] - -Your client now has permission to invoke. If you do not do this correctly, you will get a 403 Forbidden response if you try to make an exchange. - -[[_internal_external_making_request]] -==== Making the request - -When your client is exchanging an existing internal token to an external one, you provide the `requested_issuer` parameter. The parameter must be the alias of a configured identity provider. - -[source,bash,subs="attributes+"] ----- -curl -X POST \ - -d "client_id=starting-client" \ - -d "client_secret=the client secret" \ - --data-urlencode "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \ - -d "subject_token=...." \ - --data-urlencode "requested_token_type=urn:ietf:params:oauth:token-type:access_token" \ - -d "requested_issuer=google" \ - http://localhost:8080{kc_realms_path}/myrealm/protocol/openid-connect/token ----- - -The `subject_token` parameter must be an access token for the target realm. The `requested_token_type` parameter -must be `urn:ietf:params:oauth:token-type:access_token` or left blank. No other requested token type is supported -at this time. Here's -an example successful JSON response you get back from this call. - -[source,json] ----- -{ - "access_token" : "....", - "expires_in" : 3600 - "account-link-url" : "https://...." -} ----- - -If the external identity provider is not linked for whatever reason, you will get an HTTP 400 response code with -this JSON document: - -[source,json] ----- -{ - "error" : "....", - "error_description" : "..." - "account-link-url" : "https://...." -} ----- - -The `error` claim will be either `token_expired` or `not_linked`. The `account-link-url` claim is provided -so that the client can perform link:{developerguide_link}[Client Initiated Account Linking]. Most, if not all, -providers require linking through browser OAuth protocol. With the `account-link-url` just add a `redirect_uri` -query parameter to it and you can forward browsers to perform the link. - -=== External token to internal token exchange - -You can trust and exchange external tokens minted by external identity providers for internal tokens. This can be -used to bridge between realms or just to trust tokens from your social provider. It works similarly to an identity provider -browser login in that a new user is imported into your realm if it doesn't exist. - -NOTE: The current limitation on external token exchanges is that if the external token maps to an existing user an - exchange will not be allowed unless the existing user already has an account link to the external identity - provider. - -When the exchange is complete, a user session will be created within the realm, and you will receive an access -and or refresh token depending on the `requested_token_type` parameter value. You should note that this new -user session will remain active until it times out or until you call the logout endpoint of the realm passing this -new access token. - -These types of changes required a configured identity provider in the Admin Console. - -NOTE: SAML identity providers are not supported at this time. Twitter tokens cannot be exchanged either. - -==== Granting permission for the exchange - -Before external token exchanges can be done, you grant permission for the calling client to make the exchange. This -permission is granted in the same manner as <<_grant_permission_external_exchange, internal to external permission is granted>>. - -If you also provide an `audience` parameter whose value points to a different client other than the calling one, you -must also grant the calling client permission to exchange to the target client specific in the `audience` parameter. How -to do this is <<_client_to_client_permission, discussed earlier>> in this section. - -==== Making the request - -The `subject_token_type` must either be `urn:ietf:params:oauth:token-type:access_token` or `urn:ietf:params:oauth:token-type:jwt`. -If the type is `urn:ietf:params:oauth:token-type:access_token` you specify the `subject_issuer` parameter and it must be the -alias of the configured identity provider. If the type is `urn:ietf:params:oauth:token-type:jwt`, the provider will be matched via -the `issuer` claim within the JWT which must be the alias of the provider, or a registered issuer within the providers configuration. - -For validation, if the token is an access token, the provider's user info service will be invoked to validate the token. A successful call -will mean that the access token is valid. If the subject token is a JWT and if the provider has signature validation enabled, that will be attempted, -otherwise, it will default to also invoking on the user info service to validate the token. - -By default, the internal token minted will use the calling client to determine what's in the token using the protocol -mappers defined for the calling client. Alternatively, you can specify a different target client using the `audience` -parameter. - -[source,bash,subs="attributes+"] ----- -curl -X POST \ - -d "client_id=starting-client" \ - -d "client_secret=the client secret" \ - --data-urlencode "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \ - -d "subject_token=...." \ - -d "subject_issuer=myOidcProvider" \ - --data-urlencode "subject_token_type=urn:ietf:params:oauth:token-type:access_token" \ - -d "audience=target-client" \ - http://localhost:8080{kc_realms_path}/myrealm/protocol/openid-connect/token ----- - - -If your `requested_token_type` parameter -is a refresh token type, then the response will contain both an access token, refresh token, and expiration. Here's -an example JSON response you get back from this call. - -[source,json] ----- -{ - "access_token" : "....", - "refresh_token" : "....", - "expires_in" : 3600 -} ----- - - -=== Impersonation - -For internal and external token exchanges, the client can request on behalf of a user to impersonate a different user. -For example, you may have an admin application that needs to impersonate a user so that a support engineer can debug -a problem. - - -==== Granting permission for the exchange - -The user that the subject token represents must have permission to impersonate other users. See the -link:{adminguide_link}[{adminguide_name}] on how to enable this permission. It can be done through a role or through -fine grain admin permissions. - - -==== Making the request - -Make the request as described in other chapters except additionally specify the `requested_subject` parameter. The -value of this parameter must be a username or user id. - -[source,bash,subs="attributes+"] ----- -curl -X POST \ - -d "client_id=starting-client" \ - -d "client_secret=the client secret" \ - --data-urlencode "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \ - -d "subject_token=...." \ - --data-urlencode "requested_token_type=urn:ietf:params:oauth:token-type:access_token" \ - -d "audience=target-client" \ - -d "requested_subject=wburke" \ - http://localhost:8080{kc_realms_path}/myrealm/protocol/openid-connect/token ----- - -=== Direct Naked Impersonation - -You can make an internal token exchange request without providing a `subject_token`. This is called a direct -naked impersonation because it places a lot of trust in a client as that client can impersonate any user in the realm. -You might need this to bridge for applications where it is impossible to obtain a subject token to exchange. For example, -you may be integrating a legacy application that performs login directly with LDAP. In that case, the legacy app -is able to authenticate users itself, but not able to obtain a token. - -WARNING: It is very risky to enable direct naked impersonation for a client. If the client's credentials are ever - stolen, that client can impersonate any user in the system. - -==== Granting permission for the exchange - -If the `audience` parameter is provided, then the calling client must have permission to exchange to the client. How -to set this up is discussed earlier in this chapter. - -Additionally, the calling client must be granted permission to impersonate users. - -.Procedure - -. Click *Users* in the menu. - -. Click the *Permissions* tab. -+ -.User Permissions -image:images/exchange-users-permission-unset.png[User Permissions] - -. Toggle *Permissions Enabled* to *On*. -+ -.Identity Provider Permission -image:images/exchange-users-permission-set.png[Users Impersonation Permission Set] -+ -The page displays an *impersonate* link. -. Click that link to start defining the permission. -+ -This setup page displays. -+ -.Users Impersonation Permission Setup -image:images/exchange-users-permission-setup.png[Users Impersonation Permission Setup] - -. Click *Client details* in the breadcrumbs at the top of the screen. -. Define a policy for this permission. -. Go to the *Policies* tab and create a client policy. -+ -.Client Policy Creation -image:images/exchange-users-client-policy.png[Client Policy Creation] - -. Enter the starting client that is the authenticated client that is requesting a token exchange. - -. Return to the users' *impersonation* permission and add the client policy you just -defined. -+ -.Apply Client Policy -image:images/exchange-users-apply-policy.png[Apply Client Policy] - -Your client now has permission to impersonate users. If you do not do this correctly, you will get a 403 Forbidden response if you -try to make this type of exchange. - -NOTE: Public clients are not allowed to do direct naked impersonations. - - -==== Making the request - -To make the request, simply specify the `requested_subject` parameter. This must be the username or user id of -a valid user. You can also specify an `audience` parameter if you wish. - -[source,bash,subs="attributes+"] ----- -curl -X POST \ - -d "client_id=starting-client" \ - -d "client_secret=the client secret" \ - --data-urlencode "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \ - -d "requested_subject=wburke" \ - http://localhost:8080{kc_realms_path}/myrealm/protocol/openid-connect/token ----- - -=== Expand permission model with service accounts - -When granting clients permission to exchange, you don't necessarily manually enable those permissions for each and every client. -If the client has a service account associated with it, you can use a role to group permissions together and assign exchange permissions -by assigning a role to the client's service account. For example, you might define a `naked-exchange` role and any service account that has that -role can do a naked exchange. - -=== Exchange vulnerabilities - -When you start allowing token exchanges, there are various things you have to both be aware of and careful of. - -The first is public clients. Public clients do not have or require a client credential in order to perform an exchange. Anybody that has a valid -token will be able to __impersonate__ the public client and perform the exchanges that public client is allowed to perform. If there -are any untrustworthy clients that are managed by your realm, public clients may open up vulnerabilities in your permission models. -This is why direct naked exchanges do not allow public clients and will abort with an error if the calling client is public. - -It is possible to exchange social tokens provided by Facebook, Google, etc. for a realm token. Be careful and vigilante on what -the exchange token is allowed to do as it's not hard to create fake accounts on these social websites. Use default roles, groups, and identity provider mappers to control what attributes and roles -are assigned to the external social user. - -Direct naked exchanges are quite dangerous. You are putting a lot of trust in the calling client that it will never leak out -its client credentials. If those credentials are leaked, then the thief can impersonate anybody in your system. This is in direct -contrast to confidential clients that have existing tokens. You have two factors of authentication, the access token and the client -credentials, and you're only dealing with one user. So use direct naked exchanges sparingly. diff --git a/server_admin/docinfo-footer.html b/server_admin/docinfo-footer.html deleted file mode 120000 index a39d3bd0f..000000000 --- a/server_admin/docinfo-footer.html +++ /dev/null @@ -1 +0,0 @@ -../aggregation/navbar.html \ No newline at end of file diff --git a/server_admin/docinfo.html b/server_admin/docinfo.html deleted file mode 120000 index 14514f94d..000000000 --- a/server_admin/docinfo.html +++ /dev/null @@ -1 +0,0 @@ -../aggregation/navbar-head.html \ No newline at end of file diff --git a/server_admin/getting_started/images/master_realm.png b/server_admin/getting_started/images/master_realm.png deleted file mode 100644 index e02c0f4cc..000000000 Binary files a/server_admin/getting_started/images/master_realm.png and /dev/null differ diff --git a/server_admin/images/Create-authentication-execution.png b/server_admin/images/Create-authentication-execution.png deleted file mode 100644 index edeb5bf18..000000000 Binary files a/server_admin/images/Create-authentication-execution.png and /dev/null differ diff --git a/server_admin/images/Create-top-level-flow.png b/server_admin/images/Create-top-level-flow.png deleted file mode 100644 index c3bc2f0be..000000000 Binary files a/server_admin/images/Create-top-level-flow.png and /dev/null differ diff --git a/server_admin/images/New-flow.png b/server_admin/images/New-flow.png deleted file mode 100644 index 2b1ab2883..000000000 Binary files a/server_admin/images/New-flow.png and /dev/null differ diff --git a/server_admin/images/Passwordless-browser-login-common.png b/server_admin/images/Passwordless-browser-login-common.png deleted file mode 100644 index e43e9b170..000000000 Binary files a/server_admin/images/Passwordless-browser-login-common.png and /dev/null differ diff --git a/server_admin/images/Passwordless-browser-login.png b/server_admin/images/Passwordless-browser-login.png deleted file mode 100644 index 04a072a7a..000000000 Binary files a/server_admin/images/Passwordless-browser-login.png and /dev/null differ diff --git a/server_admin/images/account-console-applications.png b/server_admin/images/account-console-applications.png deleted file mode 100644 index 8fd53a99a..000000000 Binary files a/server_admin/images/account-console-applications.png and /dev/null differ diff --git a/server_admin/images/account-console-device.png b/server_admin/images/account-console-device.png deleted file mode 100644 index d4e948e5d..000000000 Binary files a/server_admin/images/account-console-device.png and /dev/null differ diff --git a/server_admin/images/account-console-intro.png b/server_admin/images/account-console-intro.png deleted file mode 100644 index 9cdd16852..000000000 Binary files a/server_admin/images/account-console-intro.png and /dev/null differ diff --git a/server_admin/images/account-console-linked.png b/server_admin/images/account-console-linked.png deleted file mode 100644 index 9046b7aa8..000000000 Binary files a/server_admin/images/account-console-linked.png and /dev/null differ diff --git a/server_admin/images/account-console-signing-in-webauthn-2factor.png b/server_admin/images/account-console-signing-in-webauthn-2factor.png deleted file mode 100644 index ebafccc51..000000000 Binary files a/server_admin/images/account-console-signing-in-webauthn-2factor.png and /dev/null differ diff --git a/server_admin/images/account-console-signing-in-webauthn-passwordless.png b/server_admin/images/account-console-signing-in-webauthn-passwordless.png deleted file mode 100644 index 6cda9af80..000000000 Binary files a/server_admin/images/account-console-signing-in-webauthn-passwordless.png and /dev/null differ diff --git a/server_admin/images/account-console-signing-in.png b/server_admin/images/account-console-signing-in.png deleted file mode 100644 index 13ac49170..000000000 Binary files a/server_admin/images/account-console-signing-in.png and /dev/null differ diff --git a/server_admin/images/account-service-apps.png b/server_admin/images/account-service-apps.png deleted file mode 100644 index 08c34b93a..000000000 Binary files a/server_admin/images/account-service-apps.png and /dev/null differ diff --git a/server_admin/images/account-service-authenticator.png b/server_admin/images/account-service-authenticator.png deleted file mode 100644 index b55d169a7..000000000 Binary files a/server_admin/images/account-service-authenticator.png and /dev/null differ diff --git a/server_admin/images/account-service-federated-identity.png b/server_admin/images/account-service-federated-identity.png deleted file mode 100644 index a43c6510e..000000000 Binary files a/server_admin/images/account-service-federated-identity.png and /dev/null differ diff --git a/server_admin/images/account-service-password.png b/server_admin/images/account-service-password.png deleted file mode 100644 index 5ebc93006..000000000 Binary files a/server_admin/images/account-service-password.png and /dev/null differ diff --git a/server_admin/images/account-service-profile.png b/server_admin/images/account-service-profile.png deleted file mode 100644 index 6da83e118..000000000 Binary files a/server_admin/images/account-service-profile.png and /dev/null differ diff --git a/server_admin/images/account-service-sessions.png b/server_admin/images/account-service-sessions.png deleted file mode 100644 index 59cda5b61..000000000 Binary files a/server_admin/images/account-service-sessions.png and /dev/null differ diff --git a/server_admin/images/add-client-oidc.png b/server_admin/images/add-client-oidc.png deleted file mode 100644 index 8495d76e0..000000000 Binary files a/server_admin/images/add-client-oidc.png and /dev/null differ diff --git a/server_admin/images/add-client-saml.png b/server_admin/images/add-client-saml.png deleted file mode 100644 index 62d903cab..000000000 Binary files a/server_admin/images/add-client-saml.png and /dev/null differ diff --git a/server_admin/images/add-event-types.png b/server_admin/images/add-event-types.png deleted file mode 100644 index 154b4cd5c..000000000 Binary files a/server_admin/images/add-event-types.png and /dev/null differ diff --git a/server_admin/images/add-identity-provider.png b/server_admin/images/add-identity-provider.png deleted file mode 100644 index 1c9a72b10..000000000 Binary files a/server_admin/images/add-identity-provider.png and /dev/null differ diff --git a/server_admin/images/add-mapper.png b/server_admin/images/add-mapper.png deleted file mode 100644 index f199cde62..000000000 Binary files a/server_admin/images/add-mapper.png and /dev/null differ diff --git a/server_admin/images/add-provider-dialog.png b/server_admin/images/add-provider-dialog.png deleted file mode 100755 index 976e5e148..000000000 Binary files a/server_admin/images/add-provider-dialog.png and /dev/null differ diff --git a/server_admin/images/add-provider-select.png b/server_admin/images/add-provider-select.png deleted file mode 100755 index 1c2e51af8..000000000 Binary files a/server_admin/images/add-provider-select.png and /dev/null differ diff --git a/server_admin/images/add-realm-menu.png b/server_admin/images/add-realm-menu.png deleted file mode 100644 index 4462459bb..000000000 Binary files a/server_admin/images/add-realm-menu.png and /dev/null differ diff --git a/server_admin/images/add-user-script.png b/server_admin/images/add-user-script.png deleted file mode 100644 index 69c6c3456..000000000 Binary files a/server_admin/images/add-user-script.png and /dev/null differ diff --git a/server_admin/images/add-user.png b/server_admin/images/add-user.png deleted file mode 100755 index 8149f3b75..000000000 Binary files a/server_admin/images/add-user.png and /dev/null differ diff --git a/server_admin/images/admin-console.png b/server_admin/images/admin-console.png deleted file mode 100644 index 69e7a1d47..000000000 Binary files a/server_admin/images/admin-console.png and /dev/null differ diff --git a/server_admin/images/admin-events-filter.png b/server_admin/images/admin-events-filter.png deleted file mode 100644 index 00c16b0bd..000000000 Binary files a/server_admin/images/admin-events-filter.png and /dev/null differ diff --git a/server_admin/images/admin-events-representation.png b/server_admin/images/admin-events-representation.png deleted file mode 100644 index d5c0e50b7..000000000 Binary files a/server_admin/images/admin-events-representation.png and /dev/null differ diff --git a/server_admin/images/admin-events-settings.png b/server_admin/images/admin-events-settings.png deleted file mode 100644 index 2e36280b7..000000000 Binary files a/server_admin/images/admin-events-settings.png and /dev/null differ diff --git a/server_admin/images/admin-events.png b/server_admin/images/admin-events.png deleted file mode 100644 index bd36fade3..000000000 Binary files a/server_admin/images/admin-events.png and /dev/null differ diff --git a/server_admin/images/audience_mapper.png b/server_admin/images/audience_mapper.png deleted file mode 100644 index ee4b8cf67..000000000 Binary files a/server_admin/images/audience_mapper.png and /dev/null differ diff --git a/server_admin/images/authentication-step-up-condition-1.png b/server_admin/images/authentication-step-up-condition-1.png deleted file mode 100644 index 5fc0b341e..000000000 Binary files a/server_admin/images/authentication-step-up-condition-1.png and /dev/null differ diff --git a/server_admin/images/authentication-step-up-condition-2.png b/server_admin/images/authentication-step-up-condition-2.png deleted file mode 100644 index fc9075245..000000000 Binary files a/server_admin/images/authentication-step-up-condition-2.png and /dev/null differ diff --git a/server_admin/images/authentication-step-up-flow.png b/server_admin/images/authentication-step-up-flow.png deleted file mode 100644 index a27c96884..000000000 Binary files a/server_admin/images/authentication-step-up-flow.png and /dev/null differ diff --git a/server_admin/images/authentication-user-session-limits.png b/server_admin/images/authentication-user-session-limits.png deleted file mode 100644 index 6dfbf9508..000000000 Binary files a/server_admin/images/authentication-user-session-limits.png and /dev/null differ diff --git a/server_admin/images/bitbucket-add-identity-provider.png b/server_admin/images/bitbucket-add-identity-provider.png deleted file mode 100644 index 2f5c668bd..000000000 Binary files a/server_admin/images/bitbucket-add-identity-provider.png and /dev/null differ diff --git a/server_admin/images/bitbucket-app-page.png b/server_admin/images/bitbucket-app-page.png deleted file mode 100644 index dc4451971..000000000 Binary files a/server_admin/images/bitbucket-app-page.png and /dev/null differ diff --git a/server_admin/images/bitbucket-developer-applications.png b/server_admin/images/bitbucket-developer-applications.png deleted file mode 100644 index f586e6517..000000000 Binary files a/server_admin/images/bitbucket-developer-applications.png and /dev/null differ diff --git a/server_admin/images/bitbucket-register-app.png b/server_admin/images/bitbucket-register-app.png deleted file mode 100644 index 6b7a95eaf..000000000 Binary files a/server_admin/images/bitbucket-register-app.png and /dev/null differ diff --git a/server_admin/images/browser-flow.png b/server_admin/images/browser-flow.png deleted file mode 100644 index 8ca5bf786..000000000 Binary files a/server_admin/images/browser-flow.png and /dev/null differ diff --git a/server_admin/images/brute-force.png b/server_admin/images/brute-force.png deleted file mode 100644 index 56c0c8df4..000000000 Binary files a/server_admin/images/brute-force.png and /dev/null differ diff --git a/server_admin/images/cache-tab.png b/server_admin/images/cache-tab.png deleted file mode 100644 index 36d0dc583..000000000 Binary files a/server_admin/images/cache-tab.png and /dev/null differ diff --git a/server_admin/images/capability-config.png b/server_admin/images/capability-config.png deleted file mode 100644 index b9a2002d7..000000000 Binary files a/server_admin/images/capability-config.png and /dev/null differ diff --git a/server_admin/images/client-credentials-jwt.png b/server_admin/images/client-credentials-jwt.png deleted file mode 100644 index da328b5fe..000000000 Binary files a/server_admin/images/client-credentials-jwt.png and /dev/null differ diff --git a/server_admin/images/client-credentials.png b/server_admin/images/client-credentials.png deleted file mode 100644 index 07fbf8572..000000000 Binary files a/server_admin/images/client-credentials.png and /dev/null differ diff --git a/server_admin/images/client-installation.png b/server_admin/images/client-installation.png deleted file mode 100644 index f7ce5fc2b..000000000 Binary files a/server_admin/images/client-installation.png and /dev/null differ diff --git a/server_admin/images/client-oidc-keys.png b/server_admin/images/client-oidc-keys.png deleted file mode 100644 index 4f0cd91b7..000000000 Binary files a/server_admin/images/client-oidc-keys.png and /dev/null differ diff --git a/server_admin/images/client-oidc-map-acr-to-loa.png b/server_admin/images/client-oidc-map-acr-to-loa.png deleted file mode 100644 index fbce25023..000000000 Binary files a/server_admin/images/client-oidc-map-acr-to-loa.png and /dev/null differ diff --git a/server_admin/images/client-scope.png b/server_admin/images/client-scope.png deleted file mode 100644 index 74983834b..000000000 Binary files a/server_admin/images/client-scope.png and /dev/null differ diff --git a/server_admin/images/client-scopes-default.png b/server_admin/images/client-scopes-default.png deleted file mode 100644 index 6dfef447a..000000000 Binary files a/server_admin/images/client-scopes-default.png and /dev/null differ diff --git a/server_admin/images/client-scopes-evaluate.png b/server_admin/images/client-scopes-evaluate.png deleted file mode 100644 index 24495a3de..000000000 Binary files a/server_admin/images/client-scopes-evaluate.png and /dev/null differ diff --git a/server_admin/images/client-scopes-list.png b/server_admin/images/client-scopes-list.png deleted file mode 100644 index 58cd44011..000000000 Binary files a/server_admin/images/client-scopes-list.png and /dev/null differ diff --git a/server_admin/images/client-scopes-phone.png b/server_admin/images/client-scopes-phone.png deleted file mode 100644 index 4a315c36e..000000000 Binary files a/server_admin/images/client-scopes-phone.png and /dev/null differ diff --git a/server_admin/images/client-sessions.png b/server_admin/images/client-sessions.png deleted file mode 100644 index 5fbfc298f..000000000 Binary files a/server_admin/images/client-sessions.png and /dev/null differ diff --git a/server_admin/images/client-settings-oidc.png b/server_admin/images/client-settings-oidc.png deleted file mode 100644 index 3319850eb..000000000 Binary files a/server_admin/images/client-settings-oidc.png and /dev/null differ diff --git a/server_admin/images/client-settings-saml.png b/server_admin/images/client-settings-saml.png deleted file mode 100644 index 7309e740c..000000000 Binary files a/server_admin/images/client-settings-saml.png and /dev/null differ diff --git a/server_admin/images/clients.png b/server_admin/images/clients.png deleted file mode 100644 index 29636e1fb..000000000 Binary files a/server_admin/images/clients.png and /dev/null differ diff --git a/server_admin/images/composite-role.png b/server_admin/images/composite-role.png deleted file mode 100644 index 398dc9430..000000000 Binary files a/server_admin/images/composite-role.png and /dev/null differ diff --git a/server_admin/images/create-oidc-client-profile.png b/server_admin/images/create-oidc-client-profile.png deleted file mode 100644 index f84d3e4ca..000000000 Binary files a/server_admin/images/create-oidc-client-profile.png and /dev/null differ diff --git a/server_admin/images/create-oidc-client-secret-rotation-condition.png b/server_admin/images/create-oidc-client-secret-rotation-condition.png deleted file mode 100644 index d894fef87..000000000 Binary files a/server_admin/images/create-oidc-client-secret-rotation-condition.png and /dev/null differ diff --git a/server_admin/images/create-oidc-client-secret-rotation-executor.png b/server_admin/images/create-oidc-client-secret-rotation-executor.png deleted file mode 100644 index d99d1292a..000000000 Binary files a/server_admin/images/create-oidc-client-secret-rotation-executor.png and /dev/null differ diff --git a/server_admin/images/create-oidc-client-secret-rotation-policy.png b/server_admin/images/create-oidc-client-secret-rotation-policy.png deleted file mode 100644 index 8673a8187..000000000 Binary files a/server_admin/images/create-oidc-client-secret-rotation-policy.png and /dev/null differ diff --git a/server_admin/images/create-realm.png b/server_admin/images/create-realm.png deleted file mode 100644 index 9b6a6f993..000000000 Binary files a/server_admin/images/create-realm.png and /dev/null differ diff --git a/server_admin/images/credentials.png b/server_admin/images/credentials.png deleted file mode 100755 index 49e01debe..000000000 Binary files a/server_admin/images/credentials.png and /dev/null differ diff --git a/server_admin/images/default-groups.png b/server_admin/images/default-groups.png deleted file mode 100644 index 7f7baca69..000000000 Binary files a/server_admin/images/default-groups.png and /dev/null differ diff --git a/server_admin/images/default-required-actions.png b/server_admin/images/default-required-actions.png deleted file mode 100644 index aac2cbfa9..000000000 Binary files a/server_admin/images/default-required-actions.png and /dev/null differ diff --git a/server_admin/images/default-roles.png b/server_admin/images/default-roles.png deleted file mode 100644 index 7aea18c8d..000000000 Binary files a/server_admin/images/default-roles.png and /dev/null differ diff --git a/server_admin/images/delete-account-client-role.png b/server_admin/images/delete-account-client-role.png deleted file mode 100644 index 739f901f4..000000000 Binary files a/server_admin/images/delete-account-client-role.png and /dev/null differ diff --git a/server_admin/images/delete-account-confirm.png b/server_admin/images/delete-account-confirm.png deleted file mode 100644 index f9050747a..000000000 Binary files a/server_admin/images/delete-account-confirm.png and /dev/null differ diff --git a/server_admin/images/delete-account-landing-screen.png b/server_admin/images/delete-account-landing-screen.png deleted file mode 100644 index aa26f9c78..000000000 Binary files a/server_admin/images/delete-account-landing-screen.png and /dev/null differ diff --git a/server_admin/images/delete-account-page.png b/server_admin/images/delete-account-page.png deleted file mode 100644 index 36a0ecf03..000000000 Binary files a/server_admin/images/delete-account-page.png and /dev/null differ diff --git a/server_admin/images/delete-user.png b/server_admin/images/delete-user.png deleted file mode 100644 index 4e2cb58c1..000000000 Binary files a/server_admin/images/delete-user.png and /dev/null differ diff --git a/server_admin/images/deny-access-execution-cond.png b/server_admin/images/deny-access-execution-cond.png deleted file mode 100644 index b1f568fc2..000000000 Binary files a/server_admin/images/deny-access-execution-cond.png and /dev/null differ diff --git a/server_admin/images/deny-access-flow.png b/server_admin/images/deny-access-flow.png deleted file mode 100644 index 1615486d1..000000000 Binary files a/server_admin/images/deny-access-flow.png and /dev/null differ diff --git a/server_admin/images/deny-access-role-condition.png b/server_admin/images/deny-access-role-condition.png deleted file mode 100644 index cf027c3f3..000000000 Binary files a/server_admin/images/deny-access-role-condition.png and /dev/null differ diff --git a/server_admin/images/domain-mode.png b/server_admin/images/domain-mode.png deleted file mode 100755 index 9d96bd062..000000000 Binary files a/server_admin/images/domain-mode.png and /dev/null differ diff --git a/server_admin/images/effective-role-mappings.png b/server_admin/images/effective-role-mappings.png deleted file mode 100644 index b3e5d78a4..000000000 Binary files a/server_admin/images/effective-role-mappings.png and /dev/null differ diff --git a/server_admin/images/email-simple-example.png b/server_admin/images/email-simple-example.png deleted file mode 100755 index f52be2e38..000000000 Binary files a/server_admin/images/email-simple-example.png and /dev/null differ diff --git a/server_admin/images/email-tab.png b/server_admin/images/email-tab.png deleted file mode 100644 index 09765f2ba..000000000 Binary files a/server_admin/images/email-tab.png and /dev/null differ diff --git a/server_admin/images/enable-delete-account-action.png b/server_admin/images/enable-delete-account-action.png deleted file mode 100644 index 70cce217e..000000000 Binary files a/server_admin/images/enable-delete-account-action.png and /dev/null differ diff --git a/server_admin/images/event-listeners.png b/server_admin/images/event-listeners.png deleted file mode 100644 index 7235814c2..000000000 Binary files a/server_admin/images/event-listeners.png and /dev/null differ diff --git a/server_admin/images/facebook-add-identity-provider.png b/server_admin/images/facebook-add-identity-provider.png deleted file mode 100644 index 1c9a72b10..000000000 Binary files a/server_admin/images/facebook-add-identity-provider.png and /dev/null differ diff --git a/server_admin/images/facebook-add-new-app.png b/server_admin/images/facebook-add-new-app.png deleted file mode 100644 index d91c1faa2..000000000 Binary files a/server_admin/images/facebook-add-new-app.png and /dev/null differ diff --git a/server_admin/images/facebook-app-settings-website.png b/server_admin/images/facebook-app-settings-website.png deleted file mode 100644 index 4cecc45ca..000000000 Binary files a/server_admin/images/facebook-app-settings-website.png and /dev/null differ diff --git a/server_admin/images/facebook-app-settings.png b/server_admin/images/facebook-app-settings.png deleted file mode 100644 index a5049f843..000000000 Binary files a/server_admin/images/facebook-app-settings.png and /dev/null differ diff --git a/server_admin/images/facebook-create-app-id.png b/server_admin/images/facebook-create-app-id.png deleted file mode 100644 index bdd4cee4d..000000000 Binary files a/server_admin/images/facebook-create-app-id.png and /dev/null differ diff --git a/server_admin/images/failed-password-policy.png b/server_admin/images/failed-password-policy.png deleted file mode 100644 index e2357b1ee..000000000 Binary files a/server_admin/images/failed-password-policy.png and /dev/null differ diff --git a/server_admin/images/fine-grain-add-view-leads.png b/server_admin/images/fine-grain-add-view-leads.png deleted file mode 100644 index 5bca8c7df..000000000 Binary files a/server_admin/images/fine-grain-add-view-leads.png and /dev/null differ diff --git a/server_admin/images/fine-grain-add-view-users.png b/server_admin/images/fine-grain-add-view-users.png deleted file mode 100644 index 2533f1c9a..000000000 Binary files a/server_admin/images/fine-grain-add-view-users.png and /dev/null differ diff --git a/server_admin/images/fine-grain-assign-query-clients.png b/server_admin/images/fine-grain-assign-query-clients.png deleted file mode 100644 index 6b94e228c..000000000 Binary files a/server_admin/images/fine-grain-assign-query-clients.png and /dev/null differ diff --git a/server_admin/images/fine-grain-client-assign-user-policy.png b/server_admin/images/fine-grain-client-assign-user-policy.png deleted file mode 100644 index d3ba30dbe..000000000 Binary files a/server_admin/images/fine-grain-client-assign-user-policy.png and /dev/null differ diff --git a/server_admin/images/fine-grain-client-manage-permissions.png b/server_admin/images/fine-grain-client-manage-permissions.png deleted file mode 100644 index 822a396fe..000000000 Binary files a/server_admin/images/fine-grain-client-manage-permissions.png and /dev/null differ diff --git a/server_admin/images/fine-grain-client-permissions-tab-off.png b/server_admin/images/fine-grain-client-permissions-tab-off.png deleted file mode 100644 index 3c427349e..000000000 Binary files a/server_admin/images/fine-grain-client-permissions-tab-off.png and /dev/null differ diff --git a/server_admin/images/fine-grain-client-permissions-tab-on.png b/server_admin/images/fine-grain-client-permissions-tab-on.png deleted file mode 100644 index 5b84142d6..000000000 Binary files a/server_admin/images/fine-grain-client-permissions-tab-on.png and /dev/null differ diff --git a/server_admin/images/fine-grain-client-user-policy.png b/server_admin/images/fine-grain-client-user-policy.png deleted file mode 100644 index e828123e6..000000000 Binary files a/server_admin/images/fine-grain-client-user-policy.png and /dev/null differ diff --git a/server_admin/images/fine-grain-client.png b/server_admin/images/fine-grain-client.png deleted file mode 100644 index dbd380a40..000000000 Binary files a/server_admin/images/fine-grain-client.png and /dev/null differ diff --git a/server_admin/images/fine-grain-group-permissions-tab-on.png b/server_admin/images/fine-grain-group-permissions-tab-on.png deleted file mode 100644 index 56468e495..000000000 Binary files a/server_admin/images/fine-grain-group-permissions-tab-on.png and /dev/null differ diff --git a/server_admin/images/fine-grain-map-roles-permission.png b/server_admin/images/fine-grain-map-roles-permission.png deleted file mode 100644 index ea1ca3b84..000000000 Binary files a/server_admin/images/fine-grain-map-roles-permission.png and /dev/null differ diff --git a/server_admin/images/fine-grain-sales-admin-login.png b/server_admin/images/fine-grain-sales-admin-login.png deleted file mode 100644 index 0f1815d2a..000000000 Binary files a/server_admin/images/fine-grain-sales-admin-login.png and /dev/null differ diff --git a/server_admin/images/fine-grain-sales-application-roles.png b/server_admin/images/fine-grain-sales-application-roles.png deleted file mode 100644 index bf7c132bb..000000000 Binary files a/server_admin/images/fine-grain-sales-application-roles.png and /dev/null differ diff --git a/server_admin/images/fine-grain-users-permissions.png b/server_admin/images/fine-grain-users-permissions.png deleted file mode 100644 index 3a2e1f2e2..000000000 Binary files a/server_admin/images/fine-grain-users-permissions.png and /dev/null differ diff --git a/server_admin/images/fine-grain-view-leads-permissions.png b/server_admin/images/fine-grain-view-leads-permissions.png deleted file mode 100644 index 3364f6514..000000000 Binary files a/server_admin/images/fine-grain-view-leads-permissions.png and /dev/null differ diff --git a/server_admin/images/fine-grain-view-leads-role-tab.png b/server_admin/images/fine-grain-view-leads-role-tab.png deleted file mode 100644 index fa0628ac3..000000000 Binary files a/server_admin/images/fine-grain-view-leads-role-tab.png and /dev/null differ diff --git a/server_admin/images/forgot-password-link.png b/server_admin/images/forgot-password-link.png deleted file mode 100644 index e1cf4eda9..000000000 Binary files a/server_admin/images/forgot-password-link.png and /dev/null differ diff --git a/server_admin/images/forgot-password-page.png b/server_admin/images/forgot-password-page.png deleted file mode 100644 index 04c5c54a7..000000000 Binary files a/server_admin/images/forgot-password-page.png and /dev/null differ diff --git a/server_admin/images/full-client-scope.png b/server_admin/images/full-client-scope.png deleted file mode 100644 index 067058ca9..000000000 Binary files a/server_admin/images/full-client-scope.png and /dev/null differ diff --git a/server_admin/images/general-tab.png b/server_admin/images/general-tab.png deleted file mode 100644 index a5756cd1b..000000000 Binary files a/server_admin/images/general-tab.png and /dev/null differ diff --git a/server_admin/images/generate-client-keys.png b/server_admin/images/generate-client-keys.png deleted file mode 100644 index dffb7d344..000000000 Binary files a/server_admin/images/generate-client-keys.png and /dev/null differ diff --git a/server_admin/images/github-add-identity-provider.png b/server_admin/images/github-add-identity-provider.png deleted file mode 100644 index a64873d91..000000000 Binary files a/server_admin/images/github-add-identity-provider.png and /dev/null differ diff --git a/server_admin/images/github-app-page.png b/server_admin/images/github-app-page.png deleted file mode 100644 index 186d87b98..000000000 Binary files a/server_admin/images/github-app-page.png and /dev/null differ diff --git a/server_admin/images/github-developer-applications.png b/server_admin/images/github-developer-applications.png deleted file mode 100644 index 50332b20a..000000000 Binary files a/server_admin/images/github-developer-applications.png and /dev/null differ diff --git a/server_admin/images/github-register-app.png b/server_admin/images/github-register-app.png deleted file mode 100644 index 5206b8a42..000000000 Binary files a/server_admin/images/github-register-app.png and /dev/null differ diff --git a/server_admin/images/gitlab-add-identity-provider.png b/server_admin/images/gitlab-add-identity-provider.png deleted file mode 100644 index 7fc8564fc..000000000 Binary files a/server_admin/images/gitlab-add-identity-provider.png and /dev/null differ diff --git a/server_admin/images/gitlab-app-page.png b/server_admin/images/gitlab-app-page.png deleted file mode 100644 index 55c83d498..000000000 Binary files a/server_admin/images/gitlab-app-page.png and /dev/null differ diff --git a/server_admin/images/gitlab-developer-applications.png b/server_admin/images/gitlab-developer-applications.png deleted file mode 100644 index 66c1ccdc5..000000000 Binary files a/server_admin/images/gitlab-developer-applications.png and /dev/null differ diff --git a/server_admin/images/google-add-identity-provider.png b/server_admin/images/google-add-identity-provider.png deleted file mode 100644 index 95b294429..000000000 Binary files a/server_admin/images/google-add-identity-provider.png and /dev/null differ diff --git a/server_admin/images/google-client-credentials.png b/server_admin/images/google-client-credentials.png deleted file mode 100644 index 251af3bea..000000000 Binary files a/server_admin/images/google-client-credentials.png and /dev/null differ diff --git a/server_admin/images/google-create-credentials.png b/server_admin/images/google-create-credentials.png deleted file mode 100644 index 4738ead97..000000000 Binary files a/server_admin/images/google-create-credentials.png and /dev/null differ diff --git a/server_admin/images/google-create-oauth-id.png b/server_admin/images/google-create-oauth-id.png deleted file mode 100644 index bf9af4fce..000000000 Binary files a/server_admin/images/google-create-oauth-id.png and /dev/null differ diff --git a/server_admin/images/google-dashboard.png b/server_admin/images/google-dashboard.png deleted file mode 100644 index 4bd98f70d..000000000 Binary files a/server_admin/images/google-dashboard.png and /dev/null differ diff --git a/server_admin/images/google-developer-console.png b/server_admin/images/google-developer-console.png deleted file mode 100644 index 5308d1610..000000000 Binary files a/server_admin/images/google-developer-console.png and /dev/null differ diff --git a/server_admin/images/google-oauth-consent-screen.png b/server_admin/images/google-oauth-consent-screen.png deleted file mode 100644 index 4cdff5008..000000000 Binary files a/server_admin/images/google-oauth-consent-screen.png and /dev/null differ diff --git a/server_admin/images/group-membership.png b/server_admin/images/group-membership.png deleted file mode 100644 index 663f82ec5..000000000 Binary files a/server_admin/images/group-membership.png and /dev/null differ diff --git a/server_admin/images/group.png b/server_admin/images/group.png deleted file mode 100644 index 73b394aa0..000000000 Binary files a/server_admin/images/group.png and /dev/null differ diff --git a/server_admin/images/groups.png b/server_admin/images/groups.png deleted file mode 100644 index 966882a68..000000000 Binary files a/server_admin/images/groups.png and /dev/null differ diff --git a/server_admin/images/groups_account_console.png b/server_admin/images/groups_account_console.png deleted file mode 100644 index b8aedc6d1..000000000 Binary files a/server_admin/images/groups_account_console.png and /dev/null differ diff --git a/server_admin/images/identity-provider-login-page.png b/server_admin/images/identity-provider-login-page.png deleted file mode 100644 index f1f4b2554..000000000 Binary files a/server_admin/images/identity-provider-login-page.png and /dev/null differ diff --git a/server_admin/images/identity-provider-mapper.png b/server_admin/images/identity-provider-mapper.png deleted file mode 100644 index 413d9f7ab..000000000 Binary files a/server_admin/images/identity-provider-mapper.png and /dev/null differ diff --git a/server_admin/images/identity-provider-mappers.png b/server_admin/images/identity-provider-mappers.png deleted file mode 100644 index 9d2614d34..000000000 Binary files a/server_admin/images/identity-provider-mappers.png and /dev/null differ diff --git a/server_admin/images/identity-providers.png b/server_admin/images/identity-providers.png deleted file mode 100644 index af7d28ef1..000000000 Binary files a/server_admin/images/identity-providers.png and /dev/null differ diff --git a/server_admin/images/identity_broker_flow.png b/server_admin/images/identity_broker_flow.png deleted file mode 100755 index 74739a2a3..000000000 Binary files a/server_admin/images/identity_broker_flow.png and /dev/null differ diff --git a/server_admin/images/import-client-cert.png b/server_admin/images/import-client-cert.png deleted file mode 100644 index 4f309e78d..000000000 Binary files a/server_admin/images/import-client-cert.png and /dev/null differ diff --git a/server_admin/images/import-client-saml.png b/server_admin/images/import-client-saml.png deleted file mode 100644 index 49f80ebb9..000000000 Binary files a/server_admin/images/import-client-saml.png and /dev/null differ diff --git a/server_admin/images/initial-welcome-page.png b/server_admin/images/initial-welcome-page.png deleted file mode 100755 index cfd0e6c58..000000000 Binary files a/server_admin/images/initial-welcome-page.png and /dev/null differ diff --git a/server_admin/images/instagram-add-identity-provider.png b/server_admin/images/instagram-add-identity-provider.png deleted file mode 100644 index 670ac8e68..000000000 Binary files a/server_admin/images/instagram-add-identity-provider.png and /dev/null differ diff --git a/server_admin/images/instagram-add-new-app.png b/server_admin/images/instagram-add-new-app.png deleted file mode 100644 index 343455c97..000000000 Binary files a/server_admin/images/instagram-add-new-app.png and /dev/null differ diff --git a/server_admin/images/instagram-add-platform.png b/server_admin/images/instagram-add-platform.png deleted file mode 100644 index caaf050fb..000000000 Binary files a/server_admin/images/instagram-add-platform.png and /dev/null differ diff --git a/server_admin/images/instagram-add-product.png b/server_admin/images/instagram-add-product.png deleted file mode 100644 index a19f854a7..000000000 Binary files a/server_admin/images/instagram-add-product.png and /dev/null differ diff --git a/server_admin/images/instagram-app-settings.png b/server_admin/images/instagram-app-settings.png deleted file mode 100644 index d5f4084c0..000000000 Binary files a/server_admin/images/instagram-app-settings.png and /dev/null differ diff --git a/server_admin/images/instagram-create-app-id.png b/server_admin/images/instagram-create-app-id.png deleted file mode 100644 index 24a8dacfa..000000000 Binary files a/server_admin/images/instagram-create-app-id.png and /dev/null differ diff --git a/server_admin/images/instagram-create-instagram-app-id.png b/server_admin/images/instagram-create-instagram-app-id.png deleted file mode 100644 index 9ee408d08..000000000 Binary files a/server_admin/images/instagram-create-instagram-app-id.png and /dev/null differ diff --git a/server_admin/images/kerberos-browser-flow.png b/server_admin/images/kerberos-browser-flow.png deleted file mode 100644 index aba46cf17..000000000 Binary files a/server_admin/images/kerberos-browser-flow.png and /dev/null differ diff --git a/server_admin/images/kerberos-provider.png b/server_admin/images/kerberos-provider.png deleted file mode 100644 index b352d86f3..000000000 Binary files a/server_admin/images/kerberos-provider.png and /dev/null differ diff --git a/server_admin/images/kerberos-trust-basic.png b/server_admin/images/kerberos-trust-basic.png deleted file mode 100644 index b78a1424f..000000000 Binary files a/server_admin/images/kerberos-trust-basic.png and /dev/null differ diff --git a/server_admin/images/keycloak-sssd-freeipa-integration-overview.png b/server_admin/images/keycloak-sssd-freeipa-integration-overview.png deleted file mode 100644 index 60e98167e..000000000 Binary files a/server_admin/images/keycloak-sssd-freeipa-integration-overview.png and /dev/null differ diff --git a/server_admin/images/keycloak_logo.png b/server_admin/images/keycloak_logo.png deleted file mode 100755 index 4883f5230..000000000 Binary files a/server_admin/images/keycloak_logo.png and /dev/null differ diff --git a/server_admin/images/keys-tab.png b/server_admin/images/keys-tab.png deleted file mode 100644 index 636f759fc..000000000 Binary files a/server_admin/images/keys-tab.png and /dev/null differ diff --git a/server_admin/images/ldap-kerberos.png b/server_admin/images/ldap-kerberos.png deleted file mode 100644 index 9602c0e17..000000000 Binary files a/server_admin/images/ldap-kerberos.png and /dev/null differ diff --git a/server_admin/images/ldap-vault.png b/server_admin/images/ldap-vault.png deleted file mode 100644 index 5ab841fed..000000000 Binary files a/server_admin/images/ldap-vault.png and /dev/null differ diff --git a/server_admin/images/linked-in-add-identity-provider.png b/server_admin/images/linked-in-add-identity-provider.png deleted file mode 100644 index aca916d54..000000000 Binary files a/server_admin/images/linked-in-add-identity-provider.png and /dev/null differ diff --git a/server_admin/images/linked-in-app-settings.png b/server_admin/images/linked-in-app-settings.png deleted file mode 100644 index db211988c..000000000 Binary files a/server_admin/images/linked-in-app-settings.png and /dev/null differ diff --git a/server_admin/images/linked-in-create-app.png b/server_admin/images/linked-in-create-app.png deleted file mode 100644 index 9c4930a6d..000000000 Binary files a/server_admin/images/linked-in-create-app.png and /dev/null differ diff --git a/server_admin/images/linked-in-developer-network.png b/server_admin/images/linked-in-developer-network.png deleted file mode 100644 index ce7bae293..000000000 Binary files a/server_admin/images/linked-in-developer-network.png and /dev/null differ diff --git a/server_admin/images/localization.png b/server_admin/images/localization.png deleted file mode 100644 index 3d6113bb0..000000000 Binary files a/server_admin/images/localization.png and /dev/null differ diff --git a/server_admin/images/login-events-config.png b/server_admin/images/login-events-config.png deleted file mode 100644 index beaa63c66..000000000 Binary files a/server_admin/images/login-events-config.png and /dev/null differ diff --git a/server_admin/images/login-events-filter.png b/server_admin/images/login-events-filter.png deleted file mode 100644 index de29a2482..000000000 Binary files a/server_admin/images/login-events-filter.png and /dev/null differ diff --git a/server_admin/images/login-events-settings.png b/server_admin/images/login-events-settings.png deleted file mode 100644 index ebf79914b..000000000 Binary files a/server_admin/images/login-events-settings.png and /dev/null differ diff --git a/server_admin/images/login-events.png b/server_admin/images/login-events.png deleted file mode 100644 index 525f02e98..000000000 Binary files a/server_admin/images/login-events.png and /dev/null differ diff --git a/server_admin/images/login-page.png b/server_admin/images/login-page.png deleted file mode 100644 index 8f28b18bd..000000000 Binary files a/server_admin/images/login-page.png and /dev/null differ diff --git a/server_admin/images/login-tab-remember-me.png b/server_admin/images/login-tab-remember-me.png deleted file mode 100644 index 1e94336d4..000000000 Binary files a/server_admin/images/login-tab-remember-me.png and /dev/null differ diff --git a/server_admin/images/login-tab.png b/server_admin/images/login-tab.png deleted file mode 100644 index 823643763..000000000 Binary files a/server_admin/images/login-tab.png and /dev/null differ diff --git a/server_admin/images/mapper-config.png b/server_admin/images/mapper-config.png deleted file mode 100644 index 12c5e7ff3..000000000 Binary files a/server_admin/images/mapper-config.png and /dev/null differ diff --git a/server_admin/images/mappers-oidc.png b/server_admin/images/mappers-oidc.png deleted file mode 100644 index 7f6b9e954..000000000 Binary files a/server_admin/images/mappers-oidc.png and /dev/null differ diff --git a/server_admin/images/master_realm.png b/server_admin/images/master_realm.png deleted file mode 100644 index e02c0f4cc..000000000 Binary files a/server_admin/images/master_realm.png and /dev/null differ diff --git a/server_admin/images/microsoft-add-identity-provider.png b/server_admin/images/microsoft-add-identity-provider.png deleted file mode 100644 index e06fcab8e..000000000 Binary files a/server_admin/images/microsoft-add-identity-provider.png and /dev/null differ diff --git a/server_admin/images/microsoft-app-register.png b/server_admin/images/microsoft-app-register.png deleted file mode 100644 index be8d112cd..000000000 Binary files a/server_admin/images/microsoft-app-register.png and /dev/null differ diff --git a/server_admin/images/microsoft-app-settings.png b/server_admin/images/microsoft-app-settings.png deleted file mode 100644 index d90dddbc6..000000000 Binary files a/server_admin/images/microsoft-app-settings.png and /dev/null differ diff --git a/server_admin/images/oidc-add-identity-provider.png b/server_admin/images/oidc-add-identity-provider.png deleted file mode 100644 index 27553eaf9..000000000 Binary files a/server_admin/images/oidc-add-identity-provider.png and /dev/null differ diff --git a/server_admin/images/oidc-client-secret-rotation-policy.png b/server_admin/images/oidc-client-secret-rotation-policy.png deleted file mode 100644 index a056c6f75..000000000 Binary files a/server_admin/images/oidc-client-secret-rotation-policy.png and /dev/null differ diff --git a/server_admin/images/openshift-4-add-identity-provider.png b/server_admin/images/openshift-4-add-identity-provider.png deleted file mode 100644 index 5a5bcf92e..000000000 Binary files a/server_admin/images/openshift-4-add-identity-provider.png and /dev/null differ diff --git a/server_admin/images/openshift-add-identity-provider.png b/server_admin/images/openshift-add-identity-provider.png deleted file mode 100644 index 51c406190..000000000 Binary files a/server_admin/images/openshift-add-identity-provider.png and /dev/null differ diff --git a/server_admin/images/otp-policy.png b/server_admin/images/otp-policy.png deleted file mode 100644 index b61b8a71f..000000000 Binary files a/server_admin/images/otp-policy.png and /dev/null differ diff --git a/server_admin/images/password-policy.png b/server_admin/images/password-policy.png deleted file mode 100644 index 8936f4f03..000000000 Binary files a/server_admin/images/password-policy.png and /dev/null differ diff --git a/server_admin/images/paypal-add-identity-provider.png b/server_admin/images/paypal-add-identity-provider.png deleted file mode 100644 index 8dc912a93..000000000 Binary files a/server_admin/images/paypal-add-identity-provider.png and /dev/null differ diff --git a/server_admin/images/paypal-developer-applications.png b/server_admin/images/paypal-developer-applications.png deleted file mode 100644 index 64dba3a50..000000000 Binary files a/server_admin/images/paypal-developer-applications.png and /dev/null differ diff --git a/server_admin/images/paypal-register-app.png b/server_admin/images/paypal-register-app.png deleted file mode 100644 index a580ebb12..000000000 Binary files a/server_admin/images/paypal-register-app.png and /dev/null differ diff --git a/server_admin/images/realm-oidc-map-acr-to-loa.png b/server_admin/images/realm-oidc-map-acr-to-loa.png deleted file mode 100644 index 7bb56032f..000000000 Binary files a/server_admin/images/realm-oidc-map-acr-to-loa.png and /dev/null differ diff --git a/server_admin/images/recaptcha-config.png b/server_admin/images/recaptcha-config.png deleted file mode 100644 index 3838b5e42..000000000 Binary files a/server_admin/images/recaptcha-config.png and /dev/null differ diff --git a/server_admin/images/registration-flow.png b/server_admin/images/registration-flow.png deleted file mode 100644 index 29d531181..000000000 Binary files a/server_admin/images/registration-flow.png and /dev/null differ diff --git a/server_admin/images/registration-form.png b/server_admin/images/registration-form.png deleted file mode 100644 index 9fdfb92c3..000000000 Binary files a/server_admin/images/registration-form.png and /dev/null differ diff --git a/server_admin/images/registration-link.png b/server_admin/images/registration-link.png deleted file mode 100644 index ed2efae73..000000000 Binary files a/server_admin/images/registration-link.png and /dev/null differ diff --git a/server_admin/images/remember-me.png b/server_admin/images/remember-me.png deleted file mode 100644 index 53618298b..000000000 Binary files a/server_admin/images/remember-me.png and /dev/null differ diff --git a/server_admin/images/reset-credentials-flow.png b/server_admin/images/reset-credentials-flow.png deleted file mode 100644 index e1cc7476a..000000000 Binary files a/server_admin/images/reset-credentials-flow.png and /dev/null differ diff --git a/server_admin/images/reset-credentials-required-actions.png b/server_admin/images/reset-credentials-required-actions.png deleted file mode 100644 index d42b5b6e2..000000000 Binary files a/server_admin/images/reset-credentials-required-actions.png and /dev/null differ diff --git a/server_admin/images/revocation.png b/server_admin/images/revocation.png deleted file mode 100644 index 76ee8efed..000000000 Binary files a/server_admin/images/revocation.png and /dev/null differ diff --git a/server_admin/images/role.png b/server_admin/images/role.png deleted file mode 100644 index fdd4108c9..000000000 Binary files a/server_admin/images/role.png and /dev/null differ diff --git a/server_admin/images/roles.png b/server_admin/images/roles.png deleted file mode 100644 index 487c09eb3..000000000 Binary files a/server_admin/images/roles.png and /dev/null differ diff --git a/server_admin/images/saml-add-identity-provider.png b/server_admin/images/saml-add-identity-provider.png deleted file mode 100644 index 895c9a4dc..000000000 Binary files a/server_admin/images/saml-add-identity-provider.png and /dev/null differ diff --git a/server_admin/images/search-user-event.png b/server_admin/images/search-user-event.png deleted file mode 100644 index 9c76e450d..000000000 Binary files a/server_admin/images/search-user-event.png and /dev/null differ diff --git a/server_admin/images/security-headers.png b/server_admin/images/security-headers.png deleted file mode 100644 index d5d1abcc2..000000000 Binary files a/server_admin/images/security-headers.png and /dev/null differ diff --git a/server_admin/images/sessions-tab.png b/server_admin/images/sessions-tab.png deleted file mode 100644 index 0c0d7f7cc..000000000 Binary files a/server_admin/images/sessions-tab.png and /dev/null differ diff --git a/server_admin/images/sessions.png b/server_admin/images/sessions.png deleted file mode 100644 index dc1242aa8..000000000 Binary files a/server_admin/images/sessions.png and /dev/null differ diff --git a/server_admin/images/stack-overflow-add-identity-provider.png b/server_admin/images/stack-overflow-add-identity-provider.png deleted file mode 100644 index c656d90b0..000000000 Binary files a/server_admin/images/stack-overflow-add-identity-provider.png and /dev/null differ diff --git a/server_admin/images/stack-overflow-app-register.png b/server_admin/images/stack-overflow-app-register.png deleted file mode 100644 index 38628f5a7..000000000 Binary files a/server_admin/images/stack-overflow-app-register.png and /dev/null differ diff --git a/server_admin/images/stack-overflow-app-settings.png b/server_admin/images/stack-overflow-app-settings.png deleted file mode 100644 index d54bbcdbb..000000000 Binary files a/server_admin/images/stack-overflow-app-settings.png and /dev/null differ diff --git a/server_admin/images/themes-tab.png b/server_admin/images/themes-tab.png deleted file mode 100644 index 9d56809c4..000000000 Binary files a/server_admin/images/themes-tab.png and /dev/null differ diff --git a/server_admin/images/tokens-tab.png b/server_admin/images/tokens-tab.png deleted file mode 100644 index f76837220..000000000 Binary files a/server_admin/images/tokens-tab.png and /dev/null differ diff --git a/server_admin/images/twitter-add-identity-provider.png b/server_admin/images/twitter-add-identity-provider.png deleted file mode 100644 index c33943dd3..000000000 Binary files a/server_admin/images/twitter-add-identity-provider.png and /dev/null differ diff --git a/server_admin/images/twitter-app-create.png b/server_admin/images/twitter-app-create.png deleted file mode 100644 index 5077e10f8..000000000 Binary files a/server_admin/images/twitter-app-create.png and /dev/null differ diff --git a/server_admin/images/twitter-app-register.png b/server_admin/images/twitter-app-register.png deleted file mode 100644 index 320f48d5a..000000000 Binary files a/server_admin/images/twitter-app-register.png and /dev/null differ diff --git a/server_admin/images/twitter-details.png b/server_admin/images/twitter-details.png deleted file mode 100644 index 8b9df58a4..000000000 Binary files a/server_admin/images/twitter-details.png and /dev/null differ diff --git a/server_admin/images/twitter-keys.png b/server_admin/images/twitter-keys.png deleted file mode 100644 index 3dc1f1bff..000000000 Binary files a/server_admin/images/twitter-keys.png and /dev/null differ diff --git a/server_admin/images/update-server-config-dialog.png b/server_admin/images/update-server-config-dialog.png deleted file mode 100755 index 5b0722785..000000000 Binary files a/server_admin/images/update-server-config-dialog.png and /dev/null differ diff --git a/server_admin/images/update-server-config-select.png b/server_admin/images/update-server-config-select.png deleted file mode 100755 index b9156e6f5..000000000 Binary files a/server_admin/images/update-server-config-select.png and /dev/null differ diff --git a/server_admin/images/user-attributes.png b/server_admin/images/user-attributes.png deleted file mode 100644 index 507a45c3e..000000000 Binary files a/server_admin/images/user-attributes.png and /dev/null differ diff --git a/server_admin/images/user-credentials-set-password.png b/server_admin/images/user-credentials-set-password.png deleted file mode 100644 index 2793c58d2..000000000 Binary files a/server_admin/images/user-credentials-set-password.png and /dev/null differ diff --git a/server_admin/images/user-credentials.png b/server_admin/images/user-credentials.png deleted file mode 100644 index b6fc34422..000000000 Binary files a/server_admin/images/user-credentials.png and /dev/null differ diff --git a/server_admin/images/user-details.png b/server_admin/images/user-details.png deleted file mode 100644 index 8aece842c..000000000 Binary files a/server_admin/images/user-details.png and /dev/null differ diff --git a/server_admin/images/user-events-settings.png b/server_admin/images/user-events-settings.png deleted file mode 100644 index 70f7ebd6b..000000000 Binary files a/server_admin/images/user-events-settings.png and /dev/null differ diff --git a/server_admin/images/user-events.png b/server_admin/images/user-events.png deleted file mode 100644 index 76316dbf4..000000000 Binary files a/server_admin/images/user-events.png and /dev/null differ diff --git a/server_admin/images/user-federation.png b/server_admin/images/user-federation.png deleted file mode 100644 index 48a0a3ed3..000000000 Binary files a/server_admin/images/user-federation.png and /dev/null differ diff --git a/server_admin/images/user-groups.png b/server_admin/images/user-groups.png deleted file mode 100644 index c397b1b3f..000000000 Binary files a/server_admin/images/user-groups.png and /dev/null differ diff --git a/server_admin/images/user-profile-annotation.png b/server_admin/images/user-profile-annotation.png deleted file mode 100644 index 39665401c..000000000 Binary files a/server_admin/images/user-profile-annotation.png and /dev/null differ diff --git a/server_admin/images/user-profile-attribute-group-list.png b/server_admin/images/user-profile-attribute-group-list.png deleted file mode 100644 index 738169ee2..000000000 Binary files a/server_admin/images/user-profile-attribute-group-list.png and /dev/null differ diff --git a/server_admin/images/user-profile-attribute-list-order.png b/server_admin/images/user-profile-attribute-list-order.png deleted file mode 100644 index 228d5a576..000000000 Binary files a/server_admin/images/user-profile-attribute-list-order.png and /dev/null differ diff --git a/server_admin/images/user-profile-create-attribute-group.png b/server_admin/images/user-profile-create-attribute-group.png deleted file mode 100644 index 5a71d1b35..000000000 Binary files a/server_admin/images/user-profile-create-attribute-group.png and /dev/null differ diff --git a/server_admin/images/user-profile-create-attribute.png b/server_admin/images/user-profile-create-attribute.png deleted file mode 100644 index d1b7651ab..000000000 Binary files a/server_admin/images/user-profile-create-attribute.png and /dev/null differ diff --git a/server_admin/images/user-profile-enabling.png b/server_admin/images/user-profile-enabling.png deleted file mode 100644 index 55e1facd9..000000000 Binary files a/server_admin/images/user-profile-enabling.png and /dev/null differ diff --git a/server_admin/images/user-profile-json-config.png b/server_admin/images/user-profile-json-config.png deleted file mode 100644 index d7f8e15e6..000000000 Binary files a/server_admin/images/user-profile-json-config.png and /dev/null differ diff --git a/server_admin/images/user-profile-permission.png b/server_admin/images/user-profile-permission.png deleted file mode 100644 index 6d34123c2..000000000 Binary files a/server_admin/images/user-profile-permission.png and /dev/null differ diff --git a/server_admin/images/user-profile-register-verify-profile-action.png b/server_admin/images/user-profile-register-verify-profile-action.png deleted file mode 100644 index 508ddc33a..000000000 Binary files a/server_admin/images/user-profile-register-verify-profile-action.png and /dev/null differ diff --git a/server_admin/images/user-profile-select-options-custom-validator.png b/server_admin/images/user-profile-select-options-custom-validator.png deleted file mode 100644 index 4bfa18a86..000000000 Binary files a/server_admin/images/user-profile-select-options-custom-validator.png and /dev/null differ diff --git a/server_admin/images/user-profile-select-options-simple-i18n.png b/server_admin/images/user-profile-select-options-simple-i18n.png deleted file mode 100644 index a05a9db97..000000000 Binary files a/server_admin/images/user-profile-select-options-simple-i18n.png and /dev/null differ diff --git a/server_admin/images/user-profile-select-options-simple.png b/server_admin/images/user-profile-select-options-simple.png deleted file mode 100644 index de9b2af51..000000000 Binary files a/server_admin/images/user-profile-select-options-simple.png and /dev/null differ diff --git a/server_admin/images/user-profile-tab.png b/server_admin/images/user-profile-tab.png deleted file mode 100644 index 3d85b5169..000000000 Binary files a/server_admin/images/user-profile-tab.png and /dev/null differ diff --git a/server_admin/images/user-profile-update-profile.png b/server_admin/images/user-profile-update-profile.png deleted file mode 100644 index ee32967c7..000000000 Binary files a/server_admin/images/user-profile-update-profile.png and /dev/null differ diff --git a/server_admin/images/user-profile-validation.png b/server_admin/images/user-profile-validation.png deleted file mode 100644 index 79567dc5c..000000000 Binary files a/server_admin/images/user-profile-validation.png and /dev/null differ diff --git a/server_admin/images/user-required-action.png b/server_admin/images/user-required-action.png deleted file mode 100644 index ee3d6d5fd..000000000 Binary files a/server_admin/images/user-required-action.png and /dev/null differ diff --git a/server_admin/images/user-role-mappings.png b/server_admin/images/user-role-mappings.png deleted file mode 100644 index f1bb33347..000000000 Binary files a/server_admin/images/user-role-mappings.png and /dev/null differ diff --git a/server_admin/images/user-search.png b/server_admin/images/user-search.png deleted file mode 100644 index c8d13a67f..000000000 Binary files a/server_admin/images/user-search.png and /dev/null differ diff --git a/server_admin/images/user-sessions.png b/server_admin/images/user-sessions.png deleted file mode 100644 index 51b3b4477..000000000 Binary files a/server_admin/images/user-sessions.png and /dev/null differ diff --git a/server_admin/images/users.png b/server_admin/images/users.png deleted file mode 100755 index 0f87bd74b..000000000 Binary files a/server_admin/images/users.png and /dev/null differ diff --git a/server_admin/images/webauthn-browser-flow-conditional-with-OTP.png b/server_admin/images/webauthn-browser-flow-conditional-with-OTP.png deleted file mode 100644 index f246f1e62..000000000 Binary files a/server_admin/images/webauthn-browser-flow-conditional-with-OTP.png and /dev/null differ diff --git a/server_admin/images/webauthn-browser-flow-conditional.png b/server_admin/images/webauthn-browser-flow-conditional.png deleted file mode 100644 index 55907bf6c..000000000 Binary files a/server_admin/images/webauthn-browser-flow-conditional.png and /dev/null differ diff --git a/server_admin/images/webauthn-browser-flow-required.png b/server_admin/images/webauthn-browser-flow-required.png deleted file mode 100644 index 9ae672a81..000000000 Binary files a/server_admin/images/webauthn-browser-flow-required.png and /dev/null differ diff --git a/server_admin/images/webauthn-loginless-flow.png b/server_admin/images/webauthn-loginless-flow.png deleted file mode 100644 index f37f42753..000000000 Binary files a/server_admin/images/webauthn-loginless-flow.png and /dev/null differ diff --git a/server_admin/images/webauthn-passwordless-flow.png b/server_admin/images/webauthn-passwordless-flow.png deleted file mode 100644 index bdf0b969d..000000000 Binary files a/server_admin/images/webauthn-passwordless-flow.png and /dev/null differ diff --git a/server_admin/images/x509-browser-flow-bindings.png b/server_admin/images/x509-browser-flow-bindings.png deleted file mode 100644 index e1c2ceaa7..000000000 Binary files a/server_admin/images/x509-browser-flow-bindings.png and /dev/null differ diff --git a/server_admin/images/x509-browser-flow.png b/server_admin/images/x509-browser-flow.png deleted file mode 100644 index c6eaa1c03..000000000 Binary files a/server_admin/images/x509-browser-flow.png and /dev/null differ diff --git a/server_admin/images/x509-client-auth.png b/server_admin/images/x509-client-auth.png deleted file mode 100644 index 61896fc70..000000000 Binary files a/server_admin/images/x509-client-auth.png and /dev/null differ diff --git a/server_admin/images/x509-configuration.png b/server_admin/images/x509-configuration.png deleted file mode 100644 index 1ddb0e6ef..000000000 Binary files a/server_admin/images/x509-configuration.png and /dev/null differ diff --git a/server_admin/images/x509-directgrant-execution.png b/server_admin/images/x509-directgrant-execution.png deleted file mode 100644 index 4a1336ecd..000000000 Binary files a/server_admin/images/x509-directgrant-execution.png and /dev/null differ diff --git a/server_admin/images/x509-directgrant-flow-bindings.png b/server_admin/images/x509-directgrant-flow-bindings.png deleted file mode 100644 index 81e98daee..000000000 Binary files a/server_admin/images/x509-directgrant-flow-bindings.png and /dev/null differ diff --git a/server_admin/images/x509-directgrant-flow.png b/server_admin/images/x509-directgrant-flow.png deleted file mode 100644 index 2c1e6c263..000000000 Binary files a/server_admin/images/x509-directgrant-flow.png and /dev/null differ diff --git a/server_admin/images/x509-execution.png b/server_admin/images/x509-execution.png deleted file mode 100644 index c9661d404..000000000 Binary files a/server_admin/images/x509-execution.png and /dev/null differ diff --git a/server_admin/index.adoc b/server_admin/index.adoc deleted file mode 100644 index 011712a9e..000000000 --- a/server_admin/index.adoc +++ /dev/null @@ -1,19 +0,0 @@ -:toc: left -:toclevels: 3 -:sectanchors: -:linkattrs: - -include::topics/templates/document-attributes.adoc[] - -:server_administration_guide: -:context: server_administration_guide - -= {adminguide_name} - -:release_header_guide: {adminguide_name_short} -:release_header_latest_link: {adminguide_link_latest} -include::topics/templates/release-header.adoc[] - -include::topics.adoc[] - -:context: diff --git a/server_admin/pom.xml b/server_admin/pom.xml deleted file mode 100644 index a093514cf..000000000 --- a/server_admin/pom.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - 4.0.0 - - - org.keycloak.documentation - documentation-parent - 999.0.0-SNAPSHOT - ../ - - - Server Administration - server-admin - pom - - - - - org.keycloak.documentation - header-maven-plugin - - - add-file-headers - - - - - org.asciidoctor - asciidoctor-maven-plugin - - - asciidoc-to-html - - - - - maven-antrun-plugin - - - echo-output - - - - - - diff --git a/server_admin/topics.adoc b/server_admin/topics.adoc deleted file mode 100644 index 91f0148e2..000000000 --- a/server_admin/topics.adoc +++ /dev/null @@ -1,85 +0,0 @@ -include::topics/overview.adoc[] -include::topics/overview/features.adoc[] -include::topics/overview/how.adoc[] -include::topics/overview/concepts.adoc[] -include::topics/assembly-creating-first-admin.adoc[] -include::topics/admin-console.adoc[] -include::topics/user-federation.adoc[] -include::topics/user-federation/ldap.adoc[] -include::topics/user-federation/sssd.adoc[] -include::topics/user-federation/custom.adoc[] -include::topics/assembly-managing-users.adoc[] -include::topics/sessions.adoc[] -include::topics/sessions/administering.adoc[] -include::topics/sessions/revocation.adoc[] -include::topics/sessions/timeouts.adoc[] -include::topics/sessions/offline.adoc[] -include::topics/sessions/preloading.adoc[] -include::topics/sessions/transient.adoc[] -include::topics/assembly-roles-groups.adoc[] -include::topics/authentication.adoc[] -include::topics/authentication/password-policies.adoc[] -include::topics/authentication/otp-policies.adoc[] -include::topics/authentication/flows.adoc[] -include::topics/authentication/kerberos.adoc[] -include::topics/authentication/x509.adoc[] -include::topics/authentication/webauthn.adoc[] -include::topics/authentication/recovery-codes.adoc[] -include::topics/authentication/conditions.adoc[] -include::topics/identity-broker.adoc[] -include::topics/identity-broker/overview.adoc[] -include::topics/identity-broker/default-provider.adoc[] -include::topics/identity-broker/configuration.adoc[] -include::topics/identity-broker/social-login.adoc[] -include::topics/identity-broker/social/bitbucket.adoc[] -include::topics/identity-broker/social/facebook.adoc[] -include::topics/identity-broker/social/github.adoc[] -include::topics/identity-broker/social/gitlab.adoc[] -include::topics/identity-broker/social/google.adoc[] -include::topics/identity-broker/social/linked-in.adoc[] -include::topics/identity-broker/social/microsoft.adoc[] -include::topics/identity-broker/social/openshift.adoc[] -include::topics/identity-broker/social/paypal.adoc[] -include::topics/identity-broker/social/stack-overflow.adoc[] -include::topics/identity-broker/social/twitter.adoc[] -include::topics/identity-broker/social/instagram.adoc[] -include::topics/identity-broker/oidc.adoc[] -include::topics/identity-broker/saml.adoc[] -include::topics/identity-broker/suggested.adoc[] -include::topics/identity-broker/mappers.adoc[] -include::topics/identity-broker/session-data.adoc[] -include::topics/identity-broker/first-login-flow.adoc[] -include::topics/identity-broker/tokens.adoc[] -include::topics/identity-broker/logout.adoc[] -include::topics/sso-protocols.adoc[] -include::topics/admin-console-permissions.adoc[] -include::topics/admin-console-permissions/master-realm.adoc[] -include::topics/admin-console-permissions/per-realm.adoc[] -include::topics/admin-console-permissions/fine-grain.adoc[] -include::topics/assembly-managing-clients.adoc[] -include::topics/vault.adoc[] -include::topics/events.adoc[] -include::topics/threat.adoc[] -include::topics/threat/host.adoc[] -include::topics/threat/admin.adoc[] -include::topics/threat/brute-force.adoc[] -include::topics/threat/read-only-attributes.adoc[] -include::topics/threat/clickjacking.adoc[] -include::topics/threat/ssl.adoc[] -include::topics/threat/csrf.adoc[] -include::topics/threat/redirect.adoc[] -include::topics/threat/fapi-compliance.adoc[] -include::topics/threat/compromised-tokens.adoc[] -include::topics/threat/compromised-codes.adoc[] -include::topics/threat/open-redirect.adoc[] -include::topics/threat/password-db-compromised.adoc[] -include::topics/threat/scope.adoc[] -include::topics/threat/audience-limit.adoc[] -include::topics/threat/auth-sessions-limit.adoc[] -include::topics/threat/sql.adoc[] -include::topics/account.adoc[] -include::topics/admin-cli.adoc[] - -//ifeval::[{project_community}==true] -//include::topics/MigrationFromOlderVersions.adoc[] -//endif::[] diff --git a/server_admin/topics/License.adoc b/server_admin/topics/License.adoc deleted file mode 100644 index becb5fbc6..000000000 --- a/server_admin/topics/License.adoc +++ /dev/null @@ -1,11 +0,0 @@ -= License -:doctype: book -:sectnums: -:toc: left -:icons: font -:experimental: -:sourcedir: . - -Keycloak codebase is distributed under the ASL 2.0 license. -It does not distribute any third party libraries that are GPL. -It does ship third party libraries licensed under Apache ASL 2.0 and LGPL. \ No newline at end of file diff --git a/server_admin/topics/account.adoc b/server_admin/topics/account.adoc deleted file mode 100644 index e1050cb27..000000000 --- a/server_admin/topics/account.adoc +++ /dev/null @@ -1,161 +0,0 @@ -[[_account-service]] - -== Account Console - -{project_name} users can manage their accounts through the Account Console. Users can configure their profiles, add two-factor authentication, include identity provider accounts, and oversee device activity. - -[role="_additional-resources"] -.Additional resources - -* The Account Console can be configured in terms of appearance and language preferences. An example is adding attributes to the *Personal info* page by clicking *Personal info* link and completing and saving details. For more information, see reference:{developerguide_link}[{developerguide_name}]. - -=== Accessing the Account Console - -Any user can access the Account Console. - -.Procedure - -. Make note of the realm name and IP address for the {project_name} server where your account exists. - -. In a web browser, enter a URL in this format: _server-root_{kc_realms_path}/{realm-name}/account. - -. Enter your login name and password. - -.Account Console -image:images/account-console-intro.png[Account Console] - -=== Configuring ways to sign in - -You can sign in to this console using basic authentication (a login name and password) or two-factor authentication. For two-factor authentication, use one of the following procedures. - -==== Two-factor authentication with OTP - -.Prerequisites - -* OTP is a valid authentication mechanism for your realm. - -.Procedure - -. Click *Account security* in the menu. - -. Click *Signing in*. - -. Click *Set up authenticator application*. -+ -.Signing in -image:images/account-console-signing-in.png[Signing in] - -. Follow the directions that appear on the screen to use either - https://freeotp.github.io/[FreeOTP] or https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2[Google Authenticator] on your mobile device as your OTP generator. - -. Scan the QR code in the screen shot into the OTP generator on your mobile device. - -. Log out and log in again. - -. Respond to the prompt by entering an OTP that is provided on your mobile device. - -==== Two-factor authentication with WebAuthn - -.Prerequisites - -* WebAuthn is a valid two-factor authentication mechanism for your realm. Please follow the xref:webauthn_{context}[WebAuthn] section for more details. - -.Procedure - -. Click *Account Security* in the menu. - -. Click *Signing In*. - -. Click *Set up Security Key*. -+ -.Signing In -image:images/account-console-signing-in-webauthn-2factor.png[Signing In With Security Key] - -. Prepare your WebAuthn Security Key. How you prepare this key depends on the type of WebAuthn security key you use. For example, for a USB based Yubikey, you may need to put your key into the USB port on your laptop. - -. Click *Register* to register your security key. - -. Log out and log in again. - -. Assuming authentication flow was correctly set, a message appears asking you to authenticate with your Security Key as second factor. - -==== Passwordless authentication with WebAuthn - -.Prerequisites - -* WebAuthn is a valid passwordless authentication mechanism for your realm. Please follow the <<_webauthn_passwordless,Passwordless WebAuthn section>> for more details. - -.Procedure - -. Click *Account Security* in the menu. - -. Click *Signing In*. - -. Click *Set up Security Key* in the *Passwordless* section. -+ -.Signing In -image:images/account-console-signing-in-webauthn-passwordless.png[Signing In With Security Key] - -. Prepare your WebAuthn Security Key. How you prepare this key depends on the type of WebAuthn security key you use. For example, for a USB based Yubikey, you may need to put your key into the USB port on your laptop. - -. Click *Register* to register your security key. - -. Log out and log in again. - -. Assuming authentication flow was correctly set, a message appears asking you to authenticate with your Security Key as second factor. You no longer need to provide your password to log in. - -=== Viewing device activity - -You can view the devices that are logged in to your account. - -.Procedure - -. Click *Account security* in the menu. -. Click *Device activity*. -. Log out a device if it looks suspicious. - -.Devices -image:images/account-console-device.png[Devices] - -=== Adding an identity provider account - -You can link your account with an <<_identity_broker, identity broker>>. This option is often used to link social provider accounts. - -.Procedure - -. Log into the Admin Console. - -. Click *Identity providers* in the menu. - -. Select a provider and complete the fields. - -. Return to the Account Console. - -. Click *Account security* in the menu. - -. Click *Linked accounts*. - -The identity provider you added appears in this page. - -.Linked Accounts -image:images/account-console-linked.png[Linked Accounts] - -=== Accessing other applications - -The *Applications* menu item shows users which applications you can access. In this case, only the Account Console is available. - -.Applications - -image:images/account-console-applications.png[Applications] - -=== Viewing group memberships - -You can view the groups you are associated with by clicking the *Groups* menu. -If you select *Direct membership* checkbox, you will see only the groups you are direct associated with. - -.Prerequisites - -* You need to have the *view-groups* account role for being able to view *Groups* menu. - -.View group memberships -image:images/groups_account_console.png[View group memberships] diff --git a/server_admin/topics/admin-cli.adoc b/server_admin/topics/admin-cli.adoc deleted file mode 100644 index 0fa1164ea..000000000 --- a/server_admin/topics/admin-cli.adoc +++ /dev/null @@ -1,1897 +0,0 @@ - -== Admin CLI - -With {project_name}, you can perform administration tasks from the command-line interface (CLI) by using the Admin CLI command-line tool. - -=== Installing the Admin CLI - -{project_name} packages the Admin CLI server distribution with the execution scripts in the `bin` directory. - -The Linux script is called `kcadm.sh`, and the script for Windows is called `kcadm.bat`. Add the {project_name} server directory to your `PATH` to use the client from any location on your file system. - -For example: - -* Linux: -[options="nowrap"] ----- -$ export PATH=$PATH:$KEYCLOAK_HOME/bin -$ kcadm.sh ----- - -* Windows: -[options="nowrap"] ----- -c:\> set PATH=%PATH%;%KEYCLOAK_HOME%\bin -c:\> kcadm ----- - -[NOTE] -==== -You must set the `KEYCLOAK_HOME` environment variable to the path where you extracted the {project_name} Server distribution. - -To avoid repetition, the rest of this document only uses Windows examples in places where the CLI differences are more than just in the `kcadm` command name. -==== - - -=== Using the Admin CLI - -The Admin CLI makes HTTP requests to Admin REST endpoints. Access to the Admin REST endpoints requires authentication. - -[NOTE] -==== -Consult the Admin REST API documentation for details about JSON attributes for specific endpoints. -==== - -. Start an authenticated session by logging in. You can now perform create, read, update, and delete (CRUD) operations. -+ -For example: - -* Linux: -+ -[options="nowrap",subs="attributes+"] ----- -$ kcadm.sh config credentials --server http://localhost:8080{kc_base_path} --realm demo --user admin --client admin -$ kcadm.sh create realms -s realm=demorealm -s enabled=true -o -$ CID=$(kcadm.sh create clients -r demorealm -s clientId=my_client -s 'redirectUris=["http://localhost:8980/myapp/*"]' -i) -$ kcadm.sh get clients/$CID/installation/providers/keycloak-oidc-keycloak-json ----- -+ -* Windows: -+ -[options="nowrap",subs="attributes+"] ----- -c:\> kcadm config credentials --server http://localhost:8080{kc_base_path} --realm demo --user admin --client admin -c:\> kcadm create realms -s realm=demorealm -s enabled=true -o -c:\> kcadm create clients -r demorealm -s clientId=my_client -s "redirectUris=[\"http://localhost:8980/myapp/*\"]" -i > clientid.txt -c:\> set /p CID= kcadm get clients/%CID%/installation/providers/keycloak-oidc-keycloak-json ----- - -. In a production environment, access {project_name} by using `https:` to avoid exposing tokens. If a trusted certificate authority, included in Java's default certificate truststore, has not issued a server's certificate, prepare a `truststore.jks` file and instruct the Admin CLI to use it. -+ -For example: - -* Linux: -+ -[options="nowrap"] ----- -$ kcadm.sh config truststore --trustpass $PASSWORD ~/.keycloak/truststore.jks ----- -+ -* Windows: -+ -[options="nowrap"] ----- -c:\> kcadm config truststore --trustpass %PASSWORD% %HOMEPATH%\.keycloak\truststore.jks ----- - - -=== Authenticating - -When you log in with the Admin CLI, you specify: - -* A server endpoint URL -* A realm -* A user name - -Another option is to specify a clientId only, which creates a unique service account for you to use. - -When you log in using a user name, use a password for the specified user. When you log in using a clientId, you need the client secret only, not the user password. You can also use the `Signed JWT` rather than the client secret. - -Ensure the account used for the session has the proper permissions to invoke Admin REST API operations. For example, the `realm-admin` role of the `realm-management` client can administer the realm of the user. - -Two primary mechanisms are available for authentication. One mechanism uses `kcadm config credentials` to start an authenticated session. - -[options="nowrap",subs="attributes+"] ----- -$ kcadm.sh config credentials --server http://localhost:8080{kc_base_path} --realm master --user admin --password admin ----- - -This mechanism maintains an authenticated session between the `kcadm` command invocations by saving the obtained access token and its associated refresh token. It can maintain other secrets in a private configuration file. See the <<_working_with_alternative_configurations, next chapter>> for more information. - -The second mechanism authenticates each command invocation for the duration of the invocation. This mechanism increases the load on the server and the time spent on round trips obtaining tokens. The benefit of this approach is that it is unnecessary to save tokens between invocations, so nothing is saved to disk. {project_name} uses this mode when the `--no-config` argument is specified. - -For example, when performing an operation, specify all the information required for authentication. -[options="nowrap",subs="attributes+"] ----- -$ kcadm.sh get realms --no-config --server http://localhost:8080{kc_base_path} --realm master --user admin --password admin ----- - -Run the `kcadm.sh help` command for more information on using the Admin CLI. - -Run the `kcadm.sh config credentials --help` command for more information about starting an authenticated session. - - -[[_working_with_alternative_configurations]] -=== Working with alternative configurations - -By default, the Admin CLI maintains a configuration file named `kcadm.config`. {project_name} places this file in the user's home directory. -In Linux-based systems, the full pathname is `$HOME/.keycloak/kcadm.config`. -In Windows, the full pathname is `%HOMEPATH%\.keycloak\kcadm.config`. - -You can use the `--config` option to point to a different file or location so you can maintain multiple authenticated sessions in parallel. - -[NOTE] -==== -Perform operations tied to a single configuration file from a single thread. -==== - -Ensure the configuration file is invisible to other users on the system. It contains access tokens and secrets that must be private. {project_name} creates the `~/.keycloak` directory and its contents automatically with proper access limits. If the directory already exists, {project_name} does not update the directory's permissions. - -It is possible to avoid storing secrets inside a configuration file, but doing so is inconvenient and increases the number of token requests. Use the `--no-config` option with all commands and specify the authentication information the `config credentials` command requires with each invocation of `kcadm`. - -=== Basic operations and resource URIs - -The Admin CLI can generically perform CRUD operations against Admin REST API endpoints with additional commands that simplify particular tasks. - -The main usage pattern is listed here: -[options="nowrap"] ----- -$ kcadm.sh create ENDPOINT [ARGUMENTS] -$ kcadm.sh get ENDPOINT [ARGUMENTS] -$ kcadm.sh update ENDPOINT [ARGUMENTS] -$ kcadm.sh delete ENDPOINT [ARGUMENTS] ----- - -The `create`, `get`, `update`, and `delete` commands map to the HTTP verbs `POST`, `GET`, `PUT`, and `DELETE`, respectively. -ENDPOINT is a target resource URI and can be absolute (starting with `http:` or `https:`) or relative, that {project_name} uses to compose absolute URLs in the following format: - -[options="nowrap"] ----- -SERVER_URI/admin/realms/REALM/ENDPOINT ----- - -For example, if you authenticate against the server http://localhost:8080{kc_base_path} and realm is `master`, using `users` as ENDPOINT creates the http://localhost:8080{kc_admins_path}/realms/master/users resource URL. - -If you set ENDPOINT to `clients`, the effective resource URI is http://localhost:8080{kc_admins_path}/realms/master/clients. - -{project_name} has a `realms` endpoint that is the container for realms. It resolves to: -[options="nowrap"] ----- -SERVER_URI/admin/realms ----- - -{project_name} has a `serverinfo` endpoint. This endpoint is independent of realms. - -When you authenticate as a user with realm-admin powers, you may need to perform commands on multiple realms. If so, specify the `-r` option to tell the CLI which realm the command is to execute against explicitly. Instead of using `REALM` as specified by the `--realm` option of `kcadm.sh config credentials`, the command uses `TARGET_REALM`. - -[options="nowrap"] ----- -SERVER_URI/admin/realms/TARGET_REALM/ENDPOINT ----- - -For example: -[options="nowrap",subs="attributes+"] ----- -$ kcadm.sh config credentials --server http://localhost:8080{kc_base_path} --realm master --user admin --password admin -$ kcadm.sh create users -s username=testuser -s enabled=true -r demorealm ----- - -In this example, you start a session authenticated as the `admin` user in the `master` realm. You then perform a POST call against the resource URL `http://localhost:8080{kc_admins_path}/realms/demorealm/users`. - -The `create` and `update` commands send a JSON body to the server. You can use `-f FILENAME` to read a pre-made document from a file. When you can use the `-f -` option, {project_name} reads the message body from the standard input. You can specify individual attributes and their values, as seen in the `create users` example. {project_name} composes the attributes into a JSON body and sends them to the server. - -Several methods are available in {project_name} to update a resource using the `update` command. You can determine the current state of a resource and save it to a file, edit that file, and send it to the server for an update. - -For example: -[options="nowraps"] ----- -$ kcadm.sh get realms/demorealm > demorealm.json -$ vi demorealm.json -$ kcadm.sh update realms/demorealm -f demorealm.json ----- - -This method updates the resource on the server with the attributes in the sent JSON document. - -Another method is to perform an on-the-fly update by using the `-s, --set` options to set new values. - -For example: -[options="nowraps"] ----- -$ kcadm.sh update realms/demorealm -s enabled=false ----- - -This method sets the `enabled` attribute to `false`. - -By default, the `update` command performs a `get` and then merges the new attribute values with existing values. In some cases, the endpoint may support the `put` command but not the `get` command. You can use the `-n` option to perform a no-merge update, which performs a `put` command without first running a `get` command. - - -=== Realm operations - -[discrete] -==== Creating a new realm - -Use the `create` command on the `realms` endpoint to create a new enabled realm. Set the attributes to `realm` and `enabled`. -[options="nowrap"] ----- -$ kcadm.sh create realms -s realm=demorealm -s enabled=true ----- - -{project_name} disables realms by default. You can use a realm immediately for authentication by enabling it. - -A description for a new object can also be in JSON format. -[options="nowrap"] ----- -$ kcadm.sh create realms -f demorealm.json ----- - -You can send a JSON document with realm attributes directly from a file or pipe the document to standard input. - -For example: - -* Linux: -[options="nowrap"] ----- -$ kcadm.sh create realms -f - << EOF -{ "realm": "demorealm", "enabled": true } -EOF ----- - -* Windows: -[options="nowrap"] ----- -c:\> echo { "realm": "demorealm", "enabled": true } | kcadm create realms -f - ----- - -[discrete] -==== Listing existing realms - -This command returns a list of all realms. -[options="nowrap"] ----- -$ kcadm.sh get realms ----- - -[NOTE] -==== -{project_name} filters the list of realms on the server to return realms a user can see only. -==== - -The list of all realm attributes can be verbose, and most users are interested in a subset of attributes, such as the realm name and the enabled status of the realm. You can specify the attributes to return by using the `--fields` option. -[options="nowrap"] ----- -$ kcadm.sh get realms --fields realm,enabled ----- - -You can display the result as comma-separated values. -[options="nowrap"] ----- -$ kcadm.sh get realms --fields realm --format csv --noquotes ----- - -[discrete] -==== Getting a specific realm - -Append a realm name to a collection URI to get an individual realm. -[options="nowrap"] ----- -$ kcadm.sh get realms/master ----- - -[discrete] -==== Updating a realm - -. Use the `-s` option to set new values for the attributes when you do not want to change all of the realm's attributes. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh update realms/demorealm -s enabled=false ----- -. If you want to set all writable attributes to new values: - -.. Run a `get` command. -.. Edit the current values in the JSON file. -.. Resubmit. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh get realms/demorealm > demorealm.json -$ vi demorealm.json -$ kcadm.sh update realms/demorealm -f demorealm.json ----- - -[discrete] -==== Deleting a realm - -Run the following command to delete a realm: -[options="nowrap"] ----- -$ kcadm.sh delete realms/demorealm ----- - -[discrete] -==== Turning on all login page options for the realm - -Set the attributes that control specific capabilities to `true`. - -For example: -[options="nowrap"] ----- -$ kcadm.sh update realms/demorealm -s registrationAllowed=true -s registrationEmailAsUsername=true -s rememberMe=true -s verifyEmail=true -s resetPasswordAllowed=true -s editUsernameAllowed=true ----- - -[discrete] -==== Listing the realm keys - -Use the `get` operation on the `keys` endpoint of the target realm. -[options="nowrap"] ----- -$ kcadm.sh get keys -r demorealm ----- - -[discrete] -==== Generating new realm keys - -. Get the ID of the target realm before adding a new RSA-generated key pair. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh get realms/demorealm --fields id --format csv --noquotes ----- -. Add a new key provider with a higher priority than the existing providers as revealed by `kcadm.sh get keys -r demorealm`. -+ -For example: -+ -* Linux: -+ -[options="nowrap"] ----- -$ kcadm.sh create components -r demorealm -s name=rsa-generated -s providerId=rsa-generated -s providerType=org.keycloak.keys.KeyProvider -s parentId=959844c1-d149-41d7-8359-6aa527fca0b0 -s 'config.priority=["101"]' -s 'config.enabled=["true"]' -s 'config.active=["true"]' -s 'config.keySize=["2048"]' ----- -* Windows: -+ -[options="nowrap"] ----- -c:\> kcadm create components -r demorealm -s name=rsa-generated -s providerId=rsa-generated -s providerType=org.keycloak.keys.KeyProvider -s parentId=959844c1-d149-41d7-8359-6aa527fca0b0 -s "config.priority=[\"101\"]" -s "config.enabled=[\"true\"]" -s "config.active=[\"true\"]" -s "config.keySize=[\"2048\"]" ----- -. Set the `parentId` attribute to the value of the target realm's ID. -+ -The newly added key is now the active key, as revealed by `kcadm.sh get keys -r demorealm`. - -[discrete] -==== Adding new realm keys from a Java Key Store file - -. Add a new key provider to add a new key pair pre-prepared as a JKS file. -+ -For example, on: -+ -* Linux: -+ -[options="nowrap"] ----- -$ kcadm.sh create components -r demorealm -s name=java-keystore -s providerId=java-keystore -s providerType=org.keycloak.keys.KeyProvider -s parentId=959844c1-d149-41d7-8359-6aa527fca0b0 -s 'config.priority=["101"]' -s 'config.enabled=["true"]' -s 'config.active=["true"]' -s 'config.keystore=["/opt/keycloak/keystore.jks"]' -s 'config.keystorePassword=["secret"]' -s 'config.keyPassword=["secret"]' -s 'config.keyAlias=["localhost"]' ----- -* Windows: -+ -[options="nowrap"] ----- -c:\> kcadm create components -r demorealm -s name=java-keystore -s providerId=java-keystore -s providerType=org.keycloak.keys.KeyProvider -s parentId=959844c1-d149-41d7-8359-6aa527fca0b0 -s "config.priority=[\"101\"]" -s "config.enabled=[\"true\"]" -s "config.active=[\"true\"]" -s "config.keystore=[\"/opt/keycloak/keystore.jks\"]" -s "config.keystorePassword=[\"secret\"]" -s "config.keyPassword=[\"secret\"]" -s "config.keyAlias=[\"localhost\"]" ----- -. Ensure you change the attribute values for `keystore`, `keystorePassword`, `keyPassword`, and `alias` to match your specific keystore. -. Set the `parentId` attribute to the value of the target realm's ID. - -[discrete] -==== Making the key passive or disabling the key - -. Identify the key you want to make passive. -+ -[options="nowrap"] ----- -$ kcadm.sh get keys -r demorealm ----- -. Use the key's `providerId` attribute to construct an endpoint URI, such as `components/PROVIDER_ID`. -. Perform an `update`. -+ -For example: - -* Linux: -+ -[options="nowrap"] ----- -$ kcadm.sh update components/PROVIDER_ID -r demorealm -s 'config.active=["false"]' ----- -* Windows: -+ -[options="nowrap"] ----- -c:\> kcadm update components/PROVIDER_ID -r demorealm -s "config.active=[\"false\"]" ----- -+ -You can update other key attributes: -. Set a new `enabled` value to disable the key, for example, `config.enabled=["false"]`. -. Set a new `priority` value to change the key's priority, for example, `config.priority=["110"]`. - -[discrete] -==== Deleting an old key - -. Ensure the key you are deleting is inactive and you have disabled it. This action is to prevent existing tokens held by applications and users from failing. -. Identify the key to delete. -+ -[options="nowrap"] ----- -$ kcadm.sh get keys -r demorealm ----- -. Use the `providerId` of the key to perform the delete. -+ -[options="nowrap"] ----- -$ kcadm.sh delete components/PROVIDER_ID -r demorealm ----- - -[discrete] -==== Configuring event logging for a realm - -Use the `update` command on the `events/config` endpoint. - -The `eventsListeners` attribute contains a list of EventListenerProviderFactory IDs, specifying all event listeners that receive events. Attributes are available that control built-in event storage, so you can query past events using the Admin REST API. {project_name} has separate control over the logging of service calls (`eventsEnabled`) and the auditing events triggered by the Admin Console or Admin REST API (`adminEventsEnabled`). You can set up the `eventsExpiration` event to expire to prevent your database from filling. {project_name} sets `eventsExpiration` to time-to-live expressed in seconds. - -You can set up a built-in event listener that receives all events and logs the events through JBoss-logging. Using the `org.keycloak.events` logger, {project_name} logs error events as `WARN` and other events as `DEBUG`. - -For example: - -* Linux: -[options="nowrap"] ----- -$ kcadm.sh update events/config -r demorealm -s 'eventsListeners=["jboss-logging"]' ----- -* Windows: -[options="nowrap"] ----- -c:\> kcadm update events/config -r demorealm -s "eventsListeners=[\"jboss-logging\"]" ----- - -For example: - -You can turn on storage for all available ERROR events, not including auditing events, for two days so you can retrieve the events through Admin REST. - -* Linux: -[options="nowrap"] ----- -$ kcadm.sh update events/config -r demorealm -s eventsEnabled=true -s 'enabledEventTypes=["LOGIN_ERROR","REGISTER_ERROR","LOGOUT_ERROR","CODE_TO_TOKEN_ERROR","CLIENT_LOGIN_ERROR","FEDERATED_IDENTITY_LINK_ERROR","REMOVE_FEDERATED_IDENTITY_ERROR","UPDATE_EMAIL_ERROR","UPDATE_PROFILE_ERROR","UPDATE_PASSWORD_ERROR","UPDATE_TOTP_ERROR","VERIFY_EMAIL_ERROR","REMOVE_TOTP_ERROR","SEND_VERIFY_EMAIL_ERROR","SEND_RESET_PASSWORD_ERROR","SEND_IDENTITY_PROVIDER_LINK_ERROR","RESET_PASSWORD_ERROR","IDENTITY_PROVIDER_FIRST_LOGIN_ERROR","IDENTITY_PROVIDER_POST_LOGIN_ERROR","CUSTOM_REQUIRED_ACTION_ERROR","EXECUTE_ACTIONS_ERROR","CLIENT_REGISTER_ERROR","CLIENT_UPDATE_ERROR","CLIENT_DELETE_ERROR"]' -s eventsExpiration=172800 ----- -* Windows: -[options="nowrap"] ----- -c:\> kcadm update events/config -r demorealm -s eventsEnabled=true -s "enabledEventTypes=[\"LOGIN_ERROR\",\"REGISTER_ERROR\",\"LOGOUT_ERROR\",\"CODE_TO_TOKEN_ERROR\",\"CLIENT_LOGIN_ERROR\",\"FEDERATED_IDENTITY_LINK_ERROR\",\"REMOVE_FEDERATED_IDENTITY_ERROR\",\"UPDATE_EMAIL_ERROR\",\"UPDATE_PROFILE_ERROR\",\"UPDATE_PASSWORD_ERROR\",\"UPDATE_TOTP_ERROR\",\"VERIFY_EMAIL_ERROR\",\"REMOVE_TOTP_ERROR\",\"SEND_VERIFY_EMAIL_ERROR\",\"SEND_RESET_PASSWORD_ERROR\",\"SEND_IDENTITY_PROVIDER_LINK_ERROR\",\"RESET_PASSWORD_ERROR\",\"IDENTITY_PROVIDER_FIRST_LOGIN_ERROR\",\"IDENTITY_PROVIDER_POST_LOGIN_ERROR\",\"CUSTOM_REQUIRED_ACTION_ERROR\",\"EXECUTE_ACTIONS_ERROR\",\"CLIENT_REGISTER_ERROR\",\"CLIENT_UPDATE_ERROR\",\"CLIENT_DELETE_ERROR\"]" -s eventsExpiration=172800 ----- - -You can reset stored event types to *all available event types*. Setting the value to an empty list is the same as enumerating all. -[options="nowrap"] ----- -$ kcadm.sh update events/config -r demorealm -s enabledEventTypes=[] ----- - -You can enable storage of auditing events. -[options="nowrap"] ----- -$ kcadm.sh update events/config -r demorealm -s adminEventsEnabled=true -s adminEventsDetailsEnabled=true ----- - -You can get the last 100 events. The events are ordered from newest to oldest. -[options="nowrap"] ----- -$ kcadm.sh get events --offset 0 --limit 100 ----- - -You can delete all saved events. -[options="nowrap"] ----- -$ kcadm delete events ----- - -[discrete] -==== Flushing the caches - -. Use the `create` command with one of these endpoints to clear caches: -* `clear-realm-cache` -* `clear-user-cache` -* `clear-keys-cache` - -. Set `realm` to the same value as the target realm. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh create clear-realm-cache -r demorealm -s realm=demorealm -$ kcadm.sh create clear-user-cache -r demorealm -s realm=demorealm -$ kcadm.sh create clear-keys-cache -r demorealm -s realm=demorealm ----- - -[discrete] -==== Importing a realm from exported .json file - -. Use the `create` command on the `partialImport` endpoint. -. Set `ifResourceExists` to `FAIL`, `SKIP`, or `OVERWRITE`. -. Use `-f` to submit the exported realm `.json` file. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh create partialImport -r demorealm2 -s ifResourceExists=FAIL -o -f demorealm.json ----- -+ -If the realm does not yet exist, create it first. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh create realms -s realm=demorealm2 -s enabled=true ----- - - -=== Role operations - -[discrete] -==== Creating a realm role - -Use the `roles` endpoint to create a realm role. - -[options="nowrap"] ----- -$ kcadm.sh create roles -r demorealm -s name=user -s 'description=Regular user with a limited set of permissions' ----- - -[discrete] -==== Creating a client role - -. Identify the client. -. Use the `get` command to list the available clients. -+ -[options="nowrap"] ----- -$ kcadm.sh get clients -r demorealm --fields id,clientId ----- -. Create a new role by using the `clientId` attribute to construct an endpoint URI, such as `clients/ID/roles`. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh create clients/a95b6af3-0bdc-4878-ae2e-6d61a4eca9a0/roles -r demorealm -s name=editor -s 'description=Editor can edit, and publish any article' ----- - -[discrete] -==== Listing realm roles - -Use the `get` command on the `roles` endpoint to list existing realm roles. -[options="nowrap"] ----- -$ kcadm.sh get roles -r demorealm ----- - -You can use the `get-roles` command also. -[options="nowrap"] ----- -$ kcadm.sh get-roles -r demorealm ----- - -[discrete] -==== Listing client roles - -{project_name} has a dedicated `get-roles` command to simplify the listing of realm and client roles. The command is an extension of the `get` command and behaves the same as the `get` command but with additional semantics for listing roles. - -Use the `get-roles` command by passing it the clientId (`--cclientid`) option or the `id` (`--cid`) option to identify the client to list client roles. - -For example: -[options="nowrap"] ----- -$ kcadm.sh get-roles -r demorealm --cclientid realm-management ----- - -[discrete] -==== Getting a specific realm role - -Use the `get` command and the role `name` to construct an endpoint URI for a specific realm role, `roles/ROLE_NAME`, where `user` is the existing role's name. - -For example: -[options="nowrap"] ----- -$ kcadm.sh get roles/user -r demorealm ----- - -You can use the `get-roles` command, passing it a role name (`--rolename` option) or ID (`--roleid` option). - -For example: -[options="nowrap"] ----- -$ kcadm.sh get-roles -r demorealm --rolename user ----- - -[discrete] -==== Getting a specific client role - -Use the `get-roles` command, passing it the clientId attribute (`--cclientid` option) or ID attribute (`--cid` option) to identify the client, and pass the role name (`--rolename` option) or the role ID attribute (`--roleid`) to identify a specific client role. - -For example: -[options="nowrap"] ----- -$ kcadm.sh get-roles -r demorealm --cclientid realm-management --rolename manage-clients ----- - -[discrete] -==== Updating a realm role - -Use the `update` command with the endpoint URI you used to get a specific realm role. - -For example: -[options="nowrap"] ----- -$ kcadm.sh update roles/user -r demorealm -s 'description=Role representing a regular user' ----- - -[discrete] -==== Updating a client role - -Use the `update` command with the endpoint URI that you used to get a specific client role. - -For example: -[options="nowrap"] ----- -$ kcadm.sh update clients/a95b6af3-0bdc-4878-ae2e-6d61a4eca9a0/roles/editor -r demorealm -s 'description=User that can edit, and publish articles' ----- - -[discrete] -==== Deleting a realm role - -Use the `delete` command with the endpoint URI that you used to get a specific realm role. - -For example: -[options="nowrap"] ----- -$ kcadm.sh delete roles/user -r demorealm ----- - -[discrete] -==== Deleting a client role - -Use the `delete` command with the endpoint URI that you used to get a specific client role. - -For example: -[options="nowrap"] ----- -$ kcadm.sh delete clients/a95b6af3-0bdc-4878-ae2e-6d61a4eca9a0/roles/editor -r demorealm ----- - -[discrete] -==== Listing assigned, available, and effective realm roles for a composite role - -Use the `get-roles` command to list assigned, available, and effective realm roles for a composite role. - -. To list *assigned* realm roles for the composite role, specify the target composite role by name (`--rname` option) or ID (`--rid` option). -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh get-roles -r demorealm --rname testrole ----- -. Use the `--effective` option to list *effective* realm roles. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh get-roles -r demorealm --rname testrole --effective ----- -. Use the `--available` option to list realm roles that you can add to the composite role. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh get-roles -r demorealm --rname testrole --available ----- - -[discrete] -==== Listing assigned, available, and effective client roles for a composite role - -Use the `get-roles` command to list assigned, available, and effective client roles for a composite role. - -. To list *assigned* client roles for the composite role, you can specify the target composite role by name (`--rname` option) or ID (`--rid` option) and client by the clientId attribute (`--cclientid` option) or ID (`--cid` option). -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh get-roles -r demorealm --rname testrole --cclientid realm-management ----- -. Use the `--effective` option to list *effective* realm roles. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh get-roles -r demorealm --rname testrole --cclientid realm-management --effective ----- -. Use the `--available` option to list realm roles that you can add to the target composite role. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh get-roles -r demorealm --rname testrole --cclientid realm-management --available ----- - -[discrete] -==== Adding realm roles to a composite role - -{project_name} provides an `add-roles` command for adding realm roles and client roles. - -This example adds the `user` role to the composite role `testrole`. -[options="nowrap"] ----- -$ kcadm.sh add-roles --rname testrole --rolename user -r demorealm ----- - -[discrete] -==== Removing realm roles from a composite role - -{project_name} provides a `remove-roles` command for removing realm roles and client roles. - -The following example removes the `user` role from the target composite role `testrole`. -[options="nowrap"] ----- -$ kcadm.sh remove-roles --rname testrole --rolename user -r demorealm ----- - -[discrete] -==== Adding client roles to a realm role - -{project_name} provides an `add-roles` command for adding realm roles and client roles. - -The following example adds the roles defined on the client `realm-management`, `create-client`, and `view-users`, to the `testrole` composite role. -[options="nowrap"] ----- -$ kcadm.sh add-roles -r demorealm --rname testrole --cclientid realm-management --rolename create-client --rolename view-users ----- - -[discrete] -==== Adding client roles to a client role - -. Determine the ID of the composite client role by using the `get-roles` command. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh get-roles -r demorealm --cclientid test-client --rolename operations ----- -. Assume that a client exists with a clientId attribute named `test-client`, a client role named `support`, and a client role named `operations` which becomes a composite role that has an ID of "fc400897-ef6a-4e8c-872b-1581b7fa8a71". -. Use the following example to add another role to the composite role. -+ -[options="nowrap"] ----- -$ kcadm.sh add-roles -r demorealm --cclientid test-client --rid fc400897-ef6a-4e8c-872b-1581b7fa8a71 --rolename support ----- -. List the roles of a composite role by using the `get-roles --all` command. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh get-roles --rid fc400897-ef6a-4e8c-872b-1581b7fa8a71 --all ----- - -[discrete] -==== Removing client roles from a composite role - -Use the `remove-roles` command to remove client roles from a composite role. - -Use the following example to remove two roles defined on the client `realm-management`, the `create-client` role and the `view-users` role, from the `testrole` composite role. -[options="nowrap"] ----- -$ kcadm.sh remove-roles -r demorealm --rname testrole --cclientid realm-management --rolename create-client --rolename view-users ----- - -[discrete] -==== Adding client roles to a group - -Use the `add-roles` command to add realm roles and client roles. - -The following example adds the roles defined on the client `realm-management`, `create-client` and `view-users`, to the `Group` group (`--gname` option). Alternatively, you can specify the group by ID (`--gid` option). - -See <<_group_operations, Group operations>> for more information. -[options="nowrap"] ----- -$ kcadm.sh add-roles -r demorealm --gname Group --cclientid realm-management --rolename create-client --rolename view-users ----- - -[discrete] -==== Removing client roles from a group - -Use the `remove-roles` command to remove client roles from a group. - -The following example removes two roles defined on the client `realm management`, `create-client` and `view-users`, from the `Group` group. - -See <<_group_operations, Group operations>> for more information. -[options="nowrap"] ----- -$ kcadm.sh remove-roles -r demorealm --gname Group --cclientid realm-management --rolename create-client --rolename view-users ----- - - -=== Client operations - -[discrete] -==== Creating a client - -. Run the `create` command on a `clients` endpoint to create a new client. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh create clients -r demorealm -s clientId=myapp -s enabled=true ----- -. Specify a secret if to set a secret for adapters to authenticate. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh create clients -r demorealm -s clientId=myapp -s enabled=true -s clientAuthenticatorType=client-secret -s secret=d0b8122f-8dfb-46b7-b68a-f5cc4e25d000 ----- - -[discrete] -==== Listing clients - -Use the `get` command on the `clients` endpoint to list clients. - -This example filters the output to list only the `id` and `clientId` attributes: -[options="nowrap"] ----- -$ kcadm.sh get clients -r demorealm --fields id,clientId ----- - -[discrete] -==== Getting a specific client - -Use the client ID to construct an endpoint URI that targets a specific client, such as `clients/ID`. - -For example: -[options="nowrap"] ----- -$ kcadm.sh get clients/c7b8547f-e748-4333-95d0-410b76b3f4a3 -r demorealm ----- - -[discrete] -==== Getting the current secret for a specific client - -Use the client ID to construct an endpoint URI, such as `clients/ID/client-secret`. - -For example: -[options="nowrap"] ----- -$ kcadm.sh get clients/$CID/client-secret ----- - -[discrete] -==== Generate a new secret for a specific client - -Use the client ID to construct an endpoint URI, such as `clients/ID/client-secret`. - -For example: -[options="nowrap"] ----- -$ kcadm.sh create clients/$CID/client-secret ----- - -[discrete] -==== Updating the current secret for a specific client - -Use the client ID to construct an endpoint URI, such as `clients/ID`. - -For example: -[options="nowrap"] ----- -$ kcadm.sh update clients/$CID -s "secret=newSecret" ----- - -[discrete] -==== Getting an adapter configuration file (keycloak.json) for a specific client - -Use the client ID to construct an endpoint URI that targets a specific client, such as `clients/ID/installation/providers/keycloak-oidc-keycloak-json`. - -For example: -[options="nowrap"] ----- -$ kcadm.sh get clients/c7b8547f-e748-4333-95d0-410b76b3f4a3/installation/providers/keycloak-oidc-keycloak-json -r demorealm ----- - -[discrete] -==== Getting a WildFly subsystem adapter configuration for a specific client - -Use the client ID to construct an endpoint URI that targets a specific client, such as `clients/ID/installation/providers/keycloak-oidc-jboss-subsystem`. - -For example: -[options="nowrap"] ----- -$ kcadm.sh get clients/c7b8547f-e748-4333-95d0-410b76b3f4a3/installation/providers/keycloak-oidc-jboss-subsystem -r demorealm ----- - -[discrete] -==== Getting a Docker-v2 example configuration for a specific client - -Use the client ID to construct an endpoint URI that targets a specific client, such as `clients/ID/installation/providers/docker-v2-compose-yaml`. - -The response is in `.zip` format. - -For example: -[options="nowrap",subs="attributes+"] ----- -$ kcadm.sh get http://localhost:8080{kc_admins_path}/realms/demorealm/clients/8f271c35-44e3-446f-8953-b0893810ebe7/installation/providers/docker-v2-compose-yaml -r demorealm > keycloak-docker-compose-yaml.zip ----- - -[discrete] -==== Updating a client - -Use the `update` command with the same endpoint URI that you use to get a specific client. - -For example: - -* Linux: -[options="nowrap"] ----- -$ kcadm.sh update clients/c7b8547f-e748-4333-95d0-410b76b3f4a3 -r demorealm -s enabled=false -s publicClient=true -s 'redirectUris=["http://localhost:8080/myapp/*"]' -s baseUrl=http://localhost:8080/myapp -s adminUrl=http://localhost:8080/myapp ----- -* Windows: -[options="nowrap"] ----- -c:\> kcadm update clients/c7b8547f-e748-4333-95d0-410b76b3f4a3 -r demorealm -s enabled=false -s publicClient=true -s "redirectUris=[\"http://localhost:8080/myapp/*\"]" -s baseUrl=http://localhost:8080/myapp -s adminUrl=http://localhost:8080/myapp ----- - -[discrete] -==== Deleting a client - -Use the `delete` command with the same endpoint URI that you use to get a specific client. - -For example: -[options="nowrap"] ----- -$ kcadm.sh delete clients/c7b8547f-e748-4333-95d0-410b76b3f4a3 -r demorealm ----- - -[discrete] -==== Adding or removing roles for client's service account - -A client's service account is a user account with username `service-account-CLIENT_ID`. You can perform the same user operations on this account as a regular account. - - -=== User operations - -[discrete] -==== Creating a user - -Run the `create` command on the `users` endpoint to create a new user. - -For example: -[options="nowrap"] ----- -$ kcadm.sh create users -r demorealm -s username=testuser -s enabled=true ----- - -[discrete] -==== Listing users - -Use the `users` endpoint to list users. The target user must change their password the next time they log in. - -For example: -[options="nowrap"] ----- -$ kcadm.sh get users -r demorealm --offset 0 --limit 1000 ----- -You can filter users by `username`, `firstName`, `lastName`, or `email`. - -For example: -[options="nowrap"] ----- -$ kcadm.sh get users -r demorealm -q email=google.com -$ kcadm.sh get users -r demorealm -q username=testuser ----- -[NOTE] -==== -Filtering does not use exact matching. This example matches the value of the `username` attribute against the `\*testuser*` pattern. -==== - -You can filter across multiple attributes by specifying multiple `-q` options. {project_name} returns users that match the condition for all the attributes only. - -[discrete] -==== Getting a specific user - -Use the user ID to compose an endpoint URI, such as `users/USER_ID`. - -For example: -[options="nowrap"] ----- -$ kcadm.sh get users/0ba7a3fd-6fd8-48cd-a60b-2e8fd82d56e2 -r demorealm ----- - -[discrete] -==== Updating a user - -Use the `update` command with the same endpoint URI that you use to get a specific user. - -For example: - -* Linux: -[options="nowrap"] ----- -$ kcadm.sh update users/0ba7a3fd-6fd8-48cd-a60b-2e8fd82d56e2 -r demorealm -s 'requiredActions=["VERIFY_EMAIL","UPDATE_PROFILE","CONFIGURE_TOTP","UPDATE_PASSWORD"]' ----- -* Windows: -[options="nowrap"] ----- -c:\> kcadm update users/0ba7a3fd-6fd8-48cd-a60b-2e8fd82d56e2 -r demorealm -s "requiredActions=[\"VERIFY_EMAIL\",\"UPDATE_PROFILE\",\"CONFIGURE_TOTP\",\"UPDATE_PASSWORD\"]" ----- - -[discrete] -==== Deleting a user - -Use the `delete` command with the same endpoint URI that you use to get a specific user. - -For example: -[options="nowrap"] ----- -$ kcadm.sh delete users/0ba7a3fd-6fd8-48cd-a60b-2e8fd82d56e2 -r demorealm ----- - -[discrete] -==== Resetting a user's password - -Use the dedicated `set-password` command to reset a user's password. - -For example: -[options="nowrap"] ----- -$ kcadm.sh set-password -r demorealm --username testuser --new-password NEWPASSWORD --temporary ----- -This command sets a temporary password for the user. The target user must change the password the next time they log in. - -You can use `--userid` to specify the user by using the `id` attribute. - -You can achieve the same result using the `update` command on an endpoint constructed from the one you used to get a specific user, such as `users/USER_ID/reset-password`. - -For example: -[options="nowrap"] ----- -$ kcadm.sh update users/0ba7a3fd-6fd8-48cd-a60b-2e8fd82d56e2/reset-password -r demorealm -s type=password -s value=NEWPASSWORD -s temporary=true -n ----- -The `-n` parameter ensures that {project_name} performs the `PUT` command without performing a `GET` command before the `PUT` command. This is necessary because the `reset-password` endpoint does not support `GET`. - -[discrete] -==== Listing assigned, available, and effective realm roles for a user - -You can use a `get-roles` command to list assigned, available, and effective realm roles for a user. - -. Specify the target user by user name or ID to list the user's *assigned* realm roles. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh get-roles -r demorealm --uusername testuser ----- -. Use the `--effective` option to list *effective* realm roles. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh get-roles -r demorealm --uusername testuser --effective ----- -. Use the `--available` option to list realm roles that you can add to a user. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh get-roles -r demorealm --uusername testuser --available ----- - -[discrete] -==== Listing assigned, available, and effective client roles for a user - -Use a `get-roles` command to list assigned, available, and effective client roles for a user. - -. Specify the target user by user name (`--uusername` option) or ID (`--uid` option) and client by a clientId attribute (`--cclientid` option) or an ID (`--cid` option) to list *assigned* client roles for the user. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh get-roles -r demorealm --uusername testuser --cclientid realm-management ----- -. Use the `--effective` option to list *effective* realm roles. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh get-roles -r demorealm --uusername testuser --cclientid realm-management --effective ----- -. Use the `--available` option to list realm roles that you can add to a user. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh get-roles -r demorealm --uusername testuser --cclientid realm-management --available ----- - -[discrete] -==== Adding realm roles to a user - -Use an `add-roles` command to add realm roles to a user. - -Use the following example to add the `user` role to user `testuser`: -[options="nowrap"] ----- -$ kcadm.sh add-roles --uusername testuser --rolename user -r demorealm ----- - -[discrete] -==== Removing realm roles from a user - -Use a `remove-roles` command to remove realm roles from a user. - -Use the following example to remove the `user` role from the user `testuser`: -[options="nowrap"] ----- -$ kcadm.sh remove-roles --uusername testuser --rolename user -r demorealm ----- - -[discrete] -==== Adding client roles to a user - -Use an `add-roles` command to add client roles to a user. - -Use the following example to add two roles defined on the client `realm management`, the `create-client` role and the `view-users` role, to the user `testuser`. -[options="nowrap"] ----- -$ kcadm.sh add-roles -r demorealm --uusername testuser --cclientid realm-management --rolename create-client --rolename view-users ----- - -[discrete] -==== Removing client roles from a user - -Use a `remove-roles` command to remove client roles from a user. - -Use the following example to remove two roles defined on the realm management client: -[options="nowrap"] ----- -$ kcadm.sh remove-roles -r demorealm --uusername testuser --cclientid realm-management --rolename create-client --rolename view-users ----- - -[discrete] -==== Listing a user's sessions - -. Identify the user's ID, -. Use the ID to compose an endpoint URI, such as `users/ID/sessions`. -. Use the `get` command to retrieve a list of the user's sessions. -+ -For example: -+ -[options="nowrap"] ----- -$kcadm get users/6da5ab89-3397-4205-afaa-e201ff638f9e/sessions ----- - -[discrete] -==== Logging out a user from a specific session - -. Determine the session's ID as described earlier. -. Use the session's ID to compose an endpoint URI, such as `sessions/ID`. -. Use the `delete` command to invalidate the session. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh delete sessions/d0eaa7cc-8c5d-489d-811a-69d3c4ec84d1 ----- - -[discrete] -==== Logging out a user from all sessions - -Use the user's ID to construct an endpoint URI, such as `users/ID/logout`. - -Use the `create` command to perform `POST` on that endpoint URI. - -For example: -[options="nowrap"] ----- -$ kcadm.sh create users/6da5ab89-3397-4205-afaa-e201ff638f9e/logout -r demorealm -s realm=demorealm -s user=6da5ab89-3397-4205-afaa-e201ff638f9e ----- - -[[_group_operations]] -=== Group operations - -[discrete] -==== Creating a group - -Use the `create` command on the `groups` endpoint to create a new group. - -For example: -[options="nowrap"] ----- -$ kcadm.sh create groups -r demorealm -s name=Group ----- - -[discrete] -==== Listing groups - -Use the `get` command on the `groups` endpoint to list groups. - -For example: -[options="nowrap"] ----- -$ kcadm.sh get groups -r demorealm ----- - -[discrete] -==== Getting a specific group - -Use the group's ID to construct an endpoint URI, such as `groups/GROUP_ID`. - -For example: -[options="nowrap"] ----- -$ kcadm.sh get groups/51204821-0580-46db-8f2d-27106c6b5ded -r demorealm ----- - -[discrete] -==== Updating a group - -Use the `update` command with the same endpoint URI that you use to get a specific group. - -For example: -[options="nowrap"] ----- -$ kcadm.sh update groups/51204821-0580-46db-8f2d-27106c6b5ded -s 'attributes.email=["group@example.com"]' -r demorealm ----- - -[discrete] -==== Deleting a group - -Use the `delete` command with the same endpoint URI that you use to get a specific group. - -For example: -[options="nowrap"] ----- -$ kcadm.sh delete groups/51204821-0580-46db-8f2d-27106c6b5ded -r demorealm ----- - -[discrete] -==== Creating a subgroup - -Find the ID of the parent group by listing groups. Use that ID to construct an endpoint URI, such as `groups/GROUP_ID/children`. - -For example: -[options="nowrap"] ----- -$ kcadm.sh create groups/51204821-0580-46db-8f2d-27106c6b5ded/children -r demorealm -s name=SubGroup ----- - -[discrete] -==== Moving a group under another group - -. Find the ID of an existing parent group and the ID of an existing child group. -. Use the parent group's ID to construct an endpoint URI, such as `groups/PARENT_GROUP_ID/children`. -. Run the `create` command on this endpoint and pass the child group's ID as a JSON body. - -For example: -[options="nowrap"] ----- -$ kcadm.sh create groups/51204821-0580-46db-8f2d-27106c6b5ded/children -r demorealm -s id=08d410c6-d585-4059-bb07-54dcb92c5094 -s name=SubGroup ----- - -[discrete] -==== Get groups for a specific user - -Use a user's ID to determine a user's membership in groups to compose an endpoint URI, such as `users/USER_ID/groups`. - -For example: -[options="nowrap"] ----- -$ kcadm.sh get users/b544f379-5fc4-49e5-8a8d-5cfb71f46f53/groups -r demorealm ----- - -[discrete] -==== Adding a user to a group - -Use the `update` command with an endpoint URI composed of a user's ID and a group's ID, such as `users/USER_ID/groups/GROUP_ID`, to add a user to a group. - -For example: -[options="nowrap"] ----- -$ kcadm.sh update users/b544f379-5fc4-49e5-8a8d-5cfb71f46f53/groups/ce01117a-7426-4670-a29a-5c118056fe20 -r demorealm -s realm=demorealm -s userId=b544f379-5fc4-49e5-8a8d-5cfb71f46f53 -s groupId=ce01117a-7426-4670-a29a-5c118056fe20 -n ----- - -[discrete] -==== Removing a user from a group - -Use the `delete` command on the same endpoint URI you use for adding a user to a group, such as `users/USER_ID/groups/GROUP_ID`, to remove a user from a group. - -For example: -[options="nowrap"] ----- -$ kcadm.sh delete users/b544f379-5fc4-49e5-8a8d-5cfb71f46f53/groups/ce01117a-7426-4670-a29a-5c118056fe20 -r demorealm ----- - -[discrete] -==== Listing assigned, available, and effective realm roles for a group - -Use a dedicated `get-roles` command to list assigned, available, and effective realm roles for a group. - -. Specify the target group by name (`--gname` option), path (`--gpath` option), or ID (`--gid` option) to list *assigned* realm roles for the group. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh get-roles -r demorealm --gname Group ----- -. Use the `--effective` option to list *effective* realm roles. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh get-roles -r demorealm --gname Group --effective ----- -. Use the `--available` option to list realm roles that you can add to the group. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh get-roles -r demorealm --gname Group --available ----- - -[discrete] -==== Listing assigned, available, and effective client roles for a group - -Use the `get-roles` command to list assigned, available, and effective client roles for a group. - -. Specify the target group by name (`--gname` option) or ID (`--gid` option), -. Specify the client by the clientId attribute (`--cclientid` option) or ID (`--id` option) to list *assigned* client roles for the user. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh get-roles -r demorealm --gname Group --cclientid realm-management ----- -. Use the `--effective` option to list *effective* realm roles. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh get-roles -r demorealm --gname Group --cclientid realm-management --effective ----- -. Use the `--available` option to list realm roles that you can still add to the group. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh get-roles -r demorealm --gname Group --cclientid realm-management --available ----- - - -=== Identity provider operations - -[discrete] -==== Listing available identity providers - -Use the `serverinfo` endpoint to list available identity providers. - -For example: -[options="nowrap"] ----- -$ kcadm.sh get serverinfo -r demorealm --fields 'identityProviders(*)' ----- - -[NOTE] -==== -{project_name} processes the `serverinfo` endpoint similarly to the `realms` endpoint. {project_name} does not resolve the endpoint relative to a target realm because it exists outside any specific realm. -==== - -[discrete] -==== Listing configured identity providers - -Use the `identity-provider/instances` endpoint. - -For example: -[options="nowrap"] ----- -$ kcadm.sh get identity-provider/instances -r demorealm --fields alias,providerId,enabled ----- - -[discrete] -==== Getting a specific configured identity provider - -Use the identity provider's `alias` attribute to construct an endpoint URI, such as `identity-provider/instances/ALIAS`, to get a specific identity provider. - -For example: -[options="nowrap"] ----- -$ kcadm.sh get identity-provider/instances/facebook -r demorealm ----- - -[discrete] -==== Removing a specific configured identity provider - -Use the `delete` command with the same endpoint URI that you use to get a specific configured identity provider to remove a specific configured identity provider. - -For example: -[options="nowrap"] ----- -$ kcadm.sh delete identity-provider/instances/facebook -r demorealm ----- - -[discrete] -==== Configuring a Keycloak OpenID Connect identity provider - -. Use `keycloak-oidc` as the `providerId` when you create a new identity provider instance. -. Provide the `config` attributes: `authorizationUrl`, `tokenUrl`, `clientId`, and `clientSecret`. -+ -For example: -+ -[options="nowrap",subs=+attributes] ----- -$ kcadm.sh create identity-provider/instances -r demorealm -s alias=keycloak-oidc -s providerId=keycloak-oidc -s enabled=true -s 'config.useJwksUrl="true"' -s config.authorizationUrl=http://localhost:8180{kc_realms_path}/demorealm/protocol/openid-connect/auth -s config.tokenUrl=http://localhost:8180{kc_realms_path}/demorealm/protocol/openid-connect/token -s config.clientId=demo-oidc-provider -s config.clientSecret=secret ----- - -[discrete] -==== Configuring an OpenID Connect identity provider - -Configure the generic OpenID Connect provider the same way you configure the Keycloak OpenID Connect provider, except you set the `providerId` attribute value to `oidc`. - -[discrete] -==== Configuring a SAML 2 identity provider - -. Use `saml` as the `providerId`. -. Provide the `config` attributes: `singleSignOnServiceUrl`, `nameIDPolicyFormat`, and `signatureAlgorithm`. - -For example: -[options="nowrap",subs=+attributes] ----- -$ kcadm.sh create identity-provider/instances -r demorealm -s alias=saml -s providerId=saml -s enabled=true -s 'config.useJwksUrl="true"' -s config.singleSignOnServiceUrl=http://localhost:8180{kc_realms_path}/saml-broker-realm/protocol/saml -s config.nameIDPolicyFormat=urn:oasis:names:tc:SAML:2.0:nameid-format:persistent -s config.signatureAlgorithm=RSA_SHA256 ----- - -[discrete] -==== Configuring a Facebook identity provider - -. Use `facebook` as the `providerId`. -. Provide the `config` attributes: `clientId` and `clientSecret`. You can find these attributes in the Facebook Developers application configuration page for your application. See the <<_facebook, Facebook identity broker>> page for more information. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh create identity-provider/instances -r demorealm -s alias=facebook -s providerId=facebook -s enabled=true -s 'config.useJwksUrl="true"' -s config.clientId=FACEBOOK_CLIENT_ID -s config.clientSecret=FACEBOOK_CLIENT_SECRET ----- - -[discrete] -==== Configuring a Google identity provider - -. Use `google` as the `providerId`. -. Provide the `config` attributes: `clientId` and `clientSecret`. You can find these attributes in the Google Developers application configuration page for your application. See the <<_google, Google identity broker>> page for more information. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh create identity-provider/instances -r demorealm -s alias=google -s providerId=google -s enabled=true -s 'config.useJwksUrl="true"' -s config.clientId=GOOGLE_CLIENT_ID -s config.clientSecret=GOOGLE_CLIENT_SECRET ----- - -[discrete] -==== Configuring a Twitter identity provider - -. Use `twitter` as the `providerId`. -. Provide the `config` attributes `clientId` and `clientSecret`. You can find these attributes in the Twitter Application Management application configuration page for your application. See the <<_twitter, Twitter identity broker>> page for more information. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh create identity-provider/instances -r demorealm -s alias=google -s providerId=google -s enabled=true -s 'config.useJwksUrl="true"' -s config.clientId=TWITTER_API_KEY -s config.clientSecret=TWITTER_API_SECRET ----- - -[discrete] -==== Configuring a GitHub identity provider - -. Use `github` as the `providerId`. -. Provide the `config` attributes `clientId` and `clientSecret`. You can find these attributes in the GitHub Developer Application Settings page for your application. See the <<_github, GitHub identity broker>> page for more information. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh create identity-provider/instances -r demorealm -s alias=github -s providerId=github -s enabled=true -s 'config.useJwksUrl="true"' -s config.clientId=GITHUB_CLIENT_ID -s config.clientSecret=GITHUB_CLIENT_SECRET ----- - -[discrete] -==== Configuring a LinkedIn identity provider - -. Use `linkedin` as the `providerId`. -. Provide the `config` attributes `clientId` and `clientSecret`. You can find these attributes in the LinkedIn Developer Console application page for your application. See the <<_linkedin, LinkedIn identity broker>> page for more information. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh create identity-provider/instances -r demorealm -s alias=linkedin -s providerId=linkedin -s enabled=true -s 'config.useJwksUrl="true"' -s config.clientId=LINKEDIN_CLIENT_ID -s config.clientSecret=LINKEDIN_CLIENT_SECRET ----- - -[discrete] -==== Configuring a Microsoft Live identity provider - -. Use `microsoft` as the `providerId`. -. Provide the `config` attributes `clientId` and `clientSecret`. You can find these attributes in the Microsoft Application Registration Portal page for your application. See the <<_microsoft, Microsoft identity broker>> page for more information. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh create identity-provider/instances -r demorealm -s alias=microsoft -s providerId=microsoft -s enabled=true -s 'config.useJwksUrl="true"' -s config.clientId=MICROSOFT_APP_ID -s config.clientSecret=MICROSOFT_PASSWORD ----- - -[discrete] -==== Configuring a Stack Overflow identity provider - -. Use `stackoverflow` command as the `providerId`. -. Provide the `config` attributes `clientId`, `clientSecret`, and `key`. You can find these attributes in the Stack Apps OAuth page for your application. See the <<_stackoverflow, Stack Overflow identity broker>> page for more information. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh create identity-provider/instances -r demorealm -s alias=stackoverflow -s providerId=stackoverflow -s enabled=true -s 'config.useJwksUrl="true"' -s config.clientId=STACKAPPS_CLIENT_ID -s config.clientSecret=STACKAPPS_CLIENT_SECRET -s config.key=STACKAPPS_KEY ----- - - -=== Storage provider operations - -[discrete] -==== Configuring a Kerberos storage provider - -. Use the `create` command against the `components` endpoint. -. Specify the realm id as a value of the `parentId` attribute. -. Specify `kerberos` as the value of the `providerId` attribute, and `org.keycloak.storage.UserStorageProvider` as the value of the `providerType` attribute. -. For example: -+ -[options="nowrap"] ----- -$ kcadm.sh create components -r demorealm -s parentId=demorealmId -s id=demokerberos -s name=demokerberos -s providerId=kerberos -s providerType=org.keycloak.storage.UserStorageProvider -s 'config.priority=["0"]' -s 'config.debug=["false"]' -s 'config.allowPasswordAuthentication=["true"]' -s 'config.editMode=["UNSYNCED"]' -s 'config.updateProfileFirstLogin=["true"]' -s 'config.allowKerberosAuthentication=["true"]' -s 'config.kerberosRealm=["KEYCLOAK.ORG"]' -s 'config.keyTab=["http.keytab"]' -s 'config.serverPrincipal=["HTTP/localhost@KEYCLOAK.ORG"]' -s 'config.cachePolicy=["DEFAULT"]' ----- - -[discrete] -==== Configuring an LDAP user storage provider - -. Use the `create` command against the `components` endpoint. -. Specify `ldap` as the value of the `providerId` attribute, and `org.keycloak.storage.UserStorageProvider` as the value of the `providerType` attribute. -. Provide the realm ID as the value of the `parentId` attribute. -. Use the following example to create a Kerberos-integrated LDAP provider. -+ -[options="nowrap"] ----- -$ kcadm.sh create components -r demorealm -s name=kerberos-ldap-provider -s providerId=ldap -s providerType=org.keycloak.storage.UserStorageProvider -s parentId=3d9c572b-8f33-483f-98a6-8bb421667867 -s 'config.priority=["1"]' -s 'config.fullSyncPeriod=["-1"]' -s 'config.changedSyncPeriod=["-1"]' -s 'config.cachePolicy=["DEFAULT"]' -s config.evictionDay=[] -s config.evictionHour=[] -s config.evictionMinute=[] -s config.maxLifespan=[] -s 'config.batchSizeForSync=["1000"]' -s 'config.editMode=["WRITABLE"]' -s 'config.syncRegistrations=["false"]' -s 'config.vendor=["other"]' -s 'config.usernameLDAPAttribute=["uid"]' -s 'config.rdnLDAPAttribute=["uid"]' -s 'config.uuidLDAPAttribute=["entryUUID"]' -s 'config.userObjectClasses=["inetOrgPerson, organizationalPerson"]' -s 'config.connectionUrl=["ldap://localhost:10389"]' -s 'config.usersDn=["ou=People,dc=keycloak,dc=org"]' -s 'config.authType=["simple"]' -s 'config.bindDn=["uid=admin,ou=system"]' -s 'config.bindCredential=["secret"]' -s 'config.searchScope=["1"]' -s 'config.useTruststoreSpi=["ldapsOnly"]' -s 'config.connectionPooling=["true"]' -s 'config.pagination=["true"]' -s 'config.allowKerberosAuthentication=["true"]' -s 'config.serverPrincipal=["HTTP/localhost@KEYCLOAK.ORG"]' -s 'config.keyTab=["http.keytab"]' -s 'config.kerberosRealm=["KEYCLOAK.ORG"]' -s 'config.debug=["true"]' -s 'config.useKerberosForPasswordAuthentication=["true"]' ----- - -[discrete] -==== Removing a user storage provider instance - -. Use the storage provider instance's `id` attribute to compose an endpoint URI, such as `components/ID`. -. Run the `delete` command against this endpoint. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh delete components/3d9c572b-8f33-483f-98a6-8bb421667867 -r demorealm ----- - -[discrete] -==== Triggering synchronization of all users for a specific user storage provider - -. Use the storage provider's `id` attribute to compose an endpoint URI, such as `user-storage/ID_OF_USER_STORAGE_INSTANCE/sync`. -. Add the `action=triggerFullSync` query parameter. -. Run the `create` command. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh create user-storage/b7c63d02-b62a-4fc1-977c-947d6a09e1ea/sync?action=triggerFullSync ----- - -[discrete] -==== Triggering synchronization of changed users for a specific user storage provider - -. Use the storage provider's `id` attribute to compose an endpoint URI, such as `user-storage/ID_OF_USER_STORAGE_INSTANCE/sync`. -. Add the `action=triggerChangedUsersSync` query parameter. -. Run the `create` command. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh create user-storage/b7c63d02-b62a-4fc1-977c-947d6a09e1ea/sync?action=triggerChangedUsersSync ----- - -[discrete] -==== Test LDAP user storage connectivity - -. Run the `get` command on the `testLDAPConnection` endpoint. -. Provide query parameters `bindCredential`, `bindDn`, `connectionUrl`, and `useTruststoreSpi`. -. Set the `action` query parameter to `testConnection`. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh create testLDAPConnection -s action=testConnection -s bindCredential=secret -s bindDn=uid=admin,ou=system -s connectionUrl=ldap://localhost:10389 -s useTruststoreSpi=ldapsOnly ----- - -[discrete] -==== Test LDAP user storage authentication - -. Run the `get` command on the `testLDAPConnection` endpoint. -. Provide the query parameters `bindCredential`, `bindDn`, `connectionUrl`, and `useTruststoreSpi`. -. Set the `action` query parameter to `testAuthentication`. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh create testLDAPConnection -s action=testAuthentication -s bindCredential=secret -s bindDn=uid=admin,ou=system -s connectionUrl=ldap://localhost:10389 -s useTruststoreSpi=ldapsOnly ----- - - -=== Adding mappers - -[discrete] -==== Adding a hard-coded role LDAP mapper - -. Run the `create` command on the `components` endpoint. -. Set the `providerType` attribute to `org.keycloak.storage.ldap.mappers.LDAPStorageMapper`. -. Set the `parentId` attribute to the ID of the LDAP provider instance. -. Set the `providerId` attribute to `hardcoded-ldap-role-mapper`. Ensure you provide a value of `role` configuration parameter. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh create components -r demorealm -s name=hardcoded-ldap-role-mapper -s providerId=hardcoded-ldap-role-mapper -s providerType=org.keycloak.storage.ldap.mappers.LDAPStorageMapper -s parentId=b7c63d02-b62a-4fc1-977c-947d6a09e1ea -s 'config.role=["realm-management.create-client"]' ----- - -[discrete] -==== Adding an MS Active Directory mapper - -. Run the `create` command on the `components` endpoint. -. Set the `providerType` attribute to `org.keycloak.storage.ldap.mappers.LDAPStorageMapper`. -. Set the `parentId` attribute to the ID of the LDAP provider instance. -. Set the `providerId` attribute to `msad-user-account-control-mapper`. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh create components -r demorealm -s name=msad-user-account-control-mapper -s providerId=msad-user-account-control-mapper -s providerType=org.keycloak.storage.ldap.mappers.LDAPStorageMapper -s parentId=b7c63d02-b62a-4fc1-977c-947d6a09e1ea ----- - -[discrete] -==== Adding a user attribute LDAP mapper - -. Run the `create` command on the `components` endpoint. -. Set the `providerType` attribute to `org.keycloak.storage.ldap.mappers.LDAPStorageMapper`. -. Set the `parentId` attribute to the ID of the LDAP provider instance. -. Set the `providerId` attribute to `user-attribute-ldap-mapper`. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh create components -r demorealm -s name=user-attribute-ldap-mapper -s providerId=user-attribute-ldap-mapper -s providerType=org.keycloak.storage.ldap.mappers.LDAPStorageMapper -s parentId=b7c63d02-b62a-4fc1-977c-947d6a09e1ea -s 'config."user.model.attribute"=["email"]' -s 'config."ldap.attribute"=["mail"]' -s 'config."read.only"=["false"]' -s 'config."always.read.value.from.ldap"=["false"]' -s 'config."is.mandatory.in.ldap"=["false"]' ----- - -[discrete] -==== Adding a group LDAP mapper - -. Run the `create` command on the `components` endpoint. -. Set the `providerType` attribute to `org.keycloak.storage.ldap.mappers.LDAPStorageMapper`. -. Set the `parentId` attribute to the ID of the LDAP provider instance. -. Set the `providerId` attribute to `group-ldap-mapper`. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh create components -r demorealm -s name=group-ldap-mapper -s providerId=group-ldap-mapper -s providerType=org.keycloak.storage.ldap.mappers.LDAPStorageMapper -s parentId=b7c63d02-b62a-4fc1-977c-947d6a09e1ea -s 'config."groups.dn"=[]' -s 'config."group.name.ldap.attribute"=["cn"]' -s 'config."group.object.classes"=["groupOfNames"]' -s 'config."preserve.group.inheritance"=["true"]' -s 'config."membership.ldap.attribute"=["member"]' -s 'config."membership.attribute.type"=["DN"]' -s 'config."groups.ldap.filter"=[]' -s 'config.mode=["LDAP_ONLY"]' -s 'config."user.roles.retrieve.strategy"=["LOAD_GROUPS_BY_MEMBER_ATTRIBUTE"]' -s 'config."mapped.group.attributes"=["admins-group"]' -s 'config."drop.non.existing.groups.during.sync"=["false"]' -s 'config.roles=["admins"]' -s 'config.groups=["admins-group"]' -s 'config.group=[]' -s 'config.preserve=["true"]' -s 'config.membership=["member"]' ----- - -[discrete] -==== Adding a full name LDAP mapper - -. Run the `create` command on the `components` endpoint. -. Set the `providerType` attribute to `org.keycloak.storage.ldap.mappers.LDAPStorageMapper`. -. Set the `parentId` attribute to the ID of the LDAP provider instance. -. Set the `providerId` attribute to `full-name-ldap-mapper`. -+ -For example: -+ -[options="nowrap"] ----- -$ kcadm.sh create components -r demorealm -s name=full-name-ldap-mapper -s providerId=full-name-ldap-mapper -s providerType=org.keycloak.storage.ldap.mappers.LDAPStorageMapper -s parentId=b7c63d02-b62a-4fc1-977c-947d6a09e1ea -s 'config."ldap.full.name.attribute"=["cn"]' -s 'config."read.only"=["false"]' -s 'config."write.only"=["true"]' ----- - - -=== Authentication operations - -[discrete] -==== Setting a password policy - -. Set the realm's `passwordPolicy` attribute to an enumeration expression that includes the specific policy provider ID and optional configuration. -. Use the following example to set a password policy to default values. The default values include: - -* 27,500 hashing iterations -* at least one special character -* at least one uppercase character -* at least one digit character -* not be equal to a user's `username` -* be at least eight characters long -+ -[options="nowrap"] ----- -$ kcadm.sh update realms/demorealm -s 'passwordPolicy="hashIterations and specialChars and upperCase and digits and notUsername and length"' ----- -. To use values different from defaults, pass the configuration in brackets. -. Use the following example to set a password policy to: - -* 25,000 hash iterations -* at least two special characters -* at least two uppercase characters -* at least two lowercase characters -* at least two digits -* be at least nine characters long -* not be equal to a user's `username` -* not repeat for at least four changes back -+ -[options="nowrap"] ----- -$ kcadm.sh update realms/demorealm -s 'passwordPolicy="hashIterations(25000) and specialChars(2) and upperCase(2) and lowerCase(2) and digits(2) and length(9) and notUsername and passwordHistory(4)"' ----- - -[discrete] -==== Obtaining the current password policy - -You can get the current realm configuration by filtering all output except for the `passwordPolicy` attribute. - -For example, display `passwordPolicy` for `demorealm`. -[options="nowrap"] ----- -$ kcadm.sh get realms/demorealm --fields passwordPolicy ----- - -[discrete] -==== Listing authentication flows - -Run the `get` command on the `authentication/flows` endpoint. - -For example: -[options="nowrap"] ----- -$ kcadm.sh get authentication/flows -r demorealm ----- - -[discrete] -==== Getting a specific authentication flow - -Run the `get` command on the `authentication/flows/FLOW_ID` endpoint. - -For example: -[options="nowrap"] ----- -$ kcadm.sh get authentication/flows/febfd772-e1a1-42fb-b8ae-00c0566fafb8 -r demorealm ----- - -[discrete] -==== Listing executions for a flow - -Run the `get` command on the `authentication/flows/FLOW_ALIAS/executions` endpoint. - -For example: -[options="nowrap"] ----- -$ kcadm.sh get authentication/flows/Copy%20of%20browser/executions -r demorealm ----- - - -[discrete] -==== Adding configuration to an execution - -. Get execution for a flow. -. Note the ID of the flow. -. Run the `create` command on the `authentication/executions/{executionId}/config` endpoint. - -For example: -[options="nowrap"] ----- -$ kcadm create "authentication/executions/a3147129-c402-4760-86d9-3f2345e401c7/config" -r examplerealm -b '{"config":{"x509-cert-auth.mapping-source-selection":"Match SubjectDN using regular expression","x509-cert-auth.regular-expression":"(.*?)(?:$)","x509-cert-auth.mapper-selection":"Custom Attribute Mapper","x509-cert-auth.mapper-selection.user-attribute-name":"usercertificate","x509-cert-auth.crl-checking-enabled":"","x509-cert-auth.crldp-checking-enabled":false,"x509-cert-auth.crl-relative-path":"crl.pem","x509-cert-auth.ocsp-checking-enabled":"","x509-cert-auth.ocsp-responder-uri":"","x509-cert-auth.keyusage":"","x509-cert-auth.extendedkeyusage":"","x509-cert-auth.confirmation-page-disallowed":""},"alias":"my_otp_config"}' ----- - - -[discrete] -==== Getting configuration for an execution - -. Get execution for a flow. -. Note its `authenticationConfig` attribute, which contains the config ID. -. Run the `get` command on the `authentication/config/ID` endpoint. - -For example: -[options="nowrap"] ----- -$ kcadm get "authentication/config/dd91611a-d25c-421a-87e2-227c18421833" -r examplerealm ----- - - -[discrete] -==== Updating configuration for an execution - -. Get the execution for the flow. -. Get the flow's `authenticationConfig` attribute. -. Note the config ID from the attribute. -. Run the `update` command on the `authentication/config/ID` endpoint. - -For example: -[options="nowrap"] ----- -$ kcadm update "authentication/config/dd91611a-d25c-421a-87e2-227c18421833" -r examplerealm -b '{"id":"dd91611a-d25c-421a-87e2-227c18421833","alias":"my_otp_config","config":{"x509-cert-auth.extendedkeyusage":"","x509-cert-auth.mapper-selection.user-attribute-name":"usercertificate","x509-cert-auth.ocsp-responder-uri":"","x509-cert-auth.regular-expression":"(.*?)(?:$)","x509-cert-auth.crl-checking-enabled":"true","x509-cert-auth.confirmation-page-disallowed":"","x509-cert-auth.keyusage":"","x509-cert-auth.mapper-selection":"Custom Attribute Mapper","x509-cert-auth.crl-relative-path":"crl.pem","x509-cert-auth.crldp-checking-enabled":"false","x509-cert-auth.mapping-source-selection":"Match SubjectDN using regular expression","x509-cert-auth.ocsp-checking-enabled":""}}' ----- - - -[discrete] -==== Deleting configuration for an execution - -. Get execution for a flow. -. Get the flows `authenticationConfig` attribute. -. Note the config ID from the attribute. -. Run the `delete` command on the `authentication/config/ID` endpoint. - -For example: -[options="nowrap"] ----- -$ kcadm delete "authentication/config/dd91611a-d25c-421a-87e2-227c18421833" -r examplerealm ----- diff --git a/server_admin/topics/admin-console-permissions.adoc b/server_admin/topics/admin-console-permissions.adoc deleted file mode 100644 index e938839de..000000000 --- a/server_admin/topics/admin-console-permissions.adoc +++ /dev/null @@ -1,7 +0,0 @@ -[[_admin_permissions]] - -== Controlling access to the Admin Console - -Each realm created on the {project_name} has a dedicated Admin Console from which that realm can be managed. -The `master` realm is a special realm that allows admins to manage more than one realm on the system. You can also -define fine-grained access to users in different realms to manage the server. This chapter goes over all the scenarios for this. diff --git a/server_admin/topics/admin-console-permissions/fine-grain.adoc b/server_admin/topics/admin-console-permissions/fine-grain.adoc deleted file mode 100644 index 5e67a1e6d..000000000 --- a/server_admin/topics/admin-console-permissions/fine-grain.adoc +++ /dev/null @@ -1,305 +0,0 @@ -[[_fine_grain_permissions]] - -=== Fine grain admin permissions - -:tech_feature_name: Fine Grain Admin Permissions -:tech_feature_setting: -Dkeycloak.profile.feature.admin_fine_grained_authz=enabled -:tech_feature_id: admin-fine-grained-authz -include::../templates/techpreview.adoc[] - -Sometimes roles like `manage-realm` or `manage-users` are too coarse grain and you want to create -restricted admin accounts that have more fine grain permissions. {project_name} allows you to define -and assign restricted access policies for managing a realm. Things like: - -* Managing one specific client -* Managing users that belong to a specific group -* Managing membership of a group -* Limited user management. -* Fine grain impersonation control -* Being able to assign a specific restricted set of roles to users. -* Being able to assign a specific restricted set of roles to a composite role. -* Being able to assign a specific restricted set of roles to a client's scope. -* New general policies for viewing and managing users, groups, roles, and clients. - -There are some important things to note about fine grain admin permissions: - -* Fine grain admin permissions were implemented on top of link:{authorizationguide_link}[Authorization Services]. It is highly recommended that you read up on those features before diving into fine grain permissions. -* Fine grain permissions are only available within <<_per_realm_admin_permissions, dedicated admin consoles>> and admins defined within those realms. You cannot define cross-realm fine grain permissions. -* Fine grain permissions are used to grant additional permissions. You cannot override the - default behavior of the built-in admin roles. - -==== Managing one specific client - -Let's look first at allowing -an admin to manage one client and one client only. In our example, we have a realm -called `test` and a client called `sales-application`. In the realm `test` we will give a -user in that realm permission to only manage that application. - -IMPORTANT: You cannot do cross realm fine grain permissions. Admins in the `master` realm are limited to the predefined admin roles defined in previous chapters. - -===== Permission setup - -The first thing we must do is login to the Admin Console so we can set up permissions for that client. We navigate to the management section -of the client, we want to define fine-grain permissions for. - -.Client management -image:images/fine-grain-client.png[Fine grain client] - -You should see a tab menu item called `Permissions`. Click on that tab. - -.Client permissions tab -image:images/fine-grain-client-permissions-tab-off.png[Fine grain client permissions tab] - -By default, each client is not enabled to do fine grain permissions. So turn the `Permissions Enabled` switch to on -to initialize permissions. - -IMPORTANT: If you turn the `Permissions Enabled` switch to off, it will delete any and all permissions you have defined for this client. - -.Client permissions tab -image:images/fine-grain-client-permissions-tab-on.png[Fine grain permission tab] - -When you switch `Permissions Enabled` to on, it initializes various permission objects behind the scenes -using link:{authorizationguide_link}[Authorization Services]. For this example, we're -interested in the `manage` permission for the client. Clicking on that will redirect you -to the permission that handles the `manage` permission for the client. All authorization -objects are contained in the `realm-management` client's `Authorization` tab. - -.Client manage permission -image:images/fine-grain-client-manage-permissions.png[Fine grain client manage permission ] - -When first initialized the `manage` permission does not have any policies associated with it. -You will need to create one by going to the policy tab. To get there fast, click on -the `Authorization` link shown in the above image. Then click on the policies tab. - -There's a pull down menu on this page called `Create policy`. There's a multitude of policies -you can define. You can define a policy that is associated with a role or a group or even define -rules in JavaScript. For this simple example, we're going to create a `User Policy`. - -.User policy -image:images/fine-grain-client-user-policy.png[Fine grain client user policy] - -This policy will match a hard-coded user in the user database. In this case, it is the `sales-admin` user. We must then go back to the -`sales-application` client's `manage` permission page and assign the policy to the permission object. - -.Assign user policy -image:images/fine-grain-client-assign-user-policy.png[Fine grain client assign user policy] - -The `sales-admin` user can now has permission to manage the `sales-application` client. - -There's one more thing we have to do. Go to the `Role Mappings` tab and assign the `query-clients` -role to the `sales-admin`. - -.Assign query-clients -image:images/fine-grain-assign-query-clients.png[Fine grain assign query clients] - - -Why do you have to do this? This role tells the Admin Console -what menu items to render when the `sales-admin` visits the Admin Console. The `query-clients` -role tells the Admin Console that it should render client menus for the `sales-admin` user. - -IMPORTANT If you do not set the `query-clients` role, restricted admins like `sales-admin` will not see any menu options when they log into the Admin Console - -===== Testing it out - -Next, we log out of the master realm and re-login to the <<_per_realm_admin_permissions, dedicated admin console>> for the `test` realm -using the `sales-admin` as a username. This is located under `{kc_admins_path}/test/console`. - -.Sales admin login -image:images/fine-grain-sales-admin-login.png[Fine grain sales admin login] - -This admin is now able to manage this one client. - -==== Restrict user role mapping - -Another thing you might want to do is to restrict the set of roles an admin is allowed -to assign to a user. Continuing our last example, let's expand the permission set of the 'sales-admin' -user so that he can also control which users are allowed to access this application. Through fine grain permissions, we can -enable it so that the `sales-admin` can only assign roles that grant specific access to -the `sales-application`. We can also restrict it so that the admin can only map roles -and not perform any other types of user administration. - -The `sales-application` has defined three different client roles. - -.Sales application roles -image:images/fine-grain-sales-application-roles.png[Fine grain sales application roles] - -We want the `sales-admin` user to be able to map these roles to any user in the system. The -first step to do this is to allow the role to be mapped by the admin. If we click on the -`viewLeads` role, you'll see that there is a `Permissions` tab for this role. - -.View leads role permission tab -image:images/fine-grain-view-leads-role-tab.png[Fine grain view leads role] - -If we click on that tab and turn the `Permissions Enabled` on, you'll see that there -are a number of actions we can apply policies to. - -.View leads permissions -image:images/fine-grain-view-leads-permissions.png[Fine grain view leads permissions] - -The one we are interested in is `map-role`. Click on this permission and add the same -User Policy that was created in the earlier example. - -.Map-roles permission -image:images/fine-grain-map-roles-permission.png[Fine grain map roles permission] - -What we've done is say that the `sales-admin` can map the `viewLeads` role. What we have -not done is specify which users the admin is allowed to map this role too. To do that -we must go to the `Users` section of the admin console for this realm. Clicking on the -`Users` left menu item brings us to the users interface of the realm. You should see a -`Permissions` tab. Click on that and enable it. - -.Users permissions -image:images/fine-grain-users-permissions.png[Fine grain user permissions] - -The permission we are interested in is `map-roles`. This is a restrictive policy -in that it only allows admins the ability to map roles to a user. If we click on the -`map-roles` permission and again add the User Policy we created for this, our `sales-admin` -will be able to map roles to any user. - -The last thing we have to do is add the `view-users` role to the `sales-admin`. This will -allow the admin to view users in the realm he wants to add the `sales-application` roles to. - -.Add view-users -image:images/fine-grain-add-view-users.png[Fine grain add view users] - - -===== Testing it out - -Next, we log out of the master realm and re-login to the <<_per_realm_admin_permissions, dedicated admin console>> for the `test` realm -using the `sales-admin` as a username. This is located under `{kc_admins_path}/test/console`. - -You will see that now the `sales-admin` can view users in the system. If you select one of the -users you'll see that each user detail page is read only, except for the `Role Mappings` tab. -Going to this tab you'll find that there are no `Available` roles for the admin to -map to the user except when we browse the `sales-application` roles. - -.Add viewleads -image:images/fine-grain-add-view-leads.png[Fine grain add view leads] - -We've only specified that the `sales-admin` can map the `viewLeads` role. - -===== Per client map-roles shortcut - -It would be tedious if we had to do this for every client role that the `sales-application` published. -to make things easier, there's a way to specify that an admin can map any role defined -by a client. If we log back into the admin console to our master realm admin and go back - to the `sales-application` permissions page, you'll see the `map-roles` permission. - -.Client map-roles permission -image:images/fine-grain-client-permissions-tab-on.png[Fine grain client permissions] - -If you grant access to this particular permission to an admin, that admin will be able -map any role defined by the client. - -==== Full list of permissions - -You can do a lot more with fine grain permissions beyond managing a specific client or the specific roles of a client. -This chapter defines the whole list of permission types that can be described for -a realm. - -===== Role - -When going to the `Permissions` tab for a specific role, you will see these -permission types listed. - -map-role:: - Policies that decide if an admin can map this role to a user. These policies - only specify that the role can be mapped to a user, not that the admin is allowed - to perform user role mapping tasks. The admin will also have to have manage or - role mapping permissions. See <<_users-permissions, Users Permissions>> for more information. -map-role-composite:: - Policies that decide if an admin can map this role as a composite to another role. - An admin can define roles for a client if he has to manage permissions for that client - but he will not be able to add composites to those roles unless he has the - `map-role-composite` privileges for the role he wants to add as a composite. -map-role-client-scope:: - Policies that decide if an admin can apply this role to the scope of a client. - Even if the admin can manage the client, he will not have permission to - create tokens for that client that contain this role unless this privilege - is granted. - -===== Client - -When going to the `Permissions` tab for a specific client, you will see these -permission types listed. - -view:: - Policies that decide if an admin can view the client's configuration. -manage:: - Policies that decide if an admin can view and manage the client's configuration. - There are some issues with this in that privileges could be leaked unintentionally. - For example, the admin could define a protocol mapper that hardcoded a role - even if the admin does not have privileges to map the role to the client's scope. - This is currently the limitation of protocol mappers as they don't have a way - to assign individual permissions to them like roles do. -configure:: - Reduced set of privileges to manage the client. It is like the `manage` scope except - the admin is not allowed to define protocol mappers, change the client template, - or the client's scope. -map-roles:: - Policies that decide if an admin can map any role defined by the client to a user. - This is a shortcut, easy-of-use feature to avoid having to define policies - for each and every role defined by the client. -map-roles-composite:: - Policies that decide if an admin can map any role defined by the client - as a composite to another role. - This is a shortcut, easy-of-use feature to avoid having to define policies - for each and every role defined by the client. -map-roles-client-scope:: - Policies that decide if an admin can map any role defined by the client - to the scope of another client. - This is a shortcut, easy-of-use feature to avoid having to define policies - for each and every role defined by the client. - -[[_users-permissions]] -===== Users - -When going to the `Permissions` tab for all users, you will see these -permission types listed. - -view:: - Policies that decide if an admin can view all users in the realm. -manage:: - Policies that decide if an admin can manage all users in the realm. This - permission grants the admin the privilege to perform user role mappings, but - it does not specify which roles the admin is allowed to map. You'll need to - define the privilege for each role you want the admin to be able to map. -map-roles:: - This is a subset of the privileges granted by the `manage` scope. In this - case the admin is only allowed to map roles. The admin is not allowed to perform - any other user management operation. Also, like `manage`, the roles that the - admin is allowed to apply must be specified per role or per set of roles if dealing - with client roles. -manage-group-membership:: - Similar to `map-roles` except that it pertains to group membership: which - groups a user can be added or removed from. These - policies just grant the admin permission to manage group membership, not which - groups the admin is allowed to manage membership for. You'll have to - specify policies for each group's `manage-members` permission. -impersonate:: - Policies that decide if the admin is allowed to impersonate other users. These - policies are applied to the administrator's attributes and role mappings. -user-impersonated:: - Policies that decide which users can be impersonated. These policies will be - applied to the user being impersonated. For example, you might want to define - a policy that will forbid anybody from impersonating a user that has admin - privileges. - -===== Group - -When going to the `Permissions` tab for a specific group, you will see these -permission types listed. - -view:: - Policies that decide if the admin can view information about the group. -manage:: - Policies that decide if the admin can manage the configuration of the group. -view-members:: - Policies that decide if the admin can view the user details of members of the group. -manage-members:: - Policies that decide if the admin can manage the users that belong to this group. -manage-membership:: - Policies that decide if an admin can change the membership of the group. Add or - remove members from the group. - - diff --git a/server_admin/topics/admin-console-permissions/master-realm.adoc b/server_admin/topics/admin-console-permissions/master-realm.adoc deleted file mode 100644 index 3c0b626a8..000000000 --- a/server_admin/topics/admin-console-permissions/master-realm.adoc +++ /dev/null @@ -1,48 +0,0 @@ - -=== Master realm access control - -The `master` realm in {project_name} is a special realm and treated differently than other realms. -Users in the {project_name} `master` realm can be granted permission to manage zero or more realms that are deployed on the {project_name} server. -When a realm is created, {project_name} automatically creates various roles that grant fine-grain permissions to access that new realm. -Access to The Admin Console and Admin REST endpoints can be controlled by mapping these roles to users in the `master` realm. -It's possible to create multiple superusers, as well as users that can only manage specific realms. - -==== Global roles - -There are two realm-level roles in the `master` realm. -These are: - -* admin -* create-realm - -Users with the `admin` role are superusers and have full access to manage any realm on the server. Users with the `create-realm` role -are allowed to create new realms. They will be granted full access to any new realm they create. - -==== Realm specific roles - -Admin users within the `master` realm can be granted management privileges to one or more other realms in the system. -Each realm in {project_name} is represented by a client in the `master` realm. -The name of the client is `-realm`. These clients each have client-level roles defined which define varying -level of access to manage an individual realm. - -The roles available are: - -* view-realm -* view-users -* view-clients -* view-events -* manage-realm -* manage-users -* create-client -* manage-clients -* manage-events -* view-identity-providers -* manage-identity-providers -* impersonation - -Assign the roles you want to your users and they will only be able to use that specific part of the administration console. - -IMPORTANT: Admins with the `manage-users` role will only be able to assign admin roles to users that they themselves have. So, if an admin has the `manage-users` role but doesn't have the `manage-realm` role, they will not be able to assign this role. - - - diff --git a/server_admin/topics/admin-console-permissions/per-realm.adoc b/server_admin/topics/admin-console-permissions/per-realm.adoc deleted file mode 100644 index 80a4f5d39..000000000 --- a/server_admin/topics/admin-console-permissions/per-realm.adoc +++ /dev/null @@ -1,25 +0,0 @@ -[[_per_realm_admin_permissions]] - -=== Dedicated realm admin consoles - -Each realm has a dedicated Admin Console that can be accessed by going to the url `{kc_admins_path}/{realm-name}/console`. -Users within that realm can be granted realm management permissions by assigning specific user role mappings. - -Each realm has a built-in client called `realm-management`. You can view this client by going to the -`Clients` left menu item of your realm. This client defines client-level roles that specify permissions that can be granted to manage the realm. - -* view-realm -* view-users -* view-clients -* view-events -* manage-realm -* manage-users -* create-client -* manage-clients -* manage-events -* view-identity-providers -* manage-identity-providers -* impersonation - -Assign the roles you want to your users and they will only be able to use that specific part of the administration console. - diff --git a/server_admin/topics/admin-console.adoc b/server_admin/topics/admin-console.adoc deleted file mode 100644 index a28eee5c8..000000000 --- a/server_admin/topics/admin-console.adoc +++ /dev/null @@ -1,21 +0,0 @@ - -== Configuring realms - -Once you have an administrative account for the Admin Console, you can configure realms. A realm is a space where you manage objects, including users, applications, roles, and groups. A user belongs to and logs into a realm. One {project_name} deployment can define, store, and manage as many realms as there is space for in the database. - -include::realms/proc-using-admin-console.adoc[leveloffset=1] -include::realms/master.adoc[leveloffset=2] -include::realms/proc-creating-a-realm.adoc[leveloffset=2] -include::realms/ssl.adoc[leveloffset=2][] -ifeval::[{project_product}==true] -include::realms/cache.adoc[leveloffset=2][] -endif::[] -include::realms/email.adoc[leveloffset=2] -include::realms/themes.adoc[leveloffset=2] -include::realms/proc-configuring-internationalization.adoc[leveloffset=2] -include::login-settings.adoc[leveloffset=2] -include::login-settings/forgot-password.adoc[leveloffset=2] -include::login-settings/remember-me.adoc[leveloffset=2] -include::login-settings/acr-to-loa-mapping.adoc[leveloffset=2] -include::login-settings/update-email-workflow.adoc[leveloffset=2] -include::realms/keys.adoc[] \ No newline at end of file diff --git a/server_admin/topics/assembly-creating-first-admin.adoc b/server_admin/topics/assembly-creating-first-admin.adoc deleted file mode 100644 index 1cb5a2861..000000000 --- a/server_admin/topics/assembly-creating-first-admin.adoc +++ /dev/null @@ -1,31 +0,0 @@ - -[id="creating-first-admin_{context}"] -== Creating the first administrator - -After installing {project_name}, you need an administrator account that can act as a _super_ admin with full permissions to manage {project_name}. With this account, you can log in to the {project_name} Admin Console where you create realms and users and register applications that are secured by {project_name}. - -=== Creating the account on the local host - -If your server is accessible from `localhost`, perform these steps. - -.Procedure - -. In a web browser, go to the http://localhost:8080{kc_base_path} URL. - -. Supply a username and password that you can recall. -+ -.Welcome page -image:images/initial-welcome-page.png[Welcome page] - -=== Creating the account remotely - -If you cannot access the server from a `localhost` address or just want to start {project_name} from the command line, use the `KEYCLOAK_ADMIN` and `KEYCLOAK_ADMIN_PASSWORD` environment variables to create an initial admin account. - -For example: -[source,bash] ----- -export KEYCLOAK_ADMIN= -export KEYCLOAK_ADMIN_PASSWORD= - -bin/kc.[sh|bat] start ----- diff --git a/server_admin/topics/assembly-managing-clients.adoc b/server_admin/topics/assembly-managing-clients.adoc deleted file mode 100644 index 1196e9fe4..000000000 --- a/server_admin/topics/assembly-managing-clients.adoc +++ /dev/null @@ -1,20 +0,0 @@ - -[id="assembly-managing-clients_{context}"] -== Managing OpenID Connect and SAML Clients - -[role="_abstract"] -Clients are entities that can request authentication of a user. Clients come in two forms. -The first type of client is an application that wants -to participate in single-sign-on. These clients just want {project_name} to provide security for them. The other type -of client is one that is requesting an access token so that it can invoke other services on behalf of the authenticated user. -This section discusses various aspects around configuring clients and various ways to do it. - -include::clients/assembly-client-oidc.adoc[leveloffset=+2] -include::clients/saml/proc-creating-saml-client.adoc[leveloffset=+2] -include::clients/saml/idp-initiated-login.adoc[leveloffset=+3] -include::clients/saml/proc-using-an-entity-descriptor.adoc[leveloffset=+3] -include::clients/con-client-links.adoc[leveloffset=+2] -include::clients/con-protocol-mappers.adoc[leveloffset=+2] -include::clients/proc-generating-client-adapter-config.adoc[leveloffset=+2] -include::clients/con-client-scopes.adoc[leveloffset=+2] -include::clients/client-policies.adoc[leveloffset=+2] diff --git a/server_admin/topics/assembly-managing-users.adoc b/server_admin/topics/assembly-managing-users.adoc deleted file mode 100644 index db2a482fd..000000000 --- a/server_admin/topics/assembly-managing-users.adoc +++ /dev/null @@ -1,33 +0,0 @@ - -[id="assembly-managing-users_{context}"] -== Managing users - -From the Admin Console, you have a wide range of actions you can perform to manage users. - -include::users/proc-creating-user.adoc[leveloffset=+2] - -include::users/ref-user-credentials.adoc[leveloffset=+2] -include::users/proc-setting-password-user.adoc[leveloffset=+3] -include::users/proc-creating-otp.adoc[leveloffset=+3] - -include::users/proc-configuring-user-attributes.adoc[leveloffset=+2] -include::users/con-user-registration.adoc[leveloffset=+2] -include::users/proc-enabling-user-registration.adoc[leveloffset=3] -include::users/proc-registering-new-user.adoc[leveloffset=3] - -include::users/con-required-actions.adoc[leveloffset=+2] -include::users/proc-setting-required-actions.adoc[leveloffset=+3] -include::users/proc-setting-default-required-actions.adoc[leveloffset=+3] -include::users/proc-enabling-terms-conditions.adoc[leveloffset=+3] - -include::users/proc-searching-user.adoc[leveloffset=+2] - -include::users/proc-deleting-user.adoc[leveloffset=+2] -include::users/proc-allow-user-to-delete-account.adoc[leveloffset=+2] - -include::users/con-user-impersonation.adoc[leveloffset=+2] -include::users/proc-enabling-recaptcha.adoc[leveloffset=+2] - -include::users/user-profile.adoc[leveloffset=+2] -include::users/ref-personal-data-collected.adoc[leveloffset=+2] - diff --git a/server_admin/topics/assembly-roles-groups.adoc b/server_admin/topics/assembly-roles-groups.adoc deleted file mode 100644 index dcf282f2c..000000000 --- a/server_admin/topics/assembly-roles-groups.adoc +++ /dev/null @@ -1,17 +0,0 @@ -== Assigning permissions using roles and groups - -Roles and groups have a similar purpose, which is to give users access and permissions to use applications. Groups are a collection of users to which you apply roles and attributes. Roles define specific applications permissions and access control. - -A role typically applies to one type of user. For example, an organization may include `admin`, `user`, `manager`, and `employee` roles. An application can assign access and permissions to a role and then assign multiple users to that role so the users have the same access and permissions. For example, the Admin Console has roles that give permission to users to access different parts of the Admin Console. - -There is a global namespace for roles and each client also has its own dedicated namespace where roles can be defined. - -include::roles-groups/proc-creating-realm-roles.adoc[leveloffset=2] -include::roles-groups/con-client-roles.adoc[leveloffset=2] -include::roles-groups/proc-converting-composite-roles.adoc[leveloffset=2] -include::roles-groups/proc-assigning-role-mappings.adoc[leveloffset=2] -include::roles-groups/proc-using-default-roles.adoc[leveloffset=2] -include::roles-groups/con-role-scope-mappings.adoc[leveloffset=2] -include::roles-groups/proc-managing-groups.adoc[leveloffset=2] -include::roles-groups/con-comparing-groups-roles.adoc[leveloffset=3] -include::roles-groups/proc-specifying-default-groups.adoc[leveloffset=3] diff --git a/server_admin/topics/authentication.adoc b/server_admin/topics/authentication.adoc deleted file mode 100644 index b403238e0..000000000 --- a/server_admin/topics/authentication.adoc +++ /dev/null @@ -1,9 +0,0 @@ -[id="configuring-authentication_{context}"] -== Configuring authentication - -This chapter covers several authentication topics. These topics include: - -* Enforcing strict password and One Time Password (OTP) policies. -* Managing different credential types. -* Logging in with Kerberos. -* Disabling and enabling built-in credential types. diff --git a/server_admin/topics/authentication/conditions.adoc b/server_admin/topics/authentication/conditions.adoc deleted file mode 100644 index e5077cba2..000000000 --- a/server_admin/topics/authentication/conditions.adoc +++ /dev/null @@ -1,85 +0,0 @@ -=== Conditions in conditional flows - -As was mentioned in <<_execution-requirements, Execution requirements>>, _Condition_ executions can be only contained in _Conditional_ subflow. -If all _Condition_ executions evaluate as true, then the _Conditional_ sub-flow acts as _Required_. -You can process the next execution in the _Conditional_ sub-flow. -If some executions included in the _Conditional_ sub-flow evaluate as false, then the whole sub-flow is considered as _Disabled_. - -==== Available conditions - -`Condition - User Role`:: -This execution has the ability to determine if the user has a role defined by _User role_ field. -If the user has the required role, the execution is considered as true and other executions are evaluated. -The administrator has to define the following fields: - -Alias::: -Describes a name of the execution, which will be shown in the authentication flow. - -User role::: -Role the user should have to execute this flow. -To specify an application role the syntax is `appname.approle` (for example `myapp.myrole`). - -`Condition - User Configured`:: -This checks if the other executions in the flow are configured for the user. -The Execution requirements section includes an example of the OTP form. - -`Condition - User Attribute`:: -This checks if the user has set up the required attribute. -There is a possibility to negate output, which means the user should not have the attribute. -The xref:proc-configuring-user-attributes_{context}[User Attributes] section shows how to add a custom attribute. -You can provide these fields: - -Alias::: -Describes a name of the execution, which will be shown in the authentication flow. - -Attribute name::: -Name of the attribute to check. - -Expected attribute value::: -Expected value in the attribute. - -Negate output::: -You can negate the output. -In other words, the attribute should not be present. - -==== Explicitly deny/allow access in conditional flows - -You can allow or deny access to resources in a conditional flow. -The two authenticators `Deny Access` and `Allow Access` control access to the resources by conditions. - -`Allow Access`:: -Authenticator will always successfully authenticate. -This authenticator is not configurable. - -`Deny Access`:: -Access will always be denied. -You can define an error message, which will be shown to the user. -You can provide these fields: - -Alias::: -Describes a name of the execution, which will be shown in the authentication flow. - -Error message::: -Error message which will be shown to the user. -The error message could be provided as a particular message or as a property in order to use it with localization. -(i.e. "_You do not have the role 'admin'._", _my-property-deny_ in messages properties) -Leave blank for the default message defined as property `access-denied`. - -Here is an example how to deny access to all users who do not have the role `role1` and show an error message defined by a property `deny-role1`. -This example includes `Condition - User Role` and `Deny Access` executions. - -.Browser flow -image:images/deny-access-flow.png[Deny access flow] - -.Condition - user role configuration -image:images/deny-access-role-condition.png[Deny access role settings] - -.Configuration of the `Deny Access` is really easy. You can specify an arbitrary Alias and required message like this: -image:images/deny-access-execution-cond.png[Deny access execution settings] - -The last thing is defining the property with an error message in the login theme `messages_en.properties` (for English): - -[source] ----- -deny-role1 = You do not have required role! ----- \ No newline at end of file diff --git a/server_admin/topics/authentication/flows.adoc b/server_admin/topics/authentication/flows.adoc deleted file mode 100644 index b68fcfdae..000000000 --- a/server_admin/topics/authentication/flows.adoc +++ /dev/null @@ -1,444 +0,0 @@ -[[_authentication-flows]] - -=== Authentication flows - -An _authentication flow_ is a container of authentications, screens, and actions, during log in, registration, and other {project_name} workflows. -To view all the flows, actions, and checks, each flow requires: - -==== Built-in flows - -{project_name} has several built-in flows. You cannot modify these flows, but you can alter the flow's requirements to suit your needs. - -.Procedure -. Click *Authentication* in the menu. -. Click on the _Browser_ item in the list to see the details. - -.Browser flow -image:images/browser-flow.png[Browser Flow] - -===== Auth type -The name of the authentication or the action to execute. If an authentication is indented, it is in a sub-flow. It may or may not be executed, depending on the behavior of its parent. - -. Cookie -+ -The first time a user logs in successfully, {project_name} sets a session cookie. If the cookie is already set, this authentication type is successful. Since the cookie provider returned success and each execution at this level of the flow is _alternative_, {project_name} does not perform any other execution. This results in a successful login. - -. Kerberos -+ -This authenticator is disabled by default and is skipped during the Browser Flow. - -. Identity Provider Redirector -+ -This action is configured through the *Actions* > *Config* link. It redirects to another IdP for <<_identity_broker, identity brokering>>. - -. Forms -+ -Since this sub-flow is marked as _alternative_, it will not be executed if the *Cookie* authentication type passed. This sub-flow contains an additional authentication type that needs to be executed. {project_name} loads the executions for this sub-flow and processes them. - -The first execution is the *Username Password Form*, an authentication type that renders the username and password page. It is marked as _required_, so the user must enter a valid username and password. - -The second execution is the *Browser - Conditional OTP* sub-flow. This sub-flow is _conditional_ and executes depending on the result of the *Condition - User Configured* execution. If the result is true, {project_name} loads the executions for this sub-flow and processes them. - -The next execution is the *Condition - User Configured* authentication. This authentication checks if {project_name} has configured other executions in the flow for the user. The *Browser - Conditional OTP* sub-flow executes only when the user has a configured OTP credential. - -The final execution is the *OTP Form*. {project_name} marks this execution as _required_ but it runs only when the user has an OTP credential set up because of the setup in the _conditional_ sub-flow. If not, the user does not see an OTP form. - -===== Requirement -A set of radio buttons that control the execution of an action executes. - -[[_execution-requirements]] -====== Required - -All _Required_ elements in the flow must be successfully sequentially executed. The flow terminates if a required element fails. - -====== Alternative - -Only a single element must successfully execute for the flow to evaluate as successful. Because the _Required_ flow elements are sufficient to mark a flow as successful, any _Alternative_ flow element within a flow containing _Required_ flow elements will not execute. - -====== Disabled - -The element does not count to mark a flow as successful. - -====== Conditional - -This requirement type is only set on sub-flows. - -* A _Conditional_ sub-flow contains executions. These executions must evaluate to logical statements. -* If all executions evaluate as _true_, the _Conditional_ sub-flow acts as _Required_. -* If any executions evaluate as _false_, the _Conditional_ sub-flow acts as _Disabled_. -* If you do not set an execution, the _Conditional_ sub-flow acts as _Disabled_. -* If a flow contains executions and the flow is not set to _Conditional_, {project_name} does not evaluate the executions, and the executions are considered functionally _Disabled_. - -==== Creating flows - -Important functionality and security considerations apply when you design a flow. - -To create a flow, perform the following: - -.Procedure -. Click *Authentication* in the menu. -. Click *Create flow*. - -[NOTE] -==== -You can copy and then modify an existing flow. Click the "Action list" (the three dots at the end of the row), click *Duplicate*, and enter a name for the new flow. -==== - -When creating a new flow, you must create a top-level flow first with the following options: - -Alias:: - The name of the flow. -Description:: - The description you can set to the flow. -Top-Level Flow Type:: - The type of flow. The type *client* is used only for the authentication of clients (applications). For all other cases, choose *generic*. - -.Create a top-level flow -image:images/Create-top-level-flow.png[Top Level Flow] - -When {project_name} has created the flow, {project_name} displays the *Add step*, and *Add flow* buttons. - -.An empty new flow -image:images/New-flow.png[New Flow] - -Three factors determine the behavior of flows and sub-flows. - -* The structure of the flow and sub-flows. -* The executions within the flows -* The requirements set within the sub-flows and the executions. - -Executions have a wide variety of actions, from sending a reset email to validating an OTP. Add executions with the *Add step* button. Hover over the question mark next to *Provider*, to see a description of the execution. - -.Adding an authentication execution -image:images/Create-authentication-execution.png[Adding an Authentication Execution] - -Two types of executions exist, _automatic executions_ and _interactive executions_. _Automatic executions_ are similar to the *Cookie* execution and will automatically -perform their action in the flow. _Interactive executions_ halt the flow to get input. Executions executing successfully set their status to _success_. For a flow to complete, it needs at least one execution with a status of _success_. - -You can add sub-flows to top-level flows with the *Add flow* button. The *Add flow* button displays the *Create Execution Flow* page. This page is similar to the *Create Top Level Form* page. The difference is that the *Flow Type* can be *generic* (default) or *form*. The *form* type constructs a sub-flow that generates a form for the user, similar to the built-in *Registration* flow. -Sub-flows success depends on how their executions evaluate, including their contained sub-flows. See the <<_execution-requirements, execution requirements section>> for an in-depth explanation of how sub-flows work. - -[NOTE] -==== -After adding an execution, check the requirement has the correct value. -==== - -All elements in a flow have a *Delete* option in the *Actions* menu. This action removes the element from the flow. -Executions have a *⚙️* menu item (the gear icon) to configure the execution. It is also possible to add executions and sub-flows to sub-flows with the *Add step* and *Add flow* links. - -Since the order of execution is important, you can move executions and sub-flows up and down by dragging their names. - -[WARNING] -==== -Make sure to properly test your configuration when you configure the authentication flow to confirm that no security holes exist in your setup. We recommend that you test various -corner cases. For example, consider testing the authentication behavior for a user when you remove various credentials from the user's account before authentication. - -As an example, when 2nd-factor authenticators, such as OTP Form or WebAuthn Authenticator, are configured in the flow as REQUIRED and the user does not have credential of particular -type, the user will be able to set up the particular credential during authentication itself. This situation means that the user does not authenticate with this credential as he set up -it right during the authentication. So for browser authentication, make sure to configure your authentication flow with some 1st-factor credentials such as Password or WebAuthn -Passwordless Authenticator. -==== - -==== Creating a password-less browser login flow - -To illustrate the creation of flows, this section describes creating an advanced browser login flow. The purpose of this flow is to allow a user a choice between logging in using a password-less manner with xref:webauthn_{context}[WebAuthn], or two-factor authentication with a password and OTP. - -.Procedure -. Click *Authentication* in the menu. -. Click the *Flows* tab. -. Click *Create flow*. -. Enter `Browser Password-less` as a name. -. Click *Create*. -. Click *Add execution*. -. Select *Cookie* from the list. -. Click *Add*. -. Select *Alternative* for the *Cookie* authentication type to set its requirement to alternative. -. Click *Add step*. -. Select *Kerberos* from the list. -. Click *Add*. -. Click *Add step*. -. Select *Identity Provider Redirector* from the list. -. Click *Add*. -. Select *Alternative* for the *Identity Provider Redirector* authentication type to set its requirement to alternative. -. Click *Add sub-flow*. -. Enter *Forms* as a name. -. Click *Add*. -. Select *Alternative* for the *Forms* authentication type to set its requirement to alternative. -+ -.The common part with the browser flow -image:images/Passwordless-browser-login-common.png[Passwordless browser login] -+ -. Click *+* menu of the *Forms* execution. -. Select *Add step*. -. Select *Username Form* from the list. -. Click *Add*. - -At this stage, the form requires a username but no password. We must enable password authentication to avoid security risks. - -. Click *+* menu of the *Forms* sub-flow. -. Click *Add sub-flow*. -. Enter `Authentication` as name. -. Click *Add*. -. Select *Required* for the *Authentication* authentication type to set its requirement to required. -. Click *+* menu of the *Authentication* sub-flow. -. Click *Add step*. -. Select *Webauthn Passwordless Authenticator* from the list. -. Click *Add*. -. Select *Alternative* for the *Webauthn Passwordless Authenticator* authentication type to set its requirement to alternative. -. Click *+* menu of the *Authentication* sub-flow. -. Click *Add sub-flow*. -. Enter `Password with OTP` as name. -. Click *Add*. -. Select *Alternative* for the *Password with OTP* authentication type to set its requirement to alternative. -. Click *+* menu of the *Password with OTP* sub-flow. -. Click *Add step*. -. Select *Password Form* from the list. -. Click *Add*. -. Select *Required* for the *Password Form* authentication type to set its requirement to required. -. Click *+* menu of the *Password with OTP* sub-flow. -. Click *Add step*. -. Select *OTP Form* from the list. -. Click *Add*. -. Click *Required* for the *OTP Form* authentication type to set its requirement to required. - -Finally, change the bindings. - -. Click the *Action* menu at the top of the screen. -. Select *Bind flow* from the menu. -. Click the *Browser Flow* drop-down list. -. Click *Save*. - -.A password-less browser login -image:images/Passwordless-browser-login.png[Passwordless browser login] - -After entering the username, the flow works as follows: - -If users have WebAuthn passwordless credentials recorded, they can use these credentials to log in directly. This is the password-less login. The user can also select *Password with OTP* because the `WebAuthn Passwordless` execution and the `Password with OTP` flow are set to *Alternative*. If they are set to *Required*, the user has to enter WebAuthn, password, and OTP. - -If the user selects the *Try another way* link with `WebAuthn passwordless` authentication, the user can choose between `Password` and `Security Key` (WebAuthn passwordless). When selecting the password, the user will need to continue and log in with the assigned OTP. If the user has no WebAuthn credentials, the user must enter the password and then the OTP. If the user has no OTP credential, they will be asked to record one. - -[NOTE] -==== -Since the WebAuthn Passwordless execution is set to *Alternative* rather than *Required*, this flow will never ask the user to register a WebAuthn credential. For a user to have a Webauthn credential, an administrator must add a required action to the user. Do this by: - -. Enabling the *Webauthn Register Passwordless* required action in the realm (see the xref:webauthn_{context}[WebAuthn] documentation). -. Setting the required action using the *Credential Reset* part of a user's xref:ref-user-credentials_{context}[Credentials] management menu. - -Creating an advanced flow such as this can have side effects. For example, if you enable the ability to reset the password for users, this would be accessible from the password form. In the default `Reset Credentials` flow, users must enter their username. Since the user has already entered a username earlier in the `Browser Password-less` flow, this action is unnecessary for {project_name} and suboptimal for user experience. To correct this problem, you can: - -* Duplicate the `Reset Credentials` flow. Set its name to `Reset Credentials for password-less`, for example. -* Click *Delete* (trash icon) of the *Choose user* step. -* In the *Action* menu, select *Bind flow* and select *Reset credentials flow* from the dropdown and click *Save* -==== - -[[_step-up-flow]] -==== Creating a browser login flow with step-up mechanism - -This section describes how to create advanced browser login flow using the step-up mechanism. The purpose of step-up authentication is to allow access to clients or resources based on a specific authentication level of a user. - -.Procedure -. Click *Authentication* in the menu. -. Click the *Flows* tab. -. Click *Create flow*. -. Enter `Browser Incl Step up Mechanism` as a name. -. Click *Save*. -. Click *Add execution*. -. Select *Cookie* from the list. -. Click *Add*. -. Select *Alternative* for the *Cookie* authentication type to set its requirement to alternative. -. Click *Add sub-flow*. -. Enter *Auth Flow* as a name. -. Click *Add*. -. Click *Alternative* for the *Auth Flow* authentication type to set its requirement to alternative. - -Now you configure the flow for the first authentication level. - -. Click *+* menu of the *Auth Flow*. -. Click *Add sub-flow*. -. Enter `1st Condition Flow` as a name. -. Click *Add*. -. Click *Conditional* for the *1st Condition Flow* authentication type to set its requirement to conditional. -. Click *+* menu of the *1st Condition Flow*. -. Click *Add condition*. -. Select *Conditional - Level Of Authentication* from the list. -. Click *Add*. -. Click *Required* for the *Conditional - Level Of Authentication* authentication type to set its requirement to required. -. Click *+* menu of the *Conditional - Level Of Authentication*. -. Click *⚙️* (gear icon). -. Enter `Level 1` as an alias. -. Enter `1` for the Level of Authentication (LoA). -. Set Max Age to *36000*. This value is in seconds and it is equivalent to 10 hours, which is the default `SSO Session Max` timeout set in the realm. - As a result, when a user authenticates with this level, subsequent SSO logins can re-use this level and the user does not need to authenticate - with this level until the end of the user session, which is 10 hours by default. -. Click *Save* -+ -.Configure the condition for the first authentication level -image:images/authentication-step-up-condition-1.png[Authentication step up condition 1] - -. Click *+* menu of the *1st Condition Flow*. -. Click *Add step*. -. Select *Username Password Form* from the list. -. Click *Add*. - -Now you configure the flow for the second authentication level. - -. Click *+* menu of the *Auth Flow*. -. Click *Add sub-flow*. -. Enter `2nd Condition Flow` as an alias. -. Click *Add*. -. Click *Conditional* for the *2nd Condition Flow* authentication type to set its requirement to conditional. -. Click *+* menu of the *2nd Condition Flow*. -. Click *Add condition*. -. Select *Conditional - Level Of Authentication* from the item list. -. Click *Add*. -. Click *Required* for the *Conditional - Level Of Authentication* authentication type to set its requirement to required. -. Click *⚙️* (gear icon). -. Enter `Level 2` as an alias. -. Enter `2` for the Level of Authentication (LoA). -. Set Max Age to *0*. As a result, when a user authenticates, this level is valid just for the current authentication, but not any - subsequent SSO authentications. So the user will always need to authenticate again with this level when this level is requested. -. Click *Save* -+ -.Configure the condition for the second authentication level -image:images/authentication-step-up-condition-2.png[Autehtnication step up condition 2] - -. Click *+* menu of the *2nd Condition Flow*. -. Click *Add step*. -. Select *OTP Form* from the list. -. Click *Add*. -. Click *Required* for the *OTP Form* authentication type to set its requirement to required. - -Finally, change the bindings. - -. Click the *Action* menu at the top of the screen. -. Select *Bind flow* from the list. -. Select *Browser Flow* in the dropdown. -. Click *Save*. - -.Browser login with step-up mechanism -image:images/authentication-step-up-flow.png[Authentication step up flow] - -.Request a certain authentication level -To use the step-up mechanism, you specify a requested level of authentication (LoA) in your authentication request. The `claims` parameter is used for this purpose: - -[source,subs=+attributes] ----- -https://{DOMAIN}{kc_realms_path}/{REALMNAME}/protocol/openid-connect/auth?client_id={CLIENT-ID}&redirect_uri={REDIRECT-URI}&scope=openid&response_type=code&response_mode=query&nonce=exg16fxdjcu&claims=%7B%22id_token%22%3A%7B%22acr%22%3A%7B%22essential%22%3Atrue%2C%22values%22%3A%5B%22gold%22%5D%7D%7D%7D ----- - -The `claims` parameter is specified in a JSON representation: -[source] ----- -claims= { - "id_token": { - "acr": { - "essential": true, - "values": ["gold"] - } - } - } ----- - -The {project_name} javascript adapter has support for easy construct of this JSON and sending it in the login request. -See link:{adapterguide_link_js_adapter}[Javascript adapter documentation] for more details. - -You can also use simpler parameter `acr_values` instead of `claims` parameter to request particular levels as non-essential. This is mentioned -in the OIDC specification. - -You can also configure the default level for the particular client, which is used when the parameter `acr_values` or the parameter `claims` with the `acr` claim is not present. -For further details, see <<_mapping-acr-to-loa-client,Client ACR configuration>>). - -NOTE: To request the acr_values as text (such as `gold`) instead of a numeric value, you configure the mapping between the ACR and the LoA. -It is possible to configure it at the realm level (recommended) or at the client level. For configuration see <<_mapping-acr-to-loa-realm,ACR to LoA Mapping>>. - -For more details see the https://openid.net/specs/openid-connect-core-1_0.html#acrSemantics[official OIDC specification]. - -*Flow logic* - -The logic for the previous configured authentication flow is as follows: + -If a client request a high authentication level, meaning Level of Authentication 2 (LoA 2), a user has to perform full 2-factor authentication: Username/Password + OTP. -However, if a user already has a session in Keycloak, that was logged in with username and password (LoA 1), the user is only asked for the second authentication factor (OTP). - -The option *Max Age* in the condition determines how long (how much seconds) the subsequent authentication level is valid. This setting helps to decide -whether the user will be asked to present the authentication factor again during a subsequent authentication. If the particular level X is requested -by the `claims` or `acr_values` parameter and user already authenticated with level X, but it is expired (for example max age is configured to 300 and user authenticated before 310 seconds) -then the user will be asked to re-authenticate again with the particular level. However if the level is not yet expired, the user will be automatically -considered as authenticated with that level. - -Using *Max Age* with the value 0 means, that particular level is valid just for this single authentication. Hence every re-authentication requesting that level -will need to authenticate again with that level. This is useful for operations that require higher security in the application (e.g. send payment) and always require authentication -with the specific level. - -WARNING: Note that parameters such as `claims` or `acr_values` might be changed by the user in the URL when the login request is sent from the client to the {project_name} via the user's browser. -This situation can be mitigated if client uses PAR (Pushed authorization request), a request object, or other mechanisms that prevents the user from rewrite the parameters in the URL. -Hence after the authentication, clients are encouraged to check the ID Token to double-check that `acr` in the token corresponds to the expected level. - -If no explicit level is requested by parameters, the {project_name} will require the authentication with the first LoA -condition found in the authentication flow, such as the Username/Password in the preceding example. When a user was already authenticated with that level -and that level expired, the user is not required to re-authenticate, but `acr` in the token will have the value 0. This result is considered as authentication -based solely on `long-lived browser cookie` as mentioned in the section 2 of OIDC Core 1.0 specification. - -NOTE: A conflict situation may arise when an admin specifies several flows, sets different LoA levels to each, and assigns the flows to different clients. However, the rule is always the same: if a user has a certain level, it needs only have that level to connect to a client. It's up to the admin to make sure that the LoA is coherent. - -*Example scenario* - -. Max Age is configured as 300 seconds for level 1 condition. -. Login request is sent without requesting any acr. Level 1 will be used and the user needs to authenticate with username and password. The token will have `acr=1`. -. Another login request is sent after 100 seconds. The user is automatically authenticated due to the SSO and the token will return `acr=1`. -. Another login request is sent after another 201 seconds (301 seconds since authentication in point 2). The user is automatically authenticated due to the SSO, but the token will return `acr=0` due the level 1 is considered expired. -. Another login request is sent, but now it will explicitly request ACR of level 1 in the `claims` parameter. User will be asked to re-authenticate with username/password - and then `acr=1` will be returned in the token. - -*ACR claim in the token* - -ACR claim is added to the token by the `acr loa level` protocol mapper defined in the `acr` client scope. This client scope is the realm default client scope -and hence will be added to all newly created clients in the realm. - -In case you do not want `acr` claim inside tokens or you need some custom logic for adding it, you can remove the client scope from your client. - -Note when the login request initiates a request with the `claims` parameter requesting `acr` as `essential` claim, then {project_name} will always return -one of the specified levels. If it is not able to return one of the specified levels (For example if the requested level is unknown or bigger than configured conditions -in the authentication flow), then {project_name} will throw an error. - -[[_user_session_limits]] -==== User session limits - -Limits on the number of session that a user can have can be configured. Sessions can be limited per realm or per client. - -To add session limits to a flow, perform the following steps. - -. Click *Add step* for the flow. -. Select *User session count limiter* from the item list. -. Click *Add*. -. Click *Required* for the *User Session Count Limiter* authentication type to set its requirement to required. -. Click *⚙️* (gear icon) for the *User Session Count Limiter*. -. Enter an alias for this config. -. Enter the required maximum number of sessions that a user can have in this realm. For example, if 2 is the value, 2 SSO sessions is the maximum that each user can have in this realm. If 0 is the value, this check is disabled. -. Enter the required maximum number of sessions a user can have for the client. For example, if 2 is the value, then 2 SSO sessions is the maximum in this realm for each client. So when a user is trying to authenticate to client `foo`, but that user has already authenticated in 2 SSO sessions to client `foo`, either the authentication will be denied or an existing sessions will be killed based on the behavior configured. If a value of 0 is used, this check is disabled. -If both session limits and client session limits are enabled, it makes sense to have client session limits to be always lower than session limits. The limit per client can never exceed the limit of all SSO sessions of this user. -. Select the behavior that is required when the user tries to create a session after the limit is reached. Available behaviors are: - - - *Deny new session* - when a new session is requested and the session limit is reached, no new sessions can be created. - - *Terminate oldest session* - when a new session is requested and the session limit has been reached, the oldest session will be removed and the new session created. - -. Optionally, add a custom error message to be displayed when the limit is reached. - -Note that the user session limits should be added to your bound *Browser flow*, *Direct grant flow*, *Reset credentials* and also to any *Post broker login flow*. -The authenticator should be added at the point when the user is already known during authentication (usually at the end of the authentication flow) and should be typically REQUIRED. Note that it is not possible to have -ALTERNATIVE and REQUIRED executions at the same level. For example for the default browser flow, it may be necessary to wrap the existing flow as a REQUIRED level-1 subflow and -add `User Session Count Limiter` to the same level as this new subflow. Example of such flow is below. - -image:images/authentication-user-session-limits.png[Authentication User Session Limits Flow] - -Currently, the administrator is responsible for maintaining consistency between the different configurations. - -Note also that the user session limit feature is not available for CIBA. - -ifeval::[{project_community}==true] -=== Script Authenticator - -Ability to upload scripts through the Admin Console and REST endpoints is deprecated. - -For more details see link:{developerguide_jsproviders_link}[{developerguide_jsproviders_name}]. - -endif::[] diff --git a/server_admin/topics/authentication/kerberos.adoc b/server_admin/topics/authentication/kerberos.adoc deleted file mode 100644 index 8627306e4..000000000 --- a/server_admin/topics/authentication/kerberos.adoc +++ /dev/null @@ -1,215 +0,0 @@ - -[[_kerberos]] - -=== Kerberos - -{project_name} supports login with a Kerberos ticket through the Simple and Protected GSSAPI Negotiation Mechanism (SPNEGO) protocol. SPNEGO authenticates transparently through the web browser after the user authenticates the session. For non-web cases, or when a ticket is not available during login, {project_name} supports login with Kerberos username and password. - -A typical use case for web authentication is the following: - -. The user logs into the desktop. -. The user accesses a web application secured by {project_name} using a browser. -. The application redirects to {project_name} login. -. {project_name} renders the HTML login screen with status 401 and HTTP header `WWW-Authenticate: Negotiate` -. If the browser has a Kerberos ticket from desktop login, the browser transfers the desktop sign-on information to {project_name} in header `Authorization: Negotiate 'spnego-token'`. Otherwise, it displays the standard login screen, and the user enters the login credentials. -. {project_name} validates the token from the browser and authenticates the user. -. If using LDAPFederationProvider with Kerberos authentication support, {project_name} provisions user data from LDAP. If using KerberosFederationProvider, {project_name} lets the user update the profile and pre-fill login data. -. {project_name} returns to the application. {project_name} and the application communicate through OpenID Connect or SAML messages. {project_name} acts as a broker to Kerberos/SPNEGO login. Therefore {project_name} authenticating through Kerberos is hidden from the application. - -[WARNING] -==== -The https://www.ietf.org/rfc/rfc4559.txt[Negotiate] www-authenticate scheme allows NTLM as a fallback to Kerberos and on some web browsers in Windows NTLM is supported by default. If a www-authenticate challenge comes from a server outside a browsers permitted list, users may encounter an NTLM dialog prompt. A user would need to click the cancel button on the dialog to continue as Keycloak does not support this mechanism. This situation can happen if Intranet web browsers are not strictly configured or if Keycloak serves users in both the Intranet and Internet. A https://github.com/keycloak/keycloak/issues/8989[custom authenticator] can be used to restrict Negotiate challenges to a whitelist of hosts. -==== - -Perform the following steps to set up Kerberos authentication: - -. The setup and configuration of the Kerberos server (KDC). -. The setup and configuration of the {project_name} server. -. The setup and configuration of the client machines. - -==== Setup of Kerberos server - -The steps to set up a Kerberos server depends on the operating system (OS) and the Kerberos vendor. Consult Windows Active Directory, MIT Kerberos, and your OS documentation for instructions on setting up and configuring a Kerberos server. - -During setup, perform these steps: - -. Add some user principals to your Kerberos database. -You can also integrate your Kerberos with LDAP, so user accounts provision from the LDAP server. -. Add service principal for "HTTP" service. -For example, if the {project_name} server runs on `www.mydomain.org`, add the service principal `HTTP/www.mydomain.org@`. -+ -On MIT Kerberos, you run a "kadmin" session. On a machine with MIT Kerberos, you can use the command: - -[source] ----- -sudo kadmin.local ----- -Then, add HTTP principal and export its key to a keytab file with commands such as: - -[source] ----- -addprinc -randkey HTTP/www.mydomain.org@MYDOMAIN.ORG -ktadd -k /tmp/http.keytab HTTP/www.mydomain.org@MYDOMAIN.ORG ----- - -Ensure the keytab file `/tmp/http.keytab` is accessible on the host where {project_name} is running. - -==== Setup and configuration of {project_name} server - -[[_server_setup]] - -Install a Kerberos client on your machine. - -.Procedure -. Install a Kerberos client. If your machine runs Fedora, Ubuntu, or RHEL, install the link:https://www.freeipa.org/page/Downloads[freeipa-client] package, containing a Kerberos client and other utilities. -. Configure the Kerberos client (on Linux, the configuration settings are in the link:https://web.mit.edu/kerberos/krb5-1.12/doc/admin/conf_files/krb5_conf.html[/etc/krb5.conf] file ). -+ -Add your Kerberos realm to the configuration and configure the HTTP domains your server runs on. -+ -For example, for the MYDOMAIN.ORG realm, you can configure the `domain_realm` section like this: -+ -[source] ----- -[domain_realm] - .mydomain.org = MYDOMAIN.ORG - mydomain.org = MYDOMAIN.ORG ----- - -. Export the keytab file with the HTTP principal and ensure the file is accessible to the process running the {project_name} server. For production, ensure that the file is readable by this process only. -+ -For the MIT Kerberos example above, we exported keytab to the `/tmp/http.keytab` file. If your _Key Distribution Centre (KDC)_ and {project_name} run on the same host, the file is already available. - -===== Enabling SPNEGO processing - -By default, {project_name} disables SPNEGO protocol support. To enable it, go to the <<_authentication-flows, browser flow>> and enable *Kerberos*. - -.Browser flow -image:images/browser-flow.png[Browser Flow] - -Set the *Kerberos* requirement from _disabled_ to _alternative_ (Kerberos is optional) or _required_ (browser must have Kerberos enabled). If you have not configured the browser to work with SPNEGO or Kerberos, {project_name} falls back to the regular login screen. - -===== Configure Kerberos user storage federation providers - -You must now use <<_user-storage-federation,User Storage Federation>> to configure how {project_name} interprets Kerberos tickets. Two different federation providers exist with Kerberos authentication support. - -To authenticate with Kerberos backed by an LDAP server, configure the <<_ldap, LDAP Federation Provider>>. - -.Procedure -. Go to the configuration page for your LDAP provider. -+ -.Ldap kerberos integration -image:images/ldap-kerberos.png[LDAP Kerberos Integration] -+ -. Toggle *Allow Kerberos authentication* to *ON* - -*Allow Kerberos authentication* makes {project_name} use the Kerberos principal access user information so information can import into the {project_name} environment. - -If an LDAP server is not backing up your Kerberos solution, use the *Kerberos* User Storage Federation Provider. - -.Procedure -. Click *User Federation* in the menu. -. Select *Kerberos* from the *Add provider* select box. -+ -.Kerberos user storage provider -image:images/kerberos-provider.png[Kerberos User Storage Provider] - -The *Kerberos* provider parses the Kerberos ticket for simple principal information and imports the information into the local {project_name} database. -User profile information, such as first name, last name, and email, are not provisioned. - -==== Setup and configuration of client machines - -Client machines must have a Kerberos client and set up the `krb5.conf` as described <<_server_setup, above>>. The client machines must also enable SPNEGO login support in their browser. See link:https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/system-level_authentication_guide/configuring_applications_for_sso[configuring Firefox for Kerberos] if you are using the Firefox browser. - -The `.mydomain.org` URI must be in the `network.negotiate-auth.trusted-uris` configuration option. - -In Windows domains, clients do not need to adjust their configuration. Internet Explorer and Edge can already participate in SPNEGO authentication. - -ifeval::[{project_community}==true] -==== Example setups - -===== {Project_name} and FreeIPA docker image - -When you install https://www.docker.com/[docker], run a docker image with the FreeIPA server installed. FreeIPA provides an integrated security solution with MIT Kerberos and 389 LDAP server. The image also contains a {project_name} server configured with an LDAP Federation provider and enabled SPNEGO/Kerberos authentication against the FreeIPA server. See details https://github.com/mposolda/keycloak-freeipa-docker/blob/master/README.md[here]. - -===== ApacheDS testing Kerberos server - -For quick testing and unit tests, use a simple https://directory.apache.org/apacheds/[ApacheDS] Kerberos server. You must build {project_name} from the source and then run the Kerberos server with the maven-exec-plugin from our test suite. See details -https://github.com/keycloak/keycloak/blob/main/docs/tests.md#kerberos-server[here]. -endif::[] - -==== Credential delegation - -Kerberos supports the credential delegation. Applications may need access to the Kerberos ticket so they can re-use it to interact with other services secured by Kerberos. Because the {project_name} server processed the SPNEGO protocol, you must propagate the GSS credential to your application within the OpenID Connect token claim or a SAML assertion attribute. {project_name} transmits this to your application from the {project_name} server. To insert this claim into the token or assertion, each application must enable the built-in protocol mapper `gss delegation credential`. This mapper is available in the *Mappers* tab of the application's client page. See <<_protocol-mappers, Protocol Mappers>> chapter for more details. - -Applications must deserialize the claim it receives from {project_name} before using it to make GSS calls against other services. When you deserialize the credential from the access token to the GSSCredential object, create the GSSContext with this credential passed to the `GSSManager.createContext` method. For example: - -[source,java] ----- -// Obtain accessToken in your application. -KeycloakPrincipal keycloakPrincipal = (KeycloakPrincipal) servletReq.getUserPrincipal(); -AccessToken accessToken = keycloakPrincipal.getKeycloakSecurityContext().getToken(); - -// Retrieve Kerberos credential from accessToken and deserialize it -String serializedGssCredential = (String) accessToken.getOtherClaims(). - get(org.keycloak.common.constants.KerberosConstants.GSS_DELEGATION_CREDENTIAL); - -GSSCredential deserializedGssCredential = org.keycloak.common.util.KerberosSerializationUtils. - deserializeCredential(serializedGssCredential); - -// Create GSSContext to call other Kerberos-secured services -GSSContext context = gssManager.createContext(serviceName, krb5Oid, - deserializedGssCredential, GSSContext.DEFAULT_LIFETIME); ----- - -ifeval::[{project_community}==true] -Examples of this code exist in `examples/kerberos` in the {project_name} example distribution or demo distribution download. You can also check the example sources directly https://github.com/keycloak/keycloak/tree/main/examples/kerberos[here]. -endif::[] - -[NOTE] -==== -Configure `forwardable` Kerberos tickets in `krb5.conf` file and add support for delegated credentials to your browser. -==== - -[WARNING] -==== -Credential delegation has security implications, so use it only if necessary and only with HTTPS. See https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/system-level_authentication_guide/configuring_applications_for_sso[this article] for more details and an example. -==== - -==== Cross-realm trust - -In the Kerberos protocol, the `realm` is a set of Kerberos principals. The definition of these principals exists in the Kerberos database, which is typically an LDAP server. - -The Kerberos protocol allows cross-realm trust. For example, if 2 Kerberos realms, A and B, exist, then cross-realm trust will allow the users from realm A to access realm B's resources. Realm B trusts realm A. - -.Kerberos cross-realm trust -image:images/kerberos-trust-basic.png[] - -The {project_name} server supports cross-realm trust. To implement this, perform the following: - -* Configure the Kerberos servers for the cross-realm trust. Implementing this step depends on the Kerberos server implementations. This step is necessary to add the Kerberos principal `krbtgt/B@A` to the Kerberos databases of realm A and B. This principal must have the same keys on both Kerberos realms. The principals must have the same password, key version numbers, and ciphers in both realms. Consult the Kerberos server documentation for more details. - -[NOTE] -==== -The cross-realm trust is unidirectional by default. You must add the principal `krbtgt/A@B` to both Kerberos databases for bidirectional trust between realm A and realm B. However, trust is transitive by default. If realm B trusts realm A and realm C trusts realm B, then realm C trusts realm A without the principal, `krbtgt/C@A`, available. Additional configuration (for example, `capaths`) may be necessary on the Kerberos client-side so clients can find the trust path. Consult the Kerberos documentation for more details. -==== - -* Configure {project_name} server - -** When using an LDAP storage provider with Kerberos support, configure the server principal for realm B, as in this example: `HTTP/mydomain.com@B`. The LDAP server must find the users from realm A if users from realm A are to successfully authenticate to {project_name}, because {project_name} must perform the SPNEGO flow and then find the users. - -For example, Kerberos principal user `john@A` must be available in the LDAP under an LDAP DN such as `uid=john,ou=People,dc=example,dc=com`. If you want users from realm A and B to authenticate, ensure that LDAP can find users from both realms A and B. - -** When using a Kerberos user storage provider (typically, Kerberos without LDAP integration), configure the server principal as `HTTP/mydomain.com@B`, and users from Kerberos realms A and B must be able to authenticate. - -[WARNING] -==== -When using the Kerberos user storage provider, there cannot be conflicting users among Kerberos realms. If conflicting users exist, {project_name} maps them to the same user. -==== - -==== Troubleshooting - -If you have issues, enable additional logging to debug the problem: - -* Enable `Debug` flag in the Admin Console for Kerberos or LDAP federation providers -* Enable TRACE logging for category `org.keycloak` to receive more information in server logs -* Add system properties `-Dsun.security.krb5.debug=true` and `-Dsun.security.spnego.debug=true` diff --git a/server_admin/topics/authentication/otp-policies.adoc b/server_admin/topics/authentication/otp-policies.adoc deleted file mode 100644 index 8ce2e1cc4..000000000 --- a/server_admin/topics/authentication/otp-policies.adoc +++ /dev/null @@ -1,61 +0,0 @@ - -=== One Time Password (OTP) policies - -{project_name} has several policies for setting up a FreeOTP or Google Authenticator One-Time Password generator. Click the *Authentication* menu and click the *OTP Policy* tab. - -.Otp policy -image:images/otp-policy.png[OTP Policy] - -{project_name} generates a QR code on the OTP set-up page, based on information configured in the *OTP Policy* tab. FreeOTP and Google Authenticator scan the QR code when configuring OTP. - -==== Time-based or counter-based one time passwords - -The algorithms available in {project_name} for your OTP generators are time-based and counter-based. - -With Time-Based One Time Passwords (TOTP), the token generator will hash the current time and a shared secret. The server validates the OTP by comparing the hashes within a window of time to the submitted value. TOTPs are valid for a short window of time. - -With Counter-Based One Time Passwords (HOTP), {project_name} uses a shared counter rather than the current time. The {project_name} server increments the counter with each successful OTP login. Valid OTPs change after a successful login. - -TOTP is more secure than HOTP because the matchable OTP is valid for a short window of time, while the OTP for HOTP is valid for an indeterminate amount of time. HOTP is more user-friendly than TOTP because no time limit exists to enter the OTP. - -HOTP requires a database update every time the server increments the counter. This update is a performance drain on the authentication server during heavy load. To increase efficiency, TOTP does not remember passwords used, so there is no need to perform database updates. The drawback is that it is possible to re-use TOTPs in the valid time interval. - -==== TOTP configuration options - -===== OTP hash algorithm - -The default algorithm is SHA1. The other, more secure options are SHA256 and SHA512. - -===== Number of digits - -The length of the OTP. Short OTP's are user-friendly, easier to type, and easier to remember. Longer OTP's are more secure than shorter OTP's. - -===== Look around window - -The number of intervals the server attempts to match the hash. This option is present in {project_name} if the clock of the TOTP generator or authentication server becomes out-of-sync. The default value of 1 is adequate. For example, if the time interval for a token is 30 seconds, the default value of 1 means it will accept valid tokens in the 90-second window (time interval 30 seconds + look ahead 30 seconds + look behind 30 seconds). Every increment of this value increases the valid window by 60 seconds (look ahead 30 seconds + look behind 30 seconds). - -===== OTP token period - -The time interval in seconds the server matches a hash. Each time the interval passes, the token generator generates a TOTP. - -===== Reusable code - -Determine whether OTP tokens can be reused in the authentication process or user needs to wait for the next token. -Users cannot reuse those tokens by default, and the administrator needs to explicitly specify that those tokens can be reused. - -==== HOTP configuration options - -===== OTP hash algorithm - -The default algorithm is SHA1. The other, more secure options are SHA256 and SHA512. - -===== Number of digits - -The length of the OTP. Short OTPs are user-friendly, easier to type, and easier to remember. Longer OTPs are more secure than shorter OTPs. - -===== Look ahead window -The number of intervals the server attempts to match the hash. This option is present in {project_name} if the clock of the TOTP generator or authentication server become out-of-sync. The default value of 1 is adequate. This option is present in {project_name} to cover when the user's counter gets ahead of the server. - -===== Initial counter - -The value of the initial counter. diff --git a/server_admin/topics/authentication/password-policies.adoc b/server_admin/topics/authentication/password-policies.adoc deleted file mode 100644 index e768dbb36..000000000 --- a/server_admin/topics/authentication/password-policies.adoc +++ /dev/null @@ -1,88 +0,0 @@ - -[[_password-policies]] - -=== Password policies - -When {project_name} creates a realm, it does not associate password policies with the realm. You can set a simple password with no restrictions on its length, security, or complexity. Simple passwords are unacceptable in production environments. {project_name} has a set of password policies available through the Admin Console. - -.Procedure -. Click *Authentication* in the menu. -. Click the *Policies* tab. -. Select the policy to add in the *Add policy* drop-down box. -. Enter a value that applies to the policy chosen. -. Click *Save*. -+ -Password policy -image:images/password-policy.png[Password Policy] - -After saving the policy, {project_name} enforces the policy for new users and sets an Update Password action for existing users to ensure they change their password the next time they log in. For example: - -.Failed password policy -image:images/failed-password-policy.png[Failed Password Policy] - -==== Password policy types - -===== HashAlgorithm - -Passwords are not stored in cleartext. Before storage or validation, {project_name} hashes passwords using standard hashing algorithms. PBKDF2 is the only built-in and default algorithm available. See the link:{developerguide_link}[{developerguide_name}] on how to add your own hashing algorithm. - -[NOTE] -==== -If you change the hashing algorithm, password hashes in storage will not change until the user logs in. -==== - -===== Hashing iterations -Specifies the number of times {project_name} hashes passwords before storage or verification. The default value is 27,500. - -{project_name} hashes passwords to ensure that hostile actors with access to the password database cannot read passwords through reverse engineering. - -[NOTE] -==== -A high hashing iteration value can impact performance as it requires higher CPU power. -==== - -===== Digits - -The number of numerical digits required in the password string. - -===== Lowercase characters - -The number of lower case letters required in the password string. - -===== Uppercase characters - -The number of upper case letters required in the password string. - -===== Special characters - -The number of special characters required in the password string. - -===== Not username - -The password cannot be the same as the username. - -===== Not email - -The password cannot be the same as the email address of the user. - -===== Regular expression - -Password must match one or more defined regular expression patterns. - -===== Expire password - -The number of days the password is valid. When the number of days has expired, the user must change their password. - -===== Not recently used - -Password cannot be already used by the user. {project_name} stores a history of used passwords. The number of old passwords stored is configurable in {project_name}. - -===== Password blacklist -Password must not be in a blacklist file. - -* Blacklist files are UTF-8 plain-text files with Unix line endings. Every line represents a blacklisted password. -* {project_name} compares passwords in a case-insensitive manner. All passwords in the blacklist must be lowercase. -* The value of the blacklist file must be the name of the blacklist file. -* Blacklist files resolve against `${kc.home.dir}/data/password-blacklists/` by default. Customize this path using: -** The `keycloak.password.blacklists.path` property. -** The `blacklistsPath` property of the `passwordBlacklist` policy SPI configuration. diff --git a/server_admin/topics/authentication/recovery-codes.adoc b/server_admin/topics/authentication/recovery-codes.adoc deleted file mode 100644 index 639eaa5d6..000000000 --- a/server_admin/topics/authentication/recovery-codes.adoc +++ /dev/null @@ -1,21 +0,0 @@ -[[_recovery-codes]] - -=== Recovery Codes (RecoveryCodes) - -You can configure Recovery codes for two-factor authentication by adding 'Recovery Authentication Code Form' as a two-factor authenticator to your authentication flow. For an example of configuring this authenticator, see xref:webauthn_{context}[WebAuthn]. - -ifeval::[{project_product}==true] -:tech_feature_name: RecoveryCodes -:tech_feature_setting: -Dkeycloak.profile.feature.recovery_codes=enabled -:tech_feature_id: recovery-codes -include::../templates/techpreview.adoc[] -endif::[] - -ifeval::[{project_community}==true] - -[IMPORTANT] -==== -Please note that Recovery Codes support is in development. Use this feature experimentally. -==== - -endif::[] \ No newline at end of file diff --git a/server_admin/topics/authentication/webauthn.adoc b/server_admin/topics/authentication/webauthn.adoc deleted file mode 100644 index 6d61404ec..000000000 --- a/server_admin/topics/authentication/webauthn.adoc +++ /dev/null @@ -1,273 +0,0 @@ - -[id="webauthn_{context}"] -=== W3C Web Authentication (WebAuthn) - -{project_name} provides support for https://www.w3.org/TR/webauthn/[W3C Web Authentication (WebAuthn)]. {project_name} works as a WebAuthn's https://www.w3.org/TR/webauthn/#webauthn-relying-party[Relying Party (RP)]. - -[NOTE] -==== -WebAuthn's operations success depends on the user's WebAuthn supporting authenticator, browser, and platform. Make sure your authenticator, browser, and platform support the WebAuthn specification. -==== - -==== Setup - -The setup procedure of WebAuthn support for 2FA is the following: - -[[_webauthn-register]] -===== Enable WebAuthn authenticator registration - -. Click *Authentication* in the menu. -. Click the *Required Actions* tab. -. Toggle the *Webauthn Register* switch to *ON*. - -Toggle the *Default Action* switch to *ON* if you want all new users to be required to register their WebAuthn credentials. - -[[_webauthn-authenticator-setup]] -==== Adding WebAuthn authentication to a browser flow - -. Click *Authentication* in the menu. -. Click the *Browser* flow. -. Select *Duplicate* from the "Action list" to make a copy of the built-in *Browser* flow. -. Enter "WebAuthn Browser" as the name of the copy. -. Click *Duplicate*. -. Click the name to go to the details -. Click the trash can icon 🗑️ of the "WebAuthn Browser Browser - Conditional OTP" and click *Delete*. - -If you require WebAuthn for all users: - -. Click *+* menu of the *WebAuthn Browser Forms*. -. Click *Add step*. -. Click *WebAuthn Authenticator*. -. Click *Add*. -. Select *Required* for the *WebAuthn Authenticator* authentication type to set its requirement to required. -+ -image:images/webauthn-browser-flow-required.png[Webauthn browser flow required] -+ -. Click the *Action* menu at the top of the screen. -. Select *Bind flow* from the drop-down list. -. Select *Browser* from the drop-down list. -. Click *Save*. - -[NOTE] -==== -If a user does not have WebAuthn credentials, the user must register WebAuthn credentials. -==== - -Users can log in with WebAuthn if they have a WebAuthn credential registered only. So instead of adding the *WebAuthn Authenticator* execution, you can: - -.Procedure -. Click *+* menu of the *WebAuthn Browser Forms* row. -. Click *Add sub-flow*. -. Enter "Conditional 2FA" for the _name_ field. -. On the *WebAuthn Browser Forms* row, click the plus sign + and select *Add step*. -. Select *Conditional* for the *Conditional 2FA* to set its requirement to conditional. -. On the *Conditional 2FA* row, click the plus sign + and select *Add condition*. -. Click *Add condition*. -. Select *Condition - User Configured*. -. Click *Add*. -. Select *Required* for the *Condition - User Configured* to set its requirement to required. -. Drag and drop *WebAuthn Authenticator* into the *Conditional 2FA* flow -. Select *Alternative* for the *WebAuthn Authenticator* to set its requirement to alternative. -+ -image:images/webauthn-browser-flow-conditional.png[Webauthn browser flow conditional] - -The user can choose between using WebAuthn and OTP for the second factor: - -.Procedure -. On the *Conditional 2FA* row, click the plus sign + and select *Add step*. -. Click *Add step*. -. Select *OTP Form* from the list. -. Click *Add*. -. Select *Alternative* for the *OTP Form* to set its requirement to alternative. -+ -image:images/webauthn-browser-flow-conditional-with-OTP.png[WebAuthn browser flow conditional with OTP] - -==== Authenticate with WebAuthn authenticator - -After registering a WebAuthn authenticator, the user carries out the following operations: - -* Open the login form. The user must authenticate with a username and password. -* The user's browser asks the user to authenticate by using their WebAuthn authenticator. - -==== Managing WebAuthn as an administrator - -===== Managing credentials - -{project_name} manages WebAuthn credentials similarly to other credentials from xref:ref-user-credentials_{context}[User credential management]: - -* {project_name} assigns users a required action to create a WebAuthn credential from the *Reset Actions* list and select *Webauthn Register*. -* Administrators can delete a WebAuthn credential by clicking *Delete*. -* Administrators can view the credential's data, such as the AAGUID, by selecting *Show data...*. -* Administrators can set a label for the credential by setting a value in the *User Label* field and saving the data. - -[[_webauthn-policy]] -===== Managing policy - -Administrators can configure WebAuthn related operations as *WebAuthn Policy* per realm. - -.Procedure -. Click *Authentication* in the menu. -. Click the *Policy* tab. -. Click the *WebAuthn Policy* tab. -. Configure the items within the policy (see description below). -. Click *Save*. - -The configurable items and their description are as follows: - -|=== -|Configuration|Description - -|Relying Party Entity Name -|The readable server name as a WebAuthn Relying Party. This item is mandatory and applies to the registration of the WebAuthn authenticator. The default setting is "keycloak". For more details, see https://www.w3.org/TR/webauthn/#dictionary-pkcredentialentity[WebAuthn Specification]. - -|Signature Algorithms -|The algorithms telling the WebAuthn authenticator which signature algorithms to use for the https://www.w3.org/TR/webauthn/#iface-pkcredential[Public Key Credential]. {project_name} uses the Public Key Credential to sign and verify https://www.w3.org/TR/webauthn/#authentication-assertion[Authentication Assertions]. If no algorithms exist, the default https://datatracker.ietf.org/doc/html/rfc8152#section-8.1[ES256] is adapted. ES256 is an optional configuration item applying to the registration of WebAuthn authenticators. For more details, see https://www.w3.org/TR/webauthn/#dictdef-publickeycredentialparameters[WebAuthn Specification]. - -|Relying Party ID -|The ID of a WebAuthn Relying Party that determines the scope of https://www.w3.org/TR/webauthn/#public-key-credential[Public Key Credentials]. The ID must be the origin's effective domain. This ID is an optional configuration item applied to the registration of WebAuthn authenticators. If this entry is blank, {project_name} adapts the host part of {project_name}'s base URL. For more details, see https://www.w3.org/TR/webauthn/[WebAuthn Specification]. - -|Attestation Conveyance Preference -|The WebAuthn API implementation on the browser (https://www.w3.org/TR/webauthn/#webauthn-client[WebAuthn Client]) is the preferential method to generate Attestation statements. This preference is an optional configuration item applying to the registration of the WebAuthn authenticator. If no option exists, its behavior is the same as selecting "none". For more details, see https://www.w3.org/TR/webauthn/[WebAuthn Specification]. - -|Authenticator Attachment -|The acceptable attachment pattern of a WebAuthn authenticator for the WebAuthn Client. This pattern is an optional configuration item applying to the registration of the WebAuthn authenticator. For more details, see https://www.w3.org/TR/webauthn/#enumdef-authenticatorattachment[WebAuthn Specification]. - -|Require Resident Key -|The option requiring that the WebAuthn authenticator generates the Public Key Credential as https://www.w3.org/TR/webauthn/[Client-side-resident Public Key Credential Source]. This option applies to the registration of the WebAuthn authenticator. If left blank, its behavior is the same as selecting "No". For more details, see https://www.w3.org/TR/webauthn/#dom-authenticatorselectioncriteria-requireresidentkey[WebAuthn Specification]. - -|User Verification Requirement -|The option requiring that the WebAuthn authenticator confirms the verification of a user. This is an optional configuration item applying to the registration of a WebAuthn authenticator and the authentication of a user by a WebAuthn authenticator. If no option exists, its behavior is the same as selecting "preferred". For more details, see https://www.w3.org/TR/webauthn/#dom-authenticatorselectioncriteria-userverification[WebAuthn Specification for registering a WebAuthn authenticator] and https://www.w3.org/TR/webauthn/#dom-publickeycredentialrequestoptions-userverification[WebAuthn Specification for authenticating the user by a WebAuthn authenticator]. - -|Timeout -|The timeout value, in seconds, for registering a WebAuthn authenticator and authenticating the user by using a WebAuthn authenticator. If set to zero, its behavior depends on the WebAuthn authenticator's implementation. The default value is 0. For more details, see https://www.w3.org/TR/webauthn/#dom-publickeycredentialcreationoptions-timeout[WebAuthn Specification for registering a WebAuthn authenticator] and https://www.w3.org/TR/webauthn/#dom-publickeycredentialrequestoptions-timeout[WebAuthn Specification for authenticating the user by a WebAuthn authenticator]. - -|Avoid Same Authenticator Registration -|If enabled, {project_name} cannot re-register an already registered WebAuthn authenticator. - -|Acceptable AAGUIDs -|The white list of AAGUIDs which a WebAuthn authenticator must register against. - -|=== - -==== Attestation statement verification - -When registering a WebAuthn authenticator, {project_name} verifies the trustworthiness of the attestation statement generated by the WebAuthn authenticator. {project_name} requires the trust anchor's certificates imported into the [truststore](https://www.keycloak.org/server/keycloak-truststore). - -To omit this validation, disable this truststore or set the WebAuthn policy's configuration item "Attestation Conveyance Preference" to "none". - - -==== Managing WebAuthn credentials as a user - -===== Register WebAuthn authenticator - -The appropriate method to register a WebAuthn authenticator depends on whether the user has already registered an account on {project_name}. - -===== New user - -If the *WebAuthn Register* required action is *Default Action* in a realm, new users must set up the WebAuthn security key after their first login. - -.Procedure - -. Open the login form. -. Click *Register*. -. Fill in the items on the form. -. Click *Register*. - -After successfully registering, the browser asks the user to enter the text of their WebAuthn authenticator's label. - -===== Existing user - -If `WebAuthn Authenticator` is set up as required as shown in the first example, then when existing users try to log in, they are required to register their WebAuthn authenticator automatically: - -.Procedure - -. Open the login form. -. Enter the items on the form. -. Click *Save*. -. Click *Login*. - -After successful registration, the user's browser asks the user to enter the text of their WebAuthn authenticator's label. - -[[_webauthn_passwordless]] -==== Passwordless WebAuthn together with Two-Factor - -{project_name} uses WebAuthn for two-factor authentication, but you can use WebAuthn as the first-factor authentication. In this case, users with `passwordless` WebAuthn credentials can authenticate to {project_name} without a password. {project_name} can use WebAuthn as both the passwordless and two-factor authentication mechanism in the context of a realm and a single authentication flow. - -An administrator typically requires that Security Keys registered by users for the WebAuthn passwordless authentication meet different requirements. For example, the security keys may require users to authenticate to the security key using a PIN, or the security key attests with a stronger certificate authority. - -Because of this, {project_name} permits administrators to configure a separate `WebAuthn Passwordless Policy`. There is a required `Webauthn Register Passwordless` action of type and separate authenticator of type `WebAuthn Passwordless Authenticator`. - -===== Setup - -Set up WebAuthn passwordless support as follows: - -. (if not already present) Register a new required action for WebAuthn passwordless support. Use the steps described in <<_webauthn-register, Enable WebAuthn Authenticator Registration>>. Register the `Webauthn Register Passwordless` action. - -. Configure the policy. You can use the steps and configuration options described in <<_webauthn-policy, Managing Policy>>. Perform the configuration in the Admin Console in the tab *WebAuthn Passwordless Policy*. Typically the requirements for the security key will be stronger than for the two-factor policy. For example, you can set the *User Verification Requirement* to *Required* when you configure the passwordless policy. - -. Configure the authentication flow. Use the *WebAuthn Browser* flow described in <<_webauthn-authenticator-setup, Adding WebAuthn Authentication to a Browser Flow>>. Configure the flow as follows: -+ -** The *WebAuthn Browser Forms* subflow contains *Username Form* as the first authenticator. Delete the default *Username Password Form* authenticator and add the *Username Form* authenticator. This action requires the user to provide a username as the first step. -+ -** There will be a required subflow, which can be named *Passwordless Or Two-factor*, for example. This subflow indicates the user can authenticate with Passwordless WebAuthn credential or with Two-factor authentication. -+ -** The flow contains *WebAuthn Passwordless Authenticator* as the first alternative. -+ -** The second alternative will be a subflow named *Password And Two-factor Webauthn*, for example. This subflow contains a *Password Form* and a *WebAuthn Authenticator*. - -The final configuration of the flow looks similar to this: - -.PasswordLess flow -image:images/webauthn-passwordless-flow.png[PasswordLess flow] - -You can now add *WebAuthn Register Passwordless* as the required action to a user, already known to {project_name}, to test this. During the first authentication, the user must use the password and second-factor WebAuthn credential. The user does not need to provide the password and second-factor WebAuthn credential if they use the WebAuthn Passwordless credential. - -[[_webauthn_loginless]] -==== LoginLess WebAuthn - -{project_name} uses WebAuthn for two-factor authentication, but you can use WebAuthn as the first-factor authentication. In this case, users with `passwordless` WebAuthn credentials can authenticate to {project_name} without submitting a login or a password. {project_name} can use WebAuthn as both the loginless/passwordless and two-factor authentication mechanism in the context of a realm. - -An administrator typically requires that Security Keys registered by users for the WebAuthn loginless authentication meet different requirements. Loginless authentication requires users to authenticate to the security key (for example by using a PIN code or a fingerprint) and that the cryptographic keys associated with the loginless credential are stored physically on the security key. Not all security keys meet that kind of requirements. Check with your security key vendor if your device supports 'user verification' and 'resident key'. See <<_webauthn-supported-keys, Supported Security Keys>>. - -{project_name} permits administrators to configure the `WebAuthn Passwordless Policy` in a way that allows loginless authentication. Note that loginless authentication can only be configured with `WebAuthn Passwordless Policy` and with `WebAuthn Passwordless` credentials. WebAuthn loginless authentication and WebAuthn passwordless authentication can be configured on the same realm but will share the same policy `WebAuthn Passwordless Policy`. - -.Procedure -===== Setup - -Set up WebAuthn Loginless support as follows: - -. (if not already present) Register a new required action for WebAuthn passwordless support. Use the steps described in <<_webauthn-register, Enable WebAuthn Authenticator Registration>>. Register the `Webauthn Register Passwordless` action. - -. Configure the `WebAuthn Passwordless Policy`. Perform the configuration in the Admin Console, `Authentication` section, in the tab `Policies` -> `WebAuthn Passwordless Policy`. You have to set *User Verification Requirement* to *required* and *Require Resident Key* to *Yes* when you configure the policy for loginless scenario. Note that since there isn't a dedicated Loginless policy it won't be possible to mix authentication scenarios with user verification=no/resident key=no and loginless scenarios (user verification=yes/resident key=yes). Storage capacity is usually very limited on security keys meaning that you won't be able to store many resident keys on your security key. - -. Configure the authentication flow. Create a new authentication flow, add the "WebAuthn Passwordless" execution and set the Requirement setting of the execution to *Required* - -The final configuration of the flow looks similar to this: - -.LoginLess flow -image:images/webauthn-loginless-flow.png[LoginLess flow] - -You can now add the required action `WebAuthn Register Passwordless` to a user, already known to {project_name}, to test this. The user with the required action configured will have to authenticate (with a username/password for example) and will then be prompted to register a security key to be used for loginless authentication. - -===== Vendor specific remarks - -====== Compatibility check list - -Loginless authentication with {project_name} requires the security key to meet the following features - -** FIDO2 compliance: not to be confused with FIDO/U2F -** User verification: the ability for the security key to authenticate the user (prevents someone finding your security key to be able to authenticate loginless and passwordless) -** Resident key: the ability for the security key to store the login and the cryptographic keys associated with the client application - -====== Windows Hello - -To use Windows Hello based credentials to authenticate against {project_name}, configure the *Signature Algorithms* setting of the `WebAuthn Passwordless Policy` to include the *RS256* value. Note that some browsers don't allow access to platform security key (like Windows Hello) inside private windows. - -[[_webauthn-supported-keys]] -====== Supported security keys - -The following security keys have been successfully tested for loginless authentication with {project_name}: - -* Windows Hello (Windows 10 21H1/21H2) -* Yubico Yubikey 5 NFC -* Feitian ePass FIDO-NFC diff --git a/server_admin/topics/authentication/x509.adoc b/server_admin/topics/authentication/x509.adoc deleted file mode 100644 index 387b81799..000000000 --- a/server_admin/topics/authentication/x509.adoc +++ /dev/null @@ -1,188 +0,0 @@ - -[[_x509]] -=== X.509 client certificate user authentication - -{project_name} supports logging in with an X.509 client certificate if you have configured the server to use mutual SSL authentication. - -A typical workflow: - -* A client sends an authentication request over SSL/TLS channel. -* During the SSL/TLS handshake, the server and the client exchange their x.509/v3 certificates. -* The container ({appserver_name}) validates the certificate PKIX path and the certificate expiration date. -* The x.509 client certificate authenticator validates the client certificate by using the following methods: -+ -** Checks the certificate revocation status by using CRL or CRL Distribution Points. -** Checks the Certificate revocation status by using OCSP (Online Certificate Status Protocol). -** Validates whether the key in the certificate matches the expected key. -** Validates whether the extended key in the certificate matches the expected extended key. -+ -* If any of the these checks fail, the x.509 authentication fails. Otherwise, the authenticator extracts the certificate identity and maps it to an existing user. - -When the certificate maps to an existing user, the behavior diverges depending on the authentication flow: - -* In the Browser Flow, the server prompts users to confirm their identity or sign in with a username and password. -* In the Direct Grant Flow, the server signs in the user. - -IMPORTANT: Note that it is the responsibility of the web container to validate certificate PKIX path. X.509 authenticator on the -{project_name} side provides just the additional support for check the certificate expiration, certificate revocation status and key usage. If you are -using {project_name} deployed behind reverse proxy, make sure that your reverse proxy is configured to validate PKIX path. If you -do not use reverse proxy and users directly access the {appserver_name}, you should be fine as {appserver_name} makes sure that PKIX path is validated as long -as it is configured as described below. - -==== Features - -Supported Certificate Identity Sources: - -* Match SubjectDN by using regular expressions -* X500 Subject's email attribute -* X500 Subject's email from Subject Alternative Name Extension (RFC822Name General Name) -* X500 Subject's other name from Subject Alternative Name Extension. This other name is the User Principal Name (UPN), typically. -* X500 Subject's Common Name attribute -* Match IssuerDN by using regular expressions -* Certificate Serial Number -* Certificate Serial Number and IssuerDN -* SHA-256 Certificate thumbprint -* Full certificate in PEM format - -===== Regular expressions -{project_name} extracts the certificate identity from Subject DN or Issuer DN by using a regular expression as a filter. For example, this regular expression matches the email attribute: - -``` -emailAddress=(.*?)(?:,|$) -``` - -The regular expression filtering applies if the `Identity Source` is set to either `Match SubjectDN using regular expression` or `Match IssuerDN using regular expression`. - -====== Mapping certificate identity to an existing user - -The certificate identity mapping can map the extracted user identity to an existing user's username, email, or a custom attribute whose value matches the certificate identity. For example, setting `Identity source` to _Subject's email_ or `User mapping method` to _Username or email_ makes the X.509 client certificate authenticator use the email attribute in the certificate's Subject DN as the search criteria when searching for an existing user by username or by email. - -[IMPORTANT] -==== -* If you disable *Login with email* at realm settings, the same rules apply to certificate authentication. Users are unable to log in by using the email attribute. -* Using `Certificate Serial Number and IssuerDN` as an identity source requires two custom attributes for the serial number and the IssuerDN. -* `SHA-256 Certificate thumbprint` is the lowercase hexadecimal representation of SHA-256 certificate thumbprint. -* Using `Full certificate in PEM format` as an identity source is limited to the custom attributes mapped to external federation sources, such as LDAP. {project_name} cannot store certificates in its database due to length limitations, so in the case of LDAP, you must enable `Always Read Value From LDAP`. -==== - -====== Extended certificate validation -* Revocation status checking using CRL. -* Revocation status checking using CRL/Distribution Point. -* Revocation status checking using OCSP/Responder URI. -* Certificate KeyUsage validation. -* Certificate ExtendedKeyUsage validation. - -[[_browser_flow]] -==== Adding X.509 client certificate authentication to browser flows - -. Click *Authentication* in the menu. -. Click the *Browser* flow. -. From the *Action* list, select *Duplicate*. -. Enter a name for the copy. -. Click *Duplicate*. -. Click *Add step*. -. Click "X509/Validate Username Form". -. Click *Add*. -+ -.X509 execution -image:images/x509-execution.png[X509 Execution] - -. Click and drag the "X509/Validate Username Form" over the "Browser Forms" execution. -. Set the requirement to "ALTERNATIVE". -+ -.X509 browser flow -image:images/x509-browser-flow.png[X509 Browser Flow] -+ -. Click the *Action* menu. -. Click the *Bind flow*. -. Click the *Browser flow* from the drop-down list. -. Click *Save*. -+ -.X509 browser flow bindings -image:images/x509-browser-flow-bindings.png[X509 Browser Flow Bindings] - -==== Configuring X.509 client certificate authentication - -.X509 configuration -image:images/x509-configuration.png[X509 Configuration] - -*User Identity Source*:: -Defines the method for extracting the user identity from a client certificate. - -*Canonical DN representation enabled*:: -Defines whether to use canonical format to determine a distinguished name. The official link:https://docs.oracle.com/javase/8/docs/api/javax/security/auth/x500/X500Principal.html#getName-java.lang.String-[Java API documentation] describes the format. This option affects the two User Identity Sources _Match SubjectDN using regular expression_ and _Match IssuerDN using regular expression_ only. Enable this option when you set up a new {project_name} instance. Disable this option to retain backward compatibility with existing {project_name} instances. - -*Enable Serial Number hexadecimal representation*:: -Represent the link:https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.2[serial number] as hexadecimal. The serial number with the sign bit set to 1 must be left padded with 00 octet. For example, a serial number with decimal value _161_, or _a1_ in hexadecimal representation is encoded as _00a1_, according to RFC5280. See link:https://datatracker.ietf.org/doc/html/rfc5280#appendix-B[RFC5280, appendix-B] for more details. - -*A regular expression*:: -A regular expression to use as a filter for extracting the certificate identity. The expression must contain a single group. - -*User Mapping Method*:: -Defines the method to match the certificate identity with an existing user. _Username or email_ searches for existing users by username or email. _Custom Attribute Mapper_ searches for existing users with a custom attribute that matches the certificate identity. The name of the custom attribute is configurable. - -*A name of user attribute*:: -A custom attribute whose value matches against the certificate identity. Use multiple custom attributes when attribute mapping is related to multiple values, For example, 'Certificate Serial Number and IssuerDN'. - -*CRL Checking Enabled*:: -Check the revocation status of the certificate by using the Certificate Revocation List. The location of the list is defined in the *CRL file path* attribute. - -*Enable CRL Distribution Point to check certificate revocation status*:: -Use CDP to check the certificate revocation status. Most PKI authorities include CDP in their certificates. - -*CRL file path*:: -The path to a file containing a CRL list. The value must be a path to a valid file if the *CRL Checking Enabled* option is enabled. - -*OCSP Checking Enabled*:: -Checks the certificate revocation status by using Online Certificate Status Protocol. - -*OCSP Fail-Open Behavior*:: -By default the OCSP check must return a positive response in order to continue with a successful authentication. Sometimes however this check can be inconclusive: for example, the OCSP server could be unreachable, overloaded, or the client certificate may not contain an OCSP responder URI. When this setting is turned ON, authentication will be denied only if an explicit negative response is received by the OCSP responder and the certificate is definitely revoked. If a valid OCSP response is not available the authentication attempt will be accepted. - -*OCSP Responder URI*:: -Override the value of the OCSP responder URI in the certificate. - -*Validate Key Usage*:: -Verifies the certificate's KeyUsage extension bits are set. For example, "digitalSignature,KeyEncipherment" verifies if bits 0 and 2 in the KeyUsage extension are set. -Leave this parameter empty to disable the Key Usage validation. See link:https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.3[RFC5280, Section-4.2.1.3] for more information. {project_name} raises an error when a key usage mismatch occurs. - -*Validate Extended Key Usage*:: -Verifies one or more purposes defined in the Extended Key Usage extension. See link:https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.12[RFC5280, Section-4.2.1.12] for more information. Leave this parameter empty to disable the Extended Key Usage validation. {project_name} raises an error when flagged as critical by the issuing CA and a key usage extension mismatch occurs. - -*Validate Certificate Policy*:: -Verifies one or more policy OIDs as defined in the Certificate Policy extension. See link:https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.4[RFC5280, Section-4.2.1.4]. Leave the parameter empty to disable the Certificate Policy validation. Multiple policies should be separated using a comma. - -*Certificate Policy Validation Mode*:: -When more than one policy is specified in the `Validate Certificate Policy` setting, it decides whether the matching should check for all requested policies to be present, or one match is enough for a successful authentication. Default value is `All`, meaning that all requested policies should be present in the client certificate. - -*Bypass identity confirmation*:: -If enabled, X.509 client certificate authentication does not prompt the user to confirm the certificate identity. {project_name} signs in the user upon successful authentication. - -*Revalidate client certificate*:: -If set, the client certificate trust chain will be always verified at the application level using the certificates present in the configured trust store. This can be useful if the underlying web server does not enforce client certificate chain validation, for example because it is behind a non-validating load balancer or reverse proxy, or when the number of allowed CAs is too large for the mutual SSL negotiation (most browsers cap the maximum SSL negotiation packet size at 32767 bytes, which corresponds to about 200 advertised CAs). By default this option is off. - -==== Adding X.509 Client Certificate Authentication to a Direct Grant Flow - - -. Click *Authentication* in the menu. -. Select *Duplicate* from the "Action list" to make a copy of the built-in "Direct grant" flow. -. Enter a name for the copy. -. Click *Duplicate*. -. Click the created flow. -. Click the trash can icon 🗑️ of the "Username Validation" and click *Delete*. -. Click the trash can icon 🗑️ of the "Password" and click *Delete*. -. Click *Add step*. -. Click "X509/Validate Username". -. Click *Add*. -+ -.X509 direct grant execution -image:images/x509-directgrant-execution.png[X509 Direct Grant Execution] -+ -. Set up the x509 authentication configuration by following the steps described in the <<_browser_flow, x509 Browser Flow>> section. -. Click the *Bindings* tab. -. Click the *Direct Grant Flow* drop-down list. -. Click the newly created "x509 Direct Grant" flow. -. Click *Save*. -+ -.X509 direct grant flow bindings -image:images/x509-directgrant-flow-bindings.png[X509 Direct Grant Flow Bindings] diff --git a/server_admin/topics/clients/assembly-client-oidc.adoc b/server_admin/topics/clients/assembly-client-oidc.adoc deleted file mode 100644 index 223ef48ac..000000000 --- a/server_admin/topics/clients/assembly-client-oidc.adoc +++ /dev/null @@ -1,20 +0,0 @@ - -[[_oidc_clients]] -= Managing OpenID Connect clients -[role="_abstract"] -xref:con-oidc_{context}[OpenID Connect] is the recommended protocol to secure applications. It was designed from the ground up to be web friendly and it works best with HTML5/JavaScript applications. - -include::oidc/proc-creating-oidc-client.adoc[leveloffset=+1] -include::oidc/con-basic-settings.adoc[leveloffset=+1] -include::oidc/con-advanced-settings.adoc[leveloffset=+1] - -include::oidc/con-confidential-client-credentials.adoc[leveloffset=+1] - -include::oidc/con-secret-rotation.adoc[leveloffset=+1] - -include::oidc/proc-secret-rotation.adoc[leveloffset=+1] - -include::oidc/proc-using-a-service-account.adoc[leveloffset=+1] - -include::oidc/con-audience.adoc[leveloffset=+1] - diff --git a/server_admin/topics/clients/client-policies.adoc b/server_admin/topics/clients/client-policies.adoc deleted file mode 100644 index 94b1f3824..000000000 --- a/server_admin/topics/clients/client-policies.adoc +++ /dev/null @@ -1,163 +0,0 @@ - -[[_client_policies]] -= Client Policies - -To make it easy to secure client applications, it is beneficial to realize the following points in a unified way. - -* Setting policies on what configuration a client can have -* Validation of client configurations -* Conformance to a required security standards and profiles such as Financial-grade API (FAPI) - -To realize these points in a unified way, _Client Policies_ concept is introduced. - -== Use-cases - -Client Policies realize the following points mentioned as follows. - -Setting policies on what configuration a client can have:: - Configuration settings on the client can be enforced by client policies during client creation/update, but also during OpenID Connect requests to {project_name} server, which are related to particular client. - {project_name} supports similar thing also through the Client Registration Policies described in the link:{adapterguide_link}#_client_registration_policies[{adapterguide_name}]. - However, Client Registration Policies can only cover OIDC Dynamic Client Registration. Client Policies cover not only what Client Registration Policies can do, but other client - registration and configuration ways. The current plans are for Client Registration to be replaced by Client Policies. - -Validation of client configurations:: - {project_name} supports validation whether the client follows settings like Proof Key for Code Exchange, - Request Object Signing Algorithm, Holder-of-Key Token, and so on some endpoints like Authorization Endpoint, Token Endpoint, and so on. - These can be specified by each setting item (on Admin Console, switch, pull-down menu and so on). To make the client application secure, the administrator needs to set - many settings in the appropriate way, which makes it difficult for the administrator to secure the client application. - Client Policies can do these validation of client configurations mentioned just above and they can also be used to autoconfigure some client configuration switches to meet - the advanced security requirements. In the future, individual client configuration settings may be replaced by Client Policies directly performing required validations. - -Conformance to a required security standards and profiles such as FAPI:: - The _Global client profiles_ are client profiles pre-configured in {project_name} by default. They are pre-configured to be compliant with standard security profiles like link:{adapterguide_link}#_fapi-support[FAPI], - which makes it easy for the administrator to secure their client application to be compliant with the particular security profile. At this moment, {project_name} has global - profiles for the support of FAPI 1 specification. The administrator will just need to configure the client policies to specify which clients should - be compliant with the FAPI. The administrator can configure client profiles and client policies, so that {project_name} clients can be easily made compliant with various other - security profiles like SPA, Native App, Open Banking and so on. - -== Protocol - -The client policy concept is independent of any specific protocol. However, {project_name} currently supports it only just for the link:{adapterguide_link}#_oidc[OpenID Connect (OIDC) protocol]. - -== Architecture - -Client Policies consists of the four building blocks: Condition, Executor, Profile and Policy. - -=== Condition - -A condition determines to which client a policy is adopted and when it is adopted. Some conditions are checked at the time of client create/update when some other conditions are -checked during client requests (OIDC Authorization request, Token endpoint request and so on). The condition checks whether one specified criteria is satisfied. For example, -some condition checks whether the access type of the client is confidential. - -The condition can not be used solely by itself. It can be used in a <<_client_policy_policy,policy>> that is described afterwards. - -A condition can be configurable the same as other configurable providers. What can be configured depends on each condition's nature. - -The following conditions are provided: - -The way of creating/updating a client:: - * Dynamic Client Registration (Anonymous or Authenticated with Initial access token or Registration access token) - * Admin REST API (Admin Console and so on) - -So for example when creating a client, a condition can be configured to evaluate to true when this client is created by OIDC Dynamic Client Registration without initial -access token (Anonymous Dynamic Client Registration). So this condition can be used for example to ensure that all clients registered through OIDC Dynamic Client Registration -are FAPI compliant. - -Author of a client (Checked by presence to the particular role or group):: - On OpenID Connect dynamic client registration, an author of a client is the end user who was authenticated to get an access token for generating a new client, not Service - Account of the existing client that actually accesses the registration endpoint with the access token. On registration by Admin REST API, an author of a client is the end user - like the administrator of the {project_name}. - -Client Access Type (confidential, public, bearer-only):: - For example when a client sends an authorization request, a policy is adopted if this client is confidential. - -Client Scope:: - Evaluates to true if the client has a particular client scope (either as default or as an optional scope used in current request). This can be used for example to ensure that - OIDC authorization requests with scope `fapi-example-scope` need to be FAPI compliant. - -Client Role:: - Applies for clients with the client role of the specified name - -Client Domain Name, Host or IP Address:: - Applied for specific domain names of client. Or for the cases when the administrator registers/updates client from particular Host or IP Address. - -Any Client:: - This condition always evaluates to true. It can be used for example to ensure that all clients in the particular realm are FAPI compliant. - -=== Executor - -An executor specifies what action is executed on a client to which a policy is adopted. The executor executes one or several specified actions. For example, -some executor checks whether the value of the parameter `redirect_uri` in the authorization request matches exactly with one of the pre-registered redirect URIs on -Authorization Endpoint and rejects this request if not. - -The executor can not be used solely by itself. It can be used in a <<_client_policy_profile,profile>> that is described afterwards. - -An executor can be configurable the same as other configurable providers. What can be configured depends on the nature of each executor. - -An executor acts on various events. An executor implementation can ignore certain types of events (For example, executor for checking OIDC `request` object acts just -on the OIDC authorization request). Events are: - -* Creating a client (including creation through dynamic client registration) -* Updating a client -* Sending an authorization request -* Sending a token request -* Sending a token refresh request -* Sending a token revocation request -* Sending a token introspection request -* Sending a userinfo request -* Sending a logout request with a refresh token - -On each event, an executor can work in multiple phases. For example, on creating/updating a client, the executor can modify the client configuration by autoconfigure specific client -settings. After that, the executor validates this configuration in validation phase. - -One of several purposes for this executor is to realize the security requirements of client conformance profiles like FAPI. To do so, the following executors are needed: - -* Enforce secure <<_client-credentials,Client Authentication method>> is used for the client -* Enforce <<_mtls-client-certificate-bound-tokens,Holder-of-key tokens>> are used -* Enforce <<_proof-key-for-code-exchange,Proof Key for Code Exchange (PKCE)>> is used -* Enforce secure signature algorithm for <<_client-credentials,Signed JWT client authentication (private-key-jwt)>> is used -* Enforce HTTPS redirect URI and make sure that configured redirect URI does not contain wildcards -* Enforce OIDC `request` object satisfying high security level -* Enforce Response Type of OIDC Hybrid Flow including ID Token used as _detached signature_ as described in the FAPI 1 specification, which means that ID Token returned from Authorization response won't contain user profile data -* Enforce more secure `state` and `nonce` parameters treatment for preventing CSRF -* Enforce more secure signature algorithm when client registration -* Enforce `binding_message` parameter is used for CIBA requests -* Enforce <<_secret_rotation, Client Secret Rotation>> -* Enforce Client Registration Access Token -* Enforce checking if a client is the one to which an intent was issued in a use case where an intent is issued before starting an authorization code flow to get an access token like UK OpenBanking - -[[_client_policy_profile]] -=== Profile - -A profile consists of several executors, which can realize a security profile like FAPI. Profile can be configured by the Admin REST API (Admin Console) together with its executors. -Three _global profiles_ exist and they are configured in {project_name} by default with pre-configured executors compliant with the FAPI Baseline, FAPI Advanced and FAPI CIBA specifications. -More details exist in the FAPI section of the link:{adapterguide_link}#_fapi-support[{adapterguide_name}]. - -[[_client_policy_policy]] -=== Policy - -A policy consists of several conditions and profiles. The policy can be adopted to clients satisfying all conditions of this policy. The policy refers several profiles and all -executors of these profiles execute their task against the client that this policy is adopted to. - - -== Configuration - -Policies, profiles, conditions, executors can be configured by Admin REST API, which means also the Admin Console. To do so, there is a tab _Realm_ -> _Realm Settings_ -> _Client Policies_ -, which means the administrator can have client policies per realm. - -The _Global Client Profiles_ are automatically available in each realm. However there are no client policies -configured by default. This means that the administrator is always required to create any client policy if they want for example the clients of his realm to be FAPI compliant. Global -profiles cannot be updated, but the administrator can easily use them as a template and create their own profile if they want to do some slight changes in the global profile configurations. -There is JSON Editor available in the Admin Console, which simplifies the creation of new profile based on some global profile. - -== Backward Compatibility - -Client Policies can replace Client Registration Policies described in the link:{adapterguide_link}#_client_registration_policies[{adapterguide_name}]. -However, Client Registration Policies also still co-exist. This means that for example during a Dynamic Client Registration request to create/update a client, both client policies and -client registration policies are applied. - -The current plans are for the Client Registration Policies feature to be removed and the existing client registration policies will be migrated into new client policies automatically. - -== Client Secret Rotation Example - -See an example configuration for <<_proc-secret-rotation,client secret rotation>>. diff --git a/server_admin/topics/clients/con-client-links.adoc b/server_admin/topics/clients/con-client-links.adoc deleted file mode 100644 index f27c3a0dc..000000000 --- a/server_admin/topics/clients/con-client-links.adoc +++ /dev/null @@ -1,15 +0,0 @@ - -[id="con-client-links_{context}"] -= Client links -[role="_abstract"] -To link from one client to another, {project_name} provides a redirect endpoint: `/realms/realm_name/clients/\{client-id}/redirect`. - -If a client accesses this endpoint using a `HTTP GET` request, {project_name} returns the configured base URL for the provided Client and Realm in the form of an `HTTP 307` (Temporary Redirect) in the response's `Location` header. As a result of this, a client needs only to know the Realm name and the Client ID to link to them. This indirection avoids hard-coding client base URLs. - -As an example, given the realm `master` and the client-id `account`: - -[source,subs=+attributes] ----- -http://host:port{kc_realms_path}/master/clients/account/redirect ----- -This URL temporarily redirects to: http://host:port{kc_realms_path}/master/account diff --git a/server_admin/topics/clients/con-client-scopes.adoc b/server_admin/topics/clients/con-client-scopes.adoc deleted file mode 100644 index ca25d9244..000000000 --- a/server_admin/topics/clients/con-client-scopes.adoc +++ /dev/null @@ -1,111 +0,0 @@ -//[id="con-client-scopes_{context}"]// - -[[_client_scopes]] -= Client scopes - -[role="_abstract"] -Use {project_name} to define a shared client configuration in an entity called a _client scope_. A _client scope_ configures <<_protocol-mappers, protocol mappers>> and <<_role_scope_mappings, role scope mappings>> for multiple clients. - -Client scopes also support the OAuth 2 *scope* parameter. Client applications use this parameter to request claims or roles in the access token, depending on the requirement of the application. - -include::proc-creating-client-scopes.adoc[] - - -== Protocol -When you create a client scope, choose the *Protocol*. Clients linked in the same scope must have the same protocol. - -Each realm has a set of pre-defined built-in client scopes in the menu. - -* SAML protocol: The *role_list*. This scope contains one protocol mapper for the roles list in the SAML assertion. -* OpenID Connect protocol: Several client scopes are available: -** *roles* -+ -This scope is not defined in the OpenID Connect specification and is not added automatically to the *scope* claim in the access token. This scope has mappers, which are used to add the roles of the user to the access token and -add audiences for clients that have at least one client role. These mappers are described in more detail in the <<_audience_resolve, Audience section>>. -+ -** *web-origins* -+ -This scope is also not defined in the OpenID Connect specification and not added to the *scope* claiming the access token. This scope is used to add allowed web origins to the access token *allowed-origins* claim. -+ -** *microprofile-jwt* -+ -This scope handles claims defined in the https://wiki.eclipse.org/MicroProfile/JWT_Auth[MicroProfile/JWT Auth Specification]. This scope defines a user property mapper for the *upn* claim and a realm role mapper for the *groups* claim. These mappers can be changed so different properties can be used to create the MicroProfile/JWT specific claims. -+ -** *offline_access* -+ -This scope is used in cases when clients need to obtain offline tokens. More details on offline tokens is available in the <<_offline-access, Offline Access section>> and in the https://openid.net/specs/openid-connect-core-1_0.html#OfflineAccess[OpenID Connect specification]. -+ -** *profile* -** *email* -** *address* -** *phone* - -The client scopes *profile*, *email*, *address* and *phone* are defined in the https://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims[OpenID Connect specification]. These scopes do not have any role scope mappings defined but they do have protocol mappers defined. These mappers correspond to the claims defined in the OpenID Connect specification. - -For example, when you open the *phone* client scope and open the *Mappers* tab, you will see the protocol mappers which correspond to the claims defined in the specification for the scope *phone*. - -.Client scope mappers -image:images/client-scopes-phone.png[] - -When the *phone* client scope is linked to a client, the client automatically inherits all the protocol mappers defined in the *phone* client scope. Access tokens issued for this client contain the phone number information about the user, assuming that the user has a defined phone number. - -Built-in client scopes contain the protocol mappers as defined in the specification. You are free to edit client scopes and create, update, or remove any protocol mappers or role scope mappings. - -== Consent related settings -Client scopes contain options related to the consent screen. Those options are useful if the linked client if *Consent Required* is enabled on the client. - -Display On Consent Screen:: - If *Display On Consent Screen* is enabled, and the scope is added to a client that requires consent, the text specified in *Consent Screen Text* will be displayed on the consent screen. This text is shown when the user is authenticated and before the user is redirected from {project_name} to the client. If *Display On Consent Screen* is disabled, this client scope will not be displayed on the consent screen. - -Consent Screen Text:: - The text displayed on the consent screen when this client scope is added to a client when consent required defaults to the name of client scope. The value for this text can be customised by specifying a substitution variable with *${var-name}* strings. The customised value is configured within the property files in your theme. See the link:{developerguide_link}[{developerguide_name}] for more information on customisation. - -[[_client_scopes_linking]] -== Link client scope with the client -Linking between a client scope and a client is configured in the *Client Scopes* tab of the client. Two ways of linking between client scope and client are available. - -Default Client Scopes:: -This setting is applicable to the OpenID Connect and SAML clients. Default client scopes are applied when issuing OpenID Connect tokens or SAML assertions for a client. The client will inherit Protocol Mappers and Role Scope Mappings that are defined on the client scope. For the OpenID Connect Protocol, the Mappers and Role Scope Mappings are always applied, regardless of the value used for the scope parameter in the OpenID Connect authorization request. - -Optional Client Scopes:: -This setting is applicable only for OpenID Connect clients. Optional client scopes are applied when issuing tokens for this client but only when requested by the *scope* parameter in the OpenID Connect authorization request. - -=== Example -For this example, assume the client has *profile* and *email* linked as default client scopes, and *phone* and *address* linked as optional client scopes. The client uses the value of the scope parameter when sending a request to the OpenID Connect authorization endpoint. - -[source,bash,subs=+attributes] ----- -scope=openid phone ----- - -The scope parameter contains the string, with the scope values divided by spaces. The value *openid* is the meta-value used for all OpenID Connect requests. The token will contain mappers and role scope mappings from the default client scopes *profile* and *email* as well as *phone*, an optional client scope requested by the scope parameter. - -[[_client_scopes_evaluate]] -== Evaluating Client Scopes -include::proc-evaluating-client-scopes.adoc[] - -== Client scopes permissions - -When issuing tokens to a user, the client scope applies only if the user is permitted to use it. - -When a client scope does not have any role scope mappings defined, each user is permitted to use this client scope. However, when a client scope has role scope mappings defined, the user must be a member of at least one of the roles. There must be an intersection between the user roles and the roles of the client scope. Composite roles are factored into evaluating this intersection. - -If a user is not permitted to use the client scope, no protocol mappers or role scope mappings will be used when generating tokens. The client scope will not appear in the _scope_ value in the token. - -== Realm default client scopes -include::proc-updating-default-scopes.adoc[] - -== Scopes explained -Client scope:: -Client scopes are entities in {project_name} that are configured at the realm level and can be linked to clients. Client scopes are referenced by their name when a request is sent to the {project_name} authorization endpoint with a corresponding value of the *scope* parameter. See the <<_client_scopes_linking, client scopes linking>> section for more details. - -Role scope mapping:: -This is available under the *Scope* tab of a client or client scope. Use *Role scope mapping* to limit the roles that can be used in the access tokens. See the <<_role_scope_mappings, Role Scope Mappings section>> for more details. - -ifeval::[{project_community}==true] - -Authorization scopes:: -The *Authorization Scope* covers the actions that can be performed in the application. See the link:{authorizationguide_link}[Authorization Services Guide] for more details. - -endif::[] - diff --git a/server_admin/topics/clients/con-protocol-mappers.adoc b/server_admin/topics/clients/con-protocol-mappers.adoc deleted file mode 100644 index 30ebb2ee6..000000000 --- a/server_admin/topics/clients/con-protocol-mappers.adoc +++ /dev/null @@ -1,67 +0,0 @@ -[id="con-protocol-mappers_{context}"] -[[_protocol-mappers]] - -= OIDC token and SAML assertion mappings - -[role="_abstract"] -Applications receiving ID tokens, access tokens, or SAML assertions may require different roles and user metadata. - -You can use {project_name} to: - -* Hardcode roles, claims and custom attributes. -* Pull user metadata into a token or assertion. -* Rename roles. - -You perform these actions in the *Mappers* tab in the Admin Console. - -.Mappers tab -image:images/mappers-oidc.png[] - -New clients do not have built-in mappers but they can inherit some mappers from client scopes. See the <<_client_scopes, client scopes section>> for more details. - -Protocol mappers map items (such as an email address, for example) to -a specific claim in the identity and access token. The function of a mapper should be self-explanatory from its name. You add pre-configured mappers by clicking *Add Builtin*. - -Each mapper has a set of common settings. Additional settings are available, depending on the mapper type. Click *Edit* next to a mapper to access the configuration screen to adjust these settings. - -.Mapper config -image:images/mapper-config.png[] - -Details on each option can be viewed by hovering over its tooltip. - -You can use most OIDC mappers to control where the claim gets placed. You opt to include or exclude the claim from the _id_ and _access_ tokens by adjusting the *Add to ID token* and *Add to access token* switches. - -include::proc-creating-mappers.adoc[] - -== Priority order - -Mapper implementations have _priority order_. _Priority order_ is not the configuration property of the mapper. It is the property of the concrete implementation of the mapper. - -Mappers are sorted by the order in the list of mappers. The changes in the token or assertion are applied in that order with the lowest applying first. Therefore, the implementations that are dependent on other implementations are processed in the necessary order. - -For example, to compute the roles which will be included with a token: - -. Resolve audiences based on those roles. -. Process a JavaScript script that uses the roles and audiences already available in the token. - -[[_protocol-mappers_oidc-user-session-note-mappers]] -== OIDC user session note mappers - -User session details are defined using mappers and are automatically included when you use or enable a feature on a client. Click *Add builtin* to include session details. - -Impersonated user sessions provide the following details: - -* *IMPERSONATOR_ID*: The ID of an impersonating user. -* *IMPERSONATOR_USERNAME*: The username of an impersonating user. - -Service account sessions provide the following details: - -* *clientId*: The client ID of the service account. -* *clientAddress*: The remote host IP of the service account's authenticated device. -* *clientHost*: The remote host name of the service account's authenticated device. - -== Script mapper - -Use the *Script Mapper* to map claims to tokens by running user-defined JavaScript code. For more details about deploying scripts to the server, see link:{developerguide_jsproviders_link}[{developerguide_jsproviders_name}]. - -When scripts deploy, you should be able to select the deployed scripts from the list of available mappers. diff --git a/server_admin/topics/clients/oidc/con-advanced-settings.adoc b/server_admin/topics/clients/oidc/con-advanced-settings.adoc deleted file mode 100644 index 1f9f5bd8b..000000000 --- a/server_admin/topics/clients/oidc/con-advanced-settings.adoc +++ /dev/null @@ -1,127 +0,0 @@ -[id="con-advanced-settings_{context}"] -= Advanced configuration -[role="_abstract"] - -After completing the fields on the *Settings* tab, you can use the other tabs to perform advanced configuration. For example, you can use the *Permissions* and *Roles* tabs to configure fine-grained authentication for administrators. See <<_fine_grain_permissions, Fine grain admin permissions>>. Also, see the remaining sections in this chapter for other capabilities. - -== Advanced tab - -When you click the *Advanced* tab, additional fields are displayed. For details on a specific field, click the question mark icon for that field. However, certain fields are described in detail in this section. - -== Fine grain OpenID Connect configuration - -*Logo URL* - -URL that references a logo for the Client application. - -*Policy URL* - -URL that the Relying Party Client provides to the End-User to read about how the profile data will be used. - -*Terms of Service URL* - -URL that the Relying Party Client provides to the End-User to read about the Relying Party's terms of service. - -[[_jwe-id-token-encryption]] -*Signed and Encrypted ID Token Support* - -{project_name} can encrypt ID tokens according to the https://datatracker.ietf.org/doc/html/rfc7516[Json Web Encryption (JWE)] specification. The administrator determines if ID tokens are encrypted for each client. - -The key used for encrypting the ID token is the Content Encryption Key (CEK). {project_name} and a client must negotiate which CEK is used and how it is delivered. The method used to determine the CEK is the Key Management Mode. The Key Management Mode that {project_name} supports is Key Encryption. - -In Key Encryption: - -. The client generates an asymmetric cryptographic key pair. -. The public key is used to encrypt the CEK. -. {project_name} generates a CEK per ID token -. {project_name} encrypts the ID token using this generated CEK -. {project_name} encrypts the CEK using the client's public key. -. The client decrypts this encrypted CEK using their private key -. The client decrypts the ID token using the decrypted CEK. - -No party, other than the client, can decrypt the ID token. - -The client must pass its public key for encrypting CEK to {project_name}. {project_name} supports downloading public keys from a URL provided by the client. The client must provide public keys according to the https://datatracker.ietf.org/doc/html/rfc7517[Json Web Keys (JWK)] specification. - -The procedure is: - -. Open the client's *Keys* tab. -. Toggle *JWKS URL* to ON. -. Input the client's public key URL in the *JWKS URL* textbox. - -Key Encryption's algorithms are defined in the https://datatracker.ietf.org/doc/html/rfc7518#section-4.1[Json Web Algorithm (JWA)] specification. {project_name} supports: - -* RSAES-PKCS1-v1_5(RSA1_5) -* RSAES OAEP using default parameters (RSA-OAEP) -* RSAES OAEP 256 using SHA-256 and MFG1 (RSA-OAEP-256) - -The procedure to select the algorithm is: - -. Open the client's *Advanced* tab. -. Open *Fine Grain OpenID Connect Configuration*. -. Select the algorithm from *ID Token Encryption Content Encryption Algorithm* pulldown menu. - -== Open ID Connect Compatibility Modes - -This section exists for backward compatibility. Click the question mark icons for details on each field. - -[[_mtls-client-certificate-bound-tokens]] -*OAuth 2.0 Mutual TLS Certificate Bound Access Tokens Enabled* - -Mutual TLS binds an access token and a refresh token together with a client certificate, which is exchanged during a TLS handshake. This binding prevents an attacker from using stolen tokens. - -This type of token is a holder-of-key token. Unlike bearer tokens, the recipient of a holder-of-key token can verify if the sender of the token is legitimate. - -If this setting is on, the workflow is: - -. A token request is sent to the token endpoint in an authorization code flow or hybrid flow. -. {project_name} requests a client certificate. -. {project_name} receives the client certificate. -. {project_name} successfully verifies the client certificate. - -If verification fails, {project_name} rejects the token. - -In the following cases, {project_name} will verify the client sending the access token or the refresh token: - -* A token refresh request is sent to the token endpoint with a holder-of-key refresh token. -* A UserInfo request is sent to UserInfo endpoint with a holder-of-key access token. -* A logout request is sent to Logout endpoint with a holder-of-key refresh token. - -See https://datatracker.ietf.org/doc/html/draft-ietf-oauth-mtls-08#section-3[Mutual TLS Client Certificate Bound Access Tokens] in the OAuth 2.0 Mutual TLS Client Authentication and Certificate Bound Access Tokens for more details. - -[NOTE] -==== -Currently, {project_name} client adapters do not support holder-of-key token verification. {project_name} adapters treat access and refresh tokens as bearer tokens. -==== - -[[_proof-key-for-code-exchange]] -*Proof Key for Code Exchange Code Challenge Method* - -If an attacker steals an authorization code of a legitimate client, Proof Key for Code Exchange (PKCE) prevents the attacker from receiving the tokens that apply to the code. - -An administrator can select one of these options: - -*(blank)*:: {project_name} does not apply PKCE unless the client sends appropriate PKCE parameters to {project_name}s authorization endpoint. -*S256*:: {project_name} applies to the client PKCE whose code challenge method is S256. -*plain*:: {project_name} applies to the client PKCE whose code challenge method is plain. - -See https://datatracker.ietf.org/doc/html/rfc7636[RFC 7636 Proof Key for Code Exchange by OAuth Public Clients] for more details. - -[[_mapping-acr-to-loa-client]] -*ACR to Level of Authentication (LoA) Mapping* - -In the advanced settings of a client, you can define which `Authentication Context Class Reference (ACR)` value is mapped to which `Level of Authentication (LoA)`. -This mapping can be specified also at the realm as mentioned in the <<_mapping-acr-to-loa-realm,ACR to LoA Mapping>>. A best practice is to configure this mapping at the -realm level, which allows to share the same settings across multiple clients. - -The `Default ACR Values` can be used to specify the default values when the login request is sent from this client to {project_name} without `acr_values` parameter and without -a `claims` parameter that has an `acr` claim attached. See https://openid.net/specs/openid-connect-registration-1_0.html#ClientMetadata[official OIDC dynamic client registration specification]. - -WARNING: Note that default ACR values are used as the default level, however it cannot be reliably used to enforce login with the particular level. -For example, assume that you configure the `Default ACR Values` to level 2. Then by default, users will be required to authenticate with level 2. -However when the user explicitly attaches the parameter into login request such as `acr_values=1`, then the level 1 will be used. As a result, if the client -really requires level 2, the client is encouraged to check the presence of the `acr` claim inside ID Token and double-check that it contains the requested level 2. - -image:images/client-oidc-map-acr-to-loa.png[alt="ACR to LoA mapping"] - -For further details see <<_step-up-flow,Step-up Authentication>> and https://openid.net/specs/openid-connect-core-1_0.html#acrSemantics[the official OIDC specification]. diff --git a/server_admin/topics/clients/oidc/con-audience.adoc b/server_admin/topics/clients/oidc/con-audience.adoc deleted file mode 100644 index 320032fec..000000000 --- a/server_admin/topics/clients/oidc/con-audience.adoc +++ /dev/null @@ -1,118 +0,0 @@ -[[audience-support]] -= Audience support -[role="_abstract"] -Typically, the environment where {project_name} is deployed consists of a set of _confidential_ or _public_ client applications that use {project_name} for authentication. - -_Services_ (_Resource Servers_ in the https://datatracker.ietf.org/doc/html/draft-ietf-oauth-mtls-08#section-4.2[OAuth 2 specification]) are also available that serve requests from client applications and provide resources to these applications. These services require an _Access token_ (Bearer token) to be sent to them to authenticate a request. This token is obtained by the frontend application upon login to {project_name}. - -In the environment where trust among services is low, you may encounter this scenario: - -. A frontend client application requires authentication against {project_name}. - -. {project_name} authenticates a user. - -. {project_name} issues a token to the application. - -. The application uses the token to invoke an untrusted service. - -. The untrusted service returns the response to the application. However, it keeps the applications token. - -. The untrusted service then invokes a trusted service using the applications token. This results in broken security as the untrusted service misuses the token to access other services on behalf of the client application. - -This scenario is unlikely in environments with a high level of trust between services but not in environments where trust is low. In some environments, this workflow may be correct as the untrusted service may have to retrieve data from a trusted service to return data to the original client application. - -An unlimited audience is useful when a high level of trust exists between services. Otherwise, the audience should be limited. You can limit the audience and, at the same time, allow untrusted services to retrieve data from trusted services. In this case, ensure that the untrusted service and the trusted service are added as audiences to the token. - -To prevent any misuse of the access token, limit the audience on the token and configure your services to verify the audience on the token. The flow will change as follows: - -. A frontend application authenticates against {project_name}. - -. {project_name} authenticates a user. - -. {project_name} issues a token to the application. The application knows that it will need to invoke an untrusted service so it places *scope=* in the authentication request sent to {project_name} (see <<_client_scopes, Client Scopes section>> for more details about the _scope_ parameter). -+ -The token issued to the application contains a reference to the untrusted service in its audience (*"audience": [ "" ]*) which declares that the client uses this access token to invoke the untrusted service. -+ -.The untrusted service serves the request to the client application but also keeps the token. - -. The untrusted service invokes a trusted service with the token. Invocation is not successful because the trusted service checks the audience on the token and find that its audience is only for the untrusted service. This behavior is expected and security is not broken. - -If the client wants to invoke the trusted service later, it must obtain another token by reissuing the SSO login with *scope=*. The returned token will then contain the trusted service as an audience: - -[source,json] ----- -"audience": [ "" ] ----- -Use this value to invoke the **. - -== Setup - -When setting up audience checking: - -* Ensure that services are configured to check audience on the access token sent to them by adding the flag *_verify-token-audience_* in the adapter configuration. See link:{adapterguide_link_latest}#_java_adapter_config[Adapter configuration] for details. - -* Ensure that access tokens issued by {project_name} contain all necessary audiences. Audiences can be added using the client roles as described in the <<_audience_resolve, next section>> or hardcoded. See <<_audience_hardcoded, Hardcoded audience>>. - -[[_audience_resolve]] -== Automatically add audience - -An _Audience Resolve_ protocol mapper is defined in the default client scope _roles_. The mapper checks for clients that have at least one client role available for the current token. The client ID of each client is then added as an audience, which is useful if your service (usually bearer-only) clients rely on client roles. - -For example, for a bearer-only client and a confidential client, -you can use the access token issued for the confidential client to invoke the bearer-only client REST service. The bearer-only client will be automatically added as an audience to the access token issued for the confidential client if the following are true: - -* The bearer-only client has any client roles defined on itself. - -* Target user has at least one of those client roles assigned. - -* Confidential client has the role scope mappings for the assigned role. - -[NOTE] -==== -If you want to ensure that the audience is not added automatically, do not configure role scope mappings directly on the confidential client. Instead, you can create a dedicated client scope that contains the role scope mappings for the client roles of your dedicated client scope. - -Assuming that the client scope is added as an optional client scope to the confidential client, the client roles and the audience will be added to the token if explicitly requested by the *scope=* parameter. -==== - -[NOTE] -==== -The frontend client itself is not automatically added to the access token audience, therefore allowing easy differentiation between the access token and the ID token, since the access token will not contain the client for which the token is issued as an audience. - -If you need the client itself as an audience, see the -<<_audience_hardcoded, hardcoded audience>> option. However, using the same client as both frontend and REST service is not recommended. -==== - -[[_audience_hardcoded]] -== Hardcoded audience - -When your service relies on realm roles or does not rely on the roles in the token at all, it can be useful to use a hardcoded audience. A hardcoded audience is a protocol mapper, that will add the client ID of the specified service client as an audience to the token. -You can use any custom value, for example a URL, if you want to use a different audience than the client ID. - -You can add the protocol mapper directly to the frontend client. If the protocol mapper is added directly, the audience will always be added as well. - -For more control over the protocol mapper, you can create the protocol mapper on the dedicated client scope, which will be called for example *good-service*. - -.Audience protocol mapper -image:images/audience_mapper.png[] - -* From the <<_client_installation, Client details tab>> of the *good-service* client, you can generate the adapter configuration and confirm that _verify-token-audience_ is set to *true*. This action forces the adapter to verify the audience if you use this configuration. - -* You need to ensure that the confidential client is able to request *good-service* as an audience in its tokens. -+ -On the confidential client: -+ -. Click the _Client Scopes_ tab. -. Assign *good-service* as an optional (or default) client scope. -+ -See <<_client_scopes_linking, Client Scopes Linking section>> for more details. - -* You can optionally <<_client_scopes_evaluate, Evaluate Client Scopes>> and generate an example access token. *good-service* will be added to the audience of the generated access token if *good-service* is included in the _scope_ parameter, when you assigned it as an optional client scope. - -* In your confidential client application, ensure that the _scope_ parameter is used. The value *good-service* must be included when you want to issue the token for accessing *good-service*. -+ -See: -+ -** link:{adapterguide_link}#_params_forwarding[parameters forwarding section] if your application uses the servlet adapter. -** link:{adapterguide_link}#_javascript_adapter[javascript adapter section] if your application uses the javascript adapter. - -NOTE: Both the _Audience_ and _Audience Resolve_ protocol mappers add the audiences to the access token only, by default. The ID Token typically contains only a single audience, the client ID for which the token was issued, a requirement of the OpenID Connect specification. However, the access token does not necessarily have the client ID, which was the token issued for, unless the audience mappers added it. diff --git a/server_admin/topics/clients/oidc/con-basic-settings.adoc b/server_admin/topics/clients/oidc/con-basic-settings.adoc deleted file mode 100644 index 6732d45c6..000000000 --- a/server_admin/topics/clients/oidc/con-basic-settings.adoc +++ /dev/null @@ -1,101 +0,0 @@ -[id="con-basic-settings_{context}"] -= Basic configuration -[role="_abstract"] - -The *Settings* tab includes many options to configure this client. - -.Settings tab -image:images/client-settings-oidc.png[Settings tab] - -== General Settings - -*Client ID*:: The alphanumeric ID string that is used in OIDC requests and in the {project_name} database to identify the client. - -*Name*:: The name for the client in {project_name} UI screen. To localize -the name, set up a replacement string value. For example, a string value such as $\{myapp}. See the link:{developerguide_link}[{developerguide_name}] for more information. - -*Description*:: The description of the client. This setting can also be localized. - -*Always Display in Console*:: Always list this client in the Account Console even if this user does not have an active session. - -== Access Settings - -*Root URL*:: If {project_name} uses any configured relative URLs, this value is prepended to them. - -*Home URL*:: Provides the default URL for when the auth server needs to redirect or link back to the client. - -*Valid Redirect URIs*:: Required field. Enter a URL pattern and click *+* to add and *-* to remove existing URLs and click *Save*. You can use wildcards at the end of the URL pattern. For example $$http://host.com/*$$ -+ -Exclusive redirect URL patterns are typically more secure. See xref:unspecific-redirect-uris_{context}[Unspecific Redirect URIs] for more information. - -Web Origins:: Enter a URL pattern and click + to add and - to remove existing URLs. Click Save. -+ -This option handles link:https://fetch.spec.whatwg.org/[Cross-Origin Resource Sharing (CORS)]. -If browser JavaScript attempts an AJAX HTTP request to a server whose domain is different from the one that the -JavaScript code came from, the request must use CORS. The server must handle CORS requests, otherwise the browser will not display or allow the request to be processed. This protocol protects against XSS, CSRF, and other JavaScript-based attacks. -+ -Domain URLs listed here are embedded within the access token sent to the client application. The client application uses this information to decide whether to allow a CORS request to be invoked on it. Only {project_name} client adapters support this feature. See link:{adapterguide_link}[{adapterguide_name}] for more information. - -[[_admin-url]] -Admin URL:: Callback endpoint for a client. The server uses this URL to make callbacks like pushing revocation policies, performing backchannel logout, and other administrative operations. For {project_name} servlet adapters, this URL can be the root URL of the servlet application. -For more information, see link:{adapterguide_link}[{adapterguide_name}]. - -== Capability Config -[[_access-type]] - -*Client authentication*:: The type of OIDC client. -* _ON_ -+ -For server-side clients that perform browser logins and require client secrets when making an Access Token Request. This setting should be used for server-side applications. - -* _OFF_ -+ -For client-side clients that perform browser logins. As it is not possible to ensure that secrets can be kept safe with client-side clients, it is important to restrict access by configuring correct redirect URIs. - -*Authorization*:: Enables or disables fine-grained authorization support for this client. - -*Standard Flow*:: If enabled, this client can use the OIDC xref:_oidc-auth-flows-authorization[Authorization Code Flow]. - -*Direct Access Grants*:: If enabled, this client can use the OIDC xref:_oidc-auth-flows-direct[Direct Access Grants]. - -*Implicit Flow*:: If enabled, this client can use the OIDC xref:_oidc-auth-flows-implicit[Implicit Flow]. - -*Service account roles*:: If enabled, this client can authenticate to {project_name} and retrieve access token dedicated to this client. In terms of OAuth2 specification, this enables support of `Client Credentials Grant` for this client. - -*Auth 2.0 Device Authorization Grant*:: If enabled, this client can use the OIDC xref:con-oidc-auth-flows_server_administration_guide[Device Authorization Grant]. - -*OIDC CIBA Grant*:: If enabled, this client can use the OIDC xref:con-oidc-auth-flows_{context}[Client Initiated Backchannel Authentication Grant]. - -== Login settings - -*Login theme*:: A theme to use for login, OTP, grant registration, and forgotten password pages. - -*Consent required*:: If enabled, users have to consent to client access. -+ -For client-side clients that perform browser logins. As it is not possible to ensure that secrets can be kept safe with client-side clients, it is important to restrict access by configuring correct redirect URIs. - -*Display client on screen*:: This switch applies if *Consent Required* is *Off*. -* _Off_ -+ -The consent screen will contain only the consents corresponding to configured client scopes. - -* _On_ -+ -There will be also one item on the consent screen about this client itself. - -*Client consent screen text*:: Applies if *Consent required* and *Display client on screen* are enabled. Contains the text that will be on the consent screen about permissions for this client. - -== Logout settings - -[[_front-channel-logout]] -*Front channel logout*:: If *Front Channel Logout* is enabled, the application should be able to log out users through the front channel as per link:https://openid.net/specs/openid-connect-frontchannel-1_0.html[OpenID Connect Front-Channel Logout] specification. If enabled, you should also provide the `Front-Channel Logout URL`. - -*Front-channel logout URL*:: URL that will be used by {project_name} to send logout requests to clients through the front-channel. - -[[_back-channel-logout-url]] -*Backchannel logout URL*:: URL that will cause the client to log itself out when a logout request is sent to this realm (via end_session_endpoint). If omitted, no logout requests are sent to the client. - -*Backchannel logout session required*:: -Specifies whether a session ID Claim is included in the Logout Token when the *Backchannel Logout URL* is used. - -*Backchannel logout revoke offline sessions*:: Specifies whether a revoke_offline_access event is included in the Logout Token when the Backchannel Logout URL is used. {project_name} will revoke offline sessions when receiving a Logout Token with this event. diff --git a/server_admin/topics/clients/oidc/con-confidential-client-credentials.adoc b/server_admin/topics/clients/oidc/con-confidential-client-credentials.adoc deleted file mode 100644 index a9d0955cf..000000000 --- a/server_admin/topics/clients/oidc/con-confidential-client-credentials.adoc +++ /dev/null @@ -1,79 +0,0 @@ -[id="con-confidential-client-credentials_{context}"] - -[[_client-credentials]] -= Confidential client credentials -[role="_abstract"] -If the <<_access-type, Client authentication>> of the client is set to *ON*, the credentials of the client must be configured under the *Credentials* tab. - -.Credentials tab -image:images/client-credentials.png[Credentials Tab] - -The *Client Authenticator* drop-down list specifies the type of credential to use for your client. - -*Client ID and Secret* - -This choice is the default setting. The secret is automatically generated. Click *Regenerate* to recreate the secret if necessary. - -.Signed JWT -image:images/client-credentials-jwt.png[Signed JWT] - -*Signed JWT* is "Signed Json Web Token". - -When choosing this credential type you will have to also generate a private key and certificate for the client in the tab `Keys`. The private key will be used to sign the JWT, while the certificate is used by the server to verify the signature. - -.Keys tab -image:images/client-oidc-keys.png[Keys tab] - -Click on the `Generate new keys` button to start this process. - -.Generate keys -image:images/generate-client-keys.png[] - -. Select the archive format you want to use. -. Enter a *key password*. -. Enter a *store password*. -. Click *Generate*. - -When you generate the keys, {project_name} will store the certificate and you download the private key and certificate for your client. - -You can also generate keys using an external tool and then import the client's certificate by clicking *Import Certificate*. - -.Import certificate -image:images/import-client-cert.png[Import Certificate] - -. Select the archive format of the certificate. -. Enter the store password. -. Select the certificate file by clicking *Import File*. -. Click *Import*. - -Importing a certificate is unnecessary if you click *Use JWKS URL*. In this case, you can provide the URL where the public key is published in https://self-issued.info/docs/draft-ietf-jose-json-web-key.html[JWK] format. With this option, if the key is ever changed, {project_name} reimports the key. - -If you are using a client secured by {project_name} adapter, you can configure the JWKS URL in this format, assuming that https://myhost.com/myapp is the root URL of your client application: - -[source,bash,subs=+attributes] ----- -https://myhost.com/myapp/k_jwks ----- - -See link:{developerguide_link}[{developerguide_name}] for more details. - -*Signed JWT with Client Secret* - -If you select this option, you can use a JWT signed by client secret instead of the private key. - -The client secret will be used to sign the JWT by the client. - -*X509 Certificate* - -{project_name} will validate if the client uses proper X509 certificate during the TLS Handshake. - -.X509 certificate -image:images/x509-client-auth.png[] - -The validator also checks the Subject DN field of the certificate with a configured regexp validation expression. For some -use cases, it is sufficient to accept all certificates. In that case, you can use `(.*?)(?:$)` expression. - -Two ways exist for {project_name} to obtain the Client ID from the request: - -* The `client_id` parameter in the query (described in Section 2.2 of the https://datatracker.ietf.org/doc/html/rfc6749[OAuth 2.0 Specification]). -* Supply `client_id` as a form parameter. diff --git a/server_admin/topics/clients/oidc/con-secret-rotation.adoc b/server_admin/topics/clients/oidc/con-secret-rotation.adoc deleted file mode 100644 index 2311e7e72..000000000 --- a/server_admin/topics/clients/oidc/con-secret-rotation.adoc +++ /dev/null @@ -1,34 +0,0 @@ -[id="con-secret-rotation_{context}"] -[[_secret_rotation]] -= Client Secret Rotation -[role="_abstract"] - -[IMPORTANT] -==== -Please note that Client Secret Rotation support is in development. Use this feature experimentally. -==== - -For a client with <<_client-credentials, Confidential>> <<_access-type, Client authentication>> {project_name} supports the functionality of rotating client secrets through <<_client_policies, Client Policies>>. - -The client secrets rotation policy provides greater security in order to alleviate problems such as secret leakage. Once enabled, {project_name} supports up to two concurrently active secrets for each client. The policy manages rotations according to the following settings: - -* *Secret expiration:* [seconds] - When the secret is rotated, this is the expiration of time of the new secret. The amount, _in seconds_, added to the secret creation date. Calculated at policy execution time. -* *Rotated secret expiration:* [seconds] - When the secret is rotated, this value is the remaining expiration time for the old secret. This value should be always smaller than Secret expiration. When the value is 0, the old secret will be immediately removed during client rotation. The amount, _in seconds_, added to the secret rotation date. Calculated at policy execution time. -* *Remaining expiration time for rotation during update:* [seconds] - Time period when an update to a dynamic client should perform client secret rotation. Calculated at policy execution time. - -When a client secret rotation occurs, a new main secret is generated and the old client main secret becomes the secondary secret with a new expiration date. - -== Rules for client secret rotation -Rotations do not occur automatically or through a background process. In order to perform the rotation, an update action is required on the client, either through the {project_name} Admin Console through the function of *Regenerate Secret*, in the client's credentials tab or Admin REST API. When invoking a client update action, secret rotation occurs according to the rules: - -* When the value of *Secret expiration* is less than the current date. -* During dynamic client registration client-update request, the client secret will be automatically rotated if the value of *Remaining expiration time for rotation during update* match the period between the current date and the *Secret expiration*. - -Additionally it is possible through Admin REST API to force a client secret rotation at any time. - -[NOTE] -==== -During the creation of new clients, if the client secret rotation policy is active, the behavior will be applied automatically. -==== - -WARNING: To apply the secret rotation behavior to an existing client, update that client after you define the policy so that the behavior is applied. diff --git a/server_admin/topics/clients/oidc/proc-creating-oidc-client.adoc b/server_admin/topics/clients/oidc/proc-creating-oidc-client.adoc deleted file mode 100644 index 9732686ae..000000000 --- a/server_admin/topics/clients/oidc/proc-creating-oidc-client.adoc +++ /dev/null @@ -1,24 +0,0 @@ -[id="proc-creating-oidc-client_{context}"] -= Creating an OpenID Connect client - -[role="_abstract"] -To protect an application that uses the OpenID connect protocol, you create a client. - -.Procedure - -. Click *Clients* in the menu. -. Click *Create client*. -+ -.Create client -image:images/add-client-oidc.png[Create Client] -. Leave *Client type* set to *OpenID Connect*. -. Enter a *Client ID.* -+ -This ID is an alphanumeric string that is used in OIDC requests and in the {project_name} database to identify the client. -. Supply a *Name* for the client. -+ -If you plan to localize this name, set up a replacement string value. For example, a string value such as $\{myapp}. See the link:{developerguide_link}[{developerguide_name}] for more information. - -. Click *Save*. - -This action creates the client and bring you to the *Settings* tab, where you can perform xref:con-basic-settings_{context}[Basic configuration]. diff --git a/server_admin/topics/clients/oidc/proc-secret-rotation.adoc b/server_admin/topics/clients/oidc/proc-secret-rotation.adoc deleted file mode 100644 index 47849634d..000000000 --- a/server_admin/topics/clients/oidc/proc-secret-rotation.adoc +++ /dev/null @@ -1,104 +0,0 @@ -[id="proc-secret-rotation_{context}"] - -[[_proc-secret-rotation]] - -= Creating an OIDC Client Secret Rotation Policy -[role="_abstract"] - -The following is an example of defining a secret rotation policy: - -.Procedure -. Click *Realm Settings* in the menu. - -. Click *Client Policies* tab. - -. On the *Profiles* page, click *Create client profile*. -+ -.Create a profile -image:images/create-oidc-client-profile.png[Create Client Profile] - -. Enter any name for *Name*. - -. Enter a description that helps you identify the purpose of the profile for *Description*. - -. Click *Save*. -+ -This action creates the profile and enables you to configure executors. -. Click *Add executor* to configure an executor for this profile. -+ -.Create a profile executor -image:images/create-oidc-client-secret-rotation-executor.png[Client Profile Executor] - -. Select _secret-rotation_ for *Executor Type*. - -. Enter the maximum duration time of each secret, in seconds, for *Secret Expiration*. - -. Enter the maximum duration time of each rotated secret, in seconds, for *Rotated Secret Expiration*. -+ -WARNING: Remember that the *Rotated Secret Expiration* value must always be less than *Secret Expiration*. -. Enter the amount of time, in seconds, after which any update action will update the client for *Remain Expiration Time*. - -. Click *Add*. -+ -==== -In the example above: - -* Each secret is valid for one week. -* The rotated secret expires after two days. -* The window for updating dynamic clients starts one day before the secret expires. -==== -+ -. Return to the *Client Policies* tab. - -. Click *Policies*. - -. Click *Create client policy*. -+ -.Create the Client Secret Rotation Policy -image:images/create-oidc-client-secret-rotation-policy.png[Client Rotation Policy] - -. Enter any name for *Name*. - -. Enter a description that helps you identify the purpose of the policy for *Description*. - -. Click *Save*. -+ -This action creates the policy and enables you to associate policies with profiles. It also allows you to configure the conditions for policy execution. -+ -. Under Conditions, click *Add condition*. -+ -.Create the Client Secret Rotation Policy Condition -image:images/create-oidc-client-secret-rotation-condition.png[Client Rotation Policy Condition] - -. To apply the behavior to all confidential clients select _client-access-type_ in the *Condition Type* field -+ -[NOTE] -==== -To apply to a specific group of clients, another approach would be to select the _client-roles_ type in the *Condition Type* field. In this way, you could create specific roles and assign a custom rotation configuration to each role. -==== -+ -. Add _confidential_ to the field *Client Access Type*. - -. Click *Add*. - -. Back in the policy setting, under _Client Profiles_, click *Add client profile* and then select *Weekly Client Secret Rotation Profile* from the list and then click *Add*. -+ -.Client Secret Rotation Policy -image:images/oidc-client-secret-rotation-policy.png[Client Rotation Policy] - -[NOTE] -==== -To apply the secret rotation behavior to an existing client, follow the following steps: - -.Using the Admin Console -. Click *Clients* in the menu. -. Click a client. -. Click the *Credentials* tab. -. Click *Re-generate* of the client secret. -==== - ---- - -.Using client REST services it can be executed in two ways: -* Through an update operation on a client -* Through the regenerate client secret endpoint diff --git a/server_admin/topics/clients/oidc/proc-using-a-service-account.adoc b/server_admin/topics/clients/oidc/proc-using-a-service-account.adoc deleted file mode 100644 index f78124a02..000000000 --- a/server_admin/topics/clients/oidc/proc-using-a-service-account.adoc +++ /dev/null @@ -1,70 +0,0 @@ -[id="proc-using-service-account_{context}"] - -[[_service_accounts]] -= Using a service account -[role="_abstract"] -Each OIDC client has a built-in _service account_. Use this _service account_ to obtain an access token. - -.Prerequisites - -.Procedure -. Click *Clients* in the menu. -. Select your client. -. Click the *Settings* tab. -. Toggle <<_access-type, Client authentication>> to *On*. -. Select *Service accounts roles*. -. Click *Save*. -. Configure your <<_client-credentials, client credentials>>. -. Click the *Scope* tab. -. Verify that you have roles or toggle *Full Scope Allowed* to *ON*. -. Click the *Service Account Roles* tab -. Configure the roles available to this service account for your client. - -Roles from access tokens are the intersection of: - -* Role scope mappings of a client combined with the role scope mappings inherited from linked client scopes. -* Service account roles. - -The REST URL to invoke is `{kc_realms_path}/{realm-name}/protocol/openid-connect/token`. This URL must be invoked as a POST request and requires that you post the client credentials with the request. - -By default, client credentials are represented by the clientId and clientSecret of the client in the *Authorization: Basic* header but you can also authenticate the client with a signed JWT assertion or any other custom mechanism for client authentication. - -You also need to set the *grant_type* parameter to "client_credentials" as per the OAuth2 specification. - -For example, the POST invocation to retrieve a service account can look like this: - -[source,subs=+attributes] ----- - - POST {kc_realms_path}/demo/protocol/openid-connect/token - Authorization: Basic cHJvZHVjdC1zYS1jbGllbnQ6cGFzc3dvcmQ= - Content-Type: application/x-www-form-urlencoded - - grant_type=client_credentials ----- - -The response would be similar to this https://datatracker.ietf.org/doc/html/rfc6749#section-4.4.3[Access Token Response] from the OAuth 2.0 specification. - -[source] ----- - -HTTP/1.1 200 OK -Content-Type: application/json;charset=UTF-8 -Cache-Control: no-store -Pragma: no-cache - -{ - "access_token":"2YotnFZFEjr1zCsicMWpAA", - "token_type":"bearer", - "expires_in":60 -} ----- - -Only the access token is returned by default. No refresh token is returned and no user session is created -on the {project_name} side upon successful authentication by default. Due to the lack of a refresh token, re-authentication is required when the access token expires. However, this situation does not mean any additional overhead for the {project_name} server because sessions are not created by default. - -In this situation, logout is unnecessary. However, issued access tokens can be revoked by sending requests to the OAuth2 Revocation Endpoint as described in the xref:con-oidc_{context}[OpenID Connect Endpoints] section. - -[role="_additional-resources"] -.Additional resources -For more details, see <<_client_credentials_grant,Client Credentials Grant>>. diff --git a/server_admin/topics/clients/oidc/service-accounts.adoc b/server_admin/topics/clients/oidc/service-accounts.adoc deleted file mode 100644 index 4d1c5e87b..000000000 --- a/server_admin/topics/clients/oidc/service-accounts.adoc +++ /dev/null @@ -1,57 +0,0 @@ -[[_service_accounts]] - -==== Service Accounts - -Each OIDC client has a built-in _service account_ which allows it to obtain an access token. -This is covered in the OAuth 2.0 specification under <<_client_credentials_grant,Client Credentials Grant>>. -To use this feature you must set the <<_access-type, Access Type>> of your client to `confidential`. When you do this, -the `Service Accounts Enabled` switch is displayed. You need to toggle this switch to ON. Also make sure that you have -configured your <<_client-credentials, client credentials>>. - -To use it you must have registered a valid `confidential` Client and you need to check the switch `Service Accounts Enabled` in {project_name} admin console for this client. -In tab `Service Account Roles` you can configure the roles available to the service account retrieved on behalf of this client. -Remember that you must have the roles available in Role Scope Mappings (tab `Scope`) of this client as well, unless you -have `Full Scope Allowed` on. As in a normal login, roles from access token are the intersection of: - -* Role scope mappings of particular client combined with the role scope mappings inherited from linked client scopes -* Service account roles - -The REST URL to invoke on is `{kc_realms_path}/{realm-name}/protocol/openid-connect/token`. -Invoking on this URL is a POST request and requires you to post the client credentials. -By default, client credentials are represented by clientId and clientSecret of the client in `Authorization: Basic` header, but you can also authenticate the client with a signed JWT assertion or any other custom mechanism for client authentication. -You also need to use the parameter `grant_type=client_credentials` as per the OAuth2 specification. - -For example the POST invocation to retrieve a service account can look like this: - -[source] ----- - - POST {kc_realms_path}/demo/protocol/openid-connect/token - Authorization: Basic cHJvZHVjdC1zYS1jbGllbnQ6cGFzc3dvcmQ= - Content-Type: application/x-www-form-urlencoded - - grant_type=client_credentials ----- -The response would be this https://datatracker.ietf.org/doc/html/rfc6749#section-4.4.3[standard JSON document] from the OAuth 2.0 specification. - -[source] ----- - -HTTP/1.1 200 OK -Content-Type: application/json;charset=UTF-8 -Cache-Control: no-store -Pragma: no-cache - -{ - "access_token":"2YotnFZFEjr1zCsicMWpAA", - "token_type":"bearer", - "expires_in":60 -} ----- - -There is the only access token returned by default. There is no refresh token returned and there is also no user session created -on the {project_name} side upon successful authentication by default. Due to the lack of a refresh token, there is a need to re-authenticate when access token expires, -however this does not mean any additional overhead on {project_name} server side due the fact that sessions are not created by default. - -Due to this, there is no need for logout, however issued access tokens can be revoked by sending request to the OAuth2 Revocation Endpoint described -in the <<_oidc-endpoints, OpenID Connect Endpoints>> section. diff --git a/server_admin/topics/clients/proc-creating-client-scopes.adoc b/server_admin/topics/clients/proc-creating-client-scopes.adoc deleted file mode 100644 index a8744fbb7..000000000 --- a/server_admin/topics/clients/proc-creating-client-scopes.adoc +++ /dev/null @@ -1,17 +0,0 @@ -[id="proc_creating_client_scopes_{context}"] - -[role="_abstract"] -To create a client scope, follow these steps: - -. Click *Client Scopes* in the menu. -+ -.Client scopes list -image:images/client-scopes-list.png[] -+ -. Click *Create*. -. Name your client scope. -. Click *Save*. - -A _client scope_ has similar tabs to regular clients. You can -define <<_protocol-mappers, protocol mappers>> and <<_role_scope_mappings, role scope mappings>>. These mappings can be inherited by other clients and are configured to inherit from this client scope. - diff --git a/server_admin/topics/clients/proc-creating-mappers.adoc b/server_admin/topics/clients/proc-creating-mappers.adoc deleted file mode 100644 index 81766dbe7..000000000 --- a/server_admin/topics/clients/proc-creating-mappers.adoc +++ /dev/null @@ -1,13 +0,0 @@ -[id="proc-creating-mappers_{context}"] - -[role="_abstract"] -You can add mapper types as follows: - -.Procedure -. Go to the *Mappers* tab. -. Click *Configure a new mapper*. -+ -.Add mapper -image:images/add-mapper.png[] -+ -. Select a *Mapper Type* from the list box. diff --git a/server_admin/topics/clients/proc-evaluating-client-scopes.adoc b/server_admin/topics/clients/proc-evaluating-client-scopes.adoc deleted file mode 100644 index dfa23d0b7..000000000 --- a/server_admin/topics/clients/proc-evaluating-client-scopes.adoc +++ /dev/null @@ -1,21 +0,0 @@ -[id="proc_evaluating_client_scopes_{context}"] - -[role="_abstract"] -The *Mappers* tab contains the protocol mappers and the *Scope* tab contains the role scope mappings declared for this client. They do not contain the mappers and scope mappings inherited from client scopes. It is possible to see the effective protocol mappers (that is the protocol mappers defined on the client itself as well as inherited from the linked client scopes) and the effective role scope mappings used when generating a token for a client. - -.Procedure -. Click the *Client Scopes* tab for the client. -. Open the sub-tab *Evaluate*. -. Select the optional client scopes that you want to apply. - -This will also show you the value of the *scope* parameter. This parameter needs to be sent from the application to the {project_name} OpenID Connect authorization endpoint. - -.Evaluating client scopes -image:images/client-scopes-evaluate.png[] - -[NOTE] -==== -To send a custom value for a *scope* parameter from your application, see the link:{adapterguide_link_latest}#_params_forwarding[parameters forwarding section], for servlet adapters or the link:{adapterguide_link_latest}#_javascript_adapter[javascript adapter section], for javascript adapters. -==== - -All examples are generated for the particular user and issued for the particular client, with the specified value of the *scope* parameter. The examples include all of the claims and role mappings used. \ No newline at end of file diff --git a/server_admin/topics/clients/proc-generating-client-adapter-config.adoc b/server_admin/topics/clients/proc-generating-client-adapter-config.adoc deleted file mode 100644 index 7ca0ef5af..000000000 --- a/server_admin/topics/clients/proc-generating-client-adapter-config.adoc +++ /dev/null @@ -1,16 +0,0 @@ -[id="proc-generating-client-adapter-config_{context}"] - -[[_client_installation]] - -= Generating client adapter config -[role="_abstract"] - -{project_name} can generate configuration files that you can use to install a client adapter in your application's deployment environment. A number of adapter types are supported for OIDC and SAML. - -. Click on the _Action_ menu and select the *Download adapter config* option -+ -image:images/client-installation.png[] -+ -. Select the *Format Option* you want configuration generated for. - -All {project_name} client adapters for OIDC and SAML are supported. The mod-auth-mellon Apache HTTPD adapter for SAML is supported as well as standard SAML entity descriptor files. diff --git a/server_admin/topics/clients/proc-updating-default-scopes.adoc b/server_admin/topics/clients/proc-updating-default-scopes.adoc deleted file mode 100644 index d3cd7a919..000000000 --- a/server_admin/topics/clients/proc-updating-default-scopes.adoc +++ /dev/null @@ -1,17 +0,0 @@ -[id="proc_updating_client_scopes_{context}"] - -[role="_abstract"] -Use *Realm Default Client Scopes* to define sets of client scopes that are automatically linked to newly created clients. - -.Procedure -. Click the *Client Scopes* tab for the client. -ifeval::[{project_product}==true] -. Click *Default Client Scopes*. -endif::[] - -From here, select the client scopes that you want to add as *Default Client Scopes* to newly created clients and *Optional Client Scopes*. - -.Default client scopes -image:images/client-scopes-default.png[] - -When a client is created, you can unlink the default client scopes, if needed. This is similar to removing <<_default_roles, Default Roles>>. diff --git a/server_admin/topics/clients/saml/idp-initiated-login.adoc b/server_admin/topics/clients/saml/idp-initiated-login.adoc deleted file mode 100644 index 136620e4d..000000000 --- a/server_admin/topics/clients/saml/idp-initiated-login.adoc +++ /dev/null @@ -1,41 +0,0 @@ - -= IDP Initiated login -[role="_abstract"] -IDP Initiated Login is a feature that allows you to set up an endpoint on the {project_name} server that will log you into a specific application/client. -In the *Settings* tab for your client, you need to specify the *IDP Initiated SSO URL Name*. -This is a simple string with no whitespace in it. -After this you can reference your client at the following URL: `root{kc_realms_path}/{realm}/protocol/saml/clients/{url-name}` - -The IDP initiated login implementation prefers _POST_ over _REDIRECT_ binding (check <<_saml, saml bindings>> for more information). -Therefore the final binding and SP URL are selected in the following way: - -1. If the specific *Assertion Consumer Service POST Binding URL* is defined (inside *Fine Grain SAML Endpoint Configuration* section -of the client settings) _POST_ binding is used through that URL. -2. If the general *Master SAML Processing URL* is specified then _POST_ binding is used again throughout this general URL. -3. As the last resort, if the *Assertion Consumer Service Redirect Binding URL* is configured (inside -*Fine Grain SAML Endpoint Configuration*) _REDIRECT_ binding is used with this URL. - -If your client requires a special relay state, you can also configure this on the *Settings* tab in the *IDP Initiated SSO Relay State* field. -Alternatively, browsers can specify the relay state in a *RelayState* query parameter, i.e. -`root{kc_realms_path}/{realm}/protocol/saml/clients/{url-name}?RelayState=thestate`. - -When using <<_identity_broker,identity brokering>>, it is possible to set up an IDP Initiated Login for a client from an -external IDP. The actual client is set up for IDP Initiated Login at broker IDP as described above. The external IDP has -to set up the client for application IDP Initiated Login that will point to a special URL pointing to the broker and -representing IDP Initiated Login endpoint for a selected client at the brokering IDP. This means that in client settings -at the external IDP: - -* *IDP Initiated SSO URL Name* is set to a name that will be published as IDP Initiated Login initial point, -* *Assertion Consumer Service POST Binding URL* in the *Fine Grain SAML Endpoint Configuration* section has - to be set to the following URL: - `broker-root{kc_realms_path}/{broker-realm}/broker/{idp-name}/endpoint/clients/{client-id}`, where: - - ** _broker-root_ is base broker URL - ** _broker-realm_ is name of the realm at broker where external IDP is declared - ** _idp-name_ is name of the external IDP at broker - ** _client-id_ is the value of *IDP Initiated SSO URL Name* attribute of the SAML client defined at broker. It is - this client, which will be made available for IDP Initiated Login from the external IDP. - -Please note that you can import basic client settings from the brokering IDP into client settings of the external IDP - -just use <<_identity_broker_saml_sp_descriptor,SP Descriptor>> available from the settings of the identity provider in -the brokering IDP, and add `clients/_client-id_` to the endpoint URL. diff --git a/server_admin/topics/clients/saml/proc-creating-saml-client.adoc b/server_admin/topics/clients/saml/proc-creating-saml-client.adoc deleted file mode 100644 index 0c6df3145..000000000 --- a/server_admin/topics/clients/saml/proc-creating-saml-client.adoc +++ /dev/null @@ -1,159 +0,0 @@ - -[[_client-saml-configuration]] -= Creating a SAML client -[role="_abstract"] -{project_name} supports <<_saml,SAML 2.0>> for registered applications. -POST and Redirect bindings are supported. You can choose to require client signature validation. You can have the server sign and/or encrypt responses as well. - -.Procedure -. Click *Clients* in the menu. -. Click *Create client* to go to the *Create client* page. -. Set *Client type* to *SAML*. -+ -.Create client -image:images/add-client-saml.png[] - -. Enter the *Client ID* of the client. This is often a URL and is the expected *issuer* value in SAML requests sent by the application. - -. Click *Save*. This action creates the client and brings you to the *Settings* tab. - -The following sections describe each setting on this tab. - -== Settings tab - -The *Settings* tab includes many options to configure this client. - -.Client settings -image:images/client-settings-saml.png[] - -=== General settings - -*Client ID*:: The alphanumeric ID string that is used in OIDC requests and in the {project_name} database to identify the client. This value must match the issuer value sent with AuthNRequests. {project_name} pulls the issuer from the Authn SAML request and match it to a client by this value. - -*Name*:: The name for the client in a {project_name} UI screen. To localize -the name, set up a replacement string value. For example, a string value such as $\{myapp}. See the link:{developerguide_link}[{developerguide_name}] for more information. - -*Description*:: The description of the client. This setting can also be localized. - -// *Enabled*:: When set to *On*, the client can request authentication. - -*Always Display in Console*:: Always list this client in the Account Console even if this user does not have an active session. - -=== Access Settings - -*Root URL*:: When {project_name} uses a configured relative URL, this value is prepended to the URL. - -*Home URL*:: If {project_name} needs to link to a client, this URL is used. - -*Valid Redirect URIs*:: Enter a URL pattern and click the + sign to add. Click the - sign to remove. Click *Save* to save these changes. -Wildcards values are allowed only at the end of a URL. For example, http://host.com/*$$. -This field is used when the exact SAML endpoints are not registered and {project_name} pulls the Assertion Consumer URL from a request. - -*IDP-Initiated SSO URL name*:: URL fragment name to reference client when you want to do IDP Initiated SSO. Leaving this empty will disable IDP Initiated SSO. The URL you will reference from your browser will be: _server-root_/realms/{realm}/protocol/saml/clients/{client-url-name} - -*IDP Initiated SSO Relay State*:: Relay state you want to send with SAML request when you want to do IDP Initiated SSO. - -*Master SAML Processing URL*:: This URL is used for all SAML requests and the response is directed to the SP. It is used as the Assertion Consumer Service URL and the Single Logout Service URL. -+ -If login requests contain the Assertion Consumer Service URL then those login requests will take precedence. This URL must be validated by a registered Valid Redirect URI pattern. - -=== SAML capabilities - -*Name ID Format*:: The Name ID Format for the subject. This format is used if no name ID policy is specified in a request, or if the Force Name ID Format attribute is set to ON. - -*Force Name ID Format*:: If a request has a name ID policy, ignore it and use the value configured in the Admin Console under *Name ID Format*. - -*Force POST Binding*:: By default, {project_name} responds using the initial SAML binding of the original request. By enabling *Force POST Binding*, {project_name} responds using the SAML POST binding even if the original request used the redirect binding. - -*Force artifact binding*:: If enabled, response messages are returned to the client through the SAML ARTIFACT binding system. - -*Include AuthnStatement*:: SAML login responses may specify the authentication method used, such as password, as well as timestamps of the login and the session expiration. -*Include AuthnStatement* is enabled by default, so that the *AuthnStatement* element will be included in login responses. Setting this to OFF prevents clients from determining the maximum session length, which can create client sessions that do not expire. - -*Include OneTimeUse Condition*:: If enable, a OneTimeUse Condition is included in login responses. - -*Optimize REDIRECT signing key lookup*:: When set to ON, the SAML protocol messages include the {project_name} native extension. This extension contains a hint with the signing key ID. The SP uses the extension for signature validation instead of attempting to validate the signature using keys. -+ -This option applies to REDIRECT bindings where the signature is transferred in query parameters and this information is not found in the signature information. This is contrary to POST binding messages where key ID is always included in document signature. -+ -This option is used when {project_name} server and adapter provide the IDP and SP. This option is only relevant when *Sign Documents* is set to ON. - -=== Signature and Encryption - -*Sign Documents*:: When set to ON, {project_name} signs the document using the realms private key. - -*Sign Assertions*:: The assertion is signed and embedded in the SAML XML Auth response. - -*Signature Algorithm*:: The algorithm used in signing SAML documents. Note that `SHA1` based algorithms are deprecated and may be removed in a future release. -We recommend the use of some more secure algorithm instead of `*_SHA1`. Also, with `*_SHA1` algorithms, verifying signatures -do not work if the SAML client runs on Java 17 or higher. - -*SAML Signature Key Name*:: Signed SAML documents sent using POST binding contain the identification of the signing key in the *KeyName* element. This action can be controlled by the *SAML Signature Key Name* option. This option controls the contents of the *Keyname*. -+ --- -* *KEY_ID* The *KeyName* contains the key ID. This option is the default option. -* *CERT_SUBJECT* The *KeyName* contains the subject from the certificate corresponding to the realm key. This option is expected by Microsoft Active Directory Federation Services. -* *NONE* The *KeyName* hint is completely omitted from the SAML message. --- -+ -*Canonicalization Method*:: The canonicalization method for XML signatures. - -=== Login settings - -*Login theme*:: A theme to use for login, OTP, grant registration, and forgotten password pages. - -*Consent required*:: If enabled, users have to consent to client access. -+ -For client-side clients that perform browser logins. As it is not possible to ensure that secrets can be kept safe with client-side clients, it is important to restrict access by configuring correct redirect URIs. - -*Display client on screen*:: This switch applies if *Consent Required* is *Off*. -* _Off_ -+ -The consent screen will contain only the consents corresponding to configured client scopes. - -* _On_ -+ -There will be also one item on the consent screen about this client itself. - -*Client consent screen text*:: Applies if *Consent required* and *Display client on screen* are enabled. Contains the text that will be on the consent screen about permissions for this client. - -=== Logout settings - -*Front channel logout*:: If *Front Channel Logout* is enabled, the application requires a browser redirect to perform a logout. For example, the application may require a cookie to be reset which could only be done via a redirect. If *Front Channel Logout* is disabled, {project_name} invokes a background SAML request to log out of the application. - -== Keys tab - -*Encrypt Assertions*:: Encrypts the assertions in SAML documents with the realms private key. The AES algorithm uses a key size of 128 bits. - -*Client Signature Required*:: If *Client Signature Required* is enabled, documents coming from a client are expected to be signed. {project_name} will validate this signature using the client public key or cert set up in the `Keys` tab. - -*Allow ECP Flow*:: If true, this application is allowed to use SAML ECP profile for authentication. - -== Advanced tab - -This tab has many fields for specific situations. Some fields are covered in other topics. For details on other fields, click the question mark icon. - -=== Fine Grain SAML Endpoint Configuration - -*Logo URL*:: URL that references a logo for the Client application. - -*Policy URL*:: URL that the Relying Party Client provides to the End-User to read about how the profile data will be used. - -*Terms of Service URL*:: URL that the Relying Party Client provides to the End-User to read about the Relying Party's terms of service. - -*Assertion Consumer Service POST Binding URL*:: POST Binding URL for the Assertion Consumer Service. - -*Assertion Consumer Service Redirect Binding URL*:: Redirect Binding URL for the Assertion Consumer Service. - -*Logout Service POST Binding URL*:: POST Binding URL for the Logout Service. - -*Logout Service Redirect Binding URL*:: Redirect Binding URL for the Logout Service. - -*Logout Service Artifact Binding URL*:: _Artifact_ Binding URL for the Logout Service. When set together with the `Force Artifact Binding` option, _Artifact_ binding is forced for both login and logout flows. _Artifact_ binding is not used for logout unless this property is set. - -*Logout Service SOAP Binding URL*:: Redirect Binding URL for the Logout Service. Only applicable if *back channel logout* is used. - -*Artifact Binding URL*:: URL to send the HTTP artifact messages to. - -*Artifact Resolution Service*:: URL of the client SOAP endpoint where to send the `ArtifactResolve` messages to. - diff --git a/server_admin/topics/clients/saml/proc-using-an-entity-descriptor.adoc b/server_admin/topics/clients/saml/proc-using-an-entity-descriptor.adoc deleted file mode 100644 index 728ea3edd..000000000 --- a/server_admin/topics/clients/saml/proc-using-an-entity-descriptor.adoc +++ /dev/null @@ -1,23 +0,0 @@ -[id="proc-using-an-entity-descriptors_{context}"] - -= Using an entity descriptor to create a client -[role="_abstract"] -Instead of registering a SAML 2.0 client manually, you can import the client using a standard SAML Entity Descriptor XML file. - -The Client page includes an *Import client* option. - -.Add client -image:images/import-client-saml.png[Import SAML client] - -.Procedure -. Click *Browse*. -. Load the file that contains the XML entity descriptor information. -. Review the information to ensure everything is set up correctly. - -Some SAML client adapters, such as _mod-auth-mellon_, need the XML Entity Descriptor for the IDP. You can find this descriptor by going to this URL: - -[source, subs="attributes"] ----- -root{kc_realms_path}/{realm}/protocol/saml/descriptor ----- -where _realm_ is the realm of your client. diff --git a/server_admin/topics/events.adoc b/server_admin/topics/events.adoc deleted file mode 100644 index 9b602c63f..000000000 --- a/server_admin/topics/events.adoc +++ /dev/null @@ -1,9 +0,0 @@ - -== Configuring auditing to track events - -[role="_abstract"] -{project_name} includes a suite of auditing capabilities. You can record every login and administrator action and review those actions in the Admin Console. {project_name} also includes a Listener SPI that listens for events and can trigger actions. Examples of built-in listeners include log files and sending emails if an event occurs. - -include::events/login.adoc[] -include::events/admin.adoc[] - diff --git a/server_admin/topics/events/admin.adoc b/server_admin/topics/events/admin.adoc deleted file mode 100644 index 73fc84912..000000000 --- a/server_admin/topics/events/admin.adoc +++ /dev/null @@ -1,43 +0,0 @@ - -=== Auditing admin events - -You can record all actions that are performed by an administrator in the Admin Console. The Admin Console performs administrative actions by invoking the {project_name} REST interface and {project_name} audits these REST invocations. You can view the resulting events in the Admin Console. - -.Procedure - -Use this procedure to start auditing admin actions. - -. Click *Realm settings* in the menu. -. Click the *Events* tab. -. Click the *Admin events settings* tab. -. Toggle *Save events* to *ON*. -+ -{project_name} displays the *Include representation* switch. -+ -. Toggle *Include representation* to *ON*. -+ -The `Include Representation` switch includes JSON documents sent through the admin REST API so you can view the administrators actions. -+ -.Admin events settings -image:images/admin-events-settings.png[Admin events settings] - -. Click *Save*. - -. To clear the database of stored actions, click *Clear admin events*. - -.Procedure - -You can now view admin events. - -. Click *Events* in the menu. -. Click the *Admin events* tab. -+ -.Admin events -image:images/admin-events.png[Admin events] - -When the `Include Representation` switch is ON, it can lead to storing a lot of information in the database. You can set a maximum length of the representation by using the `--spi-events-store-jpa-max-field-length` argument. This setting is useful if you want to adhere to the underlying storage limitation. For example: - -[source,bash] ----- -kc.[sh|bat] --spi-events-store-jpa-max-field-length=2500 ----- \ No newline at end of file diff --git a/server_admin/topics/events/login.adoc b/server_admin/topics/events/login.adoc deleted file mode 100644 index 1df417920..000000000 --- a/server_admin/topics/events/login.adoc +++ /dev/null @@ -1,187 +0,0 @@ - -=== Auditing user events - -You can record and view every event that affects users. {project_name} triggers login events for actions such as successful user login, a user entering an incorrect password, or a user account updating. By default, {project_name} does not store or display events in the Admin Console. Only the error events are logged to the Admin Console and the server’s log file. - -.Procedure - -Use this procedure to start auditing user events. - -. Click *Realm settings* in the menu. -. Click the *Events* tab. -. Click the *User events settings* tab. -. Toggle *Save events* to *ON*. -+ -.User events settings -image:images/user-events-settings.png[User events settings] - -. Specify the length of time to store events in the *Expiration* field. - -. Click *Add saved types* to see other events you can save. -+ -.Add types -image:images/add-event-types.png[Add types] - -. Click *Add*. - -Click *Clear user events* when you want to delete all saved events. - -.Procedure - -You can now view events. - -. Click the *Events* tab in the menu. -+ -.User events -image:images/user-events.png[Login Events] - -. To filter events, click *Search user event*. -+ -.Search user event -image:images/search-user-event.png[Search user event] - -==== Event types - -*Login events:* - -[cols="2",options="header"] -|=== -|Event |Description -|Login -|A user logs in. - -|Register -|A user registers. - -|Logout -|A user logs out. - -|Code to Token -|An application, or client, exchanges a code for a token. - -|Refresh Token -|An application, or client, refreshes a token. - -|=== - -*Account events:* - -[cols="2",options="header"] -|=== -|Event |Description -|Social Link -|A user account links to a social media provider. - -|Remove Social Link -|The link from a social media account to a user account severs. - -|Update Email -|An email address for an account changes. - -|Update Profile -|A profile for an account changes. - -|Send Password Reset -|{project_name} sends a password reset email. - -|Update Password -|The password for an account changes. - -|Update TOTP -|The Time-based One-time Password (TOTP) settings for an account changes. - -|Remove TOTP -|{project_name} removes TOTP from an account. - -|Send Verify Email -|{project_name} sends an email verification email. - -|Verify Email -|{project_name} verifies the email address for an account. - -|=== - -Each event has a corresponding error event. - -==== Event listener - -Event listeners listen for events and perform actions based on that event. {project_name} includes two built-in listeners, the Logging Event Listener and Email Event Listener. - -===== The logging event listener -When the Logging Event Listener is enabled, this listener writes to a log file when an error event occurs. - -An example log message from a Logging Event Listener: - ----- -11:36:09,965 WARN [org.keycloak.events] (default task-51) type=LOGIN_ERROR, realmId=master, - clientId=myapp, - userId=19aeb848-96fc-44f6-b0a3-59a17570d374, ipAddress=127.0.0.1, - error=invalid_user_credentials, auth_method=openid-connect, auth_type=code, - redirect_uri=http://localhost:8180/myapp, - code_id=b669da14-cdbb-41d0-b055-0810a0334607, username=admin ----- - -You can use the Logging Event Listener to protect against hacker bot attacks: - -. Parse the log file for the `LOGIN_ERROR` event. -. Extract the IP Address of the failed login event. -. Send the IP address to an intrusion prevention software framework tool. - -The Logging Event Listener logs events to the `org.keycloak.events` log category. {project_name} does not include debug log events in server logs, by default. - -To include debug log events in server logs: - -. Change the log level for the `org.keycloak.events` category -. Change the log level used by the Logging Event listener. - -To change the log level used by the Logging Event listener, add the following: - -[source,bash] ----- -bin/kc.[sh|bat] start --spi-events-listener-jboss-logging-success-level=info --spi-events-listener-jboss-logging-error-level=error ----- - -The valid values for log levels are `debug`, `info`, `warn`, `error`, and `fatal`. - -===== The Email Event Listener - -The Email Event Listener sends an email to the user's account when an event occurs and supports the following events: - -* Login Error. -* Update Password. -* Update Time-based One-time Password (TOTP). -* Remove Time-based One-time Password (TOTP). - -.Procedure - -To enable the Email Listener: - -. Click *Realm settings* in the menu. -. Click the *Events* tab. -. Click the *Event listeners* field. -. Select `email`. -+ -.Event listeners -image:images/event-listeners.png[Event listeners] - -You can exclude events by using the `--spi-events-listener-email-exclude-events` argument. For example: - -[source,bash] ----- -kc.[sh|bat] --spi-events-listener-email-exclude-events=UPDATE_TOTP,REMOVE_TOTP ----- - -You can set a maximum length of each Event detail in the database by using the `--spi-events-store-jpa-max-detail-length` argument. This setting is useful if a detail (for example, redirect_uri) is long. For example: - -[source,bash] ----- -kc.[sh|bat] --spi-events-store-jpa-max-detail-length=1000 ----- - -Also you can set a maximum length of all Event's details by using the `--spi-events-store-jpa-max-field-length` argument. This setting is useful if you want to adhere to the underlying storage limitation. For example: - -[source,bash] ----- -kc.[sh|bat] --spi-events-store-jpa-max-field-length=2500 ----- - diff --git a/server_admin/topics/export-import.adoc b/server_admin/topics/export-import.adoc deleted file mode 100644 index 2b9f8225b..000000000 --- a/server_admin/topics/export-import.adoc +++ /dev/null @@ -1,121 +0,0 @@ - -[id=assembly-exporting-importing_{context}] -== Importing and exporting the database -[role="_abstract"] -{project_name} includes the ability to export and import its entire database. - -You can migrate the whole {project_name} database from one environment to another or migrate to another database. The export/import triggers at server boot time, and its parameters pass through Java properties. - -[NOTE] -==== -Because import and export trigger at server startup, take no actions on the server or the database during export/import. -==== - -You can export/import your database to: - -* A directory on the filesystem. -* A single JSON file on your filesystem. - -When importing from a directory, the filenames must follow this naming convention: - -* -realm.json. For example, "acme-roadrunner-affairs-realm.json" for the realm named "acme-roadrunner-affairs". -* -users-.json. For example, "acme-roadrunner-affairs-users-0.json" for the first user's file of the realm named "acme-roadrunner-affairs" - -If you export to a directory, you can specify the number of users stored in each JSON file. - -[NOTE] -==== -Exporting into single files can produce large files, so if your database contains more than 500 users, export to a directory and not a single file. Exporting many users into a directory performs optimally as the directory provider uses a separate transaction for each "page" (a file of users). - -The default count of users per file and per transaction is fifty, but you can override this number. See <<_keycloak-migration-usersPerFile, keycloak.migration.usersPerFile>> for more information. - -Exporting to or importing from a single file uses one transaction, which can impair performance if the database contains many users. -==== - -To export into an unencrypted directory: - -[source] ----- -bin/standalone.sh -Dkeycloak.migration.action=export --Dkeycloak.migration.provider=dir -Dkeycloak.migration.dir= ----- - -To export into single JSON file: - -[source] ----- -bin/standalone.sh -Dkeycloak.migration.action=export --Dkeycloak.migration.provider=singleFile -Dkeycloak.migration.file= ----- - -Similarly, for importing,use `-Dkeycloak.migration.action=import` rather than `export`. For example: - -[source] ----- -bin/standalone.sh -Dkeycloak.migration.action=import --Dkeycloak.migration.provider=singleFile -Dkeycloak.migration.file= --Dkeycloak.migration.strategy=OVERWRITE_EXISTING ----- - -Other command line options include: - --Dkeycloak.migration.realmName:: -Use this property to export one specifically named realm. If this parameter is not specified, all realms export. - --Dkeycloak.migration.usersExportStrategy:: -This property specifies where users export to. Possible values include: - -* DIFFERENT_FILES - Users export into different files subject to the maximum <<_keycloak-migration-usersPerFile, number of users per file>>. DIFFERENT_FILES is the default value for this property. -* SKIP - {project_name} skips exporting users. -* REALM_FILE - Users export to the same file with the realm settings. The file is similar to "foo-realm.json" with realm data and users. -* SAME_FILE - Users export to the same file but different from the realm file. The result is similar to "foo-realm.json" with realm data and "foo-users.json" with users. - -[[_keycloak-migration-usersPerFile]] --Dkeycloak.migration.usersPerFile:: -This property specifies the number of users per file and database transaction. By default, its value is fifty. {project_name} uses this property if keycloak.migration.usersExportStrategy is DIFFERENT_FILES. - --Dkeycloak.migration.strategy:: -{project_name} uses this property when importing. It specifies how to proceed when a realm with the same name already exists in the database. - -Possible values are: - -* IGNORE_EXISTING - Do not import a realm if a realm with the same name already exists. -* OVERWRITE_EXISTING - Remove the existing realm and import the realm again with new data from the JSON file. Use this value to migrate from one environment to another fully. - -If you are importing files that are not from a {project_name} export, use the `keycloak.import` option. If you are importing more than one realm file, specify a comma-separated list of filenames. A list of filenames is more suitable than the previous cases because this happens after {project_name} initializes the master realm. - -Examples: - -* -Dkeycloak.import=/tmp/realm1.json -* -Dkeycloak.import=/tmp/realm1.json,/tmp/realm2.json - -[NOTE] -==== -You cannot use the `keycloak.import` parameter with `keycloak.migration.X` parameters. If you use these parameters together, {project_name} ignores the `keycloak.import` parameter. The `keycloak.import` mechanism ignores the realms which already exist in {project_name}. The `keycloak.import` mechanism is convenient for development purposes, but if more flexibility is needed, use the `keycloak.migration.X` parameters. -==== - -=== Admin console export/import - -{project_name} imports most resources from the Admin Console as well as exporting most resources. {project_name} does not support the export of users. - -[NOTE] -==== -{project_name} masks attributes containing secrets or private information in the export file. Export files from the Admin Console are not suitable for backups or data transfer between servers. Only boot-time exports are suitable for backups or data transfer between servers. -==== - -You can use the files created during an export to import from the Admin Console. You can export from one realm and import to another realm, or you can export from one server and import to another. - -[NOTE] -==== -The admin console export/import permits one realm per file only. -==== - -[WARNING] -==== -The Admin Console import can overwrite resources. Use this feature with caution, especially on a production server. JSON files from the Admin Console Export operation are not appropriate for data import because they contain invalid values for secrets. -==== - -[WARNING] -==== -You can use the Admin Console to export clients, groups, and roles. If the database in your realm contains many clients, groups, and roles, the export may take a long time to conclude, and the {project_name} server may not respond to user requests. Use this feature with caution, especially on a production server. -==== diff --git a/server_admin/topics/identity-broker.adoc b/server_admin/topics/identity-broker.adoc deleted file mode 100644 index 45c0b1804..000000000 --- a/server_admin/topics/identity-broker.adoc +++ /dev/null @@ -1,19 +0,0 @@ - -[[_identity_broker]] -== Integrating identity providers - -An Identity Broker is an intermediary service connecting service providers with identity providers. The identity broker creates a relationship with an external identity provider to use the provider's identities to access the internal services the service provider exposes. - -From a user perspective, identity brokers provide a user-centric, centralized way to manage identities for security domains and realms. You can link an account with one or more identities from identity providers or create an account based on the identity information from them. - -An identity provider derives from a specific protocol used to authenticate and send authentication and authorization information to users. It can be: - -* A social provider such as Facebook, Google, or Twitter. -* A business partner whose users need to access your services. -* A cloud-based identity service you want to integrate. - -Typically, {project_name} bases identity providers on the following protocols: - -* `SAML v2.0` -* `OpenID Connect v1.0` -* `OAuth v2.0` diff --git a/server_admin/topics/identity-broker/configuration.adoc b/server_admin/topics/identity-broker/configuration.adoc deleted file mode 100644 index 3dca155db..000000000 --- a/server_admin/topics/identity-broker/configuration.adoc +++ /dev/null @@ -1,69 +0,0 @@ - -[[_general-idp-config]] - -=== General configuration - -The foundations of the identity broker configuration are identity providers (IDPs). {project_name} creates identity providers for each realm and enables them for every application by default. Users from a realm can use any of the registered identity providers when signing in to an application. - -.Procedure -. Click *Identity Providers* in the menu. -+ -.Identity Providers -image:images/identity-providers.png[Identity Providers] -+ -. Select an identity provider. {project_name} displays the configuration page for the identity provider you selected. -+ -.Add Facebook identity Provider -image:images/add-identity-provider.png[Add Facebook Identity Provider] -+ -When you configure an identity provider, the identity provider appears on the {project_name} login page as an option. You can place custom icons on the login screen for each identity provider. See link:{developerguide_link}#custom-identity-providers-icons[custom icons] for more information. -+ -.IDP login page -image:images/identity-provider-login-page.png[] - -Social:: - Social providers enable social authentication in your realm. With {project_name}, users can log in to your application using a social network account. Supported providers include Twitter, Facebook, Google, LinkedIn, Instagram, Microsoft, PayPal, Openshift v3, GitHub, GitLab, Bitbucket, and Stack Overflow. - -Protocol-based:: - Protocol-based providers rely on specific protocols to authenticate and authorize users. Using these providers, you can connect to any identity provider compliant with a specific protocol. {project_name} provides support for SAML v2.0 and OpenID Connect v1.0 protocols. You can configure and broker any identity provider based on these open standards. - -Although each type of identity provider has its configuration options, all share a common configuration. The following configuration options available: - -.Common Configuration -[cols="1,1", options="header"] -|=== -|Configuration|Description - -|Alias -|The alias is a unique identifier for an identity provider and references an internal identity provider. {project_name} uses the alias to build redirect URIs for OpenID Connect protocols that require a redirect URI or callback URL to communicate with an identity provider. All identity providers must have an alias. Alias examples include `facebook`, `google`, and `idp.acme.com`. - -|Enabled -|Toggles the provider ON or OFF. - -|Hide on Login Page -|When *ON*, {project_name} does not display this provider as a login option on the login page. Clients can request this provider by using the 'kc_idp_hint' parameter in the URL to request a login. - -|Account Linking Only -|When *ON*, {project_name} links existing accounts with this provider. This provider cannot log users in, and {project_name} does not display this provider as an option on the login page. - -|Store Tokens -|When *ON*, {project_name} stores tokens from the identity provider. - -|Stored Tokens Readable -|When *ON*, users can retrieve the stored identity provider token. This action also applies to the _broker_ client-level role _read token_. - -|Trust Email -|When *ON*, {project_name} trusts email addresses from the identity provider. If the realm requires email validation, users that log in from this identity provider do not need to perform the email verification process. - -|GUI Order -|The sort order of the available identity providers on the login page. - -|First Login Flow -|The authentication flow {project_name} triggers when users use this identity provider to log into {project_name} for the first time. - -|Post Login Flow -|The authentication flow {project_name} triggers when a user finishes logging in with the external identity provider. - -|Sync Mode -|Strategy to update user information from the identity provider through mappers. When choosing *legacy*, {project_name} used the current behavior. *Import* does not update user data and *force* updates user data when possible. See <<_mappers, Identity Provider Mappers>> for more information. -|=== diff --git a/server_admin/topics/identity-broker/default-provider.adoc b/server_admin/topics/identity-broker/default-provider.adoc deleted file mode 100644 index 53f5e2359..000000000 --- a/server_admin/topics/identity-broker/default-provider.adoc +++ /dev/null @@ -1,16 +0,0 @@ - -[[default_identity_provider]] - -=== Default Identity Provider - -{project_name} can redirect to an identity provider rather than displaying the login form. To enable this redirection: - -.Procedure -. Click *Authentication* in the menu. -. Click the *Browser* flow. -. Click the gear icon *⚙️* on the *Identity Provider Redirector* row. -. Set *Default Identity Provider* to the identity provider you want to redirect users to. - -If {project_name} does not find the configured default identity provider, the login form is displayed. - -This authenticator is responsible for processing the `kc_idp_hint` query parameter. See the <<_client_suggested_idp, client suggested identity provider>> section for more information. diff --git a/server_admin/topics/identity-broker/first-login-flow.adoc b/server_admin/topics/identity-broker/first-login-flow.adoc deleted file mode 100644 index c72077075..000000000 --- a/server_admin/topics/identity-broker/first-login-flow.adoc +++ /dev/null @@ -1,117 +0,0 @@ - -[[_identity_broker_first_login]] - -=== First login flow - -When users log in through identity brokering, {project_name} imports and links aspects of the user within the realm's local database. When {project_name} successfully authenticates users through an external identity provider, two situations can exist: - -* {project_name} has already imported and linked a user account with the authenticated identity provider account. In this case, {project_name} authenticates as the existing user and redirects back to the application. -* No account exists for this user in {project_name}. Usually, you register and import a new account into the {project_name} database, but there may be an existing {project_name} account with the same email address. Automatically linking the existing local account to the external identity provider is a potential security hole. You cannot always trust the information you get from the external identity provider. - -Different organizations have different requirements when dealing with some of these situations. With {project_name}, you can use the `First Login Flow` option in the IDP settings to choose a <<_authentication-flows, workflow>> for a user logging in from an external IDP for the first time. By default, the `First Login Flow` option points to the `first broker login` flow, but you can use your flow or different flows for different identity providers. - -The flow is in the Admin Console under the *Authentication* tab. When you choose the `First Broker Login` flow, you see the authenticators used by default. You can re-configure the existing flow. For example, you can disable some authenticators, mark some of them as `required`, or configure some authenticators. - -ifeval::[{project_community}==true] -You can also create a new authentication flow, write your own Authenticator implementations, and use it in your flow. See link:{developerguide_link}[{developerguide_name}] for more information. -endif::[] - -==== Default first login flow authenticators - -Review Profile:: -* This authenticator displays the profile information page, so the users can review their profile that {project_name} retrieves from an identity provider. -* You can set the `Update Profile On First Login` option in the *Actions* menu. -* When *ON*, users are presented with the profile page requesting additional information to federate the user's identities. -* When *missing*, users are presented with the profile page if the identity provider does not provide mandatory information, such as email, first name, or last name. -* When *OFF*, the profile page does not display unless the user clicks in a later phase on the `Review profile info` link in the page displayed by the `Confirm Link Existing Account` authenticator. - -Create User If Unique:: - This authenticator checks if there is already an existing {project_name} account with the same email or username like the account from the identity provider. - If it's not, then the authenticator just creates a new local {project_name} account and links it with the identity provider and the whole flow is finished. - Otherwise it goes to the next `Handle Existing Account` subflow. - If you always want to ensure that there is no duplicated account, you can mark this authenticator as `REQUIRED`. In this case, the user - will see the error page if there is an existing {project_name} account and the user will need to link the identity provider account through Account management. -* This authenticator verifies that there is already a {project_name} account with the same email or username as the identity provider's account. -* If an account does not exist, the authenticator creates a local {project_name} account, links this account with the identity provider, and terminates the flow. -* If an account exists, the authenticator implements the next `Handle Existing Account` sub-flow. -* To ensure there is no duplicated account, you can mark this authenticator as `REQUIRED`. The user sees the error page if a {project_name} account exists, and users must link their identity provider account through Account management. - - -Confirm Link Existing Account:: -* On the information page, users see a {project_name} account with the same email. Users can review their profile again and use a different email or username. The flow restarts and goes back to the `Review Profile` authenticator. -* Alternatively, users can confirm that they want to link their identity provider account with their existing {project_name} account. -* Disable this authenticator if you do not want users to see this confirmation page and go straight to linking identity provider account by email verification or re-authentication. - -Verify Existing Account By Email:: -* This authenticator is `ALTERNATIVE` by default. {project_name} uses this authenticator if the realm has an SMTP setup configured. -* The authenticator sends an email to users to confirm that they want to link the identity provider with their {project_name} account. -* Disable this authenticator if you do not want to confirm linking by email, but want users to reauthenticate with their password. - -Verify Existing Account By Re-authentication:: -* Use this authenticator if the email authenticator is not available. For example, you have not configured SMTP for your realm. This authenticator displays a login screen for users to authenticate to link their {project_name} account with the Identity Provider. -* Users can also re-authenticate with another identity provider already linked to their {project_name} account. -* You can force users to use OTP. Otherwise, it is optional and used if you have set OTP for the user account. - -==== Automatically link existing first login flow - -[WARNING] -==== -The AutoLink authenticator is dangerous in a generic environment where users can register themselves using arbitrary usernames or email addresses. Do not use this authenticator unless you are carefully curating user registration and assigning usernames and email addresses. -==== - -To configure a first login flow that links users automatically without prompting, create a new flow with the following two authenticators: - -Create User If Unique:: -This authenticator ensures {project_name} handles unique users. Set the authenticator requirement to *Alternative*. - -Automatically Set Existing User:: -This authenticator sets an existing user to the authentication context without verification. Set the authenticator requirement to "Alternative". - -[NOTE] -==== -This setup is the simplest setup available, but it is possible to use other authenticators. For example: -* You can add the Review Profile authenticator to the beginning of the flow if you want end users to confirm their profile information. -* You can add authentication mechanisms to this flow, forcing a user to verify their credentials. Adding authentication mechanisms requires a complex flow. For example, you can set the "Automatically Set Existing User" and "Password Form" as "Required" in an "Alternative" sub-flow. -==== - -[[_disabling_automatic_user_creation]] -==== Disabling automatic user creation -The Default first login flow looks up the {project_name} account matching the external identity and offers to link them. If no matching {project_name} account exists, the flow automatically creates one. - -This default behavior may be unsuitable for some setups. One example is when you use a read-only LDAP user store, where all users are pre-created. In this case, you must switch off automatic user creation. - -To disable user creation: - -.Procedure -. Click *Authentication* in the menu. -. Select *First Broker Login* from the list. -. Set *Create User If Unique* to *DISABLED*. -. Set *Confirm Link Existing Account* to *DISABLED*. - -This configuration also implies that {project_name} itself won't be able to determine which internal account would correspond to the external identity. -Therefore, the `Verify Existing Account By Re-authentication` authenticator will ask the user to provide both username and password. - -NOTE: Enabling or disabling user creation by identity provider is completely independent on the realm <>. You can have enabled user-creation -by identity provider and at the same time disabled user self-registration in the realm login settings or vice-versa. - -[[_detect_existing_user_first_login_flow]] -==== Detect existing user first login flow -In order to configure a first login flow in which: - - - only users already registered in this realm can log in, - - users are automatically linked without being prompted, - -create a new flow with the following two authenticators: - -Detect Existing Broker User:: -This authenticator ensures that unique users are handled. Set the authenticator requirement to `REQUIRED`. - -Automatically Set Existing User:: -Automatically sets an existing user to the authentication context without any verification. Set the authenticator requirement to `REQUIRED`. - -You have to set the `First Login Flow` of the identity provider configuration to that flow. -You could set the also set `Sync Mode` to `force` if you want to update the user profile (Last Name, First Name...) with the identity provider attributes. - -NOTE: This flow can be used if you want to delegate the identity to other identity providers (such as GitHub, Facebook ...) but you want to manage which users that can log in. - -With this configuration, {project_name} is unable to determine which internal account corresponds to the external identity. The *Verify Existing Account By Re-authentication* authenticator asks the provider for the username and password. diff --git a/server_admin/topics/identity-broker/logout.adoc b/server_admin/topics/identity-broker/logout.adoc deleted file mode 100644 index b563fc9e7..000000000 --- a/server_admin/topics/identity-broker/logout.adoc +++ /dev/null @@ -1,4 +0,0 @@ - -=== Identity broker logout - -When logging out, {project_name} sends a request to the external identity provider that is used to log in initially and logs the user out of this identity provider. You can skip this behavior and avoid logging out of the external identity provider. See link:{adapterguide_logout_link}[adapter logout documentation] for more information. diff --git a/server_admin/topics/identity-broker/mappers.adoc b/server_admin/topics/identity-broker/mappers.adoc deleted file mode 100644 index e85d4f7be..000000000 --- a/server_admin/topics/identity-broker/mappers.adoc +++ /dev/null @@ -1,32 +0,0 @@ - -[[_mappers]] -=== Mapping claims and assertions - -You can import the SAML and OpenID Connect metadata, provided by the external IDP you are authenticating with, into the realm. After importing, you can extract user profile metadata and other information, so you can make it available to your applications. - -Each user logging into your realm using an external identity provider has an entry in the local {project_name} database, based on the metadata from the SAML or OIDC assertions and claims. - -.Procedure -. Click *Identity Providers* in the menu. -. Select one of the identity providers in the list. -. Click the *Mappers* tab. -+ -.Identity provider mappers -image:images/identity-provider-mappers.png[identity provider mappers] -+ -. Click *Add mapper*. -+ -.Identity provider mapper -image:images/identity-provider-mapper.png[identity provider mapper] -+ -. Select a value for *Sync Mode Override*. The mapper updates user information when users log in repeatedly according to this setting. -.. Select *legacy* to use the behavior of the previous {project_name} version. -.. Select *import* to import data from when the user was first created in {project_name} during the first login to {project_name} with a particular identity provider. -.. Select *force* to update user data at each user login. -.. Select *inherit* to use the sync mode configured in the identity provider. All other options will override this sync mode. -. Select a mapper from the *Mapper Type* list. Hover over the *Mapper Type* for a description of the mapper and configuration to enter for the mapper. -. Click *Save*. - -For JSON-based claims, you can use dot notation for nesting and square brackets to access array fields by index. For example, `contact.address[0].country`. - -To investigate the structure of user profile JSON data provided by social providers, you can enable the `DEBUG` level logger `org.keycloak.social.user_profile_dump` when starting the server. diff --git a/server_admin/topics/identity-broker/oidc.adoc b/server_admin/topics/identity-broker/oidc.adoc deleted file mode 100644 index 9cb27cf51..000000000 --- a/server_admin/topics/identity-broker/oidc.adoc +++ /dev/null @@ -1,80 +0,0 @@ - -[[_identity_broker_oidc]] -=== OpenID Connect v1.0 identity providers - -{project_name} brokers identity providers based on the OpenID Connect protocol. These identity providers (IDPs) must support the xref:con-oidc-auth-flows_{context}[Authorization Code Flow] defined in the specification to authenticate users and authorize access. - - -.Procedure -. Click *Identity Providers* in the menu. -. From the `Add provider` list, select `OpenID Connect v1.0`. -+ -.Add identity provider -image:images/oidc-add-identity-provider.png[Add Identity Provider] -+ -. Enter your initial configuration options. See <<_general-idp-config, General IDP Configuration>> for more information about configuration options. -+ -.OpenID connect config -|=== -|Configuration|Description - -|Authorization URL -|The authorization URL endpoint the OIDC protocol requires. - -|Token URL -|The token URL endpoint the OIDC protocol requires. - -|Logout URL -|The logout URL endpoint in the OIDC protocol. This value is optional. - -|Backchannel Logout -|A background, out-of-band, REST request to the IDP to log out the user. Some IDPs perform logout through browser redirects only, as they may identify sessions using a browser cookie. - -|User Info URL -|An endpoint the OIDC protocol defines. This endpoint points to user profile information. - -|Client Authentication -|Defines the Client Authentication method {project_name} uses with the Authorization Code Flow. In the case of JWT signed with a private key, {project_name} uses the realm private key. In the other cases, define a client secret. See the https://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication[Client Authentication specifications] for more information. - -|Client ID -|A realm acting as an OIDC client to the external IDP. The realm must have an OIDC client ID if you use the Authorization Code Flow to interact with the external IDP. - -|Client Secret -|Client secret from an external <<_vault-administration,vault>>. This secret is necessary if you are using the Authorization Code Flow. - -|Client Assertion Signature Algorithm -|Signature algorithm to create JWT assertion as client authentication. -In the case of JWT signed with private key or Client secret as jwt, it is required. If no algorithm is specified, the following algorithm is adapted. `RS256` is adapted in the case of JWT signed with private key. `HS256` is adapted in the case of Client secret as jwt. - -|Issuer -|{project_name} validates issuer claims, in responses from the IDP, against this value. - -|Default Scopes -|A list of OIDC scopes {project_name} sends with the authentication request. The default value is `openid`. A space separates each scope. - -|Prompt -|The prompt parameter in the OIDC specification. Through this parameter, you can force re-authentication and other options. See the specification for more details. - -|Accepts prompt=none forward from client -|Specifies if the IDP accepts forwarded authentication requests containing the `prompt=none` query parameter. If a realm receives an auth request with `prompt=none`, the realm checks if the user is currently authenticated and returns a `login_required` error if the user has not logged in. When {project_name} determines a default IDP for the auth request (using the `kc_idp_hint` query parameter or having a default IDP for the realm), you can forward the auth request with `prompt=none` to the default IDP. The default IDP checks the authentication of the user there. Because not all IDPs support requests with `prompt=none`, {project_name} uses this switch to indicate that the default IDP supports the parameter before redirecting the authentication request. - -If the user is unauthenticated in the IDP, the client still receives a `login_required` error. If the user is authentic in the IDP, the client can still receive an `interaction_required` error if {project_name} must display authentication pages that require user interaction. This authentication includes required actions (for example, password change), consent screens, and screens set to display by the `first broker login` flow or `post broker login` flow. - -|Validate Signatures -|Specifies if {project_name} verifies signatures on the external ID Token signed by this IDP. If *ON*, {project_name} must know the public key of the external OIDC IDP. For performance purposes, {project_name} caches the public key of the external OIDC identity provider. - -|Use JWKS URL -|This switch is applicable if `Validate Signatures` is *ON*. If *Use JWKS URL* is *ON*, {project_name} downloads the IDP's public keys from the JWKS URL. New keys download when the identity provider generates a new keypair. If *OFF*, {project_name} uses the public key (or certificate) from its database, so when the IDP keypair changes, import the new key to the {project_name} database as well. - -|JWKS URL -|The URL pointing to the location of the IDP JWK keys. For more information, see the https://self-issued.info/docs/draft-ietf-jose-json-web-key.html[JWK specification]. If you use an external {project_name} as an IDP, you can use a URL such as http://broker-keycloak:8180{kc_realms_path}/test/protocol/openid-connect/certs if your brokered {project_name} is running on http://broker-keycloak:8180 and its realm is `test`. - -|Validating Public Key -|The public key in PEM format that {project_name} uses to verify external IDP signatures. This key applies if `Use JWKS URL` is *OFF*. - -|Validating Public Key Id -|This setting applies if *Use JWKS URL* is *OFF*. This setting specifies the ID of the public key in PEM format. Because there is no standard way for computing key ID from the key, external identity providers can use different algorithms from what {project_name} uses. If this field's value is not specified, {project_name} uses the validating public key for all requests, regardless of the key ID sent by the external IDP. When *ON*, this field's value is the key ID used by {project_name} for validating signatures from providers and must match the key ID specified by the IDP. - -|=== - -You can import all this configuration data by providing a URL or file that points to OpenID Provider Metadata. If you connect to a {project_name} external IDP, you can import the IDP settings from `{kc_realms_path}/{realm-name}/.well-known/openid-configuration`. This link is a JSON document describing metadata about the IDP. diff --git a/server_admin/topics/identity-broker/overview.adoc b/server_admin/topics/identity-broker/overview.adoc deleted file mode 100644 index 1ec4ba482..000000000 --- a/server_admin/topics/identity-broker/overview.adoc +++ /dev/null @@ -1,33 +0,0 @@ - -[[_identity_broker_overview]] - -=== Brokering overview - -When using {project_name} as an identity broker, {project_name} does not force users to provide their credentials to authenticate in a specific realm. {project_name} displays a list of identity providers from which they can authenticate. - -If you configure a default identity provider, {project_name} redirects users to the default provider. - -[NOTE] -==== -Different protocols may require different authentication flows. All the identity providers supported by {project_name} use the following flow. -==== - -.Identity broker flow -image:images/identity_broker_flow.png[Identity broker flow] - -. The unauthenticated user requests a protected resource in a client application. -. The client application redirects the user to {project_name} to authenticate. -. {project_name} displays the login page with a list of identity providers configured in a realm. -. The user selects one of the identity providers by clicking its button or link. -. {project_name} issues an authentication request to the target identity provider requesting authentication and redirects the user to the identity provider's login page. The administrator has already set the connection properties and other configuration options for the Admin Console's identity provider. -. The user provides credentials or consents to authenticate with the identity provider. -. Upon successful authentication by the identity provider, the user redirects back to {project_name} with an authentication response. Usually, the response contains a security token used by {project_name} to trust the identity provider's authentication and retrieve user information. -. {project_name} checks if the response from the identity provider is valid. - If valid, {project_name} imports and creates a user if the user does not already exist. {project_name} may ask the identity provider for further user information if the token does not contain that information. This behavior is _identity federation_. - If the user already exists, {project_name} may ask the user to link the identity returned from the identity provider with the existing account. This behavior is _account linking_. With {project_name}, you can configure _Account linking_ and specify it in the <<_identity_broker_first_login,First Login Flow>>. At this step, {project_name} authenticates the user and issues its token to access the requested resource in the service provider. -. When the user authenticates, {project_name} redirects the user to the service provider by sending the token previously issued during the local authentication. -. The service provider receives the token from {project_name} and permits access to the protected resource. - -Variations of this flow are possible. For example, the client application can request a specific identity provider rather than displaying a list of them, or you can set {project_name} to force users to provide additional information before federating their identity. - -At the end of the authentication process, {project_name} issues its token to client applications. Client applications are separate from the external identity providers, so they cannot see the client application's protocol or how they validate the user's identity. The provider only needs to know about {project_name}. diff --git a/server_admin/topics/identity-broker/saml.adoc b/server_admin/topics/identity-broker/saml.adoc deleted file mode 100644 index d7bd9cf8d..000000000 --- a/server_admin/topics/identity-broker/saml.adoc +++ /dev/null @@ -1,151 +0,0 @@ - -=== SAML v2.0 Identity Providers - -{project_name} can broker identity providers based on the SAML v2.0 protocol. - -.Procedure -. Click *Identity Providers* in the menu. -. From the `Add provider` list, select `SAML v2.0`. -+ -.Add identity provider -image:images/saml-add-identity-provider.png[Add Identity Provider] -+ -. Enter your initial configuration options. See <<_general-idp-config, General IDP Configuration>> for more information about configuration options. - -.SAML Config -|=== -|Configuration|Description - -|Service Provider Entity ID -|The SAML Entity ID that the remote Identity Provider uses to identify requests from this Service Provider. By default, this setting is set to the realms base URL `{kc_realms_path}/{realm-name}`. - -|Identity Provider Entity ID -|The Entity ID used to validate the Issuer for received SAML assertions. If empty, no Issuer validation is performed. - -|Single Sign-On Service URL -|The SAML endpoint that starts the authentication process. If your SAML IDP publishes an IDP entity descriptor, the value of this field is specified there. - -|Single Logout Service URL -|The SAML logout endpoint. If your SAML IDP publishes an IDP entity descriptor, the value of this field is specified there. - -|Backchannel Logout -|Toggle this switch to *ON* if your SAML IDP supports back channel logout. - -|NameID Policy Format -|The URI reference corresponding to a name identifier format. By default, {project_name} sets it to `urn:oasis:names:tc:SAML:2.0:nameid-format:persistent`. - -|Principal Type -|Specifies which part of the SAML assertion will be used to identify and track external user identities. Can be either Subject NameID or SAML attribute (either by name or by friendly name). Subject NameID value can not be set together with 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient' NameID Policy Format value. - -|Principal Attribute -|If a Principal type is non-blank, this field specifies the name ("Attribute [Name]") or the friendly name ("Attribute [Friendly Name]") of the identifying attribute. - -|Allow create -|Allow the external identity provider to create a new identifier to represent the principal. - -|HTTP-POST Binding Response -|Controls the SAML binding in response to any SAML requests sent by an external IDP. When *OFF*, {project_name} uses Redirect Binding. - -|HTTP-POST Binding for AuthnRequest -|Controls the SAML binding when requesting authentication from an external IDP. When *OFF*, {project_name} uses Redirect Binding. - -|Want AuthnRequests Signed -|When *ON*, {project_name} uses the realm's keypair to sign requests sent to the external SAML IDP. - -|Want Assertions Signed -|Indicates whether this service provider expects a signed Assertion. - -|Want Assertions Encrypted -|Indicates whether this service provider expects an encrypted Assertion. - -|Signature Algorithm -|If *Want AuthnRequests Signed* is *ON*, the signature algorithm to use. Note that `SHA1` based algorithms are deprecated and may be removed in a future release. -We recommend to use some more secure algorithm instead of `*_SHA1`. Also, with `*_SHA1` algorithms, verifying signatures -do not work if the SAML identity provider (for example another instance of {project_name}) runs on Java 17 or higher. - -|Encryption Algorithm -|Encryption algorithm, which is used by SAML IDP for encryption of SAML -documents, assertions, or IDs. The corresponding decryption key for decrypt -SAML document parts will be chosen based on this configured algorithm and -should be available in realm keys for the encryption (ENC) usage. If the -algorithm is not configured, any supported algorithm is allowed and a -decryption key will be chosen based on the algorithm specified in SAML document -itself. - -|SAML Signature Key Name -|Signed SAML documents sent using POST binding contain the identification of signing key in `KeyName` element, which, by default, contains the {project_name} key ID. External SAML IDPs can expect a different key name. This switch controls whether `KeyName` contains: -* `KEY_ID` - Key ID. -* `CERT_SUBJECT` - the subject from the certificate corresponding to the realm key. Microsoft Active Directory Federation Services expect `CERT_SUBJECT`. -* `NONE` - {project_name} omits the key name hint from the SAML message. - -|Force Authentication -|The user must enter their credentials at the external IDP even when the user is already logged in. - -|Validate Signature -|When *ON*, the realm expects SAML requests and responses from the external IDP to be digitally signed. - -|Validating X509 Certificate -|The public certificate {project_name} uses to validate the signatures of SAML requests and responses from the external IDP. - -|Sign Service Provider Metadata -|When *ON*, {project_name} uses the realm's key pair to sign the <<_identity_broker_saml_sp_descriptor, SAML Service Provider Metadata descriptor>>. - -|Pass subject -|Controls if {project_name} forwards a `login_hint` query parameter to the IDP. {project_name} adds this field's value to the login_hint parameter in the AuthnRequest's Subject so destination providers can pre-fill their login form. - -|Attribute Consuming Service Index -|Identifies the attribute set to request to the remote IDP. {project_name} automatically adds the attributes mapped in the identity provider configuration to the autogenerated SP metadata document. - -|Attribute Consuming Service Name -|A descriptive name for the set of attributes that are advertised in the autogenerated SP metadata document. -|=== - -You can import all configuration data by providing a URL or a file pointing to the SAML IDP entity descriptor of the external IDP. If you are connecting to a {project_name} external IDP, you can import the IDP settings from the URL `{kc_realms_path}/{realm-name}/protocol/saml/descriptor`. This link is an XML document describing metadata about the IDP. You can also import all this configuration data by providing a URL or XML file pointing to the external SAML IDP's entity descriptor to connect to. - -[[_identity_broker_saml_requested_authncontext]] -==== Requesting specific AuthnContexts -Identity Providers facilitate clients specifying constraints on the authentication method verifying the user identity. For example, asking for MFA, Kerberos authentication, or security requirements. These constraints use particular AuthnContext criteria. A client can ask for one or more criteria and specify how the Identity Provider must match the requested AuthnContext, exactly, or by satisfying other equivalents. - -You can list the criteria your Service Provider requires by adding ClassRefs or DeclRefs in the Requested AuthnContext Constraints section. Usually, you need to provide either ClassRefs or DeclRefs, so check with your Identity Provider documentation which values are supported. If no ClassRefs or DeclRefs are present, the Identity Provider does not enforce additional constraints. - -.Requested AuthnContext Constraints -|=== -|Configuration|Description - -|Comparison -|The method the Identity Provider uses to evaluate the context requirements. The available values are `Exact`, `Minimum`, `Maximum`, or `Better`. The default value is `Exact`. - -|AuthnContext ClassRefs -|The AuthnContext ClassRefs describing the required criteria. - -|AuthnContext DeclRefs -|The AuthnContext DeclRefs describing the required criteria. -|=== - -[[_identity_broker_saml_sp_descriptor]] -==== SP Descriptor - -When you access the provider's SAML SP metadata, look for the `Endpoints` item in the identity provider configuration settings. It contains a `SAML 2.0 Service Provider Metadata` link which generates the SAML entity descriptor for the Service Provider. You can download the descriptor or copy its URL and then import it into the remote Identity Provider. - -This metadata is also available publicly by going to the following URL: - -[source,subs=+attributes] ----- -http[s]://{host:port}{kc_realms_path}/{realm-name}/broker/{broker-alias}/endpoint/descriptor ----- - -Ensure you save any configuration changes before accessing the descriptor. - -[[_identity_broker_saml_login_hint]] -==== Send subject in SAML requests - -By default, a social button pointing to a SAML Identity Provider redirects the user to the following login URL: - -[source,subs=+attributes] ----- -http[s]://{host:port}{kc_realms_path}/${realm-name}/broker/{broker-alias}/login ----- - -Adding a query parameter named `login_hint` to this URL adds the parameter's value to SAML request as a Subject attribute. If this query parameter is empty, {project_name} does not add a subject to the request. - -Enable the "Pass subject" option to send the subject in SAML requests. diff --git a/server_admin/topics/identity-broker/session-data.adoc b/server_admin/topics/identity-broker/session-data.adoc deleted file mode 100644 index 2e352bb95..000000000 --- a/server_admin/topics/identity-broker/session-data.adoc +++ /dev/null @@ -1,12 +0,0 @@ - -=== Available user session data - -After a user login from an external IDP, {project_name} stores user session note data that you can access. This data can be propagated to the client requesting log in using the token or SAML assertion passed back to the client using an appropriate client mapper. - -identity_provider:: - The IDP alias of the broker used to perform the login. - -identity_provider_identity:: - The IDP username of the currently authenticated user. Often, but not always, the same as the {project_name} username. For example, {project_name} can link a user john` to a Facebook user `john123@gmail.com`. In that case, the value of the user session note is `john123@gmail.com`. - -You can use a <<_protocol-mappers, Protocol Mapper>> of type `User Session Note` to propagate this information to your clients. diff --git a/server_admin/topics/identity-broker/social-login.adoc b/server_admin/topics/identity-broker/social-login.adoc deleted file mode 100644 index 521241c26..000000000 --- a/server_admin/topics/identity-broker/social-login.adoc +++ /dev/null @@ -1,4 +0,0 @@ - -=== Social Identity Providers - -A social identity provider can delegate authentication to a trusted, respected social media account. {project_name} includes support for social networks such as Google, Facebook, Twitter, GitHub, LinkedIn, Microsoft, and Stack Overflow. diff --git a/server_admin/topics/identity-broker/social/bitbucket.adoc b/server_admin/topics/identity-broker/social/bitbucket.adoc deleted file mode 100644 index d4da992ce..000000000 --- a/server_admin/topics/identity-broker/social/bitbucket.adoc +++ /dev/null @@ -1,20 +0,0 @@ - -==== Bitbucket - -To log in with Bitbucket, perform the following procedure. - -.Procedure -. Click *Identity Providers* in the menu. -. From the `Add provider` list, select `Bitbucket`. -+ -.Add identity provider -image:images/bitbucket-add-identity-provider.png[Add Identity Provider] -+ -. Copy the value of *Redirect URI* to your clipboard. -. In a separate browser tab, perform the https://support.atlassian.com/bitbucket-cloud/docs/use-oauth-on-bitbucket-cloud/[OAuth on Bitbucket Cloud] process. When you click *Add Consumer*: -.. Paste the value of *Redirect URI* into the *Callback URL* field. -.. Ensure you select *Email* and *Read* in the *Account* section to permit your application to read email. -. Note the `Key` and `Secret` values Bitbucket displays when you create your consumer. -. In {project_name}, paste the value of the `Key` into the *Consumer Key* field. -. In {project_name}, paste the value of the `Secret` into the *Consumer Secret* field. -. Click *Add*. diff --git a/server_admin/topics/identity-broker/social/facebook.adoc b/server_admin/topics/identity-broker/social/facebook.adoc deleted file mode 100644 index 01e58e64f..000000000 --- a/server_admin/topics/identity-broker/social/facebook.adoc +++ /dev/null @@ -1,22 +0,0 @@ - -[[_facebook]] -==== Facebook - -.Procedure -. Click *Identity Providers* in the menu. -. From the `Add provider` list, select `Facebook`. {project_name} displays the configuration page for the Facebook identity provider. -+ -.Add identity provider -image:images/facebook-add-identity-provider.png[Add Identity Provider] -. Copy the value of *Redirect URI* to your clipboard. -. In a separate browser tab, follow the https://developers.facebook.com/docs/development/[Facebook Developer Guide's] instructions to create a project and client in Facebook. -.. Ensure your app is a website-type app. -.. Enter the *Redirect URI's* value into the `Site URL` of the Facebook `Website` settings block. -.. Ensure the app is public. -+ -. Enter the https://developers.facebook.com/docs/facebook-login/guides/access-tokens[`Client ID` and `Client Secret`] values from your Facebook app into the `Client ID` and `Client Secret` fields in {project_name}. -. Click *Add* - -. Enter the required scopes into the *Default Scopes* field. By default, {project_name} uses the `email` scope. See https://developers.facebook.com/docs/graph-api[Graph API] for more information about Facebook scopes. - -{project_name} sends profile requests to `graph.facebook.com/me?fields=id,name,email,first_name,last_name` by default. The response contains the id, name, email, first_name, and last_name fields only. To fetch additional fields from the Facebook profile, add a corresponding scope and add the field name in the `Additional user's profile fields` configuration option field. diff --git a/server_admin/topics/identity-broker/social/github.adoc b/server_admin/topics/identity-broker/social/github.adoc deleted file mode 100644 index a6c26b251..000000000 --- a/server_admin/topics/identity-broker/social/github.adoc +++ /dev/null @@ -1,22 +0,0 @@ - -[[_github]] - -==== GitHub - -To log in with GitHub, perform the following procedure. - -.Procedure -. Click *Identity Providers* in the menu. -. From the `Add provider` list, select `Github`. -+ -.Add identity provider -image:images/github-add-identity-provider.png[Add Identity Provider] -+ -. Copy the value of *Redirect URI* to your clipboard. -. In a separate browser tab, https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/creating-an-oauth-app[create an OAUTH app]. -.. Enter the value of *Redirect URI* into the `Authorization callback URL` field when creating the app. -.. Note the Client ID and Client secret on the management page of your OAUTH app. -. In {project_name}, paste the value of the `Client ID` into the *Client ID* field. -. In {project_name}, paste the value of the `Client Secret` into the *Client Secret* field. -. Click *Add*. - diff --git a/server_admin/topics/identity-broker/social/gitlab.adoc b/server_admin/topics/identity-broker/social/gitlab.adoc deleted file mode 100644 index 15db87307..000000000 --- a/server_admin/topics/identity-broker/social/gitlab.adoc +++ /dev/null @@ -1,19 +0,0 @@ - -==== GitLab - -.Procedure -. Click *Identity Providers* in the menu. -. From the `Add provider` list, select `GitLab`. -+ -.Add identity provider -image:images/gitlab-add-identity-provider.png[Add identity provider] -+ -. Copy the value of *Redirect URI* to your clipboard. -. In a separate browser tab, https://docs.gitlab.com/ee/integration/oauth_provider.html[add a new GitLab application]. -.. Use the *Redirect URI* in your clipboard as the *Redirect URI*. -.. Note the `Client ID` and `Client Secret` when you save the application. -. In {project_name}, paste the value of the `Client ID` into the *Client ID* field. -. In {project_name}, paste the value of the `Client Secret` into the *Client Secret* field. -. Click *Add*. - - diff --git a/server_admin/topics/identity-broker/social/google.adoc b/server_admin/topics/identity-broker/social/google.adoc deleted file mode 100644 index e9df37c14..000000000 --- a/server_admin/topics/identity-broker/social/google.adoc +++ /dev/null @@ -1,27 +0,0 @@ - -[[_google]] -==== Google - -.Procedure -. Click *Identity Providers* in the menu. -. From the `Add provider` list, select `Google`. -+ -.Add identity provider -image:images/google-add-identity-provider.png[Add Identity Provider] -+ -. Copy the value of *Redirect URI* to your clipboard. -. In a separate browser tab open https://console.cloud.google.com/[the Google Cloud Platform console]. -. In the Google dashboard for your Google app, click the *OAuth consent screen* menu. Create a consent screen, ensuring that the user type of the consent screen is external. -. In the Google dashboard: -.. Click the *Credentials* menu. -.. Click *CREATE CREDENTIALS* - *OAuth Client ID*. -.. From the *Application type* list, select *Web application*. -.. Use the *Redirect URI* in your clipboard as the *Authorized redirect URIs* -.. Click *Create*. -.. Note *Your Client ID* and *Your Client Secret*. -. In {project_name}, paste the value of the *Your Client ID* into the *Client ID* field. -. In {project_name}, paste the value of the *Your Client Secret* into the *Client Secret* field. -. Click *Add* -. Enter the required scopes into the *Default Scopes* field. By default, {project_name} uses the following scopes: `openid` `profile` `email`. See the https://developers.google.com/oauthplayground/[OAuth Playground] for a list of Google scopes. -. To restrict access to your GSuite organization's members only, enter the G Suite domain into the `Hosted Domain` field. -. Click *Save*. diff --git a/server_admin/topics/identity-broker/social/instagram.adoc b/server_admin/topics/identity-broker/social/instagram.adoc deleted file mode 100644 index c30007ecd..000000000 --- a/server_admin/topics/identity-broker/social/instagram.adoc +++ /dev/null @@ -1,61 +0,0 @@ - -==== Instagram - -.Procedure -. Click *Identity Providers* in the menu. -. From the `Add provider` list, select `Instagram`. {project_name} displays the configuration page for the Instagram identity provider. -+ -.Add identity provider -image:images/instagram-add-identity-provider.png[Add Identity Provider] -. Copy the value of *Redirect URI* to your clipboard. -. In a separate browser tab, open the https://developers.facebook.com/[Facebook Developer Console]. -.. Click *My Apps*. -.. Select *Add a New App*. -+ -.Add a new app -image:images/instagram-add-new-app.png[Add a New App] -+ -.. Select `For Everything Else`. -+ -.Create a new app ID -image:images/instagram-create-app-id.png[] -+ -.. Fill in all required fields. -.. Click *Create App*. Facebook then brings you to the dashboard. -.. In the navigation panel, select *Settings* - *Basic*. -+ -.Add platform -image:images/instagram-add-platform.png[Add Platform] -+ -.. Select *+ Add Platform*. -.. Click *[Website]*. -.. Enter a URL for your site. -+ -.Add a product -image:images/instagram-add-product.png[] -+ -.. Select `Dashboard` from the menu. -.. Click *Set Up* in the Instagram box. -.. Select *Instagram* - *Basic Display* from the menu. -.. Click *Create New App*. -+ -.Create a new Instagram app ID -image:images/instagram-create-instagram-app-id.png[Create a New Instagram App ID] -+ -.. Enter a value into *Display Name*. -+ -.Set up the app -image:images/instagram-app-settings.png[Setup the App] -+ -.. Paste the *Redirect URL* from {project_name} into the *Valid OAuth Redirect URIs* field. -.. Paste the *Redirect URL* from {project_name} into the *Deauthorize Callback URL* field. -.. Paste the *Redirect URL* from {project_name} into the *Data Deletion Request URL* field. -.. Click *Show* in the *Instagram App Secret* field. -.. Note the *Instagram App ID* and the *Instagram App Secret*. -.. Click *App Review* - *Requests*. -.. Follow the instructions on the screen. -. In {project_name}, paste the value of the *Instagram App ID* into the *Client ID* field. -. In {project_name}, paste the value of the *Instagram App Secret* into the *Client Secret* field. - -. Click *Add*. - diff --git a/server_admin/topics/identity-broker/social/linked-in.adoc b/server_admin/topics/identity-broker/social/linked-in.adoc deleted file mode 100644 index 45c0311c5..000000000 --- a/server_admin/topics/identity-broker/social/linked-in.adoc +++ /dev/null @@ -1,28 +0,0 @@ - -[[_linkedin]] - -==== LinkedIn - -.Procedure -. Click *Identity Providers* in the menu. -. From the `Add provider` list, select `LinkedIn`. -+ -.Add identity provider -image:images/linked-in-add-identity-provider.png[Add Identity Provider] -+ -. Copy the value of *Redirect URI* to your clipboard. -. In a separate browser tab, https://www.linkedin.com/developer/apps[create an app]. -.. After you create the app, click the *Auth* tab. -.. Enter the value of *Redirect URI* into the *Authorized redirect URLs for your app* field. -.. Note *Your Client ID* and *Your Client Secret*. -. In {project_name}, paste the value of the *Client ID* into the *Client ID* field. -. In {project_name}, paste the value of the *Client Secret* into the *Client Secret* field. -. Click *Add*. - -.Configuration -* With `Profile Projection` you can configure the `projection` parameter for profile requests. -* For example, `(id,firstName,lastName,profilePicture(displayImage~:playableStreams))` produces the following profile request URL: -[source,txt] ----- -https://api.linkedin.com/v2/me?projection=(id,firstName,lastName,profilePicture(displayImage~:playableStreams)) ----- \ No newline at end of file diff --git a/server_admin/topics/identity-broker/social/microsoft.adoc b/server_admin/topics/identity-broker/social/microsoft.adoc deleted file mode 100644 index 7689e24c4..000000000 --- a/server_admin/topics/identity-broker/social/microsoft.adoc +++ /dev/null @@ -1,20 +0,0 @@ - -[[_microsoft]] - -==== Microsoft - -.Procedure -. Click *Identity Providers* in the menu. -. From the `Add provider` list, select `Microsoft`. -+ -.Add identity provider -image:images/microsoft-add-identity-provider.png[Add Identity Provider] -+ -. Copy the value of *Redirect URI* to your clipboard. -. In a separate browser tab, https://account.live.com/developers/applications/create[create a Microsoft app]. -.. Click *Add URL* to add the redirect URL to the Microsoft app. -.. Note the *Application ID* and *Application Secret*. -. In {project_name}, paste the value of the *Application ID* into the *Client ID* field. -. In {project_name}, paste the value of the *Application Secret* into the *Client Secret* field. -. Click *Add*. - diff --git a/server_admin/topics/identity-broker/social/openshift.adoc b/server_admin/topics/identity-broker/social/openshift.adoc deleted file mode 100644 index b5d31a035..000000000 --- a/server_admin/topics/identity-broker/social/openshift.adoc +++ /dev/null @@ -1,85 +0,0 @@ - -==== OpenShift 3 - -.Procedure -. Click *Identity Providers* in the menu. -. From the `Add provider` list, select `Openshift`. -+ -.Add identity provider -image:images/openshift-add-identity-provider.png[Add Identity Provider] -+ -. Copy the value of *Redirect URI* to your clipboard. -. Register your client using the `oc` command-line tool. -+ -[source,subs="attributes+"] ----- -$ oc create -f <(echo ' -kind: OAuthClient -apiVersion: v1 -metadata: - name: kc-client <1> -secret: "..." <2> -redirectURIs: - - "http://www.example.com/" <3> -grantMethod: prompt <4> -') ----- - -<1> The `name` of your OAuth client. Passed as `client_id` request parameter when making requests to `__/oauth/authorize` and `__/oauth/token`. -<2> The `secret` {project_name} uses for the `client_secret` request parameter. -<3> The `redirect_uri` parameter specified in requests to `__/oauth/authorize` and `__/oauth/token` must be equal to (or prefixed by) one of the URIs in `redirectURIs`. You can obtain this from the *Redirect URI* field in the Identity Provider screen -<4> The `grantMethod` {project_name} uses to determine the action when this client requests tokens but has not been granted access by the user. -+ -. In {project_name}, paste the value of the *Client ID* into the *Client ID* field. -. In {project_name}, paste the value of the *Client Secret* into the *Client Secret* field. - -. Click *Add*. - -==== OpenShift 4 - -.Prerequisites -. Installation of https://stedolan.github.io/jq/[jq]. -. `X509_CA_BUNDLE` configured in the container and set to `/var/run/secrets/kubernetes.io/serviceaccount/ca.crt`. - -.Procedure -. Run the following command on the command line and note the OpenShift 4 API URL output. -+ -[source,subs="attributes+"] ----- -curl -s -k -H "Authorization: Bearer $(oc whoami -t)" \https:///apis/config.openshift.io/v1/infrastructures/cluster | jq ".status.apiServerURL" ----- -+ -. Click *Identity Providers* in the {project_name} menu. -. From the `Add provider` list, select `Openshift`. -+ -.Add identity provider -image:images/openshift-4-add-identity-provider.png[Add Identity Provider] -+ -. Copy the value of *Redirect URI* to your clipboard. -. Register your client using the `oc` command-line tool. -+ -[source, subs="attributes+"] ----- -$ oc create -f <(echo ' -kind: OAuthClient -apiVersion: oauth.openshift.io/v1 -metadata: - name: keycloak-broker <1> -secret: "..." <2> -redirectURIs: - - "" <3> -grantMethod: prompt <4> -') ----- - -<1> The `name` of your OAuth client. Passed as `client_id` request parameter when making requests to `__/oauth/authorize` and `__/oauth/token`. The `name` parameter must be the same in the `OAuthClient` object and the {project_name} configuration. -<2> The `secret` {project_name} uses as the `client_secret` request parameter. -<3> The `redirect_uri` parameter specified in requests to `__/oauth/authorize` and `__/oauth/token` must be equal to (or prefixed by) one of the URIs in `redirectURIs`. The easiest way to configure it correctly is to copy-paste it from {project_name} OpenShift 4 Identity Provider configuration page (`Redirect URI` field). -<4> The `grantMethod` {project_name} uses to determine the action when this client requests tokens but has not been granted access by the user. -+ -. In {project_name}, paste the value of the *Client ID* into the *Client ID* field. -. In {project_name}, paste the value of the *Client Secret* into the *Client Secret* field. - -. Click *Add*. - -See https://docs.okd.io/latest/authentication/configuring-oauth-clients.html#oauth-register-additional-client_configuring-oauth-clients[official OpenShift documentation] for more information. diff --git a/server_admin/topics/identity-broker/social/paypal.adoc b/server_admin/topics/identity-broker/social/paypal.adoc deleted file mode 100644 index 4dbac8bef..000000000 --- a/server_admin/topics/identity-broker/social/paypal.adoc +++ /dev/null @@ -1,22 +0,0 @@ - -==== PayPal - -.Procedure -. Click *Identity Providers* in the menu. -. From the `Add provider` list, select `PayPal`. -+ -.Add identity provider -image:images/paypal-add-identity-provider.png[Add Identity Provider] -+ -. Copy the value of *Redirect URI* to your clipboard. -. In a separate browser tab, open the https://developer.paypal.com/developer/applications[PayPal Developer applications area]. -.. Click *Create App* to create a PayPal app. -.. Note the Client ID and Client Secret. Click the *Show* link to view the secret. -.. Ensure *Connect with PayPal* is checked. -.. Set the value of the *Return URL* field to the value of *Redirect URI* from {project_name}. -. In {project_name}, paste the value of the *Client ID* into the *Client ID* field. -. In {project_name}, paste the value of the *Client Secret* into the *Client Secret* field. - -. Click *Add*. - - diff --git a/server_admin/topics/identity-broker/social/stack-overflow.adoc b/server_admin/topics/identity-broker/social/stack-overflow.adoc deleted file mode 100644 index 81bfbed07..000000000 --- a/server_admin/topics/identity-broker/social/stack-overflow.adoc +++ /dev/null @@ -1,30 +0,0 @@ - -[[_stackoverflow]] - -==== Stack overflow - -.Procedure -. Click *Identity Providers* in the menu. -. From the `Add provider` list, select `Stack Overflow`. -+ -.Add identity provider -image:images/stack-overflow-add-identity-provider.png[Add Identity Provider] -+ -. In a separate browser tab, log into https://stackapps.com/apps/oauth/register[registering your application on Stack Apps]. -+ -.Register application -image:images/stack-overflow-app-register.png[Register Application] -+ -.. Enter your application name into the *Application Name* field. -.. Enter the OAuth domain into the *OAuth Domain* field. -.. Click *Register Your Application*. -+ -.Settings -image:images/stack-overflow-app-settings.png[Settings] -+ -. Note the *Client ID* and *Client Secret*. -. In {project_name}, paste the value of the *Client ID* into the *Client ID* field. -. In {project_name}, paste the value of the *Client Secret* into the *Client Secret* field. -. Click *Add*. - - diff --git a/server_admin/topics/identity-broker/social/twitter.adoc b/server_admin/topics/identity-broker/social/twitter.adoc deleted file mode 100644 index 60dbce63e..000000000 --- a/server_admin/topics/identity-broker/social/twitter.adoc +++ /dev/null @@ -1,26 +0,0 @@ - -[[_twitter]] - -==== Twitter - -.Prerequisites -. A Twitter developer account. - -.Procedure -. Click *Identity Providers* in the menu. -. From the `Add provider` list, select `Twitter`. -+ -.Add identity provider -image:images/twitter-add-identity-provider.png[Add Identity Provider] -+ -. Copy the value of *Redirect URI* to your clipboard. -. In a separate browser tab, create an app in https://developer.twitter.com/apps/[Twitter Application Management]. -.. Enter any value for name and description. -.. The value for *Website* can be any valid URL except `localhost`. -.. Paste the value of the *Redirect URL* into the *Callback URL* field. -.. When you create your Twitter app, note the value of *Consumer Key* and *Consumer Secret* in the *Keys and Access Tokens* section. -. In {project_name}, paste the value of the *Consumer Key* into the *Client ID* field. -. In {project_name}, paste the value of the *Consumer Secret* into the *Client Secret* field. - -. Click *Add*. - diff --git a/server_admin/topics/identity-broker/suggested.adoc b/server_admin/topics/identity-broker/suggested.adoc deleted file mode 100644 index 3c48e308f..000000000 --- a/server_admin/topics/identity-broker/suggested.adoc +++ /dev/null @@ -1,30 +0,0 @@ - -[[_client_suggested_idp]] -=== Client-suggested Identity Provider - -OIDC applications can bypass the {project_name} login page by hinting at the identity provider they want to use. You can enable this by setting the `kc_idp_hint` query parameter in the Authorization Code Flow authorization endpoint. - -With {project_name} OIDC client adapters, you can specify this query parameter when you access a secured resource in the application. - -For example: - -[source,bash,subs=+attributes] ----- -GET /myapplication.com?kc_idp_hint=facebook HTTP/1.1 -Host: localhost:8080 ----- - -In this case, your realm must have an identity provider with a `facebook` alias. If this provider does not exist, the login form is displayed. - -If you are using the `keycloak.js` adapter, you can also achieve the same behavior as follows: - -[source,javascript] ----- -const keycloak = new Keycloak('keycloak.json'); - -keycloak.createLoginUrl({ - idpHint: 'facebook' -}); ----- - -With the `kc_idp_hint` query parameter, the client can override the default identity provider if you configure one for the `Identity Provider Redirector` authenticator. The client can disable the automatic redirecting by setting the `kc_idp_hint` query parameter to an empty value. diff --git a/server_admin/topics/identity-broker/tokens.adoc b/server_admin/topics/identity-broker/tokens.adoc deleted file mode 100644 index aac71ddbe..000000000 --- a/server_admin/topics/identity-broker/tokens.adoc +++ /dev/null @@ -1,17 +0,0 @@ - -=== Retrieving external IDP tokens - -With {project_name}, you can store tokens and responses from the authentication process with the external IDP using the `Store Token` configuration option on the IDP's settings page. - -Application code can retrieve these tokens and responses to import extra user information or to request the external IDP securely. For example, an application can use the Google token to use other Google services and REST APIs. To retrieve a token for a particular identity provider, send a request as follows: - -[source,subs="attributes+"] ----- -GET {kc_realms_path}/{realm}/broker/{provider_alias}/token HTTP/1.1 -Host: localhost:8080 -Authorization: Bearer ----- - -An application must authenticate with {project_name} and receive an access token. This access token must have the `broker` client-level role `read-token` set, so the user must have a role mapping for this role, and the client application must have that role within its scope. In this case, since you are accessing a protected service in {project_name}, send the access token issued by {project_name} during the user authentication. You can assign this role to newly imported users in the broker configuration page by setting the *Stored Tokens Readable* switch to *ON*. - -These external tokens can be re-established by logging in again through the provider or using the client-initiated account linking API. diff --git a/server_admin/topics/login-settings.adoc b/server_admin/topics/login-settings.adoc deleted file mode 100644 index 0f8e0110e..000000000 --- a/server_admin/topics/login-settings.adoc +++ /dev/null @@ -1,4 +0,0 @@ - -= Controlling login options - -{project_name} includes several built-in login page features. diff --git a/server_admin/topics/login-settings/acr-to-loa-mapping.adoc b/server_admin/topics/login-settings/acr-to-loa-mapping.adoc deleted file mode 100644 index 826f93558..000000000 --- a/server_admin/topics/login-settings/acr-to-loa-mapping.adoc +++ /dev/null @@ -1,11 +0,0 @@ -[[_mapping-acr-to-loa-realm]] -== ACR to Level of Authentication (LoA) Mapping - -In the login settings of a realm, you can define which `Authentication Context Class Reference (ACR)` value is mapped to which `Level of Authentication (LoA)`. The ACR can be any value, whereas the LoA must be numeric. -The acr claim can be requested in the `claims` or `acr_values` parameter sent in the OIDC request and it is also included in the access token and ID token. The mapped number is used in the authentication flow conditions. - -Mapping can be also specified at the client level in case that particular client needs to use different values than realm. However, a best practice is to stick to realm mappings. - -image:images/realm-oidc-map-acr-to-loa.png[alt="ACR to LoA mapping"] - -For further details see <<_step-up-flow,Step-up Authentication>> and https://openid.net/specs/openid-connect-core-1_0.html#acrSemantics[the official OIDC specification]. diff --git a/server_admin/topics/login-settings/forgot-password.adoc b/server_admin/topics/login-settings/forgot-password.adoc deleted file mode 100644 index ab7171ca6..000000000 --- a/server_admin/topics/login-settings/forgot-password.adoc +++ /dev/null @@ -1,47 +0,0 @@ - -== Enabling forgot password - -If you enable `Forgot password`, users can reset their login credentials if they forget their passwords or lose their OTP generator. - -.Procedure -. Click *Realm settings* in the menu. -. Click the *Login* tab. -+ -.Login tab -image:images/login-tab.png[Login Tab] -+ -. Toggle *Forgot password* to *ON*. -+ -A `Forgot Password?` link displays in your login pages. -+ -.Forgot password link -image:images/forgot-password-link.png[Forgot Password Link] -+ -. Specify `Host` and `From` in the *Email* tab in order for Keycloak to be able to send the reset email. -+ -. Click this link to bring users where they can enter their username or email address and receive an email with a link to reset their credentials. -+ -.Forgot password page -image:images/forgot-password-page.png[Forgot Password Page] - -The text sent in the email is configurable. See link:{developerguide_link}[{developerguide_name}] for more information. - -When users click the email link, {project_name} asks them to update their password, and if they have set up an OTP generator, {project_name} asks them to reconfigure the OTP generator. Depending on security requirements of your organization, you may not want users to reset their OTP generator through email. - -To change this behavior, perform these steps: - -.Procedure -. Click *Authentication* in the menu. -. Click the *Flows* tab. -. Select the *Reset Credentials* flow. -+ -.Reset credentials flow -image:images/reset-credentials-flow.png[Reset Credentials Flow] -+ -If you do not want to reset the OTP, set the `Reset OTP` requirement to *Disabled*. -. Click *Authentication* in the menu. -. Click the *Required actions* tab. -. Ensure *Update Password* is enabled. -+ -.Required Actions -image:images/reset-credentials-required-actions.png[Required Actions] diff --git a/server_admin/topics/login-settings/remember-me.adoc b/server_admin/topics/login-settings/remember-me.adoc deleted file mode 100644 index ce72ba53e..000000000 --- a/server_admin/topics/login-settings/remember-me.adoc +++ /dev/null @@ -1,18 +0,0 @@ - -== Enabling Remember Me - -A logged-in user closing their browser destroys their session, and that user must log in again. You can set {project_name} to keep the user's login session open if that user clicks the _Remember Me_ checkbox upon login. This action turns the login cookie from a session-only cookie to a persistence cookie. - -.Procedure -. Click *Realm settings* in the menu. -. Click the *Login* tab. -. Toggle the *Remember Me* switch to *On*. -+ -.Login tab -image:images/login-tab-remember-me.png[Login Tab Remember Me] -+ -When you save this setting, a `remember me` checkbox displays on the realm's login page. -+ -.Remember Me -image:images/remember-me.png[Remember Me] - diff --git a/server_admin/topics/login-settings/update-email-workflow.adoc b/server_admin/topics/login-settings/update-email-workflow.adoc deleted file mode 100644 index 2939fa1cb..000000000 --- a/server_admin/topics/login-settings/update-email-workflow.adoc +++ /dev/null @@ -1,30 +0,0 @@ -[[_update-email-workflow]] - -== Update Email Workflow (UpdateEmail) - -With this workflow, users will have to use an UPDATE_EMAIL action to change their own email address. - -The action is associated with a single email input form. If the realm has email verification disabled, this action will allow to update the email without verification. If the realm has email verification enabled, the action will send an email update action token to the new email address without changing the account email. Only the action token triggering will complete the email update. - -Applications are able to send their users to the email update form by leveraging UPDATE_EMAIL as an AIA (Application Initiated Action). - -ifeval::[{project_product}==true] -:tech_feature_name: UpdateEmail -:tech_feature_setting: -Dkeycloak.profile.feature.update_email=enabled -:tech_feature_id: update-email -include::../templates/techpreview.adoc[] -endif::[] - -ifeval::[{project_community}==true] - -[IMPORTANT] -==== -Please note that Update Email Workflow support is in development. Use this feature experimentally. -==== - -endif::[] - -[NOTE] -==== -If you enable this feature and you are migrating from a previous version, enable the *Update Email* required action in your realms. Otherwise, users cannot update their email addresses. -==== diff --git a/server_admin/topics/overview.adoc b/server_admin/topics/overview.adoc deleted file mode 100644 index 4db462697..000000000 --- a/server_admin/topics/overview.adoc +++ /dev/null @@ -1,9 +0,0 @@ -== {project_name} features and concepts - -{project_name} is a single sign on solution for web apps and RESTful web services. The goal of {project_name} -is to make security simple so that it is easy for application developers to secure the apps and services they have deployed -in their organization. Security features that developers normally have to write for themselves are provided out of the box -and are easily tailorable to the individual requirements of your organization. {project_name} provides customizable -user interfaces for login, registration, administration, and account management. You can also use {project_name} as an -integration platform to hook it into existing LDAP and Active Directory servers. You can also delegate authentication to third -party identity providers like Facebook and Google. diff --git a/server_admin/topics/overview/concepts.adoc b/server_admin/topics/overview/concepts.adoc deleted file mode 100644 index b7e1c11b0..000000000 --- a/server_admin/topics/overview/concepts.adoc +++ /dev/null @@ -1,91 +0,0 @@ - -=== Core concepts and terms - -Consider these core concepts and terms before attempting to use {project_name} to secure your web applications and REST services. - -users:: - Users are entities that are able to log into your system. They can have attributes associated with themselves like email, - username, address, phone number, and birthday. They can be assigned group membership and have specific roles assigned to them. -authentication:: - The process of identifying and validating a user. -authorization:: - The process of granting access to a user. -credentials:: - Credentials are pieces of data that {project_name} uses to verify the identity of a user. Some examples are passwords, - one-time-passwords, digital certificates, or even fingerprints. -roles:: - Roles identify a type or category of user. `Admin`, `user`, `manager`, and `employee` are all typical roles that may exist - in an organization. Applications often assign access and permissions to specific roles rather than individual users as dealing - with users can be too fine-grained and hard to manage. -user role mapping:: - A user role mapping defines a mapping between a role and a user. A user can be associated with zero or more roles. This - role mapping information can be encapsulated into tokens and assertions so that applications can decide access permissions on - various resources they manage. -composite roles:: - A composite role is a role that can be associated with other roles. For example a `superuser` composite role could be associated with the - `sales-admin` and `order-entry-admin` roles. If a user is mapped to the `superuser` role they also inherit the `sales-admin` and `order-entry-admin` roles. -groups:: - Groups manage groups of users. Attributes can be defined for a group. You can map roles to a group as well. Users that become members of a group - inherit the attributes and role mappings that group defines. -realms:: - A realm manages a set of users, credentials, roles, and groups. A user belongs to and logs into a realm. Realms are isolated from one another - and can only manage and authenticate the users that they control. -clients:: - Clients are entities that can request {project_name} to authenticate a user. Most often, clients are applications and services that - want to use {project_name} to secure themselves and provide a single sign-on solution. Clients can also be entities that just want to request - identity information or an access token so that they can securely invoke other services on the network that are secured by {project_name}. -client adapters:: - Client adapters are plugins that you install into your application environment to be able to communicate and be secured by {project_name}. {project_name} - has a number of adapters for different platforms that you can download. There are also third-party adapters you can get for environments that we don't cover. -consent:: - Consent is when you as an admin want a user to give permission to a client before that client can participate in the authentication process. - After a user provides their credentials, {project_name} will pop up a screen identifying the client requesting a login and what identity - information is requested of the user. User can decide whether or not to grant the request. -client scopes:: - When a client is registered, you must define protocol mappers and role scope mappings for that client. It is often useful to store - a client scope, to make creating new clients easier by sharing some common settings. This is also useful for requesting some - claims or roles to be conditionally based on the value of `scope` parameter. {project_name} provides the concept of a client scope for this. -client role:: - Clients can define roles that are specific to them. This is basically a role namespace dedicated to the client. -identity token:: - A token that provides identity information about the user. Part of the OpenID Connect specification. -access token:: - A token that can be provided as part of an HTTP request that grants access to the service being invoked on. This is part of - the OpenID Connect and OAuth 2.0 specification. -assertion:: - Information about a user. This usually pertains to an XML blob that is included in a SAML authentication response that - provided identity metadata about an authenticated user. -service account:: - Each client has a built-in service account which allows it to obtain an access token. -direct grant:: - A way for a client to obtain an access token on behalf of a user via a REST invocation. -protocol mappers:: - For each client you can tailor what claims and assertions are stored in the OIDC token or SAML assertion. You do this per client by creating and configuring - protocol mappers. -session:: - When a user logs in, a session is created to manage the login session. A session contains information like when the user logged in and what - applications have participated within single-sign on during that session. Both admins and users can view session information. -user federation provider:: - {project_name} can store and manage users. Often, companies already have LDAP or Active Directory services that store user and credential - information. You can point {project_name} to validate credentials from those external stores and pull in identity information. -identity provider:: - An identity provider (IDP) is a service that can authenticate a user. {project_name} is an IDP. -identity provider federation:: - {project_name} can be configured to delegate authentication to one or more IDPs. Social login via - Facebook or Google+ is an example of identity provider federation. You can also hook {project_name} to delegate - authentication to any other OpenID Connect or SAML 2.0 IDP. -identity provider mappers:: - When doing IDP federation you can map incoming tokens and assertions to user and session attributes. This helps you propagate identity information from the external IDP - to your client requesting authentication. -required actions:: - Required actions are actions a user must perform during the authentication process. A user will not be able to complete the authentication process until these actions - are complete. For example, an admin may schedule users to reset their passwords every month. An `update password` required action would be set for all these - users. -authentication flows:: - Authentication flows are work flows a user must perform when interacting with certain aspects of the system. A login flow can define - what credential types are required. A registration flow defines what profile information a user must enter and whether something like reCAPTCHA - must be used to filter out bots. Credential reset flow defines what actions a user must do before they can reset their password. -events:: - Events are audit streams that admins can view and hook into. -themes:: - Every screen provided by {project_name} is backed by a theme. Themes define HTML templates and stylesheets which you can override as needed. diff --git a/server_admin/topics/overview/features.adoc b/server_admin/topics/overview/features.adoc deleted file mode 100644 index f9304b7a0..000000000 --- a/server_admin/topics/overview/features.adoc +++ /dev/null @@ -1,31 +0,0 @@ - -=== Features - -{project_name} provides the following features: - -* Single-Sign On and Single-Sign Out for browser applications. -* OpenID Connect support. -* OAuth 2.0 support. -* SAML support. -* Identity Brokering - Authenticate with external OpenID Connect or SAML Identity Providers. -* Social Login - Enable login with Google, GitHub, Facebook, Twitter, and other social networks. -* User Federation - Sync users from LDAP and Active Directory servers. -* Kerberos bridge - Automatically authenticate users that are logged-in to a Kerberos server. -* Admin Console for central management of users, roles, role mappings, clients and configuration. -* Account Management console that allows users to centrally manage their account. -* Theme support - Customize all user facing pages to integrate with your applications and branding. -* Two-factor Authentication - Support for TOTP/HOTP via Google Authenticator or FreeOTP. -* Login flows - optional user self-registration, recover password, verify email, require password update, etc. -* Session management - Admins and users themselves can view and manage user sessions. -* Token mappers - Map user attributes, roles, etc. how you want into tokens and statements. -* Not-before revocation policies per realm, application and user. -* CORS support - Client adapters have built-in support for CORS. -ifeval::[{project_community}==true] -* Service Provider Interfaces (SPI) - A number of SPIs to enable customizing various aspects of the server. Authentication flows, user federation providers, -protocol mappers and many more. -* Client adapters for JavaScript applications, WildFly, JBoss EAP, Tomcat, Jetty, Spring, etc. -endif::[] -ifeval::[{project_product}==true] -* Client adapters for JavaScript applications, JBoss EAP, etc. -endif::[] -* Supports any platform/language that has an OpenID Connect Relying Party library or SAML 2.0 Service Provider library. diff --git a/server_admin/topics/overview/how.adoc b/server_admin/topics/overview/how.adoc deleted file mode 100644 index 29bd5870f..000000000 --- a/server_admin/topics/overview/how.adoc +++ /dev/null @@ -1,12 +0,0 @@ - -=== Basic {project_name} operations - -{project_name} is a separate server that you manage on your network. Applications are configured to point to and -be secured by this server. {project_name} uses open protocol standards like link:https://openid.net/connect/[OpenID Connect] -or link:http://saml.xml.org/saml-specifications[SAML 2.0] to secure -your applications. Browser applications redirect a user's browser from the application to the {project_name} authentication -server where they enter their credentials. This redirection is important because users are completely isolated from applications and -applications never see a user's credentials. Applications instead are given an identity token or assertion that is cryptographically -signed. These tokens can have identity information like username, address, email, and other profile data. They can also -hold permission data so that applications can make authorization decisions. These tokens can also be used to make secure -invocations on REST-based services. diff --git a/server_admin/topics/realms.adoc b/server_admin/topics/realms.adoc deleted file mode 100644 index 3f6c68947..000000000 --- a/server_admin/topics/realms.adoc +++ /dev/null @@ -1,9 +0,0 @@ - -== Configuring realms - -A realm manages a set of users, credentials, roles, and groups. A user belongs to and logs into a realm. Realms are isolated from one another -and can only manage and authenticate the users that they control. One {project_name} deployment can define, store, and manage as many realms -as there is space for in the database. When deciding whether to have one or more realms think about what kind of isolation you want to have for -your users and applications. For example, you might define a realm for the employees of your company and have a separate realm for your customers. -Your employees would log into the employee realm and only be able to visit internal company applications. Customers would log into the customer -realm and only be able to interact with customer-facing apps. In this section you'll learn some basics about realm creation and configuration. \ No newline at end of file diff --git a/server_admin/topics/realms/cache.adoc b/server_admin/topics/realms/cache.adoc deleted file mode 100644 index 0b37cb326..000000000 --- a/server_admin/topics/realms/cache.adoc +++ /dev/null @@ -1,16 +0,0 @@ -[[_clear-cache]] -= Clearing server caches - -{project_name} caches everything it can in memory within the limits of your JVM and the limits you have configured. If the {project_name} database is modified by a third party, such as a DBA, outside the scope of the server's REST APIs or Admin Console, parts of the in-memory cache could be stale. You can clear the realm cache, user cache or cache of external public keys, such as Public keys of - external clients or Identity providers, which {project_name} may use to verify signatures of particular external entity. - -.Procedure - -. Click *Realm Settings* in the menu. - -. Click the *Cache* tab. - -. Click *Clear* for the cache you want to evict. -+ -.Cache tab -image:images/cache-tab.png[Cache tab] diff --git a/server_admin/topics/realms/email.adoc b/server_admin/topics/realms/email.adoc deleted file mode 100644 index aa94bac71..000000000 --- a/server_admin/topics/realms/email.adoc +++ /dev/null @@ -1,44 +0,0 @@ -[[_email]] - -= Configuring email for a realm - -{project_name} sends emails to users to verify their email addresses, when they forget their passwords, or when an administrator needs to receive notifications about a server event. To enable {project_name} to send emails, you provide {project_name} with your SMTP server settings. - -.Procedure - -. Click *Realm settings* in the menu. -. Click the *Email* tab. -+ -.Email tab -image:images/email-tab.png[Email Tab] - -. Fill in the fields and toggle the switches as needed. - -.Template -From:: - *From* denotes the address used for the *From* SMTP-Header for the emails sent. - -From display name:: - *From display name* allows to configure a user-friendly email address aliases (optional). If not set the plain *From* email address will be displayed in email clients. - -Reply to:: - *Reply to* denotes the address used for the *Reply-To* SMTP-Header for the mails sent (optional). If not set the plain *From* email address will be used. - -Reply to display name:: - *Reply to display name* allows to configure a user-friendly email address aliases (optional). If not set the plain *Reply To* email address will be displayed. - -Envelope from:: - *Envelope from* denotes the https://en.wikipedia.org/wiki/Bounce_address[Bounce Address] used for the *Return-Path* SMTP-Header for the mails sent (optional). - -.Connection & Authentication -Host:: - *Host* denotes the SMTP server hostname used for sending emails. - -Port:: - *Port* denotes the SMTP server port. - -Encryption:: - Tick one of these checkboxes to support sending emails for recovering usernames and passwords, especially if the SMTP server is on an external network. You will most likely need to change the *Port* to 465, the default port for SSL/TLS. - -Authentication:: - Set this switch to *ON* if your SMTP server requires authentication. When prompted, supply the *Username* and *Password*. The value of the *Password* field can refer a value from an external <<_vault-administration,vault>>. diff --git a/server_admin/topics/realms/keys.adoc b/server_admin/topics/realms/keys.adoc deleted file mode 100644 index af2b0f151..000000000 --- a/server_admin/topics/realms/keys.adoc +++ /dev/null @@ -1,137 +0,0 @@ -[[realm_keys]] -=== Configuring realm keys - -The authentication protocols that are used by {project_name} require cryptographic signatures and sometimes -encryption. {project_name} uses asymmetric key pairs, a private and public key, to accomplish this. - -{project_name} has a single active keypair at a time, but can have several passive keys as well. The active keypair -is used to create new signatures, while the passive keypair can be used to verify previous signatures. This makes it -possible to regularly rotate the keys without any downtime or interruption to users. - -When a realm is created a key pair and a self-signed certificate is automatically generated. - -.Procedure -. Click *Realm settings* in the menu. -. Click *Keys*. -. Select *Passive keys* from the filter dropdown to view passive keys. -. Select *Disabled keys* from the filter dropdown to view disabled keys. - -A keypair can have the status `Active`, but still not be selected as the currently active keypair for the realm. -The selected active pair which is used for signatures is selected based on the first key provider sorted by priority -that is able to provide an active keypair. - -==== Rotating keys - -We recommend that you regularly rotate keys. To do so, start by creating new keys with a higher priority than -the existing active keys. Or create new keys with the same priority and making the previous keys passive. - -Once new keys are available all new tokens and cookies will be signed with the new keys. When a user authenticates to an -application the SSO cookie is updated with the new signature. When OpenID Connect tokens are refreshed new tokens are -signed with the new keys. This means that over time all cookies and tokens will use the new keys and after a while the -old keys can be removed. - -The frequency of deleting old keys is a tradeoff between security and making sure all cookies and tokens are updated. Consider creating new keys every three to six months and deleting old keys one to two months after you create the new keys. If a user was inactive in the period between the new keys being added and the old keys being removed, that user will have to re-authenticate. - -Rotating keys also applies to offline tokens. To make sure they are updated, the applications need to refresh the tokens before the old keys are removed. - -==== Adding a generated keypair - -.Procedure -. Select the realm in the Admin Console. -. Click *Realm settings* in the menu. -. Click the *Keys* tab. -. Click the *Providers* tab. -. Click *Add provider* and select *rsa-generated*. -. Enter a number in the *Priority* field. This number determines if the new key pair becomes the active key pair. -. Select a value for *AES Key size*. -. Click *Save*. - -This action will generated a new keypair including a self-signed certificate. - -Changing the priority for a provider will not cause the keys to be re-generated, but if you want to change the keysize -you can edit the provider and new keys will be generated. - -==== Adding an existing keypair and certificate - -To add a keypair and certificate obtained elsewhere select `Providers` and choose `rsa` from the dropdown. You can change -the priority to make sure the new keypair becomes the active keypair. - -.Prerequisites -* A private key file. The file must be PEM formatted. - -.Procedure -. Select the realm in the Admin Console. -. Click *Realm settings*. -. Click the *Keys* tab. -. Click the *Providers* tab. -. Click *Add provider* and select *rsa*. -. Enter a number in the *Priority* field. This number determines if the new key pair becomes the active key pair. -. Click *Browse...* beside *Private RSA Key* to upload the private key file. -. If you have a signed certificate for your private key, click *Browse...* beside *X509 Certificate* to upload the certificate file. {project_name} automatically generates a self-signed certificate if you do not upload a certificate. -. Click *Save*. - -==== Loading keys from a Java Keystore - -To add a keypair and certificate stored in a Java Keystore file on the host select `Providers` and choose `java-keystore` -from the dropdown. You can change the priority to make sure the new keypair becomes the active keypair. - -For the associated certificate chain to be loaded it must be imported to the Java Keystore file with the same `Key Alias` used to load the keypair. - -.Procedure -. Select the realm in the Admin Console. -. Click *Realm settings* in the menu. -. Click the *Keys* tab. -. Click the *Providers* tab. -. Click *Add provider* and select *java-keystore*. -. Enter a number in the *Priority* field. This number determines if the new key pair becomes the active key pair. -. Enter a value for *Keystore*. -. Enter a value for *Keystore Password*. -. Enter a value for *Key Alias*. -. Enter a value for *Key Password*. -. Click *Save*. - -==== Making keys passive - -.Procedure -. Select the realm in the Admin Console. -. Click *Realm settings* in the menu. -. Click the *Keys* tab. -. Click the *Providers* tab. -. Click the provider of the key you want to make passive. -. Toggle *Active* to *Off*. -. Click *Save*. - -==== Disabling keys - -.Procedure -. Select the realm in the Admin Console. -. Click *Realm settings* in the menu. -. Click the *Keys* tab. -. Click the *Providers* tab. -. Click the provider of the key you want to make passive. -. Toggle *Enabled* to *Off*. -. Click *Save*. - -==== Compromised keys - -{project_name} has the signing keys stored just locally and they are never shared with the client applications, users or other -entities. However, if you think that your realm signing key was compromised, you should first generate new keypair as described above and -then immediately remove the compromised keypair. - -Alternatively, you can delete the provider from the `Providers` table. - -.Procedure -. Click *Clients* in the menu. -. Click *security-admin-console*. -. Scroll down to the *Capability config* section. -. Fill in the *Admin URL* field. -. Click the *Advanced* tab. -. Click *Set to now* in the *Revocation* section. -. Click *Push*. - -Pushing the not-before policy ensures that client applications do not accept the existing tokens signed by the compromised key. The client application is forced to download new key pairs from {project_name} also so the tokens signed by the compromised key will be invalid. - -[NOTE] -==== -REST and confidential clients must set *Admin URL* so {project_name} can send clients the pushed not-before policy request. -==== diff --git a/server_admin/topics/realms/master.adoc b/server_admin/topics/realms/master.adoc deleted file mode 100644 index 04ecc756f..000000000 --- a/server_admin/topics/realms/master.adoc +++ /dev/null @@ -1,18 +0,0 @@ - -= The master realm -In the Admin Console, two types of realms exist: - -* `Master realm` - This realm was created for you when you first started {project_name}. It contains the administrator account you created at the first login. Use the _master_ realm only to create and manage the realms in your system. - -* `Other realms` - These realms are created by the administrator in the master realm. In these realms, administrators manage the users in your organization and the applications they need. The applications are owned by the users. - -.Realms and applications -image:images/master_realm.png[Realms and applications] - -Realms are isolated from one another and can only manage and authenticate the users that they control. Following this security model helps prevent accidental changes and follows the tradition -of permitting user accounts access to only those privileges and powers necessary -for the successful completion of their current task. - -.Additional resources - -* See <<_per_realm_admin_permissions, Dedicated Realm Admin Consoles>> if you want to disable the _master_ realm and define administrator accounts within any new realm you create. Each realm has its own dedicated Admin Console that you can log into with local accounts. diff --git a/server_admin/topics/realms/proc-configuring-internationalization.adoc b/server_admin/topics/realms/proc-configuring-internationalization.adoc deleted file mode 100644 index 55e218882..000000000 --- a/server_admin/topics/realms/proc-configuring-internationalization.adoc +++ /dev/null @@ -1,47 +0,0 @@ -= Enabling internationalization - -Every UI screen is internationalized in {project_name}. The default language is English, but you can choose which locales you want to support and what the default locale -will be. - -.Procedure - -. Click *Realm Settings* in the menu. - -. Click the *Localization* tab. - -. Enable *Internationalization*. - -. Select the languages you will support. -+ -.Localization tab -image:images/localization.png[Localization tab] -+ -The next time a user logs in, that user can choose a language on the login page to use for the login screens, Account Console, and Admin Console. - -.Additional resources - -* The link:{developerguide_link}[{developerguide_name}] explains -how you can offer additional languages. All internationalized texts which are provided by the theme can be overwritten by realm-specific texts on the *Localization* tab. - -[[_user_locale_selection]] -== User locale selection - -A locale selector provider suggests the best locale on the information available. However, it is often unknown who the user is. For this reason, the previously authenticated user's locale is remembered in a persisted cookie. - -The logic for selecting the locale uses the first of the following that is available: - -* User selected - when the user has selected a locale using the drop-down locale selector -* User profile - when there is an authenticated user and the user has a preferred locale set -* Client selected - passed by the client using for example ui_locales parameter -* Cookie - last locale selected on the browser -* Accepted language - locale from *Accept-Language* header -* Realm default -* If none of the above, fall back to English - -When a user is authenticated an action is triggered to update the locale in the persisted cookie mentioned earlier. If the -user has actively switched the locale through the locale selector on the login pages the users locale is also updated at -this point. - -If you want to change the logic for selecting the locale, you have an option to create custom `LocaleSelectorProvider`. For details, please refer to the -link:{developerguide_link}#_locale_selector[{developerguide_name}]. - diff --git a/server_admin/topics/realms/proc-creating-a-realm.adoc b/server_admin/topics/realms/proc-creating-a-realm.adoc deleted file mode 100644 index cf66e7cbb..000000000 --- a/server_admin/topics/realms/proc-creating-a-realm.adoc +++ /dev/null @@ -1,28 +0,0 @@ - -[id=proc-creating-a-realm_{context}] -= Creating a realm - -[role="_abstract"] -You create a realm to provide a management space where you can create users and give them permissions to use applications. At first login, you are typically in the _master_ realm, the top-level realm from which you create other realms. - -When deciding what realms you need, consider the kind of isolation you want to have for your users and applications. For example, you might create a realm for the employees of your company and a separate realm for your customers. -Your employees would log into the employee realm and only be able to visit internal company applications. Customers would log into the customer -realm and only be able to interact with customer-facing apps. - -.Procedure - -. Point to the top of the left pane. - -. Click *Create Realm*. -+ -.Add realm menu -image:images/add-realm-menu.png[Add realm menu] - -. Enter a name for the realm. - -. Click *Create*. -+ -.Create realm -image:images/create-realm.png[Create realm] -+ -The current realm is now set to the realm you just created. You can switch between realms by clicking the realm name in the menu. diff --git a/server_admin/topics/realms/proc-using-admin-console.adoc b/server_admin/topics/realms/proc-using-admin-console.adoc deleted file mode 100644 index b22a7ca95..000000000 --- a/server_admin/topics/realms/proc-using-admin-console.adoc +++ /dev/null @@ -1,33 +0,0 @@ -== Using the Admin Console - -You configure realms and perform most administrative tasks in the {project_name} Admin Console. - -.Prerequisites - -* You need an administrator account. See xref:creating-first-admin_{context}[Creating the first administrator]. - -.Procedure - -. Go to the URL for the Admin Console. -+ -For example, for localhost, use this URL: http://localhost:8080{kc_admins_path}/ -+ -.Login page -image:images/login-page.png[Login page] - -. Enter the username and password you created on the Welcome Page or the `add-user-keycloak` script in the bin directory. -This action displays the Admin Console. -+ -.Admin Console -image:images/admin-console.png[Admin Console] - -. Note the menus and other options that you can use: -+ -* Click the menu labeled *Master* to pick a realm you want to manage or to create a new one. -+ -* Click the top right list to view your account or log out. -+ -* Hover over a question mark *?* icon to show a tooltip text that describes that field. The image above shows the tooltip in action. -* Click a question mark *?* icon to show a tooltip text that describes that field. The image above shows the tooltip in action. - -NOTE: Export files from the Admin Console are not suitable for backups or data transfer between servers. Only boot-time exports are suitable for backups or data transfer between servers. \ No newline at end of file diff --git a/server_admin/topics/realms/ssl.adoc b/server_admin/topics/realms/ssl.adoc deleted file mode 100644 index 3ee8f95d7..000000000 --- a/server_admin/topics/realms/ssl.adoc +++ /dev/null @@ -1,27 +0,0 @@ -[[_ssl_modes]] - -= Configuring SSL for a realm - -Each realm has an associated SSL Mode, which defines the SSL/HTTPS requirements for interacting with the realm. -Browsers and applications that interact with the realm honor the SSL/HTTPS requirements defined by the SSL Mode or they cannot interact with the server. - - -.Procedure - -. Click *Realm settings* in the menu. -. Click the *General* tab. -+ -.General tab -image:images/general-tab.png[General Tab] - -. Set *Require SSL* to one of the following SSL modes: - -* *External requests* - Users can interact with {project_name} without SSL so long as they stick to private IP addresses such as `localhost`, `127.0.0.1`, `10.x.x.x`, `192.168.x.x`, and `172.16.x.x`. - If you try to access {project_name} without SSL from a non-private IP address, you will get an error. - -* *None* - {project_name} does not require SSL. This choice applies only in development when you are experimenting and do not plan to support this deployment. - -* *All requests* - {project_name} requires SSL for all IP addresses. \ No newline at end of file diff --git a/server_admin/topics/realms/themes.adoc b/server_admin/topics/realms/themes.adoc deleted file mode 100644 index 40b20aa61..000000000 --- a/server_admin/topics/realms/themes.adoc +++ /dev/null @@ -1,29 +0,0 @@ -[[_themes]] -= Configuring themes - -For a given realm, you can change the appearance of any UI in {project_name} by using themes. - -.Procedure - -. Click *Realm setting* in the menu. -. Click the *Themes* tab. -+ -.Themes tab -image:images/themes-tab.png[Themes tab] - -. Pick the theme you want for each UI category and click *Save*. -+ -Login theme:: - Username password entry, OTP entry, new user registration, and other similar screens related to login. - -Account theme:: - Each user has a User Account Management UI. - -Admin console theme:: - The skin of the {project_name} Admin Console. - -Email theme:: - Whenever {project_name} has to send out an email, it uses templates defined in this theme to craft the email. - -.Additional resources -* The link:{developerguide_link}[{developerguide_name}] describes how to create a new theme or modify existing ones. diff --git a/server_admin/topics/roles-groups/con-client-roles.adoc b/server_admin/topics/roles-groups/con-client-roles.adoc deleted file mode 100644 index 06997340c..000000000 --- a/server_admin/topics/roles-groups/con-client-roles.adoc +++ /dev/null @@ -1,5 +0,0 @@ -[id="con-client-roles_{context}"] - -= Client roles -[role="_abstract"] -Client roles are namespaces dedicated to clients. Each client gets its own namespace. Client roles are managed under the *Roles* tab for each client. You interact with this UI the same way you do for realm-level roles. diff --git a/server_admin/topics/roles-groups/con-comparing-groups-roles.adoc b/server_admin/topics/roles-groups/con-comparing-groups-roles.adoc deleted file mode 100644 index 7833f0065..000000000 --- a/server_admin/topics/roles-groups/con-comparing-groups-roles.adoc +++ /dev/null @@ -1,9 +0,0 @@ -[id="con-comparing-groups-roles_{context}"] - -= Groups compared to roles -[role="_abstract"] -Groups and roles have some similarities and differences. In {project_name}, groups are a collection of users to which you apply roles and attributes. Roles define types of users and applications assign permissions and access control to roles. - -<<_composite-roles,Composite Roles>> are similar to Groups as they provide the same functionality. The difference between them is conceptual. Composite roles apply the permission model to a set of services and applications. Use composite roles to manage applications and services. - -Groups focus on collections of users and their roles in an organization. Use groups to manage users. diff --git a/server_admin/topics/roles-groups/con-default-roles.adoc b/server_admin/topics/roles-groups/con-default-roles.adoc deleted file mode 100644 index ea2cbc038..000000000 --- a/server_admin/topics/roles-groups/con-default-roles.adoc +++ /dev/null @@ -1,13 +0,0 @@ -[id="con-default-roles_{context}"] - -[[_default_roles]] -==== Default roles -[role="_abstract"] -Default roles allow you to automatically assign user role mappings when any user is newly created or imported through -<<_identity_broker, Identity Brokering>>. -To specify default roles go to the *Roles* left menu item, and click the *Default Roles* tab. - -.Default roles -image:images/default-roles.png[] - -This screenshot shows that some _default roles_ already exist. diff --git a/server_admin/topics/roles-groups/con-role-scope-mappings.adoc b/server_admin/topics/roles-groups/con-role-scope-mappings.adoc deleted file mode 100644 index 85a38e257..000000000 --- a/server_admin/topics/roles-groups/con-role-scope-mappings.adoc +++ /dev/null @@ -1,28 +0,0 @@ -[id="con-role-scope-mappings_{context}"] - -[[_role_scope_mappings]] - -= Role scope mappings -[role="_abstract"] -On creation of an OIDC access token or SAML assertion, the user role mappings become claims within the token or assertion. Applications use these claims to make access decisions on the resources controlled by the application. {project_name} digitally signs access tokens and applications re-use them to invoke remotely secured REST services. However, these tokens have an associated risk. An attacker can obtain these tokens and use their permissions to compromise your networks. To prevent this situation, use _Role Scope Mappings_. - -_Role Scope Mappings_ limit the roles declared inside an access token. When a client requests a user authentication, the access token they receive contains only the role mappings that are explicitly specified for the client's scope. The result is that you limit the permissions of each individual access token instead of giving the client access to all the users permissions. - -By default, each client gets all the role mappings of the user. -You can view the role mappings for a client. - -.Procedure -. Click *Clients* in the menu. -. Click the client to go to the details. -. Click the *Client scopes* tab. -. Click the link in the row with _Dedicated scope and mappers for this client_ -. Click the *Scope* tab. - -.Full scope -image:images/full-client-scope.png[Full scope] - -By default, the effective roles of scopes are every declared role in the realm. To change this default behavior, toggle *Full Scope Allowed* to *OFF* and declare the specific roles you want in each client. -You can also use <<_client_scopes, client scopes>> to define the same role scope mappings for a set of clients. - -.Partial scope -image:images/client-scope.png[Partial scope] diff --git a/server_admin/topics/roles-groups/proc-assigning-role-mappings.adoc b/server_admin/topics/roles-groups/proc-assigning-role-mappings.adoc deleted file mode 100644 index 9e17aea77..000000000 --- a/server_admin/topics/roles-groups/proc-assigning-role-mappings.adoc +++ /dev/null @@ -1,23 +0,0 @@ -[id="proc-assigning-role-mappings_{context}"] - -= Assigning role mappings -[role="_abstract"] -You can assign role mappings to a user through the *Role Mappings* tab for that user. - -.Procedure -. Click *Users* in the menu. -. Click the user that you want to perform a role mapping on. -. Click the *Role mappings* tab. -. Click *Assign role*. -. Select the role you want to assign to the user from the dialog. -. Click *Assign*. - -.Role mappings -image:images/user-role-mappings.png[Role mappings] - -In the preceding example, we are assigning the composite role *developer* to a user. That role was created in the <<_composite-roles, Composite Roles>> topic. - -.Effective role mappings -image:images/effective-role-mappings.png[Effective role mappings] - -When the *developer* role is assigned, the *employee* role associated with the *developer* composite is displayed with *Inherited* "True". *Inherited* roles are the roles explicitly assigned to users and roles that are inherited from composites. diff --git a/server_admin/topics/roles-groups/proc-converting-composite-roles.adoc b/server_admin/topics/roles-groups/proc-converting-composite-roles.adoc deleted file mode 100644 index 013a176b8..000000000 --- a/server_admin/topics/roles-groups/proc-converting-composite-roles.adoc +++ /dev/null @@ -1,25 +0,0 @@ -[id="proc-converting-composite-roles_{context}"] - -[[_composite-roles]] - -= Converting a role to a composite role -[role="_abstract"] -Any realm or client level role can become a _composite role_. A _composite role_ is a role that has one or more additional roles associated with it. When a composite role is mapped to a user, the user gains the roles associated with the composite role. This inheritance is recursive so users also inherit any composite of composites. However, we recommend that composite roles are not overused. - -.Procedure - -. Click *Realm Roles* in the menu. -. Click the role that you want to convert. -. From the *Action* list, select *Add associated roles*. - -.Composite role -image:images/composite-role.png[Composite role] - -The role selection UI is displayed on the page and you can associate realm level and client level roles to the composite role you are creating. - -In this example, the *employee* realm-level role is associated with the *developer* composite role. Any user with the *developer* role also inherits the *employee* role. - -[NOTE] -==== -When creating tokens and SAML assertions, any composite also has its associated roles added to the claims and assertions of the authentication response sent back to the client. -==== diff --git a/server_admin/topics/roles-groups/proc-creating-realm-roles.adoc b/server_admin/topics/roles-groups/proc-creating-realm-roles.adoc deleted file mode 100644 index 2834a017a..000000000 --- a/server_admin/topics/roles-groups/proc-creating-realm-roles.adoc +++ /dev/null @@ -1,18 +0,0 @@ -[id="proc-creating-realm-roles_{context}"] - -= Creating a realm role -[role="_abstract"] -Realm-level roles are a namespace for defining your roles. To see the list of roles, click *Realm Roles* in the menu. - -image:images/roles.png[] - -.Procedure -. Click *Create Role*. -. Enter a *Role Name*. -. Enter a *Description*. -. Click *Save*. - -.Add role -image:images/role.png[Add role] - -The *description* field can be localized by specifying a substitution variable with `$\{var-name}` strings. The localized value is configured to your theme within the themes property files. See the link:{developerguide_link}[{developerguide_name}] for more details. diff --git a/server_admin/topics/roles-groups/proc-managing-groups.adoc b/server_admin/topics/roles-groups/proc-managing-groups.adoc deleted file mode 100644 index bc4661391..000000000 --- a/server_admin/topics/roles-groups/proc-managing-groups.adoc +++ /dev/null @@ -1,55 +0,0 @@ -[id="proc-managing-groups_{context}"] -= Groups -[role="_abstract"] -Groups in {project_name} manage a common set of attributes and role mappings for each user. Users can be members of any number of groups and inherit the attributes and role mappings assigned to each group. - -To manage groups, click *Groups* in the menu. - -.Groups -image:images/groups.png[] - -Groups are hierarchical. A group can have multiple subgroups but a group can have only one parent. Subgroups inherit the attributes and role mappings from their parent. Users inherit the attributes and role mappings from their parent as well. - -If you have a parent group and a child group, and a user that belongs only to the child group, the user in the child group inherits the attributes and role mappings of both the parent group and the child group. - -The following example includes a top-level *Sales* group and a child *North America* subgroup. - -To add a group: - -. Click the group. -. Click *Create group*. -. Enter a group name. -. Click *Create*. -. Click the group name. -+ -The group management page is displayed. -+ -.Group -image:images/group.png[] - -Attributes and role mappings you define are inherited by the groups and users that are members of the group. - -To add a user to a group: - -. Click *Users* in the menu. -. Click the user that you want to perform a role mapping on. If the user is not displayed, click *View all users*. -. Click *Groups*. -+ -.User groups -image:images/user-groups.png[] -+ -. Click *Join Group*. -. Select a group from the dialog. -. Select a group from the *Available Groups* tree. -. Click *Join*. - -To remove a group from a user: - -. Click *Users* in the menu. -. Click the user to be removed from the group. -. Click *Leave* on the group table row. - -In this example, the user _jimlincoln_ is in the _North America_ group. You can see _jimlincoln_ displayed under the *Members* tab for the group. - -.Group membership -image:images/group-membership.png[] diff --git a/server_admin/topics/roles-groups/proc-specifying-default-groups.adoc b/server_admin/topics/roles-groups/proc-specifying-default-groups.adoc deleted file mode 100644 index 01d0a7936..000000000 --- a/server_admin/topics/roles-groups/proc-specifying-default-groups.adoc +++ /dev/null @@ -1,14 +0,0 @@ -[id="proc-specifying-default-groups_{context}"] - -= Using default groups -[role="_abstract"] -To automatically assign group membership to any users who is created or who is imported through <<_identity_broker, Identity Brokering>>, you use default groups. - -. Click *Realm settings* in the menu. -. Click the *User registration* tab. -. Click the *Default Groups* tab. -+ -.Default groups -image:images/default-groups.png[Default groups] - -This screenshot shows that some _default groups_ already exist. diff --git a/server_admin/topics/roles-groups/proc-using-default-roles.adoc b/server_admin/topics/roles-groups/proc-using-default-roles.adoc deleted file mode 100644 index 943c98116..000000000 --- a/server_admin/topics/roles-groups/proc-using-default-roles.adoc +++ /dev/null @@ -1,16 +0,0 @@ -[id="proc-using-default-roles_{context}"] - -[[_default_roles]] -= Using default roles -[role="_abstract"] -Use default roles to automatically assign user role mappings when a user is created or imported through <<_identity_broker, Identity Brokering>>. - -.Procedure - -. Click *Realm settings* in the menu. -. Click the *User registration* tab. -+ -.Default roles -image:images/default-roles.png[Default roles] - -This screenshot shows that some _default roles_ already exist. diff --git a/server_admin/topics/sessions.adoc b/server_admin/topics/sessions.adoc deleted file mode 100644 index dc6c95720..000000000 --- a/server_admin/topics/sessions.adoc +++ /dev/null @@ -1,11 +0,0 @@ - -== Managing user sessions - -When users log into realms, {project_name} maintains a user session for each user and remembers each client visited by the user within the session. Realm administrators can perform multiple actions on each user session: - -* View login statistics for the realm. -* View active users and where they logged in. -* Log a user out of their session. -* Revoke tokens. -* Set up token timeouts. -* Set up session timeouts. diff --git a/server_admin/topics/sessions/administering.adoc b/server_admin/topics/sessions/administering.adoc deleted file mode 100644 index f53580cac..000000000 --- a/server_admin/topics/sessions/administering.adoc +++ /dev/null @@ -1,37 +0,0 @@ - -=== Administering sessions - -To see a top-level view of the active clients and sessions in {project_name}, click *Sessions* from the menu. - -.Sessions -image:images/sessions.png[Sessions tab] - -==== Signing out all active sessions - -You can sign out all users in the realm. From the *Action* list, select *Sign out all active sessions*. All SSO cookies become invalid. {project_name} notifies clients by using the {project_name} OIDC client adapter of the logout event. Clients requesting authentication within active browser sessions must log in again. Client types such as SAML do not receive a back-channel logout request. - -[NOTE] -==== -Clicking *Sign out all active sessions* does not revoke outstanding access tokens. Outstanding tokens must expire naturally. For clients using the {project_name} OIDC client adapter, you can push a <<_revocation-policy, revocation policy>> to revoke the token, but this does not work for other adapters. -==== - -==== Viewing client sessions - -.Procedure -. Click *Clients* in the menu. -. Click the *Sessions* tab. -. Click a client to see that client's sessions. -+ -.Client sessions -image:images/client-sessions.png[Client sessions] - -==== Viewing user sessions - -.Procedure -. Click *Users* in the menu. -. Click the *Sessions* tab. -. Click a user to see that user's sessions. -+ -.User sessions -image:images/user-sessions.png[User sessions] - diff --git a/server_admin/topics/sessions/offline.adoc b/server_admin/topics/sessions/offline.adoc deleted file mode 100644 index 349a5f1c2..000000000 --- a/server_admin/topics/sessions/offline.adoc +++ /dev/null @@ -1,21 +0,0 @@ - -[[_offline-access]] - -=== Offline access -[role="_abstract"] - -During https://openid.net/specs/openid-connect-core-1_0.html#OfflineAccess[offline access] logins, the client application requests an offline token instead of a refresh token. The client application saves this offline token and can use it for future logins if the user logs out. This action is useful if your application needs to perform offline actions on behalf of the user even when the user is not online. For example, a regular data backup. - -The client application is responsible for persisting the offline token in storage and then using it to retrieve new access tokens from the {project_name} server. - -The difference between a refresh token and an offline token is that an offline token never expires and is not subject to the `SSO Session Idle` timeout and `SSO Session Max` lifespan. The offline token is valid after a user logout or server restart. You must use the offline token for a refresh token action at least once per thirty days or for the value of the <<_offline-session-idle, Offline Session Idle>>. - -If you enable <<_offline-session-max-limited, Offline Session Max Limited>>, offline tokens expire after 60 days even if you use the offline token for a refresh token action. You can change this value, <<_offline-session-max, Offline Session Max>>, in the Admin Console. - -If you enable the <<_revoke-refresh-token, Revoke Refresh Token>> option, you can use each offline token once only. After refresh, you must store the new offline token from the refresh response instead of the previous one. - -Users can view and revoke offline tokens that {project_name} grants them in the <<_account-service, User Account Console>>. Administrators can revoke offline tokens for individual users in the Admin Console in the `Consents` tab. Administrators can view all offline tokens issued in the `Offline Access` tab of each client. Administrators can revoke offline tokens by setting a <<_revocation-policy, revocation policy>>. - -To issue an offline token, users must have the role mapping for the realm-level `offline_access` role. Clients must also have that role in their scope. Clients must add an `offline_access` client scope as an `Optional client scope` to the role, which is done by default. - -Clients can request an offline token by adding the parameter `scope=offline_access` when sending their authorization request to {project_name}. The {project_name} OIDC client adapter automatically adds this parameter when you use it to access your application's secured URL (such as, $$http://localhost:8080/customer-portal/secured?scope=offline_access$$). The Direct Access Grant and Service Accounts support offline tokens if you include `scope=offline_access` in the authentication request body. diff --git a/server_admin/topics/sessions/preloading.adoc b/server_admin/topics/sessions/preloading.adoc deleted file mode 100644 index 9deed1a5e..000000000 --- a/server_admin/topics/sessions/preloading.adoc +++ /dev/null @@ -1,18 +0,0 @@ -[[offline-sessions-preloading]] - -=== Offline sessions preloading - -In addition to {jdgserver_name} caches, offline sessions are stored in a database which means they will be available even after server restart. -By default, the offline sessions are not preloaded from the database into the {jdgserver_name} caches during the server startup, because this -approach has a drawback if there are many offline sessions to be preloaded. It can significantly slow down the server startup time. -Therefore, the offline sessions are lazily fetched from the database by default. - -However, {project_name} can be configured to preload the offline sessions from the database into the {jdgserver_name} caches during the server startup. -It can be achieved by setting `preloadOfflineSessionsFromDatabase` property in the `userSessions` SPI to `true`. - -The following example shows how to configure offline sessions preloading. - -[source,bash] ----- -bin/kc.[sh|bat] start --spi-user-sessions-infinispan-preload-offline-sessions-from-database=true ----- diff --git a/server_admin/topics/sessions/revocation.adoc b/server_admin/topics/sessions/revocation.adoc deleted file mode 100644 index ea4f3caaf..000000000 --- a/server_admin/topics/sessions/revocation.adoc +++ /dev/null @@ -1,18 +0,0 @@ - -[[_revocation-policy]] - -=== Revoking active sessions -[role="_abstract"] - -If your system is compromised, you can revoke all active sessions and access tokens. - -.Procedure -. Click *Sessions* in the menu. -. From the *Actions* list, select *Sign out all active sessions*. -+ -.Revocation -image:images/revocation.png[Revocation] - -. Specify a time and date where sessions or tokens issued before that time and date are invalid using this console. -* Click *Set to now* to set the policy to the current time and date. -* Click *Push* to push this revocation policy to any registered OIDC client with the {project_name} OIDC client adapter. diff --git a/server_admin/topics/sessions/timeouts.adoc b/server_admin/topics/sessions/timeouts.adoc deleted file mode 100644 index c1e75a85c..000000000 --- a/server_admin/topics/sessions/timeouts.adoc +++ /dev/null @@ -1,99 +0,0 @@ - -[[_timeouts]] -=== Session and token timeouts -[role="_abstract"] - -{project_name} includes control of the session, cookie, and token timeouts through the *Sessions* and *Tokens* tabs in the *Realm settings* menu. - -.Sessions tab -image:images/sessions-tab.png[Sessions Tab] - -|=== -|Configuration|Description - -|SSO Session Idle -|This setting is for OIDC clients only. If a user is inactive for longer than this timeout, the user session is invalidated. This timeout value resets when clients request authentication or send a refresh token request. {project_name} adds a window of time to the idle timeout before the session invalidation takes effect. See the <<_idle_timeouts_note, note>> later in this section. - -|SSO Session Max -|The maximum time before a user session expires. - -|SSO Session Idle Remember Me -|This setting is similar to the standard SSO Session Idle configuration but specific to logins with *Remember Me* enabled. Users can specify longer session idle timeouts when they click *Remember Me* when logging in. This setting is an optional configuration and, if its value is not greater than zero, it uses the same idle timeout as the SSO Session Idle configuration. - -|SSO Session Max Remember Me -|This setting is similar to the standard SSO Session Max but specific to *Remember Me* logins. Users can specify longer sessions when they click *Remember Me* when logging in. This setting is an optional configuration and, if its value is not greater than zero, it uses the same session lifespan as the SSO Session Max configuration. - -|Client Session Idle -|If the user is inactive for longer than this timeout, refresh token requests bump the idle timeout. This setting specifies a shorter idle timeout of refresh tokens than the session idle timeout, but users can override it for individual clients. This setting is an optional configuration and, when set to zero, uses the same idle timeout in the SSO Session Idle configuration. - -|Client Session Max -|The maximum time before a refresh token expires and invalidates. This setting specifies a shorter timeout of refresh tokens than the session timeout, but users can override it for individual clients. This setting is an optional configuration and, when set to zero, uses the same idle timeout in the SSO Session Max configuration. - -[[_offline-session-idle]] -|Offline Session Idle -|This setting is for <<_offline-access, offline access>>. The amount of time the session remains idle before {project_name} revokes its offline token. {project_name} adds a window of time to the idle timeout before the session invalidation takes effect. See the <<_idle_timeouts_note, note>> later in this section. - -[[_offline-session-max-limited]] -|Offline Session Max Limited -|This setting is for <<_offline-access, offline access>>. If this flag is *ON*, Offline Session Max can control the maximum time the offline token remains active, regardless of user activity. Client Offline Session Idle and Client Offline Session Max are enabled. - -[[_offline-session-max]] -|Offline Session Max -|This setting is for <<_offline-access, offline access>>, and it is the maximum time before {project_name} revokes the corresponding offline token. This option controls the maximum amount of time the offline token remains active, regardless of user activity. - -|Login timeout -|The total time a logging in must take. If authentication takes longer than this time, the user must start the authentication process again. - -|Login action timeout -|The Maximum time users can spend on any one page during the authentication process. -|=== - -.Tokens tab -image:images/tokens-tab.png[Tokens Tab] - -|=== -|Configuration|Description - -|Default Signature Algorithm -|The default algorithm used to assign tokens for the realm. - -[[_revoke-refresh-token]] -|Revoke Refresh Token -|When *Enabled*, {project_name} revokes refresh tokens and issues another token that the client must use. This action applies to OIDC clients performing the refresh token flow. - -|Access Token Lifespan -|When {project_name} creates an OIDC access token, this value controls the lifetime of the token. - -|Access Token Lifespan For Implicit Flow -|With the Implicit Flow, {project_name} does not provide a refresh token. A separate timeout exists for access tokens created by the Implicit Flow. - -|Client login timeout -|The maximum time before clients must finish the Authorization Code Flow in OIDC. - -|User-Initiated Action Lifespan -|The maximum time before a user's action permission expires. Keep this value short because users generally react to self-created actions quickly. - -|Default Admin-Initiated Action Lifespan -|The maximum time before an action permission sent to a user by an administrator expires. Keep this value long to allow administrators to send e-mails to offline users. An administrator can override the default timeout before issuing the token. - -|Email Verification -| Specifies independent timeout for email verification. - -|IdP account email verification -| Specifies independent timeout for IdP account email verification. - -|Forgot password -| Specifies independent timeout for forgot password. - -|Execute actions -| Specifies independent timeout for execute actions. -|=== - -[[_idle_timeouts_note]] - -[NOTE] -==== -For idle timeouts, a two-minute window of time exists that the session is active. For example, when you have the timeout set to 30 minutes, it will be 32 minutes before the session expires. - -This action is necessary for some scenarios in cluster and cross-data center environments where the token refreshes on one cluster node a short time before the expiration and the other cluster nodes incorrectly consider the session as expired because they have not yet received the message about a successful refresh from the refreshing node. -==== diff --git a/server_admin/topics/sessions/transient.adoc b/server_admin/topics/sessions/transient.adoc deleted file mode 100644 index 1d80586ee..000000000 --- a/server_admin/topics/sessions/transient.adoc +++ /dev/null @@ -1,9 +0,0 @@ - -[[_transient-session]] - -=== Transient sessions - -You can conduct transient sessions in {project_name}. When using transient sessions, {project_name} does not create a user session after successful authentication. {project_name} creates a temporary, transient session for the scope of the current request that successfully authenticates the user. {project_name} can run <<_protocol-mappers, protocol mappers>> using transient sessions after authentication. - -During transient sessions, the client application cannot refresh tokens, introspect tokens, or validate a specific session. Sometimes these actions are unnecessary, so you can avoid the additional resource use of persisting user sessions. This session saves performance, memory, and network communication (in cluster and cross-data center environments) resources. - diff --git a/server_admin/topics/sso-protocols.adoc b/server_admin/topics/sso-protocols.adoc deleted file mode 100644 index 19403863f..000000000 --- a/server_admin/topics/sso-protocols.adoc +++ /dev/null @@ -1,12 +0,0 @@ - -== SSO protocols -[role="_abstract"] -This section discusses authentication protocols, the {project_name} authentication server and how applications, secured by the {project_name} authentication server, interact with these protocols. - -include::sso-protocols/con-oidc.adoc[] -include::sso-protocols/con-oidc-auth-flows.adoc[] -include::sso-protocols/con-server-oidc-uri-endpoints.adoc[] -include::sso-protocols/con-saml.adoc[] -include::sso-protocols/con-saml-bindings.adoc[] -include::sso-protocols/ref-saml-vs-oidc.adoc[] -include::sso-protocols/con-sso-docker.adoc[] diff --git a/server_admin/topics/sso-protocols/con-oidc-auth-flows.adoc b/server_admin/topics/sso-protocols/con-oidc-auth-flows.adoc deleted file mode 100644 index e541c41da..000000000 --- a/server_admin/topics/sso-protocols/con-oidc-auth-flows.adoc +++ /dev/null @@ -1,348 +0,0 @@ - -[id="con-oidc-auth-flows_{context}"] -==== OIDC auth flows -[role="_abstract"] -OIDC has several methods, or flows, that clients or applications can use to authenticate users and receive _identity_ and _access_ tokens. The method depends on the type of application or client requesting access. - -[[_oidc-auth-flows-authorization]] - -===== Authorization Code Flow - -The Authorization Code Flow is a browser-based protocol and suits authenticating and authorizing browser-based applications. It uses browser redirects to obtain _identity_ and _access_ tokens. - -. A user connects to an application using a browser. The application detects the user is not logged into the application. -. The application redirects the browser to {project_name} for authentication. -. The application passes a callback URL as a query parameter in the browser redirect. {project_name} uses the parameter upon successful authentication. -. {project_name} authenticates the user and creates a one-time, short-lived, temporary code. -. {project_name} redirects to the application using the callback URL and adds the temporary code as a query parameter in the callback URL. -. The application extracts the temporary code and makes a background REST invocation to {project_name} -to exchange the code for an _identity_ and _access_ and _refresh_ token. To prevent replay attacks, the temporary code cannot be used more than once. - -[NOTE] -==== -A system is vulnerable to a stolen token for the lifetime of that token. For security and scalability reasons, access tokens are generally set to expire quickly so subsequent token requests fail. If a token expires, an application can obtain a new access token using the additional _refresh_ token sent by the login protocol. -==== - -[[_confidential-clients]] -_Confidential_ clients provide client secrets when they exchange the temporary codes for tokens. _Public_ clients are not required to provide client secrets. -_Public_ clients are secure when HTTPS is strictly enforced and redirect URIs registered for the client are strictly controlled. HTML5/JavaScript clients have to be _public_ clients because there is no way to securely transmit the client secret to HTML5/JavaScript clients. For more details, see the xref:assembly-managing-clients_{context}[Managing Clients] chapter. - -{project_name} also supports the https://datatracker.ietf.org/doc/html/rfc7636[Proof Key for Code Exchange] specification. - -[[_oidc-auth-flows-implicit]] - -===== Implicit Flow - -The Implicit Flow is a browser-based protocol. It is similar to the Authorization Code Flow but with fewer requests and no refresh tokens. - -[NOTE] -==== -The possibility exists of _access_ tokens leaking in the browser history when tokens are transmitted via redirect URIs (see below). - -Also, this flow does not provide clients with refresh tokens. Therefore, access tokens have to be long-lived or users have to re-authenticate when they expire. - -We do not advise using this flow. This flow is supported because it is in the OIDC and OAuth 2.0 specification. -==== - -The protocol works as follows: - -. A user connects to an application using a browser. The application detects the user is not logged into the application. -. The application redirects the browser to {project_name} for authentication. -. The application passes a callback URL as a query parameter in the browser redirect. {project_name} uses the query parameter upon successful authentication. -. {project_name} authenticates the user and creates an _identity_ and _access_ token. {project_name} -redirects to the application using the callback URL and additionally adds the _identity_ and _access_ tokens as a query parameter in the callback URL. -. The application extracts the _identity_ and _access_ tokens from the callback URL. - -[[_oidc-auth-flows-direct]] - -===== Resource owner password credentials grant (Direct Access Grants) - -_Direct Access Grants_ are used by REST clients to obtain tokens on behalf of users. It is a HTTP POST request that contains: - -* The credentials of the user. The credentials are sent within form parameters. -* The id of the client. -* The clients secret (if it is a confidential client). - -The HTTP response contains the _identity_, _access_, and _refresh_ tokens. - -[[_client_credentials_grant]] -===== Client credentials grant - -The _Client Credentials Grant_ creates a token based on the metadata and permissions of a service account associated with the client instead of obtaining a token that works on behalf of an external user. _Client Credentials Grants_ are used by REST clients. - -See the <<_service_accounts,Service Accounts>> chapter for more information. - -===== Device authorization grant - -This is used by clients running on internet-connected devices that have limited input capabilities or lack a suitable browser. Here's a brief summary of the protocol: - -. The application requests {project_name} a device code and a user code. {project_name} creates a device code and a user code. {project_name} returns a response including the device code and the user code to the application. -. The application provides the user with the user code and the verification URI. The user accesses a verification URI to be authenticated by using another browser. You could define a short verification_uri that will be redirected to Keycloak verification URI (/realms/realm_name/device)outside Keycloak - fe in a proxy. -. The application repeatedly polls {project_name} to find out if the user completed the user authorization. If user authentication is complete, the application exchanges the device code for an _identity_, _access_ and _refresh_ token. - -[[_client_initiated_backchannel_authentication_grant]] -===== Client initiated backchannel authentication grant - -This feature is used by clients who want to initiate the authentication flow by communicating with the OpenID Provider directly without redirect through the user's browser like OAuth 2.0's authorization code grant. Here's a brief summary of the protocol: - -. The client requests {project_name} an auth_req_id that identifies the authentication request made by the client. {project_name} creates the auth_req_id. -. After receiving this auth_req_id, this client repeatedly needs to poll {project_name} to obtain an Access Token, Refresh Token and ID Token from {project_name} in return for the auth_req_id until the user is authenticated. - -An administrator can configure Client Initiated Backchannel Authentication (CIBA) related operations as `CIBA Policy` per realm. - -Also please refer to other places of {project_name} documentation like link:{adapterguide_link}#_backchannel_authentication_endpoint[Backchannel Authentication Endpoint section] of {adapterguide_name} and link:{adapterguide_link}#_client_initiated_backchannel_authentication_grant[Client Initiated Backchannel Authentication Grant section] of {adapterguide_name}. - -====== CIBA Policy - -An administrator carries out the following operations on the `Admin Console` : - -- Open the `Authentication -> CIBA Policy` tab. -- Configure items and click `Save`. - -The configurable items and their description follow. - -|=== -|Configuration|Description - -|Backchannel Token Delivery Mode -|Specifying how the CD (Consumption Device) gets the authentication result and related tokens. There are three modes, "poll", "ping" and "push". {project_name} only supports "poll". The default setting is "poll". This configuration is required. - For more details, see https://openid.net/specs/openid-client-initiated-backchannel-authentication-core-1_0.html#rfc.section.5[CIBA Specification]. - -|Expires In -|The expiration time of the "auth_req_id" in seconds since the authentication request was received. The default setting is 120. This configuration is required. - For more details, see https://openid.net/specs/openid-client-initiated-backchannel-authentication-core-1_0.html#successful_authentication_request_acknowdlegment[CIBA Specification]. - -|Interval -|The interval in seconds the CD (Consumption Device) needs to wait for between polling requests to the token endpoint. The default setting is 5. This configuration is optional. - For more details, see https://openid.net/specs/openid-client-initiated-backchannel-authentication-core-1_0.html#successful_authentication_request_acknowdlegment[CIBA Specification]. - -|Authentication Requested User Hint -|The way of identifying the end-user for whom authentication is being requested. The default setting is "login_hint". There are three modes, "login_hint", "login_hint_token" and "id_token_hint". {project_name} only supports "login_hint". This configuration is required. - For more details, see https://openid.net/specs/openid-client-initiated-backchannel-authentication-core-1_0.html#rfc.section.7.1[CIBA Specification]. - -|=== - -====== Provider Setting - -The CIBA grant uses the following two providers. - -. Authentication Channel Provider : provides the communication between {project_name} and the entity that actually authenticates the user via AD (Authentication Device). -. User Resolver Provider : get `UserModel` of {project_name} from the information provided by the client to identify the user. - -{project_name} has both default providers. However, the administrator needs to set up Authentication Channel Provider like this: - -[source,bash,subs="attributes+"] ----- -kc.[sh|bat] start --spi-ciba-auth-channel-ciba-http-auth-channel-http-authentication-channel-uri=https://backend.internal.example.com{kc_base_path} ----- - -The configurable items and their description follow. - -|=== -|Configuration|Description - -|http-authentication-channel-uri -|Specifying URI of the entity that actually authenticates the user via AD (Authentication Device). - -|=== - -====== Authentication Channel Provider - -CIBA standard document does not specify how to authenticate the user by AD. Therefore, it might be implemented at the discretion of products. {project_name} delegates this authentication to an external authentication entity. To communicate with the authentication entity, {project_name} provides Authentication Channel Provider. - -Its implementation of {project_name} assumes that the authentication entity is under the control of the administrator of {project_name} so that {project_name} trusts the authentication entity. It is not recommended to use the authentication entity that the administrator of {project_name} cannot control. - -Authentication Channel Provider is provided as SPI provider so that users of {project_name} can implement their own provider in order to meet their environment. {project_name} provides its default provider called HTTP Authentication Channel Provider that uses HTTP to communicate with the authentication entity. - -If a user of {project_name} user want to use the HTTP Authentication Channel Provider, they need to know its contract between {project_name} and the authentication entity consisting of the following two parts. - -Authentication Delegation Request/Response:: -{project_name} sends an authentication request to the authentication entity. - -Authentication Result Notification/ACK:: -The authentication entity notifies the result of the authentication to {project_name}. - -Authentication Delegation Request/Response consists of the following messaging. - -Authentication Delegation Request:: The request is sent from {project_name} to the authentication entity to ask it for user authentication by AD. - ----- -POST [delegation_reception] ----- - -* Headers - -|=== -|Name|Value|Description - -|Content-Type|application/json|The message body is json formatted. -|Authorization|Bearer [token]|The [token] is used when the authentication entity notifies the result of the authentication to {project_name}. - -|=== - -* Parameters - -|=== -|Type|Name|Description - -|Path -|delegation_reception|The endpoint provided by the authentication entity to receive the delegation request - -|=== - -* Body - -|=== -|Name|Description - -|login_hint|It tells the authentication entity who is authenticated by AD. + -By default, it is the user's "username". + -This field is required and was defined by CIBA standard document. - -|scope|It tells which scopes the authentication entity gets consent from the authenticated user. + -This field is required and was defined by CIBA standard document. - -|is_consent_required|It shows whether the authentication entity needs to get consent from the authenticated user about the scope. + - This field is required. - -|binding_message|Its value is intended to be shown in both CD and AD's UI to make the user recognize that the authentication by AD is triggered by CD. + -This field is optional and was defined by CIBA standard document. - -|acr_values|It tells the requesting Authentication Context Class Reference from CD. + -This field is optional and was defined by CIBA standard document. - -|=== - -Authentication Delegation Response:: The response is returned from the authentication entity to {project_name} to notify that the authentication entity received the authentication request from {project_name}. - -* Responses - -|=== -|HTTP Status Code|Description - -|201|It notifies {project_name} of receiving the authentication delegation request. - -|=== - -Authentication Result Notification/ACK consists of the following messaging. - -Authentication Result Notification:: The authentication entity sends the result of the authentication request to {project_name}. - -[source,subs=+attributes] ----- -POST {kc_realms_path}/[realm]/protocol/openid-connect/ext/ciba/auth/callback ----- - -* Headers - -|=== -|Name|Value|Description - -|Content-Type|application/json|The message body is json formatted. -|Authorization|Bearer [token]|The [token] must be the one the authentication entity has received from {project_name} in Authentication Delegation Request. - -|=== - -* Parameters - -|=== -|Type|Name|Description - -|Path -|realm|The realm name - -|=== - -* Body - -|=== -|Name|Description - -|status|It tells the result of user authentication by AD. + -It must be one of the following status. + - SUCCEED : The authentication by AD has been successfully completed. + - UNAUTHORIZED : The authentication by AD has not been completed. + - CANCELLED : The authentication by AD has been cancelled by the user. - -|=== - -Authentication Result ACK:: The response is returned from {project_name} to the authentication entity to notify {project_name} received the result of user authentication by AD from the authentication entity. - -* Responses - -|=== -|HTTP Status Code|Description - -|200|It notifies the authentication entity of receiving the notification of the authentication result. - -|=== - -====== User Resolver Provider - -Even if the same user, its representation may differ in each CD, {project_name} and the authentication entity. - -For CD, {project_name} and the authentication entity to recognize the same user, this User Resolver Provider converts their own user representations among them. - -User Resolver Provider is provided as SPI provider so that users of {project_name} can implement their own provider in order to meet their environment. {project_name} provides its default provider called Default User Resolver Provider that has the following characteristics. - -* Only support `login_hint` parameter and is used as default. -* `username` of UserModel in {project_name} is used to represent the user on CD, {project_name} and the authentication entity. - -[[_oidc-logout]] - -==== OIDC Logout - -OIDC has four specifications relevant to logout mechanisms. These specifications are in draft status: - -. https://openid.net/specs/openid-connect-session-1_0.html[Session Management] -. https://openid.net/specs/openid-connect-rpinitiated-1_0.html[RP-Initiated Logout] -. https://openid.net/specs/openid-connect-frontchannel-1_0.html[Front-Channel Logout] -. https://openid.net/specs/openid-connect-backchannel-1_0.html[Back-Channel Logout] - -Again since all of this is described in the OIDC specification we will only give a brief overview here. - -===== Session Management - -This is a browser-based logout. The application obtains session status information from {project_name} at a regular basis. -When the session is terminated at {project_name} the application will notice and trigger its own logout. - -===== RP-Initiated Logout - -This is also a browser-based logout where the logout starts by redirecting the user to a specific endpoint at {project_name}. -This redirect usually happens when the user clicks the `Log Out` link on the page of some application, which previously used {project_name} to authenticate the user. - -Once the user is redirected to the logout endpoint, {project_name} is going to send logout requests to -clients to let them invalidate their local user sessions, and potentially redirect the user to some URL -once the logout process is finished. The user might be optionally requested to confirm the logout in case the `id_token_hint` parameter was not used. -After logout, the user is automatically redirected to the specified `post_logout_redirect_uri` as long as it is provided as a parameter. -Note that you need to include either the `client_id` or `id_token_hint` parameter in case the `post_logout_redirect_uri` is included. Also the `post_logout_redirect_uri` parameter -needs to match one of the `Valid Post Logout Redirect URIs` specified in the client configuration. - -Depending on the client configuration, logout requests can be sent to clients through the front-channel or through the back-channel. For the frontend browser clients, which rely on the -Session Management described in the previous section, {project_name} does not need to send any logout requests to them; these clients automatically detect that SSO session -in the browser is logged out. - -===== Front-channel Logout - -To configure clients to receive logout requests through the front-channel, look at the <<_front-channel-logout, Front-Channel Logout>> client setting. When using this method, consider the following: - -* Logout requests sent by {project_name} to clients rely on the browser and on embedded `iframes` that are rendered for the logout page. -* By being based on `iframes`, front-channel logout might be impacted by Content Security Policies (CSP) and logout requests might be blocked. -* If the user closes the browser prior to rendering the logout page or before logout requests are actually sent to clients, their sessions at -the client might not be invalidated. - -[NOTE] -==== -Consider using Back-Channel Logout as it provides a more reliable and secure approach to log out users and terminate their sessions -on the clients. -==== - -If the client is not enabled with front-channel logout, then {project_name} is going to try first to send logout requests through the back-channel -using the <<_back-channel-logout-url, Back-Channel Logout URL>>. If not defined, the server is going to fall back to using the <<_admin-url, Admin URL>>. - -===== Backchannel Logout - -This is a non-browser-based logout that uses direct backchannel communication between {project_name} and clients. -{project_name} sends a HTTP POST request containing a logout token to all clients logged into {project_name}. These -requests are sent to a registered backchannel logout URLs at {project_name} and are supposed to trigger a logout at client side. - diff --git a/server_admin/topics/sso-protocols/con-oidc.adoc b/server_admin/topics/sso-protocols/con-oidc.adoc deleted file mode 100644 index ed6308f79..000000000 --- a/server_admin/topics/sso-protocols/con-oidc.adoc +++ /dev/null @@ -1,20 +0,0 @@ -[id="con-oidc_{context}"] - -=== OpenID Connect -[role="_abstract"] -link:https://openid.net/connect/[OpenID Connect] (OIDC) is an authentication protocol that is an extension of link:https://datatracker.ietf.org/doc/html/rfc6749[OAuth 2.0]. - -OAuth 2.0 is a framework for building authorization protocols and is incomplete. OIDC, however, is a full authentication and authorization protocol that uses the link:https://jwt.io[Json Web Token] (JWT) standards. The JWT standards define an identity token JSON format and methods to digitally sign and encrypt data in a compact and web-friendly way. - -In general, OIDC implements two use cases. The first case is an application requesting that a {project_name} server authenticates a user. Upon successful login, the application receives an _identity token_ and an _access token_. -The _identity token_ contains user information including user name, email, and profile information. The realm digitally signs the _access token_ which contains access information (such as user role mappings) that applications use to determine the resources users can access in the application. - -The second use case is a client accessing remote services. - -* The client requests an _access token_ from {project_name} to invoke on remote services on behalf of the user. -* {project_name} authenticates the user and asks the user for consent to grant access to the requesting client. -* The client receives the _access token_ which is digitally signed by the realm. -* The client makes REST requests on remote services using the _access token_. -* The remote REST service extracts the _access token_. -* The remote REST service verifies the tokens signature. -* The remote REST service decides, based on access information within the token, to process or reject the request. diff --git a/server_admin/topics/sso-protocols/con-saml-bindings.adoc b/server_admin/topics/sso-protocols/con-saml-bindings.adoc deleted file mode 100644 index 2822e32c5..000000000 --- a/server_admin/topics/sso-protocols/con-saml-bindings.adoc +++ /dev/null @@ -1,41 +0,0 @@ -[id="con-saml-bindings_{context}"] - -==== SAML bindings -[role="_abstract"] -{project_name} supports three binding types. - -===== Redirect binding - -_Redirect_ binding uses a series of browser redirect URIs to exchange information. - -. A user connects to an application using a browser. The application detects the user is not authenticated. -. The application generates an XML authentication request document and encodes it as a query parameter in a URI. The URI is used to redirect to the {project_name} server. Depending on your settings, the application can also digitally sign the XML document and include the signature as a query parameter in the redirect URI to {project_name}. This signature is used to validate the client that sends the request. -. The browser redirects to {project_name}. -. The server extracts the XML auth request document and verifies the digital signature, if required. -. The user enters their authentication credentials. -. After authentication, the server generates an XML authentication response document. The document contains a SAML assertion that holds metadata about the user, including name, address, email, and any role mappings the user has. The document is usually digitally signed using XML signatures, and may also be encrypted. -. The XML authentication response document is encoded as a query parameter in a redirect URI. The URI brings the browser back to the application. The digital signature is also included as a query parameter. -. The application receives the redirect URI and extracts the XML document. -. The application verifies the realm's signature to ensure it is receiving a valid authentication response. The information inside the SAML assertion is used to make access decisions or display user data. - -===== POST binding - -_POST_ binding is similar to _Redirect_ binding but _POST_ binding exchanges XML documents using POST requests instead of using GET requests. _POST_ Binding uses JavaScript to make the browser send a POST request to the {project_name} server or application when exchanging documents. HTTP responds with an HTML document which contains an HTML form containing embedded JavaScript. When the page loads, the JavaScript automatically invokes the form. - -_POST_ binding is recommended due to two restrictions: - -* *Security* -- With _Redirect_ binding, the SAML response is part of the URL. It is less secure as it is possible to capture the response in logs. - -* *Size* -- Sending the document in the HTTP payload provides more scope for large amounts of data than in a limited URL. - -===== ECP - -Enhanced Client or Proxy (ECP) is a SAML v.2.0 profile which allows the exchange of SAML attributes outside the context of a web browser. It is often used by REST or SOAP-based clients. - -==== {project_name} Server SAML URI Endpoints - -{project_name} has one endpoint for all SAML requests. - -`http(s)://authserver.host{kc_realms_path}/{realm-name}/protocol/saml` - -All bindings use this endpoint. diff --git a/server_admin/topics/sso-protocols/con-saml.adoc b/server_admin/topics/sso-protocols/con-saml.adoc deleted file mode 100644 index bac36597b..000000000 --- a/server_admin/topics/sso-protocols/con-saml.adoc +++ /dev/null @@ -1,13 +0,0 @@ -[id="con-saml_{context}"] - -[[_saml]] - -=== SAML -[role="_abstract"] -link:http://saml.xml.org/saml-specifications[SAML 2.0] is a similar specification to OIDC but more mature. It is descended from SOAP and web service messaging specifications so is generally more verbose than OIDC. SAML 2.0 is an authentication protocol that exchanges XML documents between authentication servers and applications. XML signatures and encryption are used to verify requests and responses. - -In general, SAML implements two use cases. - -The first use case is an application that requests the {project_name} server authenticates a user. Upon successful login, the application will receive an XML document. This document contains an SAML assertion that specifies user attributes. The realm digitally signs the document which contains access information (such as user role mappings) that applications use to determine the resources users are allowed to access in the application. - -The second use case is a client accessing remote services. The client requests a SAML assertion from {project_name} to invoke on remote services on behalf of the user. diff --git a/server_admin/topics/sso-protocols/con-server-oidc-uri-endpoints.adoc b/server_admin/topics/sso-protocols/con-server-oidc-uri-endpoints.adoc deleted file mode 100644 index 7e7de087c..000000000 --- a/server_admin/topics/sso-protocols/con-server-oidc-uri-endpoints.adoc +++ /dev/null @@ -1,39 +0,0 @@ -[id="con-server-oidc-uri-endpoints_{context}"] - -==== {project_name} server OIDC URI endpoints -[role="_abstract"] -The following is a list of OIDC endpoints that {project_name} publishes. These endpoints can be used when a non-{project_name} client adapter uses OIDC to communicate with the authentication server. They are all relative URLs. The root of the URL consists of the HTTP(S) protocol, hostname, and optionally the path: For example - -[source, subs="attributes"] ----- -https://localhost:8080{kc_base_path} ----- - -/realms/{realm-name}/protocol/openid-connect/auth:: - Used for obtaining a temporary code in the Authorization Code Flow or obtaining tokens using the Implicit Flow, Direct Grants, or Client Grants. - -/realms/{realm-name}/protocol/openid-connect/token:: - Used by the Authorization Code Flow to convert a temporary code into a token. - -/realms/{realm-name}/protocol/openid-connect/logout:: - Used for performing logouts. - -/realms/{realm-name}/protocol/openid-connect/userinfo:: - Used for the User Info service described in the OIDC specification. - -/realms/{realm-name}/protocol/openid-connect/revoke:: - Used for OAuth 2.0 Token Revocation described in https://datatracker.ietf.org/doc/html/rfc7009[RFC7009]. - -/realms/{realm-name}/protocol/openid-connect/certs:: - Used for the JSON Web Key Set (JWKS) containing the public keys used to verify any JSON Web Token (jwks_uri) - -/realms/{realm-name}/protocol/openid-connect/auth/device:: - Used for Device Authorization Grant to obtain a device code and a user code. - -/realms/{realm-name}/protocol/openid-connect/ext/ciba/auth:: - This is the URL endpoint for Client Initiated Backchannel Authentication Grant to obtain an auth_req_id that identifies the authentication request made by the client. - -/realms/{realm-name}/protocol/openid-connect/logout/backchannel-logout:: - This is the URL endpoint for performing backchannel logouts described in the OIDC specification. - -In all of these, replace {realm-name} with the name of the realm. diff --git a/server_admin/topics/sso-protocols/con-sso-docker.adoc b/server_admin/topics/sso-protocols/con-sso-docker.adoc deleted file mode 100644 index 885a75a41..000000000 --- a/server_admin/topics/sso-protocols/con-sso-docker.adoc +++ /dev/null @@ -1,30 +0,0 @@ -[id="con-sso-docker_{context}"] - -[[_docker]] - -=== Docker registry v2 authentication - -[NOTE] -==== -Docker authentication is disabled by default. To enable docker authentication, see the https://www.keycloak.org/server/features[Enabling and disabling features] guide. -==== -[role="_abstract"] -link:https://docs.docker.com/registry/spec/auth/[Docker Registry V2 Authentication] is a protocol, similar to OIDC, that authenticates users against Docker registries. {project_name}'s implementation of this protocol lets Docker clients use a {project_name} authentication server authenticate against a registry. This protocol uses standard token and signature mechanisms but it does deviate from a true OIDC implementation. It deviates by using a very specific JSON format for requests and responses as well as mapping repository names and permissions to the OAuth scope mechanism. - -==== Docker authentication flow -The authentication flow is described in the link:https://docs.docker.com/registry/spec/auth/token/[Docker API documentation]. The following is a summary from the perspective of the {project_name} authentication server: - -* Perform a `docker login`. -* The Docker client requests a resource from the Docker registry. If the resource is protected and no authentication token is in the request, the Docker registry server responds with a 401 HTTP message with some information on the permissions that are required and the location of the authorization server. -* The Docker client constructs an authentication request based on the 401 HTTP message from the Docker registry. The client uses the locally cached credentials (from the `docker login` command) as part of the link:https://datatracker.ietf.org/doc/html/rfc2617[HTTP Basic Authentication] request to the {project_name} authentication server. -* The {project_name} authentication server attempts to authenticate the user and return a JSON body containing an OAuth-style Bearer token. -* The Docker client receives a bearer token from the JSON response and uses it in the authorization header to request the protected resource. -* The Docker registry receives the new request for the protected resource with the token from the {project_name} server. The registry validates the token and grants access to the requested resource (if appropriate). - -NOTE: {project_name} does not create a browser SSO session after successful authentication with the Docker protocol. The browser SSO session does not use the Docker protocol as it cannot refresh tokens or obtain the status of a token or session from the {project_name} server; therefore a browser SSO session is not necessary. For more details, see the <<_transient-session, transient session>> section. - -==== {project_name} Docker Registry v2 Authentication Server URI Endpoints - -{project_name} has one endpoint for all Docker auth v2 requests. - -`http(s)://authserver.host{kc_realms_path}/{realm-name}/protocol/docker-v2` diff --git a/server_admin/topics/sso-protocols/docker.adoc b/server_admin/topics/sso-protocols/docker.adoc deleted file mode 100644 index 1f16df23f..000000000 --- a/server_admin/topics/sso-protocols/docker.adoc +++ /dev/null @@ -1,29 +0,0 @@ -[[_docker]] - -=== Docker Registry v2 Authentication - -NOTE: Docker authentication is disabled by default. To enable see the https://www.keycloak.org/server/features[Enabling and disabling features] guide. - -link:https://docs.docker.com/registry/spec/auth/[Docker Registry V2 Authentication] is an OIDC-Like protocol used to authenticate users against a Docker registry. {project_name}'s implementation of this protocol allows for a {project_name} authentication server to be used by a Docker client to authenticate against a registry. While this protocol uses fairly standard token and signature mechanisms, it has a few wrinkles that prevent it from being treated as a true OIDC implementation. The largest deviations include a very specific JSON format for requests and responses as well as the ability to understand how to map repository names and permissions to the OAuth scope mechanism. - -==== Docker Auth Flow -The link:https://docs.docker.com/registry/spec/auth/token/[Docker API documentation] best describes and illustrates this process, however a brief summary will be given below from the perspective of the {project_name} authentication server. - -NOTE: This flow assumes that a `docker login` command has already been performed - - * The flow begins when the Docker client requests a resource from the Docker registry. If the resource is protected and no auth token is present in the request, the Docker registry server will respond to the client with a 401 + some information on required permissions and where to find the authorization server. - * The Docker client will construct an authentication request based on the 401 response from the Docker registry. The client will then use the locally cached credentials (from a previously run `docker login` command) as part of a link:https://datatracker.ietf.org/doc/html/rfc2617[HTTP Basic Authentication] request to the {project_name} authentication server. - * The {project_name} authentication server will attempt to authenticate the user and return a JSON body containing an OAuth-style Bearer token. - * The Docker client will get the bearer token from the JSON response and use it in the Authorization header to request the protected resource. - * When the Docker registry receives the new request for the protected resource with the token from the {project_name} server, the registry validates the token and grants access to the requested resource (if appropriate). - -NOTE: No user session is created on the {project_name} side after successful authentication with the Docker protocol. The Docker protocol is -not used in case of browser SSO session and it does not have a way to refresh token or ask {project_name} server if a particular token/session -is still valid. So creating the session is unnecessary overhead for this protocol. For more details, see the <<_transient-session, transient session>> section. - -==== {project_name} Docker Registry v2 Authentication Server URI Endpoints - -{project_name} really only has one endpoint for all Docker auth v2 requests. - -`http(s)://authserver.host{kc_realms_path}/{realm-name}/protocol/docker-v2` - diff --git a/server_admin/topics/sso-protocols/oidc.adoc b/server_admin/topics/sso-protocols/oidc.adoc deleted file mode 100644 index ef30b2a4d..000000000 --- a/server_admin/topics/sso-protocols/oidc.adoc +++ /dev/null @@ -1,398 +0,0 @@ -[id="con-oidc_{context}"] - -=== OpenID Connect - -link:https://openid.net/connect/[OpenID Connect] (OIDC) is an authentication protocol that is an extension of link:https://datatracker.ietf.org/doc/html/rfc6749[OAuth 2.0]. -While OAuth 2.0 is only a framework for building authorization protocols and is mainly incomplete, OIDC is a full-fledged authentication and authorization -protocol. OIDC also makes heavy use of the link:https://jwt.io[Json Web Token] (JWT) set of standards. These standards define an -identity token JSON format and ways to digitally sign and encrypt that data in a compact and web-friendly way. - -There are really two types of use cases when using OIDC. The first is an application that asks the {project_name} server to authenticate -a user for them. After a successful login, the application will receive an _identity token_ and an _access token_. The _identity token_ -contains information about the user such as username, email, and other profile information. The _access token_ is digitally signed by -the realm and contains access information (like user role mappings) that the application can use to determine what resources the user -is allowed to access on the application. - -The second type of use cases is that of a client that wants to gain access to remote services. In this case, the client asks {project_name} -to obtain an _access token_ it can use to invoke on other remote services on behalf of the user. {project_name} authenticates the user -then asks the user for consent to grant access to the client requesting it. The client then receives the _access token_. This _access token_ -is digitally signed by the realm. The client can make REST invocations on remote services using this _access token_. The REST service -extracts the _access token_, verifies the signature of the token, then decides based on access information within the token whether or not to process -the request. - -[[_oidc-auth-flows]] - -==== OIDC Auth Flows - -OIDC has different ways for a client or application to authenticate a user and receive an _identity_ and _access_ token. Which -path you use depends greatly on the type of application or client requesting access. All of these flows are described in the -OIDC and OAuth 2.0 specifications so only a brief overview will be provided here. - -[[_oidc-auth-flows-authorization]] - -===== Authorization Code Flow - -This is a browser-based protocol and it is what we recommend you use to authenticate and authorize browser-based applications. It makes -heavy use of browser redirects to obtain an _identity_ and _access_ token. Here's a brief summary: - -. Browser visits application. The application notices the user is not logged in, so it redirects the browser to {project_name} - to be authenticated. The application passes along a callback URL (a redirect URL) as a query parameter in this browser redirect - that {project_name} will use when it finishes authentication. -. {project_name} authenticates the user and creates a one-time, very short-lived, temporary code. {project_name} - redirects back to the application using the callback URL provided earlier and additionally adds the temporary code - as a query parameter in the callback URL. -. The application extracts the temporary code and makes a background out of band REST invocation to {project_name} - to exchange the code for an _identity_, _access_ and _refresh_ token. Once this temporary code has been used once - to obtain the tokens, it can never be used again. This prevents potential replay attacks. - -It is important to note that _access_ tokens are usually short-lived and often expired after only minutes. The additional _refresh_ -token that was transmitted by the login protocol allows the application to obtain a new access token after it expires. This -refresh protocol is important in the situation of a compromised system. If access tokens are short-lived, the whole system is only -vulnerable to a stolen token for the lifetime of the access token. Future refresh token requests will fail if an admin -has revoked access. This makes things more secure and more scalable. - -[[_confidential-clients]] -Another important aspect of this flow is the concept of a _public_ vs. a _confidential_ client. _Confidential_ clients are required -to provide a client secret when they exchange the temporary codes for tokens. _Public_ clients are not required to provide this client secret. -_Public_ clients are perfectly fine so long as HTTPS is strictly enforced and you are very strict about what redirect URIs are registered for the -client. HTML5/JavaScript clients always have to be _public_ clients because there is no way to transmit the client secret to them in a secure -manner. Again, this is ok so long as you use HTTPS and strictly enforce redirect URI registration. This guide goes more detail -into this in the xref:assembly-managing-clients_{context}[Managing Clients] chapter. - -{project_name} also supports the optional https://datatracker.ietf.org/doc/html/rfc7636[Proof Key for Code Exchange] specification. - -[[_oidc-auth-flows-implicit]] - -===== Implicit Flow - -This is a browser-based protocol that is similar to Authorization Code Flow except there are fewer requests and no refresh tokens involved. -We do not recommend this flow as there remains the possibility of _access_ tokens being leaked in the browser history as tokens are transmitted -via redirect URIs (see below). Also, since this flow doesn't provide the client with a refresh token, access tokens would either have to -be long-lived or users would have to re-authenticate when they expired. This flow is supported because it is in the OIDC and OAuth 2.0 specification. -Here's a brief summary of the protocol: - -. Browser visits application. The application notices the user is not logged in, so it redirects the browser to {project_name} - to be authenticated. The application passes along a callback URL (a redirect URL) as a query parameter in this browser redirect - that {project_name} will use when it finishes authentication. -. {project_name} authenticates the user and creates an _identity_ and _access_ token. {project_name} - redirects back to the application using the callback URL provided earlier and additionally adding the _identity_ and - _access_ tokens as query parameters in the callback URL. -. The application extracts the _identity_ and _access_ tokens from the callback URL. - -[[_oidc-auth-flows-direct]] - -===== Resource Owner Password Credentials Grant (Direct Access Grants) - -This is referred to in the Admin Console as _Direct Access Grants_. This is used by REST clients that want to obtain a token on behalf of a user. It is one HTTP POST request that contains -the credentials of the user as well as the id of the client and the client's secret (if it is a confidential client). The user's credentials -are sent within form parameters. The HTTP response contains -_identity_, _access_, and _refresh_ tokens. - -[[_client_credentials_grant]] -===== Client Credentials Grant - -This is also used by REST clients, but instead of obtaining a token that works on behalf -of an external user, a token is created based on the metadata and permissions of a service account that is associated with the client. -More info together with example is in <<_service_accounts,Service Accounts>> chapter. - -===== Device Authorization Grant - -This is used by clients running on internet-connected devices that have limited input capabilities or lack a suitable browser. Here's a brief summary of the protocol: - -. The application requests {project_name} a device code and a user code. {project_name} creates a device code and a user code. {project_name} returns a response including the device code and the user code to the application. -. The application provides the user with the user code and the verification URI. The user accesses a verification URI to be authenticated by using another browser. -. The application repeatedly polls {project_name} to find out if the user completed the user authorization. If user authentication is complete, the application exchanges the device code for an _identity_, _access_ and _refresh_ token. - -[[_client_initiated_backchannel_authentication_grant]] -===== Client Initiated Backchannel Authentication Grant - -This is used by clients who want to initiate the authentication flow by communicating with the OpenID Provider directly without redirect through the user's browser like OAuth 2.0's authorization code grant. Here's a brief summary of the protocol: - -. The client requests {project_name} an auth_req_id that identifies the authentication request made by the client. {project_name} creates the auth_req_id. -. After receiving this auth_req_id, this client repeatedly needs to poll {project_name} to obtain an Access Token, Refresh Token and ID Token from {project_name} in return for the auth_req_id until the user is authenticated. - -An administrator can configure Client Initiated Backchannel Authentication (CIBA) related operations as `CIBA Policy` per realm. - -Also please refer to other places of {project_name} documentation like link:{adapterguide_link}#_backchannel_authentication_endpoint[Backchannel Authentication Endpoint section] of {adapterguide_name} and link:{adapterguide_link}#_client_initiated_backchannel_authentication_grant[Client Initiated Backchannel Authentication Grant section] of {adapterguide_name}. - -====== CIBA Policy - -An administrator carries out the following operations on the `Admin Console` : - -- Open the `Authentication -> CIBA Policy` tab. -- Configure items and click `Save`. - -The configurable items and their description follow. - -|=== -|Configuration|Description - -|Backchannel Token Delivery Mode -|Specifying how the CD (Consumption Device) gets the authentication result and related tokens. There are three modes, "poll", "ping" and "push". {project_name} only supports "poll" and "ping" modes. -The default setting is "poll". This configuration is used as the default mode for clients, however every client can override the mode. - For more details, see https://openid.net/specs/openid-client-initiated-backchannel-authentication-core-1_0.html#rfc.section.5[CIBA Specification]. - -|Expires In -|The expiration time of the "auth_req_id" in seconds since the authentication request was received. The default setting is 120. This configuration is required. - For more details, see https://openid.net/specs/openid-client-initiated-backchannel-authentication-core-1_0.html#successful_authentication_request_acknowdlegment[CIBA Specification]. - -|Interval -|The interval in seconds the CD (Consumption Device) needs to wait for between polling requests to the token endpoint. The default setting is 5. This configuration is optional. - For more details, see https://openid.net/specs/openid-client-initiated-backchannel-authentication-core-1_0.html#successful_authentication_request_acknowdlegment[CIBA Specification]. - -|Authentication Requested User Hint -|The way of identifying the end-user for whom authentication is being requested. The default setting is "login_hint". There are three modes, "login_hint", "login_hint_token" and "id_token_hint". {project_name} only supports "login_hint". This configuration is required. - For more details, see https://openid.net/specs/openid-client-initiated-backchannel-authentication-core-1_0.html#rfc.section.7.1[CIBA Specification]. - -|=== - -====== Provider Setting - -The CIBA grant uses the following two providers. - -. Authentication Channel Provider : provides the communication between {project_name} and the entity that actually authenticates the user via AD (Authentication Device). -. User Resolver Provider : get `UserModel` of {project_name} from the information provided by the client to identify the user. - -{project_name} has both default providers. However, the administrator needs to set up Authentication Channel Provider like this: - -[source,bash,subs="attributes+"] ----- -kc.[sh|bat] start --spi-ciba-auth-channel-ciba-http-auth-channel-http-authentication-channel-uri=https://backend.internal.example.com{kc_base_path} ----- - -The configurable items and their description follow. - -|=== -|Configuration|Description - -|httpAuthenticationChannelUri -|Specifying URI of the entity that actually authenticates the user via AD (Authentication Device). - -|=== - -====== Authentication Channel Provider - -CIBA standard document does not specify how to authenticate the user by AD. Therefore, it might be implemented at the discretion of products. {project_name} delegates this authentication to an external authentication entity. To communicate with the authentication entity, {project_name} provides Authentication Channel Provider. - -Its implementation of {project_name} assumes that the authentication entity is under the control of the administrator of {project_name} so that {project_name} trusts the authentication entity. It is not recommended to use the authentication entity that the administrator of {project_name} cannot control. - -Authentication Channel Provider is provided as SPI provider so that users of {project_name} can implement their own provider in order to meet their environment. {project_name} provides its default provider called HTTP Authentication Channel Provider that uses HTTP to communicate with the authentication entity. - -If a user of {project_name} user want to use the HTTP Authentication Channel Provider, they need to know its contract between {project_name} and the authentication entity consisting of the following two parts. - -Authentication Delegation Request/Response:: -{project_name} sends an authentication request to the authentication entity. - -Authentication Result Notification/ACK:: -The authentication entity notifies the result of the authentication to {project_name}. - -Authentication Delegation Request/Response consists of the following messaging. - -Authentication Delegation Request:: The request is sent from {project_name} to the authentication entity to ask it for user authentication by AD. - ----- -POST [delegation_reception] ----- - -* Headers - -|=== -|Name|Value|Description - -|Content-Type|application/json|The message body is json formatted. -|Authorization|Bearer [token]|The [token] is used when the authentication entity notifies the result of the authentication to {project_name}. - -|=== - -* Parameters - -|=== -|Type|Name|Description - -|Path -|delegation_reception|The endpoint provided by the authentication entity to receive the delegation request - -|=== - -* Body - -|=== -|Name|Description - -|login_hint|It tells the authentication entity who is authenticated by AD. + -By default, it is the user's "username". + -This field is required and was defined by CIBA standard document. - -|scope|It tells which scopes the authentication entity gets consent from the authenticated user. + -This field is required and was defined by CIBA standard document. - -|is_consent_required|It shows whether the authentication entity needs to get consent from the authenticated user about the scope. + - This field is required. - -|binding_message|Its value is intended to be shown in both CD and AD's UI to make the user recognize that the authentication by AD is triggered by CD. + -This field is optional and was defined by CIBA standard document. - -|acr_values|It tells the requesting Authentication Context Class Reference from CD. + -This field is optional and was defined by CIBA standard document. - -|=== - -Besides the mentioned parameters, any custom parameter that is sent to the Backchannel Authentication Endpoint, will be forwarded to Channel Provider as well. - -Authentication Delegation Response:: The response is returned from the authentication entity to {project_name} to notify that the authentication entity received the authentication request from {project_name}. - -* Responses - -|=== -|HTTP Status Code|Description - -|201|It notifies {project_name} of receiving the authentication delegation request. - -|=== - -Authentication Result Notification/ACK consists of the following messaging. - -Authentication Result Notification:: The authentication entity sends the result of the authentication request to {project_name}. - -[source,subs=+attributes] ----- -POST {kc_realms_path}/[realm]/protocol/openid-connect/ext/ciba/auth/callback ----- - -* Headers - -|=== -|Name|Value|Description - -|Content-Type|application/json|The message body is json formatted. -|Authorization|Bearer [token]|The [token] must be the one the authentication entity has received from {project_name} in Authentication Delegation Request. - -|=== - -* Parameters - -|=== -|Type|Name|Description - -|Path -|realm|The realm name - -|=== - -* Body - -|=== -|Name|Description - -|status|It tells the result of user authentication by AD. + -It must be one of the following status. + - SUCCEED : The authentication by AD has been successfully completed. + - UNAUTHORIZED : The authentication by AD has not been completed. + - CANCELLED : The authentication by AD has been cancelled by the user. - -|=== - -Authentication Result ACK:: The response is returned from {project_name} to the authentication entity to notify {project_name} received the result of user authentication by AD from the authentication entity. - -* Responses - -|=== -|HTTP Status Code|Description - -|200|It notifies the authentication entity of receiving the notification of the authentication result. - -|=== - -====== User Resolver Provider - -Even if the same user, its representation may differ in each CD, {project_name} and the authentication entity. - -For CD, {project_name} and the authentication entity to recognize the same user, this User Resolver Provider converts their own user representations among them. - -User Resolver Provider is provided as SPI provider so that users of {project_name} can implement their own provider in order to meet their environment. {project_name} provides its default provider called Default User Resolver Provider that has the following characteristics. - -* Only support `login_hint` parameter and is used as default. -* `username` of UserModel in {project_name} is used to represent the user on CD, {project_name} and the authentication entity. - - -[[_oidc-logout]] - -==== OIDC Logout - -OIDC has three different specifications relevant to logout mechanisms, all of these are currently in draft status: - -. https://openid.net/specs/openid-connect-session-1_0.html[Session Management] -. https://openid.net/specs/openid-connect-frontchannel-1_0.html[Front-Channel Logout] -. https://openid.net/specs/openid-connect-backchannel-1_0.html[Back-Channel Logout] - -Again since all of this is described in the OIDC specification we will only give a brief overview here. - -===== Session Management - -This is a browser-based logout. The application obtains session status information from {project_name} at a regular basis. -When the session is terminated at {project_name} the application will notice and trigger its own logout. - -===== Front-Channel Logout - -This is also a browser-based logout where the logout starts by redirecting the user to a specific endpoint at {project_name}. - -Once the user is redirected to the logout endpoint, {project_name} is going to send logout requests to -clients to let them invalidate their local user sessions, and potentially redirect the user to some URL -once the logout process is finished. - -Depending on the client configuration, logout requests can be sent to clients through the front-channel or through the back-channel. - -To configure clients to receive logout requests through the front-channel, look at the <<_front-channel-logout, Front-Channel Logout>> client setting. When using this method, consider the following: - -* Logout requests sent by {project_name} to clients rely on the browser and on embedded `iframes` that are rendered for the logout page. -* By being based on `iframes`, front-channel logout might be impacted by Content Security Policies (CSP) and logout requests might be blocked. -* If the user closes the browser prior to rendering the logout page or before logout requests are actually sent to clients, their sessions at -the client might not be invalidated. - -[NOTE] -==== -Consider using Back-Channel Logout as it provides a more reliable and secure approach to log out users and terminate their sessions -on the clients. -==== - -If the client is not enabled with front-channel logout, then {project_name} is going to try first to send logout requests through the back-channel -using the <<_back-channel-logout-url, Back-Channel Logout URL>>. If not defined, the server is going to fall back to using the <<_admin-url, Admin URL>>. - -===== Backchannel Logout - -This is a non-browser-based logout that uses direct backchannel communication between {project_name} and clients. -{project_name} sends a HTTP POST request containing a logout token to all clients logged into {project_name}. These -requests are sent to a registered backchannel logout URLs at {project_name} and are supposed to trigger a logout at client side. - - -[[_oidc-endpoints]] -==== {project_name} Server OIDC URI Endpoints - -Here's a list of OIDC endpoints that the {project_name} publishes. These URLs are useful if you are using a non-{project_name} client adapter to -talk OIDC with the auth server. These are all relative URLs and the root of the URL being the HTTP(S) protocol, hostname, and usually path prefixed with -_/auth_, for example \https://localhost:8080{kc_base_path}. - -You can also find these endpoints under "OpenID Endpoint Configuration" in your realm settings. - -/realms/{realm-name}/protocol/openid-connect/auth:: - This is the URL endpoint for obtaining a temporary code in the Authorization Code Flow or for obtaining tokens via the - Implicit Flow or Hybrid Flow. -/realms/{realm-name}/protocol/openid-connect/token:: - This is the URL endpoint for the Authorization Code Flow to turn a temporary code into a token, or for obtaining tokens - directly via Resource Owner Password Credentials (Direct Access Grants) or Client Credentials. -/realms/{realm-name}/protocol/openid-connect/logout:: - This is the URL endpoint for performing logouts. -/realms/{realm-name}/protocol/openid-connect/userinfo:: - This is the URL endpoint for the User Info service described in the OIDC specification. -/realms/{realm-name}/protocol/openid-connect/revoke:: - This is the URL endpoint for OAuth 2.0 Token Revocation described in https://datatracker.ietf.org/doc/html/rfc7009[RFC7009]. -/realms/{realm-name}/protocol/openid-connect/certs:: - This is the URL endpoint for the JSON Web Key Set (JWKS) containing the public keys used to verify any JSON Web Token (jwks_uri) -/realms/{realm-name}/protocol/openid-connect/auth/device:: - This is the URL endpoint for Device Authorization Grant to obtain a device code and a user code. -/realms/{realm-name}/protocol/openid-connect/ext/ciba/auth:: - This is the URL endpoint for Client Initiated Backchannel Authentication Grant to obtain an auth_req_id that identifies the authentication request made by the client. -/realms/{realm-name}/protocol/openid-connect/logout/backchannel-logout:: - This is the URL endpoint for performing backchannel logouts described in the OIDC specification. - -In all of these replace _{realm-name}_ with the name of the realm. diff --git a/server_admin/topics/sso-protocols/ref-saml-vs-oidc.adoc b/server_admin/topics/sso-protocols/ref-saml-vs-oidc.adoc deleted file mode 100644 index e4b52d658..000000000 --- a/server_admin/topics/sso-protocols/ref-saml-vs-oidc.adoc +++ /dev/null @@ -1,21 +0,0 @@ -[id="ref-saml-vs-oidc_{context}"] - -=== OpenID Connect compared to SAML -[role="_abstract"] -The following lists a number of factors to consider when choosing a protocol. - -For most purposes, {project_name} recommends using OIDC. - -*OIDC* - -* OIDC is specifically designed to work with the web. -* OIDC is suited for HTML5/JavaScript applications because it is easier to implement on the client side than SAML. -* OIDC tokens are in the JSON format which makes them easier for Javascript to consume. -* OIDC has features to make security implementation easier. For example, see the link:https://openid.net/specs/openid-connect-session-1_0.html#ChangeNotification[iframe trick] that the specification uses to determine a users login status. - -*SAML* - -* SAML is designed as a layer to work on top of the web. -* SAML can be more verbose than OIDC. -* Users pick SAML over OIDC because there is a perception that it is mature. -* Users pick SAML over OIDC existing applications that are secured with it. diff --git a/server_admin/topics/templates b/server_admin/topics/templates deleted file mode 120000 index d19126411..000000000 --- a/server_admin/topics/templates +++ /dev/null @@ -1 +0,0 @@ -../../topics/templates \ No newline at end of file diff --git a/server_admin/topics/threat.adoc b/server_admin/topics/threat.adoc deleted file mode 100644 index 3c09664c7..000000000 --- a/server_admin/topics/threat.adoc +++ /dev/null @@ -1,4 +0,0 @@ - -== Mitigating security threats - -Security vulnerabilities exist in any authentication server. See the Internet Engineering Task Force's (IETF) https://datatracker.ietf.org/doc/html/rfc6819[OAuth 2.0 Threat Model] and the https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics-15[OAuth 2.0 Security Best Current Practice] for more information. diff --git a/server_admin/topics/threat/admin.adoc b/server_admin/topics/threat/admin.adoc deleted file mode 100644 index bc5aa6b12..000000000 --- a/server_admin/topics/threat/admin.adoc +++ /dev/null @@ -1,5 +0,0 @@ - -=== Admin endpoints and Admin Console - -{project_name} exposes the administrative REST API and the web console on the same port as non-administrative usage. -Do not expose administrative endpoints externally if external access is not necessary. diff --git a/server_admin/topics/threat/audience-limit.adoc b/server_admin/topics/threat/audience-limit.adoc deleted file mode 100644 index aeb3cf57a..000000000 --- a/server_admin/topics/threat/audience-limit.adoc +++ /dev/null @@ -1,5 +0,0 @@ - -=== Limit token audience - -In environments with low levels of trust among services, limit the audiences on the token. See the https://datatracker.ietf.org/doc/html/rfc6819#section-5.1.5.5[OAuth2 Threat Model] and the -<> section for more information. diff --git a/server_admin/topics/threat/auth-sessions-limit.adoc b/server_admin/topics/threat/auth-sessions-limit.adoc deleted file mode 100644 index 988d18ced..000000000 --- a/server_admin/topics/threat/auth-sessions-limit.adoc +++ /dev/null @@ -1,39 +0,0 @@ -[[_limit-authentication-sessions]] -=== Limit Authentication Sessions - -When a login page is opened for the first time in a web browser, {project_name} creates an object called authentication session that stores some useful information about the request. -Whenever a new login page is opened from a different tab in the same browser, {project_name} creates a new record called authentication sub-session that is stored within the authentication session. -Authentication requests can come from any type of clients such as the Admin CLI. In that case, a new authentication session is also created with one authentication sub-session. -Please note that authentication sessions can be created also in other ways than using a browser flow. The text below is applicable regardless of the source flow. - -NOTE: This section describes deployments that use the {jdgserver_name} provider for authentication sessions. - -Authentication session is internally stored as `RootAuthenticationSessionEntity`. Each `RootAuthenticationSessionEntity` can have multiple authentication sub-sessions stored within the -`RootAuthenticationSessionEntity` as a collection of `AuthenticationSessionEntity` objects. {project_name} stores authentication sessions in a dedicated {jdgserver_name} cache. -The number of `AuthenticationSessionEntity` per `RootAuthenticationSessionEntity` contributes to the size of each cache entry. Total memory footprint of authentication session cache is determined by -the number of stored `RootAuthenticationSessionEntity` and by the number of `AuthenticationSessionEntity` within each `RootAuthenticationSessionEntity`. - -The number of maintained `RootAuthenticationSessionEntity` objects corresponds to the number of unfinished login flows from the browser. To keep the number of `RootAuthenticationSessionEntity` -under control, using an advanced firewall control to limit ingress network traffic is recommended. - - -Higher memory usage may occur for deployments where there are many active `RootAuthenticationSessionEntity` with a lot of `AuthenticationSessionEntity`. -If the load balancer does not support or is not configured for session stickiness, the load over network in a cluster can -increase significantly. The reason for this load is that each request that lands on a node that does not own the appropriate authentication session needs to retrieve -and update the authentication session record in the owner node which involves a separate network transmission for both the retrieval and the storage. - -The maximum number of `AuthenticationSessionEntity` per `RootAuthenticationSessionEntity` can be configured in `authenticationSessions` SPI by setting property `authSessionsLimit`. The default value is set to 300 `AuthenticationSessionEntity` per a `RootAuthenticationSessionEntity`. When this limit is reached, the oldest authentication sub-session will be removed after a new authentication session request. - -The following example shows how to limit the number of active `AuthenticationSessionEntity` per a `RootAuthenticationSessionEntity` to 100. - -[source,bash] ----- -bin/kc.[sh|bat] start --spi-authentication-sessions-infinispan-auth-sessions-limit=100 ----- - -The equivalent command for the new map storage: - -[source,bash] ----- -bin/kc.[sh|bat] start --spi-authentication-sessions-map-auth-sessions-limit=100 ----- diff --git a/server_admin/topics/threat/brute-force.adoc b/server_admin/topics/threat/brute-force.adoc deleted file mode 100644 index 2ac674ce9..000000000 --- a/server_admin/topics/threat/brute-force.adoc +++ /dev/null @@ -1,103 +0,0 @@ - -[[password-guess-brute-force-attacks]] -=== Brute force attacks - -A brute force attack attempts to guess a user's password by trying to log in multiple times. {project_name} has brute force detection capabilities and can temporarily disable a user account if the number of login failures exceeds a specified threshold. - -[NOTE] -==== -{project_name} disables brute force detection by default. Enable this feature to protect against brute force attacks. -==== - -.Procedure - -To enable this protection: - -. Click *Realm Settings* in the menu -. Click the *Security Defenses* tab. -. Click the *Brute Force Detection* tab. -+ -.Brute force detection -image:images/brute-force.png[] - -{project_name} can deploy permanent lockout and temporary lockout actions when it detects an attack. Permanent lockout disables a user account until an administrator re-enables it. Temporary lockout disables a user account for a specific period of time. The time period that the account is disabled increases as the attack continues. - -[NOTE] -==== -When a user is temporarily locked and attempts to log in, {project_name} displays the default `Invalid username or password` error message. This message is the same error message as the message displayed for an invalid username or invalid password to ensure the attacker is unaware the account is disabled. -==== - -*Common Parameters* - -|=== -|Name |Description |Default - -|Max Login Failures -|The maximum number of login failures. -|30 failures. - -|Quick Login Check Milliseconds -|The minimum time between login attempts. -|1000 milliseconds. - -|Minimum Quick Login Wait -|The minimum time the user is disabled when login attempts are quicker than _Quick Login Check Milliseconds_. -|1 minute. - -|=== - -*Permanent Lockout Flow* -==== -. On successful login -.. Reset `count` -. On failed login -.. Increment `count` -.. If `count` greater than _Max Login Failures_ -... Permanently disable user -.. Else if the time between this failure and the last failure is less than _Quick Login Check Milliseconds_ -... Temporarily disable user for _Minimum Quick Login Wait_ - -When {project_name} disables a user, the user cannot log in until an administrator enables the user. Enabling an account resets the `count`. -==== - -*Temporary Lockout Parameters* - -|=== -|Name |Description |Default - -|Wait Increment -|The time added to the time a user is temporarily disabled when the user's login attempts exceed _Max Login Failures_. -|1 minute. - -|Max Wait -|The maximum time a user is temporarily disabled. -|15 minutes. - -|Failure Reset Time -|The time when the failure count resets. The timer runs from the last failed login. -|12 hours. - -|=== - -*Temporary Lockout Algorithm* -==== -. On successful login -.. Reset `count` -. On failed login -.. If the time between this failure and the last failure is greater than _Failure Reset Time_ -... Reset `count` -.. Increment `count` -.. Calculate `wait` using _Wait Increment_ * (`count` / _Max Login Failures_). The division is an integer division rounded down to a whole number -.. If `wait` equals 0 and the time between this failure and the last failure is less than _Quick Login Check Milliseconds_, set `wait` to _Minimum Quick Login Wait_. -... Temporarily disable the user for the smallest of `wait` and _Max Wait_ seconds - -`count` does not increment when a temporarily disabled account commits a login failure. -==== - -The downside of {project_name} brute force detection is that the server becomes vulnerable to denial of service attacks. When implementing a denial of service attack, an attacker can attempt to log in by guessing passwords for any accounts it knows and eventually causing {project_name} to disable the accounts. - -Consider using intrusion prevention software (IPS). {project_name} logs every login failure and client IP address failure. You can point the IPS to the {project_name} server's log file, and the IPS can modify firewalls to block connections from these IP addresses. - -==== Password policies - -Ensure you have a complex password policy to force users to choose complex passwords. See the <<_password-policies, Password Policies>> chapter for more information. Prevent password guessing by setting up the {project_name} server to use one-time-passwords. diff --git a/server_admin/topics/threat/clickjacking.adoc b/server_admin/topics/threat/clickjacking.adoc deleted file mode 100644 index bacdb8538..000000000 --- a/server_admin/topics/threat/clickjacking.adoc +++ /dev/null @@ -1,19 +0,0 @@ - -=== Clickjacking - -Clickjacking is a technique of tricking users into clicking on a user interface element different from what users perceive. A malicious site loads the target site in a transparent iFrame, overlaid on top of a set of dummy buttons placed directly under important buttons on the target site. When a user clicks a visible button, they are clicking a button on the hidden page. An attacker can steal a user's authentication credentials and access their resources by using this method. - -By default, every response by {project_name} sets some specific HTTP headers that can prevent this from happening. -Specifically, it sets https://datatracker.ietf.org/doc/html/rfc7034[X-Frame-Options] and https://www.w3.org/TR/CSP/[Content-Security-Policy]. -You should take a look at the definition of both of these headers as there is a lot of fine-grain browser access you can control. - -.Procedure -In the Admin Console, you can specify the values of the X-Frame-Options and Content-Security-Policy headers. - -. Click the *Realm Settings* menu item. -. Click the *Security Defenses* tab. -+ -.Security Defenses -image:images/security-headers.png[Security Defenses] - -By default, {project_name} only sets up a _same-origin_ policy for iframes. diff --git a/server_admin/topics/threat/compromised-codes.adoc b/server_admin/topics/threat/compromised-codes.adoc deleted file mode 100644 index 86ab88d9e..000000000 --- a/server_admin/topics/threat/compromised-codes.adoc +++ /dev/null @@ -1,8 +0,0 @@ - -=== Compromised authorization code - -For the xref:con-oidc-auth-flows_{context}[OIDC Auth Code Flow], {project_name} generates a cryptographically strong random value for its authorization codes. An authorization code is used only once to obtain an access token. - -On the <<_timeouts, timeouts page>> in the Admin Console, you can specify the length of time an authorization code is valid. Ensure that the length of time is less than 10 seconds, which is long enough for a client to request a token from the code. - -You can also defend against leaked authorization codes by applying <<_proof-key-for-code-exchange, Proof Key for Code Exchange (PKCE)>> to clients. diff --git a/server_admin/topics/threat/compromised-tokens.adoc b/server_admin/topics/threat/compromised-tokens.adoc deleted file mode 100644 index 45152cf3a..000000000 --- a/server_admin/topics/threat/compromised-tokens.adoc +++ /dev/null @@ -1,15 +0,0 @@ - -=== Compromised access and refresh tokens - -{project_name} includes several actions to prevent malicious actors from stealing access tokens and refresh tokens. The crucial action is to enforce SSL/HTTPS communication between {project_name} and its clients and applications. {project_name} does not enable SSL by default. - -Another action to mitigate damage from leaked access tokens is to shorten the token's lifespans. You can specify token lifespans within the <<_timeouts, timeouts page>>. Short lifespans for access tokens force clients and applications to refresh their access tokens after a short time. If an admin detects a leak, the admin can log out all user sessions to invalidate these refresh tokens or set up a revocation policy. - -Ensure refresh tokens always stay private to the client and are never transmitted. - -You can mitigate damage from leaked access tokens and refresh tokens by issuing these tokens as holder-of-key tokens. See <<_mtls-client-certificate-bound-tokens, OAuth 2.0 Mutual TLS Client Certificate Bound Access Token>> for more information. - -If an access token or refresh token is compromised, access the Admin Console and push a not-before revocation policy to all applications. Pushing a not-before policy ensures that any tokens issued before that time become invalid. -Pushing a new not-before policy ensures that applications must download new public keys from {project_name} and mitigate damage from a compromised realm signing key. See the <> for more information. - -You can disable specific applications, clients, or users if they are compromised. diff --git a/server_admin/topics/threat/csrf.adoc b/server_admin/topics/threat/csrf.adoc deleted file mode 100644 index f5d3358c9..000000000 --- a/server_admin/topics/threat/csrf.adoc +++ /dev/null @@ -1,10 +0,0 @@ - -=== CSRF attacks - -A Cross-site request forgery (CSRF) attack uses HTTP requests from users that websites have already authenticated. Any site using cookie-based authentication is vulnerable to CSRF attacks. You can mitigate these attacks by matching a state cookie against a posted form or query parameter. - -The OAuth 2.0 login specification requires that a state cookie matches against a transmitted state parameter. {project_name} fully implements this part of the specification, so all logins are protected. - -The {project_name} Admin Console is a JavaScript/HTML5 application that makes REST calls to the backend {project_name} admin REST API. These calls all require bearer token authentication and consist of JavaScript Ajax calls, so CSRF is impossible. You can configure the admin REST API to validate the CORS origins. - -The user account management section in {project_name} can be vulnerable to CSRF. To prevent CSRF attacks, {project_name} sets a state cookie and embeds the value of this cookie in hidden form fields or query parameters within action links. {project_name} checks the query/form parameter against the state cookie to verify that the user makes the call. diff --git a/server_admin/topics/threat/fapi-compliance.adoc b/server_admin/topics/threat/fapi-compliance.adoc deleted file mode 100644 index 6330fa717..000000000 --- a/server_admin/topics/threat/fapi-compliance.adoc +++ /dev/null @@ -1,7 +0,0 @@ - -=== FAPI compliance - -To make sure that {project_name} server will validate your client to be more secure and FAPI compliant, you can configure client policies -for the FAPI support. Details are described in the FAPI section of link:{adapterguide_link}#_fapi-support[{adapterguide_name}]. Among other things, this ensures some security best practices -described above like SSL required for clients, secure redirect URI used and more of similar best practices. - diff --git a/server_admin/topics/threat/host.adoc b/server_admin/topics/threat/host.adoc deleted file mode 100644 index db25cb1b7..000000000 --- a/server_admin/topics/threat/host.adoc +++ /dev/null @@ -1,8 +0,0 @@ - -=== Host - -{project_name} uses the public hostname in several ways, such as within token issuer fields and URLs in password reset emails. - -By default, the hostname derives from request headers. No validation exists to ensure a hostname is valid. If you are not using a load balancer, or proxy, with {project_name} to prevent invalid host headers, configure the acceptable hostnames. - -The hostname's Service Provider Interface (SPI) provides a way to configure the hostname for requests. You can use this built-in provider to set a fixed URL for frontend requests while allowing backend requests based on the request URI. If the built-in provider does not have the required capability, you can develop a customized provider. diff --git a/server_admin/topics/threat/open-redirect.adoc b/server_admin/topics/threat/open-redirect.adoc deleted file mode 100644 index 98a08705c..000000000 --- a/server_admin/topics/threat/open-redirect.adoc +++ /dev/null @@ -1,6 +0,0 @@ - -=== Open redirectors - -An open redirector is an endpoint using a parameter to automatically redirect a user agent to the location specified by the parameter value without validation. An attacker can use the end-user authorization endpoint and the redirect URI parameter to use the authorization server as an open redirector, using a user's trust in an authorization server to launch a phishing attack. - -{project_name} requires that all registered applications and clients register at least one redirection URI pattern. When a client requests that {project_name} performs a redirect, {project_name} checks the redirect URI against the list of valid registered URI patterns. Clients and applications must register as specific a URI pattern as possible to mitigate open redirector attacks. diff --git a/server_admin/topics/threat/password-db-compromised.adoc b/server_admin/topics/threat/password-db-compromised.adoc deleted file mode 100644 index 0d19b566a..000000000 --- a/server_admin/topics/threat/password-db-compromised.adoc +++ /dev/null @@ -1,4 +0,0 @@ - -=== Password database compromised - -{project_name} does not store passwords in raw text but as hashed text, using the PBKDF2 hashing algorithm. {project_name} performs 27,500 hashing iterations, the number of iterations recommended by the security community. This number of hashing iterations can adversely affect performance as PBKDF2 hashing uses a significant amount of CPU resources. \ No newline at end of file diff --git a/server_admin/topics/threat/read-only-attributes.adoc b/server_admin/topics/threat/read-only-attributes.adoc deleted file mode 100644 index 11e609708..000000000 --- a/server_admin/topics/threat/read-only-attributes.adoc +++ /dev/null @@ -1,43 +0,0 @@ -[[_read_only_user_attributes]] -=== Read-only user attributes - -Typical users who are stored in {project_name} have various attributes related to their user profiles. Such attributes include email, firstName or lastName. -However users may also have attributes, which are not typical profile data, but rather metadata. The metadata attributes usually should be read-only for the users -and the typical users never should have a way to update those attributes from the {project_name} user interface or Account REST API. Some of the attributes should -be even read-only for the administrators when creating or updating user with the Admin REST API. - -The metadata attributes are usually attributes from those groups: - -* Various links or metadata related to the user storage providers. For example in case of the LDAP integration, the `LDAP_ID` attribute contains -the ID of the user in the LDAP server. -* Metadata provisioned by User Storage. For example `createdTimestamp` provisioned from the LDAP should be always read-only by user or administrator. -* Metadata related to various authenticators. For example `KERBEROS_PRINCIPAL` attribute can contain the kerberos principal name of the particular user. Similarly attribute -`usercertificate` can contain metadata related to binding the user with the data from the X.509 certificate, which is used typically when X.509 certificate authentication is enabled. -* Metadata related to the identificator of users by the applications/clients. For example `saml.persistent.name.id.for.my_app` can contain SAML NameID, which will -be used by the client application `my_app` as the identifier of the user. -* Metadata related to the authorization policies, which are used for the attribute based access control (ABAC). Values of those attributes may be used for the -authorization decisions. Hence it is important that those attributes cannot be updated by the users. - -From the long term perspective, {project_name} will have a proper User Profile SPI, which will allow fine-grained configuration of every user attribute. Currently -this capability is not fully available yet. So {project_name} has the internal list of user attributes, which are read-only for the users and read-only for the administrators configured -at the server level. - -This is the list of the read-only attributes, which are used internally by the {project_name} default providers and functionalities and hence are always read-only: - -* For users: `KERBEROS_PRINCIPAL`, `LDAP_ID`, `LDAP_ENTRY_DN`, `CREATED_TIMESTAMP`, `createTimestamp`, `modifyTimestamp`, `userCertificate`, `saml.persistent.name.id.for.*`, `ENABLED`, `EMAIL_VERIFIED` -* For administrators: `KERBEROS_PRINCIPAL`, `LDAP_ID`, `LDAP_ENTRY_DN`, `CREATED_TIMESTAMP`, `createTimestamp`, `modifyTimestamp` - -System administrators have a way to add additional attributes to this list. The configuration is currently available at the server level. - -You can add this configuration by using the `spi-user-profile-legacy-user-profile-read-only-attributes` and ``spi-user-profile-legacy-user-profile-admin-read-only-attributes` options. For example: - -[source,bash,options="nowrap"] ----- -kc.[sh|bat] start --spi-user-profile-legacy-user-profile-read-only-attributes=foo,bar* ----- - -For this example, users and administrators would not be able to update attribute `foo`. Users would not be able to edit any attributes starting with the `bar`. -So for example `bar` or `barrier`. Configuration is case-insensitive, so attributes like `FOO` or `BarRier` will be denied as well for this example. The wildcard character `\*` is supported -only at the end of the attribute name, so the administrator can effectively deny all the attributes starting with the specified character. The `*` in the middle of the attribute is considered -as a normal character. - diff --git a/server_admin/topics/threat/redirect.adoc b/server_admin/topics/threat/redirect.adoc deleted file mode 100644 index eeca92d71..000000000 --- a/server_admin/topics/threat/redirect.adoc +++ /dev/null @@ -1,5 +0,0 @@ - -[id="unspecific-redirect-uris_{context}"] -=== Unspecific redirect URIs - -Make your registered redirect URIs as specific as feasible. Registering vague redirect URIs for xref:con-oidc-auth-flows_{context}[Authorization Code Flows] can allow malicious clients to impersonate another client with broader access. Impersonation can happen if two clients live under the same domain, for example. diff --git a/server_admin/topics/threat/scope.adoc b/server_admin/topics/threat/scope.adoc deleted file mode 100644 index 6681551ce..000000000 --- a/server_admin/topics/threat/scope.adoc +++ /dev/null @@ -1,6 +0,0 @@ - -=== Limiting scope - -By default, new client applications have unlimited `role scope mappings`. Every access token for that client contains all permissions that the user has. If an attacker compromises the client and obtains the client's access tokens, each system that the user can access is compromised. - -Limit the roles of an access token by using the <<_role_scope_mappings, Scope menu>> for each client. Alternatively, you can set role scope mappings at the Client Scope level and assign Client Scopes to your client by using the <<_client_scopes_linking, Client Scope menu>>. diff --git a/server_admin/topics/threat/sql.adoc b/server_admin/topics/threat/sql.adoc deleted file mode 100644 index 7ac18a716..000000000 --- a/server_admin/topics/threat/sql.adoc +++ /dev/null @@ -1,4 +0,0 @@ - -=== SQL injection attacks - -Currently, {project_name} has no known SQL injection vulnerabilities. diff --git a/server_admin/topics/threat/ssl.adoc b/server_admin/topics/threat/ssl.adoc deleted file mode 100644 index 31827d3fd..000000000 --- a/server_admin/topics/threat/ssl.adoc +++ /dev/null @@ -1,8 +0,0 @@ - -=== SSL/HTTPS requirement - -OAuth 2.0/OpenID Connect uses access tokens for security. Attackers can scan your network for access tokens and use them to perform malicious operations for which the token has permission. This attack is known as a man-in-the-middle attack. Use SSL/HTTPS for communication between the {project_name} auth server and the clients {project_name} secures to prevent man-in-the-middle attacks. - -{project_name} has <<_ssl_modes,three modes for SSL/HTTPS>>. SSL is complex to set up, so {project_name} allows non-HTTPS communication over private IP addresses such as localhost, 192.168.x.x, and other private IP addresses. In production, ensure you enable SSL and SSL is compulsory for all operations. - -On the adapter/client-side, you can disable the SSL trust manager. The trust manager ensures the client's identity that {project_name} communicates with is valid and ensures the DNS domain name against the server's certificate. In production, ensure that each of your client adapters uses a truststore to prevent DNS man-in-the-middle attacks. diff --git a/server_admin/topics/user-federation.adoc b/server_admin/topics/user-federation.adoc deleted file mode 100644 index 41d4a1c6b..000000000 --- a/server_admin/topics/user-federation.adoc +++ /dev/null @@ -1,33 +0,0 @@ -[[_user-storage-federation]] - -== Using external storage - -[role="_abstract"] -Organizations can have databases containing information, passwords, and other credentials. Typically, you cannot migrate existing data storage to a {project_name} deployment so {project_name} can federate existing external user databases. {project_name} supports LDAP and Active Directory, but you can also code extensions for any custom user database by using the {project_name} User Storage SPI. - -When a user attempts to log in, {project_name} examines that user's storage to find that user. If {project_name} does not find the user, {project_name} iterates over each User Storage provider for the realm until it finds a match. Data from the external data storage then maps into a standard user model the {project_name} runtime consumes. This user model then maps to OIDC token claims and SAML assertion attributes. - -External user databases rarely have the data necessary to support all the features of {project_name}, so the User Storage Provider can opt to store items locally in {project_name} user data storage. Providers can import users locally and sync periodically with external data storage. This approach depends on the capabilities of the provider and the configuration of the provider. For example, your external user data storage may not support OTP. The OTP can be handled and stored by {project_name}, depending on the provider. - -=== Adding a provider -To add a storage provider, perform the following procedure: - -.Procedure -. Click *User Federation* in the menu. -+ -.User federation -image:images/user-federation.png[User federation] -+ -. Select the provider type card from the listed cards. -+ -{project_name} brings you to that provider's configuration page. - -=== Dealing with provider failures - -If a User Storage Provider fails, you may not be able to log in and view users in the Admin Console. {project_name} does not detect failures when using a Storage Provider to look up a user, so it cancels the invocation. If you have a Storage Provider with a high priority that fails during user lookup, the login or user query fails with an exception and will not fail over to the next configured provider. - -{project_name} searches the local {project_name} user database first to resolve users before any LDAP or custom User Storage Provider. Consider creating an administrator account stored in the local {project_name} user database in case of problems connecting to your LDAP and back ends. - -Each LDAP and custom User Storage Provider has an `enable` toggle on its Admin Console page. Disabling the User Storage Provider skips the provider when performing queries, so you can view and log in with user accounts in a different provider with lower priority. If your provider uses an `import` strategy and is disabled, imported users are still available for lookup in read-only mode. - -When a Storage Provider lookup fails, {project_name} does not fail over because user databases often have duplicate usernames or duplicate emails between them. Duplicate usernames and emails can cause problems because the user loads from one external data store when the admin expects them to load from another data store. diff --git a/server_admin/topics/user-federation/custom.adoc b/server_admin/topics/user-federation/custom.adoc deleted file mode 100644 index daf105cba..000000000 --- a/server_admin/topics/user-federation/custom.adoc +++ /dev/null @@ -1,4 +0,0 @@ - -=== Custom providers - -{project_name} does have a Service Provider Interface (SPI) for User Storage Federation to develop custom providers. You can find documentation on developing customer providers in the link:{developerguide_link}[{developerguide_name}]. diff --git a/server_admin/topics/user-federation/ldap.adoc b/server_admin/topics/user-federation/ldap.adoc deleted file mode 100644 index f767e39f9..000000000 --- a/server_admin/topics/user-federation/ldap.adoc +++ /dev/null @@ -1,190 +0,0 @@ -[[_ldap]] - -=== Lightweight Directory Access Protocol (LDAP) and Active Directory - -{project_name} includes an LDAP/AD provider. You can federate multiple different LDAP servers in one {project_name} realm and map LDAP user attributes into the {project_name} common user model. - -By default, {project_name} maps the username, email, first name, and last name of the user account, but you can also configure additional <<_ldap_mappers,mappings>>. {project_name}'s LDAP/AD provider supports password validation using LDAP/AD protocols and storage, edit, and synchronization modes. - -==== Configuring federated LDAP storage - -.Procedure -. Click *User Federation* in the menu. -+ -.User federation -image:images/user-federation.png[User federation] -+ -. Click *Add LDAP providers*. -+ -{project_name} brings you to the LDAP configuration page. - -==== Storage mode - -{project_name} imports users from LDAP into the local {project_name} user database. This copy of the user database synchronizes on-demand or through a periodic background task. An exception exists for synchronizing passwords. {project_name} never imports passwords. Password validation always occurs on the LDAP server. - -The advantage of synchronization is that all {project_name} features work efficiently because any required extra per-user data is stored locally. The disadvantage is that each time {project_name} queries a specific user for the first time, {project_name} performs a corresponding database insert. - -You can synchronize the import with your LDAP server. Import synchronization is unnecessary when LDAP mappers always read particular attributes from the LDAP rather than the database. - -You can use LDAP with {project_name} without importing users into the {project_name} user database. The LDAP server backs up the common user model that the {project_name} runtime uses. If LDAP does not support data that a {project_name} feature requires, that feature will not work. The advantage of this approach is that you do not have the resource usage of importing and synchronizing copies of LDAP users into the {project_name} user database. - -The *Import Users* switch on the LDAP configuration page controls this storage mode. To import users, toggle this switch to *ON*. - -[NOTE] -==== -If you disable *Import Users*, you cannot save user profile attributes into the {project_name} database. Also, you cannot save metadata except for user profile metadata mapped to the LDAP. This metadata can include role mappings, group mappings, and other metadata based on the LDAP mappers' configuration. - -When you attempt to change the non-LDAP mapped user data, the user update is not possible. For example, you cannot disable the LDAP mapped user unless the user's `enabled` flag maps to an LDAP attribute. -==== - -==== Edit mode - -Users and admins can modify user metadata, users through the <<_account-service, Account Console>>, and administrators through the Admin Console. The `Edit Mode` configuration on the LDAP configuration page defines the user's LDAP update privileges. - -READONLY:: -You cannot change the username, email, first name, last name, and other mapped attributes. {project_name} shows an error anytime a user attempts to update these fields. Password updates are not supported. - -WRITABLE:: -You can change the username, email, first name, last name, and other mapped attributes and passwords and synchronize them automatically with the LDAP store. - -UNSYNCED:: -{project_name} stores changes to the username, email, first name, last name, and passwords in {project_name} local storage, so the administrator must synchronize this data back to LDAP. In this mode, {project_name} deployments can update user metadata on read-only LDAP servers. This option also applies when importing users from LDAP into the local {project_name} user database. - -[NOTE] -==== -When {project_name} creates the LDAP provider, {project_name} also creates a set of initial <<_ldap_mappers,LDAP mappers>>. {project_name} configures these mappers based on a combination of the *Vendor*, *Edit Mode*, and *Import Users* switches. For example, when edit mode is UNSYNCED, {project_name} configures the mappers to read a particular user attribute from the database and not from the LDAP server. However, if you later change the edit mode, the mapper's configuration does not change because it is impossible to detect if the configuration changes changed in UNSYNCED mode. Decide the *Edit Mode* when creating the LDAP provider. This note applies to *Import Users* switch also. -==== - -==== Other configuration options - -Console Display Name:: -The name of the provider to display in the admin console. - -Priority:: -The priority of the provider when looking up users or adding a user. - -Sync Registrations:: -Toggle this switch to *ON* if you want new users created by {project_name} added to LDAP. - -Allow Kerberos authentication:: -Enable Kerberos/SPNEGO authentication in the realm with user data provisioned from LDAP. For more information, see the <<_kerberos,Kerberos section>>. - -Other options:: -Hover the mouse pointer over the tooltips in the Admin Console to see more details about these options. - -==== Connecting to LDAP over SSL - -When you configure a secure connection URL to your LDAP store (for example,`ldaps://myhost.com:636`), {project_name} uses SSL to communicate with the LDAP server. Configure a truststore on the {project_name} server side so that {project_name} can trust the SSL connection to LDAP. - -Configure the global truststore for {project_name} with the Truststore SPI. For more information about configuring the global truststore, see the [Configuring a Truststore](https://www.keycloak.org/server/keycloak-truststore) guide. If you do not configure the Truststore SPI, the truststore falls back to the default mechanism provided by Java, which can be the file supplied by the `javax.net.ssl.trustStore` system property or the cacerts file from the JDK if the system property is unset. - -The `Use Truststore SPI` configuration property, in the LDAP federation provider configuration, controls the truststore SPI. By default, {project_name} sets the property to `Only for ldaps`, which is adequate for most deployments. {project_name} uses the Truststore SPI if the connection URL to LDAP starts with `ldaps` only. - -==== Synchronizing LDAP users to {project_name} - -If you set the *Import Users* option, the LDAP Provider handles importing LDAP users into the {project_name} local database. The first time a user logs in, the LDAP provider imports the LDAP user into the {project_name} database and validates the LDAP password. This first time a user logs in is the only time {project_name} imports the user. If you click the *Users* menu in the Admin Console and click the *View all users* button, you only see the LDAP users authenticated at least once by {project_name}. {project_name} imports users this way, so this operation does not trigger an import of the entire LDAP user database. - -If you want to sync all LDAP users into the {project_name} database, configure and enable the *Sync Settings* on the LDAP provider configuration page. - -Two types of synchronization exist: - -Periodic Full sync:: -This type synchronizes all LDAP users into the {project_name} database. The LDAP users already in {project_name}, but different in LDAP, directly update in the {project_name} database. - -Periodic Changed users sync:: -When synchronizing, {project_name} creates or updates users created or updated after the last sync only. - -The best way to synchronize is to click *Synchronize all users* when you first create the LDAP provider, then set up periodic synchronization of changed users. - -[[_ldap_mappers]] -==== LDAP mappers - -LDAP mappers are `listeners` triggered by the LDAP Provider. They provide another extension point to LDAP integration. LDAP mappers are triggered when: - -* Users log in by using LDAP. -* Users initially register. -* The Admin Console queries a user. - -When you create an LDAP Federation provider, {project_name} automatically provides a set of `mappers` for this provider. This set is changeable by users, who can also develop mappers or update/delete existing ones. - -User Attribute Mapper:: -This mapper specifies which LDAP attribute maps to the attribute of the {project_name} user. For example, you can configure the `mail` LDAP attribute to the `email` attribute in the {project_name} database. For this mapper implementation, a one-to-one mapping always exists. - -FullName Mapper:: -This mapper specifies the full name of the user. {project_name} saves the name in an LDAP attribute (usually `cn`) and maps the name to the `firstName` and `lastname` attributes in the {project_name} database. Having `cn` to contain the full name of the user is common for LDAP deployments. - -[NOTE] -==== -When you register new users in {project_name} and `Sync Registrations` is ON for the LDAP provider, the fullName mapper permits falling back to the username. This fallback is useful when using Microsoft Active Directory (MSAD). The common setup for MSAD is to configure the `cn` LDAP attribute as fullName and, at the same time, use the `cn` LDAP attribute as the `RDN LDAP Attribute` in the LDAP provider configuration. With this setup, {project_name} falls back to the username. For example, if you create {project_name} user "john123" and leave firstName and lastName empty, then the fullname mapper saves "john123" as the value of the `cn` in LDAP. When you enter "John Doe" for firstName and lastName later, the fullname mapper updates LDAP `cn` to the "John Doe" value as falling back to the username is unnecessary. -==== - -Hardcoded Attribute Mapper:: -This mapper adds a hardcoded attribute value to each {project_name} user linked with LDAP. This mapper can also force values for the `enabled` or `emailVerified` user properties. - -Role Mapper:: -This mapper configures role mappings from LDAP into {project_name} role mappings. A single role mapper can map LDAP roles (usually groups from a particular branch of the LDAP tree) into roles corresponding to a specified client's realm roles or client roles. You can configure more Role mappers for the same LDAP provider. For example, you can specify that role mappings from groups under `ou=main,dc=example,dc=org` map to realm role mappings, and role mappings from groups under `ou=finance,dc=example,dc=org` map to client role mappings of client `finance`. - -Hardcoded Role Mapper:: -This mapper grants a specified {project_name} role to each {project_name} user from the LDAP provider. - -Group Mapper:: -This mapper maps LDAP groups from a branch of an LDAP tree into groups within {project_name}. This mapper also propagates user-group mappings from LDAP into user-group mappings in {project_name}. - -MSAD User Account Mapper:: -This mapper is specific to Microsoft Active Directory (MSAD). It can integrate the MSAD user account state into the {project_name} account state, such as enabled account or expired password. This mapper uses the `userAccountControl`, and `pwdLastSet` LDAP attributes, specific to MSAD and are not the LDAP standard. For example, if the value of `pwdLastSet` is `0`, the {project_name} user must update their password. The result is an UPDATE_PASSWORD required action added to the user. If the value of `userAccountControl` is `514` (disabled account), the {project_name} user is disabled. - -Certificate Mapper:: -This mapper maps X.509 certificates. {project_name} uses it in conjunction with X.509 authentication and `Full certificate in PEM format` as an identity source. This mapper behaves similarly to the `User Attribute Mapper`, but {project_name} can filter for an LDAP attribute storing a PEM or DER format certificate. Enable `Always Read Value From LDAP` with this mapper. - -User Attribute mappers that map basic {project_name} user attributes, such as username, firstname, lastname, and email, to corresponding LDAP attributes. You can extend these and provide your own additional attribute mappings. The Admin Console provides tooltips to help with configuring the corresponding mappers. - -[[_ldap_password_hashing]] -==== Password hashing - -When {project_name} updates a password, {project_name} sends the password in plain-text format. This action is different from updating the password in the built-in {project_name} database, where {project_name} hashes and salts the password before sending it to the database. For LDAP, {project_name} relies on the LDAP server to hash and salt the password. - -By default, LDAP servers such as MSAD, RHDS, or FreeIPA hash and salt passwords. Other LDAP servers such as OpenLDAP or ApacheDS store the passwords in plain-text unless you use the _LDAPv3 Password Modify Extended Operation_ as described in https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.3[RFC3062]. Enable the LDAPv3 Password Modify Extended Operation in the LDAP configuration page. See the documentation of your LDAP server for more details. - -WARNING: Always verify that user passwords are properly hashed and not stored as plaintext by inspecting a changed -directory entry using `ldapsearch` and base64 decode the `userPassword` attribute value. - -[[_ldap_troubleshooting]] -==== Troubleshooting - -It is useful to increase the logging level to TRACE for the category `org.keycloak.storage.ldap`. With this setting, many logging messages are sent -to the server log in the `TRACE` level, including the logging for all queries to the LDAP server and the parameters, which were -used to send the queries. When you are creating any LDAP question on user forum or JIRA, consider attaching the server log with -enabled TRACE logging. If it is too big, the good alternative is to include just the snippet from server log with the messages, which were -added to the log during the operation, which causes the issues to you. - - -- When you create an LDAP provider, a message appears in the server log in the INFO level starting with: - - -``` -Creating new LDAP Store for the LDAP storage provider: ... -``` -It shows the configuration of your LDAP provider. Before you are asking the questions or reporting bugs, it will be nice to include this -message to show your LDAP configuration. Eventually feel free to replace some config changes, which you do not want to include, with some -placeholder values. One example is `bindDn=some-placeholder` . For `connectionUrl`, feel free to replace it as well, but it is generally -useful to include at least the protocol, which was used (`ldap` vs `ldaps`)`. Similarly it can be useful to include the details for -configuration of your LDAP mappers, which are displayed with the message like this at the DEBUG level: -``` -Mapper for provider: XXX, Mapper name: YYY, Provider: ZZZ ... -``` -Note those messages are displayed just with the enabled DEBUG logging. - -- For tracking the performance or connection pooling issues, consider setting the value of property `Connection Pool Debug Level` of -the LDAP provider to value `all`. This will add lots of additional messages to server log with the included logging for the LDAP connection -pooling. This can be used to track the issues related to connection pooling or performance. - -NOTE: After changing the configuration of connection pooling, you may need to restart the Keycloak server to enforce re-initialization -of the LDAP provider connection. - -If no more messages appear for connection pooling even after server restart, it can indicate that connection pooling does not work -with your LDAP server. - -- For the case of reporting LDAP issue, you may consider to attach some part of your LDAP tree with the target data, which causes issues -in your environment. For example if login of some user takes lot of time, you can consider attach his LDAP entry showing count of `member` attributes -of various "group" entries. In this case, it might be useful to add if those group entries are mapped to some Group LDAP mapper (or Role LDAP Mapper) -in {project_name} etc. diff --git a/server_admin/topics/user-federation/sssd.adoc b/server_admin/topics/user-federation/sssd.adoc deleted file mode 100644 index 36ec7ceca..000000000 --- a/server_admin/topics/user-federation/sssd.adoc +++ /dev/null @@ -1,196 +0,0 @@ - -[[_sssd]] - -=== SSSD and FreeIPA Identity Management integration - -{project_name} includes the https://fedoraproject.org/wiki/Features/SSSD[System Security Services Daemon (SSSD)] plugin. SSSD is part of the Fedora and Red Hat Enterprise Linux (RHEL), and it provides access to multiple identities and authentication providers. SSSD also provides benefits such as failover and offline support. For more information, see https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/system-level_authentication_guide/sssd[the Red Hat Enterprise Linux Identity Management documentation]. - -SSSD integrates with the FreeIPA identity management (IdM) server, providing authentication and access control. With this integration, {project_name} can authenticate against privileged access management (PAM) services and retrieve user data from SSSD. For more information about using Red Hat Identity Management in Linux environments, see https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/linux_domain_identity_authentication_and_policy_guide/index[the Red Hat Enterprise Linux Identity Management documentation]. - -image:images/keycloak-sssd-freeipa-integration-overview.png[] - -{project_name} and SSSD communicate through read-only D-Bus interfaces. For this reason, the way to provision and update users is to use the FreeIPA/IdM administration interface. By default, the interface imports the username, email, first name, and last name. - -[NOTE] -==== -{project_name} registers groups and roles automatically but does not synchronize them. Any changes made by the {project_name} administrator in {project_name} do not synchronize with SSSD. -==== - -==== FreeIPA/IdM server - -The https://hub.docker.com/r/freeipa/freeipa-server/[FreeIPA Docker image] is available in Docker Hub. To set up the FreeIPA server, see the https://www.freeipa.org/page/Quick_Start_Guide[FreeIPA documentation]. - -.Procedure -. Run your FreeIPA server using this command: -+ -[source,bash,subs=+attributes] ----- - docker run --name freeipa-server-container -it \ - -h server.freeipa.local -e PASSWORD=YOUR_PASSWORD \ - -v /sys/fs/cgroup:/sys/fs/cgroup:ro \ - -v /var/lib/ipa-data:/data:Z freeipa/freeipa-server ----- -+ -The parameter `-h` with `server.freeipa.local` represents the FreeIPA/IdM server hostname. -Change `YOUR_PASSWORD` to a password of your own. - -. After the container starts, change the `/etc/hosts` file to include: -+ -[source,bash,subs=+attributes] ----- -x.x.x.x server.freeipa.local ----- -+ -If you do not make this change, you must set up a DNS server. - -. Use the following command to enroll your Linux server in the IPA domain so that the SSSD federation provider starts and runs on {project_name}: -+ -[source,bash,subs=+attributes] ----- - ipa-client-install --mkhomedir -p admin -w password ----- - -. Run the following command on the client to verify the installation is working: -+ -[source,bash,subs=+attributes] ----- - kinit admin ----- - -. Enter your password. -. Add users to the IPA server using this command: -+ -[source,bash,subs=+attributes] ----- -$ ipa user-add --first= --last= --email= --phone= --street= \ --city= --state= --postalcode= --password ----- - -. Force set the user's password using kinit. -+ -[source,bash,subs=+attributes] ----- - kinit ----- - -. Enter the following to restore normal IPA operation: -+ -[source,bash,subs=+attributes] ----- -kdestroy -A -kinit admin ----- - -==== SSSD and D-Bus - -The federation provider obtains the data from SSSD using D-BUS. It authenticates the data using PAM. - -.Procedure -. Install the sssd-dbus RPM. -+ -[source,bash,subs=+attributes] ----- -$ sudo yum install sssd-dbus ----- - -. Run the following provisioning script: -+ -[source,bash,subs=+attributes] ----- -$ bin/federation-sssd-setup.sh ----- -+ -This script makes the following changes to `/etc/sssd/sssd.conf`: -+ -[source,bash,subs=+attributes] ----- - [domain/your-hostname.local] - ... - ldap_user_extra_attrs = mail:mail, sn:sn, givenname:givenname, telephoneNumber:telephoneNumber - ... - [sssd] - services = nss, sudo, pam, ssh, ifp - ... - [ifp] - allowed_uids = root, yourOSUsername - user_attributes = +mail, +telephoneNumber, +givenname, +sn ----- - -. Run `dbus-send` to ensure the setup is successful. -+ -[source,bash,subs=+attributes] ----- -sudo dbus-send --print-reply --system --dest=org.freedesktop.sssd.infopipe /org/freedesktop/sssd/infopipe org.freedesktop.sssd.infopipe.GetUserGroups string:john ----- -+ -If the setup is successful, you see the user's group. If this command returns a timeout or an error, the federation provider running on {project_name} cannot retrieve any data. This error usually happens because the server is not enrolled in the FreeIPA IdM server, or does not have permission to access the SSSD service. -+ -If you do not have permission to access the SSSD service, ensure that the user running the {project_name} server is in the `/etc/sssd/sssd.conf` file in the following section: -+ -[source,bash,subs=+attributes] ----- -[ifp] -allowed_uids = root, your_username ----- - -==== Enabling the SSSD federation provider - -{project_name} uses DBus-Java to communicate at a low level with D-Bus. D-Bus depends on the http://www.matthew.ath.cx/projects/java/[Unix Sockets Library]. - -ifeval::[{project_community}==true] - -You can find an RPM for this library in https://github.com/keycloak/libunix-dbus-java/releases[the keycloak repository]. Before installing this RPM, check the RPM signature using this command: - -[source,bash,subs=+attributes] ----- - $ rpm -K libunix-dbus-java-0.8.0-1.fc24.x86_64.rpm - libunix-dbus-java-0.8.0-1.fc24.x86_64.rpm: - Header V4 RSA/SHA256 Signature, key ID 84dc9914: OK - Header SHA1 digest: OK (d17bb7ebaa7a5304c1856ee4357c8ba4ec9c0b89) - V4 RSA/SHA256 Signature, key ID 84dc9914: OK - MD5 digest: OK (770c2e68d052cb4a4473e1e9fd8818cf) ----- - -Install the RPM using this command: - -[source,bash,subs=+attributes] ----- -$ sudo yum install libunix-dbus-java-0.8.0-1.fc24.x86_64.rpm ----- - -endif::[] - -ifeval::[{project_product}==true] - -Before enabling the SSSD Federation provider, install the RPM for this library: - -[source,bash,subs=+attributes] ----- -$ sudo yum install rh-sso7-libunix-dbus-java ----- - -endif::[] - -{project_name} uses JNA to authenticate with PAM. Ensure you have the JAN package installed. - -[source,bash,subs=+attributes] ----- -$ sudo yum install jna - ----- - -Use the `sssctl user-checks` command to validate your setup: -[source] ----- - $ sudo sssctl user-checks admin -s keycloak ----- - -=== Configuring a federated SSSD store - -After the installation, configure a federated SSSD store. - -.Procedure -. Click *User Federation* in the menu. -. From the *Add Provider* list select _sssd_. {project_name} brings you to the sssd configuration page. -. Click *Save*. - -You can now authenticate against {project_name} using FreeIPA/IdM credentials. diff --git a/server_admin/topics/users/con-required-actions.adoc b/server_admin/topics/users/con-required-actions.adoc deleted file mode 100644 index d5ed18919..000000000 --- a/server_admin/topics/users/con-required-actions.adoc +++ /dev/null @@ -1,23 +0,0 @@ -// Module included in the following assemblies: -// -// server_admin/topics/users.adoc - -[id="con-required-actions_{context}"] -= Defining actions required at login - -You can set the actions that a user must perform at the first login. These actions are required after the user provides credentials. After the first login, these actions are no longer required. You add required actions on the *Details* tab of that user. - -The following are examples of required action types: - -Update Password:: - The user must change their password. - -Configure OTP:: - The user must configure a one-time password generator on their mobile device using either the Free OTP or Google Authenticator application. - -Verify Email:: - The user must verify their email account. An email will be sent to the user with a validation link that they must click. Once this workflow is successfully completed, the user will be allowed to log in. - -Update Profile:: - The user must update profile information, such as name, address, email, and phone number. - diff --git a/server_admin/topics/users/con-user-impersonation.adoc b/server_admin/topics/users/con-user-impersonation.adoc deleted file mode 100644 index 419dbe2fe..000000000 --- a/server_admin/topics/users/con-user-impersonation.adoc +++ /dev/null @@ -1,25 +0,0 @@ -// Module included in the following assemblies: -// -// server_admin/topics/users.adoc - -[id="con-user-impersonation_{context}"] -= Impersonating a user - -An administrator with the appropriate permissions can impersonate a user. For example, if a user experiences a bug in an application, an administrator can impersonate the user to investigate or duplicate the issue. - -Any user with the `impersonation` role in the realm can impersonate a user. - -.Procedure -. Click *Users* in the menu. -. Click a user to impersonate. -. From the *Actions* list, select *Impersonate*. -+ -image:images/user-details.png[] - -* If the administrator and the user are in the same realm, then the administrator will be logged out and automatically logged in as the user being impersonated. -* If the administrator and user are in different realms, the administrator will remain logged in, and additionally will be logged in as the user in that user's realm. - -In both instances, the *User Account Management* page of the impersonated user is displayed. - -.Additional resources -* For more information on assigning administration permissions, see the <<_admin_permissions,Admin Console Access Control>> chapter. diff --git a/server_admin/topics/users/con-user-registration.adoc b/server_admin/topics/users/con-user-registration.adoc deleted file mode 100644 index 27bcf1ead..000000000 --- a/server_admin/topics/users/con-user-registration.adoc +++ /dev/null @@ -1,27 +0,0 @@ -// Module included in the following assemblies: -// -// server_admin/topics/users.adoc - -[id="con-user-registration_{context}"] -= Allowing users to self-register - -[role="_abstract"] -You can use {project_name} as a third-party authorization server to manage application users, including users who self-register. If you enable self-registration, the login page displays a registration link so that user can create an account. - -.Registration link -image:images/registration-link.png[] - -A user must add profile information to the registration form to complete registration. The registration form can be customized by removing or adding the fields that must be completed by a user. - -.Clarification on identity brokering and admin API -Even when self-registrations is disabled, new users can be still added to {project_name} by either: - -* Administrator can add new users with the usage of admin console (or admin REST API) -* When identity brokering is enabled, new users authenticated by identity provider may be automatically added/registered in {project_name} storage. -See the <<_identity_broker_first_login, First login flow section in the Identity Brokering chapter>> for more information. - -Also users coming from the <<_user-storage-federation, 3rd-party user storage>> (for example LDAP) are automatically available in {project_name} when the particular user storage is enabled - -[role="_additional-resources"] -.Additional resources -* For more information on customizing user registration, see the link:{developerguide_link}[{developerguide_name}]. diff --git a/server_admin/topics/users/proc-allow-user-to-delete-account.adoc b/server_admin/topics/users/proc-allow-user-to-delete-account.adoc deleted file mode 100644 index b8ad0703a..000000000 --- a/server_admin/topics/users/proc-allow-user-to-delete-account.adoc +++ /dev/null @@ -1,52 +0,0 @@ -[id="proc-allow-user-to-delete-account_{context}"] -= Enabling account deletion by users - -End users and applications can delete their accounts in the Account Console if you enable this capability in the Admin Console. Once you enable this capability, you can give that capability to specific users. - -== Enabling the Delete Account Capability - -You enable this capability on the *Required Actions* tab. - -.Procedure -. Click *Authentication* in the menu. -. Click the *Required Actions* tab. -. Select *Enabled* on the *Delete Account* row. -+ -.Delete account on required actions tab -image:images/enable-delete-account-action.png[] - -== Giving a user the *delete-account* role - -You can give specific users a role that allows account deletion. - -.Procedure -. Click *Users* in the menu. -. Select a user. -. Click the *Role Mappings* tab. -. Click the *Assign role* button. -. Click *account delete-account*. -. Click *Assign*. -+ -.Delete-account role -image:images/delete-account-client-role.png[delete-account role] - -== Deleting your account - -Once you have the *delete-account* role, you can delete your own account. - -. Log into the Account Console. -. At the bottom of the *Personal Info* page, click *Delete Account*. -+ -.Delete account page -image:images/delete-account-page.png[Delete account page] - -. Enter your credentials and confirm the deletion. -+ -.Delete confirmation -image:images/delete-account-confirm.png[] -+ -[NOTE] -==== -This action is irreversible. All your data in {project_name} will be removed. -==== - diff --git a/server_admin/topics/users/proc-configuring-user-attributes.adoc b/server_admin/topics/users/proc-configuring-user-attributes.adoc deleted file mode 100644 index 38601cb9d..000000000 --- a/server_admin/topics/users/proc-configuring-user-attributes.adoc +++ /dev/null @@ -1,27 +0,0 @@ -// Module included in the following assemblies: -// -// server_admin/topics/users.adoc - -[id="proc-configuring-user-attributes_{context}"] -= Configuring user attributes - -User attributes provide a customized experience for each user. You can create a personalized identity for each user in the console by configuring user attributes. - -.Users -image:images/user-attributes.png[] - -.Prerequisite -* You are in the realm where the user exists. - -.Procedure -. Click *Users* in the menu. -. Select a user to manage. -. Click the *Attributes* tab. -. Enter the attribute name in the *Key* field. -. Enter the attribute value in the *Value* field. -. Click *Save*. - - -NOTE: Some read-only attributes are not supposed to be updated by the administrators. This includes attributes that are read-only -by design like for example `LDAP_ID`, which is filled automatically by the LDAP provider. Some other attributes should be read-only for -typical user administrators due to security reasons. See the details in the xref:_read_only_user_attributes[Mitigating security threats] chapter. diff --git a/server_admin/topics/users/proc-creating-otp.adoc b/server_admin/topics/users/proc-creating-otp.adoc deleted file mode 100644 index a0662715e..000000000 --- a/server_admin/topics/users/proc-creating-otp.adoc +++ /dev/null @@ -1,24 +0,0 @@ -// Module included in the following assemblies: -// -// server_admin/topics/users.adoc - -[id="proc_creating-otp_{context}"] -= Creating an OTP - -[role="_abstract"] -If OTP is conditional in your realm, the user must navigate to {project_name} Account Console to reconfigure a new OTP generator. If OTP is required, then the user must reconfigure a new OTP generator when logging in. - -Alternatively, you can send an email to the user that requests the user reset the OTP generator. The following procedure also applies if the user already has an OTP credential. - -.Prerequisite -* You are logged in to the appropriate realm. - -.Procedure -. Click *Users* in the main menu. The *Users* page is displayed. -. Select a user. -. Click the *Credentials* tab. -. Click *Credential Reset*. -. Select *Configure OTP*. -. Navigate to the *Reset Actions* list. -. Click *Configure OTP*. -. Click *Send Email*. The sent email contains a link that directs the user to the *OTP setup page*. diff --git a/server_admin/topics/users/proc-creating-user.adoc b/server_admin/topics/users/proc-creating-user.adoc deleted file mode 100644 index d839a911a..000000000 --- a/server_admin/topics/users/proc-creating-user.adoc +++ /dev/null @@ -1,34 +0,0 @@ -// Module included in the following assemblies: -// -// server_admin/topics/users.adoc - -[id="proc-creating-user_{context}"] -= Creating users - -[role="_abstract"] -You create users in the realm where you intend to have applications needed by those users. Avoid creating users in the master realm, which is only intended for creating other realms. - -.Prerequisite -* You are in a realm other than the master realm. - -.Procedure -. Click *Users* in the menu. -. Click *Add User*. -. Enter the details for the new user. - -ifdef::standalone[] -+ -NOTE: *Username* is the only required field. -+ -. Click *Save*. After saving the details, the *Management* page for the new user is displayed. -endif::[] - -ifdef::api-management[] -. Toggle *Email Verified* to *ON*. -. Click *Save*. -. In the *Credentials* tab, set the password in both fields. -.. Toggle *Temporary* to *OFF* to avoid resetting the password during the next login. -.. Click *Reset Password*. -.. Click *Change Password*. -.. Click *Save*. -endif::[] \ No newline at end of file diff --git a/server_admin/topics/users/proc-deleting-user.adoc b/server_admin/topics/users/proc-deleting-user.adoc deleted file mode 100644 index 99ad3c19f..000000000 --- a/server_admin/topics/users/proc-deleting-user.adoc +++ /dev/null @@ -1,18 +0,0 @@ -// Module included in the following assemblies: -// -// server_admin/topics/users.adoc - -[id="proc-deleting-user_{context}"] -= Deleting a user - -You can delete a user, who no longer needs access to applications. If a user is deleted, the user profile and data is also deleted. - - -.Procedure -. Click *Users* in the menu. The *Users* page is displayed. -. Click *View all users* to find a user to delete. -. Click *Users* in the menu. The *Users* page is displayed. -+ -NOTE: Alternatively, you can use the search bar to find a user. -+ -. Click *Delete* from the action menu next to the user you want to remove and confirm deletion. diff --git a/server_admin/topics/users/proc-enabling-recaptcha.adoc b/server_admin/topics/users/proc-enabling-recaptcha.adoc deleted file mode 100644 index 45bef02f8..000000000 --- a/server_admin/topics/users/proc-enabling-recaptcha.adoc +++ /dev/null @@ -1,51 +0,0 @@ -// Module included in the following assemblies: -// -// server_admin/topics/users.adoc - -[id="proc-enabling-recaptcha_{context}"] -= Enabling reCAPTCHA - -[role="_abstract"] -To safeguard registration against bots, {project_name} has integration with Google reCAPTCHA. - -Once reCAPTCHA is enabled, you can edit `register.ftl` in your login theme to configure the placement and styling of the reCAPTCHA button on the registration page. - -.Procedure -. Enter the following URL in a browser: -+ -[source,bash,subs=+attributes] ----- -https://developers.google.com/recaptcha/ ----- - -. Create an API key to get your reCAPTCHA site key and secret. Note the reCAPTCHA site key and secret for future use in this procedure. -+ -NOTE: The localhost works by default. You do not have to specify a domain. -+ -. Navigate to the {project_name} admin console. -. Click *Authentication* in the menu. -. Click the *Flows* tab. -. Select *Registration* from the list. -. Set the *reCAPTCHA* requirement to *Required*. This enables -reCAPTCHA. -. Click the *gear icon* ⚙️ on the *reCAPTCHA* row. -. Click the *Config* link. - -+ -.Recaptcha config page -image:images/recaptcha-config.png[] - -.. Enter the *Recaptcha Site Key* generated from the Google reCAPTCHA website. -.. Enter the *Recaptcha Secret* generated from the Google reCAPTCHA website. -. Authorize Google to use the registration page as an iframe. -+ -NOTE: In {project_name}, websites cannot include a login page dialog in an iframe. This restriction is to prevent clickjacking attacks. You need to change the default HTTP response headers that is set in {project_name}. -+ -.. Click *Realm Settings* in the menu. -.. Click the *Security Defenses* tab. -.. Enter `https://www.google.com` in the field for the *X-Frame-Options* header. -.. Enter `https://www.google.com` in the field for the *Content-Security-Policy* header. - -[role="_additional-resources"] -.Additional resources -* For more information on extending and creating themes, see the link:{developerguide_link}[{developerguide_name}]. diff --git a/server_admin/topics/users/proc-enabling-terms-conditions.adoc b/server_admin/topics/users/proc-enabling-terms-conditions.adoc deleted file mode 100644 index d19818dfc..000000000 --- a/server_admin/topics/users/proc-enabling-terms-conditions.adoc +++ /dev/null @@ -1,17 +0,0 @@ -// Module included in the following assemblies: -// -// con-required-actions.adoc - -[id="proc-enabling-terms-conditions_{context}"] -= Enabling terms and conditions as a required action - -You can enable a required action that new users must accept the terms and conditions before logging in to {project_name} for the first time. - -.Procedure -. Click *Authentication* in the menu. -. Click the *Required Actions* tab. -. Enable the *Terms and Conditions* action. -. Edit the `terms.ftl` file in the base login theme. - -.Additional resources -* For more information on extending and creating themes, see the link:{developerguide_link}[{developerguide_name}]. diff --git a/server_admin/topics/users/proc-enabling-user-registration.adoc b/server_admin/topics/users/proc-enabling-user-registration.adoc deleted file mode 100644 index 0cf727a20..000000000 --- a/server_admin/topics/users/proc-enabling-user-registration.adoc +++ /dev/null @@ -1,17 +0,0 @@ -// Module included in the following assemblies: -// -// con-user-registration.adoc - -[id="proc-enabling-user-registration_{context}"] -= Enabling user registration - -[role="_abstract"] -Enable users to self-register. - -.Procedure -. Click *Realm Settings* in the main menu. -. Click the *Login* tab. -. Toggle *User Registration* to *ON*. -. Click *Save*. - -After you enable this setting, a *Register* link displays on the login page of the Admin Console. \ No newline at end of file diff --git a/server_admin/topics/users/proc-registering-new-user.adoc b/server_admin/topics/users/proc-registering-new-user.adoc deleted file mode 100644 index 13f311792..000000000 --- a/server_admin/topics/users/proc-registering-new-user.adoc +++ /dev/null @@ -1,21 +0,0 @@ -// Module included in the following assemblies: -// -// con-user-registration.adoc - -[id="proc-registering-new-user_{context}"] -= Registering as a new user - -[role="_abstract"] -As a new user, you must complete a registration form to log in for the first time. You add profile information and a password to register. - -.Registration form -image:images/registration-form.png[] - -.Prerequisite -* User registration is enabled. - -.Procedure -. Click the *Register* link on the login page. The registration page is displayed. -. Enter the user profile information. -. Enter the new password. -. Click *Save*. diff --git a/server_admin/topics/users/proc-searching-user.adoc b/server_admin/topics/users/proc-searching-user.adoc deleted file mode 100644 index 77b5deefa..000000000 --- a/server_admin/topics/users/proc-searching-user.adoc +++ /dev/null @@ -1,27 +0,0 @@ -// Module included in the following assemblies: -// -// server_admin/topics/users.adoc - -[id="proc-searching-user_{context}"] -= Searching for a user - -Search for a user to view detailed information about the user, such as the user's groups and roles. - -.Prerequisite -* You are in the realm where the user exists. - -.Procedure -. Click *Users* in the main menu. This *Users* page is displayed. -. Type the full name, last name, first name, or email address of the user you want to search for in the search box. The search returns all users who match your criteria. -. Alternatively, you can click *View all users* to list every user in the system. -+ -NOTE: This action searches only the local {project_name} database and not the federated database, such as LDAP. The backends for federated databases do not have a pagination mechanism that enables searching for users. -+ -.. To search users from a federated backend, the user list must be synced into the {project_name} database. Adjust the search criteria to sync the backend users to the {project_name} database. -+ -.. Alternatively, click the *User Federation* in the left menu. -... To apply changes to a selected user, click *Sync changed users* on the page with your federation provider. -... To apply changes to all users in the database, click *Sync all users* on the page with your federation provider. - -.Additional resources -* For more information on user federation, see <<_user-storage-federation,User Federation>>. diff --git a/server_admin/topics/users/proc-setting-default-required-actions.adoc b/server_admin/topics/users/proc-setting-default-required-actions.adoc deleted file mode 100644 index 78ce67a22..000000000 --- a/server_admin/topics/users/proc-setting-default-required-actions.adoc +++ /dev/null @@ -1,12 +0,0 @@ - -[id="proc-setting-default-required-actions_{context}"] -= Setting required actions for all users - -You can specify what actions are required before the first login of all new users. The requirements apply to a user created by the *Add User* button on the *Users* page or the *Register* link on the login page. - -.Procedure - -. Click *Authentication* in the menu. -. Click the *Required Actions* tab. -. Click the checkbox in the *Set as default action* column for one or more required actions. When a new user logs in for the first time, the selected actions must be executed. - diff --git a/server_admin/topics/users/proc-setting-password-user.adoc b/server_admin/topics/users/proc-setting-password-user.adoc deleted file mode 100644 index 186378abd..000000000 --- a/server_admin/topics/users/proc-setting-password-user.adoc +++ /dev/null @@ -1,26 +0,0 @@ -// Module included in the following assemblies: -// -// server_admin/topics/users.adoc - -[id="proc-setting-password-user_{context}"] -= Setting a password for a user - -[role="_abstract"] -If a user does not have a password, or if the password has been deleted, the *Set Password* section is displayed. - -If a user already has a password, it can be reset in the *Reset Password* section. - -.Procedure -. Click *Users* in the menu. The *Users* page is displayed. -. Select a user. -. Click the *Credentials* tab. -. Type a new password in the *Set Password* section. -. Click *Set Password*. -+ -NOTE: If *Temporary* is *ON*, the user must change the password at the first login. To allow users to keep the password supplied, set *Temporary* to *OFF.* The user must click *Set Password* to change the password. -+ -. Alternatively, you can send an email to the user that requests the user reset the password. -.. Click *Credential Reset*. -.. Select *Update Password* from the list. -.. Click *Send Email*. The sent email contains a link that directs the user to the *Update Password* window. -.. Optionally, you can set the validity of the email link. This is set to the default preset in the *Tokens* tab in *Realm Settings*. diff --git a/server_admin/topics/users/proc-setting-required-actions.adoc b/server_admin/topics/users/proc-setting-required-actions.adoc deleted file mode 100644 index b4b0feb4e..000000000 --- a/server_admin/topics/users/proc-setting-required-actions.adoc +++ /dev/null @@ -1,14 +0,0 @@ -[id="proc-setting-required-actions_{context}"] -= Setting required actions for one user - -You can set the actions that are required for any user. - -.Procedure -. Click *Users* in the menu. -. Select a user from the list. -. Navigate to the *Required User Actions* list. -+ -image:images/user-required-action.png[] -. Select all the actions you want to add to the account. -. Click the *X* next to the action name to remove it. -. Click *Save* after you select which actions to add. diff --git a/server_admin/topics/users/ref-personal-data-collected.adoc b/server_admin/topics/users/ref-personal-data-collected.adoc deleted file mode 100644 index ee22565c7..000000000 --- a/server_admin/topics/users/ref-personal-data-collected.adoc +++ /dev/null @@ -1,22 +0,0 @@ -// Module included in the following assemblies: -// -// server_admin/topics/users.adoc - -[id="ref-personal-data-collected_{context}"] -= Personal data collected by {project_name} - -By default, {project_name} collects the following data: - -* Basic user profile data, such as the user email, first name, and last name. - -* Basic user profile data used for social accounts and references to the social account when using a social login. - -* Device information collected for audit and security purposes, such as the IP address, operating system name, and the browser name. - -The information collected in {project_name} is highly customizable. The following guidelines apply when making customizations: - -* Registration and account forms can contain custom fields, such as birthday, gender, and nationality. An administrator can configure {project_name} to retrieve data from a social provider or a user storage provider such as LDAP. - -* {project_name} collects user credentials, such as password, OTP codes, and WebAuthn public keys. This information is encrypted and saved in a database, so it is not visible to {project_name} administrators. Each type of credential can include non-confidential metadata that is visible to administrators such as the algorithm that is used to hash the password and the number of hash iterations used to hash the password. - -* With authorization services and UMA support enabled, {project_name} can hold information about some objects for which a particular user is the owner. \ No newline at end of file diff --git a/server_admin/topics/users/ref-user-credentials.adoc b/server_admin/topics/users/ref-user-credentials.adoc deleted file mode 100644 index 85d88994f..000000000 --- a/server_admin/topics/users/ref-user-credentials.adoc +++ /dev/null @@ -1,31 +0,0 @@ -// Module included in the following assemblies: -// -// server_admin/topics/users.adoc - -[id="ref-user-credentials_{context}"] -= Defining user credentials - -You can manage credentials of a user in the *Credentials* tab. - -.Credential management -image:images/user-credentials.png[user credentials] - -You change the priority of credentials by dragging and dropping rows. The new order determines the priority of the credentials for that user. The topmost credential has the highest priority. The priority determines which credential is displayed first after a user logs in. - -Type:: - This column displays the type of credential, for example *password* or *OTP*. - -User Label:: - This is an assignable label to recognize the credential when presented as a selection option during login. It can be set to any value to describe the - credential. - -Data:: - This is the non-confidential technical information about the credential. It is hidden, by default. You can click *Show data...* to display the data for a - credential. - -Actions:: - Click *Reset password* to change the password for the user and *Delete* to remove the credential. - -You cannot configure other types of credentials for a specific user in the Admin Console; that task is the user's responsibility. - -You can delete the credentials of a user in the event a user loses an OTP device or if credentials have been compromised. You can only delete credentials of a user in the *Credentials* tab. diff --git a/server_admin/topics/users/user-profile.adoc b/server_admin/topics/users/user-profile.adoc deleted file mode 100644 index eab9cd498..000000000 --- a/server_admin/topics/users/user-profile.adoc +++ /dev/null @@ -1,742 +0,0 @@ -[[user-profile]] -= Defining a user profile - -In {project_name} a user is associated with a set of attributes. These attributes are used to better describe and identify users within {project_name} as well as to pass over additional information about them to applications. - -A user profile defines a well-defined schema for representing user attributes and how they are managed within a realm. By providing a consistent view over user information, it allows administrators to control the different aspects on how attributes are managed as well as to make it much easier to extend {project_name} to support additional attributes. - -Among other capabilities, user profile enables administrators to: - -* Define a schema for user attributes -* Define whether an attribute is required based on contextual information (e.g.: if required only for users, or admins, or both, or depending on the scope being requested.) -* Define specific permissions for viewing and editing user attributes, making possible to adhere to strong privacy requirements where some attributes can not be seen or be changed by third-parties (including administrators) -* Dynamically enforce user profile compliance so that user information is always updated and in compliance with the metadata and rules associated with attributes -* Define validation rules on a per-attribute basis by leveraging the built-in validators or writing custom ones -* Dynamically render forms that users interact with like registration, update profile, brokering, and personal information in the account console, according to the attribute definitions and without any need to manually change themes. - -The User Profile capabilities are backed by the User Profile SPI. By default, these capabilities are disabled and realms are configured to use a default configuration that keeps backward compatibility with the legacy behavior. - -[NOTE] -==== -The legacy behavior is about keeping the default constraints used by {project_name} when managing users root attributes such as username, email, first and last name, without any restriction on how custom attributes are managed. Regarding user flows such as registration, profile update, brokering, and managing accounts through the account console, users are restricted to use the attributes aforementioned with the possibility to change theme templates to support additional attributes. - -If you are already using {project_name}, the legacy behavior is what you have been using so far. -==== - -Differently than the legacy behavior, the declarative provider gives you a lot more flexibility to define the user profile configuration to a realm through the administration console and a well-defined JSON schema. - -In the next sections, we'll be looking at how to use the declarative provider to define your own user profile configuration. - -[NOTE] -==== -In the future, the legacy behavior will no longer be supported in {project_name}. Ideally, you should start looking at the new capabilities provided by the User Profile and migrate your realms accordingly. -==== - -== Enabling the User Profile - -:tech_feature_name: Declarative User Profile -:tech_feature_setting: -Dkeycloak.profile.feature.declarative_user_profile=enabled -:tech_feature_id: declarative-user-profile -include::../templates/techpreview.adoc[] - -In addition to enabling the `declarative_user_profile` feature, you should enable User Profile for a realm. To do that, click on the `Realm Settings` link on -the left side menu and turn on the `User Profile Enabled` switch. - -image:images/user-profile-enabling.png[] - -Once you enable it and click on the `Save` button, you can access the `User Profile` tab from where you can manage the configuration for user attributes. - -By enabling the user profile for a realm, {project_name} is going to impose additional constraints on how attributes are managed based on the user profile configuration. In summary, here is the list of what you should expect when the feature is enabled: - -* From an administration point of view, the `Attributes` tab at the user details page will only show the attributes defined in the user profile configuration. The conditions defined on a per-attribute basis will also be taken into account when managing attributes. - -* User facing forms like registration, update profile, brokering, and personal info in the account console, are going to be rendered dynamically based on the user profile configuration. For that, {project_name} is going to rely on different templates to render these forms dynamically. - -In the next topics, we'll be exploring how to manage the user profile configuration and how it affects your realm. - -== Managing the User Profile - -The user profile configuration is managed on a per-realm basis. For that, click on the -`Realm Settings` link on the left side menu and then click on the `User Profile` tab. - -.User Profile Tab -image:images/user-profile-tab.png[] - -In the `Attributes` sub-tab you have a list of the attributes currently associated with the user profile. By default, the configuration is created based on the user root attributes and each attribute is configured with some defaults in terms of validation and permissioning. - -In the `Attribute Groups` sub-tab you can manage attribute groups. An attribute group allows you to correlate attributes so that they are displayed together when rendering user facing forms. - -[NOTE] -==== -For now, attribute groups are only used for rendering purposes but in the future they should also enable defining top-level configurations to the attributes they are linked to. -==== - -In the `JSON Editor` sub-tab you can view and edit the configuration using a well-defined JSON schema. Any change you make when at any other tab are reflected in the JSON configuration shown at this tab. - -In the next section, you are going to learn how to manage the configuration from the `Attributes` sub-tab. - -== Managing Attributes - -At the `Attributes` sub-tab you can create, edit, and delete the attributes associated with the user profile. - -To define a new attribute and associate it with the user profile, click on the *Create attribute* button at the top the attribute listing. - -.Attribute Configuration -image:images/user-profile-create-attribute.png[] - -When configuring the attribute you can define the following settings: - -Name:: -The name of the attribute. - -Display name:: -A user-friendly name for the attribute, mainly used when rendering user-facing forms. It supports internationalization so that values can be loaded from message bundles. - -Attribute Group:: -The attribute group to which the attribute belongs to, if any. - -Enabled when scope:: -Allows you to define a list of scopes to dynamically enable an attribute. If not set, the attribute is always enabled and its constraints are always enforced when managing user profiles as well as when rendering user-facing forms. Otherwise, the same constraints only apply when any of the scopes in the list is requested by clients. - - -Required:: -Set the attribute as required. If not enabled, the attribute is optional. Otherwise, the attribute must be provided by users and administrators with the possibility to also make the attribute required only for users or administrators as well as based on the scopes requested by clients. - -Permission:: -In this section, you can define read and write permissions for users and administrators. - -Validation:: -In this section, you can define the validations that will be performed when managing the attribute value. {project_name} provides a set of built-in validators you can choose from with the possibility to add your own. - -Annotation:: -In this section, you can associate annotations to the attribute. Annotations are mainly useful to pass over additional metadata to frontends for rendering purposes. - -=== Managing Permissions - -In the `Permission` section, you can define the level of access users and administrators have to read and write to an attribute. - -.Attribute Permission -image:images/user-profile-permission.png[] - -For that, you can use the following settings: - -Can user view?:: -If enabled, users can view the attribute. Otherwise, users don't have access to the attribute. - -Can user edit?:: -If enabled, users can view and edit the attribute. Otherwise, users don't have access to write to the attribute. - -Can admin view?:: -If enabled, administrators can view the attribute. Otherwise, administrators don't have access to the attribute. - -Can admin edit?:: -If enabled, administrators can view and edit the attribute. Otherwise, administrators don't have access to write to the attribute. - -[NOTE] -==== -When you create an attribute, no permission is set to the attribute. Effectively, the attribute won't be accessible by either users or administrators. Once you create the attribute, make sure to set the permissions accordingly to that the attribute is only visible by the target audience. -==== - -Permissioning has a direct impact on how and who can manage the attribute, as well as on how the attribute is rendered in user-facing forms. - -For instance, by marking an attribute as only viewable by users, the administrators won't have access to the attribute when managing users through the administration console (neither from the User API). Also, users won't be able to change the attribute when updating their profiles. An interesting configuration if user attributes are fetched from an existing identity store (federation) and you just want to make attributes visible to users without any possibility to update the attribute other than through the source identity store. - -Similarly, you can also mark an attribute as writable only for administrators with read-only access for users. In this case, only administrators are going to be allowed to manage the attribute. - -Depending on your privacy requirements, you might also want attributes inaccessible to administrators but with read-write permissions for users. - -Make sure to set the correct permissions whenever you add a new attribute to the user profile configuration. - -=== Managing validations - -In the `Validation` section, you can choose from different forms of validation to make sure the attribute value conforms to specific rules. - -.Attribute Validation -image:images/user-profile-validation.png[] - -{project_name} provides different validators out of the box: - -[cols="3*", options="header"] -|=== -|Name -|Description -|Configuration - -|length -|Check the length of a string value based on a minimum and maximum length. -| - -*min*: an integer to define the minimum allowed length. - -*max*: an integer to define the maximum allowed length. - -*trim-disabled*: a boolean to define whether the value is trimmed prior to validation. - -|integer -|Check if the value is an integer and within a lower and/or upper range. If no range is defined, the validator only checks whether the value is a valid number. -| - -*min*: an integer to define the lower range. - -*max*: an integer to define the upper range. - -|double -|Check if the value is a double and within a lower and/or upper range. If no range is defined, the validator only checks whether the value is a valid number. -| - -*min*: an integer to define the lower range. - -*max*: an integer to define the upper range. - -|uri -|Check if the value is a valid URI. -| None - -|pattern -|Check if the value matches a specific RegEx pattern. -| - -*pattern*: the RegEx pattern to use when validating values. - -*error-message*: the key of the error message in i18n bundle. If not set a generic message is used. - -|email -|Check if the value has a valid e-mail format. -| None - -|local-date -|Check if the value has a valid format based on the realm and/or user locale. -| None - -|person-name-prohibited-characters -| Check if the value is a valid person name as an additional barrier for attacks such as script injection. The validation is based on a default RegEx pattern that blocks characters not common in person names. -| - -*error-message*: the key of the error message in i18n bundle. If not set a generic message is used. - -|username-prohibited-characters -| Check if the value is a valid username as an additional barrier for attacks such as script injection. The validation is based on a default RegEx pattern that blocks characters not common in usernames. -| - -*error-message*: the key of the error message in i18n bundle. If not set a generic message is used. - -|options -|Check if the value is from the defined set of allowed values. Useful to validate values entered through select and multiselect fields. -| - -*options*: array of strings containing allowed values. - -|=== - -==== Managing annotations - -In order to pass additional information to frontends, attributes can be decorated with -annotations to dictate how attributes are rendered. This capability is mainly useful when extending {project_name} themes -to render pages dynamically based on the annotations associated with attributes. -This mechanism is used for example to link:#_configuring_form_input_field_for_attribute[configure Form input filed for attribute]. - -.Attribute Annotation -image:images/user-profile-annotation.png[] - -== Managing Attribute Groups - -At the `Attribute Groups` sub-tab you can create, edit, and delete attribute groups. An attribute group allows you to define a container for correlated attributes so that they are rendered together when at the user-facing forms. - -.Attribute Group List -image:images/user-profile-attribute-group-list.png[] - -[NOTE] -==== -You can't delete attribute groups that are bound to attributes. For that, you should first update the attributes to remove the binding. -==== - -To create a new group, click on the *Create attributes group* button on the top of the attribute groups listing. - -.Attribute Group Configuration -image:images/user-profile-create-attribute-group.png[] - -When configuring the group you can define the following settings: - -Name:: -The name of the group. - -Display name:: -A user-friendly name for the group, mainly used when rendering user-facing forms. It supports internationalization so that values can be loaded from message bundles. - -Display description:: -A user-friendly text that will be displayed as a tooltip when rendering user-facing forms. - -Annotation:: -In this section, you can associate annotations to the attribute. Annotations are mainly useful to pass over additional metadata to frontends for rendering purposes. - -== Using the JSON configuration - -The user profile configuration is stored using a well-defined JSON schema. You can choose from editing the user profile configuration directly by clicking on the `JSON Editor` sub-tab. - -.JSON Configuration -image:images/user-profile-json-config.png[] - -The JSON schema is defined as follows: - -[source,json] ----- -{ - "attributes": [ - { - "name": "myattribute", - "required": { - "roles": [ "user", "admin" ], - "scopes": [ "foo", "bar" ] - }, - "permissions": { - "view": [ "admin", "user" ], - "edit": [ "admin", "user" ] - }, - "validations": { - "email": {}, - "length": { - "max": 255 - } - }, - "annotations": { - "myannotation": "myannotation-value" - } - } - ], - "groups": [ - { - "name": "personalInfo", - "displayHeader": "Personal Information" - } - ] -} ----- - -The schema supports as many attributes as you need. - -For each attribute you should define a `name` and, optionally, the `required`, `permission`, and the `annotations` settings. - -=== Required property - -The `required` setting defines whether an attribute is required. {project_name} allows you to set an attribute as required based on different conditions. - -When the `required` setting is defined as an empty object, the attribute is always required. - -[source,json] ----- -{ - "attributes": [ - { - "name": "myattribute", - "required": {} - ] -} ----- - -On the other hand, you can choose to make the attribute required only for users, or administrators, or both. As well as mark the attribute as required only in case a specific scope is requested when the user is authenticating in {project_name}. - -To mark an attribute as required for a user and/or administrator, set the `roles` property as follows: - -[source,json] ----- -{ - "attributes": [ - { - "name": "myattribute", - "required": { - "roles": ["user"] - } - ] -} ----- - -The `roles` property expects an array whose values can be either `user` or `admin`, depending on whether the attribute is required by the user or the administrator, respectively. - -Similarly, you can choose to make the attribute required when a set of one or more scopes is requested by a client when authenticating a user. For that, you can use the `scopes` property as follows: - -[source,json] ----- -{ - "attributes": [ - { - "name": "myattribute", - "required": { - "scopes": ["foo"] - } - ] -} ----- - -The `scopes` property is an array whose values can be any string representing a client scope. - -=== Permissions property - -The attribute-level `permissions` property can be used to define the read and write permissions to an attribute. The permissions are set based on whether these operations can be performed on the attribute by a user, or administrator, or both. - -[source,json] ----- -{ - "attributes": [ - { - "name": "myattribute", - "permissions": { - "view": ["admin"], - "edit": ["user"] - } - ] -} ----- - -Both `view` and `edit` properties expect an array whose values can be either `user` or `admin`, depending on whether the attribute is viewable or editable by the user or the administrator, respectively. - -When the `edit` permission is granted, the `view` permission is implicitly granted. - -=== Annotations property - -The attribute-level `annotation` property can be used to associate additional metadata to attributes. Annotations are mainly useful for passing over additional information about attributes to frontends rendering user attributes based on the user profile configuration. Each annotation is a key/value pair. - -[source,json] ----- -{ - "attributes": [ - { - "name": "myattribute", - "annotations": { - "foo": ["foo-value"], - "bar": ["bar-value"] - } - ] -} ----- - -== Using dynamic forms - -One of the main capabilities of User Profile is the possibility to dynamically render user-facing forms based on attributes metadata. When you have the feature enabled to your realm, forms like registration and update profile are rendered using specific theme templates to dynamically render pages based on the user profile configuration. - -That said, you shouldn't need to customize templates at all if the default rendering mechanisms serves to your needs. In case you still need customizations to themes, here are the templates you should be looking at: - -[cols="2*", options="header"] -|=== -|Template -|Description - -| base/login/update-user-profile.ftl -| The template that renders the update profile page. - -| base/login/register-user-profile.ftl -| The template that renders the registration page. - -| base/login/idp-review-user-profile.ftl -| The template that renders the page to review/update the user profile when federating users through brokering. - -| base/login/user-profile-commons.ftl -| The template that renders input fields in forms based on attributes configuration. Used from all three page templates described above. New input types can be implemented here. - -|=== - -The default rendering mechanism provides the following capabilities: - -* Dynamically display fields based on the permissions set to attributes. -* Dynamically render markers for required fields based on the constraints set to the attributes. -* Dynamically render field input type (text, date, number, select, multiselect) set to an attribute. -* Dynamically render read-only fields depending on the permissions set to an attribute. -* Dynamically order fields depending on the order set to the attributes. -* Dynamically group fields that belong to a same attribute group. - -=== Ordering attributes - -The attributes order is set by dragging and dropping the attribute rows on the attribute listing page. - -.Ordering Attributes -image:images/user-profile-attribute-list-order.png[] - -The order you set in this page is respected when fields are rendered in dynamic forms. - -=== Grouping attributes - -When dynamic forms are rendered, they will try to group together attributes that belong to a same attribute group. - -.Dynamic Update Profile Form -image:images/user-profile-update-profile.png[] - -[NOTE] -==== -When attributes are linked to an attribute group, the attribute order is also important to make sure attributes within the same group are close together, within a same group header. Otherwise, if attributes within a group do not have a sequential order you might have the same group header rendered multiple times in the dynamic form. -==== - -[[_configuring_form_input_field_for_attribute]] -=== Configuring Form input filed for Attributes - -{project_name} provides built-in annotations to configure which input type will be used for the attribute in dynamic forms and other aspects of it's visualization. - -Available annotations are: -[cols="2*", options="header"] -|=== -|Name -|Description - -|inputType -|Type of the form input field. Available types are described in a table below. - -|inputHelperTextBefore -|Helper text rendered before (above) the input field. Direct text or internationalization pattern (like `${i18n.key}`) can be used here. -Text is NOT html escaped when rendered into the page, so you can use html tags here to format the text, but you also have to correctly escape html control characters. - -|inputHelperTextAfter -|Helper text rendered after (under) the input field. Direct text or internationalization pattern (like `${i18n.key}`) can be used here. -Text is NOT html escaped when rendered into the page, so you can use html tags here to format the text, but you also have to correctly escape html control characters. - -|inputOptionsFromValidation -|Annotation for select and multiselect types. Optional name of custom attribute validation to get input options from. See link:#_managing_options_for_select_fields[detailed description] below. - -|inputOptionLabelsI18nPrefix -|Annotation for select and multiselect types. Internationalization key prefix to render options in UI. See link:#_managing_options_for_select_fields[detailed description] below. - -|inputOptionLabels -|Annotation for select and multiselect types. Optional map to define UI labels for options (directly or using internationalization). See link:#_managing_options_for_select_fields[detailed description] below. - -|inputTypePlaceholder -|HTML input `placeholder` attribute applied to the field - specifies a short hint that describes the expected value of an input field (e.g. a sample value -or a short description of the expected format). The short hint is displayed in the input field before the user enters a value. - -|inputTypeSize -|HTML input `size` attribute applied to the field - specifies the width, in characters, of a single line input field. For fields based on HTML `select` type -it specifies number of rows with options shown. May not work, depending on css in used theme! - -|inputTypeCols -|HTML input `cols` attribute applied to the field - specifies the width, in characters, for `textarea` type. May not work, depending on css in used theme! - -|inputTypeRows -|HTML input `rows` attribute applied to the field - specifies the height, in characters, for `textarea` type. For select fields it specifies number -of rows with options shown. May not work, depending on css in used theme! - -|inputTypePattern -|HTML input `pattern` attribute applied to the field providing client side validation - specifies a regular expression that an input field's value -is checked against. Useful for single line inputs. - -|inputTypeMaxLength -|HTML input `maxlength` attribute applied to the field providing client side validation - maximal length of the text which can be entered into the input -field. Useful for text fields. - -|inputTypeMinLength -|HTML input `minlength` attribute applied to the field providing client side validation - minimal length of the text which can be entered into the input -field. Useful for text fields. - -|inputTypeMax -|HTML input `max` attribute applied to the field providing client side validation - maximal value which can be entered into the input field. -Useful for numeric fields. - -|inputTypeMin -|HTML input `min` attribute applied to the field providing client side validation - minimal value which can be entered into the input field. -Useful for numeric fields. - -|inputTypeStep -|HTML input `step` attribute applied to the field - Specifies the interval between legal numbers in an input field. Useful for numeric fields. - -|=== - -[NOTE] -==== -Field types use HTML form field tags and attributes applied to them - they behave based on the HTML specifications and browser support for them. - -Visual rendering also depends on css styles applied in the used theme. -==== - -Available `inputType` annotation values: -[cols="3*", options="header"] -|=== -|Name -|Description -|HTML tag used - -|text -|Single line text input. -|input - -|textarea -|Multiple line text input. -|textarea - -|select -|Common single select input. See link:#_managing_options_for_select_fields[description how to configure options] below. -|select - -|select-radiobuttons -|Single select input through group of radio buttons. See link:#_managing_options_for_select_fields[description how to configure options] below. -|group of input - -|multiselect -|Common multiselect input. See link:#_managing_options_for_select_fields[description how to configure options] below. -|select - -|multiselect-checkboxes -|Multiselect input through group of checkboxes. See link:#_managing_options_for_select_fields[description how to configure options] below. -|group of input - -|html5-email -|Single line text input for email address based on HTML 5 spec. -|input - -|html5-tel -|Single line text input for phone number based on HTML 5 spec. -|input - -|html5-url -|Single line text input for URL based on HTML 5 spec. -|input - -|html5-number -|Single line input for number (integer or float depending on `step`) based on HTML 5 spec. -|input - -|html5-range -|Slider for number entering based on HTML 5 spec. -|input - -|html5-datetime-local -|Date Time input based on HTML 5 spec. -|input - -|html5-date -|Date input based on HTML 5 spec. -|input - -|html5-month -|Month input based on HTML 5 spec. -|input - -|html5-week -|Week input based on HTML 5 spec. -|input - -|html5-time -|Time input based on HTML 5 spec. -|input - -|=== - -[[_managing_options_for_select_fields]] -==== Defining options for select and multiselect fields - -Options for select and multiselect fields are taken from validation applied to the attribute to be -sure validation and field options presented in UI are always consistent. By default, options are taken from built-in `options` validation. - -You can use various ways to provide nice human-readable labels for select and multiselect options. The simplest -case is when attribute values are same as UI labels. No extra configuration is necessary in this case. - -.Option values same as UI labels -image:images/user-profile-select-options-simple.png[] - -When attribute value is kind of ID not suitable for UI, you can use simple internationalization support provided -by `inputOptionLabelsI18nPrefix` annotation. It defines prefix for internationalization keys, option value is dot appended to this prefix. - -.Simple internationalization for UI labels using i18n key prefix -image:images/user-profile-select-options-simple-i18n.png[] - -Localized UI label texts for option value have to be provided by `userprofile.jobtitle.sweng` and `userprofile.jobtitle.swarch` -keys then, using common localization mechanism. - -You can also use `inputOptionLabels` annotation to provide labels for individual options. It contains map of labels for option - key in the map is -option value (defined in validation), and value in the map is UI label text itself or its internationalization pattern (like `${i18n.key}`) for that option. - -[NOTE] -==== -You have to use User Profile `JSON Editor` to enter map as `inputOptionLabels` annotation value. -==== - - -Example of directly entered labels for individual options without internationalization: -[source,json] ----- -"attributes": [ -<... -{ - "name": "jobTitle", - "validations": { - "options": { - "options":[ - "sweng", - "swarch" - ] - } - }, - "annotations": { - "inputType": "select", - "inputOptionLabels": { - "sweng": "Software Engineer", - "swarch": "Software Architect" - } - } -} -... -] ----- - -Example of the internationalized labels for individual options: -[source,json] ----- -"attributes": [ -... -{ - "name": "jobTitle", - "validations": { - "options": { - "options":[ - "sweng", - "swarch" - ] - } - }, - "annotations": { - "inputType": "select-radiobuttons", - "inputOptionLabels": { - "sweng": "${jobtitle.swengineer}", - "swarch": "${jobtitle.swarchitect}" - } - } -} -... -] ----- -Localized texts have to be provided by `jobtitle.swengineer` and `jobtitle.swarchitect` keys then, using common localization mechanism. - -Custom validator can be used to provide options thanks to `inputOptionsFromValidation` attribute annotation. -This validation have to have `options` config providing array of options. Internationalization works the same way as for options -provided by built-in `options` validation. - -.Options provided by custom validator -image:images/user-profile-select-options-custom-validator.png[] - - -== Forcing User Profile compliance - -In order to make sure user profiles are in compliance with the configuration, administrators may use the `VerifyProfile` required action to eventually force users to update their profiles when authenticating to {project_name}. - -[NOTE] -==== -The `VerifyProfile` action is similar to the `UpdateProfile` action. However, it leverages all the capabilities provided by the user profile to automatically enforce compliance with the user profile configuration. -==== - -When enabled, the `VerifyProfile` action is going to perform the following steps when the user is authenticating: - -* Check whether the user profile is fully compliant with the user profile configuration set to the realm. -* If not, perform an additional step during the authentication so that the user can update any missing or invalid attribute. -* If the user profile is compliant with the configuration, no additional step is performed, and the user continues with the authentication process. - -By default, the `VerifyProfile` action is disabled. To enabled it, click on the -`Authentication` link on the left side menu and then click on the `Required Actions` tab. At this tab, select the *Enabled* switch of the `VerifyProfile` action. - -.Registering the VerifyProfile Required Action -image:images/user-profile-register-verify-profile-action.png[] - -== Migrating to User Profile - -Before enabling the User Profile capabilities to a realm, there are some important considerations you should be aware of. By providing a single place to manage attribute metadata, the feature is very strict about the attributes that can be set to users and how they are managed. - -In terms of user management, administrators are able to manage only the attributes defined in the user profile configuration. Any other attribute set to the user and not yet defined in the user profile configuration won't be accessible. It is recommended to update your user profile configuration with all the user attributes you want to expose either to users or administrators. - -The same recommendation applies for those accessing the User REST API to query user information. - -In regards to {project_name} internal user attributes such as `LDAP_ID`, `LDAP_ENTRY_DN`, or `KERBEROS_PRINCIPAL`, if you want to be able to access those attributes you should have them as attributes in your user profile configuration. The recommendation is to mark these attributes as viewable only to administrators so that you can look at them when managing the user attributes through the administration console or querying users via User API. - -In regards to theming, if you already have customizations to the legacy templates (those hardcoded with user root attributes) your custom templates won't be used when rendering user-facing forms but the new templates that render these forms dynamically. Ideally, you should avoid having any customizations to templates and try to stick with the behavior provided by these new templates to dynamically render forms for you. If they are still not enough to address your requirements, you can either customize them or provide us with any feedback so that we discuss whether it makes sense to enhance the new templates. diff --git a/server_admin/topics/vault.adoc b/server_admin/topics/vault.adoc deleted file mode 100644 index 29b6b2888..000000000 --- a/server_admin/topics/vault.adoc +++ /dev/null @@ -1,61 +0,0 @@ - -[[_vault-administration]] - -== Using a vault to obtain secrets - -To obtain a secret from a vault rather than entering it directly, enter the following specially crafted string into the appropriate field: - -[source] ----- -${vault.key} ----- -where the `key` is the name of the secret recognized by the vault. - -To prevent secrets from leaking across realms, {project_name} combines the realm name with the `key` obtained from the vault expression. This method means that the `key` does not directly map to an entry in the vault but creates the final entry name according to the algorithm used to combine the `key` with the realm name. - -You can obtain the secret from the vault in the following fields: - -SMTP password:: -In the realm <<_email,SMTP settings>> - -LDAP bind credential:: -In the <<_ldap,LDAP settings>> of LDAP-based user federation. - -OIDC identity provider secret:: -In the _Client Secret_ inside identity provider <<_identity_broker_oidc,OpenID Connect Config>> - -=== Key resolvers - -All built-in providers support the configuration of key resolvers. A key resolver implements the algorithm or strategy for combining the realm name with the key, obtained from the `${vault.key}` expression, into the final entry name used to retrieve the secret from the vault. {project_name} uses the `keyResolvers` property to configure the resolvers that the provider uses. The value is a comma-separated list of resolver names. An example of the configuration for the `files-plaintext` provider follows: - -[source,bash] ----- -kc.[sh.bat] start --spi-vault-file-key-resolvers=REALM_UNDERSCORE_KEY,KEY_ONLY ----- - -The resolvers run in the same order you declare them in the configuration. For each resolver, {project_name} uses the last entry name the resolver produces, which combines the realm with the vault key to search for the vault's secret. If {project_name} finds a secret, it returns the secret. If not, {project_name} uses the next resolver. This search continues until {project_name} finds a non-empty secret or runs out of resolvers. If {project_name} finds no secret, {project_name} returns an empty secret. - -In the previous example, {project_name} uses the `REALM_UNDERSCORE_KEY` resolver first. If {project_name} finds an entry in the vault that using that resolver, {project_name} returns that entry. If not, {project_name} searches again using the `KEY_ONLY` resolver. If {project_name} finds an entry by using the `KEY_ONLY` resolver, {project_name} returns that entry. If {project_name} uses all resolvers, {project_name} returns an empty secret. - -A list of the currently available resolvers follows: - -|=== -|Name |Description - -| KEY_ONLY -| {project_name} ignores the realm name and uses the key from the vault expression. - -| REALM_UNDERSCORE_KEY -| {project_name} combines the realm and key by using an underscore character. {project_name} escapes occurrences of underscores in the realm or key with another underscore character. For example, if the realm is called `master_realm` and the key is `smtp_key`, the combined key is `master+++__+++realm_smtp+++__+++key`. - -| REALM_FILESEPARATOR_KEY -| {project_name} combines the realm and key by using the platform file separator character. - -ifeval::[{project_community}==true] -| FACTORY_PROVIDED -| {project_name} combines the realm and key by using the vault provider factory's `VaultKeyResolver`, allowing the creation of a custom key resolver by extending an existing factory and implementing the `getFactoryResolver` method. -endif::[] - -|=== - -If you have not configured a resolver for the built-in providers, {project_name} selects the `REALM_UNDERSCORE_KEY`. \ No newline at end of file diff --git a/server_development/.asciidoctorconfig b/server_development/.asciidoctorconfig deleted file mode 100644 index acb09a095..000000000 --- a/server_development/.asciidoctorconfig +++ /dev/null @@ -1 +0,0 @@ -:imagesdir: {asciidoctorconfigdir} diff --git a/server_development/docinfo-footer.html b/server_development/docinfo-footer.html deleted file mode 120000 index a39d3bd0f..000000000 --- a/server_development/docinfo-footer.html +++ /dev/null @@ -1 +0,0 @@ -../aggregation/navbar.html \ No newline at end of file diff --git a/server_development/docinfo.html b/server_development/docinfo.html deleted file mode 120000 index 14514f94d..000000000 --- a/server_development/docinfo.html +++ /dev/null @@ -1 +0,0 @@ -../aggregation/navbar-head.html \ No newline at end of file diff --git a/server_development/images/empty-user-federation-page.png b/server_development/images/empty-user-federation-page.png deleted file mode 100644 index 5576a174f..000000000 Binary files a/server_development/images/empty-user-federation-page.png and /dev/null differ diff --git a/server_development/images/keycloak_logo.png b/server_development/images/keycloak_logo.png deleted file mode 100755 index 4883f5230..000000000 Binary files a/server_development/images/keycloak_logo.png and /dev/null differ diff --git a/server_development/images/login-sunrise.png b/server_development/images/login-sunrise.png deleted file mode 100644 index 6879b1f43..000000000 Binary files a/server_development/images/login-sunrise.png and /dev/null differ diff --git a/server_development/images/storage-provider-created.png b/server_development/images/storage-provider-created.png deleted file mode 100644 index 7e5757ce8..000000000 Binary files a/server_development/images/storage-provider-created.png and /dev/null differ diff --git a/server_development/images/storage-provider-with-config.png b/server_development/images/storage-provider-with-config.png deleted file mode 100644 index 933daca0a..000000000 Binary files a/server_development/images/storage-provider-with-config.png and /dev/null differ diff --git a/server_development/images/user-federation-page.png b/server_development/images/user-federation-page.png deleted file mode 100644 index 787eb9e08..000000000 Binary files a/server_development/images/user-federation-page.png and /dev/null differ diff --git a/server_development/index.adoc b/server_development/index.adoc deleted file mode 100644 index 85f334aed..000000000 --- a/server_development/index.adoc +++ /dev/null @@ -1,16 +0,0 @@ -:toc: left -:toclevels: 3 -:sectanchors: -:linkattrs: - -include::topics/templates/document-attributes.adoc[] - -:server_developer_guide: - -= {developerguide_name} - -:release_header_guide: {developerguide_name_short} -:release_header_latest_link: {developerguide_link_latest} -include::topics/templates/release-header.adoc[] - -include::topics.adoc[] diff --git a/server_development/pom.xml b/server_development/pom.xml deleted file mode 100644 index 41dee455d..000000000 --- a/server_development/pom.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - 4.0.0 - - - org.keycloak.documentation - documentation-parent - 999.0.0-SNAPSHOT - ../ - - - Server Developer - server-development - pom - - - - - org.keycloak.documentation - header-maven-plugin - - - add-file-headers - - - - - org.asciidoctor - asciidoctor-maven-plugin - - - asciidoc-to-html - - - - - maven-antrun-plugin - - - echo-output - - - - - - diff --git a/server_development/topics.adoc b/server_development/topics.adoc deleted file mode 100644 index e802fc26e..000000000 --- a/server_development/topics.adoc +++ /dev/null @@ -1,34 +0,0 @@ -include::topics/preface.adoc[] -include::topics/admin-rest-api.adoc[] -include::topics/themes.adoc[] -include::topics/themes-selector.adoc[] -include::topics/themes-resources.adoc[] -include::topics/locale-selector.adoc[] -include::topics/custom-attributes.adoc[] -include::topics/identity-brokering.adoc[] -include::topics/identity-brokering/tokens.adoc[] -include::topics/identity-brokering/account-linking.adoc[] -include::topics/providers.adoc[] -ifeval::[{project_community}==true] -include::topics/extensions.adoc[] -include::topics/auth-spi.adoc[] -include::topics/action-token-handler-spi.adoc[] -include::topics/events.adoc[] -include::topics/saml-role-mappings-spi.adoc[] -endif::[] -include::topics/user-storage.adoc[] -include::topics/user-storage/provider-interfaces.adoc[] -include::topics/user-storage/provider-capability-interfaces.adoc[] -include::topics/user-storage/model-interfaces.adoc[] -include::topics/user-storage/packaging.adoc[] -include::topics/user-storage/simple-example.adoc[] -include::topics/user-storage/configuration.adoc[] -include::topics/user-storage/registration-query.adoc[] -include::topics/user-storage/augmenting.adoc[] -include::topics/user-storage/import.adoc[] -include::topics/user-storage/cache.adoc[] -include::topics/user-storage/javaee.adoc[] -include::topics/user-storage/rest.adoc[] -include::topics/user-storage/migration.adoc[] -include::topics/user-storage/stream-interfaces.adoc[] -include::topics/vault.adoc[] diff --git a/server_development/topics/action-token-handler-spi.adoc b/server_development/topics/action-token-handler-spi.adoc deleted file mode 100644 index 951d97917..000000000 --- a/server_development/topics/action-token-handler-spi.adoc +++ /dev/null @@ -1,173 +0,0 @@ -[[_action_token_handler_spi]] -== Action Token Handler SPI - -An action token is a special instance of Json Web Token (JWT) that permits its bearer to perform some actions, e.g. to -reset a password or validate e-mail address. They are usually sent to users in form of a link that points to an endpoint -processing action tokens for a particular realm. - -{project_name} offers four basic token types allowing the bearer to: - - * Reset credentials - * Confirm e-mail address - * Execute required action(s) - * Confirm linking of an account with account in external identity provider - -In addition to that, it is possible to implement any functionality that initiates or modifies authentication session -using action token handler SPI, details of which are described in the text below. - -[[_action_token_anatomy]] -=== Anatomy of action token - -Action token is a standard Json Web Token signed with active realm key where the payload contains several fields: - - * `typ` - Identification of the action (e.g. `verify-email`) - * `iat` and `exp` - Times of token validity - * `sub` - ID of the user - * `azp` - Client name - * `iss` - Issuer - URL of the issuing realm - * `aud` - Audience - list containing URL of the issuing realm - * `asid` - ID of the authentication session (_optional_) - * `nonce` - Random nonce to guarantee uniqueness of use if the operation can only be executed once (_optional_) - -In addition, an action token can contain any number of custom fields serializable into JSON. - -=== Action token processing - -When an action token is passed to a {project_name} endpoint -`_KEYCLOAK_ROOT_{kc_realms_path}/master/login-actions/action-token` via `key` parameter, it is validated and a proper action -token handler is executed. *The processing always takes place in a context of an authentication session*, either a fresh -one or the action token service joins an existing authentication session (details are described below). The action token -handler can perform actions prescribed by the token (often it alters the authentication session) and results into an HTTP -response (e.g. it can continue in authentication or display an information/error page). These steps are detailed below. - -1. *Basic action token validation.* Signature and time validity is checked, and action token handler is determined based -on `typ` field. - -2. [[determining-auth-sess]]*Determining authentication session.* If the action token URL was opened in browser with -existing authentication session, and the token contains authentication session ID matching the authentication session -from the browser, action token validation and handling will attach this ongoing authentication session. Otherwise, -action token handler creates a fresh authentication session that replaces any other authentication session present at -that time in the browser. - -3. *Token validations specific for token type.* Action token endpoint logic validates that the user (`sub` field) and -client (`azp`) from the token exist, are valid and not disabled. Then it validates all custom validations defined in the -action token handler. Furthermore, token handler can request this token be single-use. Already used tokens would then be -rejected by action token endpoint logic. - -4. *Performing the action.* After all these validations, action token handler code is called that performs the actual -action according to parameters in the token. - -5. *Invalidation of single-Use tokens.* If the token is set to single-use, once the authentication flow finishes, the -action token is invalidated. - -=== Implement your own action token and its handler - -==== How to create an action token - -As action token is just a signed JWT with few mandatory fields (see <<_action_token_anatomy,Anatomy of action token>> -above), it can be serialized and signed as such using Keycloak's `JWSBuilder` class. This way has been already -implemented in `serialize(session, realm, uriInfo)` method of `org.keycloak.authentication.actiontoken.DefaultActionToken` -and can be leveraged by implementors by using that class for tokens instead of plain `JsonWebToken`. - -The following example shows the implementation of a simple action token. Note that the class must have a private constructor without any arguments. -This is necessary to deserialize the token class from JWT. - -[source,java] ----- -import org.keycloak.authentication.actiontoken.DefaultActionToken; - -public class DemoActionToken extends DefaultActionToken { - - public static final String TOKEN_TYPE = "my-demo-token"; - - public DemoActionToken(String userId, int absoluteExpirationInSecs, String compoundAuthenticationSessionId) { - super(userId, TOKEN_TYPE, absoluteExpirationInSecs, null, compoundAuthenticationSessionId); - } - - private DemoActionToken() { - // Required to deserialize from JWT - super(); - } -} ----- - -If the action token you are implementing contains any custom fields that should be serializabled to JSON fields, you -should consider implementing a descendant of `org.keycloak.representations.JsonWebToken` class that would implement -`org.keycloak.models.ActionTokenKeyModel` interface. In that case, you can take advantage of the existing -`org.keycloak.authentication.actiontoken.DefaultActionToken` class as it already satisfies both these conditions, -and either use it directly or implement its child, the fields of which can be annotated with appropriate Jackson -annotations, e.g. `com.fasterxml.jackson.annotation.JsonProperty` to serialize them to JSON. - -The following example extends the `DemoActionToken` from the previous example with the field `demo-id`: - -[source,java] ----- -import com.fasterxml.jackson.annotation.JsonProperty; -import org.keycloak.authentication.actiontoken.DefaultActionToken; - -public class DemoActionToken extends DefaultActionToken { - - public static final String TOKEN_TYPE = "my-demo-token"; - - private static final String JSON_FIELD_DEMO_ID = "demo-id"; - - @JsonProperty(value = JSON_FIELD_DEMO_ID) - private String demoId; - - public DemoActionToken(String userId, int absoluteExpirationInSecs, String compoundAuthenticationSessionId, String demoId) { - super(userId, TOKEN_TYPE, absoluteExpirationInSecs, null, compoundAuthenticationSessionId); - this.demoId = demoId; - } - - private DemoActionToken() { - // you must have this private constructor for deserializer - } - - public String getDemoId() { - return demoId; - } -} - ----- - - -==== Packaging classes and deployment - -To plug your own action token and its handler, you need to implement few interfaces on server side: - - * `org.keycloak.authentication.actiontoken.ActionTokenHandler` - actual handler of action token for a particular - action (i.e. for a given value of `typ` token field). -+ -The central method in that interface is `handleToken(token, context)` which defines actual operation executed upon -receiving the action token. Usually it is some alteration of authentication session notes but generally it can be -arbitrary. This method is only called if all verifiers (including those defined in `getVerifiers(context)`) have -succeeded, and it is guaranteed that the `token` would be of the class returned by `getTokenClass()` method. -+ -To be able to determine whether the action token was issued for the current authentication session as described in -<>, method for extracting authentication session ID has to be declared in -`getAuthenticationSessionIdFromToken(token, context)` method. The implementation in `DefaultActionToken` returns the -value of `asid` field from the token if it is defined. Note that you can override that method to return current -authentication session ID regardless of the token - that way you can create tokens that would step into the ongoing -authentication flow before any authentication flow would be started. -+ -If the authentication session from the token does not match the current one, the action token handler would be asked to -start a fresh one by calling `startFreshAuthenticationSession(token, context)`. It can throw a `VerificationException` -(or better its more descriptive variant `ExplainedTokenVerificationException`) to signal that would be forbidden. -+ -The token handler also determines via method `canUseTokenRepeatedly(token, context)` whether the token would be -invalidated after it is used and authentication completes. Note that if you would have a flow utilizing multiple action -token, only the last token would be invalidated. In that case, you should use -`org.keycloak.models.SingleUseObjectProvider` in action token handler to invalidate the used tokens manually. -+ -Default implementation of most of the `ActionTokenHandler` methods is the -`org.keycloak.authentication.actiontoken.AbstractActionTokenHandler` abstract class in `keycloak-services` module. The -only method that needs to be implemented is `handleToken(token, context)` that performs the actual action. - - * `org.keycloak.authentication.actiontoken.ActionTokenHandlerFactory` - factory that instantiates action token - handler. Implementations have to override `getId()` to return value that must match precisely the value of `typ` - field in the action token. -+ -Note that you have to register the custom `ActionTokenHandlerFactory` implementation as explained in the -<<_providers,Service Provider Interfaces>> section of this guide. - - diff --git a/server_development/topics/admin-rest-api.adoc b/server_development/topics/admin-rest-api.adoc deleted file mode 100644 index b398219aa..000000000 --- a/server_development/topics/admin-rest-api.adoc +++ /dev/null @@ -1,99 +0,0 @@ -== Admin REST API - -{project_name} comes with a fully functional Admin REST API with all features provided by the Admin Console. - -To invoke the API you need to obtain an access token with the appropriate permissions. The required permissions are described in the Server Administration Guide. - -You can obtain a token by enabling authentication for your application using {project_name}; see the Securing Applications and Services Guide. You can also use direct access grant to obtain an access token. - -=== Examples of using CURL - -==== Authenticating with a username and password - -.Procedure - -. Obtain an access token for the user in the realm `master` with username `admin` and password `password`: -+ -[source,bash,subs=+attributes] ----- -curl \ - -d "client_id=admin-cli" \ - -d "username=admin" \ - -d "password=password" \ - -d "grant_type=password" \ - "http://localhost:8080{kc_realms_path}/master/protocol/openid-connect/token" ----- -+ -NOTE: By default this token expires in 1 minute -+ -The result will be a JSON document. - -. Invoke the API you need by extracting the value of the `access_token` property. - -. Invoke the API by including the value in the `Authorization` header of requests to the API. -+ -The following example shows how to get the details of the master realm: -+ -[source,bash,subs="attributes+"] ----- -curl \ - -H "Authorization: bearer eyJhbGciOiJSUz..." \ - "http://localhost:8080{kc_admins_path}/realms/master" ----- - -==== Authenticating with a service account - -To authenticate against the Admin REST API using a `client_id` and a `client_secret`, perform this procedure. - -.Procedure - -. Make sure the client is configured as follows: - -* `client_id` is a **confidential** client that belongs to the realm *master* -* `client_id` has `Service Accounts Enabled` option enabled -* `client_id` has a custom "Audience" mapper - ** Included Client Audience: `security-admin-console` - -. Check that `client_id` has the role 'admin' assigned in the "Service Account Roles" tab. - -[source,bash,subs="attributes+"] ----- -curl \ - -d "client_id=" \ - -d "client_secret=" \ - -d "grant_type=client_credentials" \ - "http://localhost:8080{kc_realms_path}/master/protocol/openid-connect/token" ----- - -ifeval::[{project_community}==true] -=== Example using Java - -There's a Java client library for the Admin REST API that makes it easy to use from Java. To use it from your application add a dependency on the -`keycloak-admin-client` library. - -The following example shows how to use the Java client library to get the details of the master realm: - -[source,java,subs="attributes+"] ----- - -import org.keycloak.admin.client.Keycloak; -import org.keycloak.representations.idm.RealmRepresentation; -... - -Keycloak keycloak = Keycloak.getInstance( - "http://localhost:8080{kc_base_path}", - "master", - "admin", - "password", - "admin-cli"); -RealmRepresentation realm = keycloak.realm("master").toRepresentation(); ----- - -Complete Javadoc for the admin client is available at {apidocs_link}[{apidocs_name}]. -endif::[] - -=== Additional resources -[role="_additional-resources"] -* {adminguide_link}[{adminguide_name}] -* {adapterguide_link}[{adapterguide_name}] -* {apidocs_link}[{apidocs_name}] diff --git a/server_development/topics/auth-spi.adoc b/server_development/topics/auth-spi.adoc deleted file mode 100644 index 52a9f656d..000000000 --- a/server_development/topics/auth-spi.adoc +++ /dev/null @@ -1,1213 +0,0 @@ -[[_auth_spi]] -== Authentication SPI - -{project_name} includes a range of different authentication mechanisms: kerberos, password, otp and others. -These mechanisms may not meet all of your requirements and you may want to plug in your own custom ones. -{project_name} provides an authentication SPI that you can use to write new plugins. -The Admin Console supports applying, ordering, and configuring these new mechanisms. - -{project_name} also supports a simple registration form. -Different aspects of this form can be enabled and disabled for example -Recaptcha support can be turned off and on. -The same authentication SPI can be used to add another page to the registration flow or reimplement it entirely. -There's also an additional fine-grained SPI you can use to add specific validations and user extensions to the built-in registration form. - -A required action in {project_name} is an action that a user has to perform after he authenticates. -After the action is performed successfully, the user doesn't have to perform the action again. -{project_name} comes with some built in required actions like "reset password". This action forces the user to change their password after they have logged in. -You can write and plug in your own required actions. - -WARNING: If your authenticator or required action implementation is using some user attributes as the metadata attributes for linking/establishing the user identity, -then please make sure that users are not able to edit the attributes and the corresponding attributes are read-only. See the details in the link:{adminguide_link}#_read_only_user_attributes[Threat model mitigation chapter]. - -=== Terms - -To first learn about the Authentication SPI, let's go over some of the terms used to describe it. - -Authentication Flow:: - A flow is a container for all authentications that must happen during login or registration. - If you go to the Admin Console authentication page, you can view all the defined flows in the system and what authenticators they are made up of. - Flows can contain other flows. - You can also bind a new different flow for browser login, direct grant access, and registration. - -Authenticator:: - An authenticator is a pluggable component that hold the logic for performing the authentication or action within a flow. - It is usually a singleton. - -Execution:: - An execution is an object that binds the authenticator to the flow and the authenticator to the configuration of the authenticator. - Flows contain execution entries. - -Execution Requirement:: - Each execution defines how an authenticator behaves in a flow. - The requirement defines whether the authenticator is enabled, disabled, conditional, required, or an alternative. - An alternative requirement means that the authenticator is enough to validate the flow it's in, but isn't necessary. - For example, in the built-in browser flow, cookie authentication, the Identity Provider Redirector, and the set of all authenticators in the - forms subflow are all alternative. As they are executed in a sequential top-to-bottom order, if one of them is successful, the flow is - successful, and any following execution in the flow (or sub-flow) is not evaluated. - -Authenticator Config:: - This object defines the configuration for the Authenticator for a specific execution within an authentication flow. - Each execution can have a different config. - -Required Action:: - After authentication completes, the user might have one or more one-time actions he must complete before he is allowed to login. - The user might be required to set up an OTP token generator or reset an expired password or even accept a Terms and Conditions document. - -=== Algorithm overview - -Let's talk about how this all works for browser login. -Let's assume the following flows, executions and sub flows. -[source] ----- - -Cookie - ALTERNATIVE -Kerberos - ALTERNATIVE -Forms subflow - ALTERNATIVE - Username/Password Form - REQUIRED - Conditional OTP subflow - CONDITIONAL - Condition - User Configured - REQUIRED - OTP Form - REQUIRED ----- - -In the top level of the form we have 3 executions of which all are alternatively required. -This means that if any of these are successful, then the others do not have to execute. -The Username/Password form is not executed if there is an SSO Cookie set or a successful Kerberos login. -Let's walk through the steps from when a client first redirects to keycloak to authenticate the user. - -. The OpenID Connect or SAML protocol provider unpacks relevant data, verifies the client and any signatures. - It creates an AuthenticationSessionModel. - It looks up what the browser flow should be, then starts executing the flow. -. The flow looks at the cookie execution and sees that it is an alternative. - It loads the cookie provider. - It checks to see if the cookie provider requires that a user already be associated with the authentication session. - Cookie provider does not require a user. - If it did, the flow would abort and the user would see an error screen. - Cookie provider then executes. - Its purpose is to see if there is an SSO cookie set. - If there is one set, it is validated and the UserSessionModel is verified and associated with the AuthenticationSessionModel. - The Cookie provider returns a success() status if the SSO cookie exists and is validated. - Since the cookie provider returned success and each execution at this level of the flow is ALTERNATIVE, no other execution is executed and this results in a successful login. - If there is no SSO cookie, the cookie provider returns with a status of attempted(). This means there was no error condition, but no success either. - The provider tried, but the request just wasn't set up to handle this authenticator. -. Next the flow looks at the Kerberos execution. - This is also an alternative. - The kerberos provider also does not require a user to be already set up and associated with the AuthenticationSessionModel so this provider is executed. - Kerberos uses the SPNEGO browser protocol. - This requires a series of challenge/responses between the server and client exchanging negotiation headers. - The kerberos provider does not see any negotiate header, so it assumes that this is the first interaction between the server and client. - It therefore creates an HTTP challenge response to the client and sets a forceChallenge() status. - A forceChallenge() means that this HTTP response cannot be ignored by the flow and must be returned to the client. - If instead the provider returned a challenge() status, the flow would hold the challenge response until all other alternatives are attempted. - So, in this initial phase, the flow would stop and the challenge response would be sent back to the browser. - If the browser then responds with a successful negotiate header, the provider associates the user with the AuthenticationSession and the flow ends because the rest of the executions on this level of the flow are all alternatives. - Otherwise, again, the kerberos provider sets an attempted() status and the flow continues. -. The next execution is a subflow called Forms. - The executions for this subflow are loaded and the same processing logic occurs. -. The first execution in the Forms subflow is the UsernamePassword provider. - This provider also does not require for a user to already be associated with the flow. - This provider creates a challenge HTTP response and sets its status to challenge(). This execution is required, so the flow honors this challenge and sends the HTTP response back to the browser. - This response is a rendering of the Username/Password HTML page. - The user enters in their username and password and clicks submit. - This HTTP request is directed to the UsernamePassword provider. - If the user entered an invalid username or password, a new challenge response is created and a status of failureChallenge() is set for this execution. - A failureChallenge() means that there is a challenge, but that the flow should log this as an error in the error log. - This error log can be used to lock accounts or IP Addresses that have had too many login failures. - If the username and password is valid, the provider associated the UserModel with the AuthenticationSessionModel and returns a status of success(). -. The next execution is a subflow called Conditional OTP. The executions for this subflow are loaded and the same processing logic occurs. Its Requirement is - Conditional. This means that the flow will first evaluate all conditional executors that it contains. Conditional executors are authenticators that - implement `ConditionalAuthenticator`, and must implement the method `boolean matchCondition(AuthenticationFlowContext context)`. A conditional subflow will - call the `matchCondition` method of all conditional executions it contains, and if all of them evaluate to true, it will act as if it was a required subflow. If - not, it will act as if it was a disabled subflow. Conditional authenticators are only used for this purpose, and are not used as authenticators. - This means that even if the conditional authenticator evaluates to "true", then this will not mark a flow or subflow as successful. For example, - a flow containing only a Conditional subflow with only a conditional authenticator will never allow a user to log in. -. The first execution of the Conditional OTP subflow is the Condition - User Configured. - This provider requires that a user has been associated with the flow. - This requirement is satisfied because the UsernamePassword provider already associated the user with the flow. - This provider's `matchCondition` method will evaluate the `configuredFor` method for all other Authenticators in its current subflow. If the subflow contains - executors with their Requirement set to required, then the `matchCondition` method will only evaluate to true if all the required authenticators' `configuredFor` - method evaluate to true. Otherwise, the `matchCondition` method will evaluate to true if any alternative authenticator evaluates to true. -. The next execution is the OTP Form. - This provider also requires that a user has been associated with the flow. - This requirement is satisfied because the UsernamePassword provider already associated the user with the flow. - Since a user is required for this provider, the provider is also asked if the user is configured to use this provider. - If user is not configured, then the flow will then set up a required action that the user must perform after authentication is complete. - For OTP, this means the OTP setup page. If the user is configured, he will be asked to enter his otp code. In our scenario, because of the conditional - sub-flow, the user will never see the OTP login page, unless the Conditional OTP subflow is set to Required. -. After the flow is complete, the authentication processor creates a UserSessionModel and associates it with the AuthenticationSessionModel. - It then checks to see if the user is required to complete any required actions before logging in. -. First, each required action's evaluateTriggers() method is called. - This allows the required action provider to figure out if there is some state that might trigger the action to be fired. - For example, if your realm has a password expiration policy, it might be triggered by this method. -. Each required action associated with the user that has its requiredActionChallenge() method called. - Here the provider sets up an HTTP response which renders the page for the required action. - This is done by setting a challenge status. -. If the required action is ultimately successful, then the required action is removed from the user's required actions list. -. After all required actions have been resolved, the user is finally logged in. - -[[_auth_spi_walkthrough]] -=== Authenticator SPI walk through - -In this section, we'll take a look at the Authenticator interface. -For this, we are going to implement an authenticator that requires that a user enter in the answer to a secret question like "What is your mother's maiden name?". -This example is fully implemented and contained in the examples/providers/authenticator directory of the demo distribution of {project_name}. - -To create an authenticator, you must at minimum implement the org.keycloak.authentication.AuthenticatorFactory and Authenticator interfaces. -The Authenticator interface defines the logic. The AuthenticatorFactory is responsible for creating instances of an Authenticator. -They both extend a more generic Provider and ProviderFactory set of interfaces that other {project_name} components like User Federation do. - -Some authenticators, like the CookieAuthenticator don't rely on a Credential that the user has or knows to authenticate the user. -However, some authenticators, such as the PasswordForm authenticator or the OTPFormAuthenticator rely on the user inputting some -information and verifying that information against some information in the -database. For the PasswordForm for example, the authenticator will verify the hash of the password against a hash stored in the database, while the -OTPFormAuthenticator will verify the OTP received against the one generated from the shared secret stored in the database. - -These types of authenticators are called CredentialValidators, and will require you to implement a few more classes: - -* A class that extends org.keycloak.credential.CredentialModel, and that can generate the correct format of the credential in the database -* A class implementing the org.keycloak.credential.CredentialProvider and interface, and a class implementing its CredentialProviderFactory factory interface. - -The SecretQuestionAuthenticator we'll see in this walk through is a CredentialValidator, so we'll see how to implement all these classes. - -==== Packaging classes and deployment - -You will package your classes within a single jar. -This jar must contain a file named `org.keycloak.authentication.AuthenticatorFactory` and must be contained in the `META-INF/services/` directory of your jar. -This file must list the fully qualified class name of each AuthenticatorFactory implementation you have in the jar. -For example: - -[source,java] ----- -org.keycloak.examples.authenticator.SecretQuestionAuthenticatorFactory -org.keycloak.examples.authenticator.AnotherProviderFactory ----- - -This services/ file is used by {project_name} to scan the providers it has to load into the system. - -To deploy this jar, just copy it to the providers directory. - -==== Extending the CredentialModel class - -In {project_name}, credentials are stored in the database in the Credentials table. It has the following structure: - ----- ------------------------------ -| ID | ------------------------------ -| user_ID | ------------------------------ -| credential_type | ------------------------------ -| created_date | ------------------------------ -| user_label | ------------------------------ -| secret_data | ------------------------------ -| credential_data | ------------------------------ -| priority | ------------------------------ ----- - -Where: - -* `ID` is the primary key of the credential. -* `user_ID` is the foreign key linking the credential to a user. -* `credential_type` is a string set during the creation that must reference an existing credential type. -* `created_date` is the creation timestamp (in long format) of the credential. -* `user_label` is the editable name of the credential by the user -* `secret_data` contains a static json with the information that cannot be transmitted outside of {project_name} -* `credential_data` contains a json with the static information of the credential that can be shared in the Admin Console or via the REST API. -* `priority` defines how "preferred" a credential is for a user, to determine which credential to present when a user has multiple choices. - -As the secret_data and credential_data fields are designed to contain json, it is up to you to determine how to structure, read and write into -these fields, allowing you a lot of flexibility. - -For this example, we are going to use a very simple credential data, containing only the question asked to the user: - -[source] ----- -{ - "question":"aQuestion" -} ----- - -with an equally simple secret data, containing only the secret answer: - -[source] ----- -{ - "answer":"anAnswer" -} ----- - -Here the answer will be kept in plain text in the database for the sake of simplicity, but it would also be possible to have a salted hash for the answer, -as is the case for passwords in {project_name}. In this case, the secret data would also have to contain a field for the salt, and the credential data information -about the algorithm such as the type of algorithm used and the number of iterations used. For more details you can consult the implementation of the -`org.keycloak.models.credential.PasswordCredentialModel` class. - -In our case we create the class `SecretQuestionCredentialModel`: - - -[source,java] ----- -public class SecretQuestionCredentialModel extends CredentialModel { - public static final String TYPE = "SECRET_QUESTION"; - - private final SecretQuestionCredentialData credentialData; - private final SecretQuestionSecretData secretData; ----- - -Where `TYPE` is the credential_type we write in the database. For consistency, we make sure that this String is always the one referenced when -getting the type for this credential. The classes `SecretQuestionCredentialData` and `SecretQuestionSecretData` are used to marshal and unmarshal the json: - -[source,java] ----- -public class SecretQuestionCredentialData { - - private final String question; - - @JsonCreator - public SecretQuestionCredentialData(@JsonProperty("question") String question) { - this.question = question; - } - - public String getQuestion() { - return question; - } -} ----- - -[source,java] ----- -public class SecretQuestionSecretData { - - private final String answer; - - @JsonCreator - public SecretQuestionSecretData(@JsonProperty("answer") String answer) { - this.answer = answer; - } - - public String getAnswer() { - return answer; - } -} ----- - -To be fully usable, the `SecretQuestionCredentialModel` objects must both contain the raw json data from its parent class, -and the unmarshalled objects in its own attributes. This leads us to create a method which reads from a simple CredentialModel, -such as is created when reading from the database, to make a `SecretQuestionCredentialModel`: - -[source,java] ----- -private SecretQuestionCredentialModel(SecretQuestionCredentialData credentialData, SecretQuestionSecretData secretData) { - this.credentialData = credentialData; - this.secretData = secretData; -} - -public static SecretQuestionCredentialModel createFromCredentialModel(CredentialModel credentialModel){ - try { - SecretQuestionCredentialData credentialData = JsonSerialization.readValue(credentialModel.getCredentialData(), SecretQuestionCredentialData.class); - SecretQuestionSecretData secretData = JsonSerialization.readValue(credentialModel.getSecretData(), SecretQuestionSecretData.class); - - SecretQuestionCredentialModel secretQuestionCredentialModel = new SecretQuestionCredentialModel(credentialData, secretData); - secretQuestionCredentialModel.setUserLabel(credentialModel.getUserLabel()); - secretQuestionCredentialModel.setCreatedDate(credentialModel.getCreatedDate()); - secretQuestionCredentialModel.setType(TYPE); - secretQuestionCredentialModel.setId(credentialModel.getId()); - secretQuestionCredentialModel.setSecretData(credentialModel.getSecretData()); - secretQuestionCredentialModel.setCredentialData(credentialModel.getCredentialData()); - return secretQuestionCredentialModel; - } catch (IOException e){ - throw new RuntimeException(e); - } -} ----- - -And a method to create a `SecretQuestionCredentialModel` from the question and answer: - -[source,java] ----- -private SecretQuestionCredentialModel(String question, String answer) { - credentialData = new SecretQuestionCredentialData(question); - secretData = new SecretQuestionSecretData(answer); -} - -public static SecretQuestionCredentialModel createSecretQuestion(String question, String answer) { - SecretQuestionCredentialModel credentialModel = new SecretQuestionCredentialModel(question, answer); - credentialModel.fillCredentialModelFields(); - return credentialModel; -} - -private void fillCredentialModelFields(){ - try { - setCredentialData(JsonSerialization.writeValueAsString(credentialData)); - setSecretData(JsonSerialization.writeValueAsString(secretData)); - setType(TYPE); - setCreatedDate(Time.currentTimeMillis()); - } catch (IOException e) { - throw new RuntimeException(e); - } -} ----- - -==== Implementing a CredentialProvider - -As with all Providers, to allow {project_name} to generate the CredentialProvider, we require a CredentialProviderFactory. For this requirement we create -the SecretQuestionCredentialProviderFactory, whose `create` method will be called when a SecretQuestionCredentialProvider is asked for: - -[source,java] ----- -public class SecretQuestionCredentialProviderFactory implements CredentialProviderFactory { - - public static final String PROVIDER_ID = "secret-question"; - - @Override - public String getId() { - return PROVIDER_ID; - } - - @Override - public CredentialProvider create(KeycloakSession session) { - return new SecretQuestionCredentialProvider(session); - } -} ----- - -The CredentialProvider interface takes a generic parameter that extends a CredentialModel. In our case we to use the SecretQuestionCredentialModel we created: - -[source,java] ----- -public class SecretQuestionCredentialProvider implements CredentialProvider, CredentialInputValidator { - private static final Logger logger = Logger.getLogger(SecretQuestionCredentialProvider.class); - - protected KeycloakSession session; - - public SecretQuestionCredentialProvider(KeycloakSession session) { - this.session = session; - } - - private UserCredentialStore getCredentialStore() { - return session.userCredentialManager(); - } ----- - -We also want to implement the CredentialInputValidator interface, as this allows {project_name} to know that this provider can also be used to validate a -credential for an Authenticator. For the CredentialProvider interface, the first method that needs to be implemented is the `getType()` method. This will simply -return the `SecretQuestionCredentialModel`'s TYPE String: - -[source,java] ----- -@Override -public String getType() { - return SecretQuestionCredentialModel.TYPE; -} ----- - -The second method is to create a `SecretQuestionCredentialModel` from a `CredentialModel`. For this method we simply call the existing static method -from `SecretQuestionCredentialModel`: - -[source,java] ----- -@Override -public SecretQuestionCredentialModel getCredentialFromModel(CredentialModel model) { - return SecretQuestionCredentialModel.createFromCredentialModel(model); -} ----- - -Finally, we have the methods to create a credential and delete a credential. These methods call the KeycloakSession's `userCredentialManager`, which -is responsible for knowing where to read or write the credential, for example local storage or federated storage. - -[source,java] ----- -@Override -public CredentialModel createCredential(RealmModel realm, UserModel user, SecretQuestionCredentialModel credentialModel) { - if (credentialModel.getCreatedDate() == null) { - credentialModel.setCreatedDate(Time.currentTimeMillis()); - } - return getCredentialStore().createCredential(realm, user, credentialModel); -} - -@Override -public boolean deleteCredential(RealmModel realm, UserModel user, String credentialId) { - return getCredentialStore().removeStoredCredential(realm, user, credentialId); -} ----- - -For the CredentialInputValidator, the main method to implement is the `isValid`, which tests whether a credential is valid for a -given user in a given realm. This is the method that is called by the Authenticator when it seeks to validate the user's input. Here we -simply need to check that the input String is the one recorded in the Credential: - -[source,java] ----- -@Override -public boolean isValid(RealmModel realm, UserModel user, CredentialInput input) { - if (!(input instanceof UserCredentialModel)) { - logger.debug("Expected instance of UserCredentialModel for CredentialInput"); - return false; - } - if (!input.getType().equals(getType())) { - return false; - } - String challengeResponse = input.getChallengeResponse(); - if (challengeResponse == null) { - return false; - } - CredentialModel credentialModel = getCredentialStore().getStoredCredentialById(realm, user, input.getCredentialId()); - SecretQuestionCredentialModel sqcm = getCredentialFromModel(credentialModel); - return sqcm.getSecretQuestionSecretData().getAnswer().equals(challengeResponse); -} ----- - -The other two methods to implement are a test if the CredentialProvider supports the given credential type and a test to check -if the credential type is configured for a given user. For our case, the latter test simply means checking if the user has a credential -of the SECRET_QUESTION type: - -[source,java] ----- -@Override -public boolean supportsCredentialType(String credentialType) { - return getType().equals(credentialType); -} - -@Override -public boolean isConfiguredFor(RealmModel realm, UserModel user, String credentialType) { - if (!supportsCredentialType(credentialType)) return false; - return !getCredentialStore().getStoredCredentialsByType(realm, user, credentialType).isEmpty(); -} ----- - -==== Implementing an authenticator - -When implementing an authenticator that uses Credentials to authenticate a user, you should have the authenticator implement -the CredentialValidator interface. This interfaces takes a class extending a CredentialProvider as a parameter, and will -allow {project_name} to directly call the methods from the CredentialProvider. The only method that needs to be implemented is -`getCredentialProvider` method, which in our example allows the SecretQuestionAuthenticator to retrieve the SecretQuestionCredentialProvider: - -[source,java] ----- -public SecretQuestionCredentialProvider getCredentialProvider(KeycloakSession session) { - return (SecretQuestionCredentialProvider)session.getProvider(CredentialProvider.class, SecretQuestionCredentialProviderFactory.PROVIDER_ID); -} ----- - -When implementing the Authenticator interface, the first method that needs to be implemented is the requiresUser() method. -For our example, this method must return true as we need to validate the secret question associated with the user. -A provider like kerberos would return false from this method as it can resolve a user from the negotiate header. -This example, however, is validating a specific credential of a specific user. - -The next method to implement is the configuredFor() method. -This method is responsible for determining if the user is configured for this particular authenticator. In our case, -we can just call the method implemented in the SecretQuestionCredentialProvider - -[source,java] ----- -@Override -public boolean configuredFor(KeycloakSession session, RealmModel realm, UserModel user) { - return getCredentialProvider(session).isConfiguredFor(realm, user, getType(session)); -} ----- - -The next method to implement on the Authenticator is setRequiredActions(). If configuredFor() returns false and our example authenticator -is required within the flow, this method will be called, but only if the associated AuthenticatorFactory's `isUserSetupAllowed` method returns true. -The setRequiredActions() method is responsible for registering any required actions that must be performed by the user. -In our example, we need to register a required action that will force the user to set up the answer to the secret question. -We will implement this required action provider later in this chapter. -Here is the implementation of the setRequiredActions() method. - -[source,java] ----- - @Override - public void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user) { - user.addRequiredAction("SECRET_QUESTION_CONFIG"); - } ----- - -Now we are getting into the meat of the Authenticator implementation. -The next method to implement is authenticate(). This is the initial method the flow invokes when the execution is first visited. -What we want is that if a user has answered the secret question already on their browser's machine, then the user doesn't -have to answer the question again, making that machine "trusted". The authenticate() method isn't responsible for processing the secret question form. -Its sole purpose is to render the page or to continue the flow. - -[source,java] ----- -@Override -public void authenticate(AuthenticationFlowContext context) { - if (hasCookie(context)) { - context.success(); - return; - } - Response challenge = context.form() - .createForm("secret-question.ftl"); - context.challenge(challenge); -} - -protected boolean hasCookie(AuthenticationFlowContext context) { - Cookie cookie = context.getHttpRequest().getHttpHeaders().getCookies().get("SECRET_QUESTION_ANSWERED"); - boolean result = cookie != null; - if (result) { - System.out.println("Bypassing secret question because cookie is set"); - } - return result; -} ----- - -The hasCookie() method checks to see if there is already a cookie set on the browser which indicates that the secret question has already been answered. -If that returns true, we just mark this execution's status as SUCCESS using the AuthenticationFlowContext.success() method and returning from the authentication() method. - -If the hasCookie() method returns false, we must return a response that renders the secret question HTML form. -AuthenticationFlowContext has a form() method that initializes a Freemarker page builder with appropriate base information needed to build the form. -This page builder is called `org.keycloak.login.LoginFormsProvider`. The LoginFormsProvider.createForm() method loads a Freemarker template file from your login theme. -Additionally you can call the LoginFormsProvider.setAttribute() method if you want to pass additional information to the Freemarker template. -We'll go over this later. - -Calling LoginFormsProvider.createForm() returns a JAX-RS Response object. -We then call AuthenticationFlowContext.challenge() passing in this response. -This sets the status of the execution as CHALLENGE and if the execution is Required, this JAX-RS Response object will be sent to the browser. - -So, the HTML page asking for the answer to a secret question is displayed to the user and the user enters in the answer and clicks submit. -The action URL of the HTML form will send an HTTP request to the flow. -The flow will end up invoking the action() method of our Authenticator implementation. - -[source,java] ----- -@Override -public void action(AuthenticationFlowContext context) { - boolean validated = validateAnswer(context); - if (!validated) { - Response challenge = context.form() - .setError("badSecret") - .createForm("secret-question.ftl"); - context.failureChallenge(AuthenticationFlowError.INVALID_CREDENTIALS, challenge); - return; - } - setCookie(context); - context.success(); -} ----- - -If the answer is not valid, we rebuild the HTML Form with an additional error message. -We then call AuthenticationFlowContext.failureChallenge() passing in the reason for the value and the JAX-RS response. -failureChallenge() works the same as challenge(), but it also records the failure so it can be analyzed by any attack detection service. - -If validation is successful, then we set a cookie to remember that the secret question has been answered and we call AuthenticationFlowContext.success(). - -The validation itself gets the data that was received from the form, and calls the isValid method from the SecretQuestionCredentialProvider. You'll notice -that there's a section of the code concerning getting the credential Id. This is because if {project_name} is configured to allow multiple types of alternative -authenticators, or if the user could record multiple credentials of the SECRET_QUESTION type (for example if we allowed to choose from several questions, -and we allowed the user to have answers for more than one of those questions), then {project_name} needs to know which credential is being used to log the user. -In case there is more than one credential, {project_name} allows the user to choose during the login which credential is being used, and the information is transmitted by -the form to the Authenticator. -In case the form doesn't present this information, credential id used is given by the CredentialProvider's `default getDefaultCredential` method, which will -return the "most preferred" credential of the correct type of the user, - -[source,java] ----- -protected boolean validateAnswer(AuthenticationFlowContext context) { - MultivaluedMap formData = context.getHttpRequest().getDecodedFormParameters(); - String secret = formData.getFirst("secret_answer"); - String credentialId = formData.getFirst("credentialId"); - if (credentialId == null || credentialId.isEmpty()) { - credentialId = getCredentialProvider(context.getSession()) - .getDefaultCredential(context.getSession(), context.getRealm(), context.getUser()).getId(); - } - - UserCredentialModel input = new UserCredentialModel(credentialId, getType(context.getSession()), secret); - return getCredentialProvider(context.getSession()).isValid(context.getRealm(), context.getUser(), input); -} ----- - -Next method is the setCookie(). -This is an example of providing configuration for the Authenticator. -In this case we want the max age of the cookie to be configurable. - -[source,java] ----- -protected void setCookie(AuthenticationFlowContext context) { - AuthenticatorConfigModel config = context.getAuthenticatorConfig(); - int maxCookieAge = 60 * 60 * 24 * 30; // 30 days - if (config != null) { - maxCookieAge = Integer.valueOf(config.getConfig().get("cookie.max.age")); - - } - URI uri = context.getUriInfo().getBaseUriBuilder().path("realms").path(context.getRealm().getName()).build(); - addCookie(context, "SECRET_QUESTION_ANSWERED", "true", - uri.getRawPath(), - null, null, - maxCookieAge, - false, true); -} ----- - -We obtain an AuthenticatorConfigModel from the AuthenticationFlowContext.getAuthenticatorConfig() method. -If configuration exists we pull the max age config out of it. -We will see how we can define what should be configured when we talk about the AuthenticatorFactory implementation. -The config values can be defined within the Admin Console if you set up config definitions in your AuthenticatorFactory implementation. - -[source,java] ----- -@Override - public CredentialTypeMetadata getCredentialTypeMetadata(CredentialTypeMetadataContext metadataContext) { - return CredentialTypeMetadata.builder() - .type(getType()) - .category(CredentialTypeMetadata.Category.TWO_FACTOR) - .displayName(SecretQuestionCredentialProviderFactory.PROVIDER_ID) - .helpText("secret-question-text") - .createAction(SecretQuestionAuthenticatorFactory.PROVIDER_ID) - .removeable(false) - .build(session); - } ----- - -The last method to implement in the SecretQuestionCredentialProvider class is getCredentialTypeMetadata(CredentialTypeMetadataContext metadataContext), which is an abstract method of the CredentialProvider interface. Each Credential provider has to provide and implement this method. The method returns an instance of CredentialTypeMetadata, -which should at least include type and category of authenticator, displayName and removable item. In this example, the builder -takes type of authenticator from method getType(), category is Two Factor (the authenticator can be used as second factor of authentication) -and removable, which is set up to false (user can't remove some previously registered credentials). - -Other items of builder are helpText (will be shown to the user on various screens), createAction (the providerID of the required action, -which can be used by the user to create new credential) or updateAction (same as createAction, but instead of creating the new credential, it will update the credential). - -==== Implementing an AuthenticatorFactory - -The next step in this process is to implement an AuthenticatorFactory. -This factory is responsible for instantiating an Authenticator. -It also provides deployment and configuration metadata about the Authenticator. - -The getId() method is just the unique name of the component. -The create() method is called by the runtime to allocate and process the Authenticator. - -[source,java] ----- - -public class SecretQuestionAuthenticatorFactory implements AuthenticatorFactory, ConfigurableAuthenticatorFactory { - - public static final String PROVIDER_ID = "secret-question-authenticator"; - private static final SecretQuestionAuthenticator SINGLETON = new SecretQuestionAuthenticator(); - - @Override - public String getId() { - return PROVIDER_ID; - } - - @Override - public Authenticator create(KeycloakSession session) { - return SINGLETON; - } ----- - -The next thing the factory is responsible for is to specify the allowed requirement switches. -While there are four different requirement types: ALTERNATIVE, REQUIRED, CONDITIONAL, DISABLED, AuthenticatorFactory implementations can limit which -requirement options are shown in the Admin Console when defining a flow. CONDITIONAL should only always be used for subflows, and unless there's a good -reason for doing otherwise, the requirement on an authenticator should be REQUIRED, ALTERNATIVE and DISABLED: - -[source,java] ----- - - private static AuthenticationExecutionModel.Requirement[] REQUIREMENT_CHOICES = { - AuthenticationExecutionModel.Requirement.REQUIRED, - AuthenticationExecutionModel.Requirement.ALTERNATIVE, - AuthenticationExecutionModel.Requirement.DISABLED - }; - @Override - public AuthenticationExecutionModel.Requirement[] getRequirementChoices() { - return REQUIREMENT_CHOICES; - } ----- - -The AuthenticatorFactory.isUserSetupAllowed() is a flag that tells the flow manager whether or not Authenticator.setRequiredActions() method will be called. -If an Authenticator is not configured for a user, the flow manager checks isUserSetupAllowed(). If it is false, then the flow aborts with an error. -If it returns true, then the flow manager will invoke Authenticator.setRequiredActions(). - -[source,java] ----- - - @Override - public boolean isUserSetupAllowed() { - return true; - } ----- - -The next few methods define how the Authenticator can be configured. -The isConfigurable() method is a flag which specifies to the Admin Console on whether the Authenticator can be configured within a flow. -The getConfigProperties() method returns a list of ProviderConfigProperty objects. -These objects define a specific configuration attribute. - -[source,java] ----- - - @Override - public List getConfigProperties() { - return configProperties; - } - - private static final List configProperties = new ArrayList(); - - static { - ProviderConfigProperty property; - property = new ProviderConfigProperty(); - property.setName("cookie.max.age"); - property.setLabel("Cookie Max Age"); - property.setType(ProviderConfigProperty.STRING_TYPE); - property.setHelpText("Max age in seconds of the SECRET_QUESTION_COOKIE."); - configProperties.add(property); - } ----- - -Each ProviderConfigProperty defines the name of the config property. -This is the key used in the config map stored in AuthenticatorConfigModel. -The label defines how the config option will be displayed in the Admin Console. -The type defines if it is a String, Boolean, or other type. -The Admin Console will display different UI inputs depending on the type. -The help text is what will be shown in the tooltip for the config attribute in the Admin Console. -Read the javadoc of ProviderConfigProperty for more detail. - -The rest of the methods are for the Admin Console. -getHelpText() is the tooltip text that will be shown when you are picking the Authenticator you want to bind to an execution. -getDisplayType() is the text that will be shown in the Admin Console when listing the Authenticator. -getReferenceCategory() is just a category the Authenticator belongs to. - -==== Adding an authenticator form - -{project_name} comes with a Freemarker <<_themes,theme and template engine>>. -The createForm() method you called within authenticate() of your Authenticator class, builds an HTML page from a file within your login theme: `secret-question.ftl`. -This file should be added to the `theme-resources/templates` in your JAR, see <<_theme_resource,Theme Resource Provider>> for more details. - -Let's take a bigger look at secret-question.ftl Here's a small code snippet: - -[source,xml] ----- - -
-
-
- -
- -
- -
-
-
----- - -Any piece of text enclosed in `${}` corresponds to an attribute or template function. -If you see the form's action, you see it points to `${url.loginAction}`. -This value is automatically generated when you invoke the AuthenticationFlowContext.form() method. -You can also obtain this value by calling the AuthenticationFlowContext.getActionURL() method in Java code. - -You'll also see `${properties.someValue}`. -These correspond to properties defined in your theme.properties file of our theme. - `${msg("someValue")}` corresponds to the internationalized message bundles (.properties files) included with the login theme messages/ directory. -If you're just using english, you can just add the value of the `loginSecretQuestion`. -This should be the question you want to ask the user. - -When you call AuthenticationFlowContext.form() this gives you a LoginFormsProvider instance. -If you called, `LoginFormsProvider.setAttribute("foo", "bar")`, the value of "foo" would be available for reference in your form as `${foo}`. -The value of an attribute can be any Java bean as well. - -If you look at the top of the file, you'll see that we are importing a template: - -[source,xml] ----- -<#import "select.ftl" as layout> ----- - -Importing this template, instead of the standard `template.ftl` allows {project_name} to display a dropdown box that allows the user to select -a different credential or execution. - -[[_adding_authenticator]] -==== Adding an authenticator to a flow - -Adding an Authenticator to a flow must be done in the Admin Console. -If you go to the Authentication menu item and go to the Flow tab, you will be able to view the currently defined flows. -You cannot modify built in flows, so, to add the Authenticator we've created you have to copy an existing flow or create your own. -Our hope is that the user interface is sufficiently clear so that you can determine how to create a flow and add the Authenticator. For -more details, see the `Authentication Flows` chapter in link:{adminguide_link}[{adminguide_name}] . - -After you've created your flow, you have to bind it to the login action you want to bind it to. -If you go to the Authentication menu and go to the Bindings tab you will see options to bind a flow to the browser, registration, or direct grant flow. - -=== Required action walkthrough - -In this section we will discuss how to define a required action. -In the Authenticator section you may have wondered, "How will we get the user's answer to the secret question entered into the system?". As we showed in the example, if the answer is not set up, a required action will be triggered. -This section discusses how to implement the required action for the Secret Question Authenticator. - -==== Packaging classes and deployment - -You will package your classes within a single jar. -This jar does not have to be separate from other provider classes but it must contain a file named `org.keycloak.authentication.RequiredActionFactory` and must be contained in the `META-INF/services/` directory of your jar. -This file must list the fully qualified classname of each RequiredActionFactory implementation you have in the jar. -For example: - -[source,java] ----- -org.keycloak.examples.authenticator.SecretQuestionRequiredActionFactory ----- - -This services/ file is used by {project_name} to scan the providers it has to load into the system. - -To deploy this jar, copy it to the `providers/` directory, then run `bin/kc.[sh|bat] build`. - -==== Implement the RequiredActionProvider - -Required actions must first implement the RequiredActionProvider interface. -The RequiredActionProvider.requiredActionChallenge() is the initial call by the flow manager into the required action. -This method is responsible for rendering the HTML form that will drive the required action. - -[source,java] ----- - - @Override - public void requiredActionChallenge(RequiredActionContext context) { - Response challenge = context.form().createForm("secret_question_config.ftl"); - context.challenge(challenge); - - } ----- - -You see that RequiredActionContext has similar methods to AuthenticationFlowContext. -The form() method allows you to render the page from a Freemarker template. -The action URL is preset by the call to this form() method. -You just need to reference it within your HTML form. -I'll show you this later. - -The challenge() method notifies the flow manager that a required action must be executed. - -The next method is responsible for processing input from the HTML form of the required action. -The action URL of the form will be routed to the RequiredActionProvider.processAction() method - -[source,java] ----- - - @Override - public void processAction(RequiredActionContext context) { - String answer = (context.getHttpRequest().getDecodedFormParameters().getFirst("answer")); - UserCredentialValueModel model = new UserCredentialValueModel(); - model.setValue(answer); - model.setType(SecretQuestionAuthenticator.CREDENTIAL_TYPE); - context.getUser().updateCredentialDirectly(model); - context.success(); - } ----- - -The answer is pulled out of the form post. -A UserCredentialValueModel is created and the type and value of the credential are set. -Then UserModel.updateCredentialDirectly() is invoked. -Finally, RequiredActionContext.success() notifies the container that the required action was successful. - -==== Implement the RequiredActionFactory - -This class is really simple. -It is just responsible for creating the required action provider instance. - -[source,java] ----- - -public class SecretQuestionRequiredActionFactory implements RequiredActionFactory { - - private static final SecretQuestionRequiredAction SINGLETON = new SecretQuestionRequiredAction(); - - @Override - public RequiredActionProvider create(KeycloakSession session) { - return SINGLETON; - } - - - @Override - public String getId() { - return SecretQuestionRequiredAction.PROVIDER_ID; - } - - @Override - public String getDisplayText() { - return "Secret Question"; - } ----- - -The getDisplayText() method is just for the Admin Console when it wants to display a friendly name for the required action. - -==== Enable required action - -The final thing you have to do is go into the Admin Console. -Click on the Authentication left menu. -Click on the Required Actions tab. -Click on the Register button and choose your new Required Action. -Your new required action should now be displayed and enabled in the required actions list. - -=== Modifying or extending the registration form - -It is entirely possible for you to implement your own flow with a set of Authenticators to totally change how registration is done in {project_name}. -But what you'll usually want to do is just add a bit of validation to the out-of-the-box registration page. -An additional SPI was created to be able to do this. -It basically allows you to add validation of form elements on the page as well as to initialize UserModel attributes and data after the user has been registered. -We'll look at both the implementation of the user profile registration processing as well as the registration Google Recaptcha plugin. - -==== Implementation FormAction interface - -The core interface you have to implement is the FormAction interface. -A FormAction is responsible for rendering and processing a portion of the page. -Rendering is done in the buildPage() method, validation is done in the validate() method, post validation operations are done in success(). Let's first take a look at buildPage() method of the Recaptcha plugin. - -[source,java] ----- - - @Override - public void buildPage(FormContext context, LoginFormsProvider form) { - AuthenticatorConfigModel captchaConfig = context.getAuthenticatorConfig(); - if (captchaConfig == null || captchaConfig.getConfig() == null - || captchaConfig.getConfig().get(SITE_KEY) == null - || captchaConfig.getConfig().get(SITE_SECRET) == null - ) { - form.addError(new FormMessage(null, Messages.RECAPTCHA_NOT_CONFIGURED)); - return; - } - String siteKey = captchaConfig.getConfig().get(SITE_KEY); - form.setAttribute("recaptchaRequired", true); - form.setAttribute("recaptchaSiteKey", siteKey); - form.addScript("https://www.google.com/recaptcha/api.js"); - } ----- - -The Recaptcha buildPage() method is a callback by the form flow to help render the page. -It receives a form parameter which is a LoginFormsProvider. -You can add additional attributes to the form provider so that they can be displayed in the HTML page generated by the registration Freemarker template. - -The code above is from the registration recaptcha plugin. -Recaptcha requires some specific settings that must be obtained from configuration. -FormActions are configured in the exact same as Authenticators are. -In this example, we pull the Google Recaptcha site key from configuration and add it as an attribute to the form provider. -Our registration template file can read this attribute now. - -Recaptcha also has the requirement of loading a JavaScript script. -You can do this by calling LoginFormsProvider.addScript() passing in the URL. - -For user profile processing, there is no additional information that it needs to add to the form, so its buildPage() method is empty. - -The next meaty part of this interface is the validate() method. -This is called immediately upon receiving a form post. -Let's look at the Recaptcha's plugin first. - -[source,java] ----- - - @Override - public void validate(ValidationContext context) { - MultivaluedMap formData = context.getHttpRequest().getDecodedFormParameters(); - List errors = new ArrayList<>(); - boolean success = false; - - String captcha = formData.getFirst(G_RECAPTCHA_RESPONSE); - if (!Validation.isBlank(captcha)) { - AuthenticatorConfigModel captchaConfig = context.getAuthenticatorConfig(); - String secret = captchaConfig.getConfig().get(SITE_SECRET); - - success = validateRecaptcha(context, success, captcha, secret); - } - if (success) { - context.success(); - } else { - errors.add(new FormMessage(null, Messages.RECAPTCHA_FAILED)); - formData.remove(G_RECAPTCHA_RESPONSE); - context.validationError(formData, errors); - return; - - - } - } ----- - -Here we obtain the form data that the Recaptcha widget adds to the form. -We obtain the Recaptcha secret key from configuration. -We then validate the recaptcha. -If successful, ValidationContext.success() is called. -If not, we invoke ValidationContext.validationError() passing in the formData (so the user doesn't have to re-enter data), we also specify an error message we want displayed. -The error message must point to a message bundle property in the internationalized message bundles. -For other registration extensions validate() might be validating the format of a form element, for example an alternative email attribute. - -Let's also look at the user profile plugin that is used to validate email address and other user information when registering. - -[source,java] ----- - - @Override - public void validate(ValidationContext context) { - MultivaluedMap formData = context.getHttpRequest().getDecodedFormParameters(); - List errors = new ArrayList<>(); - - String eventError = Errors.INVALID_REGISTRATION; - - if (Validation.isBlank(formData.getFirst((RegistrationPage.FIELD_FIRST_NAME)))) { - errors.add(new FormMessage(RegistrationPage.FIELD_FIRST_NAME, Messages.MISSING_FIRST_NAME)); - } - - if (Validation.isBlank(formData.getFirst((RegistrationPage.FIELD_LAST_NAME)))) { - errors.add(new FormMessage(RegistrationPage.FIELD_LAST_NAME, Messages.MISSING_LAST_NAME)); - } - - String email = formData.getFirst(Validation.FIELD_EMAIL); - if (Validation.isBlank(email)) { - errors.add(new FormMessage(RegistrationPage.FIELD_EMAIL, Messages.MISSING_EMAIL)); - } else if (!Validation.isEmailValid(email)) { - formData.remove(Validation.FIELD_EMAIL); - errors.add(new FormMessage(RegistrationPage.FIELD_EMAIL, Messages.INVALID_EMAIL)); - } - - if (context.getSession().users().getUserByEmail(email, context.getRealm()) != null) { - formData.remove(Validation.FIELD_EMAIL); - errors.add(new FormMessage(RegistrationPage.FIELD_EMAIL, Messages.EMAIL_EXISTS)); - } - - if (errors.size() > 0) { - context.validationError(formData, errors); - return; - - } else { - context.success(); - } - } ----- - -As you can see, this validate() method of user profile processing makes sure that the email, first, and last name are filled in the form. -It also makes sure that email is in the right format. -If any of these validations fail, an error message is queued up for rendering. -Any fields in error are removed from the form data. -Error messages are represented by the FormMessage class. -The first parameter of the constructor of this class takes the HTML element id. -The input in error will be highlighted when the form is re-rendered. -The second parameter is a message reference id. -This id must correspond to a property in one of the localized message bundle files. -in the theme. - -After all validations have been processed then, the form flow then invokes the FormAction.success() method. -For recaptcha this is a no-op, so we won't go over it. -For user profile processing, this method fills in values in the registered user. - -[source,java] ----- - - @Override - public void success(FormContext context) { - UserModel user = context.getUser(); - MultivaluedMap formData = context.getHttpRequest().getDecodedFormParameters(); - user.setFirstName(formData.getFirst(RegistrationPage.FIELD_FIRST_NAME)); - user.setLastName(formData.getFirst(RegistrationPage.FIELD_LAST_NAME)); - user.setEmail(formData.getFirst(RegistrationPage.FIELD_EMAIL)); - } ----- - -Pretty simple implementation. -The UserModel of the newly registered user is obtained from the FormContext. -The appropriate methods are called to initialize UserModel data. - -Finally, you are also required to define a FormActionFactory class. -This class is implemented similarly to AuthenticatorFactory, so we won't go over it. - -==== Packaging the action - -You will package your classes within a single jar. -This jar must contain a file named `org.keycloak.authentication.FormActionFactory` and must be contained in the `META-INF/services/` directory of your jar. -This file must list the fully qualified class name of each FormActionFactory implementation you have in the jar. -For example: - -[source] ----- - -org.keycloak.authentication.forms.RegistrationProfile -org.keycloak.authentication.forms.RegistrationRecaptcha ----- - -This services/ file is used by {project_name} to scan the providers it has to load into the system. - -To deploy this jar, copy it to the `providers/` directory, then run `bin/kc.[sh|bat] build`. - -==== Adding FormAction to the registration flow - -Adding a FormAction to a registration page flow must be done in the Admin Console. -If you go to the Authentication menu item and go to the Flow tab, you will be able to view the currently defined flows. -You cannot modify built in flows, so, to add the Authenticator we've created you have to copy an existing flow or create your own. -I'm hoping the UI is intuitive enough so that you can figure out for yourself how to create a flow and add the FormAction. - -Basically you'll have to copy the registration flow. -Then click Actions menu to the right of the Registration Form, and pick "Add execution" to add a new execution. -You'll pick the FormAction from the selection list. -Make sure your FormAction comes after "Registration User Creation" by using the down buttons to move it if your FormAction isn't already listed after "Registration User Creation". You want your FormAction to come after user creation because the success() method of Registration User Creation is responsible for creating the new UserModel. - -After you've created your flow, you have to bind it to registration. -If you go to the Authentication menu and go to the Bindings tab you will see options to bind a flow to the browser, registration, or direct grant flow. - -=== Modifying forgot password/credential flow - -{project_name} also has a specific authentication flow for forgot password, or rather credential reset initiated by a user. -If you go to the Admin Console flows page, there is a "reset credentials" flow. -By default, {project_name} asks for the email or username of the user and sends an email to them. -If the user clicks on the link, then they are able to reset both their password and OTP (if an OTP has been set up). You can disable automatic OTP reset by disabling the "Reset OTP" authenticator in the flow. - -You can add additional functionality to this flow as well. -For example, many deployments would like for the user to answer one or more secret questions in additional to sending an email with a link. -You could expand on the secret question example that comes with the distro and incorporate it into the reset credential flow. - -One thing to note if you are extending the reset credentials flow. -The first "authenticator" is just a page to obtain the username or email. -If the username or email exists, then the AuthenticationFlowContext.getUser() will return the located user. -Otherwise this will be null. -This form *WILL NOT* re-ask the user to enter an email or username if the previous email or username did not exist. -You need to prevent attackers from being able to guess valid users. -So, if AuthenticationFlowContext.getUser() returns null, you should proceed with the flow to make it look like a valid user was selected. -I suggest that if you want to add secret questions to this flow, you should ask these questions after the email is sent. -In other words, add your custom authenticator after the "Send Reset Email" authenticator. - -=== Modifying first broker login flow - -First Broker Login flow is used during first login with some identity provider. -Term `First Login` means that there is not yet existing {project_name} account linked with the particular authenticated identity provider account. - -[role="_additional-resource"] -.Additional resources -* See the `Identity Brokering` chapter in link:{adminguide_link}[{adminguide_name}] . - -[[_client_authentication]] -=== Authentication of clients - -{project_name} actually supports pluggable authentication for https://openid.net/specs/openid-connect-core-1_0.html[OpenID Connect] client applications. -Authentication of client (application) is used under the hood by the {project_name} adapter during sending any backchannel requests -to the {project_name} server (like the request for exchange code to access token after successful authentication or request to refresh token). -But the client authentication can be also used directly by you during `Direct Access grants` (represented by OAuth2 `Resource Owner Password Credentials Flow`) -or during `Service account` authentication (represented by OAuth2 `Client Credentials Flow`). - -[role="_additional-resource"] -.Additional resources -* For more details about {project_name} adapter and OAuth2 flows see link:{adapterguide_link}[{adapterguide_name}]. - -==== Default implementations - -Actually {project_name} has 2 default implementations of client authentication: - -Traditional authentication with client_id and client_secret:: - This is default mechanism mentioned in the https://openid.net/specs/openid-connect-core-1_0.html[OpenID Connect] or https://datatracker.ietf.org/doc/html/rfc6749[OAuth2] specification and {project_name} supports it since it's early days. - The public client needs to include `client_id` parameter with its ID in the POST request (so it's de facto not authenticated) and the confidential client needs to include `Authorization: Basic` header with the clientId and clientSecret used as username and password. - -Authentication with signed JWT:: - This is based on the https://datatracker.ietf.org/doc/html/rfc7523[JWT Bearer Token Profiles for OAuth 2.0] specification. - The client/adapter generates the https://datatracker.ietf.org/doc/html/rfc7519[JWT] and signs it with his private key. - The {project_name} then verifies the signed JWT with the client's public key and authenticates client based on it. - -See the demo example and especially the `examples/preconfigured-demo/product-app` for the example application showing -the application using client authentication with signed JWT. - -==== Implement your own client authenticator - -For plug your own client authenticator, you need to implement few interfaces on both client (adapter) and server side. - -Client side:: -Here you need to implement `org.keycloak.adapters.authentication.ClientCredentialsProvider` and put the implementation either to: - -* your WAR file into WEB-INF/classes . But in this case, the implementation can be used just for this single WAR application -* Some JAR file, which will be added into WEB-INF/lib of your WAR - * Some JAR file, which will be used as jboss module and configured in jboss-deployment-structure.xml of your WAR. In all cases, you also need to create the file `META-INF/services/org.keycloak.adapters.authentication.ClientCredentialsProvider` either in the WAR or in your JAR. - -Server side:: - Here you need to implement `org.keycloak.authentication.ClientAuthenticatorFactory` and `org.keycloak.authentication.ClientAuthenticator` . You also need to add the file `META-INF/services/org.keycloak.authentication.ClientAuthenticatorFactory` with the name of the implementation classes. - See <<_auth_spi_walkthrough,authenticators>> for more details. diff --git a/server_development/topics/custom-attributes.adoc b/server_development/topics/custom-attributes.adoc deleted file mode 100644 index 5e0b03209..000000000 --- a/server_development/topics/custom-attributes.adoc +++ /dev/null @@ -1,67 +0,0 @@ -[[_custom_user_attributes]] -== Custom user attributes - -You can add custom user attributes to the registration page and account management console with a custom theme. - -=== Registration page - -Use this procedure to enter custom attributes in the registration page. - -.Procedure - -. Copy the template `themes/base/login/register.ftl` to the login type of your custom theme. - -. Open the copy in an editor. -+ -For example, to add a mobile number to the registration page, add the following snippet to the form: -+ -[source,html] ----- -
-
- -
- -
- -
-
----- - -. Ensure the name of the input html element starts with `user.attributes`. In the example above, the attribute will be stored by {project_name} with the name `mobile`. - -. To see the changes, make sure your realm is using your custom theme for the login theme and open the registration page. - -=== Account Management Console - -Use this procedure to manage custom attributes in the user profile page in the account management console. - -.Procedure -. Copy the template `themes/base/account/account.ftl` to the -account type of your custom theme. - -. Open the copy in an editor. -+ -As an example to add a mobile number to the account page add the following snippet to the form: -+ -[source,html] ----- -
-
- -
- -
- -
-
----- - -. Ensure the name of the input html element starts with `user.attributes`. - -. To see the changes, make sure your realm is using your custom theme for the account theme and open the user profile page in the account management console. - -[role="_additional-resources"] -=== Additional resources - -* See <<_themes,Themes>> for how to create a custom theme. diff --git a/server_development/topics/events.adoc b/server_development/topics/events.adoc deleted file mode 100644 index 0a5ad26fa..000000000 --- a/server_development/topics/events.adoc +++ /dev/null @@ -1,8 +0,0 @@ -[[_events]] -== Event Listener SPI - -Writing an Event Listener Provider starts by implementing the `EventListenerProvider` and `EventListenerProviderFactory` interfaces. Please see the Javadoc -and examples for complete details on how to do this. - -For details on how to package and deploy a custom provider refer to the <<_providers,Service Provider Interfaces>> chapter. - diff --git a/server_development/topics/extensions.adoc b/server_development/topics/extensions.adoc deleted file mode 100644 index 2e88d7018..000000000 --- a/server_development/topics/extensions.adoc +++ /dev/null @@ -1,155 +0,0 @@ -[[_extensions]] - -== Extending the server - -The {project_name} SPI framework offers the possibility to implement or override particular built-in providers. However {project_name} -also provides capabilities to extend its core functionalities and domain. This includes possibilities to: - -* Add custom REST endpoints to the {project_name} server -* Add your own custom SPI -* Add custom JPA entities to the {project_name} data model - -[[_extensions_rest]] -=== Add custom REST endpoints - -This is a very powerful extension, which allows you to deploy your own REST endpoints to the {project_name} server. It enables all kinds of extensions, for example -the possibility to trigger functionality on the {project_name} server, which is not available through the default set of built-in {project_name} REST endpoints. - -To add a custom REST endpoint, you need to implement the `RealmResourceProviderFactory` and `RealmResourceProvider` interfaces. `RealmResourceProvider` has one important method: - -[source,java] ----- - -Object getResource(); - ----- - -Use this method to return an object, which acts as a https://github.com/jax-rs[JAX-RS Resource]. For more details, see the Javadoc and our examples. -There is a very simple example in the example distribution in `providers/rest` and there is a more advanced example in `providers/domain-extension`, -which shows how to add an authenticated REST endpoint and other functionalities like <<_extensions_spi, Adding your own SPI>> -or <<_extensions_jpa,Extending the datamodel with custom JPA entities>>. - -For details on how to package and deploy a custom provider, refer to the <<_providers,Service Provider Interfaces>> chapter. - -[[_extensions_spi]] -=== Add your own custom SPI - -A custom SPI is especially useful with Custom REST endpoints. Use this procedure to add your own SPI - -.Procedure - -. implement the interface `org.keycloak.provider.Spi` and define the ID of your SPI and the `ProviderFactory` and `Provider` classes. That looks like this: -+ -[source,java] ----- -package org.keycloak.examples.domainextension.spi; - -import ... - -public class ExampleSpi implements Spi { - - @Override - public boolean isInternal() { - return false; - } - - @Override - public String getName() { - return "example"; - } - - @Override - public Class getProviderClass() { - return ExampleService.class; - } - - @Override - @SuppressWarnings("rawtypes") - public Class getProviderFactoryClass() { - return ExampleServiceProviderFactory.class; - } - -} - ----- - -. Create the file `META-INF/services/org.keycloak.provider.Spi` and add the class of your SPI to it. For example: -+ -[source] ----- -org.keycloak.examples.domainextension.spi.ExampleSpi ----- - -. Create the interfaces `ExampleServiceProviderFactory`, which extends from `ProviderFactory` and `ExampleService`, which extends from `Provider`. -The `ExampleService` will usually contain the business methods you need for your use case. Note that the `ExampleServiceProviderFactory` instance -is always scoped per application, however `ExampleService` is scoped per-request (or more accurately per `KeycloakSession` lifecycle). - -. Finally you need to implement your providers in the same manner as described in the <<_providers,Service Provider Interfaces>> chapter. - -For more details, take a look at the example distribution at `providers/domain-extension`, which shows an Example SPI similar to the one above. - -[role="_additional-resources"] -.Additional resources -* <<_extensions_rest,Custom REST endpoints>> - -[[_extensions_jpa]] -=== Add custom JPA entities to the {project_name} data model - -If the {project_name} data model does not exactly match your desired solution, or if you want to add some core functionality to {project_name}, -or when you have your own REST endpoint, you might want to extend the {project_name} data model. We enable you to add your -own JPA entities to the {project_name} JPA `EntityManager` . - -To add your own JPA entities, you need to implement `JpaEntityProviderFactory` and `JpaEntityProvider`. The `JpaEntityProvider` -allows you to return a list of your custom JPA entities and provide the location and id of the Liquibase changelog. An example implementation can look like this: - -NOTE: This is an unsupported API, which means you can use it but there is no guarantee that it will not be removed or changed without warning. - -[source,java] ----- -public class ExampleJpaEntityProvider implements JpaEntityProvider { - - // List of your JPA entities. - @Override - public List> getEntities() { - return Collections.>singletonList(Company.class); - } - - // This is used to return the location of the Liquibase changelog file. - // You can return null if you don't want Liquibase to create and update the DB schema. - @Override - public String getChangelogLocation() { - return "META-INF/example-changelog.xml"; - } - - // Helper method, which will be used internally by Liquibase. - @Override - public String getFactoryId() { - return "sample"; - } - - ... -} ----- - -In the example above, we added a single JPA entity represented by class `Company`. In the code of your REST endpoint, you can then use something like -this to retrieve `EntityManager` and call DB operations on it. - - -[source,java] ----- -EntityManager em = session.getProvider(JpaConnectionProvider.class).getEntityManager(); -Company myCompany = em.find(Company.class, "123"); ----- - -The methods `getChangelogLocation` and `getFactoryId` are important to support automatic updating of your entities by Liquibase. https://www.liquibase.org/[Liquibase] -is a framework for updating the database schema, which {project_name} internally uses to create the DB schema and update the DB schema among versions. You may need to use -it as well and create a changelog for your entities. Note that versioning of your own Liquibase changelog is independent -of {project_name} versions. In other words, when you update to a new {project_name} version, you are not forced to update your -schema at the same time. And vice versa, you can update your schema even without updating the {project_name} version. The Liquibase update -is always done at the server startup, so to trigger a DB update of your schema, you just need to add the new changeset to your Liquibase changelog file (in the example above -it's the file `META-INF/example-changelog.xml` which must be packed in same JAR as the JPA entities and `ExampleJpaEntityProvider`) and then restart server. -The DB schema will be automatically updated at startup. - -For more details, take a look at the example distribution at example `providers/domain-extension`, which shows the `ExampleJpaEntityProvider` and `example-changelog.xml` described above. - -NOTE: Don't forget to always back up your database before doing any changes in the Liquibase changelog and triggering a DB update. diff --git a/server_development/topics/identity-brokering.adoc b/server_development/topics/identity-brokering.adoc deleted file mode 100644 index cf5ca9251..000000000 --- a/server_development/topics/identity-brokering.adoc +++ /dev/null @@ -1,8 +0,0 @@ - -== Identity Brokering APIs - -{project_name} can delegate authentication to a parent IDP for login. A typical example of this is the case -where you want users to be able to log in through a social provider such as Facebook or Google. You can -also link existing accounts to a brokered IDP. This section describes some APIs that your applications -can use as it pertains to identity brokering. - diff --git a/server_development/topics/identity-brokering/account-linking.adoc b/server_development/topics/identity-brokering/account-linking.adoc deleted file mode 100644 index d0d77ce1d..000000000 --- a/server_development/topics/identity-brokering/account-linking.adoc +++ /dev/null @@ -1,94 +0,0 @@ - -=== Client initiated account linking - -Some applications want to integrate with social providers like Facebook, but do not want to provide an option to login via -these social providers. {project_name} offers a browser-based API that applications can use to link an existing -user account to a specific external IDP. This is called client-initiated account linking. Account linking can only be initiated by OIDC applications. - -The way it works is that the application forwards the user's browser to a URL on the {project_name} server requesting -that it wants to link the user's account to a specific external provider (i.e. Facebook). The server -initiates a login with the external provider. The browser logs in at the external provider and is redirected -back to the server. The server establishes the link and redirects back to the application with a confirmation. - -There are some preconditions that must be met by the client application before it can initiate this protocol: - -* The desired identity provider must be configured and enabled for the user's realm in the admin console. -* The user account must already be logged in as an existing user via the OIDC protocol -* The user must have an `account.manage-account` or `account.manage-account-links` role mapping. -* The application must be granted the scope for those roles within its access token -* The application must have access to its access token as it needs information within it to generate the redirect URL. - -To initiate the login, the application must fabricate a URL and redirect the user's browser to this URL. The URL looks like this: - -[source,subs="attributes+"] ----- -/{auth-server-root}{kc_realms_path}/{realm}/broker/{provider}/link?client_id={id}&redirect_uri={uri}&nonce={nonce}&hash={hash} ----- - -Here's a description of each path and query param: - -provider:: - This is the provider alias of the external IDP that you defined in the `Identity Provider` section of the admin console. - -client_id:: - This is the OIDC client id of your application. When you registered the application as a client in the admin console, - you had to specify this client id. - -redirect_uri:: - This is the application callback URL you want to redirect to after the account link is established. It must be a valid - client redirect URI pattern. In other words, it must match one of the valid URL patterns you defined when you registered - the client in the admin console. - -nonce:: - This is a random string that your application must generate - -hash:: - This is a Base64 URL encoded hash. This hash is generated by Base64 URL encoding a SHA_256 hash of `nonce` + `token.getSessionState()` + `token.getIssuedFor()` + `provider`. - The token variable are obtained from the OIDC access token. Basically you are hashing the random nonce, the user session id, the client id, and the identity - provider alias you want to access. - -Here's an example of Java Servlet code that generates the URL to establish the account link. - - -[source,java,subs="attributes+"] ----- - KeycloakSecurityContext session = (KeycloakSecurityContext) httpServletRequest.getAttribute(KeycloakSecurityContext.class.getName()); - AccessToken token = session.getToken(); - String clientId = token.getIssuedFor(); - String nonce = UUID.randomUUID().toString(); - MessageDigest md = null; - try { - md = MessageDigest.getInstance("SHA-256"); - } catch (NoSuchAlgorithmException e) { - throw new RuntimeException(e); - } - String input = nonce + token.getSessionState() + clientId + provider; - byte[] check = md.digest(input.getBytes(StandardCharsets.UTF_8)); - String hash = Base64Url.encode(check); - request.getSession().setAttribute("hash", hash); - String redirectUri = ...; - String accountLinkUrl = KeycloakUriBuilder.fromUri(authServerRootUrl) - .path("{kc_realms_path}/{realm}/broker/{provider}/link") - .queryParam("nonce", nonce) - .queryParam("hash", hash) - .queryParam("client_id", clientId) - .queryParam("redirect_uri", redirectUri).build(realm, provider).toString(); ----- - -Why is this hash included? We do this so that the auth server is guaranteed to know that the client application initiated the request and no other rogue app -just randomly asked for a user account to be linked to a specific provider. The auth server will first check to see if the user is logged in by checking the SSO -cookie set at login. It will then try to regenerate the hash based on the current login and match it up to the hash sent by the application. - -After the account has been linked, the auth server will redirect back to the `redirect_uri`. If there is a problem servicing the link request, -the auth server may or may not redirect back to the `redirect_uri`. The browser may just end up at an error page instead of being redirected back -to the application. If there is an error condition and the auth server deems it safe enough to redirect back to the client app, an additional -`error` query parameter will be appended to the `redirect_uri`. - -[WARNING] - While this API guarantees that the application initiated the request, it does not completely prevent CSRF attacks for this operation. The application - is still responsible for guarding against CSRF attacks target at itself. - -==== Refreshing external tokens - -If you are using the external token generated by logging into the provider (i.e. a Facebook or GitHub token), you can refresh this token by re-initiating the account linking API. - diff --git a/server_development/topics/identity-brokering/tokens.adoc b/server_development/topics/identity-brokering/tokens.adoc deleted file mode 100644 index a11b0abb3..000000000 --- a/server_development/topics/identity-brokering/tokens.adoc +++ /dev/null @@ -1,26 +0,0 @@ - -=== Retrieving external IDP tokens - -{project_name} allows you to store tokens and responses from the authentication process with the external IDP. -For that, you can use the `Store Token` configuration option on the IDP's settings page. - -Application code can retrieve these tokens and responses to pull in extra user information, or to securely invoke requests on the external IDP. -For example, an application might want to use the Google token to invoke on other Google services and REST APIs. -To retrieve a token for a particular identity provider you need to send a request as follows: - -[source,subs="attributes+"] ----- -GET {kc_realms_path}/{realm}/broker/{provider_alias}/token HTTP/1.1 -Host: localhost:8080 -Authorization: Bearer ----- - -An application must have authenticated with {project_name} and have received an access token. This access token -will need to have the `broker` client-level role `read-token` set. This means that the user must have a role mapping for this role -and the client application must have that role within its scope. -In this case, given that you are accessing a protected service in {project_name}, you need to send the access token issued by {project_name} during the user authentication. -In the broker configuration page you can automatically assign this role to newly imported users by turning on the `Stored Tokens Readable` switch. - -These external tokens can be re-established by either logging in again through the provider, or using the client initiated account linking API. - - diff --git a/server_development/topics/locale-selector.adoc b/server_development/topics/locale-selector.adoc deleted file mode 100644 index 458b66e14..000000000 --- a/server_development/topics/locale-selector.adoc +++ /dev/null @@ -1,16 +0,0 @@ -[[_locale_selector]] -=== Locale selector - -By default, the locale is selected using the `DefaultLocaleSelectorProvider` which implements the `LocaleSelectorProvider` interface. English is the default language when internationalization is disabled. - -With internationalization enabled, the locale is resolved according to the logic described in the link:{adminguide_link}#_user_locale_selection[{adminguide_name}]. - -This behavior can be changed through the `LocaleSelectorSPI` by implementing the `LocaleSelectorProvider` and `LocaleSelectorProviderFactory`. - -The `LocaleSelectorProvider` interface has a single method, `resolveLocale`, which must return a locale given a `RealmModel` and a nullable `UserModel`. The actual request is available from the `KeycloakSession#getContext` method. - -Custom implementations can extend the `DefaultLocaleSelectorProvider` in order to reuse parts of the default behavior. For example to ignore the `Accept-Language` request header, a custom implementation could extend the default provider, override it's `getAcceptLanguageHeaderLocale`, and return a null value. As a result the locale selection will fall back on the realm's default language. - -[role="_additional-resources"] -=== Additional resources -* For more details on creating and deploying a custom provider, see <<_providers,Service Provider Interfaces>>. diff --git a/server_development/topics/preface.adoc b/server_development/topics/preface.adoc deleted file mode 100644 index 2636040a3..000000000 --- a/server_development/topics/preface.adoc +++ /dev/null @@ -1,20 +0,0 @@ -== Preface - -In some of the example listings, what is meant to be displayed on one line does not fit inside the available page width. These lines have been broken up. A '\' at the end of a line means that a break has been introduced to fit in the page, with the following lines indented. -So: - -[source] ----- -Let's pretend to have an extremely \ -long line that \ -does not fit -This one is short ----- -Is really: - -[source] ----- -Let's pretend to have an extremely long line that does not fit -This one is short ----- - diff --git a/server_development/topics/providers.adoc b/server_development/topics/providers.adoc deleted file mode 100644 index 0fcf83bba..000000000 --- a/server_development/topics/providers.adoc +++ /dev/null @@ -1,397 +0,0 @@ -[[_providers]] - -== Service Provider Interfaces (SPI) - -{project_name} is designed to cover most use-cases without requiring custom code, but we also want it to be customizable. -To achieve this {project_name} has a number of Service Provider Interfaces (SPI) for which you can implement your own providers. - -[[_implementing_spi]] -=== Implementing an SPI - -To implement an SPI you need to implement its ProviderFactory and Provider interfaces. You also need to create a service configuration file. - -For example, to implement the Theme Selector SPI you need to implement ThemeSelectorProviderFactory and ThemeSelectorProvider and also provide the file -`META-INF/services/org.keycloak.theme.ThemeSelectorProviderFactory`. - -Example ThemeSelectorProviderFactory: - -[source,java] ----- -package org.acme.provider; - -import ... - -public class MyThemeSelectorProviderFactory implements ThemeSelectorProviderFactory { - - @Override - public ThemeSelectorProvider create(KeycloakSession session) { - return new MyThemeSelectorProvider(session); - } - - @Override - public void init(Config.Scope config) { - } - - @Override - public void postInit(KeycloakSessionFactory factory) { - } - - @Override - public void close() { - } - - @Override - public String getId() { - return "myThemeSelector"; - } -} ----- - -NOTE: {project_name} creates a single instance of provider factories which makes it possible to store state for multiple requests. -Provider instances are created by calling create on the factory for each request so these should be light-weight object. - -Example ThemeSelectorProvider: - -[source,java] ----- -package org.acme.provider; - -import ... - -public class MyThemeSelectorProvider implements ThemeSelectorProvider { - - public MyThemeSelectorProvider(KeycloakSession session) { - } - - - @Override - public String getThemeName(Theme.Type type) { - return "my-theme"; - } - - @Override - public void close() { - } -} ----- - -Example service configuration file (`META-INF/services/org.keycloak.theme.ThemeSelectorProviderFactory`): - -[source] ----- -org.acme.provider.MyThemeSelectorProviderFactory ----- - -To configure your provider, see the link:https://www.keycloak.org/server/configuration-provider[Configuring Providers] guide. - -For example, to configure a provider you can set options as follows: - -[source,bash] ----- -bin/kc.[sh|bat] --spi-theme-selector-my-theme-selector-enabled=true --spi-theme-selector-my-theme-selector-theme=my-theme ----- - -Then you can retrieve the config in the `ProviderFactory` init method: - -[source,java] ----- -public void init(Config.Scope config) { - String themeName = config.get("theme"); -} ----- - -Your provider can also look up other providers if needed. For example: - -[source,java] ----- -public class MyThemeSelectorProvider implements ThemeSelectorProvider { - - private KeycloakSession session; - - public MyThemeSelectorProvider(KeycloakSession session) { - this.session = session; - } - - @Override - public String getThemeName(Theme.Type type) { - return session.getContext().getRealm().getLoginTheme(); - } -} ----- - -[[_providers_admin_console]] -==== Show info from your SPI implementation in the Admin Console - -Sometimes it is useful to show additional info about your Provider to a {project_name} administrator. You can show provider build time information (for example, version of -custom provider currently installed), current configuration of the provider (e.g. url of remote system your provider talks to) or some operational info -(average time of response from remote system your provider talks to). {project_name} Admin Console provides Server Info page to show this kind of information. - -To show info from your provider it is enough to implement `org.keycloak.provider.ServerInfoAwareProviderFactory` interface in your `ProviderFactory`. - -Example implementation for `MyThemeSelectorProviderFactory` from previous example: - -[source,java] ----- -package org.acme.provider; - -import ... - -public class MyThemeSelectorProviderFactory implements ThemeSelectorProviderFactory, ServerInfoAwareProviderFactory { - ... - - @Override - public Map getOperationalInfo() { - Map ret = new LinkedHashMap<>(); - ret.put("theme-name", "my-theme"); - return ret; - } -} ----- - -[[_use_available_providers]] -=== Use available providers - -In your provider implementation, you can use other providers available in {project_name}. The existing providers can be typically retrieved with the -usage of the `KeycloakSession`, which is available to your provider as described in the section <<_implementing_spi,Implementing an SPI>>. - -{project_name} has two provider types: - -* *Single-implementation provider types* - There can be only a single active implementation of the particular provider type in {project_name} runtime. -+ -For example `HostnameProvider` specifies the hostname to be used by {project_name} and that is shared for the whole {project_name} server. -Hence there can be only single implementation of this provider active for the {project_name} server. If there are multiple provider implementations available to the server runtime, -one of them needs to be specified as the default one. - -For example such as: -[source,bash] ----- -bin/kc.[sh|bat] build --spi-hostname-provider=default ----- - -The value `default` used as the value of `default-provider` must match the ID returned by the `ProviderFactory.getId()` of the particular provider factory implementation. -In the code, you can obtain the provider such as `keycloakSession.getProvider(HostnameProvider.class)` - -* *Multiple implementation provider types* - Those are provider types, that allow multiple implementations available and working together -in the {project_name} runtime. -+ -For example `EventListener` provider allows to have multiple implementations available and registered, which means -that particular event can be sent to all the listeners (jboss-logging, sysout etc). In the code, you can obtain a specified instance of the provider -for example such as `session.getProvider(EventListener.class, "jboss-logging")` . You need to specify `provider_id` of the provider as the second argument -as there can be multiple instances of this provider type as described above. -+ -The provider ID must match the ID returned by the `ProviderFactory.getId()` of the -particular provider factory implementation. Some provider types can be retrieved with the usage of `ComponentModel` as the second argument and some (for example `Authenticator`) even -need to be retrieved with the usage of `KeycloakSessionFactory`. It is not recommended to implement your own providers this way as it may be deprecated in the future. - -=== Registering provider implementations - -Providers are registered with the server by simply copying them to the `providers` directory. - -If your provider needs additional dependencies not already provided by Keycloak copy these to the `providers` directory. - -After registering new providers or dependencies Keycloak needs to be re-built with the `kc.[sh|bat] build` command. - -==== Disabling a provider - -You can disable a provider by setting the enabled attribute for the provider to false. -For example to disable the Infinispan user cache provider use: - -[source,bash] ----- -bin/kc.[sh|bat] build --spi-user-cache-infinispan-enabled=false ----- - -[[_script_providers]] -=== JavaScript providers - -{project_name} has the ability to execute scripts during runtime in order to allow administrators to customize specific functionalities: - -* Authenticator -* JavaScript Policy -* OpenID Connect Protocol Mapper -* SAML Protocol Mapper - -==== Authenticator - -Authentication scripts must provide at least one of the following functions: -`authenticate(..)`, which is called from `Authenticator#authenticate(AuthenticationFlowContext)` -`action(..)`, which is called from `Authenticator#action(AuthenticationFlowContext)` - -Custom `Authenticator` should at least provide the `authenticate(..)` function. -You can use the `javax.script.Bindings` script within the code. - -`script`:: -the `ScriptModel` to access script metadata -`realm`:: -the `RealmModel` -`user`:: -the current `UserModel` -`session`:: -the active `KeycloakSession` -`authenticationSession`:: -the current `AuthenticationSessionModel` -`httpRequest`:: -the current `org.jboss.resteasy.spi.HttpRequest` -`LOG`:: -a `org.jboss.logging.Logger` scoped to `ScriptBasedAuthenticator` - -NOTE: You can extract additional context information from the `context` argument passed to the `authenticate(context)` `action(context)` function. - -[source,javascript] ----- -AuthenticationFlowError = Java.type("org.keycloak.authentication.AuthenticationFlowError"); - -function authenticate(context) { - - LOG.info(script.name + " --> trace auth for: " + user.username); - - if ( user.username === "tester" - && user.getAttribute("someAttribute") - && user.getAttribute("someAttribute").contains("someValue")) { - - context.failure(AuthenticationFlowError.INVALID_USER); - return; - } - - context.success(); -} ----- - -==== Create a JAR with the scripts to deploy - -NOTE: JAR files are regular ZIP files with a `.jar` extension. - -In order to make your scripts available to {project_name} you need to deploy them to the server. For that, you should create -a `JAR` file with the following structure: - -[source] ----- -META-INF/keycloak-scripts.json - -my-script-authenticator.js -my-script-policy.js -my-script-mapper.js ----- - -The `META-INF/keycloak-scripts.json` is a file descriptor that provides metadata information about the scripts you want to deploy. It is a JSON file with the following structure: - -```json -{ - "authenticators": [ - { - "name": "My Authenticator", - "fileName": "my-script-authenticator.js", - "description": "My Authenticator from a JS file" - } - ], - "policies": [ - { - "name": "My Policy", - "fileName": "my-script-policy.js", - "description": "My Policy from a JS file" - } - ], - "mappers": [ - { - "name": "My Mapper", - "fileName": "my-script-mapper.js", - "description": "My Mapper from a JS file" - } - ], - "saml-mappers": [ - { - "name": "My Mapper", - "fileName": "my-script-mapper.js", - "description": "My Mapper from a JS file" - } - ] -} -``` - -This file should reference the different types of script providers that you want to deploy: - -* `authenticators` -+ -For OpenID Connect Script Authenticators. You can have one or multiple authenticators in the same JAR file -+ -* `policies` -+ -For JavaScript Policies when using {project_name} Authorization Services. You can have one or multiple policies in the same JAR file -+ -* `mappers` -+ -For OpenID Connect Script Protocol Mappers. You can have one or multiple mappers in the same JAR file -+ -* `saml-mappers` -+ -For SAML Script Protocol Mappers. You can have one or multiple mappers in the same JAR file - -For each script file in your `JAR` file, you need a corresponding entry in `META-INF/keycloak-scripts.json` that maps your scripts files to a specific provider type. For that you should provide the following properties for each entry: - -* `name` -+ -A friendly name that will be used to show the scripts through the {project_name} Administration Console. If not provided, the name -of the script file will be used instead -+ -* `description` -+ -An optional text that better describes the intend of the script file -+ -* `fileName` -+ -The name of the script file. This property is *mandatory* and should map to a file within the JAR. - -==== Deploy the script JAR - -Once you have a JAR file with a descriptor and the scripts you want to deploy, you just need to copy the JAR to the {project_name} `providers/` directory, then run `bin/kc.[sh|bat] build`. - -===== Deploy the script engine on Java 15 and later - -To run the scripts, JavaScript providers require that a JavaScript engine is available in your Java application. Java 14 and lower versions include the Nashorn JavaScript Engine. It is -automatically available as part of the Java itself and JavaScript providers are able to use this script engine by default. However, for Java 15 or higher versions, the script engine is not part -of the Java itself. It needs to be added to your server because {project_name} does not have any script engine by default. Java 15 and higher versions require an extra step when deploying script -providers - adding the script engine of your choice to your distribution. - -You can use any script engine. However, we only test with the Nashorn JavaScript Engine. The following steps assume that this engine is used: - -Install the script engine by copying the nashorn script engine JAR and its dependencies directly to the `KEYCLOAK_HOME/providers` directory. In the `pom.xml` file -of your script project, you can declare the dependency such as this in the `dependencies` section: - -```xml - - org.openjdk.nashorn - nashorn-core - 15.3 - -``` - -and declare `maven-dependency-plugin` in the `plugins` section to copy the dependencies to the specified directory: - -```xml - - org.apache.maven.plugins - maven-dependency-plugin - - - copy-dependencies-quarkus - package - - copy-dependencies - - - ${project.build.directory}/keycloak-server-copy/providers - nashorn-core,asm,asm-util,asm-commons - - - - -``` -Once the project is built, copy the script engine and its dependencies to the `KEYCLOAK_HOME/providers` directory. -```bash -cp target/keycloak-server-copy/providers/*.jar KEYCLOAK_HOME/providers/ -``` -After re-augment the distribution with `kc.sh build`, the script engine should be deployed and your script providers should work. - -=== Available SPIs - -If you want to see list of all available SPIs at runtime, you can check `Server Info` page in Admin Console as described in <<_providers_admin_console,Admin Console>> section. diff --git a/server_development/topics/saml-role-mappings-spi.adoc b/server_development/topics/saml-role-mappings-spi.adoc deleted file mode 100644 index 8c99f1244..000000000 --- a/server_development/topics/saml-role-mappings-spi.adoc +++ /dev/null @@ -1,29 +0,0 @@ -[[_saml_role_mappings_spi]] -== SAML role mappings SPI - -{project_name} defines an SPI for mapping SAML roles into roles that exist in the SP environment. The roles returned by -a third-party IDP might not always correspond to the roles that were defined for the SP application so there is a need for a -mechanism that allows mapping the SAML roles into different roles. It is used by the SAML adapter after it extracts the roles -from the SAML assertion to set up the container's security context. - -The `org.keycloak.adapters.saml.RoleMappingsProvider` SPI doesn't impose any restrictions on the mappings that can be performed. -Implementations can not only map roles into other roles but also add or remove roles (and thus augment or reduce the set of -roles assigned to the SAML principal) depending on the use case. - -For details about the configuration of the role mappings provider for the SAML adapter as well as a description of the default -implementations available see the link:{adapterguide_link}[{adapterguide_name}]. - -=== Implementing a custom role mappings provider - -To implement a custom role mappings provider one first needs to implement the `org.keycloak.adapters.saml.RoleMappingsProvider` -interface. Then, a `META-INF/services/org.keycloak.adapters.saml.RoleMappingsProvider` file containing the fully qualified name -of the custom implementation must be added to the archive that also contains the implementation class. This archive can be: - -* The SP application WAR file where the provider class is included in WEB-INF/classes; -* A custom JAR file which will be added into WEB-INF/lib of the SP application WAR; -* (WildFly/JBoss EAP only) A custom JAR file configured as a `jboss module` and referenced in `jboss-deployment-structure.xml` - of the SP application WAR. - -When the SP application is deployed, the role mappings provider that will be used is selected by the id that was set in -`keycloak-saml.xml` or in the `keycloak-saml` subsystem. So to enable your custom provider simply make sure that its id is -properly set in the adapter configuration. \ No newline at end of file diff --git a/server_development/topics/templates b/server_development/topics/templates deleted file mode 120000 index d19126411..000000000 --- a/server_development/topics/templates +++ /dev/null @@ -1 +0,0 @@ -../../topics/templates \ No newline at end of file diff --git a/server_development/topics/themes-resources.adoc b/server_development/topics/themes-resources.adoc deleted file mode 100644 index ba816358e..000000000 --- a/server_development/topics/themes-resources.adoc +++ /dev/null @@ -1,15 +0,0 @@ -[[_theme_resource]] -=== Theme resources - -When implementing custom providers in {project_name} there may often be a need to add additional templates, resources and messages bundles. - -ifeval::[{project_community}==true] -An example use-case would be a <<_auth_spi,custom authenticator>> that requires additional templates and resources. -endif::[] - -The easiest way to load additional theme resources is to create a JAR with templates in `theme-resources/templates` -resources in `theme-resources/resources` and messages bundles in `theme-resources/messages`. - -If you want a more flexible way to load templates and resources that can be achieved through the ThemeResourceSPI. -By implementing `ThemeResourceProviderFactory` and `ThemeResourceProvider` you can decide exactly how to load templates -and resources. diff --git a/server_development/topics/themes-selector.adoc b/server_development/topics/themes-selector.adoc deleted file mode 100644 index 712fc720b..000000000 --- a/server_development/topics/themes-selector.adoc +++ /dev/null @@ -1,10 +0,0 @@ -[[_theme_selector]] -=== Theme selector - -By default the theme configured for the realm is used, with the exception of clients being able to override the login -theme. This behavior can be changed through the Theme Selector SPI. - -This could be used to select different themes for desktop and mobile devices by looking at the user agent -header, for example. - -To create a custom theme selector you need to implement `ThemeSelectorProviderFactory` and `ThemeSelectorProvider`. diff --git a/server_development/topics/themes.adoc b/server_development/topics/themes.adoc deleted file mode 100755 index 8010ff1f2..000000000 --- a/server_development/topics/themes.adoc +++ /dev/null @@ -1,409 +0,0 @@ - -[[_themes]] -== Themes - -{project_name} provides theme support for web pages and emails. This allows customizing the look and feel of end-user facing pages so they can be -integrated with your applications. - -image::images/login-sunrise.png[caption="",title="Login page with sunrise example theme"] - -=== Theme types - -A theme can provide one or more types to customize different aspects of {project_name}. The types available are: - -* Account - Account management -* Admin - Admin Console -* Email - Emails -* Login - Login forms -* Welcome - Welcome page - -=== Configuring a theme - -All theme types, except welcome, are configured through the Admin Console. - -.Procedure - -. Log into the Admin Console. -. Select your realm from the drop-down box in the top left corner. -. Click *Realm Settings* from the menu. -. Click the *Themes* tab. -+ -NOTE: To set the theme for the `master` Admin Console you need to set the Admin Console theme for the `master` realm. -+ -. To see the changes to the Admin Console refresh the page. - -. Change the welcome theme by using the `spi-theme-welcome-theme` option. - -. For example: -+ -[source,bash] ----- -bin/kc.[sh|bat] start --spi-theme-welcome-theme=custom-theme ----- - -=== Default themes - -{project_name} comes bundled with default themes in the server's root `themes` directory. To simplify upgrading you should not edit the bundled themes -directly. Instead create your own theme that extends one of the bundled themes. - -=== Creating a theme - -A theme consists of: - -* HTML templates (https://freemarker.apache.org/[Freemarker Templates]) -* Images -* Message bundles -* Stylesheets -* Scripts -* Theme properties - -Unless you plan to replace every single page you should extend another theme. Most likely you will want to extend the {project_name} theme, but you could also -consider extending the base theme if you are significantly changing the look and feel of the pages. The base theme primarily consists of HTML templates and -message bundles, while the {project_name} theme primarily contains images and stylesheets. - -When extending a theme you can override individual resources (templates, stylesheets, etc.). If you decide to override HTML templates bear in mind that you may -need to update your custom template when upgrading to a new release. - -While creating a theme it's a good idea to disable caching as this makes it possible to edit theme resources directly from the `themes` directory without -restarting {project_name}. - -.Procedure - -. Run Keycloak with the following options: -+ -[source,bash] ----- -bin/kc.[sh|bat] start --spi-theme-static-max-age=-1 --spi-theme-cache-themes=false --spi-theme-cache-templates=false ----- - -. Create a directory in the `themes` directory. -+ -The name of the directory becomes the name of the theme. For example to -create a theme called `mytheme` create the directory `themes/mytheme`. - -. Inside the theme directory, create a directory for each of the types your theme is going to provide. -+ -For example, to add the login type to the `mytheme` theme, create the directory `themes/mytheme/login`. - -. For each type create a file `theme.properties` which allows setting some configuration for the theme. -+ -For example, to configure the theme `themes/mytheme/login` to extend the base theme and import some common resources, create the file `themes/mytheme/login/theme.properties` with following contents: -+ -[source] ----- -parent=base -import=common/keycloak ----- -+ -You have now created a theme with support for the login type. - -. Log into the Admin Console to check out your new theme -. Select your realm -. Click *Realm Settings* from the menu. -. Click on the *Themes* tab. -. For *Login Theme* select *mytheme* and click *Save*. -. Open the login page for the realm. -+ -You can do this either by logging in through your application or by opening the Account Management console (`/realms/{realm name}/account`). - -. To see the effect of changing the parent theme, set `parent=keycloak` in `theme.properties` and refresh the login page. - -[NOTE] -==== -Be sure to re-enable caching in production as it will significantly impact performance. -==== - -==== Theme properties - -Theme properties are set in the file `/theme.properties` in the theme directory. - -* parent - Parent theme to extend -* import - Import resources from another theme -* styles - Space-separated list of styles to include -* locales - Comma-separated list of supported locales - -There are a list of properties that can be used to change the css class used for certain element types. For a list of these properties look at the theme.properties -file in the corresponding type of the keycloak theme (`themes/keycloak//theme.properties`). - -You can also add your own custom properties and use them from custom templates. - -When doing so, you can substitute system properties or environment variables by using these formats: - -* `${some.system.property}` - for system properties -* `${env.ENV_VAR}` - for environment variables. - -A default value can also be provided in case the system property or the environment variable is not found with `${foo:defaultValue}`. - -NOTE: If no default value is provided and there's no corresponding system property or environment variable, then nothing is replaced and you end up with the format in your template. - -Here's an example of what is possible: - -[source,properties] ----- -javaVersion=${java.version} - -unixHome=${env.HOME:Unix home not found} -windowsHome=${env.HOMEPATH:Windows home not found} ----- - -==== Add a stylesheet to a theme - -You can add one or more stylesheets to a theme. - -.Procedure - -. Create a file in the `/resources/css` directory of your theme. - -. Add this file to the `styles` property in `theme.properties`. -+ -For example, to add `styles.css` to the `mytheme`, create `themes/mytheme/login/resources/css/styles.css` with the following content: -+ -[source,css] ----- -.login-pf body { - background: DimGrey none; -} ----- - -. Edit `themes/mytheme/login/theme.properties` and add: -+ -[source] ----- -styles=css/styles.css ----- - -. To see the changes, open the login page for your realm. -+ -You will notice that the only styles being applied are those from your custom stylesheet. - -. To include the styles from the parent theme, load the styles from that theme. Edit `themes/mytheme/login/theme.properties` and change `styles` to: -+ -[source] ----- -styles=web_modules/@fontawesome/fontawesome-free/css/icons/all.css web_modules/@patternfly/react-core/dist/styles/base.css web_modules/@patternfly/react-core/dist/styles/app.css node_modules/patternfly/dist/css/patternfly.min.css node_modules/patternfly/dist/css/patternfly-additions.min.css css/login.css css/styles.css ----- -+ -NOTE: To override styles from the parent stylesheets, ensure that your stylesheet is listed last. - -==== Adding a script to a theme - -You can add one or more scripts to a theme. - -.Procedure - -. Create a file in the `/resources/js` directory of your theme. - -. Add the file to the `scripts` property in `theme.properties`. -+ -For example, to add `script.js` to the `mytheme`, create `themes/mytheme/login/resources/js/script.js` with the following content: -+ -[source,javascript] ----- -alert('Hello'); ----- -+ -Then edit `themes/mytheme/login/theme.properties` and add: -+ -[source] ----- -scripts=js/script.js ----- - -==== Adding an image to a theme - -To make images available to the theme add them to the `/resources/img` directory of your theme. These can be used from within stylesheets or -directly in HTML templates. - -For example to add an image to the `mytheme` copy an image to `themes/mytheme/login/resources/img/image.jpg`. - -You can then use this image from within a custom stylesheet with: - -[source,css] ----- -body { - background-image: url('../img/image.jpg'); - background-size: cover; -} ----- - -Or to use directly in HTML templates add the following to a custom HTML template: - -[source,html] ----- - ----- - -==== Messages - -Text in the templates is loaded from message bundles. A theme that extends another theme will inherit all messages from the parent's message bundle and you can -override individual messages by adding `/messages/messages_en.properties` to your theme. - -For example to replace `Username` on the login form with `Your Username` for the `mytheme` create the file -`themes/mytheme/login/messages/messages_en.properties` with the following content: - -[source] ----- -usernameOrEmail=Your Username ----- - -Within a message values like `{0}` and `{1}` are replaced with arguments when the message is used. For example {0} in `Log in to {0}` is replaced with the name -of the realm. - -Texts of these message bundles can be overwritten by realm-specific values. The realm-specific values are manageable via UI and API. - -==== Adding a language to a realm - -.Prerequisites - -* To enable internationalization for a realm, see the {adminguide_link}[{adminguide_name}]. - -.Procedure - -. Create the file `/messages/messages_.properties` in the directory of your theme. - -. Add this file to the `locales` property in `/theme.properties`. -For a language to be available to users the realms `login`, `account` and `email`, the theme has to support the language, so you need to add your language for those theme types. -+ -For example, to add Norwegian translations to the `mytheme` theme create the file `themes/mytheme/login/messages/messages_no.properties` with the -following content: -+ -[source] ----- -usernameOrEmail=Brukernavn -password=Passord ----- -+ -If you omit a translation for messages, they will use English. - -. Edit `themes/mytheme/login/theme.properties` and add: -+ -[source] ----- -locales=en,no ----- - -. Add the same for the `account` and `email` theme types. To do this create `themes/mytheme/account/messages/messages_no.properties` and -`themes/mytheme/email/messages/messages_no.properties`. Leaving these files empty will result in the English messages being used. - -. Copy `themes/mytheme/login/theme.properties` to `themes/mytheme/account/theme.properties` and `themes/mytheme/email/theme.properties`. - -. Add a translation for the language selector. This is done by adding a message to the English translation. To do this add the following to -`themes/mytheme/account/messages/messages_en.properties` and `themes/mytheme/login/messages/messages_en.properties`: -+ -[source] ----- -locale_no=Norsk ----- -+ -By default message properties files should be encoded using ISO-8859-1. It's also possible to specify the encoding using a special header. For example to use UTF-8 encoding: -+ -[source] ----- -# encoding: UTF-8 -usernameOrEmail=.... ----- - -[role="_additional-resources"] -.Additional resources -* See <<_locale_selector,Locale Selector>> for details on how the current locale is selected. - -[[custom-identity-providers-icons]] -==== Adding custom Identity Providers icons - -{project_name} supports adding icons for custom Identity providers, which are displayed on the login screen. - -.Procedure - -. Define icon classes in your login `theme.properties` file (for example, `themes/mytheme/login/theme.properties`) with key pattern `kcLogoIdP-`. - -. For an Identity Provider with an alias `myProvider`, you may add a line to `theme.properties` file of your custom theme. For example: -+ -[source] ----- -kcLogoIdP-myProvider = fa fa-lock ----- - -All icons are available on the official website of PatternFly4. -Icons for social providers are already defined in base login theme properties (`themes/keycloak/login/theme.properties`), where you can inspire yourself. - -==== Creating a custom HTML template - -{project_name} uses https://freemarker.apache.org/[Apache Freemarker] templates to generate HTML. You can override individual templates in your own theme by -creating `/