├── 10_docker_tricks
├── .gitignore
├── 10_busybox
│ └── run.sh
├── 1_healthcheck
│ ├── docker-compose.yml
│ └── run.sh
├── 2_multistage_builds
│ ├── Dockerfile
│ ├── pom.xml
│ ├── run.sh
│ └── src
│ │ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── johannesinnerbichler
│ │ │ │ └── dockerbuilddemo
│ │ │ │ └── DockerBuildDemoApplication.java
│ │ └── resources
│ │ │ └── application.properties
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── johannesinnerbichler
│ │ └── dockerbuilddemo
│ │ └── DockerBuildDemoApplicationTests.java
├── 3_network_security
│ ├── docker-compose.yaml
│ └── run.sh
├── 4_database_init
│ ├── docker-compose.yml
│ ├── init.sql
│ └── run.sh
├── 5_ps_output
│ └── run.sh
├── 6_docker_in_docker
│ ├── docker-compose.yml
│ └── run.sh
├── 7_onbuild
│ ├── Dockerfile
│ ├── DockerfileOnBuild
│ ├── main.py
│ ├── requirements.txt
│ └── run.sh
├── 8_non_root
│ ├── Dockerfile
│ ├── docker-compose.yml
│ ├── index.html
│ ├── nginx.conf
│ └── run.sh
└── 9_apt_get
│ ├── Dockerfile
│ └── run.sh
├── LICENSE
├── README.md
├── k8s_keycloak
├── .gitignore
├── Dockerfile
├── kubernetes
│ ├── app-deployment.yml
│ └── keycloak-deployment.yml
├── persons-application.iml
├── pom.xml
├── readme.md
├── src
│ └── main
│ │ ├── java
│ │ └── com
│ │ │ └── johannesinnerbichler
│ │ │ └── personapp
│ │ │ └── PersonApplication.java
│ │ └── resources
│ │ ├── application.properties
│ │ ├── static
│ │ └── index.html
│ │ └── templates
│ │ └── persons.ftl
└── util.sh
├── keycloak_4_spring_boot_2
├── keycloak
│ ├── config
│ │ ├── PersonRealm-realm.json
│ │ ├── PersonRealm-users-0.json
│ │ ├── master-realm.json
│ │ └── master-users-0.json
│ └── docker-compose.yml
├── pom.xml
├── readme.md
└── src
│ └── main
│ ├── java
│ └── com
│ │ └── johannesinnerbichler
│ │ └── personapp
│ │ └── PersonApplication.java
│ └── resources
│ ├── application.yml
│ └── templates
│ ├── index.ftl
│ └── persons.ftl
└── spring-data-jpa-encryption
├── .gitignore
├── Dockerfile
├── docker-compose.yml
├── pom.xml
├── readme.md
└── src
├── main
├── java
│ └── com
│ │ └── johannesinnerbichler
│ │ └── spring
│ │ └── data
│ │ └── jpa
│ │ └── encryption
│ │ ├── JPAEncryptionApplication.java
│ │ ├── converters
│ │ ├── AbstractConverter.java
│ │ ├── AesEncryptor.java
│ │ ├── DatabaseEncryptionPasswordProperty.java
│ │ ├── LocalDateConverter.java
│ │ ├── LocalDateTimeConverter.java
│ │ └── StringConverter.java
│ │ └── customer
│ │ ├── Customer.java
│ │ └── CustomerRepository.java
└── resources
│ └── application.yml
└── test
└── java
└── com
└── johannesinnerbichler
└── springdata
└── jpa
└── encryption
└── customer
└── CustomerRepositoryTest.java
/10_docker_tricks/.gitignore:
--------------------------------------------------------------------------------
1 | 2_multistage_builds/target
--------------------------------------------------------------------------------
/10_docker_tricks/10_busybox/run.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | sample_job=$(docker run -d busybox /bin/sh -c "while true; do echo Docker; sleep 1; done")
4 | docker logs -f $sample_job
5 |
--------------------------------------------------------------------------------
/10_docker_tricks/1_healthcheck/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '2.1'
2 |
3 | services:
4 | db:
5 | image: postgres:10
6 | environment:
7 | POSTGRES_USER: admin
8 | POSTGRES_PASSWORD: password
9 | healthcheck:
10 | test: ["CMD-SHELL", "pg_isready -U postgres"]
11 | interval: 30s
12 | timeout: 30s
13 | retries: 3
14 |
15 | pgweb:
16 | image: sosedoff/pgweb
17 | ports:
18 | - "8081:8081"
19 | environment:
20 | - DATABASE_URL=postgres://admin:password@db:5432/postgres?sslmode=disable
21 | depends_on:
22 | db:
23 | condition: service_healthy
--------------------------------------------------------------------------------
/10_docker_tricks/1_healthcheck/run.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | docker-compose up
--------------------------------------------------------------------------------
/10_docker_tricks/2_multistage_builds/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM maven:3.5-jdk-8 as builder
2 | WORKDIR /
3 | COPY . /
4 | RUN mvn clean package
5 |
6 | FROM openjdk:8-jdk-alpine
7 | LABEL maintainer="j.innerbichler@gmail.com"
8 | COPY --from=builder /target/docker-build-demo-0.0.1-SNAPSHOT.jar app.jar
9 | EXPOSE 8080
10 | ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
--------------------------------------------------------------------------------
/10_docker_tricks/2_multistage_builds/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | com.johannesinnerbichler
7 | docker-build-demo
8 | 0.0.1-SNAPSHOT
9 | jar
10 |
11 | docker-build-demo
12 | Demo project for Spring Boot
13 |
14 |
15 | org.springframework.boot
16 | spring-boot-starter-parent
17 | 2.0.5.RELEASE
18 |
19 |
20 |
21 |
22 | UTF-8
23 | UTF-8
24 | 1.8
25 |
26 |
27 |
28 |
29 | org.springframework.boot
30 | spring-boot-starter
31 |
32 |
33 |
34 | org.springframework.boot
35 | spring-boot-starter-test
36 | test
37 |
38 |
39 |
40 |
41 |
42 |
43 | org.springframework.boot
44 | spring-boot-maven-plugin
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/10_docker_tricks/2_multistage_builds/run.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | docker build -t my-app .
4 | docker run -it --rm --name my-running-app my-app
--------------------------------------------------------------------------------
/10_docker_tricks/2_multistage_builds/src/main/java/com/johannesinnerbichler/dockerbuilddemo/DockerBuildDemoApplication.java:
--------------------------------------------------------------------------------
1 | package com.johannesinnerbichler.dockerbuilddemo;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class DockerBuildDemoApplication {
8 |
9 | public static void main(String[] args) {
10 | System.out.println("It's working. Starting Spring Application...");
11 | SpringApplication.run(DockerBuildDemoApplication.class, args);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/10_docker_tricks/2_multistage_builds/src/main/resources/application.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jinnerbichler/blog/db95432aea12d1ccf4319d9db891483ca06aaeb0/10_docker_tricks/2_multistage_builds/src/main/resources/application.properties
--------------------------------------------------------------------------------
/10_docker_tricks/2_multistage_builds/src/test/java/com/johannesinnerbichler/dockerbuilddemo/DockerBuildDemoApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.johannesinnerbichler.dockerbuilddemo;
2 |
3 | import org.junit.Test;
4 | import org.junit.runner.RunWith;
5 | import org.springframework.boot.test.context.SpringBootTest;
6 | import org.springframework.test.context.junit4.SpringRunner;
7 |
8 | @RunWith(SpringRunner.class)
9 | @SpringBootTest
10 | public class DockerBuildDemoApplicationTests {
11 |
12 | @Test
13 | public void contextLoads() {
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/10_docker_tricks/3_network_security/docker-compose.yaml:
--------------------------------------------------------------------------------
1 | version: '3'
2 |
3 | services:
4 |
5 | maildev:
6 | image: djfarrelly/maildev:1.0.0-rc2
7 | ports:
8 | - "8082:80"
9 | - "25"
10 | networks:
11 | - frontend
12 |
13 | pgweb:
14 | image: sosedoff/pgweb
15 | restart: on-failure
16 | ports:
17 | - "8081:8081"
18 | environment:
19 | - DATABASE_URL=postgres://admin:password@db:5432/postgres?sslmode=disable
20 | networks:
21 | - frontend
22 | - db-backend
23 |
24 | db:
25 | image: postgres:10
26 | environment:
27 | POSTGRES_USER: admin
28 | POSTGRES_PASSWORD: password
29 | networks:
30 | - db-backend
31 |
32 | networks:
33 | db-backend:
34 | frontend:
--------------------------------------------------------------------------------
/10_docker_tricks/3_network_security/run.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | docker-compose up
4 |
--------------------------------------------------------------------------------
/10_docker_tricks/4_database_init/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 |
3 | services:
4 | pgweb:
5 | image: sosedoff/pgweb
6 | restart: on-failure
7 | ports:
8 | - "8081:8081"
9 | environment:
10 | - DATABASE_URL=postgres://admin:password@db:5432/persons?sslmode=disable
11 | db:
12 | image: postgres:10
13 | ports:
14 | - "5432:5432"
15 | environment:
16 | POSTGRES_USER: admin
17 | POSTGRES_PASSWORD: password
18 | POSTGRES_DB: persons
19 | volumes:
20 | - ./init.sql:/docker-entrypoint-initdb.d/init.sql
--------------------------------------------------------------------------------
/10_docker_tricks/4_database_init/init.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE Persons (
2 | PersonID int,
3 | LastName varchar(255),
4 | FirstName varchar(255),
5 | Address varchar(255),
6 | City varchar(255)
7 | );
8 |
9 | INSERT INTO Persons VALUES (1, 'Johannes', 'Innerbichler', 'Salzburg');
--------------------------------------------------------------------------------
/10_docker_tricks/4_database_init/run.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | docker-compose up
4 |
--------------------------------------------------------------------------------
/10_docker_tricks/5_ps_output/run.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # more info: https://container42.com/2016/03/27/docker-quicktip-7-psformat/
4 | docker run busybox echo "hello from busybox"
5 |
6 | docker ps -a --format "table {{.Names}}\\t{{.Image}}\\t{{.Status}}"
7 |
8 |
--------------------------------------------------------------------------------
/10_docker_tricks/6_docker_in_docker/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 |
3 | services:
4 | dind:
5 | image: docker
6 | volumes:
7 | - /var/run/docker.sock:/var/run/docker.sock
8 | entrypoint: ["docker", "run", "busybox", "echo", "\"hello from busybox\""]
--------------------------------------------------------------------------------
/10_docker_tricks/6_docker_in_docker/run.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | docker-compose up
--------------------------------------------------------------------------------
/10_docker_tricks/7_onbuild/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3-onbuild
2 | CMD [ "python", "./main.py" ]
--------------------------------------------------------------------------------
/10_docker_tricks/7_onbuild/DockerfileOnBuild:
--------------------------------------------------------------------------------
1 | FROM python:3.6
2 |
3 | RUN mkdir -p /usr/src/app
4 | WORKDIR /usr/src/app
5 |
6 | ONBUILD COPY requirements.txt /usr/src/app/
7 | ONBUILD RUN pip install --no-cache-dir -r requirements.txt
8 |
9 | ONBUILD COPY . /usr/src/app
--------------------------------------------------------------------------------
/10_docker_tricks/7_onbuild/main.py:
--------------------------------------------------------------------------------
1 | import django
2 |
3 | print('It is working. Django version', django.__version__, 'is installed.')
4 |
--------------------------------------------------------------------------------
/10_docker_tricks/7_onbuild/requirements.txt:
--------------------------------------------------------------------------------
1 | django
--------------------------------------------------------------------------------
/10_docker_tricks/7_onbuild/run.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | docker build -t my-onbuild-app .
4 | docker run -it --rm --name my-running-app my-onbuild-app
--------------------------------------------------------------------------------
/10_docker_tricks/8_non_root/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM nginx:1.15.3
2 |
3 | # setup configuration
4 | COPY ./nginx.conf /etc/nginx/nginx.conf
5 |
6 | # set proper access right
7 | RUN touch /var/run/nginx.pid && \
8 | chown -R www-data:www-data /var/run/nginx.pid && \
9 | chown -R www-data:www-data /var/cache/nginx
10 |
11 | # change user
12 | USER www-data
13 |
14 | # copy static html file
15 | COPY index.html /var/www/htdocs/
--------------------------------------------------------------------------------
/10_docker_tricks/8_non_root/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 |
3 | services:
4 | nginx:
5 | build: .
6 | ports:
7 | - "80:8080"
--------------------------------------------------------------------------------
/10_docker_tricks/8_non_root/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | No Root
6 |
7 |
8 |
9 |
10 | Running without root ;)
11 |
12 |
13 |
--------------------------------------------------------------------------------
/10_docker_tricks/8_non_root/nginx.conf:
--------------------------------------------------------------------------------
1 | worker_processes 1;
2 | error_log /var/log/nginx/error.log warn;
3 | pid /var/run/nginx.pid;
4 |
5 | events {
6 | worker_connections 1024;
7 | }
8 |
9 | http {
10 | include /etc/nginx/mime.types;
11 | default_type application/octet-stream;
12 |
13 | sendfile on;
14 |
15 | keepalive_timeout 65;
16 |
17 | server {
18 | listen 8080;
19 | server_name localhost;
20 | location / {
21 | root /var/www/htdocs;
22 | index index.html index.htm;
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/10_docker_tricks/8_non_root/run.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | docker-compose up --build
--------------------------------------------------------------------------------
/10_docker_tricks/9_apt_get/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ubuntu:14.04
2 |
3 | RUN apt-get update && apt-get install -y curl
4 |
5 | ENTRYPOINT ["curl", "example.com"]
--------------------------------------------------------------------------------
/10_docker_tricks/9_apt_get/run.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | docker build -t my-app .
4 | docker run -it --rm --name my-running-app my-app
5 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Code base for blog articles at https://medium.com/@jinnerbichler
2 |
3 | Details can be found in respective folders.
4 |
--------------------------------------------------------------------------------
/k8s_keycloak/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by .ignore support plugin (hsz.mobi)
2 |
3 | target
--------------------------------------------------------------------------------
/k8s_keycloak/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:8-jdk-alpine
2 | VOLUME /tmp
3 | ARG JAR_FILE
4 | COPY ${JAR_FILE} app.jar
5 | ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
--------------------------------------------------------------------------------
/k8s_keycloak/kubernetes/app-deployment.yml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | name: person-app
5 | labels:
6 | name: person-app
7 | app: person-app
8 | spec:
9 | replicas: 1
10 | selector:
11 | matchLabels:
12 | app: person-app
13 | template:
14 | metadata:
15 | name: person-app
16 | labels:
17 | app: person-app
18 | name: person-app
19 | spec:
20 | restartPolicy: Always
21 | containers:
22 | - name: keycloak
23 | image: jinnerbichler/keycloak-k8s:latest
24 | imagePullPolicy: IfNotPresent
25 | ports:
26 | - containerPort: 8080
27 | protocol: TCP
28 | resources:
29 | requests:
30 | cpu: 200m
31 | memory: 256Mi
32 | limits:
33 | cpu: 400m
34 | memory: 512Mi
35 |
36 | ---
37 |
38 | apiVersion: v1
39 | kind: Service
40 | metadata:
41 | name: person-app
42 | labels:
43 | app: person-app
44 | name: person-app
45 | spec:
46 | type: NodePort
47 | ports:
48 | - name: http
49 | protocol: TCP
50 | port: 8080
51 | nodePort: 30081
52 | selector:
53 | app: person-app
54 | name: person-app
--------------------------------------------------------------------------------
/k8s_keycloak/kubernetes/keycloak-deployment.yml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | name: keycloak
5 | labels:
6 | name: keycloak
7 | app: keycloak
8 | spec:
9 | replicas: 1
10 | selector:
11 | matchLabels:
12 | app: keycloak
13 | template:
14 | metadata:
15 | name: keycloak
16 | labels:
17 | app: keycloak
18 | name: keycloak
19 | spec:
20 | restartPolicy: Always
21 | containers:
22 | - name: keycloak
23 | image: jboss/keycloak:3.4.3.Final
24 | imagePullPolicy: IfNotPresent
25 | ports:
26 | - containerPort: 8080
27 | protocol: TCP
28 | resources:
29 | requests:
30 | cpu: 200m
31 | memory: 256Mi
32 | limits:
33 | cpu: 400m
34 | memory: 512Mi
35 | env:
36 | - name: KEYCLOAK_LOGLEVEL
37 | value: "DEBUG"
38 | - name: PROXY_ADDRESS_FORWARDING
39 | value: "true"
40 | - name: KEYCLOAK_USER
41 | value: "admin"
42 | - name: KEYCLOAK_PASSWORD
43 | value: "password"
44 | - name: POSTGRES_USER
45 | value: "admin"
46 | - name: POSTGRES_PASSWORD
47 | value: "password"
48 | - name: POSTGRES_PORT_5432_TCP_ADDR
49 | value: "keycloak-db-postgresql"
50 | - name: POSTGRES_PORT_5432_TCP_PORT
51 | value: "5432"
52 | - name: POSTGRES_DATABASE
53 | value: "keycloak-db"
54 |
55 | ---
56 |
57 | apiVersion: v1
58 | kind: Service
59 | metadata:
60 | name: keycloak
61 | labels:
62 | app: keycloak
63 | name: keycloak
64 | spec:
65 | type: NodePort
66 | ports:
67 | - name: http
68 | protocol: TCP
69 | port: 8080
70 | nodePort: 30080
71 | selector:
72 | app: keycloak
73 | name: keycloak
--------------------------------------------------------------------------------
/k8s_keycloak/persons-application.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/k8s_keycloak/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | com.johannesinnerbichler
7 | keycloak-k8s
8 | 0.0.1-SNAPSHOT
9 | jar
10 |
11 | person-app
12 | Example project for integrating Keycloak with Spring Boot applications on Kubernetes.
13 |
14 |
15 | org.springframework.boot
16 | spring-boot-starter-parent
17 | 1.5.3.RELEASE
18 |
19 |
20 |
21 |
22 | UTF-8
23 | UTF-8
24 | 1.8
25 | 3.1.0.Final
26 | jinnerbichler
27 |
28 |
29 |
30 |
31 | org.springframework.boot
32 | spring-boot-starter-freemarker
33 |
34 |
35 | org.keycloak
36 | keycloak-spring-boot-starter
37 |
38 |
39 | org.springframework.boot
40 | spring-boot-starter-web
41 |
42 |
43 | org.springframework.boot
44 | spring-boot-starter-security
45 |
46 |
47 | org.springframework.boot
48 | spring-boot-starter-test
49 | test
50 |
51 |
52 |
53 |
54 |
55 |
56 | org.keycloak.bom
57 | keycloak-adapter-bom
58 | ${keycloak.version}
59 | pom
60 | import
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 | org.springframework.boot
69 | spring-boot-maven-plugin
70 |
71 |
72 | com.spotify
73 | dockerfile-maven-plugin
74 | 1.3.6
75 |
76 | ${docker.image.prefix}/${project.artifactId}
77 |
78 | target/${project.build.finalName}.jar
79 |
80 |
81 |
82 |
83 |
84 |
85 |
--------------------------------------------------------------------------------
/k8s_keycloak/readme.md:
--------------------------------------------------------------------------------
1 | ## Setup Prerequisites
2 |
3 | This project shows a simple Spring Boot application with Keycloak. Both, the application and Keycloak (including the database), will be deployed to a Kubernetes cluster.
4 |
5 | The Kubernetes cluster is created via Minikube, which provides tools for creating clusters on a local machine easily. Keycloak, the database, and the Spring Boot application are deployed to the newly created cluster.
6 | The following versions are used throughout the example:
7 |
8 | * __Minikube__: v0.25.0
9 | * __Docker__: 18.03.1-ce
10 | * __Kubectl__: v1.10.1
11 | * __Kubernetes__: v1.9.0
12 | * __Helm__: v2.8.2
13 | * __Spring Boot__: 1.5.3.RELEASE
14 | * __Keycloak__: 3.4.3.Final
15 |
16 | More details on the setup and the example application can be found in the corresponding [blog article](https://medium.com/@jinnerbichler/securing-spring-boot-applications-with-keycloak-on-kubernetes-76cdb6b8d674).
--------------------------------------------------------------------------------
/k8s_keycloak/src/main/java/com/johannesinnerbichler/personapp/PersonApplication.java:
--------------------------------------------------------------------------------
1 | package com.johannesinnerbichler.personapp;
2 |
3 | import org.keycloak.adapters.KeycloakConfigResolver;
4 | import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver;
5 | import org.keycloak.adapters.springsecurity.KeycloakSecurityComponents;
6 | import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider;
7 | import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter;
8 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
9 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
10 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
11 | import org.springframework.security.core.authority.mapping.SimpleAuthorityMapper;
12 | import org.springframework.security.core.session.SessionRegistryImpl;
13 | import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy;
14 | import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
15 | import org.springframework.beans.factory.annotation.Autowired;
16 | import org.springframework.boot.SpringApplication;
17 | import org.springframework.boot.autoconfigure.SpringBootApplication;
18 | import org.springframework.context.annotation.Bean;
19 | import org.springframework.context.annotation.ComponentScan;
20 | import org.springframework.context.annotation.Configuration;
21 | import org.springframework.stereotype.Controller;
22 | import org.springframework.ui.Model;
23 | import org.springframework.web.bind.annotation.GetMapping;
24 |
25 | import javax.servlet.ServletException;
26 | import javax.servlet.http.HttpServletRequest;
27 | import java.util.Arrays;
28 |
29 | @SpringBootApplication
30 | public class PersonApplication {
31 |
32 | public static void main(String[] args) {
33 | SpringApplication.run(PersonApplication.class, args);
34 | }
35 | }
36 |
37 | @Controller
38 | class PersonController {
39 |
40 | @GetMapping(path = "/persons")
41 | public String getPersons(Model model) {
42 | model.addAttribute("persons", Arrays.asList("John", "David", "Peter"));
43 | return "persons";
44 | }
45 |
46 | @GetMapping(path = "/logout")
47 | public String logout(HttpServletRequest request) throws ServletException {
48 | request.logout();
49 | return "/";
50 | }
51 | }
52 |
53 | @Configuration
54 | @EnableWebSecurity
55 | @ComponentScan(basePackageClasses = KeycloakSecurityComponents.class)
56 | class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
57 |
58 | /**
59 | * Registers the KeycloakAuthenticationProvider with the authentication manager.
60 | */
61 | @Autowired
62 | public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
63 | KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
64 |
65 | // adding proper authority mapper for prefixing role with "ROLE_"
66 | keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
67 |
68 | auth.authenticationProvider(keycloakAuthenticationProvider);
69 | }
70 |
71 | /**
72 | * Provide a session authentication strategy bean which should be of type
73 | * RegisterSessionAuthenticationStrategy for public or confidential applications
74 | * and NullAuthenticatedSessionStrategy for bearer-only applications.
75 | */
76 | @Bean
77 | @Override
78 | protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
79 | return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
80 | }
81 |
82 | /**
83 | * Use properties in application.properties instead of keycloak.json
84 | */
85 | @Bean
86 | public KeycloakConfigResolver KeycloakConfigResolver() {
87 | return new KeycloakSpringBootConfigResolver();
88 | }
89 |
90 | /**
91 | * Secure appropriate endpoints
92 | */
93 | @Override
94 | protected void configure(HttpSecurity http) throws Exception {
95 | super.configure(http);
96 | http
97 | .authorizeRequests()
98 | .antMatchers("/persons*").hasRole("user") // only user with role user are allowed to access
99 | .anyRequest().permitAll();
100 | }
101 | }
102 |
103 |
--------------------------------------------------------------------------------
/k8s_keycloak/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | keycloak.auth-server-url=http://192.168.99.100:30080/auth/
2 | keycloak.resource=persons-app
3 | keycloak.realm=master
4 | keycloak.public-client=true
5 | keycloak.principal-attribute=preferred_username
6 |
--------------------------------------------------------------------------------
/k8s_keycloak/src/main/resources/static/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Landing page
6 |
7 |
8 |
9 | All persons
10 |
11 |
12 |
--------------------------------------------------------------------------------
/k8s_keycloak/src/main/resources/templates/persons.ftl:
--------------------------------------------------------------------------------
1 | <#import "/spring.ftl" as spring>
2 |
3 |
4 | Persons
5 |
6 | <#list persons as person>
7 | - ${person}
8 | #list>
9 |
10 |
11 | Logout
12 |
--------------------------------------------------------------------------------
/k8s_keycloak/util.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 |
4 | set -e # Exits immediately if a command exits with a non-zero status.
5 |
6 | if [[ "$1" = "keycloak-db" ]]; then
7 |
8 | helm install --name keycloak-db \
9 | --set postgresUser=admin \
10 | --set postgresPassword=password \
11 | --set postgresDatabase=keycloak-db \
12 | stable/postgresql
13 |
14 | elif [ "$1" == "keycloak-start" ]; then
15 |
16 | kubectl apply -f ./kubernetes/keycloak-deployment.yml
17 |
18 | elif [ "$1" == "keycloak-open" ]; then
19 |
20 | minikube service keycloak
21 |
22 | elif [ "$1" == "keycloak-url" ]; then
23 |
24 | minikube service keycloak --url
25 |
26 | elif [ "$1" == "keycloak-logs" ]; then
27 |
28 | POD_NAME=$(kubectl get pods -l name=keycloak -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}')
29 | kubectl logs -f ${POD_NAME}
30 |
31 | elif [ "$1" == "app-open" ]; then
32 |
33 | minikube service person-app
34 |
35 | elif [ "$1" == "app-url" ]; then
36 |
37 | minikube service person-app --url
38 |
39 | elif [ "$1" == "app-logs" ]; then
40 |
41 | POD_NAME=$(kubectl get pods -l name=person-app -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}')
42 | kubectl logs -f ${POD_NAME}
43 |
44 | fi
45 |
46 | fi
--------------------------------------------------------------------------------
/keycloak_4_spring_boot_2/keycloak/config/PersonRealm-realm.json:
--------------------------------------------------------------------------------
1 | {
2 | "id" : "PersonRealm",
3 | "realm" : "PersonRealm",
4 | "notBefore" : 0,
5 | "revokeRefreshToken" : false,
6 | "refreshTokenMaxReuse" : 0,
7 | "accessTokenLifespan" : 300,
8 | "accessTokenLifespanForImplicitFlow" : 900,
9 | "ssoSessionIdleTimeout" : 1800,
10 | "ssoSessionMaxLifespan" : 36000,
11 | "offlineSessionIdleTimeout" : 2592000,
12 | "accessCodeLifespan" : 60,
13 | "accessCodeLifespanUserAction" : 300,
14 | "accessCodeLifespanLogin" : 1800,
15 | "actionTokenGeneratedByAdminLifespan" : 43200,
16 | "actionTokenGeneratedByUserLifespan" : 300,
17 | "enabled" : true,
18 | "sslRequired" : "external",
19 | "registrationAllowed" : false,
20 | "registrationEmailAsUsername" : false,
21 | "rememberMe" : false,
22 | "verifyEmail" : false,
23 | "loginWithEmailAllowed" : true,
24 | "duplicateEmailsAllowed" : false,
25 | "resetPasswordAllowed" : false,
26 | "editUsernameAllowed" : false,
27 | "bruteForceProtected" : false,
28 | "permanentLockout" : false,
29 | "maxFailureWaitSeconds" : 900,
30 | "minimumQuickLoginWaitSeconds" : 60,
31 | "waitIncrementSeconds" : 60,
32 | "quickLoginCheckMilliSeconds" : 1000,
33 | "maxDeltaTimeSeconds" : 43200,
34 | "failureFactor" : 30,
35 | "roles" : {
36 | "realm" : [ {
37 | "id" : "f1fd854e-ef55-4df3-b256-8e39cd69a589",
38 | "name" : "uma_authorization",
39 | "description" : "${role_uma_authorization}",
40 | "composite" : false,
41 | "clientRole" : false,
42 | "containerId" : "PersonRealm"
43 | }, {
44 | "id" : "e427f7a9-4add-4c6f-a951-77b1b57a463b",
45 | "name" : "offline_access",
46 | "description" : "${role_offline-access}",
47 | "composite" : false,
48 | "clientRole" : false,
49 | "containerId" : "PersonRealm"
50 | }, {
51 | "id" : "be37d4f9-7ee8-4be2-b1a1-15481aef4024",
52 | "name" : "user",
53 | "composite" : false,
54 | "clientRole" : false,
55 | "containerId" : "PersonRealm"
56 | } ],
57 | "client" : {
58 | "realm-management" : [ {
59 | "id" : "9c5314b9-c1d9-449d-b5f6-b6cde96d616d",
60 | "name" : "view-identity-providers",
61 | "description" : "${role_view-identity-providers}",
62 | "composite" : false,
63 | "clientRole" : true,
64 | "containerId" : "bf8bb9d8-0a7b-44aa-8605-4e118682a7c9"
65 | }, {
66 | "id" : "f1f305da-12a7-4906-a77f-8954a39a5cb3",
67 | "name" : "manage-users",
68 | "description" : "${role_manage-users}",
69 | "composite" : false,
70 | "clientRole" : true,
71 | "containerId" : "bf8bb9d8-0a7b-44aa-8605-4e118682a7c9"
72 | }, {
73 | "id" : "5d44e28d-cf22-4c5e-9517-0f42d02a883c",
74 | "name" : "impersonation",
75 | "description" : "${role_impersonation}",
76 | "composite" : false,
77 | "clientRole" : true,
78 | "containerId" : "bf8bb9d8-0a7b-44aa-8605-4e118682a7c9"
79 | }, {
80 | "id" : "0088b2ac-8c27-4274-9b56-1a505def98fc",
81 | "name" : "create-client",
82 | "description" : "${role_create-client}",
83 | "composite" : false,
84 | "clientRole" : true,
85 | "containerId" : "bf8bb9d8-0a7b-44aa-8605-4e118682a7c9"
86 | }, {
87 | "id" : "83c7d7da-fcda-4fb6-a705-a14f1a7b9fe5",
88 | "name" : "query-realms",
89 | "description" : "${role_query-realms}",
90 | "composite" : false,
91 | "clientRole" : true,
92 | "containerId" : "bf8bb9d8-0a7b-44aa-8605-4e118682a7c9"
93 | }, {
94 | "id" : "f90b735e-abcb-445a-9ef0-a13a9a57e08c",
95 | "name" : "view-clients",
96 | "description" : "${role_view-clients}",
97 | "composite" : true,
98 | "composites" : {
99 | "client" : {
100 | "realm-management" : [ "query-clients" ]
101 | }
102 | },
103 | "clientRole" : true,
104 | "containerId" : "bf8bb9d8-0a7b-44aa-8605-4e118682a7c9"
105 | }, {
106 | "id" : "fc487a40-cdaa-42dd-bd50-2477a3d7239e",
107 | "name" : "view-authorization",
108 | "description" : "${role_view-authorization}",
109 | "composite" : false,
110 | "clientRole" : true,
111 | "containerId" : "bf8bb9d8-0a7b-44aa-8605-4e118682a7c9"
112 | }, {
113 | "id" : "3f4e2fd9-2372-4424-87e5-e547bc6d211b",
114 | "name" : "query-users",
115 | "description" : "${role_query-users}",
116 | "composite" : false,
117 | "clientRole" : true,
118 | "containerId" : "bf8bb9d8-0a7b-44aa-8605-4e118682a7c9"
119 | }, {
120 | "id" : "d8412b94-0806-4f4b-be37-3454829b8aa4",
121 | "name" : "manage-realm",
122 | "description" : "${role_manage-realm}",
123 | "composite" : false,
124 | "clientRole" : true,
125 | "containerId" : "bf8bb9d8-0a7b-44aa-8605-4e118682a7c9"
126 | }, {
127 | "id" : "ffd68f72-06eb-4ef9-9662-74bdd4b9a46a",
128 | "name" : "manage-identity-providers",
129 | "description" : "${role_manage-identity-providers}",
130 | "composite" : false,
131 | "clientRole" : true,
132 | "containerId" : "bf8bb9d8-0a7b-44aa-8605-4e118682a7c9"
133 | }, {
134 | "id" : "7367b94d-064c-4418-922f-7828c5c3d333",
135 | "name" : "query-groups",
136 | "description" : "${role_query-groups}",
137 | "composite" : false,
138 | "clientRole" : true,
139 | "containerId" : "bf8bb9d8-0a7b-44aa-8605-4e118682a7c9"
140 | }, {
141 | "id" : "551bd221-bffa-4d27-841f-dfc1c89010fb",
142 | "name" : "realm-admin",
143 | "description" : "${role_realm-admin}",
144 | "composite" : true,
145 | "composites" : {
146 | "client" : {
147 | "realm-management" : [ "view-identity-providers", "manage-users", "impersonation", "create-client", "query-realms", "view-clients", "view-authorization", "query-users", "manage-realm", "manage-identity-providers", "query-groups", "manage-clients", "view-events", "view-users", "manage-events", "view-realm", "manage-authorization", "query-clients" ]
148 | }
149 | },
150 | "clientRole" : true,
151 | "containerId" : "bf8bb9d8-0a7b-44aa-8605-4e118682a7c9"
152 | }, {
153 | "id" : "1eb333d2-96e1-49ec-a7e4-10f2c74f730a",
154 | "name" : "manage-clients",
155 | "description" : "${role_manage-clients}",
156 | "composite" : false,
157 | "clientRole" : true,
158 | "containerId" : "bf8bb9d8-0a7b-44aa-8605-4e118682a7c9"
159 | }, {
160 | "id" : "318990a0-75e9-417f-bf00-2cfc93f1b2bf",
161 | "name" : "view-events",
162 | "description" : "${role_view-events}",
163 | "composite" : false,
164 | "clientRole" : true,
165 | "containerId" : "bf8bb9d8-0a7b-44aa-8605-4e118682a7c9"
166 | }, {
167 | "id" : "573c2f39-49c3-4375-bcc1-9ce5e4f4759a",
168 | "name" : "view-users",
169 | "description" : "${role_view-users}",
170 | "composite" : true,
171 | "composites" : {
172 | "client" : {
173 | "realm-management" : [ "query-users", "query-groups" ]
174 | }
175 | },
176 | "clientRole" : true,
177 | "containerId" : "bf8bb9d8-0a7b-44aa-8605-4e118682a7c9"
178 | }, {
179 | "id" : "375038ea-c600-43cc-bf98-80d52a147ff8",
180 | "name" : "manage-events",
181 | "description" : "${role_manage-events}",
182 | "composite" : false,
183 | "clientRole" : true,
184 | "containerId" : "bf8bb9d8-0a7b-44aa-8605-4e118682a7c9"
185 | }, {
186 | "id" : "b9d47a12-99f5-42b6-9465-9a4246c741f9",
187 | "name" : "view-realm",
188 | "description" : "${role_view-realm}",
189 | "composite" : false,
190 | "clientRole" : true,
191 | "containerId" : "bf8bb9d8-0a7b-44aa-8605-4e118682a7c9"
192 | }, {
193 | "id" : "401d748c-3f89-4eb7-8a1d-a222f31fd27b",
194 | "name" : "manage-authorization",
195 | "description" : "${role_manage-authorization}",
196 | "composite" : false,
197 | "clientRole" : true,
198 | "containerId" : "bf8bb9d8-0a7b-44aa-8605-4e118682a7c9"
199 | }, {
200 | "id" : "3d3b7c47-9f5e-4c62-94d3-43b93ae5f248",
201 | "name" : "query-clients",
202 | "description" : "${role_query-clients}",
203 | "composite" : false,
204 | "clientRole" : true,
205 | "containerId" : "bf8bb9d8-0a7b-44aa-8605-4e118682a7c9"
206 | } ],
207 | "security-admin-console" : [ ],
208 | "admin-cli" : [ ],
209 | "persons-app" : [ ],
210 | "broker" : [ {
211 | "id" : "1b8bce57-194a-46b5-8315-6846c7501efc",
212 | "name" : "read-token",
213 | "description" : "${role_read-token}",
214 | "composite" : false,
215 | "clientRole" : true,
216 | "containerId" : "b34e5ac9-79a5-4242-81b2-2fdfa3847386"
217 | } ],
218 | "account" : [ {
219 | "id" : "58928f97-e7e3-486f-b091-028ec718dcd1",
220 | "name" : "manage-account-links",
221 | "description" : "${role_manage-account-links}",
222 | "composite" : false,
223 | "clientRole" : true,
224 | "containerId" : "53955858-c44e-462e-bb17-b9377998d1c1"
225 | }, {
226 | "id" : "a0f4c87e-49fd-4d21-a715-d922a0ef5dab",
227 | "name" : "view-profile",
228 | "description" : "${role_view-profile}",
229 | "composite" : false,
230 | "clientRole" : true,
231 | "containerId" : "53955858-c44e-462e-bb17-b9377998d1c1"
232 | }, {
233 | "id" : "9a96bbe2-ecd3-436c-8023-4e85e6352f42",
234 | "name" : "manage-account",
235 | "description" : "${role_manage-account}",
236 | "composite" : true,
237 | "composites" : {
238 | "client" : {
239 | "account" : [ "manage-account-links" ]
240 | }
241 | },
242 | "clientRole" : true,
243 | "containerId" : "53955858-c44e-462e-bb17-b9377998d1c1"
244 | } ]
245 | }
246 | },
247 | "groups" : [ ],
248 | "defaultRoles" : [ "uma_authorization", "offline_access" ],
249 | "requiredCredentials" : [ "password" ],
250 | "otpPolicyType" : "totp",
251 | "otpPolicyAlgorithm" : "HmacSHA1",
252 | "otpPolicyInitialCounter" : 0,
253 | "otpPolicyDigits" : 6,
254 | "otpPolicyLookAheadWindow" : 1,
255 | "otpPolicyPeriod" : 30,
256 | "otpSupportedApplications" : [ "FreeOTP", "Google Authenticator" ],
257 | "scopeMappings" : [ {
258 | "clientScope" : "offline_access",
259 | "roles" : [ "offline_access" ]
260 | } ],
261 | "clients" : [ {
262 | "id" : "53955858-c44e-462e-bb17-b9377998d1c1",
263 | "clientId" : "account",
264 | "name" : "${client_account}",
265 | "baseUrl" : "/auth/realms/PersonRealm/account",
266 | "surrogateAuthRequired" : false,
267 | "enabled" : true,
268 | "clientAuthenticatorType" : "client-secret",
269 | "secret" : "**********",
270 | "defaultRoles" : [ "view-profile", "manage-account" ],
271 | "redirectUris" : [ "/auth/realms/PersonRealm/account/*" ],
272 | "webOrigins" : [ ],
273 | "notBefore" : 0,
274 | "bearerOnly" : false,
275 | "consentRequired" : false,
276 | "standardFlowEnabled" : true,
277 | "implicitFlowEnabled" : false,
278 | "directAccessGrantsEnabled" : false,
279 | "serviceAccountsEnabled" : false,
280 | "publicClient" : false,
281 | "frontchannelLogout" : false,
282 | "protocol" : "openid-connect",
283 | "attributes" : { },
284 | "authenticationFlowBindingOverrides" : { },
285 | "fullScopeAllowed" : false,
286 | "nodeReRegistrationTimeout" : 0,
287 | "defaultClientScopes" : [ "role_list", "profile", "email" ],
288 | "optionalClientScopes" : [ "address", "phone", "offline_access" ]
289 | }, {
290 | "id" : "00561324-be76-43e0-860d-6131e6a111df",
291 | "clientId" : "admin-cli",
292 | "name" : "${client_admin-cli}",
293 | "surrogateAuthRequired" : false,
294 | "enabled" : true,
295 | "clientAuthenticatorType" : "client-secret",
296 | "secret" : "**********",
297 | "redirectUris" : [ ],
298 | "webOrigins" : [ ],
299 | "notBefore" : 0,
300 | "bearerOnly" : false,
301 | "consentRequired" : false,
302 | "standardFlowEnabled" : false,
303 | "implicitFlowEnabled" : false,
304 | "directAccessGrantsEnabled" : true,
305 | "serviceAccountsEnabled" : false,
306 | "publicClient" : true,
307 | "frontchannelLogout" : false,
308 | "protocol" : "openid-connect",
309 | "attributes" : { },
310 | "authenticationFlowBindingOverrides" : { },
311 | "fullScopeAllowed" : false,
312 | "nodeReRegistrationTimeout" : 0,
313 | "defaultClientScopes" : [ "role_list", "profile", "email" ],
314 | "optionalClientScopes" : [ "address", "phone", "offline_access" ]
315 | }, {
316 | "id" : "b34e5ac9-79a5-4242-81b2-2fdfa3847386",
317 | "clientId" : "broker",
318 | "name" : "${client_broker}",
319 | "surrogateAuthRequired" : false,
320 | "enabled" : true,
321 | "clientAuthenticatorType" : "client-secret",
322 | "secret" : "**********",
323 | "redirectUris" : [ ],
324 | "webOrigins" : [ ],
325 | "notBefore" : 0,
326 | "bearerOnly" : false,
327 | "consentRequired" : false,
328 | "standardFlowEnabled" : true,
329 | "implicitFlowEnabled" : false,
330 | "directAccessGrantsEnabled" : false,
331 | "serviceAccountsEnabled" : false,
332 | "publicClient" : false,
333 | "frontchannelLogout" : false,
334 | "protocol" : "openid-connect",
335 | "attributes" : { },
336 | "authenticationFlowBindingOverrides" : { },
337 | "fullScopeAllowed" : false,
338 | "nodeReRegistrationTimeout" : 0,
339 | "defaultClientScopes" : [ "role_list", "profile", "email" ],
340 | "optionalClientScopes" : [ "address", "phone", "offline_access" ]
341 | }, {
342 | "id" : "bef95718-8080-465c-b242-94730834379f",
343 | "clientId" : "persons-app",
344 | "baseUrl" : "http://localhost:8080/",
345 | "surrogateAuthRequired" : false,
346 | "enabled" : true,
347 | "clientAuthenticatorType" : "client-secret",
348 | "secret" : "**********",
349 | "redirectUris" : [ "http://localhost:8080/*" ],
350 | "webOrigins" : [ ],
351 | "notBefore" : 0,
352 | "bearerOnly" : false,
353 | "consentRequired" : false,
354 | "standardFlowEnabled" : true,
355 | "implicitFlowEnabled" : false,
356 | "directAccessGrantsEnabled" : true,
357 | "serviceAccountsEnabled" : false,
358 | "publicClient" : true,
359 | "frontchannelLogout" : false,
360 | "protocol" : "openid-connect",
361 | "attributes" : {
362 | "saml.assertion.signature" : "false",
363 | "saml.force.post.binding" : "false",
364 | "saml.multivalued.roles" : "false",
365 | "saml.encrypt" : "false",
366 | "saml.server.signature" : "false",
367 | "saml.server.signature.keyinfo.ext" : "false",
368 | "exclude.session.state.from.auth.response" : "false",
369 | "saml_force_name_id_format" : "false",
370 | "saml.client.signature" : "false",
371 | "tls.client.certificate.bound.access.tokens" : "false",
372 | "saml.authnstatement" : "false",
373 | "display.on.consent.screen" : "false",
374 | "saml.onetimeuse.condition" : "false"
375 | },
376 | "authenticationFlowBindingOverrides" : { },
377 | "fullScopeAllowed" : true,
378 | "nodeReRegistrationTimeout" : -1,
379 | "defaultClientScopes" : [ "role_list", "profile", "email" ],
380 | "optionalClientScopes" : [ "address", "phone", "offline_access" ]
381 | }, {
382 | "id" : "bf8bb9d8-0a7b-44aa-8605-4e118682a7c9",
383 | "clientId" : "realm-management",
384 | "name" : "${client_realm-management}",
385 | "surrogateAuthRequired" : false,
386 | "enabled" : true,
387 | "clientAuthenticatorType" : "client-secret",
388 | "secret" : "**********",
389 | "redirectUris" : [ ],
390 | "webOrigins" : [ ],
391 | "notBefore" : 0,
392 | "bearerOnly" : true,
393 | "consentRequired" : false,
394 | "standardFlowEnabled" : true,
395 | "implicitFlowEnabled" : false,
396 | "directAccessGrantsEnabled" : false,
397 | "serviceAccountsEnabled" : false,
398 | "publicClient" : false,
399 | "frontchannelLogout" : false,
400 | "protocol" : "openid-connect",
401 | "attributes" : { },
402 | "authenticationFlowBindingOverrides" : { },
403 | "fullScopeAllowed" : false,
404 | "nodeReRegistrationTimeout" : 0,
405 | "defaultClientScopes" : [ "role_list", "profile", "email" ],
406 | "optionalClientScopes" : [ "address", "phone", "offline_access" ]
407 | }, {
408 | "id" : "b40d57ce-7f22-40eb-89a7-d8272c614bd7",
409 | "clientId" : "security-admin-console",
410 | "name" : "${client_security-admin-console}",
411 | "baseUrl" : "/auth/admin/PersonRealm/console/index.html",
412 | "surrogateAuthRequired" : false,
413 | "enabled" : true,
414 | "clientAuthenticatorType" : "client-secret",
415 | "secret" : "**********",
416 | "redirectUris" : [ "/auth/admin/PersonRealm/console/*" ],
417 | "webOrigins" : [ ],
418 | "notBefore" : 0,
419 | "bearerOnly" : false,
420 | "consentRequired" : false,
421 | "standardFlowEnabled" : true,
422 | "implicitFlowEnabled" : false,
423 | "directAccessGrantsEnabled" : false,
424 | "serviceAccountsEnabled" : false,
425 | "publicClient" : true,
426 | "frontchannelLogout" : false,
427 | "protocol" : "openid-connect",
428 | "attributes" : { },
429 | "authenticationFlowBindingOverrides" : { },
430 | "fullScopeAllowed" : false,
431 | "nodeReRegistrationTimeout" : 0,
432 | "protocolMappers" : [ {
433 | "id" : "b486d4cf-2fcc-4dde-960c-cfceafe91f06",
434 | "name" : "locale",
435 | "protocol" : "openid-connect",
436 | "protocolMapper" : "oidc-usermodel-attribute-mapper",
437 | "consentRequired" : false,
438 | "config" : {
439 | "userinfo.token.claim" : "true",
440 | "user.attribute" : "locale",
441 | "id.token.claim" : "true",
442 | "access.token.claim" : "true",
443 | "claim.name" : "locale",
444 | "jsonType.label" : "String"
445 | }
446 | } ],
447 | "defaultClientScopes" : [ "role_list", "profile", "email" ],
448 | "optionalClientScopes" : [ "address", "phone", "offline_access" ]
449 | } ],
450 | "clientScopes" : [ {
451 | "id" : "1cb966fd-2a2d-4b3f-850e-ae541bbf44b1",
452 | "name" : "offline_access",
453 | "description" : "OpenID Connect built-in scope: offline_access",
454 | "protocol" : "openid-connect",
455 | "attributes" : {
456 | "consent.screen.text" : "${offlineAccessScopeConsentText}",
457 | "display.on.consent.screen" : "true"
458 | }
459 | }, {
460 | "id" : "0cdbb297-b565-4048-b11d-8d53dd55d887",
461 | "name" : "role_list",
462 | "description" : "SAML role list",
463 | "protocol" : "saml",
464 | "attributes" : {
465 | "consent.screen.text" : "${samlRoleListScopeConsentText}",
466 | "display.on.consent.screen" : "true"
467 | },
468 | "protocolMappers" : [ {
469 | "id" : "1982e790-d3dc-46e5-8a84-eed22f88e0f9",
470 | "name" : "role list",
471 | "protocol" : "saml",
472 | "protocolMapper" : "saml-role-list-mapper",
473 | "consentRequired" : false,
474 | "config" : {
475 | "single" : "false",
476 | "attribute.nameformat" : "Basic",
477 | "attribute.name" : "Role"
478 | }
479 | } ]
480 | }, {
481 | "id" : "b12748f6-57df-4c27-80ec-2f05a8af43be",
482 | "name" : "profile",
483 | "description" : "OpenID Connect built-in scope: profile",
484 | "protocol" : "openid-connect",
485 | "attributes" : {
486 | "consent.screen.text" : "${profileScopeConsentText}",
487 | "display.on.consent.screen" : "true"
488 | },
489 | "protocolMappers" : [ {
490 | "id" : "703e93ee-35bd-46a9-89b2-adaa47447c43",
491 | "name" : "given name",
492 | "protocol" : "openid-connect",
493 | "protocolMapper" : "oidc-usermodel-property-mapper",
494 | "consentRequired" : false,
495 | "config" : {
496 | "userinfo.token.claim" : "true",
497 | "user.attribute" : "firstName",
498 | "id.token.claim" : "true",
499 | "access.token.claim" : "true",
500 | "claim.name" : "given_name",
501 | "jsonType.label" : "String"
502 | }
503 | }, {
504 | "id" : "e924738f-ae01-4e04-a33b-f9d31c609d8a",
505 | "name" : "zoneinfo",
506 | "protocol" : "openid-connect",
507 | "protocolMapper" : "oidc-usermodel-attribute-mapper",
508 | "consentRequired" : false,
509 | "config" : {
510 | "userinfo.token.claim" : "true",
511 | "user.attribute" : "zoneinfo",
512 | "id.token.claim" : "true",
513 | "access.token.claim" : "true",
514 | "claim.name" : "zoneinfo",
515 | "jsonType.label" : "String"
516 | }
517 | }, {
518 | "id" : "280677f2-c9a9-4876-94fe-add64181467c",
519 | "name" : "picture",
520 | "protocol" : "openid-connect",
521 | "protocolMapper" : "oidc-usermodel-attribute-mapper",
522 | "consentRequired" : false,
523 | "config" : {
524 | "userinfo.token.claim" : "true",
525 | "user.attribute" : "picture",
526 | "id.token.claim" : "true",
527 | "access.token.claim" : "true",
528 | "claim.name" : "picture",
529 | "jsonType.label" : "String"
530 | }
531 | }, {
532 | "id" : "23631684-ffb2-4127-be27-96f0c4761d0d",
533 | "name" : "birthdate",
534 | "protocol" : "openid-connect",
535 | "protocolMapper" : "oidc-usermodel-attribute-mapper",
536 | "consentRequired" : false,
537 | "config" : {
538 | "userinfo.token.claim" : "true",
539 | "user.attribute" : "birthdate",
540 | "id.token.claim" : "true",
541 | "access.token.claim" : "true",
542 | "claim.name" : "birthdate",
543 | "jsonType.label" : "String"
544 | }
545 | }, {
546 | "id" : "0331ba55-8552-46d9-a55b-e9b0475e142f",
547 | "name" : "nickname",
548 | "protocol" : "openid-connect",
549 | "protocolMapper" : "oidc-usermodel-attribute-mapper",
550 | "consentRequired" : false,
551 | "config" : {
552 | "userinfo.token.claim" : "true",
553 | "user.attribute" : "nickname",
554 | "id.token.claim" : "true",
555 | "access.token.claim" : "true",
556 | "claim.name" : "nickname",
557 | "jsonType.label" : "String"
558 | }
559 | }, {
560 | "id" : "45a14c9a-923a-47bb-a794-767ec624c1ed",
561 | "name" : "profile",
562 | "protocol" : "openid-connect",
563 | "protocolMapper" : "oidc-usermodel-attribute-mapper",
564 | "consentRequired" : false,
565 | "config" : {
566 | "userinfo.token.claim" : "true",
567 | "user.attribute" : "profile",
568 | "id.token.claim" : "true",
569 | "access.token.claim" : "true",
570 | "claim.name" : "profile",
571 | "jsonType.label" : "String"
572 | }
573 | }, {
574 | "id" : "180f1743-31d2-41bd-8bfe-6855fc3818e5",
575 | "name" : "website",
576 | "protocol" : "openid-connect",
577 | "protocolMapper" : "oidc-usermodel-attribute-mapper",
578 | "consentRequired" : false,
579 | "config" : {
580 | "userinfo.token.claim" : "true",
581 | "user.attribute" : "website",
582 | "id.token.claim" : "true",
583 | "access.token.claim" : "true",
584 | "claim.name" : "website",
585 | "jsonType.label" : "String"
586 | }
587 | }, {
588 | "id" : "9fb04bdb-2c2e-4e17-914c-01963f978097",
589 | "name" : "gender",
590 | "protocol" : "openid-connect",
591 | "protocolMapper" : "oidc-usermodel-attribute-mapper",
592 | "consentRequired" : false,
593 | "config" : {
594 | "userinfo.token.claim" : "true",
595 | "user.attribute" : "gender",
596 | "id.token.claim" : "true",
597 | "access.token.claim" : "true",
598 | "claim.name" : "gender",
599 | "jsonType.label" : "String"
600 | }
601 | }, {
602 | "id" : "210ef4e2-c552-447b-8c35-0388612a8a7d",
603 | "name" : "username",
604 | "protocol" : "openid-connect",
605 | "protocolMapper" : "oidc-usermodel-property-mapper",
606 | "consentRequired" : false,
607 | "config" : {
608 | "userinfo.token.claim" : "true",
609 | "user.attribute" : "username",
610 | "id.token.claim" : "true",
611 | "access.token.claim" : "true",
612 | "claim.name" : "preferred_username",
613 | "jsonType.label" : "String"
614 | }
615 | }, {
616 | "id" : "bb71ec7d-06f1-409d-bb41-f85156061d08",
617 | "name" : "middle name",
618 | "protocol" : "openid-connect",
619 | "protocolMapper" : "oidc-usermodel-attribute-mapper",
620 | "consentRequired" : false,
621 | "config" : {
622 | "userinfo.token.claim" : "true",
623 | "user.attribute" : "middleName",
624 | "id.token.claim" : "true",
625 | "access.token.claim" : "true",
626 | "claim.name" : "middle_name",
627 | "jsonType.label" : "String"
628 | }
629 | }, {
630 | "id" : "01027a38-0ec8-4447-8cce-cf4b2f5ae712",
631 | "name" : "updated at",
632 | "protocol" : "openid-connect",
633 | "protocolMapper" : "oidc-usermodel-attribute-mapper",
634 | "consentRequired" : false,
635 | "config" : {
636 | "userinfo.token.claim" : "true",
637 | "user.attribute" : "updatedAt",
638 | "id.token.claim" : "true",
639 | "access.token.claim" : "true",
640 | "claim.name" : "updated_at",
641 | "jsonType.label" : "String"
642 | }
643 | }, {
644 | "id" : "8c851fa5-8727-45d6-b4cc-5fb75b902127",
645 | "name" : "locale",
646 | "protocol" : "openid-connect",
647 | "protocolMapper" : "oidc-usermodel-attribute-mapper",
648 | "consentRequired" : false,
649 | "config" : {
650 | "userinfo.token.claim" : "true",
651 | "user.attribute" : "locale",
652 | "id.token.claim" : "true",
653 | "access.token.claim" : "true",
654 | "claim.name" : "locale",
655 | "jsonType.label" : "String"
656 | }
657 | }, {
658 | "id" : "0eedaa1b-0a0b-491d-bb49-e63ab26734f9",
659 | "name" : "family name",
660 | "protocol" : "openid-connect",
661 | "protocolMapper" : "oidc-usermodel-property-mapper",
662 | "consentRequired" : false,
663 | "config" : {
664 | "userinfo.token.claim" : "true",
665 | "user.attribute" : "lastName",
666 | "id.token.claim" : "true",
667 | "access.token.claim" : "true",
668 | "claim.name" : "family_name",
669 | "jsonType.label" : "String"
670 | }
671 | }, {
672 | "id" : "03adb547-2127-41e2-9101-19a4646bc314",
673 | "name" : "full name",
674 | "protocol" : "openid-connect",
675 | "protocolMapper" : "oidc-full-name-mapper",
676 | "consentRequired" : false,
677 | "config" : {
678 | "id.token.claim" : "true",
679 | "access.token.claim" : "true",
680 | "userinfo.token.claim" : "true"
681 | }
682 | } ]
683 | }, {
684 | "id" : "444173d1-a4cd-4adc-a831-842ddcae18a5",
685 | "name" : "email",
686 | "description" : "OpenID Connect built-in scope: email",
687 | "protocol" : "openid-connect",
688 | "attributes" : {
689 | "consent.screen.text" : "${emailScopeConsentText}",
690 | "display.on.consent.screen" : "true"
691 | },
692 | "protocolMappers" : [ {
693 | "id" : "3bb21539-0281-4bf4-a57b-ad3e715658df",
694 | "name" : "email",
695 | "protocol" : "openid-connect",
696 | "protocolMapper" : "oidc-usermodel-property-mapper",
697 | "consentRequired" : false,
698 | "config" : {
699 | "userinfo.token.claim" : "true",
700 | "user.attribute" : "email",
701 | "id.token.claim" : "true",
702 | "access.token.claim" : "true",
703 | "claim.name" : "email",
704 | "jsonType.label" : "String"
705 | }
706 | }, {
707 | "id" : "a5c03d59-f8d4-43da-8949-73ede4cb307a",
708 | "name" : "email verified",
709 | "protocol" : "openid-connect",
710 | "protocolMapper" : "oidc-usermodel-property-mapper",
711 | "consentRequired" : false,
712 | "config" : {
713 | "userinfo.token.claim" : "true",
714 | "user.attribute" : "emailVerified",
715 | "id.token.claim" : "true",
716 | "access.token.claim" : "true",
717 | "claim.name" : "email_verified",
718 | "jsonType.label" : "boolean"
719 | }
720 | } ]
721 | }, {
722 | "id" : "c72035d3-f82b-4316-8fb1-82c6316a954d",
723 | "name" : "address",
724 | "description" : "OpenID Connect built-in scope: address",
725 | "protocol" : "openid-connect",
726 | "attributes" : {
727 | "consent.screen.text" : "${addressScopeConsentText}",
728 | "display.on.consent.screen" : "true"
729 | },
730 | "protocolMappers" : [ {
731 | "id" : "379c75c6-4393-412d-9a47-a004172b4f37",
732 | "name" : "address",
733 | "protocol" : "openid-connect",
734 | "protocolMapper" : "oidc-address-mapper",
735 | "consentRequired" : false,
736 | "config" : {
737 | "user.attribute.formatted" : "formatted",
738 | "user.attribute.country" : "country",
739 | "user.attribute.postal_code" : "postal_code",
740 | "userinfo.token.claim" : "true",
741 | "user.attribute.street" : "street",
742 | "id.token.claim" : "true",
743 | "user.attribute.region" : "region",
744 | "access.token.claim" : "true",
745 | "user.attribute.locality" : "locality"
746 | }
747 | } ]
748 | }, {
749 | "id" : "48563fc3-c999-4d5e-9ecd-d6fd503e017f",
750 | "name" : "phone",
751 | "description" : "OpenID Connect built-in scope: phone",
752 | "protocol" : "openid-connect",
753 | "attributes" : {
754 | "consent.screen.text" : "${phoneScopeConsentText}",
755 | "display.on.consent.screen" : "true"
756 | },
757 | "protocolMappers" : [ {
758 | "id" : "b9814882-f42d-4c25-92c8-53d9b6f8e031",
759 | "name" : "phone number verified",
760 | "protocol" : "openid-connect",
761 | "protocolMapper" : "oidc-usermodel-attribute-mapper",
762 | "consentRequired" : false,
763 | "config" : {
764 | "userinfo.token.claim" : "true",
765 | "user.attribute" : "phoneNumberVerified",
766 | "id.token.claim" : "true",
767 | "access.token.claim" : "true",
768 | "claim.name" : "phone_number_verified",
769 | "jsonType.label" : "boolean"
770 | }
771 | }, {
772 | "id" : "058ef5e4-698c-40e7-ac7f-8ab20edb0b6c",
773 | "name" : "phone number",
774 | "protocol" : "openid-connect",
775 | "protocolMapper" : "oidc-usermodel-attribute-mapper",
776 | "consentRequired" : false,
777 | "config" : {
778 | "userinfo.token.claim" : "true",
779 | "user.attribute" : "phoneNumber",
780 | "id.token.claim" : "true",
781 | "access.token.claim" : "true",
782 | "claim.name" : "phone_number",
783 | "jsonType.label" : "String"
784 | }
785 | } ]
786 | } ],
787 | "defaultDefaultClientScopes" : [ "role_list", "profile", "email" ],
788 | "defaultOptionalClientScopes" : [ "offline_access", "address", "phone" ],
789 | "browserSecurityHeaders" : {
790 | "xContentTypeOptions" : "nosniff",
791 | "xRobotsTag" : "none",
792 | "xFrameOptions" : "SAMEORIGIN",
793 | "xXSSProtection" : "1; mode=block",
794 | "contentSecurityPolicy" : "frame-src 'self'; frame-ancestors 'self'; object-src 'none';",
795 | "strictTransportSecurity" : "max-age=31536000; includeSubDomains"
796 | },
797 | "smtpServer" : { },
798 | "eventsEnabled" : false,
799 | "eventsListeners" : [ "jboss-logging" ],
800 | "enabledEventTypes" : [ ],
801 | "adminEventsEnabled" : false,
802 | "adminEventsDetailsEnabled" : false,
803 | "components" : {
804 | "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy" : [ {
805 | "id" : "9ed2a7d8-6222-4035-aa72-939034d70ec7",
806 | "name" : "Allowed Client Scopes",
807 | "providerId" : "allowed-client-templates",
808 | "subType" : "authenticated",
809 | "subComponents" : { },
810 | "config" : {
811 | "allow-default-scopes" : [ "true" ]
812 | }
813 | }, {
814 | "id" : "2af3bafd-c4c5-46cf-b3d2-ab011d94b699",
815 | "name" : "Trusted Hosts",
816 | "providerId" : "trusted-hosts",
817 | "subType" : "anonymous",
818 | "subComponents" : { },
819 | "config" : {
820 | "host-sending-registration-request-must-match" : [ "true" ],
821 | "client-uris-must-match" : [ "true" ]
822 | }
823 | }, {
824 | "id" : "b045a99f-467c-4ff9-9b87-aaf6c6fb5b0f",
825 | "name" : "Full Scope Disabled",
826 | "providerId" : "scope",
827 | "subType" : "anonymous",
828 | "subComponents" : { },
829 | "config" : { }
830 | }, {
831 | "id" : "11d6c898-835a-479f-9f45-fbf44d2735e2",
832 | "name" : "Allowed Protocol Mapper Types",
833 | "providerId" : "allowed-protocol-mappers",
834 | "subType" : "authenticated",
835 | "subComponents" : { },
836 | "config" : {
837 | "allowed-protocol-mapper-types" : [ "oidc-usermodel-attribute-mapper", "oidc-sha256-pairwise-sub-mapper", "saml-role-list-mapper", "saml-user-property-mapper", "saml-user-attribute-mapper", "oidc-address-mapper", "oidc-usermodel-property-mapper", "oidc-full-name-mapper" ]
838 | }
839 | }, {
840 | "id" : "145d2faa-e533-4601-88aa-2fea7e0ba2b1",
841 | "name" : "Allowed Protocol Mapper Types",
842 | "providerId" : "allowed-protocol-mappers",
843 | "subType" : "anonymous",
844 | "subComponents" : { },
845 | "config" : {
846 | "allowed-protocol-mapper-types" : [ "oidc-usermodel-property-mapper", "saml-user-property-mapper", "oidc-usermodel-attribute-mapper", "oidc-sha256-pairwise-sub-mapper", "saml-role-list-mapper", "saml-user-attribute-mapper", "oidc-full-name-mapper", "oidc-address-mapper" ]
847 | }
848 | }, {
849 | "id" : "e79f1e93-d630-4329-b9d6-f0a09cf64311",
850 | "name" : "Max Clients Limit",
851 | "providerId" : "max-clients",
852 | "subType" : "anonymous",
853 | "subComponents" : { },
854 | "config" : {
855 | "max-clients" : [ "200" ]
856 | }
857 | }, {
858 | "id" : "a185eed3-2eb9-48cc-a316-84ab9009affd",
859 | "name" : "Allowed Client Scopes",
860 | "providerId" : "allowed-client-templates",
861 | "subType" : "anonymous",
862 | "subComponents" : { },
863 | "config" : {
864 | "allow-default-scopes" : [ "true" ]
865 | }
866 | }, {
867 | "id" : "06fc217f-2339-428a-88ce-9a9addca99c8",
868 | "name" : "Consent Required",
869 | "providerId" : "consent-required",
870 | "subType" : "anonymous",
871 | "subComponents" : { },
872 | "config" : { }
873 | } ],
874 | "org.keycloak.keys.KeyProvider" : [ {
875 | "id" : "660d172e-2602-4c60-8a4e-dda577889ea6",
876 | "name" : "hmac-generated",
877 | "providerId" : "hmac-generated",
878 | "subComponents" : { },
879 | "config" : {
880 | "kid" : [ "9e5a2be1-41cf-451c-9e74-e96b24945d41" ],
881 | "secret" : [ "QlJz9cfoUP2kOWfjZmIW41l4exXIylpQJIC-Rue8j8g" ],
882 | "priority" : [ "100" ]
883 | }
884 | }, {
885 | "id" : "69972cdf-bb31-43ea-bfa9-8091edcc2669",
886 | "name" : "aes-generated",
887 | "providerId" : "aes-generated",
888 | "subComponents" : { },
889 | "config" : {
890 | "kid" : [ "e790563c-82a4-4990-baa7-412e01c019cc" ],
891 | "secret" : [ "iDOwuVebs_SrcZfWddo3iw" ],
892 | "priority" : [ "100" ]
893 | }
894 | }, {
895 | "id" : "a098753f-1121-4cfe-956f-f483cb741603",
896 | "name" : "rsa-generated",
897 | "providerId" : "rsa-generated",
898 | "subComponents" : { },
899 | "config" : {
900 | "privateKey" : [ "MIIEogIBAAKCAQEAigava4XHe0clhOr4FV+DY9vusim5ErvpIwRcIWYWuzTCmSx/RyfIxe/meupyTSp1/cgRd06V0zHUbAtxNJ5m4ShLOmGP2dwEl+SqOT/QFG4kU/2zQFvj+6+38HimMeBU0S2VJPo70drj0O7OpMSOarxy5AMGj8eMZz+vRkOS94Ma1dL78p8DMeRYVhcm19Vx59baWBvMW7kNymrDPfgrzZsPkEkPg+IOXl1AQ4ziIa9xI38J2Z+C+J8t+yoPO7/kAbvwQIpJU+v5CjrObu15I7PMzxthc+ZIvWhhI8W+vytCCvVQXkLbtnJSYjz3eFhqcIF66TEGrjDumFZOG5fVwQIDAQABAoIBAFPohoHmHQP7l3p7YX+UxgpR7IUQyjryU2N/RgbjyhPamiaGH4YBUJPMKKA2oG/6zSoPk1alRn3SgCGCvzpOxZpBZaJDJzE5CO3SDA2rlnKlFp6cz3jjo/AgvcCJh/cwOj/D5zRIj08fM3mTg7o056NJlsq4cCe+FsO5unMLp2+hrHfSeW3+wyeRhUlGRSgk5VdvZnk2Z4Of92RpoT9bIMDW3m6aCwadeJkIHkVIyAy+T1yIj5CrHQegcQxLn5jFyOknJj2UPgGyEg5LUQvFZEoWgpg/wqHiZdccrP6AKBQy/O/xqG47fwPByJHLmK4ybjvp/XxNBZ+KUynTvQlLscECgYEA/JmXDkIjS0CLcHf1WBj0SmJLiVy5rNIN5s3v9Gh2f9s6dJ7tgDudHMA2dkfKOezsetdF2kesPFN+xhxkIo7ao0PpwplLnVIxhTO3W79xODZp+BYXTIIl2istPX5Q8+LlCMZlTipXRDYAXk9NSi3oEthhdM6StK64qjD73fXg4CkCgYEAi+JL0TVXzH1RI2A+5lF6V7Rk/RLEQX156csbECme8huEH7eYbMDubdBX3ywbFvJqYQBU8Yr7C99M55rw2Qr04cDLr544YksYPCBLqmnk2SNzWTF3hHY/BFCv6pYcblsnEmGBemFjTE1P3SMyvmCrpas1H2zXw9/KziC3ygpZm9kCgYAH4suieFIdwVAZHMWeEHlf8R2mlix9xrkEYZ2CJdi9ORzkEyoa/MF06lNI8gjQMiNX2myl2eL4pyqoCK7fnVIaEr6zgpGnwa8mF208AggI1zoLsrTbgJyp6Psqlkz0sDqyQW9cN1ouGPl9+D/Tdwdtvy+bs+9EkMfXGFxkm45/sQKBgFLA/p920kk8ferSvoNdAmauZuw81PP1elEwggMuzERouOJWqAr2nFdE4Sc7HY+WvA5Etvvqf5hHc2S1CfUtATAo8ZckoDCuQlkXtgvL98Hpsgy7MfygQ6mW3muGgK1cqaG7I3E1+huixTOK5jMwV3t77MJ5jq/nTkBhpLkXJGoJAoGAJk0uIgJfFcuYUSyhKvKyniHGQ4KFR2vTiiiwXqHfrmhzrTkok+8iR2Vq4ST8Hzkamm3GpIsBw807WP0XCsnPDdXu/k0vJ9TyH95KGIWCZApp2XXq1uHvGfF+0kaOFVf8QYqHNsxwm9yytpsNX3ExGxCt4WwY/RYpHrpzL6Ftw1M=" ],
901 | "certificate" : [ "MIICpTCCAY0CBgFkADdOLzANBgkqhkiG9w0BAQsFADAWMRQwEgYDVQQDDAtQZXJzb25SZWFsbTAeFw0xODA2MTQyMTMxMjFaFw0yODA2MTQyMTMzMDFaMBYxFDASBgNVBAMMC1BlcnNvblJlYWxtMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAigava4XHe0clhOr4FV+DY9vusim5ErvpIwRcIWYWuzTCmSx/RyfIxe/meupyTSp1/cgRd06V0zHUbAtxNJ5m4ShLOmGP2dwEl+SqOT/QFG4kU/2zQFvj+6+38HimMeBU0S2VJPo70drj0O7OpMSOarxy5AMGj8eMZz+vRkOS94Ma1dL78p8DMeRYVhcm19Vx59baWBvMW7kNymrDPfgrzZsPkEkPg+IOXl1AQ4ziIa9xI38J2Z+C+J8t+yoPO7/kAbvwQIpJU+v5CjrObu15I7PMzxthc+ZIvWhhI8W+vytCCvVQXkLbtnJSYjz3eFhqcIF66TEGrjDumFZOG5fVwQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQB/txYzi8urNj9XjpEiXj6z7m2P9CzDAU9fs5X81p6cdt+UeVwJG2bQpbr+uuMN3HVkYlcBSbkDtanc3WGyER/p90sqBLd+wJl7k16LDMawU+FypSFwm7ZQT8Cp+yeYzyS0QvFHrKgZeZZJoIDtyuZOYzLVHDE0vEe0qPMAU6R99xAbIOJs+aqNM9YWVA7eBD0EMncozmXCZ3Prbln+uth38h2WwsK1X4lylGB08vleXMOtKaAgIB9RlCjDWiMbjQNQiNwU761AvCmP42LxPwBZy7fDVl7UhtOCGTwHKwp0egtA0ohKMlAJ0uULgAASVay5u9gYUUFOLAJqvzsRvLaM" ],
902 | "priority" : [ "100" ]
903 | }
904 | } ]
905 | },
906 | "internationalizationEnabled" : false,
907 | "supportedLocales" : [ ],
908 | "authenticationFlows" : [ {
909 | "id" : "99ed1d67-28d3-49a3-823f-c1c8d8eb5d4f",
910 | "alias" : "Handle Existing Account",
911 | "description" : "Handle what to do if there is existing account with same email/username like authenticated identity provider",
912 | "providerId" : "basic-flow",
913 | "topLevel" : false,
914 | "builtIn" : true,
915 | "authenticationExecutions" : [ {
916 | "authenticator" : "idp-confirm-link",
917 | "requirement" : "REQUIRED",
918 | "priority" : 10,
919 | "userSetupAllowed" : false,
920 | "autheticatorFlow" : false
921 | }, {
922 | "authenticator" : "idp-email-verification",
923 | "requirement" : "ALTERNATIVE",
924 | "priority" : 20,
925 | "userSetupAllowed" : false,
926 | "autheticatorFlow" : false
927 | }, {
928 | "requirement" : "ALTERNATIVE",
929 | "priority" : 30,
930 | "flowAlias" : "Verify Existing Account by Re-authentication",
931 | "userSetupAllowed" : false,
932 | "autheticatorFlow" : true
933 | } ]
934 | }, {
935 | "id" : "5237f9d3-c505-48d7-b2b5-4ba5845b7981",
936 | "alias" : "Verify Existing Account by Re-authentication",
937 | "description" : "Reauthentication of existing account",
938 | "providerId" : "basic-flow",
939 | "topLevel" : false,
940 | "builtIn" : true,
941 | "authenticationExecutions" : [ {
942 | "authenticator" : "idp-username-password-form",
943 | "requirement" : "REQUIRED",
944 | "priority" : 10,
945 | "userSetupAllowed" : false,
946 | "autheticatorFlow" : false
947 | }, {
948 | "authenticator" : "auth-otp-form",
949 | "requirement" : "OPTIONAL",
950 | "priority" : 20,
951 | "userSetupAllowed" : false,
952 | "autheticatorFlow" : false
953 | } ]
954 | }, {
955 | "id" : "9d1402bf-5dc2-4de2-9aed-d97c4ba0ef5e",
956 | "alias" : "browser",
957 | "description" : "browser based authentication",
958 | "providerId" : "basic-flow",
959 | "topLevel" : true,
960 | "builtIn" : true,
961 | "authenticationExecutions" : [ {
962 | "authenticator" : "auth-cookie",
963 | "requirement" : "ALTERNATIVE",
964 | "priority" : 10,
965 | "userSetupAllowed" : false,
966 | "autheticatorFlow" : false
967 | }, {
968 | "authenticator" : "auth-spnego",
969 | "requirement" : "DISABLED",
970 | "priority" : 20,
971 | "userSetupAllowed" : false,
972 | "autheticatorFlow" : false
973 | }, {
974 | "authenticator" : "identity-provider-redirector",
975 | "requirement" : "ALTERNATIVE",
976 | "priority" : 25,
977 | "userSetupAllowed" : false,
978 | "autheticatorFlow" : false
979 | }, {
980 | "requirement" : "ALTERNATIVE",
981 | "priority" : 30,
982 | "flowAlias" : "forms",
983 | "userSetupAllowed" : false,
984 | "autheticatorFlow" : true
985 | } ]
986 | }, {
987 | "id" : "b498dc60-21bb-471d-a757-1ac99aae0c20",
988 | "alias" : "clients",
989 | "description" : "Base authentication for clients",
990 | "providerId" : "client-flow",
991 | "topLevel" : true,
992 | "builtIn" : true,
993 | "authenticationExecutions" : [ {
994 | "authenticator" : "client-secret",
995 | "requirement" : "ALTERNATIVE",
996 | "priority" : 10,
997 | "userSetupAllowed" : false,
998 | "autheticatorFlow" : false
999 | }, {
1000 | "authenticator" : "client-jwt",
1001 | "requirement" : "ALTERNATIVE",
1002 | "priority" : 20,
1003 | "userSetupAllowed" : false,
1004 | "autheticatorFlow" : false
1005 | }, {
1006 | "authenticator" : "client-secret-jwt",
1007 | "requirement" : "ALTERNATIVE",
1008 | "priority" : 30,
1009 | "userSetupAllowed" : false,
1010 | "autheticatorFlow" : false
1011 | } ]
1012 | }, {
1013 | "id" : "cb77f85f-12b2-44d2-bf10-1c35a61b97b6",
1014 | "alias" : "direct grant",
1015 | "description" : "OpenID Connect Resource Owner Grant",
1016 | "providerId" : "basic-flow",
1017 | "topLevel" : true,
1018 | "builtIn" : true,
1019 | "authenticationExecutions" : [ {
1020 | "authenticator" : "direct-grant-validate-username",
1021 | "requirement" : "REQUIRED",
1022 | "priority" : 10,
1023 | "userSetupAllowed" : false,
1024 | "autheticatorFlow" : false
1025 | }, {
1026 | "authenticator" : "direct-grant-validate-password",
1027 | "requirement" : "REQUIRED",
1028 | "priority" : 20,
1029 | "userSetupAllowed" : false,
1030 | "autheticatorFlow" : false
1031 | }, {
1032 | "authenticator" : "direct-grant-validate-otp",
1033 | "requirement" : "OPTIONAL",
1034 | "priority" : 30,
1035 | "userSetupAllowed" : false,
1036 | "autheticatorFlow" : false
1037 | } ]
1038 | }, {
1039 | "id" : "316f698b-f622-415b-a2b5-a3eedc7e64a9",
1040 | "alias" : "docker auth",
1041 | "description" : "Used by Docker clients to authenticate against the IDP",
1042 | "providerId" : "basic-flow",
1043 | "topLevel" : true,
1044 | "builtIn" : true,
1045 | "authenticationExecutions" : [ {
1046 | "authenticator" : "docker-http-basic-authenticator",
1047 | "requirement" : "REQUIRED",
1048 | "priority" : 10,
1049 | "userSetupAllowed" : false,
1050 | "autheticatorFlow" : false
1051 | } ]
1052 | }, {
1053 | "id" : "d1201cb0-c1e6-4ffe-a9c9-62bbacb81841",
1054 | "alias" : "first broker login",
1055 | "description" : "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account",
1056 | "providerId" : "basic-flow",
1057 | "topLevel" : true,
1058 | "builtIn" : true,
1059 | "authenticationExecutions" : [ {
1060 | "authenticatorConfig" : "review profile config",
1061 | "authenticator" : "idp-review-profile",
1062 | "requirement" : "REQUIRED",
1063 | "priority" : 10,
1064 | "userSetupAllowed" : false,
1065 | "autheticatorFlow" : false
1066 | }, {
1067 | "authenticatorConfig" : "create unique user config",
1068 | "authenticator" : "idp-create-user-if-unique",
1069 | "requirement" : "ALTERNATIVE",
1070 | "priority" : 20,
1071 | "userSetupAllowed" : false,
1072 | "autheticatorFlow" : false
1073 | }, {
1074 | "requirement" : "ALTERNATIVE",
1075 | "priority" : 30,
1076 | "flowAlias" : "Handle Existing Account",
1077 | "userSetupAllowed" : false,
1078 | "autheticatorFlow" : true
1079 | } ]
1080 | }, {
1081 | "id" : "90436c35-2dd0-4630-a7a8-c37ee59ccfef",
1082 | "alias" : "forms",
1083 | "description" : "Username, password, otp and other auth forms.",
1084 | "providerId" : "basic-flow",
1085 | "topLevel" : false,
1086 | "builtIn" : true,
1087 | "authenticationExecutions" : [ {
1088 | "authenticator" : "auth-username-password-form",
1089 | "requirement" : "REQUIRED",
1090 | "priority" : 10,
1091 | "userSetupAllowed" : false,
1092 | "autheticatorFlow" : false
1093 | }, {
1094 | "authenticator" : "auth-otp-form",
1095 | "requirement" : "OPTIONAL",
1096 | "priority" : 20,
1097 | "userSetupAllowed" : false,
1098 | "autheticatorFlow" : false
1099 | } ]
1100 | }, {
1101 | "id" : "09f41d31-78e1-413e-98d8-67a7b4d711c4",
1102 | "alias" : "registration",
1103 | "description" : "registration flow",
1104 | "providerId" : "basic-flow",
1105 | "topLevel" : true,
1106 | "builtIn" : true,
1107 | "authenticationExecutions" : [ {
1108 | "authenticator" : "registration-page-form",
1109 | "requirement" : "REQUIRED",
1110 | "priority" : 10,
1111 | "flowAlias" : "registration form",
1112 | "userSetupAllowed" : false,
1113 | "autheticatorFlow" : true
1114 | } ]
1115 | }, {
1116 | "id" : "9f4e77bc-8220-4d03-95f2-ab378213adee",
1117 | "alias" : "registration form",
1118 | "description" : "registration form",
1119 | "providerId" : "form-flow",
1120 | "topLevel" : false,
1121 | "builtIn" : true,
1122 | "authenticationExecutions" : [ {
1123 | "authenticator" : "registration-user-creation",
1124 | "requirement" : "REQUIRED",
1125 | "priority" : 20,
1126 | "userSetupAllowed" : false,
1127 | "autheticatorFlow" : false
1128 | }, {
1129 | "authenticator" : "registration-profile-action",
1130 | "requirement" : "REQUIRED",
1131 | "priority" : 40,
1132 | "userSetupAllowed" : false,
1133 | "autheticatorFlow" : false
1134 | }, {
1135 | "authenticator" : "registration-password-action",
1136 | "requirement" : "REQUIRED",
1137 | "priority" : 50,
1138 | "userSetupAllowed" : false,
1139 | "autheticatorFlow" : false
1140 | }, {
1141 | "authenticator" : "registration-recaptcha-action",
1142 | "requirement" : "DISABLED",
1143 | "priority" : 60,
1144 | "userSetupAllowed" : false,
1145 | "autheticatorFlow" : false
1146 | } ]
1147 | }, {
1148 | "id" : "ab6a2908-4541-4bf6-a665-9d169a3bfc15",
1149 | "alias" : "reset credentials",
1150 | "description" : "Reset credentials for a user if they forgot their password or something",
1151 | "providerId" : "basic-flow",
1152 | "topLevel" : true,
1153 | "builtIn" : true,
1154 | "authenticationExecutions" : [ {
1155 | "authenticator" : "reset-credentials-choose-user",
1156 | "requirement" : "REQUIRED",
1157 | "priority" : 10,
1158 | "userSetupAllowed" : false,
1159 | "autheticatorFlow" : false
1160 | }, {
1161 | "authenticator" : "reset-credential-email",
1162 | "requirement" : "REQUIRED",
1163 | "priority" : 20,
1164 | "userSetupAllowed" : false,
1165 | "autheticatorFlow" : false
1166 | }, {
1167 | "authenticator" : "reset-password",
1168 | "requirement" : "REQUIRED",
1169 | "priority" : 30,
1170 | "userSetupAllowed" : false,
1171 | "autheticatorFlow" : false
1172 | }, {
1173 | "authenticator" : "reset-otp",
1174 | "requirement" : "OPTIONAL",
1175 | "priority" : 40,
1176 | "userSetupAllowed" : false,
1177 | "autheticatorFlow" : false
1178 | } ]
1179 | }, {
1180 | "id" : "3d43bb68-5329-41e9-8844-98d41f36fdad",
1181 | "alias" : "saml ecp",
1182 | "description" : "SAML ECP Profile Authentication Flow",
1183 | "providerId" : "basic-flow",
1184 | "topLevel" : true,
1185 | "builtIn" : true,
1186 | "authenticationExecutions" : [ {
1187 | "authenticator" : "http-basic-authenticator",
1188 | "requirement" : "REQUIRED",
1189 | "priority" : 10,
1190 | "userSetupAllowed" : false,
1191 | "autheticatorFlow" : false
1192 | } ]
1193 | } ],
1194 | "authenticatorConfig" : [ {
1195 | "id" : "6089728e-fb33-4485-8452-a29020d52c41",
1196 | "alias" : "create unique user config",
1197 | "config" : {
1198 | "require.password.update.after.registration" : "false"
1199 | }
1200 | }, {
1201 | "id" : "918eabe4-8722-426b-b181-18b9e8592494",
1202 | "alias" : "review profile config",
1203 | "config" : {
1204 | "update.profile.on.first.login" : "missing"
1205 | }
1206 | } ],
1207 | "requiredActions" : [ {
1208 | "alias" : "CONFIGURE_TOTP",
1209 | "name" : "Configure OTP",
1210 | "providerId" : "CONFIGURE_TOTP",
1211 | "enabled" : true,
1212 | "defaultAction" : false,
1213 | "config" : { }
1214 | }, {
1215 | "alias" : "UPDATE_PASSWORD",
1216 | "name" : "Update Password",
1217 | "providerId" : "UPDATE_PASSWORD",
1218 | "enabled" : true,
1219 | "defaultAction" : false,
1220 | "config" : { }
1221 | }, {
1222 | "alias" : "UPDATE_PROFILE",
1223 | "name" : "Update Profile",
1224 | "providerId" : "UPDATE_PROFILE",
1225 | "enabled" : true,
1226 | "defaultAction" : false,
1227 | "config" : { }
1228 | }, {
1229 | "alias" : "VERIFY_EMAIL",
1230 | "name" : "Verify Email",
1231 | "providerId" : "VERIFY_EMAIL",
1232 | "enabled" : true,
1233 | "defaultAction" : false,
1234 | "config" : { }
1235 | }, {
1236 | "alias" : "terms_and_conditions",
1237 | "name" : "Terms and Conditions",
1238 | "providerId" : "terms_and_conditions",
1239 | "enabled" : false,
1240 | "defaultAction" : false,
1241 | "config" : { }
1242 | } ],
1243 | "browserFlow" : "browser",
1244 | "registrationFlow" : "registration",
1245 | "directGrantFlow" : "direct grant",
1246 | "resetCredentialsFlow" : "reset credentials",
1247 | "clientAuthenticationFlow" : "clients",
1248 | "dockerAuthenticationFlow" : "docker auth",
1249 | "attributes" : {
1250 | "_browser_header.xXSSProtection" : "1; mode=block",
1251 | "_browser_header.strictTransportSecurity" : "max-age=31536000; includeSubDomains",
1252 | "_browser_header.xFrameOptions" : "SAMEORIGIN",
1253 | "quickLoginCheckMilliSeconds" : "1000",
1254 | "permanentLockout" : "false",
1255 | "_browser_header.xRobotsTag" : "none",
1256 | "maxFailureWaitSeconds" : "900",
1257 | "minimumQuickLoginWaitSeconds" : "60",
1258 | "failureFactor" : "30",
1259 | "actionTokenGeneratedByUserLifespan" : "300",
1260 | "maxDeltaTimeSeconds" : "43200",
1261 | "_browser_header.xContentTypeOptions" : "nosniff",
1262 | "actionTokenGeneratedByAdminLifespan" : "43200",
1263 | "bruteForceProtected" : "false",
1264 | "_browser_header.contentSecurityPolicy" : "frame-src 'self'; frame-ancestors 'self'; object-src 'none';",
1265 | "waitIncrementSeconds" : "60"
1266 | },
1267 | "keycloakVersion" : "4.0.0.Final",
1268 | "userManagedAccessAllowed" : false
1269 | }
--------------------------------------------------------------------------------
/keycloak_4_spring_boot_2/keycloak/config/PersonRealm-users-0.json:
--------------------------------------------------------------------------------
1 | {
2 | "realm" : "PersonRealm",
3 | "users" : [ {
4 | "id" : "bc68a03e-4c6e-47bc-8409-9b973e4b78e0",
5 | "createdTimestamp" : 1529012775558,
6 | "username" : "username",
7 | "enabled" : true,
8 | "totp" : false,
9 | "emailVerified" : false,
10 | "credentials" : [ {
11 | "type" : "password",
12 | "hashedSaltedValue" : "9DaXQqtjc+BXofTxzNy8I7kn9pX1Fgwa1z6hJzYBDHVL6TE8hLwNPg/rj9PoP6n4VSjA1xSlsxePmubEarXAdA==",
13 | "salt" : "LVYQP+OtLcJUC2Abc/nP6A==",
14 | "hashIterations" : 27500,
15 | "counter" : 0,
16 | "algorithm" : "pbkdf2-sha256",
17 | "digits" : 0,
18 | "period" : 0,
19 | "createdDate" : 1529012789604,
20 | "config" : { }
21 | } ],
22 | "disableableCredentialTypes" : [ "password" ],
23 | "requiredActions" : [],
24 | "realmRoles" : [ "uma_authorization", "offline_access", "user" ],
25 | "clientRoles" : {
26 | "account" : [ "view-profile", "manage-account" ]
27 | },
28 | "notBefore" : 0,
29 | "groups" : [ ]
30 | } ]
31 | }
--------------------------------------------------------------------------------
/keycloak_4_spring_boot_2/keycloak/config/master-realm.json:
--------------------------------------------------------------------------------
1 | {
2 | "id" : "master",
3 | "realm" : "master",
4 | "displayName" : "Keycloak",
5 | "displayNameHtml" : "Keycloak
",
6 | "notBefore" : 0,
7 | "revokeRefreshToken" : false,
8 | "refreshTokenMaxReuse" : 0,
9 | "accessTokenLifespan" : 60,
10 | "accessTokenLifespanForImplicitFlow" : 900,
11 | "ssoSessionIdleTimeout" : 1800,
12 | "ssoSessionMaxLifespan" : 36000,
13 | "offlineSessionIdleTimeout" : 2592000,
14 | "accessCodeLifespan" : 60,
15 | "accessCodeLifespanUserAction" : 300,
16 | "accessCodeLifespanLogin" : 1800,
17 | "actionTokenGeneratedByAdminLifespan" : 43200,
18 | "actionTokenGeneratedByUserLifespan" : 300,
19 | "enabled" : true,
20 | "sslRequired" : "external",
21 | "registrationAllowed" : false,
22 | "registrationEmailAsUsername" : false,
23 | "rememberMe" : false,
24 | "verifyEmail" : false,
25 | "loginWithEmailAllowed" : true,
26 | "duplicateEmailsAllowed" : false,
27 | "resetPasswordAllowed" : false,
28 | "editUsernameAllowed" : false,
29 | "bruteForceProtected" : false,
30 | "permanentLockout" : false,
31 | "maxFailureWaitSeconds" : 900,
32 | "minimumQuickLoginWaitSeconds" : 60,
33 | "waitIncrementSeconds" : 60,
34 | "quickLoginCheckMilliSeconds" : 1000,
35 | "maxDeltaTimeSeconds" : 43200,
36 | "failureFactor" : 30,
37 | "roles" : {
38 | "realm" : [ {
39 | "id" : "f6df0ecb-6001-401b-aa1c-a66fc0435d5a",
40 | "name" : "admin",
41 | "description" : "${role_admin}",
42 | "composite" : true,
43 | "composites" : {
44 | "realm" : [ "create-realm" ],
45 | "client" : {
46 | "PersonRealm-realm" : [ "view-realm", "manage-realm", "view-events", "query-groups", "create-client", "query-clients", "query-realms", "manage-events", "view-authorization", "manage-authorization", "view-clients", "manage-clients", "manage-identity-providers", "view-users", "impersonation", "query-users", "manage-users", "view-identity-providers" ],
47 | "master-realm" : [ "manage-users", "view-events", "view-authorization", "query-groups", "view-clients", "view-users", "query-realms", "manage-events", "query-clients", "query-users", "impersonation", "manage-clients", "view-realm", "create-client", "manage-realm", "view-identity-providers", "manage-identity-providers", "manage-authorization" ]
48 | }
49 | },
50 | "clientRole" : false,
51 | "containerId" : "master"
52 | }, {
53 | "id" : "30cceaad-d831-4739-8b8b-2fab441846e8",
54 | "name" : "create-realm",
55 | "description" : "${role_create-realm}",
56 | "composite" : false,
57 | "clientRole" : false,
58 | "containerId" : "master"
59 | }, {
60 | "id" : "7e9e45b6-5da0-420b-a3e9-f02c64ed0641",
61 | "name" : "offline_access",
62 | "description" : "${role_offline-access}",
63 | "composite" : false,
64 | "clientRole" : false,
65 | "containerId" : "master"
66 | }, {
67 | "id" : "75ba68c4-bd9a-41bf-83eb-c9fd92643482",
68 | "name" : "uma_authorization",
69 | "description" : "${role_uma_authorization}",
70 | "composite" : false,
71 | "clientRole" : false,
72 | "containerId" : "master"
73 | } ],
74 | "client" : {
75 | "PersonRealm-realm" : [ {
76 | "id" : "f7b4da1c-5d59-486f-8a0e-33158721417a",
77 | "name" : "view-authorization",
78 | "description" : "${role_view-authorization}",
79 | "composite" : false,
80 | "clientRole" : true,
81 | "containerId" : "7b932c60-7f2e-4537-91f8-8b64bd4a07cd"
82 | }, {
83 | "id" : "36e19d18-69bb-4a67-9edb-ffa8a1db1dbd",
84 | "name" : "manage-authorization",
85 | "description" : "${role_manage-authorization}",
86 | "composite" : false,
87 | "clientRole" : true,
88 | "containerId" : "7b932c60-7f2e-4537-91f8-8b64bd4a07cd"
89 | }, {
90 | "id" : "fc86107c-cad3-41ac-9500-ad3fc3515785",
91 | "name" : "view-realm",
92 | "description" : "${role_view-realm}",
93 | "composite" : false,
94 | "clientRole" : true,
95 | "containerId" : "7b932c60-7f2e-4537-91f8-8b64bd4a07cd"
96 | }, {
97 | "id" : "b4357313-17c7-47f2-bee9-d9c7aa2a813d",
98 | "name" : "view-clients",
99 | "description" : "${role_view-clients}",
100 | "composite" : true,
101 | "composites" : {
102 | "client" : {
103 | "PersonRealm-realm" : [ "query-clients" ]
104 | }
105 | },
106 | "clientRole" : true,
107 | "containerId" : "7b932c60-7f2e-4537-91f8-8b64bd4a07cd"
108 | }, {
109 | "id" : "4fdc558e-17fd-4ae0-ac63-25505f75f3ea",
110 | "name" : "manage-clients",
111 | "description" : "${role_manage-clients}",
112 | "composite" : false,
113 | "clientRole" : true,
114 | "containerId" : "7b932c60-7f2e-4537-91f8-8b64bd4a07cd"
115 | }, {
116 | "id" : "684da6c6-42e7-4651-ac1a-d87be8e389b4",
117 | "name" : "manage-realm",
118 | "description" : "${role_manage-realm}",
119 | "composite" : false,
120 | "clientRole" : true,
121 | "containerId" : "7b932c60-7f2e-4537-91f8-8b64bd4a07cd"
122 | }, {
123 | "id" : "052e85c4-6c93-427b-adf3-175a97f2862d",
124 | "name" : "view-events",
125 | "description" : "${role_view-events}",
126 | "composite" : false,
127 | "clientRole" : true,
128 | "containerId" : "7b932c60-7f2e-4537-91f8-8b64bd4a07cd"
129 | }, {
130 | "id" : "6999fbeb-b6b5-41ae-982f-9fdf6ec3440b",
131 | "name" : "query-groups",
132 | "description" : "${role_query-groups}",
133 | "composite" : false,
134 | "clientRole" : true,
135 | "containerId" : "7b932c60-7f2e-4537-91f8-8b64bd4a07cd"
136 | }, {
137 | "id" : "2cf64307-03a7-4ec8-8a68-377c96941f14",
138 | "name" : "manage-identity-providers",
139 | "description" : "${role_manage-identity-providers}",
140 | "composite" : false,
141 | "clientRole" : true,
142 | "containerId" : "7b932c60-7f2e-4537-91f8-8b64bd4a07cd"
143 | }, {
144 | "id" : "fd3f2065-4aae-423e-81b1-841970230c9d",
145 | "name" : "create-client",
146 | "description" : "${role_create-client}",
147 | "composite" : false,
148 | "clientRole" : true,
149 | "containerId" : "7b932c60-7f2e-4537-91f8-8b64bd4a07cd"
150 | }, {
151 | "id" : "847bdf78-3339-4c87-a60c-2552bc670dc1",
152 | "name" : "query-clients",
153 | "description" : "${role_query-clients}",
154 | "composite" : false,
155 | "clientRole" : true,
156 | "containerId" : "7b932c60-7f2e-4537-91f8-8b64bd4a07cd"
157 | }, {
158 | "id" : "6cd127e2-5d73-4362-9185-5b6cc202ce96",
159 | "name" : "view-users",
160 | "description" : "${role_view-users}",
161 | "composite" : true,
162 | "composites" : {
163 | "client" : {
164 | "PersonRealm-realm" : [ "query-users", "query-groups" ]
165 | }
166 | },
167 | "clientRole" : true,
168 | "containerId" : "7b932c60-7f2e-4537-91f8-8b64bd4a07cd"
169 | }, {
170 | "id" : "aa5300a5-951e-434a-ac34-bfc08ecca837",
171 | "name" : "query-realms",
172 | "description" : "${role_query-realms}",
173 | "composite" : false,
174 | "clientRole" : true,
175 | "containerId" : "7b932c60-7f2e-4537-91f8-8b64bd4a07cd"
176 | }, {
177 | "id" : "ea1602f8-747e-4fe3-8ec4-87ad09b7c618",
178 | "name" : "impersonation",
179 | "description" : "${role_impersonation}",
180 | "composite" : false,
181 | "clientRole" : true,
182 | "containerId" : "7b932c60-7f2e-4537-91f8-8b64bd4a07cd"
183 | }, {
184 | "id" : "b634a11d-7ec7-4140-b35b-ddf1da4e3d9f",
185 | "name" : "query-users",
186 | "description" : "${role_query-users}",
187 | "composite" : false,
188 | "clientRole" : true,
189 | "containerId" : "7b932c60-7f2e-4537-91f8-8b64bd4a07cd"
190 | }, {
191 | "id" : "37398f2d-aab8-41e9-9199-6e324030697c",
192 | "name" : "manage-users",
193 | "description" : "${role_manage-users}",
194 | "composite" : false,
195 | "clientRole" : true,
196 | "containerId" : "7b932c60-7f2e-4537-91f8-8b64bd4a07cd"
197 | }, {
198 | "id" : "f75f92c9-b52b-4f06-902d-b8feff6a13ee",
199 | "name" : "view-identity-providers",
200 | "description" : "${role_view-identity-providers}",
201 | "composite" : false,
202 | "clientRole" : true,
203 | "containerId" : "7b932c60-7f2e-4537-91f8-8b64bd4a07cd"
204 | }, {
205 | "id" : "adf091c2-e7df-4df2-8087-cb15aca2efc3",
206 | "name" : "manage-events",
207 | "description" : "${role_manage-events}",
208 | "composite" : false,
209 | "clientRole" : true,
210 | "containerId" : "7b932c60-7f2e-4537-91f8-8b64bd4a07cd"
211 | } ],
212 | "security-admin-console" : [ ],
213 | "admin-cli" : [ ],
214 | "broker" : [ {
215 | "id" : "b40d4af2-4d25-4a6f-bd9e-c41fba1a3d8e",
216 | "name" : "read-token",
217 | "description" : "${role_read-token}",
218 | "composite" : false,
219 | "clientRole" : true,
220 | "containerId" : "74eca6d3-3afd-4fee-9c02-983f175a39ec"
221 | } ],
222 | "master-realm" : [ {
223 | "id" : "0760ce96-4c27-4c7e-a37e-196ad11727e4",
224 | "name" : "manage-users",
225 | "description" : "${role_manage-users}",
226 | "composite" : false,
227 | "clientRole" : true,
228 | "containerId" : "4b4b0523-297d-4f01-b13e-0322e6f07692"
229 | }, {
230 | "id" : "795f8d81-db01-4dd2-a012-bc844777bacb",
231 | "name" : "view-events",
232 | "description" : "${role_view-events}",
233 | "composite" : false,
234 | "clientRole" : true,
235 | "containerId" : "4b4b0523-297d-4f01-b13e-0322e6f07692"
236 | }, {
237 | "id" : "9b1a0ea9-a0aa-4c2f-8067-7e52c4fe1620",
238 | "name" : "query-users",
239 | "description" : "${role_query-users}",
240 | "composite" : false,
241 | "clientRole" : true,
242 | "containerId" : "4b4b0523-297d-4f01-b13e-0322e6f07692"
243 | }, {
244 | "id" : "fc845391-9d81-4849-be6a-71b4412f54d2",
245 | "name" : "impersonation",
246 | "description" : "${role_impersonation}",
247 | "composite" : false,
248 | "clientRole" : true,
249 | "containerId" : "4b4b0523-297d-4f01-b13e-0322e6f07692"
250 | }, {
251 | "id" : "6fe49e43-38b8-498f-878a-0ff098f454b2",
252 | "name" : "manage-clients",
253 | "description" : "${role_manage-clients}",
254 | "composite" : false,
255 | "clientRole" : true,
256 | "containerId" : "4b4b0523-297d-4f01-b13e-0322e6f07692"
257 | }, {
258 | "id" : "a6cbc3ea-821f-42ff-9213-c3278a2179db",
259 | "name" : "view-realm",
260 | "description" : "${role_view-realm}",
261 | "composite" : false,
262 | "clientRole" : true,
263 | "containerId" : "4b4b0523-297d-4f01-b13e-0322e6f07692"
264 | }, {
265 | "id" : "3b33157c-41f5-48ca-8500-72c4f633474e",
266 | "name" : "view-authorization",
267 | "description" : "${role_view-authorization}",
268 | "composite" : false,
269 | "clientRole" : true,
270 | "containerId" : "4b4b0523-297d-4f01-b13e-0322e6f07692"
271 | }, {
272 | "id" : "bd1940bf-391c-4939-ae1e-d62fa506f672",
273 | "name" : "create-client",
274 | "description" : "${role_create-client}",
275 | "composite" : false,
276 | "clientRole" : true,
277 | "containerId" : "4b4b0523-297d-4f01-b13e-0322e6f07692"
278 | }, {
279 | "id" : "8162e52a-b3e2-4e41-bcfd-739398f7754d",
280 | "name" : "query-groups",
281 | "description" : "${role_query-groups}",
282 | "composite" : false,
283 | "clientRole" : true,
284 | "containerId" : "4b4b0523-297d-4f01-b13e-0322e6f07692"
285 | }, {
286 | "id" : "fac80180-677f-4b73-9e74-d79c1958d095",
287 | "name" : "view-clients",
288 | "description" : "${role_view-clients}",
289 | "composite" : true,
290 | "composites" : {
291 | "client" : {
292 | "master-realm" : [ "query-clients" ]
293 | }
294 | },
295 | "clientRole" : true,
296 | "containerId" : "4b4b0523-297d-4f01-b13e-0322e6f07692"
297 | }, {
298 | "id" : "d30bc182-6715-47f9-93a7-eeadba874ba7",
299 | "name" : "view-users",
300 | "description" : "${role_view-users}",
301 | "composite" : true,
302 | "composites" : {
303 | "client" : {
304 | "master-realm" : [ "query-users", "query-groups" ]
305 | }
306 | },
307 | "clientRole" : true,
308 | "containerId" : "4b4b0523-297d-4f01-b13e-0322e6f07692"
309 | }, {
310 | "id" : "89b023be-03a4-4e79-97cb-7d69075926b4",
311 | "name" : "manage-realm",
312 | "description" : "${role_manage-realm}",
313 | "composite" : false,
314 | "clientRole" : true,
315 | "containerId" : "4b4b0523-297d-4f01-b13e-0322e6f07692"
316 | }, {
317 | "id" : "7fd982e4-86b4-4e2f-92ac-556a4ea4b63d",
318 | "name" : "view-identity-providers",
319 | "description" : "${role_view-identity-providers}",
320 | "composite" : false,
321 | "clientRole" : true,
322 | "containerId" : "4b4b0523-297d-4f01-b13e-0322e6f07692"
323 | }, {
324 | "id" : "bf027ad1-3f87-4c4f-a756-78c0cf090176",
325 | "name" : "query-realms",
326 | "description" : "${role_query-realms}",
327 | "composite" : false,
328 | "clientRole" : true,
329 | "containerId" : "4b4b0523-297d-4f01-b13e-0322e6f07692"
330 | }, {
331 | "id" : "218249c2-b4b8-4543-99c9-622dda61230f",
332 | "name" : "manage-events",
333 | "description" : "${role_manage-events}",
334 | "composite" : false,
335 | "clientRole" : true,
336 | "containerId" : "4b4b0523-297d-4f01-b13e-0322e6f07692"
337 | }, {
338 | "id" : "3f34d131-fa3e-45e7-8cd8-b49688f3fe6b",
339 | "name" : "query-clients",
340 | "description" : "${role_query-clients}",
341 | "composite" : false,
342 | "clientRole" : true,
343 | "containerId" : "4b4b0523-297d-4f01-b13e-0322e6f07692"
344 | }, {
345 | "id" : "f3771c0a-5438-4358-9199-0cc451c99b33",
346 | "name" : "manage-identity-providers",
347 | "description" : "${role_manage-identity-providers}",
348 | "composite" : false,
349 | "clientRole" : true,
350 | "containerId" : "4b4b0523-297d-4f01-b13e-0322e6f07692"
351 | }, {
352 | "id" : "e96b23ab-1496-4dc3-bf32-e120d7063ab8",
353 | "name" : "manage-authorization",
354 | "description" : "${role_manage-authorization}",
355 | "composite" : false,
356 | "clientRole" : true,
357 | "containerId" : "4b4b0523-297d-4f01-b13e-0322e6f07692"
358 | } ],
359 | "account" : [ {
360 | "id" : "3fd5901a-47de-494a-a84e-b7bac78155a9",
361 | "name" : "manage-account-links",
362 | "description" : "${role_manage-account-links}",
363 | "composite" : false,
364 | "clientRole" : true,
365 | "containerId" : "f216945d-7af3-4695-8daf-eb042a8c626b"
366 | }, {
367 | "id" : "eaa552ac-4ba6-48f8-913c-c20a07feaf0f",
368 | "name" : "view-profile",
369 | "description" : "${role_view-profile}",
370 | "composite" : false,
371 | "clientRole" : true,
372 | "containerId" : "f216945d-7af3-4695-8daf-eb042a8c626b"
373 | }, {
374 | "id" : "7021dfe7-b545-4352-9183-8642e05a1199",
375 | "name" : "manage-account",
376 | "description" : "${role_manage-account}",
377 | "composite" : true,
378 | "composites" : {
379 | "client" : {
380 | "account" : [ "manage-account-links" ]
381 | }
382 | },
383 | "clientRole" : true,
384 | "containerId" : "f216945d-7af3-4695-8daf-eb042a8c626b"
385 | } ]
386 | }
387 | },
388 | "groups" : [ ],
389 | "defaultRoles" : [ "offline_access", "uma_authorization" ],
390 | "requiredCredentials" : [ "password" ],
391 | "otpPolicyType" : "totp",
392 | "otpPolicyAlgorithm" : "HmacSHA1",
393 | "otpPolicyInitialCounter" : 0,
394 | "otpPolicyDigits" : 6,
395 | "otpPolicyLookAheadWindow" : 1,
396 | "otpPolicyPeriod" : 30,
397 | "otpSupportedApplications" : [ "FreeOTP", "Google Authenticator" ],
398 | "scopeMappings" : [ {
399 | "clientScope" : "offline_access",
400 | "roles" : [ "offline_access" ]
401 | } ],
402 | "clients" : [ {
403 | "id" : "f216945d-7af3-4695-8daf-eb042a8c626b",
404 | "clientId" : "account",
405 | "name" : "${client_account}",
406 | "baseUrl" : "/auth/realms/master/account",
407 | "surrogateAuthRequired" : false,
408 | "enabled" : true,
409 | "clientAuthenticatorType" : "client-secret",
410 | "secret" : "ade754c4-c4c0-4be1-9923-f7a2efbcc1bc",
411 | "defaultRoles" : [ "view-profile", "manage-account" ],
412 | "redirectUris" : [ "/auth/realms/master/account/*" ],
413 | "webOrigins" : [ ],
414 | "notBefore" : 0,
415 | "bearerOnly" : false,
416 | "consentRequired" : false,
417 | "standardFlowEnabled" : true,
418 | "implicitFlowEnabled" : false,
419 | "directAccessGrantsEnabled" : false,
420 | "serviceAccountsEnabled" : false,
421 | "publicClient" : false,
422 | "frontchannelLogout" : false,
423 | "protocol" : "openid-connect",
424 | "attributes" : { },
425 | "authenticationFlowBindingOverrides" : { },
426 | "fullScopeAllowed" : false,
427 | "nodeReRegistrationTimeout" : 0,
428 | "defaultClientScopes" : [ "role_list", "profile", "email" ],
429 | "optionalClientScopes" : [ "address", "phone", "offline_access" ]
430 | }, {
431 | "id" : "e15b4b6d-db59-4b76-8255-e7badba48bdb",
432 | "clientId" : "admin-cli",
433 | "name" : "${client_admin-cli}",
434 | "surrogateAuthRequired" : false,
435 | "enabled" : true,
436 | "clientAuthenticatorType" : "client-secret",
437 | "secret" : "45c9742c-fb8b-410e-bef4-670988a12e4b",
438 | "redirectUris" : [ ],
439 | "webOrigins" : [ ],
440 | "notBefore" : 0,
441 | "bearerOnly" : false,
442 | "consentRequired" : false,
443 | "standardFlowEnabled" : false,
444 | "implicitFlowEnabled" : false,
445 | "directAccessGrantsEnabled" : true,
446 | "serviceAccountsEnabled" : false,
447 | "publicClient" : true,
448 | "frontchannelLogout" : false,
449 | "protocol" : "openid-connect",
450 | "attributes" : { },
451 | "authenticationFlowBindingOverrides" : { },
452 | "fullScopeAllowed" : false,
453 | "nodeReRegistrationTimeout" : 0,
454 | "defaultClientScopes" : [ "role_list", "profile", "email" ],
455 | "optionalClientScopes" : [ "address", "phone", "offline_access" ]
456 | }, {
457 | "id" : "74eca6d3-3afd-4fee-9c02-983f175a39ec",
458 | "clientId" : "broker",
459 | "name" : "${client_broker}",
460 | "surrogateAuthRequired" : false,
461 | "enabled" : true,
462 | "clientAuthenticatorType" : "client-secret",
463 | "secret" : "211eea52-5cda-4f1f-8519-7e6119697056",
464 | "redirectUris" : [ ],
465 | "webOrigins" : [ ],
466 | "notBefore" : 0,
467 | "bearerOnly" : false,
468 | "consentRequired" : false,
469 | "standardFlowEnabled" : true,
470 | "implicitFlowEnabled" : false,
471 | "directAccessGrantsEnabled" : false,
472 | "serviceAccountsEnabled" : false,
473 | "publicClient" : false,
474 | "frontchannelLogout" : false,
475 | "protocol" : "openid-connect",
476 | "attributes" : { },
477 | "authenticationFlowBindingOverrides" : { },
478 | "fullScopeAllowed" : false,
479 | "nodeReRegistrationTimeout" : 0,
480 | "defaultClientScopes" : [ "role_list", "profile", "email" ],
481 | "optionalClientScopes" : [ "address", "phone", "offline_access" ]
482 | }, {
483 | "id" : "4b4b0523-297d-4f01-b13e-0322e6f07692",
484 | "clientId" : "master-realm",
485 | "name" : "master Realm",
486 | "surrogateAuthRequired" : false,
487 | "enabled" : true,
488 | "clientAuthenticatorType" : "client-secret",
489 | "secret" : "f0d5009f-ffe9-439a-868c-b1df94175294",
490 | "redirectUris" : [ ],
491 | "webOrigins" : [ ],
492 | "notBefore" : 0,
493 | "bearerOnly" : true,
494 | "consentRequired" : false,
495 | "standardFlowEnabled" : true,
496 | "implicitFlowEnabled" : false,
497 | "directAccessGrantsEnabled" : false,
498 | "serviceAccountsEnabled" : false,
499 | "publicClient" : false,
500 | "frontchannelLogout" : false,
501 | "attributes" : { },
502 | "authenticationFlowBindingOverrides" : { },
503 | "fullScopeAllowed" : true,
504 | "nodeReRegistrationTimeout" : 0,
505 | "defaultClientScopes" : [ "role_list", "profile", "email" ],
506 | "optionalClientScopes" : [ "address", "phone", "offline_access" ]
507 | }, {
508 | "id" : "7b932c60-7f2e-4537-91f8-8b64bd4a07cd",
509 | "clientId" : "PersonRealm-realm",
510 | "name" : "PersonRealm Realm",
511 | "surrogateAuthRequired" : false,
512 | "enabled" : true,
513 | "clientAuthenticatorType" : "client-secret",
514 | "secret" : "1ede8419-4dbe-4c0c-9891-0db584e49dec",
515 | "redirectUris" : [ ],
516 | "webOrigins" : [ ],
517 | "notBefore" : 0,
518 | "bearerOnly" : true,
519 | "consentRequired" : false,
520 | "standardFlowEnabled" : true,
521 | "implicitFlowEnabled" : false,
522 | "directAccessGrantsEnabled" : false,
523 | "serviceAccountsEnabled" : false,
524 | "publicClient" : false,
525 | "frontchannelLogout" : false,
526 | "attributes" : { },
527 | "authenticationFlowBindingOverrides" : { },
528 | "fullScopeAllowed" : true,
529 | "nodeReRegistrationTimeout" : 0,
530 | "defaultClientScopes" : [ "role_list", "profile", "email" ],
531 | "optionalClientScopes" : [ "address", "phone", "offline_access" ]
532 | }, {
533 | "id" : "c8b8170c-a8a7-44a5-b125-ab1b4995c1db",
534 | "clientId" : "security-admin-console",
535 | "name" : "${client_security-admin-console}",
536 | "baseUrl" : "/auth/admin/master/console/index.html",
537 | "surrogateAuthRequired" : false,
538 | "enabled" : true,
539 | "clientAuthenticatorType" : "client-secret",
540 | "secret" : "05dabda0-c95c-4d30-952f-ca58c6688fc6",
541 | "redirectUris" : [ "/auth/admin/master/console/*" ],
542 | "webOrigins" : [ ],
543 | "notBefore" : 0,
544 | "bearerOnly" : false,
545 | "consentRequired" : false,
546 | "standardFlowEnabled" : true,
547 | "implicitFlowEnabled" : false,
548 | "directAccessGrantsEnabled" : false,
549 | "serviceAccountsEnabled" : false,
550 | "publicClient" : true,
551 | "frontchannelLogout" : false,
552 | "protocol" : "openid-connect",
553 | "attributes" : { },
554 | "authenticationFlowBindingOverrides" : { },
555 | "fullScopeAllowed" : false,
556 | "nodeReRegistrationTimeout" : 0,
557 | "protocolMappers" : [ {
558 | "id" : "4734497d-9ae0-4c93-9394-7f994a9c5632",
559 | "name" : "locale",
560 | "protocol" : "openid-connect",
561 | "protocolMapper" : "oidc-usermodel-attribute-mapper",
562 | "consentRequired" : false,
563 | "config" : {
564 | "userinfo.token.claim" : "true",
565 | "user.attribute" : "locale",
566 | "id.token.claim" : "true",
567 | "access.token.claim" : "true",
568 | "claim.name" : "locale",
569 | "jsonType.label" : "String"
570 | }
571 | } ],
572 | "defaultClientScopes" : [ "role_list", "profile", "email" ],
573 | "optionalClientScopes" : [ "address", "phone", "offline_access" ]
574 | } ],
575 | "clientScopes" : [ {
576 | "id" : "7c617354-b8ad-4863-b6b2-8f3028a2a977",
577 | "name" : "phone",
578 | "description" : "OpenID Connect built-in scope: phone",
579 | "protocol" : "openid-connect",
580 | "attributes" : {
581 | "consent.screen.text" : "${phoneScopeConsentText}",
582 | "display.on.consent.screen" : "true"
583 | },
584 | "protocolMappers" : [ {
585 | "id" : "46fee28a-291c-449a-be68-001a57a443e2",
586 | "name" : "phone number verified",
587 | "protocol" : "openid-connect",
588 | "protocolMapper" : "oidc-usermodel-attribute-mapper",
589 | "consentRequired" : false,
590 | "config" : {
591 | "userinfo.token.claim" : "true",
592 | "user.attribute" : "phoneNumberVerified",
593 | "id.token.claim" : "true",
594 | "access.token.claim" : "true",
595 | "claim.name" : "phone_number_verified",
596 | "jsonType.label" : "boolean"
597 | }
598 | }, {
599 | "id" : "09aead2d-71c1-4eed-9f10-66fa9121b34f",
600 | "name" : "phone number",
601 | "protocol" : "openid-connect",
602 | "protocolMapper" : "oidc-usermodel-attribute-mapper",
603 | "consentRequired" : false,
604 | "config" : {
605 | "userinfo.token.claim" : "true",
606 | "user.attribute" : "phoneNumber",
607 | "id.token.claim" : "true",
608 | "access.token.claim" : "true",
609 | "claim.name" : "phone_number",
610 | "jsonType.label" : "String"
611 | }
612 | } ]
613 | }, {
614 | "id" : "956a3712-5658-4278-bf8b-7b70a8de093c",
615 | "name" : "address",
616 | "description" : "OpenID Connect built-in scope: address",
617 | "protocol" : "openid-connect",
618 | "attributes" : {
619 | "consent.screen.text" : "${addressScopeConsentText}",
620 | "display.on.consent.screen" : "true"
621 | },
622 | "protocolMappers" : [ {
623 | "id" : "d696a932-e960-4d77-a98a-9b9329a6e473",
624 | "name" : "address",
625 | "protocol" : "openid-connect",
626 | "protocolMapper" : "oidc-address-mapper",
627 | "consentRequired" : false,
628 | "config" : {
629 | "user.attribute.formatted" : "formatted",
630 | "user.attribute.country" : "country",
631 | "user.attribute.postal_code" : "postal_code",
632 | "userinfo.token.claim" : "true",
633 | "user.attribute.street" : "street",
634 | "id.token.claim" : "true",
635 | "user.attribute.region" : "region",
636 | "access.token.claim" : "true",
637 | "user.attribute.locality" : "locality"
638 | }
639 | } ]
640 | }, {
641 | "id" : "47db2c12-c9f2-4347-b177-7fd2f7ec20cb",
642 | "name" : "email",
643 | "description" : "OpenID Connect built-in scope: email",
644 | "protocol" : "openid-connect",
645 | "attributes" : {
646 | "consent.screen.text" : "${emailScopeConsentText}",
647 | "display.on.consent.screen" : "true"
648 | },
649 | "protocolMappers" : [ {
650 | "id" : "da6ffb3c-7191-46c4-a1e2-85b8dc36e98d",
651 | "name" : "email",
652 | "protocol" : "openid-connect",
653 | "protocolMapper" : "oidc-usermodel-property-mapper",
654 | "consentRequired" : false,
655 | "config" : {
656 | "userinfo.token.claim" : "true",
657 | "user.attribute" : "email",
658 | "id.token.claim" : "true",
659 | "access.token.claim" : "true",
660 | "claim.name" : "email",
661 | "jsonType.label" : "String"
662 | }
663 | }, {
664 | "id" : "705385e0-69a4-4278-83c5-8e2892ebb143",
665 | "name" : "email verified",
666 | "protocol" : "openid-connect",
667 | "protocolMapper" : "oidc-usermodel-property-mapper",
668 | "consentRequired" : false,
669 | "config" : {
670 | "userinfo.token.claim" : "true",
671 | "user.attribute" : "emailVerified",
672 | "id.token.claim" : "true",
673 | "access.token.claim" : "true",
674 | "claim.name" : "email_verified",
675 | "jsonType.label" : "boolean"
676 | }
677 | } ]
678 | }, {
679 | "id" : "e3eee2ef-7bdc-4823-af4a-4ddc220cff61",
680 | "name" : "profile",
681 | "description" : "OpenID Connect built-in scope: profile",
682 | "protocol" : "openid-connect",
683 | "attributes" : {
684 | "consent.screen.text" : "${profileScopeConsentText}",
685 | "display.on.consent.screen" : "true"
686 | },
687 | "protocolMappers" : [ {
688 | "id" : "33dae257-bcc1-419f-b5a2-db2a2068b70d",
689 | "name" : "nickname",
690 | "protocol" : "openid-connect",
691 | "protocolMapper" : "oidc-usermodel-attribute-mapper",
692 | "consentRequired" : false,
693 | "config" : {
694 | "userinfo.token.claim" : "true",
695 | "user.attribute" : "nickname",
696 | "id.token.claim" : "true",
697 | "access.token.claim" : "true",
698 | "claim.name" : "nickname",
699 | "jsonType.label" : "String"
700 | }
701 | }, {
702 | "id" : "8105d39d-a87c-45a7-8833-a3c45bc6f45d",
703 | "name" : "full name",
704 | "protocol" : "openid-connect",
705 | "protocolMapper" : "oidc-full-name-mapper",
706 | "consentRequired" : false,
707 | "config" : {
708 | "id.token.claim" : "true",
709 | "access.token.claim" : "true",
710 | "userinfo.token.claim" : "true"
711 | }
712 | }, {
713 | "id" : "dd726b9a-6f57-43e2-8464-c41d820f3858",
714 | "name" : "family name",
715 | "protocol" : "openid-connect",
716 | "protocolMapper" : "oidc-usermodel-property-mapper",
717 | "consentRequired" : false,
718 | "config" : {
719 | "userinfo.token.claim" : "true",
720 | "user.attribute" : "lastName",
721 | "id.token.claim" : "true",
722 | "access.token.claim" : "true",
723 | "claim.name" : "family_name",
724 | "jsonType.label" : "String"
725 | }
726 | }, {
727 | "id" : "253c4da1-f113-40e2-9984-23638f2ed786",
728 | "name" : "picture",
729 | "protocol" : "openid-connect",
730 | "protocolMapper" : "oidc-usermodel-attribute-mapper",
731 | "consentRequired" : false,
732 | "config" : {
733 | "userinfo.token.claim" : "true",
734 | "user.attribute" : "picture",
735 | "id.token.claim" : "true",
736 | "access.token.claim" : "true",
737 | "claim.name" : "picture",
738 | "jsonType.label" : "String"
739 | }
740 | }, {
741 | "id" : "82fcbd47-c87e-46d5-ac1f-a52ea5bff22d",
742 | "name" : "website",
743 | "protocol" : "openid-connect",
744 | "protocolMapper" : "oidc-usermodel-attribute-mapper",
745 | "consentRequired" : false,
746 | "config" : {
747 | "userinfo.token.claim" : "true",
748 | "user.attribute" : "website",
749 | "id.token.claim" : "true",
750 | "access.token.claim" : "true",
751 | "claim.name" : "website",
752 | "jsonType.label" : "String"
753 | }
754 | }, {
755 | "id" : "1e5e9e68-f04b-4480-9bc8-44202424d5c7",
756 | "name" : "updated at",
757 | "protocol" : "openid-connect",
758 | "protocolMapper" : "oidc-usermodel-attribute-mapper",
759 | "consentRequired" : false,
760 | "config" : {
761 | "userinfo.token.claim" : "true",
762 | "user.attribute" : "updatedAt",
763 | "id.token.claim" : "true",
764 | "access.token.claim" : "true",
765 | "claim.name" : "updated_at",
766 | "jsonType.label" : "String"
767 | }
768 | }, {
769 | "id" : "4a7da284-5d52-41c7-96e5-fa2dcf02f09d",
770 | "name" : "locale",
771 | "protocol" : "openid-connect",
772 | "protocolMapper" : "oidc-usermodel-attribute-mapper",
773 | "consentRequired" : false,
774 | "config" : {
775 | "userinfo.token.claim" : "true",
776 | "user.attribute" : "locale",
777 | "id.token.claim" : "true",
778 | "access.token.claim" : "true",
779 | "claim.name" : "locale",
780 | "jsonType.label" : "String"
781 | }
782 | }, {
783 | "id" : "da98c273-8d11-4c6f-b249-321f8e724dbf",
784 | "name" : "given name",
785 | "protocol" : "openid-connect",
786 | "protocolMapper" : "oidc-usermodel-property-mapper",
787 | "consentRequired" : false,
788 | "config" : {
789 | "userinfo.token.claim" : "true",
790 | "user.attribute" : "firstName",
791 | "id.token.claim" : "true",
792 | "access.token.claim" : "true",
793 | "claim.name" : "given_name",
794 | "jsonType.label" : "String"
795 | }
796 | }, {
797 | "id" : "652c8229-fc70-4595-8be3-4ca7f9e289d3",
798 | "name" : "username",
799 | "protocol" : "openid-connect",
800 | "protocolMapper" : "oidc-usermodel-property-mapper",
801 | "consentRequired" : false,
802 | "config" : {
803 | "userinfo.token.claim" : "true",
804 | "user.attribute" : "username",
805 | "id.token.claim" : "true",
806 | "access.token.claim" : "true",
807 | "claim.name" : "preferred_username",
808 | "jsonType.label" : "String"
809 | }
810 | }, {
811 | "id" : "b2f773d3-d58e-4078-96e3-75b8171fb431",
812 | "name" : "middle name",
813 | "protocol" : "openid-connect",
814 | "protocolMapper" : "oidc-usermodel-attribute-mapper",
815 | "consentRequired" : false,
816 | "config" : {
817 | "userinfo.token.claim" : "true",
818 | "user.attribute" : "middleName",
819 | "id.token.claim" : "true",
820 | "access.token.claim" : "true",
821 | "claim.name" : "middle_name",
822 | "jsonType.label" : "String"
823 | }
824 | }, {
825 | "id" : "9292c0fe-6640-4d44-8c28-ccf99442f83a",
826 | "name" : "zoneinfo",
827 | "protocol" : "openid-connect",
828 | "protocolMapper" : "oidc-usermodel-attribute-mapper",
829 | "consentRequired" : false,
830 | "config" : {
831 | "userinfo.token.claim" : "true",
832 | "user.attribute" : "zoneinfo",
833 | "id.token.claim" : "true",
834 | "access.token.claim" : "true",
835 | "claim.name" : "zoneinfo",
836 | "jsonType.label" : "String"
837 | }
838 | }, {
839 | "id" : "301fab17-c053-4fd3-8eac-93dd69869b22",
840 | "name" : "gender",
841 | "protocol" : "openid-connect",
842 | "protocolMapper" : "oidc-usermodel-attribute-mapper",
843 | "consentRequired" : false,
844 | "config" : {
845 | "userinfo.token.claim" : "true",
846 | "user.attribute" : "gender",
847 | "id.token.claim" : "true",
848 | "access.token.claim" : "true",
849 | "claim.name" : "gender",
850 | "jsonType.label" : "String"
851 | }
852 | }, {
853 | "id" : "8e1a1961-a4a6-49f0-a2c1-3eaeff83b530",
854 | "name" : "profile",
855 | "protocol" : "openid-connect",
856 | "protocolMapper" : "oidc-usermodel-attribute-mapper",
857 | "consentRequired" : false,
858 | "config" : {
859 | "userinfo.token.claim" : "true",
860 | "user.attribute" : "profile",
861 | "id.token.claim" : "true",
862 | "access.token.claim" : "true",
863 | "claim.name" : "profile",
864 | "jsonType.label" : "String"
865 | }
866 | }, {
867 | "id" : "27516982-fcb1-4f0a-bfbb-f3c293ab14b8",
868 | "name" : "birthdate",
869 | "protocol" : "openid-connect",
870 | "protocolMapper" : "oidc-usermodel-attribute-mapper",
871 | "consentRequired" : false,
872 | "config" : {
873 | "userinfo.token.claim" : "true",
874 | "user.attribute" : "birthdate",
875 | "id.token.claim" : "true",
876 | "access.token.claim" : "true",
877 | "claim.name" : "birthdate",
878 | "jsonType.label" : "String"
879 | }
880 | } ]
881 | }, {
882 | "id" : "22cd0a2f-1079-49a1-93ad-e8d67e823cbe",
883 | "name" : "role_list",
884 | "description" : "SAML role list",
885 | "protocol" : "saml",
886 | "attributes" : {
887 | "consent.screen.text" : "${samlRoleListScopeConsentText}",
888 | "display.on.consent.screen" : "true"
889 | },
890 | "protocolMappers" : [ {
891 | "id" : "49c318ba-9199-4a18-82b4-322863a6b93c",
892 | "name" : "role list",
893 | "protocol" : "saml",
894 | "protocolMapper" : "saml-role-list-mapper",
895 | "consentRequired" : false,
896 | "config" : {
897 | "single" : "false",
898 | "attribute.nameformat" : "Basic",
899 | "attribute.name" : "Role"
900 | }
901 | } ]
902 | }, {
903 | "id" : "041ae8c3-6d65-4215-b48e-f7b97bf5ce89",
904 | "name" : "offline_access",
905 | "description" : "OpenID Connect built-in scope: offline_access",
906 | "protocol" : "openid-connect",
907 | "attributes" : {
908 | "consent.screen.text" : "${offlineAccessScopeConsentText}",
909 | "display.on.consent.screen" : "true"
910 | }
911 | } ],
912 | "defaultDefaultClientScopes" : [ "role_list", "profile", "email" ],
913 | "defaultOptionalClientScopes" : [ "offline_access", "address", "phone" ],
914 | "browserSecurityHeaders" : {
915 | "xContentTypeOptions" : "nosniff",
916 | "xRobotsTag" : "none",
917 | "xFrameOptions" : "SAMEORIGIN",
918 | "xXSSProtection" : "1; mode=block",
919 | "contentSecurityPolicy" : "frame-src 'self'; frame-ancestors 'self'; object-src 'none';",
920 | "strictTransportSecurity" : "max-age=31536000; includeSubDomains"
921 | },
922 | "smtpServer" : { },
923 | "eventsEnabled" : false,
924 | "eventsListeners" : [ "jboss-logging" ],
925 | "enabledEventTypes" : [ ],
926 | "adminEventsEnabled" : false,
927 | "adminEventsDetailsEnabled" : false,
928 | "components" : {
929 | "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy" : [ {
930 | "id" : "ac1053b0-0d47-45c8-b686-58edee9569ac",
931 | "name" : "Allowed Client Scopes",
932 | "providerId" : "allowed-client-templates",
933 | "subType" : "authenticated",
934 | "subComponents" : { },
935 | "config" : {
936 | "allow-default-scopes" : [ "true" ]
937 | }
938 | }, {
939 | "id" : "1f3078a7-5253-4486-9e0b-75c4fbe48212",
940 | "name" : "Max Clients Limit",
941 | "providerId" : "max-clients",
942 | "subType" : "anonymous",
943 | "subComponents" : { },
944 | "config" : {
945 | "max-clients" : [ "200" ]
946 | }
947 | }, {
948 | "id" : "9dfccd04-e04c-45e8-b0e5-e6d50dc74716",
949 | "name" : "Allowed Client Scopes",
950 | "providerId" : "allowed-client-templates",
951 | "subType" : "anonymous",
952 | "subComponents" : { },
953 | "config" : {
954 | "allow-default-scopes" : [ "true" ]
955 | }
956 | }, {
957 | "id" : "c3b67cef-318b-4fbb-a506-2931dc2b9748",
958 | "name" : "Allowed Protocol Mapper Types",
959 | "providerId" : "allowed-protocol-mappers",
960 | "subType" : "anonymous",
961 | "subComponents" : { },
962 | "config" : {
963 | "allowed-protocol-mapper-types" : [ "oidc-full-name-mapper", "oidc-usermodel-property-mapper", "oidc-sha256-pairwise-sub-mapper", "saml-user-property-mapper", "oidc-address-mapper", "oidc-usermodel-attribute-mapper", "saml-role-list-mapper", "saml-user-attribute-mapper" ]
964 | }
965 | }, {
966 | "id" : "7578bcbb-657d-44dc-87a0-24100684eb63",
967 | "name" : "Full Scope Disabled",
968 | "providerId" : "scope",
969 | "subType" : "anonymous",
970 | "subComponents" : { },
971 | "config" : { }
972 | }, {
973 | "id" : "e95afe7b-b56d-458c-9226-f276145086d4",
974 | "name" : "Allowed Protocol Mapper Types",
975 | "providerId" : "allowed-protocol-mappers",
976 | "subType" : "authenticated",
977 | "subComponents" : { },
978 | "config" : {
979 | "allowed-protocol-mapper-types" : [ "saml-user-property-mapper", "oidc-usermodel-property-mapper", "oidc-sha256-pairwise-sub-mapper", "saml-role-list-mapper", "oidc-usermodel-attribute-mapper", "saml-user-attribute-mapper", "oidc-full-name-mapper", "oidc-address-mapper" ]
980 | }
981 | }, {
982 | "id" : "013d1eea-dd7d-4b0d-8567-062d816b73f8",
983 | "name" : "Consent Required",
984 | "providerId" : "consent-required",
985 | "subType" : "anonymous",
986 | "subComponents" : { },
987 | "config" : { }
988 | }, {
989 | "id" : "35807724-673b-4322-8bfd-4f18ff9f34b0",
990 | "name" : "Trusted Hosts",
991 | "providerId" : "trusted-hosts",
992 | "subType" : "anonymous",
993 | "subComponents" : { },
994 | "config" : {
995 | "host-sending-registration-request-must-match" : [ "true" ],
996 | "client-uris-must-match" : [ "true" ]
997 | }
998 | } ],
999 | "org.keycloak.keys.KeyProvider" : [ {
1000 | "id" : "ae30e5ec-9564-464f-8199-c029bb93bbaa",
1001 | "name" : "hmac-generated",
1002 | "providerId" : "hmac-generated",
1003 | "subComponents" : { },
1004 | "config" : {
1005 | "kid" : [ "1e8fddac-27a7-4922-9146-be334a5a7176" ],
1006 | "secret" : [ "HubGcrE0NT4wY2pMl91-yHbqcjjoipKgyli6aNXWlFE" ],
1007 | "priority" : [ "100" ]
1008 | }
1009 | }, {
1010 | "id" : "e65e8ce5-79c6-4c01-9955-77fe5337caca",
1011 | "name" : "aes-generated",
1012 | "providerId" : "aes-generated",
1013 | "subComponents" : { },
1014 | "config" : {
1015 | "kid" : [ "e0f9c277-999e-45a1-8abd-c7b4136f9f09" ],
1016 | "secret" : [ "bXck72kOkcgWN-1YW1L65Q" ],
1017 | "priority" : [ "100" ]
1018 | }
1019 | }, {
1020 | "id" : "5afaa16f-eb46-473b-916b-2084a32d5c97",
1021 | "name" : "rsa-generated",
1022 | "providerId" : "rsa-generated",
1023 | "subComponents" : { },
1024 | "config" : {
1025 | "privateKey" : [ "MIIEowIBAAKCAQEAnEnAYX+w56CXEyyeH4JgDwuSjWt5bw7phxOczutaQ22ZDYZNwxyl6GaEG8uGw4FS3dGPkeGUpW3ukZV8GJhxs2eJPnvmDBqC2CLQYr2DtGjYPPrxd1eZ/6nOX4xlOJZaociLTJfKCNXTmpynyHMGsmVVy5QQiaeSa7e3+etfsD9igfsJPx6E1647LSJaIaDVHT0GuL9Hl9JMeQOIEh7wxswxfYHI2Qi5/fyAzpQqeZkC0bkrkLdFamZVhcqrtU8x/nN5XlnkQHe/ow/9O9NQLuzn7kPWkUuFl0w+axygQnHgA8di6uBsU94b6xuVik88xB3vSFV+USnDTKVkUg9nVQIDAQABAoIBAG8m/M3a1ORHkGqwptzeCpdosZgmwby8rFXHGxUGybF+9wVpaVDExTIeBwMFoxjUlyzvZ95mwyNMpgmgeRu8/9CKaE+qKpidGkXBrNcs1civcGseRjGMehgcmovV+/9c36SETp3wrl3ORaqGk8W6GR8zdutMqN5d8YLurMfwIKPlsVZK0RVrTB80fYECw8U9vBjD73Cacou+5kQAy9IcF1gn+SoomGQURFi2oVkCQlPDL1iDQvkI/hQSFUHBPAtTPQ2t4IZR+yLfu3ADmxbq8XH1mvdeiOXQccOeqYe5ZRKi+hX+WtA9Dqx2EQIR1EiyEV6bv84yIDXYHfzSyrXoMEECgYEA5cCjdhu96L9XRGZ00wWvtZphQ/cNffUy6fhnvbGjbb1FNrEhmm5vfU1nVU0060G6p8x25jW6eLgeT1V0OLq0DLuec4lXbt8OhqVhh8pvXvSOy/C+HBixWMDPJZ4TnQ75p/yZ2MC3fVQEgMHiNaYO0VZ7qyshDNzeidPuwsfqx/0CgYEAriSRD7yzXxraEwJ6OYBxubOb0TtJFePzucsZ9mjrVCzCWFgJkDtnh1Y9FS+xBW1gyFe1CudiTcAneuGCICw0yZPAdUsdc3m3LgeP4dDWPJ9bFVx0mgf6onv+agrJVyV/KEJzA5Co0wB7qtMWhJmNpGcMPq1K3GFSREOvhsQSYDkCgYEAhV0PBY4Q7Lu00lWO1rdkSUw1zZfo0waz6TByN6CXtym4tYiYcuZL/TYjF1bbsvvSd3iuQ+9IMK7fmTmHXy6xOPrnfTVp9UexTONO+928TCg1g5hZIkILH/O7yqA5zl9U9/ge7bzgRfWxL3Rb9LxRuZ4z5yX/51GGNAc7fwFA/ZkCgYAPVPTYl9qLAwg0KEGuklpw6RlM4JVcsgchUnpksXQWoyIxOP8OjcxdpAAYv2wseCbPPLmZzilfgw12yif0wS+cl7+YFBbxtcOk79GBJivWhok0ZkF11kIA0D3kBDMZ0xlQ6BjMNY5HlYFN1uvinMpVsSTo18UBhigCDpuDl/uuMQKBgCR9U6oYGBvU0jEzcn/XBe3xrf3+/0a3hKiLqnG7d3oj2zuZo4Y5nqY1LNIbroIcSsieGqD0zBiPE01EdwUAdrPicEH/8mr1BWnK9GdbdUc8SVCRNj66hnCMTsTAZbRDXnyafaOzvYWeEPMa48BC8N5tH/bYFpjNLkFJyX7jiZFJ" ],
1026 | "certificate" : [ "MIICmzCCAYMCBgFkADdJeTANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZtYXN0ZXIwHhcNMTgwNjE0MjEzMTIwWhcNMjgwNjE0MjEzMzAwWjARMQ8wDQYDVQQDDAZtYXN0ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCcScBhf7DnoJcTLJ4fgmAPC5KNa3lvDumHE5zO61pDbZkNhk3DHKXoZoQby4bDgVLd0Y+R4ZSlbe6RlXwYmHGzZ4k+e+YMGoLYItBivYO0aNg8+vF3V5n/qc5fjGU4llqhyItMl8oI1dOanKfIcwayZVXLlBCJp5Jrt7f561+wP2KB+wk/HoTXrjstIlohoNUdPQa4v0eX0kx5A4gSHvDGzDF9gcjZCLn9/IDOlCp5mQLRuSuQt0VqZlWFyqu1TzH+c3leWeRAd7+jD/0701Au7OfuQ9aRS4WXTD5rHKBCceADx2Lq4GxT3hvrG5WKTzzEHe9IVX5RKcNMpWRSD2dVAgMBAAEwDQYJKoZIhvcNAQELBQADggEBADYbmgYTRxUGEuJaQh3tPBnPmRn/vMN3JRRjCLeJ1Yg0T7PdQ3GCFa09uIJhiox1SXCDnd9csz+JmXCwamU21RkykfBneEICZ1nRh4fdtWWXsJVelSTLxZk2h1+8/xpz/HK29Dah5eAmp00QhBDPj6POmAx0YwUqMdQFtrG17Dr3lYzZFchJuCHoUBnIZT9yLbfq+znZlAb+Wtczu3B2Hw+ZBRKsan9C/GywQQuwGCYTcJMTrT7fzwuLtTEmcvcQCBjh9eUxcVSktW4DkP1RXcF3jFfrGtuWIoaTZi8bcw2ylmkmczRGbjM2Gy2R/uI/9Bpya5t6SAbVLZIAoz+R1kk=" ],
1027 | "priority" : [ "100" ]
1028 | }
1029 | } ]
1030 | },
1031 | "internationalizationEnabled" : false,
1032 | "supportedLocales" : [ ],
1033 | "authenticationFlows" : [ {
1034 | "id" : "61a1b04f-4cda-4d04-9f99-9ccafb0ec25d",
1035 | "alias" : "Handle Existing Account",
1036 | "description" : "Handle what to do if there is existing account with same email/username like authenticated identity provider",
1037 | "providerId" : "basic-flow",
1038 | "topLevel" : false,
1039 | "builtIn" : true,
1040 | "authenticationExecutions" : [ {
1041 | "authenticator" : "idp-confirm-link",
1042 | "requirement" : "REQUIRED",
1043 | "priority" : 10,
1044 | "userSetupAllowed" : false,
1045 | "autheticatorFlow" : false
1046 | }, {
1047 | "authenticator" : "idp-email-verification",
1048 | "requirement" : "ALTERNATIVE",
1049 | "priority" : 20,
1050 | "userSetupAllowed" : false,
1051 | "autheticatorFlow" : false
1052 | }, {
1053 | "requirement" : "ALTERNATIVE",
1054 | "priority" : 30,
1055 | "flowAlias" : "Verify Existing Account by Re-authentication",
1056 | "userSetupAllowed" : false,
1057 | "autheticatorFlow" : true
1058 | } ]
1059 | }, {
1060 | "id" : "0122afb1-77ec-4b00-93a5-434a765ed1a2",
1061 | "alias" : "Verify Existing Account by Re-authentication",
1062 | "description" : "Reauthentication of existing account",
1063 | "providerId" : "basic-flow",
1064 | "topLevel" : false,
1065 | "builtIn" : true,
1066 | "authenticationExecutions" : [ {
1067 | "authenticator" : "idp-username-password-form",
1068 | "requirement" : "REQUIRED",
1069 | "priority" : 10,
1070 | "userSetupAllowed" : false,
1071 | "autheticatorFlow" : false
1072 | }, {
1073 | "authenticator" : "auth-otp-form",
1074 | "requirement" : "OPTIONAL",
1075 | "priority" : 20,
1076 | "userSetupAllowed" : false,
1077 | "autheticatorFlow" : false
1078 | } ]
1079 | }, {
1080 | "id" : "783fff67-0563-4937-a8b7-3dfc292c1dd8",
1081 | "alias" : "browser",
1082 | "description" : "browser based authentication",
1083 | "providerId" : "basic-flow",
1084 | "topLevel" : true,
1085 | "builtIn" : true,
1086 | "authenticationExecutions" : [ {
1087 | "authenticator" : "auth-cookie",
1088 | "requirement" : "ALTERNATIVE",
1089 | "priority" : 10,
1090 | "userSetupAllowed" : false,
1091 | "autheticatorFlow" : false
1092 | }, {
1093 | "authenticator" : "auth-spnego",
1094 | "requirement" : "DISABLED",
1095 | "priority" : 20,
1096 | "userSetupAllowed" : false,
1097 | "autheticatorFlow" : false
1098 | }, {
1099 | "authenticator" : "identity-provider-redirector",
1100 | "requirement" : "ALTERNATIVE",
1101 | "priority" : 25,
1102 | "userSetupAllowed" : false,
1103 | "autheticatorFlow" : false
1104 | }, {
1105 | "requirement" : "ALTERNATIVE",
1106 | "priority" : 30,
1107 | "flowAlias" : "forms",
1108 | "userSetupAllowed" : false,
1109 | "autheticatorFlow" : true
1110 | } ]
1111 | }, {
1112 | "id" : "ab20292d-e385-4bc6-a61a-6d80b5b2350f",
1113 | "alias" : "clients",
1114 | "description" : "Base authentication for clients",
1115 | "providerId" : "client-flow",
1116 | "topLevel" : true,
1117 | "builtIn" : true,
1118 | "authenticationExecutions" : [ {
1119 | "authenticator" : "client-secret",
1120 | "requirement" : "ALTERNATIVE",
1121 | "priority" : 10,
1122 | "userSetupAllowed" : false,
1123 | "autheticatorFlow" : false
1124 | }, {
1125 | "authenticator" : "client-jwt",
1126 | "requirement" : "ALTERNATIVE",
1127 | "priority" : 20,
1128 | "userSetupAllowed" : false,
1129 | "autheticatorFlow" : false
1130 | }, {
1131 | "authenticator" : "client-secret-jwt",
1132 | "requirement" : "ALTERNATIVE",
1133 | "priority" : 30,
1134 | "userSetupAllowed" : false,
1135 | "autheticatorFlow" : false
1136 | } ]
1137 | }, {
1138 | "id" : "4166bae5-3edf-4965-85ac-be094f4c1a7e",
1139 | "alias" : "direct grant",
1140 | "description" : "OpenID Connect Resource Owner Grant",
1141 | "providerId" : "basic-flow",
1142 | "topLevel" : true,
1143 | "builtIn" : true,
1144 | "authenticationExecutions" : [ {
1145 | "authenticator" : "direct-grant-validate-username",
1146 | "requirement" : "REQUIRED",
1147 | "priority" : 10,
1148 | "userSetupAllowed" : false,
1149 | "autheticatorFlow" : false
1150 | }, {
1151 | "authenticator" : "direct-grant-validate-password",
1152 | "requirement" : "REQUIRED",
1153 | "priority" : 20,
1154 | "userSetupAllowed" : false,
1155 | "autheticatorFlow" : false
1156 | }, {
1157 | "authenticator" : "direct-grant-validate-otp",
1158 | "requirement" : "OPTIONAL",
1159 | "priority" : 30,
1160 | "userSetupAllowed" : false,
1161 | "autheticatorFlow" : false
1162 | } ]
1163 | }, {
1164 | "id" : "cfabe9ae-6534-4fc6-a12c-9e5528a11b94",
1165 | "alias" : "docker auth",
1166 | "description" : "Used by Docker clients to authenticate against the IDP",
1167 | "providerId" : "basic-flow",
1168 | "topLevel" : true,
1169 | "builtIn" : true,
1170 | "authenticationExecutions" : [ {
1171 | "authenticator" : "docker-http-basic-authenticator",
1172 | "requirement" : "REQUIRED",
1173 | "priority" : 10,
1174 | "userSetupAllowed" : false,
1175 | "autheticatorFlow" : false
1176 | } ]
1177 | }, {
1178 | "id" : "8ed0f2e4-6c13-48c1-9e5b-de66c31585bc",
1179 | "alias" : "first broker login",
1180 | "description" : "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account",
1181 | "providerId" : "basic-flow",
1182 | "topLevel" : true,
1183 | "builtIn" : true,
1184 | "authenticationExecutions" : [ {
1185 | "authenticatorConfig" : "review profile config",
1186 | "authenticator" : "idp-review-profile",
1187 | "requirement" : "REQUIRED",
1188 | "priority" : 10,
1189 | "userSetupAllowed" : false,
1190 | "autheticatorFlow" : false
1191 | }, {
1192 | "authenticatorConfig" : "create unique user config",
1193 | "authenticator" : "idp-create-user-if-unique",
1194 | "requirement" : "ALTERNATIVE",
1195 | "priority" : 20,
1196 | "userSetupAllowed" : false,
1197 | "autheticatorFlow" : false
1198 | }, {
1199 | "requirement" : "ALTERNATIVE",
1200 | "priority" : 30,
1201 | "flowAlias" : "Handle Existing Account",
1202 | "userSetupAllowed" : false,
1203 | "autheticatorFlow" : true
1204 | } ]
1205 | }, {
1206 | "id" : "70ba014d-febc-4dc0-8933-162d5719fc45",
1207 | "alias" : "forms",
1208 | "description" : "Username, password, otp and other auth forms.",
1209 | "providerId" : "basic-flow",
1210 | "topLevel" : false,
1211 | "builtIn" : true,
1212 | "authenticationExecutions" : [ {
1213 | "authenticator" : "auth-username-password-form",
1214 | "requirement" : "REQUIRED",
1215 | "priority" : 10,
1216 | "userSetupAllowed" : false,
1217 | "autheticatorFlow" : false
1218 | }, {
1219 | "authenticator" : "auth-otp-form",
1220 | "requirement" : "OPTIONAL",
1221 | "priority" : 20,
1222 | "userSetupAllowed" : false,
1223 | "autheticatorFlow" : false
1224 | } ]
1225 | }, {
1226 | "id" : "9117514e-34ed-4713-975a-4bd1f1d8b87e",
1227 | "alias" : "registration",
1228 | "description" : "registration flow",
1229 | "providerId" : "basic-flow",
1230 | "topLevel" : true,
1231 | "builtIn" : true,
1232 | "authenticationExecutions" : [ {
1233 | "authenticator" : "registration-page-form",
1234 | "requirement" : "REQUIRED",
1235 | "priority" : 10,
1236 | "flowAlias" : "registration form",
1237 | "userSetupAllowed" : false,
1238 | "autheticatorFlow" : true
1239 | } ]
1240 | }, {
1241 | "id" : "0db3b011-5777-4c32-84a7-f68215b6d819",
1242 | "alias" : "registration form",
1243 | "description" : "registration form",
1244 | "providerId" : "form-flow",
1245 | "topLevel" : false,
1246 | "builtIn" : true,
1247 | "authenticationExecutions" : [ {
1248 | "authenticator" : "registration-user-creation",
1249 | "requirement" : "REQUIRED",
1250 | "priority" : 20,
1251 | "userSetupAllowed" : false,
1252 | "autheticatorFlow" : false
1253 | }, {
1254 | "authenticator" : "registration-profile-action",
1255 | "requirement" : "REQUIRED",
1256 | "priority" : 40,
1257 | "userSetupAllowed" : false,
1258 | "autheticatorFlow" : false
1259 | }, {
1260 | "authenticator" : "registration-password-action",
1261 | "requirement" : "REQUIRED",
1262 | "priority" : 50,
1263 | "userSetupAllowed" : false,
1264 | "autheticatorFlow" : false
1265 | }, {
1266 | "authenticator" : "registration-recaptcha-action",
1267 | "requirement" : "DISABLED",
1268 | "priority" : 60,
1269 | "userSetupAllowed" : false,
1270 | "autheticatorFlow" : false
1271 | } ]
1272 | }, {
1273 | "id" : "8c32835d-b47a-4692-b4f7-e381ce88cb3c",
1274 | "alias" : "reset credentials",
1275 | "description" : "Reset credentials for a user if they forgot their password or something",
1276 | "providerId" : "basic-flow",
1277 | "topLevel" : true,
1278 | "builtIn" : true,
1279 | "authenticationExecutions" : [ {
1280 | "authenticator" : "reset-credentials-choose-user",
1281 | "requirement" : "REQUIRED",
1282 | "priority" : 10,
1283 | "userSetupAllowed" : false,
1284 | "autheticatorFlow" : false
1285 | }, {
1286 | "authenticator" : "reset-credential-email",
1287 | "requirement" : "REQUIRED",
1288 | "priority" : 20,
1289 | "userSetupAllowed" : false,
1290 | "autheticatorFlow" : false
1291 | }, {
1292 | "authenticator" : "reset-password",
1293 | "requirement" : "REQUIRED",
1294 | "priority" : 30,
1295 | "userSetupAllowed" : false,
1296 | "autheticatorFlow" : false
1297 | }, {
1298 | "authenticator" : "reset-otp",
1299 | "requirement" : "OPTIONAL",
1300 | "priority" : 40,
1301 | "userSetupAllowed" : false,
1302 | "autheticatorFlow" : false
1303 | } ]
1304 | }, {
1305 | "id" : "43360983-3a87-4972-a1c7-8094ff7ecfc7",
1306 | "alias" : "saml ecp",
1307 | "description" : "SAML ECP Profile Authentication Flow",
1308 | "providerId" : "basic-flow",
1309 | "topLevel" : true,
1310 | "builtIn" : true,
1311 | "authenticationExecutions" : [ {
1312 | "authenticator" : "http-basic-authenticator",
1313 | "requirement" : "REQUIRED",
1314 | "priority" : 10,
1315 | "userSetupAllowed" : false,
1316 | "autheticatorFlow" : false
1317 | } ]
1318 | } ],
1319 | "authenticatorConfig" : [ {
1320 | "id" : "a8bc5248-6eec-4422-b49f-1bfb3864af24",
1321 | "alias" : "create unique user config",
1322 | "config" : {
1323 | "require.password.update.after.registration" : "false"
1324 | }
1325 | }, {
1326 | "id" : "0ba52bb9-2da6-4731-852b-22871ada8170",
1327 | "alias" : "review profile config",
1328 | "config" : {
1329 | "update.profile.on.first.login" : "missing"
1330 | }
1331 | } ],
1332 | "requiredActions" : [ {
1333 | "alias" : "CONFIGURE_TOTP",
1334 | "name" : "Configure OTP",
1335 | "providerId" : "CONFIGURE_TOTP",
1336 | "enabled" : true,
1337 | "defaultAction" : false,
1338 | "config" : { }
1339 | }, {
1340 | "alias" : "UPDATE_PASSWORD",
1341 | "name" : "Update Password",
1342 | "providerId" : "UPDATE_PASSWORD",
1343 | "enabled" : true,
1344 | "defaultAction" : false,
1345 | "config" : { }
1346 | }, {
1347 | "alias" : "UPDATE_PROFILE",
1348 | "name" : "Update Profile",
1349 | "providerId" : "UPDATE_PROFILE",
1350 | "enabled" : true,
1351 | "defaultAction" : false,
1352 | "config" : { }
1353 | }, {
1354 | "alias" : "VERIFY_EMAIL",
1355 | "name" : "Verify Email",
1356 | "providerId" : "VERIFY_EMAIL",
1357 | "enabled" : true,
1358 | "defaultAction" : false,
1359 | "config" : { }
1360 | }, {
1361 | "alias" : "terms_and_conditions",
1362 | "name" : "Terms and Conditions",
1363 | "providerId" : "terms_and_conditions",
1364 | "enabled" : false,
1365 | "defaultAction" : false,
1366 | "config" : { }
1367 | } ],
1368 | "browserFlow" : "browser",
1369 | "registrationFlow" : "registration",
1370 | "directGrantFlow" : "direct grant",
1371 | "resetCredentialsFlow" : "reset credentials",
1372 | "clientAuthenticationFlow" : "clients",
1373 | "dockerAuthenticationFlow" : "docker auth",
1374 | "attributes" : {
1375 | "_browser_header.xXSSProtection" : "1; mode=block",
1376 | "_browser_header.strictTransportSecurity" : "max-age=31536000; includeSubDomains",
1377 | "_browser_header.xFrameOptions" : "SAMEORIGIN",
1378 | "quickLoginCheckMilliSeconds" : "1000",
1379 | "permanentLockout" : "false",
1380 | "displayName" : "Keycloak",
1381 | "_browser_header.xRobotsTag" : "none",
1382 | "maxFailureWaitSeconds" : "900",
1383 | "displayNameHtml" : "Keycloak
",
1384 | "minimumQuickLoginWaitSeconds" : "60",
1385 | "failureFactor" : "30",
1386 | "maxDeltaTimeSeconds" : "43200",
1387 | "_browser_header.xContentTypeOptions" : "nosniff",
1388 | "bruteForceProtected" : "false",
1389 | "_browser_header.contentSecurityPolicy" : "frame-src 'self'; frame-ancestors 'self'; object-src 'none';",
1390 | "waitIncrementSeconds" : "60"
1391 | },
1392 | "keycloakVersion" : "4.0.0.Final",
1393 | "userManagedAccessAllowed" : false
1394 | }
--------------------------------------------------------------------------------
/keycloak_4_spring_boot_2/keycloak/config/master-users-0.json:
--------------------------------------------------------------------------------
1 | {
2 | "realm" : "master",
3 | "users" : [ {
4 | "id" : "f7329203-f7bb-4509-854b-95f493f95452",
5 | "createdTimestamp" : 1529011982038,
6 | "username" : "admin",
7 | "enabled" : true,
8 | "totp" : false,
9 | "emailVerified" : false,
10 | "credentials" : [ {
11 | "type" : "password",
12 | "hashedSaltedValue" : "EGJ14cgjk392xckQO6ZIJXbBFknVCRT4PJO32Rq015r5UEl1w4OiY9gLYzgqdLY1gpjZWhkraBkRi5FaOElJcw==",
13 | "salt" : "Qv0W3asckEj6fd80bMoyvQ==",
14 | "hashIterations" : 27500,
15 | "counter" : 0,
16 | "algorithm" : "pbkdf2-sha256",
17 | "digits" : 0,
18 | "period" : 0,
19 | "config" : { }
20 | } ],
21 | "disableableCredentialTypes" : [ "password" ],
22 | "requiredActions" : [ ],
23 | "realmRoles" : [ "admin", "offline_access", "uma_authorization" ],
24 | "clientRoles" : {
25 | "account" : [ "manage-account", "view-profile" ]
26 | },
27 | "notBefore" : 0,
28 | "groups" : [ ]
29 | } ]
30 | }
--------------------------------------------------------------------------------
/keycloak_4_spring_boot_2/keycloak/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 |
3 | services:
4 |
5 | keycloak:
6 | image: jboss/keycloak:4.0.0.Final
7 | restart: on-failure
8 | command:
9 | - "-b"
10 | - "0.0.0.0"
11 | - "-Dkeycloak.migration.action=import"
12 | - "-Dkeycloak.migration.provider=dir"
13 | - "-Dkeycloak.migration.dir=/config/"
14 | - "-Dkeycloak.migration.strategy=IGNORE_EXISTING"
15 | volumes:
16 | - ./config:/config/
17 | environment:
18 | - KEYCLOAK_USER=admin
19 | - KEYCLOAK_PASSWORD=password
20 | - DB_VENDOR=postgres
21 | - DB_USER=admin
22 | - DB_PASSWORD=password
23 | - DB_ADDR=keycloak-db
24 | - DB_PORT=5432
25 | - DB_DATABASE=keycloakdb
26 | ports:
27 | - "8081:8080"
28 | depends_on:
29 | - keycloak-db
30 |
31 | keycloak-db:
32 | image: postgres:10
33 | environment:
34 | POSTGRES_USER: admin
35 | POSTGRES_PASSWORD: password
36 | POSTGRES_DB: keycloakdb
37 | volumes:
38 | - pgdata:/var/lib/postgresql/data
39 |
40 | volumes:
41 | pgdata:
--------------------------------------------------------------------------------
/keycloak_4_spring_boot_2/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | com.johannesinnerbichler
7 | keycloak-4-spring-boot-2
8 | 0.0.1-SNAPSHOT
9 | jar
10 |
11 | person-app
12 | Example project for integrating Keycloak with Spring Boot applications on Kubernetes.
13 |
14 |
15 | org.springframework.boot
16 | spring-boot-starter-parent
17 | 2.0.3.RELEASE
18 |
19 |
20 |
21 |
22 | UTF-8
23 | UTF-8
24 | 1.8
25 | 4.0.0.Final
26 | jinnerbichler
27 |
28 |
29 |
30 |
31 | org.springframework.boot
32 | spring-boot-starter-freemarker
33 |
34 |
35 | org.springframework.boot
36 | spring-boot-starter-web
37 |
38 |
39 | org.springframework.boot
40 | spring-boot-starter-security
41 |
42 |
43 | org.keycloak
44 | keycloak-spring-boot-2-starter
45 |
46 |
47 | org.springframework.boot
48 | spring-boot-starter-test
49 | test
50 |
51 |
52 |
53 |
54 |
55 |
56 | org.keycloak.bom
57 | keycloak-adapter-bom
58 | ${keycloak.version}
59 | pom
60 | import
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 | org.springframework.boot
69 | spring-boot-maven-plugin
70 |
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/keycloak_4_spring_boot_2/readme.md:
--------------------------------------------------------------------------------
1 | # Integrating Keycloak 4 with Spring Boot 2 Microservices
2 |
3 | This project shows a simple integration of Keycloak 4 in Spring Boot 2 applications.
4 |
5 | The following versions are used:
6 |
7 | * __Docker__: 18.03.1-ce
8 | * __Docker-compose__: 1.21.1
9 | * __Apache Maven__: 3.5.3
10 | * __Spring Boot__: 2.0.3.RELEASE
11 | * __Keycloak__: 4.0.0.Final
12 |
13 | ## Keycloak Setup
14 |
15 | First Keycloak and the database needs to be started via:
16 |
17 | ```
18 | docker-compose -f keycloak/docker-compose.yml up
19 | ```
20 |
21 | It imports a demo realm with an example user and sets the admin credentials to `admin:password`. You can visit the administration console at [http://localhost:8081/auth/](http://localhost:8081/auth/).
22 |
23 | ## Spring Boot Application
24 |
25 | After Keycloak started successfully, you can start the Spring Boot application in a separate terminal via
26 |
27 | ```
28 | mvn package spring-boot:run
29 | ```
30 |
31 | It is accessible on [http://localhost:8080](http://localhost:8080). After clicking on `All Persons`, the login page from Keycloak shows up. The credentials of the demo user are `username:password`. Signing in with that user should redirect you back to the application, where the restricted list of persons is shown.
32 |
--------------------------------------------------------------------------------
/keycloak_4_spring_boot_2/src/main/java/com/johannesinnerbichler/personapp/PersonApplication.java:
--------------------------------------------------------------------------------
1 | package com.johannesinnerbichler.personapp;
2 |
3 | import org.keycloak.adapters.KeycloakConfigResolver;
4 | import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver;
5 | import org.keycloak.adapters.springsecurity.KeycloakConfiguration;
6 | import org.keycloak.adapters.springsecurity.KeycloakSecurityComponents;
7 | import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider;
8 | import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter;
9 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
10 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
11 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
12 | import org.springframework.security.core.authority.mapping.SimpleAuthorityMapper;
13 | import org.springframework.security.core.session.SessionRegistryImpl;
14 | import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy;
15 | import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
16 | import org.springframework.beans.factory.annotation.Autowired;
17 | import org.springframework.boot.SpringApplication;
18 | import org.springframework.boot.autoconfigure.SpringBootApplication;
19 | import org.springframework.context.annotation.Bean;
20 | import org.springframework.context.annotation.ComponentScan;
21 | import org.springframework.context.annotation.Configuration;
22 | import org.springframework.stereotype.Controller;
23 | import org.springframework.ui.Model;
24 | import org.springframework.web.bind.annotation.GetMapping;
25 |
26 | import javax.servlet.ServletException;
27 | import javax.servlet.http.HttpServletRequest;
28 | import java.util.Arrays;
29 |
30 | @SpringBootApplication
31 | public class PersonApplication {
32 |
33 | public static void main(String[] args) {
34 | SpringApplication.run(PersonApplication.class, args);
35 | }
36 | }
37 |
38 | @Controller
39 | class PersonController {
40 |
41 | @GetMapping(path = "/")
42 | public String getIndex() {
43 | return "index";
44 | }
45 |
46 | @GetMapping(path = "/persons")
47 | public String getPersons(Model model) {
48 | model.addAttribute("persons", Arrays.asList("John", "David", "Peter"));
49 | return "persons";
50 | }
51 |
52 | @GetMapping(path = "/logout")
53 | public String logout(HttpServletRequest request) throws ServletException {
54 | request.logout();
55 | return "/";
56 | }
57 | }
58 |
59 | @KeycloakConfiguration
60 | class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
61 |
62 | /**
63 | * Registers the KeycloakAuthenticationProvider with the authentication manager.
64 | */
65 | @Autowired
66 | public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
67 | KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
68 |
69 | // adding proper authority mapper for prefixing role with "ROLE_"
70 | keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
71 |
72 | auth.authenticationProvider(keycloakAuthenticationProvider);
73 | }
74 |
75 | /**
76 | * Provide a session authentication strategy bean which should be of type
77 | * RegisterSessionAuthenticationStrategy for public or confidential applications
78 | * and NullAuthenticatedSessionStrategy for bearer-only applications.
79 | */
80 | @Bean
81 | @Override
82 | protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
83 | return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
84 | }
85 |
86 | /**
87 | * Use properties in application.properties instead of keycloak.json
88 | */
89 | @Bean
90 | public KeycloakConfigResolver KeycloakConfigResolver() {
91 | return new KeycloakSpringBootConfigResolver();
92 | }
93 |
94 | /**
95 | * Secure appropriate endpoints
96 | */
97 | @Override
98 | protected void configure(HttpSecurity http) throws Exception {
99 | super.configure(http);
100 | http.authorizeRequests()
101 | .antMatchers("/persons*").hasRole("user") // only user with role user are allowed to access
102 | .anyRequest().permitAll();
103 | }
104 | }
105 |
106 |
--------------------------------------------------------------------------------
/keycloak_4_spring_boot_2/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | keycloak:
2 | auth-server-url: http://127.0.0.1:8081/auth/
3 | resource: persons-app
4 | realm: PersonRealm
5 | public-client: true
6 | principal-attribute: preferred_username
7 |
--------------------------------------------------------------------------------
/keycloak_4_spring_boot_2/src/main/resources/templates/index.ftl:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Landing page
6 |
7 |
8 |
9 | All persons
10 |
11 |
12 |
--------------------------------------------------------------------------------
/keycloak_4_spring_boot_2/src/main/resources/templates/persons.ftl:
--------------------------------------------------------------------------------
1 | <#import "/spring.ftl" as spring>
2 |
3 |
4 | Persons
5 |
6 | <#list persons as person>
7 | - ${person}
8 | #list>
9 |
10 |
11 | Logout
12 |
--------------------------------------------------------------------------------
/spring-data-jpa-encryption/.gitignore:
--------------------------------------------------------------------------------
1 | /target/
2 | !.mvn/wrapper/maven-wrapper.jar
3 |
4 | ### STS ###
5 | .apt_generated
6 | .classpath
7 | .factorypath
8 | .project
9 | .settings
10 | .springBeans
11 | .sts4-cache
12 |
13 | ### IntelliJ IDEA ###
14 | .idea
15 | *.iws
16 | *.iml
17 | *.ipr
18 |
19 | ### NetBeans ###
20 | /nbproject/private/
21 | /build/
22 | /nbbuild/
23 | /dist/
24 | /nbdist/
25 | /.nb-gradle/
--------------------------------------------------------------------------------
/spring-data-jpa-encryption/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM maven:3.5-jdk-8 as builder
2 | WORKDIR /
3 | COPY . /
4 | RUN mvn clean package
5 |
6 | FROM openjdk:8-jdk-alpine
7 | LABEL maintainer="j.innerbichler@gmail.com"
8 | COPY --from=builder /target/spring-data-jpa-encryption-0.0.1-SNAPSHOT.jar app.jar
9 | EXPOSE 8080
10 | ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
11 |
--------------------------------------------------------------------------------
/spring-data-jpa-encryption/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 |
3 | services:
4 | db:
5 | image: postgres:10
6 | environment:
7 | POSTGRES_USER: admin
8 | POSTGRES_PASSWORD: password
9 | POSTGRES_DB: customerdb
10 | healthcheck:
11 | test: ["CMD-SHELL", "pg_isready -U postgres"]
12 | interval: 30s
13 | timeout: 30s
14 | retries: 3
15 |
16 | app:
17 | build: .
18 | restart: on-failure
19 | environment:
20 | POSTGRES_HOST: db
21 | POSTGRES_PORT: 5432
22 | POSTGRES_DB: customerdb
23 | POSTGRES_USER: admin
24 | POSTGRES_PASSWORD: password
25 | depends_on:
26 | - db
27 |
28 | pgweb:
29 | image: sosedoff/pgweb
30 | restart: on-failure
31 | ports:
32 | - "8081:8081"
33 | environment:
34 | - DATABASE_URL=postgres://admin:password@db:5432/customerdb?sslmode=disable
35 | depends_on:
36 | - db
--------------------------------------------------------------------------------
/spring-data-jpa-encryption/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | com.johannesinnerbichler
7 | spring-data-jpa-encryption
8 | 0.0.1-SNAPSHOT
9 | jar
10 |
11 | database-encryption
12 | Demo project for Spring Boot
13 |
14 |
15 | org.springframework.boot
16 | spring-boot-starter-parent
17 | 2.0.2.RELEASE
18 |
19 |
20 |
21 |
22 | UTF-8
23 | UTF-8
24 | 1.8
25 |
26 |
27 |
28 |
29 | org.springframework.boot
30 | spring-boot-starter-data-jpa
31 |
32 |
33 | org.springframework.boot
34 | spring-boot-starter-security
35 |
36 |
37 | com.h2database
38 | h2
39 | runtime
40 |
41 |
42 |
43 | org.postgresql
44 | postgresql
45 | 42.2.2
46 |
47 |
48 |
49 | org.bouncycastle
50 | bcpkix-jdk15on
51 | 1.59
52 |
53 |
54 |
55 | org.springframework.boot
56 | spring-boot-starter-test
57 | test
58 |
59 |
60 | org.springframework.security
61 | spring-security-test
62 | test
63 |
64 |
65 |
66 |
67 |
68 |
69 | org.springframework.boot
70 | spring-boot-maven-plugin
71 |
72 |
73 |
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/spring-data-jpa-encryption/readme.md:
--------------------------------------------------------------------------------
1 | # GDPR Compliance with Spring Boot Applications and External Databases
2 |
3 | Additional details can be found on the corresponding [blog post]().
4 |
5 | Execute
6 |
7 | ```
8 | docker-compose up --build
9 | ```
10 |
11 | in order to build the application and execute the exemplary setup.
--------------------------------------------------------------------------------
/spring-data-jpa-encryption/src/main/java/com/johannesinnerbichler/spring/data/jpa/encryption/JPAEncryptionApplication.java:
--------------------------------------------------------------------------------
1 | package com.johannesinnerbichler.spring.data.jpa.encryption;
2 |
3 | import com.johannesinnerbichler.spring.data.jpa.encryption.customer.Customer;
4 | import com.johannesinnerbichler.spring.data.jpa.encryption.customer.CustomerRepository;
5 | import org.slf4j.Logger;
6 | import org.slf4j.LoggerFactory;
7 | import org.springframework.beans.factory.annotation.Autowired;
8 | import org.springframework.boot.CommandLineRunner;
9 | import org.springframework.boot.SpringApplication;
10 | import org.springframework.boot.autoconfigure.SpringBootApplication;
11 | import org.springframework.stereotype.Component;
12 |
13 | import java.time.LocalDate;
14 | import java.time.LocalDateTime;
15 |
16 | @SpringBootApplication
17 | public class JPAEncryptionApplication {
18 |
19 |
20 | public static void main(String[] args) {
21 | SpringApplication.run(JPAEncryptionApplication.class, args);
22 | }
23 |
24 | @Component
25 | public static class DataLoader implements CommandLineRunner {
26 |
27 | private final Logger logger = LoggerFactory.getLogger(DataLoader.class);
28 |
29 | @Autowired
30 | CustomerRepository customerRepository;
31 |
32 | @Override
33 | public void run(String... strings) {
34 |
35 | // save different customers (columns are encrypted before stored in database)
36 | Customer customer1 = new Customer();
37 | customer1.setFirstName("Johannes");
38 | customer1.setLastName("Innerbichler");
39 | customer1.setEmail("j.innerbichler@gmail.com");
40 | customer1.setBirthDate(LocalDate.of(1987, 6, 17));
41 | customer1.setCreationDate(LocalDateTime.now());
42 | customerRepository.save(customer1);
43 | logger.info("Stored customer one");
44 | Customer customer2 = new Customer();
45 | customer2.setFirstName("Jack");
46 | customer2.setLastName("Black");
47 | customer2.setEmail("jack@black.example");
48 | customer2.setBirthDate(LocalDate.of(1984, 8, 17));
49 | customer2.setCreationDate(LocalDateTime.now());
50 | customerRepository.save(customer2);
51 | logger.info("Stored customer two");
52 |
53 | // find customers by mail (columns are decrypted after being fetched from database)
54 | assert customerRepository.findOneByEmail("j.innerbichler@gmail.com") != null;
55 | logger.info("Found customer one");
56 | assert customerRepository.findOneByEmail("jack@black.example") != null;
57 | logger.info("Found customer two");
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/spring-data-jpa-encryption/src/main/java/com/johannesinnerbichler/spring/data/jpa/encryption/converters/AbstractConverter.java:
--------------------------------------------------------------------------------
1 | package com.johannesinnerbichler.spring.data.jpa.encryption.converters;
2 |
3 | import org.springframework.security.crypto.encrypt.TextEncryptor;
4 |
5 | import javax.persistence.AttributeConverter;
6 |
7 | import static com.johannesinnerbichler.spring.data.jpa.encryption.converters.DatabaseEncryptionPasswordProperty.DATABASE_ENCRYPTION_PASSWORD;
8 |
9 | abstract class AbstractConverter implements AttributeConverter {
10 |
11 | @Override
12 | public String convertToDatabaseColumn(T attribute) {
13 | TextEncryptor encryptor = getEncryptor();
14 | if (encryptor != null && attribute != null)
15 | return encrypt(encryptor, attribute);
16 | return entityAttributeToString(attribute);
17 | }
18 |
19 | @Override
20 | public T convertToEntityAttribute(String dbData) {
21 | TextEncryptor encryptor = getEncryptor();
22 | if (encryptor != null && dbData != null)
23 | return decrypt(encryptor, dbData);
24 | return stringToEntityAttribute(dbData);
25 | }
26 |
27 | private TextEncryptor getEncryptor() {
28 | return DATABASE_ENCRYPTION_PASSWORD != null ? new AesEncryptor() : null;
29 | }
30 |
31 | abstract T stringToEntityAttribute(String data);
32 |
33 | abstract String entityAttributeToString(T attribute);
34 |
35 | private String encrypt(TextEncryptor encryptor, T attribute) {
36 | String attributeString = entityAttributeToString(attribute);
37 | return encryptor.encrypt(attributeString);
38 | }
39 |
40 | private T decrypt(TextEncryptor encryptor, String attributeString) {
41 | String decryptedAttributeString = encryptor.decrypt(attributeString);
42 | return stringToEntityAttribute(decryptedAttributeString);
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/spring-data-jpa-encryption/src/main/java/com/johannesinnerbichler/spring/data/jpa/encryption/converters/AesEncryptor.java:
--------------------------------------------------------------------------------
1 | package com.johannesinnerbichler.spring.data.jpa.encryption.converters;
2 |
3 | import org.springframework.security.crypto.codec.Hex;
4 | import org.springframework.security.crypto.codec.Utf8;
5 | import org.springframework.security.crypto.encrypt.BouncyCastleAesCbcBytesEncryptor;
6 | import org.springframework.security.crypto.encrypt.BytesEncryptor;
7 | import org.springframework.security.crypto.encrypt.TextEncryptor;
8 | import org.springframework.security.crypto.keygen.BytesKeyGenerator;
9 |
10 | import java.util.Random;
11 |
12 |
13 | import static com.johannesinnerbichler.spring.data.jpa.encryption.converters.DatabaseEncryptionPasswordProperty.DATABASE_ENCRYPTION_PASSWORD;
14 | import static com.johannesinnerbichler.spring.data.jpa.encryption.converters.DatabaseEncryptionPasswordProperty.DATABASE_ENCRYPTION_SALT;
15 |
16 | final class AesEncryptor implements TextEncryptor {
17 |
18 | private final BytesEncryptor encryptor;
19 |
20 | AesEncryptor() {
21 | this.encryptor = new BouncyCastleAesCbcBytesEncryptor(
22 | DATABASE_ENCRYPTION_PASSWORD,
23 | DATABASE_ENCRYPTION_SALT,
24 | new PredictableRandomBytesKeyGenerator(16));
25 | }
26 |
27 | public String encrypt(String text) {
28 | return new String(Hex.encode(encryptor.encrypt(Utf8.encode(text))));
29 | }
30 |
31 | public String decrypt(String encryptedText) {
32 | return Utf8.decode(encryptor.decrypt(Hex.decode(encryptedText)));
33 | }
34 |
35 | /**
36 | * A BytesKeyGenerator that always generates the same sequence of values
37 | */
38 | private static class PredictableRandomBytesKeyGenerator implements BytesKeyGenerator {
39 |
40 | private final Random random;
41 |
42 | private final int keyLength;
43 |
44 | PredictableRandomBytesKeyGenerator(int keyLength) {
45 | this.random = new Random(1); // always use the same seed
46 | this.keyLength = keyLength;
47 | }
48 |
49 | public int getKeyLength() {
50 | return keyLength;
51 | }
52 |
53 | public byte[] generateKey() {
54 | byte[] bytes = new byte[keyLength];
55 | random.nextBytes(bytes);
56 | return bytes;
57 | }
58 | }
59 | }
--------------------------------------------------------------------------------
/spring-data-jpa-encryption/src/main/java/com/johannesinnerbichler/spring/data/jpa/encryption/converters/DatabaseEncryptionPasswordProperty.java:
--------------------------------------------------------------------------------
1 | package com.johannesinnerbichler.spring.data.jpa.encryption.converters;
2 |
3 | import org.springframework.beans.factory.annotation.Value;
4 | import org.springframework.stereotype.Component;
5 |
6 | @Component
7 | public class DatabaseEncryptionPasswordProperty {
8 |
9 | public static String DATABASE_ENCRYPTION_PASSWORD;
10 | public static String DATABASE_ENCRYPTION_SALT;
11 |
12 | @Value("${innerbichler.database.encryption.password}")
13 | public void setPassword(String databaseEncryptionPassword) {
14 | DATABASE_ENCRYPTION_PASSWORD = databaseEncryptionPassword;
15 | }
16 |
17 | @Value("${innerbichler.database.encryption.salt}")
18 | public void setSalt(String databaseEncryptionSalt) {
19 | DATABASE_ENCRYPTION_SALT = databaseEncryptionSalt;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/spring-data-jpa-encryption/src/main/java/com/johannesinnerbichler/spring/data/jpa/encryption/converters/LocalDateConverter.java:
--------------------------------------------------------------------------------
1 | package com.johannesinnerbichler.spring.data.jpa.encryption.converters;
2 |
3 | import javax.persistence.Converter;
4 | import java.time.LocalDate;
5 |
6 | import static java.time.format.DateTimeFormatter.ISO_DATE;
7 |
8 | @Converter
9 | public class LocalDateConverter extends AbstractConverter {
10 | @Override
11 | LocalDate stringToEntityAttribute(String data) {
12 | if (data == null)
13 | return null;
14 | return LocalDate.parse(data, ISO_DATE);
15 | }
16 |
17 | @Override
18 | String entityAttributeToString(LocalDate attr) {
19 | if (attr == null)
20 | return null;
21 | return attr.format(ISO_DATE);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/spring-data-jpa-encryption/src/main/java/com/johannesinnerbichler/spring/data/jpa/encryption/converters/LocalDateTimeConverter.java:
--------------------------------------------------------------------------------
1 | package com.johannesinnerbichler.spring.data.jpa.encryption.converters;
2 |
3 | import javax.persistence.Converter;
4 | import java.time.LocalDateTime;
5 |
6 | import static java.time.format.DateTimeFormatter.ISO_DATE_TIME;
7 |
8 | @Converter
9 | public class LocalDateTimeConverter extends AbstractConverter {
10 | @Override
11 | LocalDateTime stringToEntityAttribute(String data) {
12 | if (data == null)
13 | return null;
14 | return LocalDateTime.parse(data, ISO_DATE_TIME);
15 | }
16 |
17 | @Override
18 | String entityAttributeToString(LocalDateTime attr) {
19 | if (attr == null)
20 | return null;
21 | return attr.format(ISO_DATE_TIME);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/spring-data-jpa-encryption/src/main/java/com/johannesinnerbichler/spring/data/jpa/encryption/converters/StringConverter.java:
--------------------------------------------------------------------------------
1 | package com.johannesinnerbichler.spring.data.jpa.encryption.converters;
2 |
3 | import javax.persistence.Converter;
4 |
5 | @Converter
6 | public class StringConverter extends AbstractConverter {
7 |
8 | @Override
9 | String stringToEntityAttribute(String data) {
10 | return data;
11 | }
12 |
13 | @Override
14 | String entityAttributeToString(String attr) {
15 | return attr;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/spring-data-jpa-encryption/src/main/java/com/johannesinnerbichler/spring/data/jpa/encryption/customer/Customer.java:
--------------------------------------------------------------------------------
1 | package com.johannesinnerbichler.spring.data.jpa.encryption.customer;
2 |
3 |
4 | import com.johannesinnerbichler.spring.data.jpa.encryption.converters.LocalDateConverter;
5 | import com.johannesinnerbichler.spring.data.jpa.encryption.converters.LocalDateTimeConverter;
6 | import com.johannesinnerbichler.spring.data.jpa.encryption.converters.StringConverter;
7 |
8 | import javax.persistence.*;
9 |
10 | import java.time.LocalDate;
11 | import java.time.LocalDateTime;
12 |
13 | import static javax.persistence.GenerationType.IDENTITY;
14 |
15 | @Entity
16 | @Table(name = "customer")
17 | public class Customer {
18 |
19 | @Id
20 | @GeneratedValue(strategy = IDENTITY)
21 | @Column(name = "id")
22 | private Long id;
23 |
24 | @Column(name = "first_name")
25 | @Convert(converter = StringConverter.class)
26 | private String firstName;
27 |
28 | @Column(name = "last_name")
29 | @Convert(converter = StringConverter.class)
30 | private String lastName;
31 |
32 | @Column(name = "email")
33 | @Convert(converter = StringConverter.class)
34 | private String email;
35 |
36 | @Column(name = "birth_date")
37 | @Convert(converter = LocalDateConverter.class)
38 | private LocalDate birthDate;
39 |
40 | @Column(name = "creation_date")
41 | @Convert(converter = LocalDateTimeConverter.class)
42 | private LocalDateTime creationDate;
43 |
44 | public Long getId() {
45 | return id;
46 | }
47 |
48 | public void setId(Long id) {
49 | this.id = id;
50 | }
51 |
52 | public String getFirstName() {
53 | return firstName;
54 | }
55 |
56 | public void setFirstName(String firstName) {
57 | this.firstName = firstName;
58 | }
59 |
60 | public String getLastName() {
61 | return lastName;
62 | }
63 |
64 | public void setLastName(String lastName) {
65 | this.lastName = lastName;
66 | }
67 |
68 | public String getEmail() {
69 | return email;
70 | }
71 |
72 | public void setEmail(String email) {
73 | this.email = email;
74 | }
75 |
76 | public LocalDate getBirthDate() {
77 | return birthDate;
78 | }
79 |
80 | public void setBirthDate(LocalDate birthDate) {
81 | this.birthDate = birthDate;
82 | }
83 |
84 | public LocalDateTime getCreationDate() {
85 | return creationDate;
86 | }
87 |
88 | public void setCreationDate(LocalDateTime creationDate) {
89 | this.creationDate = creationDate;
90 | }
91 | }
--------------------------------------------------------------------------------
/spring-data-jpa-encryption/src/main/java/com/johannesinnerbichler/spring/data/jpa/encryption/customer/CustomerRepository.java:
--------------------------------------------------------------------------------
1 | package com.johannesinnerbichler.spring.data.jpa.encryption.customer;
2 |
3 | import org.springframework.data.jpa.repository.JpaRepository;
4 |
5 | public interface CustomerRepository extends JpaRepository {
6 | Customer findOneByEmail(String email);
7 | }
--------------------------------------------------------------------------------
/spring-data-jpa-encryption/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: ${PORT:8080}
3 |
4 | spring:
5 | jpa:
6 | database-platform: org.hibernate.dialect.PostgreSQLDialect
7 | hibernate:
8 | ddl-auto: update
9 | properties:
10 | hibernate:
11 | temp:
12 | use_jdbc_metadata_defaults: false # Fix "Method org.postgresql.jdbc.PgConnection.createClob() is not yet implemented."
13 | datasource:
14 | driverClassName: org.postgresql.Driver
15 | url: jdbc:postgresql://${POSTGRES_HOST:localhost}:${POSTGRES_PORT:5432}/${POSTGRES_DB:customer}
16 | username: ${POSTGRES_USER:admin}
17 | password: ${POSTGRES_PASSWORD:password}
18 |
19 | innerbichler:
20 | database:
21 | encryption:
22 | password: ${ENCRYPTION_PASSWORD:superSecretPassword}
23 | salt: ${ENCRYPTION_SALT:deadbeef}
24 |
25 | ---
26 |
27 | spring:
28 | profiles: test
29 | jpa:
30 | database-platform: org.hibernate.dialect.H2Dialect
31 | hibernate:
32 | ddl-auto: update
33 | datasource:
34 | url: jdbc:h2:mem:AZ;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
35 | username: sa
36 | password:
37 | driver-class-name: org.h2.Driver
--------------------------------------------------------------------------------
/spring-data-jpa-encryption/src/test/java/com/johannesinnerbichler/springdata/jpa/encryption/customer/CustomerRepositoryTest.java:
--------------------------------------------------------------------------------
1 | package com.johannesinnerbichler.springdata.jpa.encryption.customer;
2 |
3 | import com.johannesinnerbichler.spring.data.jpa.encryption.JPAEncryptionApplication;
4 | import com.johannesinnerbichler.spring.data.jpa.encryption.converters.DatabaseEncryptionPasswordProperty;
5 | import com.johannesinnerbichler.spring.data.jpa.encryption.customer.Customer;
6 | import com.johannesinnerbichler.spring.data.jpa.encryption.customer.CustomerRepository;
7 | import org.junit.Before;
8 | import org.junit.Test;
9 | import org.junit.runner.RunWith;
10 | import org.springframework.beans.factory.annotation.Autowired;
11 | import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
12 | import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager;
13 | import org.springframework.boot.test.context.SpringBootTest;
14 | import org.springframework.test.context.ActiveProfiles;
15 | import org.springframework.test.context.junit4.SpringRunner;
16 |
17 | import static com.johannesinnerbichler.springdata.jpa.encryption.customer.CustomerRepositoryTest.Helper.disableDatabaseEncryption;
18 | import static com.johannesinnerbichler.springdata.jpa.encryption.customer.CustomerRepositoryTest.Helper.enableDatabaseEncryption;
19 | import static org.assertj.core.api.Assertions.assertThat;
20 |
21 | @DataJpaTest
22 | @ActiveProfiles("test")
23 | @RunWith(SpringRunner.class)
24 | @SpringBootTest(classes = JPAEncryptionApplication.class)
25 | public class CustomerRepositoryTest {
26 |
27 | @Autowired
28 | private CustomerRepository customerRepository;
29 |
30 | @Autowired
31 | private TestEntityManager testEntityManager;
32 |
33 | private Customer customer;
34 |
35 | @Before
36 | public void setUp() {
37 | enableDatabaseEncryption(testEntityManager);
38 | customer = new Customer();
39 | }
40 |
41 | @Test
42 | public void save_should_persist_customer_with_auto_incremented_id() {
43 | Customer firstPersist = customerRepository.save(customer);
44 | Customer secondCustomer = new Customer();
45 |
46 | Customer secondPersist = customerRepository.save(secondCustomer);
47 |
48 | assertThat(secondPersist.getId()).isEqualTo(firstPersist.getId() + 1);
49 | }
50 |
51 | @Test
52 | public void save_should_verify_that_encryption_is_enabled_on_first_name_field() {
53 | String plainFirstName = "Johannes";
54 | customer.setFirstName(plainFirstName);
55 | Customer savedCustomerWithEncryptionEnabled = customerRepository.save(customer);
56 | disableDatabaseEncryption(testEntityManager);
57 |
58 | Customer customerRetrievedWithoutEncryptionEnabled = testEntityManager.find(Customer.class, savedCustomerWithEncryptionEnabled.getId());
59 |
60 | assertThat(customerRetrievedWithoutEncryptionEnabled.getFirstName())
61 | .isNotEqualTo(plainFirstName)
62 | .isEqualTo("73d51abbd89cb8196f0efb6892f94d684b9bb00e302a79defe4bc621a65f1f0f");
63 | }
64 |
65 | @Test
66 | public void save_should_verify_that_encryption_is_enabled_on_last_name_field() {
67 | String plainLastName = "Innerbichler";
68 | customer.setLastName(plainLastName);
69 | Customer savedCustomerWithEncryptionEnabled = customerRepository.save(customer);
70 | disableDatabaseEncryption(testEntityManager);
71 |
72 | Customer customerRetrievedWithoutEncryptionEnabled = testEntityManager.find(Customer.class, savedCustomerWithEncryptionEnabled.getId());
73 |
74 | assertThat(customerRetrievedWithoutEncryptionEnabled.getLastName())
75 | .isNotEqualTo(plainLastName)
76 | .isEqualTo("73d51abbd89cb8196f0efb6892f94d68b406039fa8488b90b4dce1374348607f");
77 | }
78 |
79 | @Test
80 | public void save_should_verify_that_encryption_is_enabled_on_email_field() {
81 | String plainEmail = "j.innerbichler@gmail.com";
82 | customer.setEmail(plainEmail);
83 | Customer savedCustomerWithEncryptionEnabled = customerRepository.save(customer);
84 | disableDatabaseEncryption(testEntityManager);
85 |
86 | Customer customerRetrievedWithoutEncryptionEnabled = testEntityManager.find(Customer.class, savedCustomerWithEncryptionEnabled.getId());
87 |
88 | assertThat(customerRetrievedWithoutEncryptionEnabled.getEmail())
89 | .isNotEqualTo(plainEmail)
90 | .isEqualTo("73d51abbd89cb8196f0efb6892f94d68894ed82ec367a8c562cfd884c93a5578bd96a01b8c0607f80adda09c5805d297");
91 | }
92 |
93 | final static class Helper {
94 |
95 | static void enableDatabaseEncryption(TestEntityManager testEntityManager) {
96 | DatabaseEncryptionPasswordProperty.DATABASE_ENCRYPTION_PASSWORD = "MySuperSecretKey";
97 | DatabaseEncryptionPasswordProperty.DATABASE_ENCRYPTION_SALT= "deadbeef";
98 | testEntityManager.clear();
99 | }
100 |
101 | static void disableDatabaseEncryption(TestEntityManager testEntityManager) {
102 | DatabaseEncryptionPasswordProperty.DATABASE_ENCRYPTION_PASSWORD = null;
103 | DatabaseEncryptionPasswordProperty.DATABASE_ENCRYPTION_SALT= "deadbeef";
104 | testEntityManager.clear();
105 | }
106 | }
107 |
108 | }
--------------------------------------------------------------------------------