Merge pull request #19119 from ahus1/is-CIAM-5056-move-documentation-to-main-repo
Move documentation to main repo
6
docs/documentation/.asciidoctorconfig
Normal file
|
@ -0,0 +1,6 @@
|
|||
:icons: font
|
||||
:idprefix:
|
||||
:idseparator: -
|
||||
:project_buildType: latest
|
||||
ifndef::asciidoctorconfigdir[:asciidoctorconfigdir: .]
|
||||
include::{asciidoctorconfigdir}/topics/templates/document-attributes.adoc[]
|
20
docs/documentation/.gitattributes
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
* 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
|
40
docs/documentation/.github/ISSUE_TEMPLATE/bug.yml
vendored
Normal file
|
@ -0,0 +1,40 @@
|
|||
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
|
11
docs/documentation/.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
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
|
31
docs/documentation/.github/ISSUE_TEMPLATE/enhancement.yml
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
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
|
32
docs/documentation/.github/ISSUE_TEMPLATE/epic.yml
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
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
|
31
docs/documentation/.github/ISSUE_TEMPLATE/feature.yml
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
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
|
10
docs/documentation/.github/ISSUE_TEMPLATE/task.yml
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
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
|
26
docs/documentation/.github/workflows/test-external-links.yml
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
# 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
|
25
docs/documentation/.github/workflows/test-guides.yml
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
# 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
|
60
docs/documentation/.gitignore
vendored
Normal file
|
@ -0,0 +1,60 @@
|
|||
.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
|
8
docs/documentation/.vale.ini
Normal file
|
@ -0,0 +1,8 @@
|
|||
StylesPath = /Users/bdooley/Documents/code/vale-boilerplate/styles
|
||||
MinAlertLevel = error
|
||||
|
||||
Vocab = blog
|
||||
|
||||
|
||||
[*.adoc]
|
||||
BasedOnStyles = IBM, Vale, write-good
|
210
docs/documentation/License.html
Executable file
|
@ -0,0 +1,210 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html>
|
||||
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
<pre>
|
||||
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.
|
||||
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
49
docs/documentation/README.md
Executable file
|
@ -0,0 +1,49 @@
|
|||
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)
|
238
docs/documentation/aggregation/navbar-head.html
Normal file
|
@ -0,0 +1,238 @@
|
|||
<style>
|
||||
/* Top menu */
|
||||
|
||||
@media only screen and (min-width: 768px) {
|
||||
div.top-menu-guides {
|
||||
position: fixed;
|
||||
display: inline-block;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
div.top-menu-guides p {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.top-menu-guides .content {
|
||||
margin: 0;
|
||||
padding: 7px 20px 0 20px;
|
||||
background-color: #ededed;
|
||||
height: 48px;
|
||||
width: 20em;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1280px) {
|
||||
div.top-menu-guides .content {
|
||||
width: 15em;
|
||||
}
|
||||
}
|
||||
|
||||
div.top-menu-guides .ulist {
|
||||
display: none;
|
||||
position: absolute;
|
||||
background-color: #f9f9f9;
|
||||
min-width: 160px;
|
||||
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
|
||||
padding: 0px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
div.top-menu-guides .ulist ul {
|
||||
list-style: none;
|
||||
padding: 5px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
div.top-menu-guides .ulist li {
|
||||
padding: 5px 10px;
|
||||
}
|
||||
|
||||
div.top-menu-guides:hover .ulist {
|
||||
display: block;
|
||||
}
|
||||
|
||||
div.top-menu-version {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
div.top-menu-version .content {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
background-color: #eee;
|
||||
height: 48px;
|
||||
padding: 7px;
|
||||
}
|
||||
|
||||
.versionarchive {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.versionarchive p {
|
||||
margin: 0;
|
||||
padding: 2px 5px 2px 10px;
|
||||
}
|
||||
|
||||
.versionarchive a {
|
||||
background-color: #ffdd57;
|
||||
padding: 0 5px;
|
||||
font-style: normal;
|
||||
border-radius: 5px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.versionlatest {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.versionlatest p {
|
||||
background-color: #eee;
|
||||
border-radius: 5px;
|
||||
margin: 0;
|
||||
padding: 2px 5px 2px 10px;
|
||||
}
|
||||
|
||||
.versionlatest em {
|
||||
background-color: #23d160;
|
||||
padding: 0 5px;
|
||||
font-style: normal;
|
||||
border-radius: 5px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
/* TOC */
|
||||
|
||||
#tocbot a.toc-link.node-name--H1{ font-style: italic }
|
||||
@media screen{
|
||||
#tocbot > ul.toc-list{ margin-bottom: 0.5em; margin-left: 0.125em }
|
||||
#tocbot ul.sectlevel0, #tocbot a.toc-link.node-name--H1 + ul{
|
||||
padding-left: 0 }
|
||||
#tocbot a.toc-link{ height:100% }
|
||||
.is-collapsible{ max-height:3000px; overflow:hidden; }
|
||||
.is-collapsed{ max-height:0 }
|
||||
.is-active-link{ font-weight:700 }
|
||||
}
|
||||
@media print{
|
||||
#tocbot a.toc-link.node-name--H4{ display:none }
|
||||
}
|
||||
|
||||
/* Fix scroll to anchor hides title */
|
||||
h1::before, h2::before, h3::before, h4::before, h5::before, h6::before {
|
||||
display: block;
|
||||
content: " ";
|
||||
height: 70px;
|
||||
margin-top: -70px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
border-bottom: none !important
|
||||
}
|
||||
|
||||
#toc.toc2 {
|
||||
top: 30px;
|
||||
bottom: 0px;
|
||||
height: unset;
|
||||
}
|
||||
|
||||
body.toc2 {
|
||||
padding-top: 30px;
|
||||
}
|
||||
|
||||
@media only screen and (min-width:768px) {
|
||||
#toc.toc2 {
|
||||
top: 40px;
|
||||
}
|
||||
|
||||
body.toc2 {
|
||||
padding-top: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width:1280px) {
|
||||
#toc.toc2 {
|
||||
top: 48px;
|
||||
}
|
||||
|
||||
body.toc2 {
|
||||
padding-top: 48px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* General Changes */
|
||||
|
||||
h1, h2, h3, #toctitle, .sidebarblock>.content>.title, h4, h5, h6 {
|
||||
color: #444444;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #004670;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #7da1dc;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: "Open Sans","DejaVu Sans",sans-serif;
|
||||
color: #444444;
|
||||
}
|
||||
|
||||
.subheader, .admonitionblock td.content>.title, .audioblock>.title, .exampleblock>.title, .imageblock>.title, .listingblock>.title, .literalblock>.title, .stemblock>.title, .openblock>.title, .paragraph>.title, .quoteblock>.title, table.tableblock>.title, .verseblock>.title, .videoblock>.title, .dlist>.title, .olist>.title, .ulist>.title, .qlist>.title, .hdlist>.title {
|
||||
color: #444444;
|
||||
}
|
||||
|
||||
.admonitionblock td.content>.title, .audioblock>.title, .exampleblock>.title, .imageblock>.title, .listingblock>.title, .literalblock>.title, .stemblock>.title, .openblock>.title, .paragraph>.title, .quoteblock>.title, table.tableblock>.title, .verseblock>.title, .videoblock>.title, .dlist>.title, .olist>.title, .ulist>.title, .qlist>.title, .hdlist>.title {
|
||||
font-family: "Open Sans","DejaVu Sans",sans-serif;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
span.image img {
|
||||
border:1px solid #ccc;
|
||||
-webkit-box-shadow: 3px 3px 15px 0px rgba(0,0,0,0.5);
|
||||
-moz-box-shadow: 3px 3px 15px 0px rgba(0,0,0,0.5);
|
||||
box-shadow: 3px 3px 15px 0px rgba(0,0,0,0.5);
|
||||
}
|
||||
|
||||
.sect1+.sect1 {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.page-links {
|
||||
border-bottom: 1px solid #efefed;
|
||||
border-top: none;
|
||||
background: none;
|
||||
position: relative;
|
||||
left: 0em;
|
||||
width: 100%;
|
||||
top: -5em;
|
||||
height: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.sect2 .page-links {
|
||||
top: -3.5em;
|
||||
}
|
||||
|
||||
.page-links .content {
|
||||
background: #f8f8f7;
|
||||
border: 1px solid #e0e0dc;
|
||||
float: right;
|
||||
font-size: 0.8em;
|
||||
margin: 0;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.page-links a {
|
||||
display: block;
|
||||
padding: 5px;
|
||||
}
|
||||
</style>
|
||||
|
37
docs/documentation/aggregation/navbar.html
Normal file
|
@ -0,0 +1,37 @@
|
|||
<script src="https://cdnjs.cloudflare.com/ajax/libs/tocbot/4.4.2/tocbot.js"></script>
|
||||
|
||||
<script>
|
||||
const oldtoc = document.getElementById('toctitle').nextElementSibling;
|
||||
const newtoc = document.createElement('div');
|
||||
newtoc.setAttribute('id', 'tocbot');
|
||||
newtoc.setAttribute('class', 'js-toc');
|
||||
oldtoc.parentNode.replaceChild(newtoc, oldtoc);
|
||||
tocbot.init({ contentSelector: '#content',
|
||||
headingSelector: 'h2, h3, h4',
|
||||
smoothScroll: false
|
||||
});
|
||||
const handleTocOnResize = function() {
|
||||
const width = window.innerWidth
|
||||
|| document.documentElement.clientWidth
|
||||
|| document.body.clientWidth;
|
||||
if (width < 768) {
|
||||
tocbot.refresh({
|
||||
contentSelector: '#content',
|
||||
headingSelector: 'h2, h3, h4',
|
||||
collapseDepth: 6,
|
||||
activeLinkClass: 'ignoreactive',
|
||||
throttleTimeout: 1000,
|
||||
smoothScroll: false
|
||||
});
|
||||
}
|
||||
else {
|
||||
tocbot.refresh({
|
||||
contentSelector: '#content',
|
||||
headingSelector: 'h2, h3, h4',
|
||||
smoothScroll: false
|
||||
});
|
||||
}
|
||||
};
|
||||
window.addEventListener('resize', handleTocOnResize);
|
||||
handleTocOnResize();
|
||||
</script>
|
230
docs/documentation/aggregation/pom.xml
Normal file
|
@ -0,0 +1,230 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.keycloak.documentation</groupId>
|
||||
<artifactId>documentation-parent</artifactId>
|
||||
<version>999.0.0-SNAPSHOT</version>
|
||||
<relativePath>../</relativePath>
|
||||
</parent>
|
||||
|
||||
<name>Aggregation</name>
|
||||
<artifactId>aggregation</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.keycloak.documentation</groupId>
|
||||
<artifactId>api-documentation</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>pom</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak.documentation</groupId>
|
||||
<artifactId>authorization-services</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>pom</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak.documentation</groupId>
|
||||
<artifactId>securing-apps</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>pom</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak.documentation</groupId>
|
||||
<artifactId>server-admin</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>pom</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak.documentation</groupId>
|
||||
<artifactId>server-development</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>pom</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak.documentation</groupId>
|
||||
<artifactId>release-notes</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>pom</type>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<outputDirectory>../target</outputDirectory>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>copy-api_documentation</id>
|
||||
<phase>process-resources</phase>
|
||||
<goals>
|
||||
<goal>copy-resources</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<outputDirectory>${project.build.outputDirectory}/api_documentation/</outputDirectory>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>../api_documentation/target/generated-docs</directory>
|
||||
<include>**/**</include>
|
||||
</resource>
|
||||
</resources>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>copy-authorization_services</id>
|
||||
<phase>process-resources</phase>
|
||||
<goals>
|
||||
<goal>copy-resources</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<outputDirectory>${project.build.outputDirectory}/authorization_services/</outputDirectory>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>../authorization_services/target/generated-docs</directory>
|
||||
<include>**/**</include>
|
||||
</resource>
|
||||
</resources>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>copy-getting_started</id>
|
||||
<phase>process-resources</phase>
|
||||
<goals>
|
||||
<goal>copy-resources</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<outputDirectory>${project.build.outputDirectory}/getting_started/</outputDirectory>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>../getting_started/target/generated-docs</directory>
|
||||
<include>**/**</include>
|
||||
</resource>
|
||||
</resources>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>copy-securing_apps</id>
|
||||
<phase>process-resources</phase>
|
||||
<goals>
|
||||
<goal>copy-resources</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<outputDirectory>${project.build.outputDirectory}/securing_apps/</outputDirectory>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>../securing_apps/target/generated-docs</directory>
|
||||
<include>**/**</include>
|
||||
</resource>
|
||||
</resources>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>copy-server_admin</id>
|
||||
<phase>process-resources</phase>
|
||||
<goals>
|
||||
<goal>copy-resources</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<outputDirectory>${project.build.outputDirectory}/server_admin/</outputDirectory>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>../server_admin/target/generated-docs</directory>
|
||||
<include>**/**</include>
|
||||
</resource>
|
||||
</resources>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>copy-server_development</id>
|
||||
<phase>process-resources</phase>
|
||||
<goals>
|
||||
<goal>copy-resources</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<outputDirectory>${project.build.outputDirectory}/server_development/</outputDirectory>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>../server_development/target/generated-docs</directory>
|
||||
<include>**/**</include>
|
||||
</resource>
|
||||
</resources>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>copy-release_notes</id>
|
||||
<phase>process-resources</phase>
|
||||
<goals>
|
||||
<goal>copy-resources</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<outputDirectory>${project.build.outputDirectory}/release_notes/</outputDirectory>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>../release_notes/target/generated-docs</directory>
|
||||
<include>**/**</include>
|
||||
</resource>
|
||||
</resources>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>copy-upgrading</id>
|
||||
<phase>process-resources</phase>
|
||||
<goals>
|
||||
<goal>copy-resources</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<outputDirectory>${project.build.outputDirectory}/upgrading/</outputDirectory>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>../upgrading/target/generated-docs</directory>
|
||||
<include>**/**</include>
|
||||
</resource>
|
||||
</resources>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>copy-index</id>
|
||||
<phase>process-resources</phase>
|
||||
<goals>
|
||||
<goal>copy-resources</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<outputDirectory>${project.build.outputDirectory}/</outputDirectory>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src</directory>
|
||||
<include>*.html</include>
|
||||
<include>*.png</include>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-antrun-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>echo-output-aggregation</id>
|
||||
<phase>process-resources</phase>
|
||||
<goals>
|
||||
<goal>run</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<target>
|
||||
<echo>OUTPUT (no-frames): file://${project.build.outputDirectory}/index.html</echo>
|
||||
</target>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
45
docs/documentation/aggregation/src/index.html
Normal file
|
@ -0,0 +1,45 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Documentation Index</title>
|
||||
</head>
|
||||
<style>
|
||||
body {
|
||||
background-color: #ededed;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
li {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
li a {
|
||||
color: #004670;
|
||||
text-align: center;
|
||||
padding: 5px 16px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
li a:hover {
|
||||
color: #428bca;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<img src="keycloak_logo.png"/>
|
||||
<ul>
|
||||
<li><a href="securing_apps/${masterFile}.html">Securing Apps</a></li>
|
||||
<li><a href="server_admin/${masterFile}.html">Server Admin</a></li>
|
||||
<li><a href="server_development/${masterFile}.html">Server Development</a></li>
|
||||
<li><a href="authorization_services/${masterFile}.html">Authorization Services</a></li>
|
||||
<li><a href="upgrading/${masterFile}.html">Upgrading</a></li>
|
||||
<li><a href="release_notes/${masterFile}.html">Release Notes</a></li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
BIN
docs/documentation/aggregation/src/keycloak_logo.png
Normal file
After Width: | Height: | Size: 18 KiB |
8
docs/documentation/api_documentation/index.adoc
Normal file
|
@ -0,0 +1,8 @@
|
|||
include::topics/templates/document-attributes.adoc[]
|
||||
|
||||
:api_documentation:
|
||||
:linkattrs:
|
||||
|
||||
= {apidocs_name}
|
||||
|
||||
include::topics.adoc[]
|
46
docs/documentation/api_documentation/pom.xml
Normal file
|
@ -0,0 +1,46 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.keycloak.documentation</groupId>
|
||||
<artifactId>documentation-parent</artifactId>
|
||||
<version>999.0.0-SNAPSHOT</version>
|
||||
<relativePath>../</relativePath>
|
||||
</parent>
|
||||
|
||||
<name>API Documentation</name>
|
||||
<artifactId>api-documentation</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.keycloak.documentation</groupId>
|
||||
<artifactId>header-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>add-file-headers</id>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.asciidoctor</groupId>
|
||||
<artifactId>asciidoctor-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>asciidoc-to-html</id>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-antrun-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>echo-output</id>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
1
docs/documentation/api_documentation/topics.adoc
Normal file
|
@ -0,0 +1 @@
|
|||
include::topics/overview.adoc[]
|
12
docs/documentation/api_documentation/topics/overview.adoc
Normal file
|
@ -0,0 +1,12 @@
|
|||
|
||||
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}]
|
1
docs/documentation/api_documentation/topics/templates
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../topics/templates
|
1
docs/documentation/authorization_services/docinfo-footer.html
Symbolic link
|
@ -0,0 +1 @@
|
|||
../aggregation/navbar.html
|
1
docs/documentation/authorization_services/docinfo.html
Symbolic link
|
@ -0,0 +1 @@
|
|||
../aggregation/navbar-head.html
|
After Width: | Height: | Size: 24 KiB |
BIN
docs/documentation/authorization_services/images/authz-calls.png
Normal file
After Width: | Height: | Size: 30 KiB |
After Width: | Height: | Size: 29 KiB |
After Width: | Height: | Size: 97 KiB |
After Width: | Height: | Size: 139 KiB |
After Width: | Height: | Size: 74 KiB |
After Width: | Height: | Size: 68 KiB |
After Width: | Height: | Size: 67 KiB |
After Width: | Height: | Size: 95 KiB |
After Width: | Height: | Size: 214 KiB |
After Width: | Height: | Size: 47 KiB |
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 107 KiB |
After Width: | Height: | Size: 74 KiB |
BIN
docs/documentation/authorization_services/images/keycloak_logo.png
Executable file
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 55 KiB |
After Width: | Height: | Size: 62 KiB |
After Width: | Height: | Size: 67 KiB |
After Width: | Height: | Size: 104 KiB |
After Width: | Height: | Size: 102 KiB |
After Width: | Height: | Size: 21 KiB |
After Width: | Height: | Size: 118 KiB |
After Width: | Height: | Size: 47 KiB |
After Width: | Height: | Size: 82 KiB |
After Width: | Height: | Size: 90 KiB |
After Width: | Height: | Size: 112 KiB |
After Width: | Height: | Size: 115 KiB |
After Width: | Height: | Size: 66 KiB |
After Width: | Height: | Size: 45 KiB |
After Width: | Height: | Size: 105 KiB |
After Width: | Height: | Size: 111 KiB |
After Width: | Height: | Size: 72 KiB |
BIN
docs/documentation/authorization_services/images/policy/view.png
Normal file
After Width: | Height: | Size: 276 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 172 KiB |
After Width: | Height: | Size: 141 KiB |
After Width: | Height: | Size: 75 KiB |
After Width: | Height: | Size: 217 KiB |
After Width: | Height: | Size: 148 KiB |
After Width: | Height: | Size: 75 KiB |
After Width: | Height: | Size: 123 KiB |
After Width: | Height: | Size: 122 KiB |
After Width: | Height: | Size: 121 KiB |
After Width: | Height: | Size: 83 KiB |
After Width: | Height: | Size: 140 KiB |
After Width: | Height: | Size: 151 KiB |
BIN
docs/documentation/authorization_services/images/rs-r-scopes.png
Normal file
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 90 KiB |
After Width: | Height: | Size: 107 KiB |
After Width: | Height: | Size: 63 KiB |
After Width: | Height: | Size: 73 KiB |
20
docs/documentation/authorization_services/index.adoc
Normal file
|
@ -0,0 +1,20 @@
|
|||
: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:
|
||||
|
46
docs/documentation/authorization_services/pom.xml
Normal file
|
@ -0,0 +1,46 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.keycloak.documentation</groupId>
|
||||
<artifactId>documentation-parent</artifactId>
|
||||
<version>999.0.0-SNAPSHOT</version>
|
||||
<relativePath>../</relativePath>
|
||||
</parent>
|
||||
|
||||
<name>Authorization Services</name>
|
||||
<artifactId>authorization-services</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.keycloak.documentation</groupId>
|
||||
<artifactId>header-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>add-file-headers</id>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.asciidoctor</groupId>
|
||||
<artifactId>asciidoctor-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>asciidoc-to-html</id>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-antrun-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>echo-output</id>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
121
docs/documentation/authorization_services/topics.adoc
Normal file
|
@ -0,0 +1,121 @@
|
|||
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]
|
|
@ -0,0 +1,130 @@
|
|||
[[_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>>
|
|
@ -0,0 +1,38 @@
|
|||
[[_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.
|
|
@ -0,0 +1,76 @@
|
|||
[[_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.
|
|
@ -0,0 +1,35 @@
|
|||
[[_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.
|
||||
|
||||
|===
|
|
@ -0,0 +1,71 @@
|
|||
[[_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.
|
|
@ -0,0 +1,165 @@
|
|||
[[_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<MyClaimInformationPointProvider> {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "my-claims";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(PolicyEnforcer policyEnforcer) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public MyClaimInformationPointProvider create(Map<String, Object> 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<String, Object> config;
|
||||
|
||||
public MyClaimInformationPointProvider(Map<String, Object> config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, List<String>> resolve(HttpFacade httpFacade) {
|
||||
Map<String, List<String>> claims = new HashMap<>();
|
||||
|
||||
// put whatever claim you want into the map
|
||||
|
||||
return claims;
|
||||
}
|
||||
}
|
||||
```
|
|
@ -0,0 +1,18 @@
|
|||
[[_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.
|
|
@ -0,0 +1,149 @@
|
|||
[[_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+"]
|
||||
----
|
||||
<script src="http://...{kc_js_path}/keycloak-authz.js"></script>
|
||||
----
|
||||
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;
|
||||
```
|
|
@ -0,0 +1,166 @@
|
|||
[[_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.
|
|
@ -0,0 +1,32 @@
|
|||
[[_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.
|
|
@ -0,0 +1,26 @@
|
|||
[[_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}].
|
|
@ -0,0 +1,15 @@
|
|||
= 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*.
|
|
@ -0,0 +1,33 @@
|
|||
[[_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*.
|
|
@ -0,0 +1,39 @@
|
|||
[[_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>>
|
|
@ -0,0 +1,129 @@
|
|||
[[_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>>.
|
|
@ -0,0 +1,14 @@
|
|||
[[_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.
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
[[_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.
|
|
@ -0,0 +1,37 @@
|
|||
[[_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.
|
|
@ -0,0 +1,16 @@
|
|||
[[_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.
|