├── .gitignore
├── .mvn
└── wrapper
│ ├── maven-wrapper.jar
│ └── maven-wrapper.properties
├── LICENSE
├── README.md
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
├── main
├── java
│ └── com
│ │ └── mozen
│ │ └── springbootkeycloakadminapi
│ │ ├── Application.java
│ │ ├── ApplicationConfiguration.java
│ │ └── initializer
│ │ ├── KeycloakInitializer.java
│ │ ├── KeycloakInitializerConfigurationProperties.java
│ │ ├── KeycloakInitializerController.java
│ │ └── KeycloakUser.java
└── resources
│ ├── application.yml
│ └── initializer
│ ├── init-keycloak-users.json
│ └── init-keycloak.json
└── test
└── java
└── com
└── example
└── springbootkeycloakadminapi
└── ApplicationTests.java
/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**/target/
5 | !**/src/test/**/target/
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 | !**/src/main/**/build/
30 | !**/src/test/**/build/
31 |
32 | ### VS Code ###
33 | .vscode/
--------------------------------------------------------------------------------
/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mozenn/spring-boot-keycloak-admin-api/56a800d4ec6dde5e4c9a85a17679010291d05320/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.5/apache-maven-3.8.5-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar
3 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Gauthier Cassany
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Companion repository for the blog post : "Set up Keycloak in Spring Boot using the Keycloak Admin API"
2 |
3 | Checkout the blog post for more details : https://gauthier-cassany.com/posts/spring-boot-keycloak-admin-api
4 |
--------------------------------------------------------------------------------
/mvnw:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # ----------------------------------------------------------------------------
3 | # Licensed to the Apache Software Foundation (ASF) under one
4 | # or more contributor license agreements. See the NOTICE file
5 | # distributed with this work for additional information
6 | # regarding copyright ownership. The ASF licenses this file
7 | # to you under the Apache License, Version 2.0 (the
8 | # "License"); you may not use this file except in compliance
9 | # with the License. You may obtain a copy of the License at
10 | #
11 | # https://www.apache.org/licenses/LICENSE-2.0
12 | #
13 | # Unless required by applicable law or agreed to in writing,
14 | # software distributed under the License is distributed on an
15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | # KIND, either express or implied. See the License for the
17 | # specific language governing permissions and limitations
18 | # under the License.
19 | # ----------------------------------------------------------------------------
20 |
21 | # ----------------------------------------------------------------------------
22 | # Maven Start Up Batch script
23 | #
24 | # Required ENV vars:
25 | # ------------------
26 | # JAVA_HOME - location of a JDK home dir
27 | #
28 | # Optional ENV vars
29 | # -----------------
30 | # M2_HOME - location of maven2's installed home dir
31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven
32 | # e.g. to debug Maven itself, use
33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files
35 | # ----------------------------------------------------------------------------
36 |
37 | if [ -z "$MAVEN_SKIP_RC" ] ; then
38 |
39 | if [ -f /usr/local/etc/mavenrc ] ; then
40 | . /usr/local/etc/mavenrc
41 | fi
42 |
43 | if [ -f /etc/mavenrc ] ; then
44 | . /etc/mavenrc
45 | fi
46 |
47 | if [ -f "$HOME/.mavenrc" ] ; then
48 | . "$HOME/.mavenrc"
49 | fi
50 |
51 | fi
52 |
53 | # OS specific support. $var _must_ be set to either true or false.
54 | cygwin=false;
55 | darwin=false;
56 | mingw=false
57 | case "`uname`" in
58 | CYGWIN*) cygwin=true ;;
59 | MINGW*) mingw=true;;
60 | Darwin*) darwin=true
61 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
62 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
63 | if [ -z "$JAVA_HOME" ]; then
64 | if [ -x "/usr/libexec/java_home" ]; then
65 | export JAVA_HOME="`/usr/libexec/java_home`"
66 | else
67 | export JAVA_HOME="/Library/Java/Home"
68 | fi
69 | fi
70 | ;;
71 | esac
72 |
73 | if [ -z "$JAVA_HOME" ] ; then
74 | if [ -r /etc/gentoo-release ] ; then
75 | JAVA_HOME=`java-config --jre-home`
76 | fi
77 | fi
78 |
79 | if [ -z "$M2_HOME" ] ; then
80 | ## resolve links - $0 may be a link to maven's home
81 | PRG="$0"
82 |
83 | # need this for relative symlinks
84 | while [ -h "$PRG" ] ; do
85 | ls=`ls -ld "$PRG"`
86 | link=`expr "$ls" : '.*-> \(.*\)$'`
87 | if expr "$link" : '/.*' > /dev/null; then
88 | PRG="$link"
89 | else
90 | PRG="`dirname "$PRG"`/$link"
91 | fi
92 | done
93 |
94 | saveddir=`pwd`
95 |
96 | M2_HOME=`dirname "$PRG"`/..
97 |
98 | # make it fully qualified
99 | M2_HOME=`cd "$M2_HOME" && pwd`
100 |
101 | cd "$saveddir"
102 | # echo Using m2 at $M2_HOME
103 | fi
104 |
105 | # For Cygwin, ensure paths are in UNIX format before anything is touched
106 | if $cygwin ; then
107 | [ -n "$M2_HOME" ] &&
108 | M2_HOME=`cygpath --unix "$M2_HOME"`
109 | [ -n "$JAVA_HOME" ] &&
110 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
111 | [ -n "$CLASSPATH" ] &&
112 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
113 | fi
114 |
115 | # For Mingw, ensure paths are in UNIX format before anything is touched
116 | if $mingw ; then
117 | [ -n "$M2_HOME" ] &&
118 | M2_HOME="`(cd "$M2_HOME"; pwd)`"
119 | [ -n "$JAVA_HOME" ] &&
120 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
121 | fi
122 |
123 | if [ -z "$JAVA_HOME" ]; then
124 | javaExecutable="`which javac`"
125 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
126 | # readlink(1) is not available as standard on Solaris 10.
127 | readLink=`which readlink`
128 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
129 | if $darwin ; then
130 | javaHome="`dirname \"$javaExecutable\"`"
131 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
132 | else
133 | javaExecutable="`readlink -f \"$javaExecutable\"`"
134 | fi
135 | javaHome="`dirname \"$javaExecutable\"`"
136 | javaHome=`expr "$javaHome" : '\(.*\)/bin'`
137 | JAVA_HOME="$javaHome"
138 | export JAVA_HOME
139 | fi
140 | fi
141 | fi
142 |
143 | if [ -z "$JAVACMD" ] ; then
144 | if [ -n "$JAVA_HOME" ] ; then
145 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
146 | # IBM's JDK on AIX uses strange locations for the executables
147 | JAVACMD="$JAVA_HOME/jre/sh/java"
148 | else
149 | JAVACMD="$JAVA_HOME/bin/java"
150 | fi
151 | else
152 | JAVACMD="`\\unset -f command; \\command -v java`"
153 | fi
154 | fi
155 |
156 | if [ ! -x "$JAVACMD" ] ; then
157 | echo "Error: JAVA_HOME is not defined correctly." >&2
158 | echo " We cannot execute $JAVACMD" >&2
159 | exit 1
160 | fi
161 |
162 | if [ -z "$JAVA_HOME" ] ; then
163 | echo "Warning: JAVA_HOME environment variable is not set."
164 | fi
165 |
166 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
167 |
168 | # traverses directory structure from process work directory to filesystem root
169 | # first directory with .mvn subdirectory is considered project base directory
170 | find_maven_basedir() {
171 |
172 | if [ -z "$1" ]
173 | then
174 | echo "Path not specified to find_maven_basedir"
175 | return 1
176 | fi
177 |
178 | basedir="$1"
179 | wdir="$1"
180 | while [ "$wdir" != '/' ] ; do
181 | if [ -d "$wdir"/.mvn ] ; then
182 | basedir=$wdir
183 | break
184 | fi
185 | # workaround for JBEAP-8937 (on Solaris 10/Sparc)
186 | if [ -d "${wdir}" ]; then
187 | wdir=`cd "$wdir/.."; pwd`
188 | fi
189 | # end of workaround
190 | done
191 | echo "${basedir}"
192 | }
193 |
194 | # concatenates all lines of a file
195 | concat_lines() {
196 | if [ -f "$1" ]; then
197 | echo "$(tr -s '\n' ' ' < "$1")"
198 | fi
199 | }
200 |
201 | BASE_DIR=`find_maven_basedir "$(pwd)"`
202 | if [ -z "$BASE_DIR" ]; then
203 | exit 1;
204 | fi
205 |
206 | ##########################################################################################
207 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
208 | # This allows using the maven wrapper in projects that prohibit checking in binary data.
209 | ##########################################################################################
210 | if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
211 | if [ "$MVNW_VERBOSE" = true ]; then
212 | echo "Found .mvn/wrapper/maven-wrapper.jar"
213 | fi
214 | else
215 | if [ "$MVNW_VERBOSE" = true ]; then
216 | echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
217 | fi
218 | if [ -n "$MVNW_REPOURL" ]; then
219 | jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
220 | else
221 | jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
222 | fi
223 | while IFS="=" read key value; do
224 | case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
225 | esac
226 | done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
227 | if [ "$MVNW_VERBOSE" = true ]; then
228 | echo "Downloading from: $jarUrl"
229 | fi
230 | wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
231 | if $cygwin; then
232 | wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
233 | fi
234 |
235 | if command -v wget > /dev/null; then
236 | if [ "$MVNW_VERBOSE" = true ]; then
237 | echo "Found wget ... using wget"
238 | fi
239 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
240 | wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
241 | else
242 | wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
243 | fi
244 | elif command -v curl > /dev/null; then
245 | if [ "$MVNW_VERBOSE" = true ]; then
246 | echo "Found curl ... using curl"
247 | fi
248 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
249 | curl -o "$wrapperJarPath" "$jarUrl" -f
250 | else
251 | curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
252 | fi
253 |
254 | else
255 | if [ "$MVNW_VERBOSE" = true ]; then
256 | echo "Falling back to using Java to download"
257 | fi
258 | javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
259 | # For Cygwin, switch paths to Windows format before running javac
260 | if $cygwin; then
261 | javaClass=`cygpath --path --windows "$javaClass"`
262 | fi
263 | if [ -e "$javaClass" ]; then
264 | if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
265 | if [ "$MVNW_VERBOSE" = true ]; then
266 | echo " - Compiling MavenWrapperDownloader.java ..."
267 | fi
268 | # Compiling the Java class
269 | ("$JAVA_HOME/bin/javac" "$javaClass")
270 | fi
271 | if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
272 | # Running the downloader
273 | if [ "$MVNW_VERBOSE" = true ]; then
274 | echo " - Running MavenWrapperDownloader.java ..."
275 | fi
276 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
277 | fi
278 | fi
279 | fi
280 | fi
281 | ##########################################################################################
282 | # End of extension
283 | ##########################################################################################
284 |
285 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
286 | if [ "$MVNW_VERBOSE" = true ]; then
287 | echo $MAVEN_PROJECTBASEDIR
288 | fi
289 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
290 |
291 | # For Cygwin, switch paths to Windows format before running java
292 | if $cygwin; then
293 | [ -n "$M2_HOME" ] &&
294 | M2_HOME=`cygpath --path --windows "$M2_HOME"`
295 | [ -n "$JAVA_HOME" ] &&
296 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
297 | [ -n "$CLASSPATH" ] &&
298 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
299 | [ -n "$MAVEN_PROJECTBASEDIR" ] &&
300 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
301 | fi
302 |
303 | # Provide a "standardized" way to retrieve the CLI args that will
304 | # work with both Windows and non-Windows executions.
305 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
306 | export MAVEN_CMD_LINE_ARGS
307 |
308 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
309 |
310 | exec "$JAVACMD" \
311 | $MAVEN_OPTS \
312 | $MAVEN_DEBUG_OPTS \
313 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
314 | "-Dmaven.home=${M2_HOME}" \
315 | "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
316 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
317 |
--------------------------------------------------------------------------------
/mvnw.cmd:
--------------------------------------------------------------------------------
1 | @REM ----------------------------------------------------------------------------
2 | @REM Licensed to the Apache Software Foundation (ASF) under one
3 | @REM or more contributor license agreements. See the NOTICE file
4 | @REM distributed with this work for additional information
5 | @REM regarding copyright ownership. The ASF licenses this file
6 | @REM to you under the Apache License, Version 2.0 (the
7 | @REM "License"); you may not use this file except in compliance
8 | @REM with the License. You may obtain a copy of the License at
9 | @REM
10 | @REM https://www.apache.org/licenses/LICENSE-2.0
11 | @REM
12 | @REM Unless required by applicable law or agreed to in writing,
13 | @REM software distributed under the License is distributed on an
14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | @REM KIND, either express or implied. See the License for the
16 | @REM specific language governing permissions and limitations
17 | @REM under the License.
18 | @REM ----------------------------------------------------------------------------
19 |
20 | @REM ----------------------------------------------------------------------------
21 | @REM Maven Start Up Batch script
22 | @REM
23 | @REM Required ENV vars:
24 | @REM JAVA_HOME - location of a JDK home dir
25 | @REM
26 | @REM Optional ENV vars
27 | @REM M2_HOME - location of maven2's installed home dir
28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
31 | @REM e.g. to debug Maven itself, use
32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34 | @REM ----------------------------------------------------------------------------
35 |
36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
37 | @echo off
38 | @REM set title of command window
39 | title %0
40 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
42 |
43 | @REM set %HOME% to equivalent of $HOME
44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
45 |
46 | @REM Execute a user defined script before this one
47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending
49 | if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
50 | if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
51 | :skipRcPre
52 |
53 | @setlocal
54 |
55 | set ERROR_CODE=0
56 |
57 | @REM To isolate internal variables from possible post scripts, we use another setlocal
58 | @setlocal
59 |
60 | @REM ==== START VALIDATION ====
61 | if not "%JAVA_HOME%" == "" goto OkJHome
62 |
63 | echo.
64 | echo Error: JAVA_HOME not found in your environment. >&2
65 | echo Please set the JAVA_HOME variable in your environment to match the >&2
66 | echo location of your Java installation. >&2
67 | echo.
68 | goto error
69 |
70 | :OkJHome
71 | if exist "%JAVA_HOME%\bin\java.exe" goto init
72 |
73 | echo.
74 | echo Error: JAVA_HOME is set to an invalid directory. >&2
75 | echo JAVA_HOME = "%JAVA_HOME%" >&2
76 | echo Please set the JAVA_HOME variable in your environment to match the >&2
77 | echo location of your Java installation. >&2
78 | echo.
79 | goto error
80 |
81 | @REM ==== END VALIDATION ====
82 |
83 | :init
84 |
85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
86 | @REM Fallback to current working directory if not found.
87 |
88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
90 |
91 | set EXEC_DIR=%CD%
92 | set WDIR=%EXEC_DIR%
93 | :findBaseDir
94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound
95 | cd ..
96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound
97 | set WDIR=%CD%
98 | goto findBaseDir
99 |
100 | :baseDirFound
101 | set MAVEN_PROJECTBASEDIR=%WDIR%
102 | cd "%EXEC_DIR%"
103 | goto endDetectBaseDir
104 |
105 | :baseDirNotFound
106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
107 | cd "%EXEC_DIR%"
108 |
109 | :endDetectBaseDir
110 |
111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
112 |
113 | @setlocal EnableExtensions EnableDelayedExpansion
114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
116 |
117 | :endReadAdditionalConfig
118 |
119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
122 |
123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
124 |
125 | FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
126 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
127 | )
128 |
129 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
130 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data.
131 | if exist %WRAPPER_JAR% (
132 | if "%MVNW_VERBOSE%" == "true" (
133 | echo Found %WRAPPER_JAR%
134 | )
135 | ) else (
136 | if not "%MVNW_REPOURL%" == "" (
137 | SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
138 | )
139 | if "%MVNW_VERBOSE%" == "true" (
140 | echo Couldn't find %WRAPPER_JAR%, downloading it ...
141 | echo Downloading from: %DOWNLOAD_URL%
142 | )
143 |
144 | powershell -Command "&{"^
145 | "$webclient = new-object System.Net.WebClient;"^
146 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
147 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
148 | "}"^
149 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
150 | "}"
151 | if "%MVNW_VERBOSE%" == "true" (
152 | echo Finished downloading %WRAPPER_JAR%
153 | )
154 | )
155 | @REM End of extension
156 |
157 | @REM Provide a "standardized" way to retrieve the CLI args that will
158 | @REM work with both Windows and non-Windows executions.
159 | set MAVEN_CMD_LINE_ARGS=%*
160 |
161 | %MAVEN_JAVA_EXE% ^
162 | %JVM_CONFIG_MAVEN_PROPS% ^
163 | %MAVEN_OPTS% ^
164 | %MAVEN_DEBUG_OPTS% ^
165 | -classpath %WRAPPER_JAR% ^
166 | "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
167 | %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
168 | if ERRORLEVEL 1 goto error
169 | goto end
170 |
171 | :error
172 | set ERROR_CODE=1
173 |
174 | :end
175 | @endlocal & set ERROR_CODE=%ERROR_CODE%
176 |
177 | if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
178 | @REM check for post script, once with legacy .bat ending and once with .cmd ending
179 | if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
180 | if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
181 | :skipRcPost
182 |
183 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
184 | if "%MAVEN_BATCH_PAUSE%"=="on" pause
185 |
186 | if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
187 |
188 | cmd /C exit /B %ERROR_CODE%
189 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.7.1
9 |
10 |
11 | com.mozen
12 | spring-boot-keycloak-admin-api
13 | 1.0.0-SNAPSHOT
14 | demo
15 | Demo project for Spring Boot
16 |
17 | 17
18 | 18.0.2
19 |
20 |
21 |
22 | org.springframework.boot
23 | spring-boot-starter-web
24 |
25 |
26 |
27 | org.projectlombok
28 | lombok
29 | true
30 |
31 |
32 | org.springframework.boot
33 | spring-boot-starter-test
34 | test
35 |
36 |
37 |
38 | org.keycloak
39 | keycloak-admin-client
40 | 18.0.2
41 |
42 |
43 |
44 |
45 |
46 |
47 | org.springframework.boot
48 | spring-boot-maven-plugin
49 |
50 |
51 |
52 | org.projectlombok
53 | lombok
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/src/main/java/com/mozen/springbootkeycloakadminapi/Application.java:
--------------------------------------------------------------------------------
1 | package com.mozen.springbootkeycloakadminapi;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
6 | import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
7 |
8 | @ConfigurationPropertiesScan("com.mozen.springbootkeycloakadminapi")
9 | @SpringBootApplication(exclude={DataSourceAutoConfiguration.class})
10 | public class Application {
11 |
12 | public static void main(String[] args) {
13 | SpringApplication.run(Application.class, args);
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/com/mozen/springbootkeycloakadminapi/ApplicationConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.mozen.springbootkeycloakadminapi;
2 |
3 | import com.mozen.springbootkeycloakadminapi.initializer.KeycloakInitializerConfigurationProperties;
4 | import org.keycloak.OAuth2Constants;
5 | import org.keycloak.admin.client.Keycloak;
6 | import org.keycloak.admin.client.KeycloakBuilder;
7 | import org.springframework.beans.factory.annotation.Autowired;
8 | import org.springframework.context.annotation.Bean;
9 | import org.springframework.context.annotation.Configuration;
10 |
11 | @Configuration
12 | public class ApplicationConfiguration {
13 |
14 | @Autowired
15 | KeycloakInitializerConfigurationProperties keycloakInitializerConfigurationProperties;
16 |
17 | @Bean
18 | protected Keycloak keycloak() {
19 | return KeycloakBuilder.builder()
20 | .grantType(OAuth2Constants.PASSWORD)
21 | .realm(keycloakInitializerConfigurationProperties.getMasterRealm())
22 | .clientId(keycloakInitializerConfigurationProperties.getClientId())
23 | .username(keycloakInitializerConfigurationProperties.getUsername())
24 | .password(keycloakInitializerConfigurationProperties.getPassword())
25 | .serverUrl(keycloakInitializerConfigurationProperties.getUrl())
26 | .build();
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/com/mozen/springbootkeycloakadminapi/initializer/KeycloakInitializer.java:
--------------------------------------------------------------------------------
1 | package com.mozen.springbootkeycloakadminapi.initializer;
2 |
3 | import com.fasterxml.jackson.databind.ObjectMapper;
4 | import lombok.extern.slf4j.Slf4j;
5 | import org.keycloak.admin.client.Keycloak;
6 | import org.keycloak.admin.client.resource.UserResource;
7 | import org.keycloak.representations.idm.CredentialRepresentation;
8 | import org.keycloak.representations.idm.RealmRepresentation;
9 | import org.keycloak.representations.idm.RoleRepresentation;
10 | import org.keycloak.representations.idm.UserRepresentation;
11 | import org.springframework.beans.factory.InitializingBean;
12 | import org.springframework.core.io.ClassPathResource;
13 | import org.springframework.core.io.Resource;
14 | import org.springframework.stereotype.Service;
15 |
16 | import javax.ws.rs.NotFoundException;
17 | import java.io.IOException;
18 | import java.util.ArrayList;
19 | import java.util.Arrays;
20 | import java.util.List;
21 |
22 | @Slf4j
23 | @Service
24 | public class KeycloakInitializer implements InitializingBean {
25 |
26 | private final Keycloak keycloak;
27 |
28 | private final KeycloakInitializerConfigurationProperties keycloakInitializerConfigurationProperties;
29 |
30 | private final ObjectMapper mapper;
31 |
32 | private static String REALM_ID;
33 |
34 | private static final String INIT_KEYCLOAK_PATH = "initializer/init-keycloak.json";
35 | private static final String INIT_KEYCLOAK_USERS_PATH =
36 | "initializer/init-keycloak-users.json";
37 |
38 | public KeycloakInitializer(Keycloak keycloak,
39 | KeycloakInitializerConfigurationProperties keycloakInitializerConfigurationProperties,
40 | ObjectMapper mapper) {
41 | this.keycloak = keycloak;
42 | this.keycloakInitializerConfigurationProperties = keycloakInitializerConfigurationProperties;
43 | this.mapper = mapper;
44 | }
45 |
46 | @Override
47 | public void afterPropertiesSet() throws Exception {
48 | REALM_ID = keycloakInitializerConfigurationProperties.getApplicationRealm();
49 |
50 | if (keycloakInitializerConfigurationProperties.initializeOnStartup()) {
51 | init(false);
52 | }
53 | }
54 |
55 | public void init(boolean overwrite) {
56 |
57 | log.info("Initializer start");
58 |
59 | List realms = keycloak.realms().findAll();
60 | boolean isAlreadyInitialized =
61 | realms.stream().anyMatch(realm -> realm.getId().equals(REALM_ID));
62 |
63 | if (isAlreadyInitialized && overwrite) {
64 | reset();
65 | }
66 |
67 | if (!isAlreadyInitialized || overwrite) {
68 |
69 | initKeycloak();
70 |
71 | log.info("Keycloak initialized successfully");
72 | } else {
73 | log.warn("Keycloak initialization cancelled: realm already exist");
74 | }
75 | }
76 |
77 | private void initKeycloak() {
78 |
79 | initKeycloakRealm();
80 | initKeycloakUsers();
81 | }
82 |
83 | private void initKeycloakRealm() {
84 | RealmRepresentation realmRepresentation = new RealmRepresentation();
85 | realmRepresentation.setRealm(REALM_ID);
86 | realmRepresentation.setId(REALM_ID);
87 |
88 | Resource resource = new ClassPathResource(INIT_KEYCLOAK_PATH);
89 | try {
90 | RealmRepresentation realmRepresentationToImport =
91 | mapper.readValue(resource.getFile(), RealmRepresentation.class);
92 | keycloak.realms().create(realmRepresentationToImport);
93 | } catch (IOException e) {
94 | String errorMessage =
95 | String.format("Failed to import keycloak realm representation : %s", e.getMessage());
96 | log.error(errorMessage);
97 | throw new RuntimeException(errorMessage, e);
98 | }
99 | }
100 |
101 | private void initKeycloakUsers() {
102 |
103 | List users = null;
104 | try {
105 | Resource resource = new ClassPathResource(INIT_KEYCLOAK_USERS_PATH);
106 | users =
107 | mapper.readValue(
108 | resource.getFile(),
109 | mapper.getTypeFactory().constructCollectionType(ArrayList.class, KeycloakUser.class));
110 | } catch (IOException e) {
111 | String errorMessage = String.format("Failed to read keycloak users : %s", e.getMessage());
112 | log.error(errorMessage);
113 | throw new RuntimeException(errorMessage, e);
114 | }
115 |
116 | users.stream().forEach(u -> initKeycloakUser(u));
117 | }
118 |
119 | private void initKeycloakUser(KeycloakUser user) {
120 |
121 | UserRepresentation userRepresentation = new UserRepresentation();
122 | userRepresentation.setEmail(user.getEmail());
123 | userRepresentation.setUsername(user.getUsername());
124 | userRepresentation.setEnabled(true);
125 | userRepresentation.setEmailVerified(true);
126 | CredentialRepresentation userCredentialRepresentation = new CredentialRepresentation();
127 | userCredentialRepresentation.setType(CredentialRepresentation.PASSWORD);
128 | userCredentialRepresentation.setTemporary(false);
129 | userCredentialRepresentation.setValue(user.getPassword());
130 | userRepresentation.setCredentials(Arrays.asList(userCredentialRepresentation));
131 | keycloak.realm(REALM_ID).users().create(userRepresentation);
132 |
133 | if (user.isAdmin()) {
134 | userRepresentation =
135 | keycloak.realm(REALM_ID).users().search(user.getUsername()).get(0);
136 | UserResource userResource =
137 | keycloak.realm(REALM_ID).users().get(userRepresentation.getId());
138 | List rolesToAdd =
139 | Arrays.asList(keycloak.realm(REALM_ID).roles().get("admin").toRepresentation());
140 | userResource.roles().realmLevel().add(rolesToAdd);
141 | }
142 | }
143 |
144 | public void reset() {
145 | try {
146 | keycloak.realm(REALM_ID).remove();
147 | } catch (NotFoundException e) {
148 | log.error("Failed to reset Keycloak", e);
149 | }
150 | }
151 | }
152 |
--------------------------------------------------------------------------------
/src/main/java/com/mozen/springbootkeycloakadminapi/initializer/KeycloakInitializerConfigurationProperties.java:
--------------------------------------------------------------------------------
1 | package com.mozen.springbootkeycloakadminapi.initializer;
2 |
3 | import lombok.AccessLevel;
4 | import lombok.Data;
5 | import lombok.Getter;
6 | import org.springframework.boot.context.properties.ConfigurationProperties;
7 |
8 | @Data
9 | @ConfigurationProperties(prefix = "keycloak-initializer")
10 | public class KeycloakInitializerConfigurationProperties {
11 |
12 | @Getter(AccessLevel.NONE)
13 | private boolean initializeOnStartup;
14 |
15 | public boolean initializeOnStartup() {
16 | return initializeOnStartup;
17 | }
18 |
19 | private String masterRealm;
20 |
21 | private String applicationRealm;
22 |
23 | private String clientId;
24 |
25 | private String username;
26 |
27 | private String password;
28 |
29 | private String url;
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/com/mozen/springbootkeycloakadminapi/initializer/KeycloakInitializerController.java:
--------------------------------------------------------------------------------
1 | package com.mozen.springbootkeycloakadminapi.initializer;
2 |
3 | import org.springframework.web.bind.annotation.*;
4 |
5 | @RestController
6 | @RequestMapping("/keycloak")
7 | public class KeycloakInitializerController {
8 |
9 | private KeycloakInitializer keycloakInitializer;
10 |
11 | public KeycloakInitializerController(KeycloakInitializer keycloakInitializer) {
12 | this.keycloakInitializer = keycloakInitializer;
13 | }
14 |
15 | @PostMapping("/init")
16 | public void init(@RequestParam boolean overwrite) {
17 | keycloakInitializer.init(overwrite);
18 | }
19 |
20 | @DeleteMapping("/reset")
21 | public void reset() {
22 | keycloakInitializer.reset();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/com/mozen/springbootkeycloakadminapi/initializer/KeycloakUser.java:
--------------------------------------------------------------------------------
1 | package com.mozen.springbootkeycloakadminapi.initializer;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 |
6 | @Data
7 | @AllArgsConstructor
8 | public class KeycloakUser {
9 |
10 | private String username;
11 |
12 | private String password;
13 |
14 | private String email;
15 |
16 | private boolean isAdmin;
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 9000
3 |
4 | keycloak-initializer:
5 | initializeOnStartup: true
6 | masterRealm: master
7 | applicationRealm: SpringBootKeycloakAdminAPI
8 | client-id: admin-cli
9 | username: admin
10 | password: password
11 | url: http://${KEYCLOAK_HOST:localhost}:${KEYCLOAK_PORT:8180}/auth/
--------------------------------------------------------------------------------
/src/main/resources/initializer/init-keycloak-users.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "username": "admin",
4 | "password": "admin",
5 | "email": "admin@gmail.com",
6 | "isAdmin": true
7 | },
8 | {
9 | "username": "user",
10 | "password": "password",
11 | "email": "user@gmail.com",
12 | "isAdmin": false
13 | }
14 | ]
--------------------------------------------------------------------------------
/src/main/resources/initializer/init-keycloak.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "SpringBootKeycloakAdminAPI",
3 | "realm": "SpringBootKeycloakAdminAPI",
4 | "notBefore": 0,
5 | "defaultSignatureAlgorithm": "RS256",
6 | "revokeRefreshToken": false,
7 | "refreshTokenMaxReuse": 0,
8 | "accessTokenLifespan": 300,
9 | "accessTokenLifespanForImplicitFlow": 900,
10 | "ssoSessionIdleTimeout": 1800,
11 | "ssoSessionMaxLifespan": 36000,
12 | "ssoSessionIdleTimeoutRememberMe": 0,
13 | "ssoSessionMaxLifespanRememberMe": 0,
14 | "offlineSessionIdleTimeout": 2592000,
15 | "offlineSessionMaxLifespanEnabled": false,
16 | "offlineSessionMaxLifespan": 5184000,
17 | "clientSessionIdleTimeout": 0,
18 | "clientSessionMaxLifespan": 0,
19 | "clientOfflineSessionIdleTimeout": 0,
20 | "clientOfflineSessionMaxLifespan": 0,
21 | "accessCodeLifespan": 60,
22 | "accessCodeLifespanUserAction": 300,
23 | "accessCodeLifespanLogin": 1800,
24 | "actionTokenGeneratedByAdminLifespan": 43200,
25 | "actionTokenGeneratedByUserLifespan": 300,
26 | "oauth2DeviceCodeLifespan": 600,
27 | "oauth2DevicePollingInterval": 5,
28 | "enabled": true,
29 | "sslRequired": "external",
30 | "registrationAllowed": false,
31 | "registrationEmailAsUsername": false,
32 | "rememberMe": false,
33 | "verifyEmail": false,
34 | "loginWithEmailAllowed": true,
35 | "duplicateEmailsAllowed": false,
36 | "resetPasswordAllowed": false,
37 | "editUsernameAllowed": false,
38 | "bruteForceProtected": false,
39 | "permanentLockout": false,
40 | "maxFailureWaitSeconds": 900,
41 | "minimumQuickLoginWaitSeconds": 60,
42 | "waitIncrementSeconds": 60,
43 | "quickLoginCheckMilliSeconds": 1000,
44 | "maxDeltaTimeSeconds": 43200,
45 | "failureFactor": 30,
46 | "roles": {
47 | "realm": [
48 | {
49 | "id": "09e83b6c-874a-46e1-a5f1-404b758c9358",
50 | "name": "default-roles-springbootkeycloakadminapi",
51 | "description": "${role_default-roles}",
52 | "composite": true,
53 | "composites": {
54 | "realm": [
55 | "offline_access",
56 | "uma_authorization"
57 | ],
58 | "client": {
59 | "account": [
60 | "manage-account",
61 | "view-profile"
62 | ]
63 | }
64 | },
65 | "clientRole": false,
66 | "containerId": "SpringBootKeycloakAdminAPI",
67 | "attributes": {}
68 | },
69 | {
70 | "id": "4767a116-81c2-4f9e-b914-4089010143a9",
71 | "name": "offline_access",
72 | "description": "${role_offline-access}",
73 | "composite": false,
74 | "clientRole": false,
75 | "containerId": "SpringBootKeycloakAdminAPI",
76 | "attributes": {}
77 | },
78 | {
79 | "id": "950d97be-0734-4a34-89d0-c882d23bf8ba",
80 | "name": "admin",
81 | "composite": false,
82 | "clientRole": false,
83 | "containerId": "SpringBootKeycloakAdminAPI",
84 | "attributes": {}
85 | },
86 | {
87 | "id": "9799ba20-c39a-477c-a2c2-ec66b2ee3c93",
88 | "name": "uma_authorization",
89 | "description": "${role_uma_authorization}",
90 | "composite": false,
91 | "clientRole": false,
92 | "containerId": "SpringBootKeycloakAdminAPI",
93 | "attributes": {}
94 | }
95 | ],
96 | "client": {
97 | "realm-management": [
98 | {
99 | "id": "15abfe47-1bd9-41bd-9b6e-b4e396f2f243",
100 | "name": "create-client",
101 | "description": "${role_create-client}",
102 | "composite": false,
103 | "clientRole": true,
104 | "containerId": "1b024c36-0193-4c5b-8030-b9536db34fdf",
105 | "attributes": {}
106 | },
107 | {
108 | "id": "4e339f03-50a6-409d-8ba7-beff1aed87a9",
109 | "name": "manage-events",
110 | "description": "${role_manage-events}",
111 | "composite": false,
112 | "clientRole": true,
113 | "containerId": "1b024c36-0193-4c5b-8030-b9536db34fdf",
114 | "attributes": {}
115 | },
116 | {
117 | "id": "0517284c-ce04-4230-b758-167182838c7d",
118 | "name": "query-clients",
119 | "description": "${role_query-clients}",
120 | "composite": false,
121 | "clientRole": true,
122 | "containerId": "1b024c36-0193-4c5b-8030-b9536db34fdf",
123 | "attributes": {}
124 | },
125 | {
126 | "id": "1affe43a-418f-4a42-93bf-609e213ee63a",
127 | "name": "query-users",
128 | "description": "${role_query-users}",
129 | "composite": false,
130 | "clientRole": true,
131 | "containerId": "1b024c36-0193-4c5b-8030-b9536db34fdf",
132 | "attributes": {}
133 | },
134 | {
135 | "id": "7d5594f4-864a-456e-8c11-b3a8b669aac3",
136 | "name": "query-realms",
137 | "description": "${role_query-realms}",
138 | "composite": false,
139 | "clientRole": true,
140 | "containerId": "1b024c36-0193-4c5b-8030-b9536db34fdf",
141 | "attributes": {}
142 | },
143 | {
144 | "id": "7b4c767a-4fa4-4c81-a7f0-53487e071560",
145 | "name": "view-users",
146 | "description": "${role_view-users}",
147 | "composite": true,
148 | "composites": {
149 | "client": {
150 | "realm-management": [
151 | "query-groups",
152 | "query-users"
153 | ]
154 | }
155 | },
156 | "clientRole": true,
157 | "containerId": "1b024c36-0193-4c5b-8030-b9536db34fdf",
158 | "attributes": {}
159 | },
160 | {
161 | "id": "98fda5d6-2003-4ffa-a066-bba292f07730",
162 | "name": "manage-identity-providers",
163 | "description": "${role_manage-identity-providers}",
164 | "composite": false,
165 | "clientRole": true,
166 | "containerId": "1b024c36-0193-4c5b-8030-b9536db34fdf",
167 | "attributes": {}
168 | },
169 | {
170 | "id": "a02a81a8-6639-4dba-a45d-a8b3e0bb5ded",
171 | "name": "manage-realm",
172 | "description": "${role_manage-realm}",
173 | "composite": false,
174 | "clientRole": true,
175 | "containerId": "1b024c36-0193-4c5b-8030-b9536db34fdf",
176 | "attributes": {}
177 | },
178 | {
179 | "id": "c80848c9-833d-4c66-aa29-fa6ebae3e3ce",
180 | "name": "view-events",
181 | "description": "${role_view-events}",
182 | "composite": false,
183 | "clientRole": true,
184 | "containerId": "1b024c36-0193-4c5b-8030-b9536db34fdf",
185 | "attributes": {}
186 | },
187 | {
188 | "id": "81d35256-b9ba-4238-9acd-622b73443129",
189 | "name": "realm-admin",
190 | "description": "${role_realm-admin}",
191 | "composite": true,
192 | "composites": {
193 | "client": {
194 | "realm-management": [
195 | "create-client",
196 | "manage-events",
197 | "query-clients",
198 | "query-users",
199 | "query-realms",
200 | "view-users",
201 | "manage-identity-providers",
202 | "manage-realm",
203 | "view-events",
204 | "view-realm",
205 | "view-identity-providers",
206 | "query-groups",
207 | "impersonation",
208 | "manage-users",
209 | "view-authorization",
210 | "manage-clients",
211 | "view-clients",
212 | "manage-authorization"
213 | ]
214 | }
215 | },
216 | "clientRole": true,
217 | "containerId": "1b024c36-0193-4c5b-8030-b9536db34fdf",
218 | "attributes": {}
219 | },
220 | {
221 | "id": "05c8970e-5f29-45f0-815e-420c82804ec1",
222 | "name": "view-realm",
223 | "description": "${role_view-realm}",
224 | "composite": false,
225 | "clientRole": true,
226 | "containerId": "1b024c36-0193-4c5b-8030-b9536db34fdf",
227 | "attributes": {}
228 | },
229 | {
230 | "id": "c398959e-22d5-4afc-b4cc-e034441becb2",
231 | "name": "query-groups",
232 | "description": "${role_query-groups}",
233 | "composite": false,
234 | "clientRole": true,
235 | "containerId": "1b024c36-0193-4c5b-8030-b9536db34fdf",
236 | "attributes": {}
237 | },
238 | {
239 | "id": "1365306b-2582-4082-882f-eea84bc8d2b3",
240 | "name": "view-identity-providers",
241 | "description": "${role_view-identity-providers}",
242 | "composite": false,
243 | "clientRole": true,
244 | "containerId": "1b024c36-0193-4c5b-8030-b9536db34fdf",
245 | "attributes": {}
246 | },
247 | {
248 | "id": "0d9bfb23-2e8e-4562-8af1-11aa92b24311",
249 | "name": "impersonation",
250 | "description": "${role_impersonation}",
251 | "composite": false,
252 | "clientRole": true,
253 | "containerId": "1b024c36-0193-4c5b-8030-b9536db34fdf",
254 | "attributes": {}
255 | },
256 | {
257 | "id": "055c8f6f-268c-4065-bd78-40efc53107fa",
258 | "name": "manage-users",
259 | "description": "${role_manage-users}",
260 | "composite": false,
261 | "clientRole": true,
262 | "containerId": "1b024c36-0193-4c5b-8030-b9536db34fdf",
263 | "attributes": {}
264 | },
265 | {
266 | "id": "4441dbec-3842-4a7a-853b-b369208ab371",
267 | "name": "manage-clients",
268 | "description": "${role_manage-clients}",
269 | "composite": false,
270 | "clientRole": true,
271 | "containerId": "1b024c36-0193-4c5b-8030-b9536db34fdf",
272 | "attributes": {}
273 | },
274 | {
275 | "id": "9f4a7706-75d7-47eb-97e6-3ceb473c9710",
276 | "name": "view-authorization",
277 | "description": "${role_view-authorization}",
278 | "composite": false,
279 | "clientRole": true,
280 | "containerId": "1b024c36-0193-4c5b-8030-b9536db34fdf",
281 | "attributes": {}
282 | },
283 | {
284 | "id": "c98f856a-c0be-439c-b22f-422953291fd2",
285 | "name": "manage-authorization",
286 | "description": "${role_manage-authorization}",
287 | "composite": false,
288 | "clientRole": true,
289 | "containerId": "1b024c36-0193-4c5b-8030-b9536db34fdf",
290 | "attributes": {}
291 | },
292 | {
293 | "id": "2926e629-715f-4cf6-8a2f-4984f2b87b25",
294 | "name": "view-clients",
295 | "description": "${role_view-clients}",
296 | "composite": true,
297 | "composites": {
298 | "client": {
299 | "realm-management": [
300 | "query-clients"
301 | ]
302 | }
303 | },
304 | "clientRole": true,
305 | "containerId": "1b024c36-0193-4c5b-8030-b9536db34fdf",
306 | "attributes": {}
307 | }
308 | ],
309 | "security-admin-console": [],
310 | "admin-cli": [],
311 | "account-console": [],
312 | "broker": [
313 | {
314 | "id": "62364646-55ad-4428-b7ba-909fed7eb727",
315 | "name": "read-token",
316 | "description": "${role_read-token}",
317 | "composite": false,
318 | "clientRole": true,
319 | "containerId": "54abba39-84ab-4d37-87c9-864dda16f7ee",
320 | "attributes": {}
321 | }
322 | ],
323 | "account": [
324 | {
325 | "id": "c34ff867-4326-4e3b-b091-422db48fe63c",
326 | "name": "view-applications",
327 | "description": "${role_view-applications}",
328 | "composite": false,
329 | "clientRole": true,
330 | "containerId": "edd9455b-9993-4d2d-b793-e12abb1f4127",
331 | "attributes": {}
332 | },
333 | {
334 | "id": "c7502250-d5d9-470e-ae8e-ecf67ac5440a",
335 | "name": "view-consent",
336 | "description": "${role_view-consent}",
337 | "composite": false,
338 | "clientRole": true,
339 | "containerId": "edd9455b-9993-4d2d-b793-e12abb1f4127",
340 | "attributes": {}
341 | },
342 | {
343 | "id": "21ff2807-7614-431e-8a2a-eeb3ce613848",
344 | "name": "delete-account",
345 | "description": "${role_delete-account}",
346 | "composite": false,
347 | "clientRole": true,
348 | "containerId": "edd9455b-9993-4d2d-b793-e12abb1f4127",
349 | "attributes": {}
350 | },
351 | {
352 | "id": "af99088f-40d5-4395-8fb9-4fd8fcfe0173",
353 | "name": "manage-account",
354 | "description": "${role_manage-account}",
355 | "composite": true,
356 | "composites": {
357 | "client": {
358 | "account": [
359 | "manage-account-links"
360 | ]
361 | }
362 | },
363 | "clientRole": true,
364 | "containerId": "edd9455b-9993-4d2d-b793-e12abb1f4127",
365 | "attributes": {}
366 | },
367 | {
368 | "id": "8b635393-31e1-42a7-9cb4-4c6dae588c36",
369 | "name": "manage-account-links",
370 | "description": "${role_manage-account-links}",
371 | "composite": false,
372 | "clientRole": true,
373 | "containerId": "edd9455b-9993-4d2d-b793-e12abb1f4127",
374 | "attributes": {}
375 | },
376 | {
377 | "id": "741d0783-3f6e-403f-9b85-b210552f3359",
378 | "name": "manage-consent",
379 | "description": "${role_manage-consent}",
380 | "composite": true,
381 | "composites": {
382 | "client": {
383 | "account": [
384 | "view-consent"
385 | ]
386 | }
387 | },
388 | "clientRole": true,
389 | "containerId": "edd9455b-9993-4d2d-b793-e12abb1f4127",
390 | "attributes": {}
391 | },
392 | {
393 | "id": "c2135632-5d56-4186-ba48-09d30c23b0a3",
394 | "name": "view-profile",
395 | "description": "${role_view-profile}",
396 | "composite": false,
397 | "clientRole": true,
398 | "containerId": "edd9455b-9993-4d2d-b793-e12abb1f4127",
399 | "attributes": {}
400 | }
401 | ]
402 | }
403 | },
404 | "groups": [],
405 | "defaultRole": {
406 | "id": "09e83b6c-874a-46e1-a5f1-404b758c9358",
407 | "name": "default-roles-springbootkeycloakadminapi",
408 | "description": "${role_default-roles}",
409 | "composite": true,
410 | "clientRole": false,
411 | "containerId": "SpringBootKeycloakAdminAPI"
412 | },
413 | "requiredCredentials": [
414 | "password"
415 | ],
416 | "otpPolicyType": "totp",
417 | "otpPolicyAlgorithm": "HmacSHA1",
418 | "otpPolicyInitialCounter": 0,
419 | "otpPolicyDigits": 6,
420 | "otpPolicyLookAheadWindow": 1,
421 | "otpPolicyPeriod": 30,
422 | "otpSupportedApplications": [
423 | "FreeOTP",
424 | "Google Authenticator"
425 | ],
426 | "webAuthnPolicyRpEntityName": "keycloak",
427 | "webAuthnPolicySignatureAlgorithms": [
428 | "ES256"
429 | ],
430 | "webAuthnPolicyRpId": "",
431 | "webAuthnPolicyAttestationConveyancePreference": "not specified",
432 | "webAuthnPolicyAuthenticatorAttachment": "not specified",
433 | "webAuthnPolicyRequireResidentKey": "not specified",
434 | "webAuthnPolicyUserVerificationRequirement": "not specified",
435 | "webAuthnPolicyCreateTimeout": 0,
436 | "webAuthnPolicyAvoidSameAuthenticatorRegister": false,
437 | "webAuthnPolicyAcceptableAaguids": [],
438 | "webAuthnPolicyPasswordlessRpEntityName": "keycloak",
439 | "webAuthnPolicyPasswordlessSignatureAlgorithms": [
440 | "ES256"
441 | ],
442 | "webAuthnPolicyPasswordlessRpId": "",
443 | "webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified",
444 | "webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified",
445 | "webAuthnPolicyPasswordlessRequireResidentKey": "not specified",
446 | "webAuthnPolicyPasswordlessUserVerificationRequirement": "not specified",
447 | "webAuthnPolicyPasswordlessCreateTimeout": 0,
448 | "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false,
449 | "webAuthnPolicyPasswordlessAcceptableAaguids": [],
450 | "scopeMappings": [
451 | {
452 | "clientScope": "offline_access",
453 | "roles": [
454 | "offline_access"
455 | ]
456 | }
457 | ],
458 | "clientScopeMappings": {
459 | "account": [
460 | {
461 | "client": "account-console",
462 | "roles": [
463 | "manage-account"
464 | ]
465 | }
466 | ]
467 | },
468 | "clients": [
469 | {
470 | "id": "edd9455b-9993-4d2d-b793-e12abb1f4127",
471 | "clientId": "account",
472 | "name": "${client_account}",
473 | "rootUrl": "${authBaseUrl}",
474 | "baseUrl": "/realms/SpringBootKeycloakAdminAPI/account/",
475 | "surrogateAuthRequired": false,
476 | "enabled": true,
477 | "alwaysDisplayInConsole": false,
478 | "clientAuthenticatorType": "client-secret",
479 | "redirectUris": [
480 | "/realms/SpringBootKeycloakAdminAPI/account/*"
481 | ],
482 | "webOrigins": [],
483 | "notBefore": 0,
484 | "bearerOnly": false,
485 | "consentRequired": false,
486 | "standardFlowEnabled": true,
487 | "implicitFlowEnabled": false,
488 | "directAccessGrantsEnabled": false,
489 | "serviceAccountsEnabled": false,
490 | "publicClient": true,
491 | "frontchannelLogout": false,
492 | "protocol": "openid-connect",
493 | "attributes": {},
494 | "authenticationFlowBindingOverrides": {},
495 | "fullScopeAllowed": false,
496 | "nodeReRegistrationTimeout": 0,
497 | "defaultClientScopes": [
498 | "web-origins",
499 | "profile",
500 | "roles",
501 | "email"
502 | ],
503 | "optionalClientScopes": [
504 | "address",
505 | "phone",
506 | "offline_access",
507 | "microprofile-jwt"
508 | ]
509 | },
510 | {
511 | "id": "4e3cb07c-7571-4eb5-8b82-9479cdd74219",
512 | "clientId": "account-console",
513 | "name": "${client_account-console}",
514 | "rootUrl": "${authBaseUrl}",
515 | "baseUrl": "/realms/SpringBootKeycloakAdminAPI/account/",
516 | "surrogateAuthRequired": false,
517 | "enabled": true,
518 | "alwaysDisplayInConsole": false,
519 | "clientAuthenticatorType": "client-secret",
520 | "redirectUris": [
521 | "/realms/SpringBootKeycloakAdminAPI/account/*"
522 | ],
523 | "webOrigins": [],
524 | "notBefore": 0,
525 | "bearerOnly": false,
526 | "consentRequired": false,
527 | "standardFlowEnabled": true,
528 | "implicitFlowEnabled": false,
529 | "directAccessGrantsEnabled": false,
530 | "serviceAccountsEnabled": false,
531 | "publicClient": true,
532 | "frontchannelLogout": false,
533 | "protocol": "openid-connect",
534 | "attributes": {
535 | "pkce.code.challenge.method": "S256"
536 | },
537 | "authenticationFlowBindingOverrides": {},
538 | "fullScopeAllowed": false,
539 | "nodeReRegistrationTimeout": 0,
540 | "protocolMappers": [
541 | {
542 | "id": "1b0d0fd1-899f-4d10-8418-7420d60c9cc0",
543 | "name": "audience resolve",
544 | "protocol": "openid-connect",
545 | "protocolMapper": "oidc-audience-resolve-mapper",
546 | "consentRequired": false,
547 | "config": {}
548 | }
549 | ],
550 | "defaultClientScopes": [
551 | "web-origins",
552 | "profile",
553 | "roles",
554 | "email"
555 | ],
556 | "optionalClientScopes": [
557 | "address",
558 | "phone",
559 | "offline_access",
560 | "microprofile-jwt"
561 | ]
562 | },
563 | {
564 | "id": "37f896eb-21f3-4feb-90a6-929dfab143a0",
565 | "clientId": "admin-cli",
566 | "name": "${client_admin-cli}",
567 | "surrogateAuthRequired": false,
568 | "enabled": true,
569 | "alwaysDisplayInConsole": false,
570 | "clientAuthenticatorType": "client-secret",
571 | "redirectUris": [],
572 | "webOrigins": [],
573 | "notBefore": 0,
574 | "bearerOnly": false,
575 | "consentRequired": false,
576 | "standardFlowEnabled": false,
577 | "implicitFlowEnabled": false,
578 | "directAccessGrantsEnabled": true,
579 | "serviceAccountsEnabled": false,
580 | "publicClient": true,
581 | "frontchannelLogout": false,
582 | "protocol": "openid-connect",
583 | "attributes": {},
584 | "authenticationFlowBindingOverrides": {},
585 | "fullScopeAllowed": false,
586 | "nodeReRegistrationTimeout": 0,
587 | "defaultClientScopes": [
588 | "web-origins",
589 | "profile",
590 | "roles",
591 | "email"
592 | ],
593 | "optionalClientScopes": [
594 | "address",
595 | "phone",
596 | "offline_access",
597 | "microprofile-jwt"
598 | ]
599 | },
600 | {
601 | "id": "54abba39-84ab-4d37-87c9-864dda16f7ee",
602 | "clientId": "broker",
603 | "name": "${client_broker}",
604 | "surrogateAuthRequired": false,
605 | "enabled": true,
606 | "alwaysDisplayInConsole": false,
607 | "clientAuthenticatorType": "client-secret",
608 | "redirectUris": [],
609 | "webOrigins": [],
610 | "notBefore": 0,
611 | "bearerOnly": true,
612 | "consentRequired": false,
613 | "standardFlowEnabled": true,
614 | "implicitFlowEnabled": false,
615 | "directAccessGrantsEnabled": false,
616 | "serviceAccountsEnabled": false,
617 | "publicClient": false,
618 | "frontchannelLogout": false,
619 | "protocol": "openid-connect",
620 | "attributes": {},
621 | "authenticationFlowBindingOverrides": {},
622 | "fullScopeAllowed": false,
623 | "nodeReRegistrationTimeout": 0,
624 | "defaultClientScopes": [
625 | "web-origins",
626 | "profile",
627 | "roles",
628 | "email"
629 | ],
630 | "optionalClientScopes": [
631 | "address",
632 | "phone",
633 | "offline_access",
634 | "microprofile-jwt"
635 | ]
636 | },
637 | {
638 | "id": "1b024c36-0193-4c5b-8030-b9536db34fdf",
639 | "clientId": "realm-management",
640 | "name": "${client_realm-management}",
641 | "surrogateAuthRequired": false,
642 | "enabled": true,
643 | "alwaysDisplayInConsole": false,
644 | "clientAuthenticatorType": "client-secret",
645 | "redirectUris": [],
646 | "webOrigins": [],
647 | "notBefore": 0,
648 | "bearerOnly": true,
649 | "consentRequired": false,
650 | "standardFlowEnabled": true,
651 | "implicitFlowEnabled": false,
652 | "directAccessGrantsEnabled": false,
653 | "serviceAccountsEnabled": false,
654 | "publicClient": false,
655 | "frontchannelLogout": false,
656 | "protocol": "openid-connect",
657 | "attributes": {},
658 | "authenticationFlowBindingOverrides": {},
659 | "fullScopeAllowed": false,
660 | "nodeReRegistrationTimeout": 0,
661 | "defaultClientScopes": [
662 | "web-origins",
663 | "profile",
664 | "roles",
665 | "email"
666 | ],
667 | "optionalClientScopes": [
668 | "address",
669 | "phone",
670 | "offline_access",
671 | "microprofile-jwt"
672 | ]
673 | },
674 | {
675 | "id": "e9dc45bc-6005-4ba8-9dde-095892d7f905",
676 | "clientId": "security-admin-console",
677 | "name": "${client_security-admin-console}",
678 | "rootUrl": "${authAdminUrl}",
679 | "baseUrl": "/admin/SpringBootKeycloakAdminAPI/console/",
680 | "surrogateAuthRequired": false,
681 | "enabled": true,
682 | "alwaysDisplayInConsole": false,
683 | "clientAuthenticatorType": "client-secret",
684 | "redirectUris": [
685 | "/admin/SpringBootKeycloakAdminAPI/console/*"
686 | ],
687 | "webOrigins": [
688 | "+"
689 | ],
690 | "notBefore": 0,
691 | "bearerOnly": false,
692 | "consentRequired": false,
693 | "standardFlowEnabled": true,
694 | "implicitFlowEnabled": false,
695 | "directAccessGrantsEnabled": false,
696 | "serviceAccountsEnabled": false,
697 | "publicClient": true,
698 | "frontchannelLogout": false,
699 | "protocol": "openid-connect",
700 | "attributes": {
701 | "pkce.code.challenge.method": "S256"
702 | },
703 | "authenticationFlowBindingOverrides": {},
704 | "fullScopeAllowed": false,
705 | "nodeReRegistrationTimeout": 0,
706 | "protocolMappers": [
707 | {
708 | "id": "9152c80c-bbae-45d6-944c-495e175f4858",
709 | "name": "locale",
710 | "protocol": "openid-connect",
711 | "protocolMapper": "oidc-usermodel-attribute-mapper",
712 | "consentRequired": false,
713 | "config": {
714 | "userinfo.token.claim": "true",
715 | "user.attribute": "locale",
716 | "id.token.claim": "true",
717 | "access.token.claim": "true",
718 | "claim.name": "locale",
719 | "jsonType.label": "String"
720 | }
721 | }
722 | ],
723 | "defaultClientScopes": [
724 | "web-origins",
725 | "profile",
726 | "roles",
727 | "email"
728 | ],
729 | "optionalClientScopes": [
730 | "address",
731 | "phone",
732 | "offline_access",
733 | "microprofile-jwt"
734 | ]
735 | }
736 | ],
737 | "clientScopes": [
738 | {
739 | "id": "1cfe6822-0f9a-4b84-a7d0-234835e8e57f",
740 | "name": "profile",
741 | "description": "OpenID Connect built-in scope: profile",
742 | "protocol": "openid-connect",
743 | "attributes": {
744 | "include.in.token.scope": "true",
745 | "display.on.consent.screen": "true",
746 | "consent.screen.text": "${profileScopeConsentText}"
747 | },
748 | "protocolMappers": [
749 | {
750 | "id": "25604eb4-7ca0-4e93-95d5-78d822dd7a5f",
751 | "name": "family name",
752 | "protocol": "openid-connect",
753 | "protocolMapper": "oidc-usermodel-property-mapper",
754 | "consentRequired": false,
755 | "config": {
756 | "userinfo.token.claim": "true",
757 | "user.attribute": "lastName",
758 | "id.token.claim": "true",
759 | "access.token.claim": "true",
760 | "claim.name": "family_name",
761 | "jsonType.label": "String"
762 | }
763 | },
764 | {
765 | "id": "21911c61-fa03-4f8a-b9ab-5f402bf955ed",
766 | "name": "picture",
767 | "protocol": "openid-connect",
768 | "protocolMapper": "oidc-usermodel-attribute-mapper",
769 | "consentRequired": false,
770 | "config": {
771 | "userinfo.token.claim": "true",
772 | "user.attribute": "picture",
773 | "id.token.claim": "true",
774 | "access.token.claim": "true",
775 | "claim.name": "picture",
776 | "jsonType.label": "String"
777 | }
778 | },
779 | {
780 | "id": "1ae44bc1-92bb-4079-9f12-d9f698e473ed",
781 | "name": "zoneinfo",
782 | "protocol": "openid-connect",
783 | "protocolMapper": "oidc-usermodel-attribute-mapper",
784 | "consentRequired": false,
785 | "config": {
786 | "userinfo.token.claim": "true",
787 | "user.attribute": "zoneinfo",
788 | "id.token.claim": "true",
789 | "access.token.claim": "true",
790 | "claim.name": "zoneinfo",
791 | "jsonType.label": "String"
792 | }
793 | },
794 | {
795 | "id": "01ac4077-4248-4dd8-a917-414fb3bb41aa",
796 | "name": "username",
797 | "protocol": "openid-connect",
798 | "protocolMapper": "oidc-usermodel-property-mapper",
799 | "consentRequired": false,
800 | "config": {
801 | "userinfo.token.claim": "true",
802 | "user.attribute": "username",
803 | "id.token.claim": "true",
804 | "access.token.claim": "true",
805 | "claim.name": "preferred_username",
806 | "jsonType.label": "String"
807 | }
808 | },
809 | {
810 | "id": "72bd716b-b73b-450a-a208-e490f1a6a27e",
811 | "name": "gender",
812 | "protocol": "openid-connect",
813 | "protocolMapper": "oidc-usermodel-attribute-mapper",
814 | "consentRequired": false,
815 | "config": {
816 | "userinfo.token.claim": "true",
817 | "user.attribute": "gender",
818 | "id.token.claim": "true",
819 | "access.token.claim": "true",
820 | "claim.name": "gender",
821 | "jsonType.label": "String"
822 | }
823 | },
824 | {
825 | "id": "9443ddae-bc7e-4824-9977-81dedf1e04f9",
826 | "name": "nickname",
827 | "protocol": "openid-connect",
828 | "protocolMapper": "oidc-usermodel-attribute-mapper",
829 | "consentRequired": false,
830 | "config": {
831 | "userinfo.token.claim": "true",
832 | "user.attribute": "nickname",
833 | "id.token.claim": "true",
834 | "access.token.claim": "true",
835 | "claim.name": "nickname",
836 | "jsonType.label": "String"
837 | }
838 | },
839 | {
840 | "id": "c83ea903-c6d2-4378-9fb1-e321577ae342",
841 | "name": "middle name",
842 | "protocol": "openid-connect",
843 | "protocolMapper": "oidc-usermodel-attribute-mapper",
844 | "consentRequired": false,
845 | "config": {
846 | "userinfo.token.claim": "true",
847 | "user.attribute": "middleName",
848 | "id.token.claim": "true",
849 | "access.token.claim": "true",
850 | "claim.name": "middle_name",
851 | "jsonType.label": "String"
852 | }
853 | },
854 | {
855 | "id": "e817c6e6-3e46-4229-af33-9c9bfa6839ad",
856 | "name": "birthdate",
857 | "protocol": "openid-connect",
858 | "protocolMapper": "oidc-usermodel-attribute-mapper",
859 | "consentRequired": false,
860 | "config": {
861 | "userinfo.token.claim": "true",
862 | "user.attribute": "birthdate",
863 | "id.token.claim": "true",
864 | "access.token.claim": "true",
865 | "claim.name": "birthdate",
866 | "jsonType.label": "String"
867 | }
868 | },
869 | {
870 | "id": "20254a9e-e935-41ea-b3fa-bb98b83a162a",
871 | "name": "website",
872 | "protocol": "openid-connect",
873 | "protocolMapper": "oidc-usermodel-attribute-mapper",
874 | "consentRequired": false,
875 | "config": {
876 | "userinfo.token.claim": "true",
877 | "user.attribute": "website",
878 | "id.token.claim": "true",
879 | "access.token.claim": "true",
880 | "claim.name": "website",
881 | "jsonType.label": "String"
882 | }
883 | },
884 | {
885 | "id": "7d8e08e0-38eb-4ff5-a799-63109cd6a65c",
886 | "name": "locale",
887 | "protocol": "openid-connect",
888 | "protocolMapper": "oidc-usermodel-attribute-mapper",
889 | "consentRequired": false,
890 | "config": {
891 | "userinfo.token.claim": "true",
892 | "user.attribute": "locale",
893 | "id.token.claim": "true",
894 | "access.token.claim": "true",
895 | "claim.name": "locale",
896 | "jsonType.label": "String"
897 | }
898 | },
899 | {
900 | "id": "f76042eb-4238-4373-9aee-71e62869adaf",
901 | "name": "given name",
902 | "protocol": "openid-connect",
903 | "protocolMapper": "oidc-usermodel-property-mapper",
904 | "consentRequired": false,
905 | "config": {
906 | "userinfo.token.claim": "true",
907 | "user.attribute": "firstName",
908 | "id.token.claim": "true",
909 | "access.token.claim": "true",
910 | "claim.name": "given_name",
911 | "jsonType.label": "String"
912 | }
913 | },
914 | {
915 | "id": "732fb9cb-0b72-434a-b74d-302d44e431d2",
916 | "name": "profile",
917 | "protocol": "openid-connect",
918 | "protocolMapper": "oidc-usermodel-attribute-mapper",
919 | "consentRequired": false,
920 | "config": {
921 | "userinfo.token.claim": "true",
922 | "user.attribute": "profile",
923 | "id.token.claim": "true",
924 | "access.token.claim": "true",
925 | "claim.name": "profile",
926 | "jsonType.label": "String"
927 | }
928 | },
929 | {
930 | "id": "0336778f-45b1-4983-a0ad-c6f5063a05f4",
931 | "name": "updated at",
932 | "protocol": "openid-connect",
933 | "protocolMapper": "oidc-usermodel-attribute-mapper",
934 | "consentRequired": false,
935 | "config": {
936 | "userinfo.token.claim": "true",
937 | "user.attribute": "updatedAt",
938 | "id.token.claim": "true",
939 | "access.token.claim": "true",
940 | "claim.name": "updated_at",
941 | "jsonType.label": "String"
942 | }
943 | },
944 | {
945 | "id": "084bb4ca-a90a-44e9-99d9-2879e4f66ef3",
946 | "name": "full name",
947 | "protocol": "openid-connect",
948 | "protocolMapper": "oidc-full-name-mapper",
949 | "consentRequired": false,
950 | "config": {
951 | "id.token.claim": "true",
952 | "access.token.claim": "true",
953 | "userinfo.token.claim": "true"
954 | }
955 | }
956 | ]
957 | },
958 | {
959 | "id": "efc9d154-322d-413c-8ba3-dd6e00989abd",
960 | "name": "offline_access",
961 | "description": "OpenID Connect built-in scope: offline_access",
962 | "protocol": "openid-connect",
963 | "attributes": {
964 | "consent.screen.text": "${offlineAccessScopeConsentText}",
965 | "display.on.consent.screen": "true"
966 | }
967 | },
968 | {
969 | "id": "344d37d1-f2be-4083-b7ab-dcd21258f844",
970 | "name": "email",
971 | "description": "OpenID Connect built-in scope: email",
972 | "protocol": "openid-connect",
973 | "attributes": {
974 | "include.in.token.scope": "true",
975 | "display.on.consent.screen": "true",
976 | "consent.screen.text": "${emailScopeConsentText}"
977 | },
978 | "protocolMappers": [
979 | {
980 | "id": "78b50680-3c3a-4b12-ba5d-2a6ab92d9a79",
981 | "name": "email",
982 | "protocol": "openid-connect",
983 | "protocolMapper": "oidc-usermodel-property-mapper",
984 | "consentRequired": false,
985 | "config": {
986 | "userinfo.token.claim": "true",
987 | "user.attribute": "email",
988 | "id.token.claim": "true",
989 | "access.token.claim": "true",
990 | "claim.name": "email",
991 | "jsonType.label": "String"
992 | }
993 | },
994 | {
995 | "id": "38affbd3-917b-43a7-accd-9e0740d4638b",
996 | "name": "email verified",
997 | "protocol": "openid-connect",
998 | "protocolMapper": "oidc-usermodel-property-mapper",
999 | "consentRequired": false,
1000 | "config": {
1001 | "userinfo.token.claim": "true",
1002 | "user.attribute": "emailVerified",
1003 | "id.token.claim": "true",
1004 | "access.token.claim": "true",
1005 | "claim.name": "email_verified",
1006 | "jsonType.label": "boolean"
1007 | }
1008 | }
1009 | ]
1010 | },
1011 | {
1012 | "id": "a49f564d-f4ca-46c5-ba24-590422b85841",
1013 | "name": "microprofile-jwt",
1014 | "description": "Microprofile - JWT built-in scope",
1015 | "protocol": "openid-connect",
1016 | "attributes": {
1017 | "include.in.token.scope": "true",
1018 | "display.on.consent.screen": "false"
1019 | },
1020 | "protocolMappers": [
1021 | {
1022 | "id": "2ee7dab1-468f-4a46-9d5c-0f8fbe43ee0d",
1023 | "name": "groups",
1024 | "protocol": "openid-connect",
1025 | "protocolMapper": "oidc-usermodel-realm-role-mapper",
1026 | "consentRequired": false,
1027 | "config": {
1028 | "multivalued": "true",
1029 | "user.attribute": "foo",
1030 | "id.token.claim": "true",
1031 | "access.token.claim": "true",
1032 | "claim.name": "groups",
1033 | "jsonType.label": "String"
1034 | }
1035 | },
1036 | {
1037 | "id": "16f51463-0aaf-4605-a234-9ce0438b273c",
1038 | "name": "upn",
1039 | "protocol": "openid-connect",
1040 | "protocolMapper": "oidc-usermodel-property-mapper",
1041 | "consentRequired": false,
1042 | "config": {
1043 | "userinfo.token.claim": "true",
1044 | "user.attribute": "username",
1045 | "id.token.claim": "true",
1046 | "access.token.claim": "true",
1047 | "claim.name": "upn",
1048 | "jsonType.label": "String"
1049 | }
1050 | }
1051 | ]
1052 | },
1053 | {
1054 | "id": "45a2426d-e87c-4c9b-9a14-085bcfd1fe0a",
1055 | "name": "web-origins",
1056 | "description": "OpenID Connect scope for add allowed web origins to the access token",
1057 | "protocol": "openid-connect",
1058 | "attributes": {
1059 | "include.in.token.scope": "false",
1060 | "display.on.consent.screen": "false",
1061 | "consent.screen.text": ""
1062 | },
1063 | "protocolMappers": [
1064 | {
1065 | "id": "09e77576-38ec-4392-9f24-2ab57b31cb04",
1066 | "name": "allowed web origins",
1067 | "protocol": "openid-connect",
1068 | "protocolMapper": "oidc-allowed-origins-mapper",
1069 | "consentRequired": false,
1070 | "config": {}
1071 | }
1072 | ]
1073 | },
1074 | {
1075 | "id": "31494e11-da14-4c9d-9026-89b359c208c6",
1076 | "name": "role_list",
1077 | "description": "SAML role list",
1078 | "protocol": "saml",
1079 | "attributes": {
1080 | "consent.screen.text": "${samlRoleListScopeConsentText}",
1081 | "display.on.consent.screen": "true"
1082 | },
1083 | "protocolMappers": [
1084 | {
1085 | "id": "0ba413b3-808b-4e8d-9319-3a7e246e2272",
1086 | "name": "role list",
1087 | "protocol": "saml",
1088 | "protocolMapper": "saml-role-list-mapper",
1089 | "consentRequired": false,
1090 | "config": {
1091 | "single": "false",
1092 | "attribute.nameformat": "Basic",
1093 | "attribute.name": "Role"
1094 | }
1095 | }
1096 | ]
1097 | },
1098 | {
1099 | "id": "67c8c6b8-2d23-40d1-b0c8-47c85a1520c0",
1100 | "name": "phone",
1101 | "description": "OpenID Connect built-in scope: phone",
1102 | "protocol": "openid-connect",
1103 | "attributes": {
1104 | "include.in.token.scope": "true",
1105 | "display.on.consent.screen": "true",
1106 | "consent.screen.text": "${phoneScopeConsentText}"
1107 | },
1108 | "protocolMappers": [
1109 | {
1110 | "id": "2a84982a-a12d-4792-87be-c7e1e3b07a93",
1111 | "name": "phone number",
1112 | "protocol": "openid-connect",
1113 | "protocolMapper": "oidc-usermodel-attribute-mapper",
1114 | "consentRequired": false,
1115 | "config": {
1116 | "userinfo.token.claim": "true",
1117 | "user.attribute": "phoneNumber",
1118 | "id.token.claim": "true",
1119 | "access.token.claim": "true",
1120 | "claim.name": "phone_number",
1121 | "jsonType.label": "String"
1122 | }
1123 | },
1124 | {
1125 | "id": "65288970-410f-48f0-9351-d8dab0888949",
1126 | "name": "phone number verified",
1127 | "protocol": "openid-connect",
1128 | "protocolMapper": "oidc-usermodel-attribute-mapper",
1129 | "consentRequired": false,
1130 | "config": {
1131 | "userinfo.token.claim": "true",
1132 | "user.attribute": "phoneNumberVerified",
1133 | "id.token.claim": "true",
1134 | "access.token.claim": "true",
1135 | "claim.name": "phone_number_verified",
1136 | "jsonType.label": "boolean"
1137 | }
1138 | }
1139 | ]
1140 | },
1141 | {
1142 | "id": "2757cf35-6d5a-4db1-ad38-e76100220e3f",
1143 | "name": "address",
1144 | "description": "OpenID Connect built-in scope: address",
1145 | "protocol": "openid-connect",
1146 | "attributes": {
1147 | "include.in.token.scope": "true",
1148 | "display.on.consent.screen": "true",
1149 | "consent.screen.text": "${addressScopeConsentText}"
1150 | },
1151 | "protocolMappers": [
1152 | {
1153 | "id": "cf7b49cd-7c34-460b-b533-c0e7d5438a5b",
1154 | "name": "address",
1155 | "protocol": "openid-connect",
1156 | "protocolMapper": "oidc-address-mapper",
1157 | "consentRequired": false,
1158 | "config": {
1159 | "user.attribute.formatted": "formatted",
1160 | "user.attribute.country": "country",
1161 | "user.attribute.postal_code": "postal_code",
1162 | "userinfo.token.claim": "true",
1163 | "user.attribute.street": "street",
1164 | "id.token.claim": "true",
1165 | "user.attribute.region": "region",
1166 | "access.token.claim": "true",
1167 | "user.attribute.locality": "locality"
1168 | }
1169 | }
1170 | ]
1171 | },
1172 | {
1173 | "id": "340f7c94-a1fd-41a5-8b94-1e683ea87075",
1174 | "name": "roles",
1175 | "description": "OpenID Connect scope for add user roles to the access token",
1176 | "protocol": "openid-connect",
1177 | "attributes": {
1178 | "include.in.token.scope": "false",
1179 | "display.on.consent.screen": "true",
1180 | "consent.screen.text": "${rolesScopeConsentText}"
1181 | },
1182 | "protocolMappers": [
1183 | {
1184 | "id": "cc98eaaf-c097-4ce5-92a2-b7323c9e63ec",
1185 | "name": "realm roles",
1186 | "protocol": "openid-connect",
1187 | "protocolMapper": "oidc-usermodel-realm-role-mapper",
1188 | "consentRequired": false,
1189 | "config": {
1190 | "user.attribute": "foo",
1191 | "access.token.claim": "true",
1192 | "claim.name": "realm_access.roles",
1193 | "jsonType.label": "String",
1194 | "multivalued": "true"
1195 | }
1196 | },
1197 | {
1198 | "id": "b8b94531-9519-45e2-a04c-0cb24bd6ee3d",
1199 | "name": "audience resolve",
1200 | "protocol": "openid-connect",
1201 | "protocolMapper": "oidc-audience-resolve-mapper",
1202 | "consentRequired": false,
1203 | "config": {}
1204 | },
1205 | {
1206 | "id": "c1a269dc-1dbd-4d50-b34f-610cfc3f2713",
1207 | "name": "client roles",
1208 | "protocol": "openid-connect",
1209 | "protocolMapper": "oidc-usermodel-client-role-mapper",
1210 | "consentRequired": false,
1211 | "config": {
1212 | "user.attribute": "foo",
1213 | "access.token.claim": "true",
1214 | "claim.name": "resource_access.${client_id}.roles",
1215 | "jsonType.label": "String",
1216 | "multivalued": "true"
1217 | }
1218 | }
1219 | ]
1220 | }
1221 | ],
1222 | "defaultDefaultClientScopes": [
1223 | "role_list",
1224 | "profile",
1225 | "email",
1226 | "roles",
1227 | "web-origins"
1228 | ],
1229 | "defaultOptionalClientScopes": [
1230 | "offline_access",
1231 | "address",
1232 | "phone",
1233 | "microprofile-jwt"
1234 | ],
1235 | "browserSecurityHeaders": {
1236 | "contentSecurityPolicyReportOnly": "",
1237 | "xContentTypeOptions": "nosniff",
1238 | "xRobotsTag": "none",
1239 | "xFrameOptions": "SAMEORIGIN",
1240 | "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';",
1241 | "xXSSProtection": "1; mode=block",
1242 | "strictTransportSecurity": "max-age=31536000; includeSubDomains"
1243 | },
1244 | "smtpServer": {},
1245 | "eventsEnabled": false,
1246 | "eventsListeners": [
1247 | "jboss-logging"
1248 | ],
1249 | "enabledEventTypes": [],
1250 | "adminEventsEnabled": false,
1251 | "adminEventsDetailsEnabled": false,
1252 | "identityProviders": [],
1253 | "identityProviderMappers": [],
1254 | "components": {
1255 | "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [
1256 | {
1257 | "id": "ef0b4c72-1b3b-4760-9e61-a1786f51fcb0",
1258 | "name": "Consent Required",
1259 | "providerId": "consent-required",
1260 | "subType": "anonymous",
1261 | "subComponents": {},
1262 | "config": {}
1263 | },
1264 | {
1265 | "id": "13c56126-c0d7-485e-b89a-0cd3f95e6da2",
1266 | "name": "Allowed Protocol Mapper Types",
1267 | "providerId": "allowed-protocol-mappers",
1268 | "subType": "authenticated",
1269 | "subComponents": {},
1270 | "config": {
1271 | "allowed-protocol-mapper-types": [
1272 | "oidc-usermodel-attribute-mapper",
1273 | "oidc-sha256-pairwise-sub-mapper",
1274 | "saml-user-property-mapper",
1275 | "saml-role-list-mapper",
1276 | "oidc-usermodel-property-mapper",
1277 | "oidc-address-mapper",
1278 | "oidc-full-name-mapper",
1279 | "saml-user-attribute-mapper"
1280 | ]
1281 | }
1282 | },
1283 | {
1284 | "id": "48454321-5206-4226-92b8-a853dd74de73",
1285 | "name": "Max Clients Limit",
1286 | "providerId": "max-clients",
1287 | "subType": "anonymous",
1288 | "subComponents": {},
1289 | "config": {
1290 | "max-clients": [
1291 | "200"
1292 | ]
1293 | }
1294 | },
1295 | {
1296 | "id": "462581b7-c9fb-4ac8-bf49-96ee244c8760",
1297 | "name": "Trusted Hosts",
1298 | "providerId": "trusted-hosts",
1299 | "subType": "anonymous",
1300 | "subComponents": {},
1301 | "config": {
1302 | "host-sending-registration-request-must-match": [
1303 | "true"
1304 | ],
1305 | "client-uris-must-match": [
1306 | "true"
1307 | ]
1308 | }
1309 | },
1310 | {
1311 | "id": "02baa388-ebbf-453a-8dd3-4634d70f9772",
1312 | "name": "Allowed Client Scopes",
1313 | "providerId": "allowed-client-templates",
1314 | "subType": "anonymous",
1315 | "subComponents": {},
1316 | "config": {
1317 | "allow-default-scopes": [
1318 | "true"
1319 | ]
1320 | }
1321 | },
1322 | {
1323 | "id": "b5a0c9b2-0863-4c29-aefd-8c6f9a753bd8",
1324 | "name": "Allowed Client Scopes",
1325 | "providerId": "allowed-client-templates",
1326 | "subType": "authenticated",
1327 | "subComponents": {},
1328 | "config": {
1329 | "allow-default-scopes": [
1330 | "true"
1331 | ]
1332 | }
1333 | },
1334 | {
1335 | "id": "8b7ec3ff-e741-475e-8fc0-e49a83b8e233",
1336 | "name": "Full Scope Disabled",
1337 | "providerId": "scope",
1338 | "subType": "anonymous",
1339 | "subComponents": {},
1340 | "config": {}
1341 | },
1342 | {
1343 | "id": "d2d65562-9d67-4ca0-ba3f-9e0cd2dc77fb",
1344 | "name": "Allowed Protocol Mapper Types",
1345 | "providerId": "allowed-protocol-mappers",
1346 | "subType": "anonymous",
1347 | "subComponents": {},
1348 | "config": {
1349 | "allowed-protocol-mapper-types": [
1350 | "oidc-usermodel-property-mapper",
1351 | "oidc-full-name-mapper",
1352 | "saml-user-attribute-mapper",
1353 | "oidc-address-mapper",
1354 | "oidc-usermodel-attribute-mapper",
1355 | "oidc-sha256-pairwise-sub-mapper",
1356 | "saml-user-property-mapper",
1357 | "saml-role-list-mapper"
1358 | ]
1359 | }
1360 | }
1361 | ],
1362 | "org.keycloak.keys.KeyProvider": [
1363 | {
1364 | "id": "bc3a36ef-db95-4432-ba5d-9a808efb4123",
1365 | "name": "rsa-enc-generated",
1366 | "providerId": "rsa-enc-generated",
1367 | "subComponents": {},
1368 | "config": {
1369 | "priority": [
1370 | "100"
1371 | ],
1372 | "algorithm": [
1373 | "RSA-OAEP"
1374 | ]
1375 | }
1376 | },
1377 | {
1378 | "id": "9c3e4d64-d3e1-41bd-93cb-65db843afec7",
1379 | "name": "hmac-generated",
1380 | "providerId": "hmac-generated",
1381 | "subComponents": {},
1382 | "config": {
1383 | "priority": [
1384 | "100"
1385 | ],
1386 | "algorithm": [
1387 | "HS256"
1388 | ]
1389 | }
1390 | },
1391 | {
1392 | "id": "f70cb07b-0f32-4c43-96cd-d3fc478ced79",
1393 | "name": "aes-generated",
1394 | "providerId": "aes-generated",
1395 | "subComponents": {},
1396 | "config": {
1397 | "priority": [
1398 | "100"
1399 | ]
1400 | }
1401 | },
1402 | {
1403 | "id": "ce037ab8-2450-4a26-9cf4-325a847ba492",
1404 | "name": "rsa-generated",
1405 | "providerId": "rsa-generated",
1406 | "subComponents": {},
1407 | "config": {
1408 | "priority": [
1409 | "100"
1410 | ]
1411 | }
1412 | }
1413 | ]
1414 | },
1415 | "internationalizationEnabled": false,
1416 | "supportedLocales": [],
1417 | "authenticationFlows": [
1418 | {
1419 | "id": "8ad484e3-d780-43b1-9f66-629730777562",
1420 | "alias": "Account verification options",
1421 | "description": "Method with which to verity the existing account",
1422 | "providerId": "basic-flow",
1423 | "topLevel": false,
1424 | "builtIn": true,
1425 | "authenticationExecutions": [
1426 | {
1427 | "authenticator": "idp-email-verification",
1428 | "authenticatorFlow": false,
1429 | "requirement": "ALTERNATIVE",
1430 | "priority": 10,
1431 | "userSetupAllowed": false,
1432 | "autheticatorFlow": false
1433 | },
1434 | {
1435 | "authenticatorFlow": true,
1436 | "requirement": "ALTERNATIVE",
1437 | "priority": 20,
1438 | "flowAlias": "Verify Existing Account by Re-authentication",
1439 | "userSetupAllowed": false,
1440 | "autheticatorFlow": true
1441 | }
1442 | ]
1443 | },
1444 | {
1445 | "id": "d7879e81-99a8-4187-bbf6-22b8fa3b0f30",
1446 | "alias": "Authentication Options",
1447 | "description": "Authentication options.",
1448 | "providerId": "basic-flow",
1449 | "topLevel": false,
1450 | "builtIn": true,
1451 | "authenticationExecutions": [
1452 | {
1453 | "authenticator": "basic-auth",
1454 | "authenticatorFlow": false,
1455 | "requirement": "REQUIRED",
1456 | "priority": 10,
1457 | "userSetupAllowed": false,
1458 | "autheticatorFlow": false
1459 | },
1460 | {
1461 | "authenticator": "basic-auth-otp",
1462 | "authenticatorFlow": false,
1463 | "requirement": "DISABLED",
1464 | "priority": 20,
1465 | "userSetupAllowed": false,
1466 | "autheticatorFlow": false
1467 | },
1468 | {
1469 | "authenticator": "auth-spnego",
1470 | "authenticatorFlow": false,
1471 | "requirement": "DISABLED",
1472 | "priority": 30,
1473 | "userSetupAllowed": false,
1474 | "autheticatorFlow": false
1475 | }
1476 | ]
1477 | },
1478 | {
1479 | "id": "d2e179fb-3004-4402-9623-fb41b27fd05a",
1480 | "alias": "Browser - Conditional OTP",
1481 | "description": "Flow to determine if the OTP is required for the authentication",
1482 | "providerId": "basic-flow",
1483 | "topLevel": false,
1484 | "builtIn": true,
1485 | "authenticationExecutions": [
1486 | {
1487 | "authenticator": "conditional-user-configured",
1488 | "authenticatorFlow": false,
1489 | "requirement": "REQUIRED",
1490 | "priority": 10,
1491 | "userSetupAllowed": false,
1492 | "autheticatorFlow": false
1493 | },
1494 | {
1495 | "authenticator": "auth-otp-form",
1496 | "authenticatorFlow": false,
1497 | "requirement": "REQUIRED",
1498 | "priority": 20,
1499 | "userSetupAllowed": false,
1500 | "autheticatorFlow": false
1501 | }
1502 | ]
1503 | },
1504 | {
1505 | "id": "b06a5a36-6183-4e5e-8f08-f047bf556b90",
1506 | "alias": "Direct Grant - Conditional OTP",
1507 | "description": "Flow to determine if the OTP is required for the authentication",
1508 | "providerId": "basic-flow",
1509 | "topLevel": false,
1510 | "builtIn": true,
1511 | "authenticationExecutions": [
1512 | {
1513 | "authenticator": "conditional-user-configured",
1514 | "authenticatorFlow": false,
1515 | "requirement": "REQUIRED",
1516 | "priority": 10,
1517 | "userSetupAllowed": false,
1518 | "autheticatorFlow": false
1519 | },
1520 | {
1521 | "authenticator": "direct-grant-validate-otp",
1522 | "authenticatorFlow": false,
1523 | "requirement": "REQUIRED",
1524 | "priority": 20,
1525 | "userSetupAllowed": false,
1526 | "autheticatorFlow": false
1527 | }
1528 | ]
1529 | },
1530 | {
1531 | "id": "9018f050-7e08-4800-b7fd-6f3f29ac559b",
1532 | "alias": "First broker login - Conditional OTP",
1533 | "description": "Flow to determine if the OTP is required for the authentication",
1534 | "providerId": "basic-flow",
1535 | "topLevel": false,
1536 | "builtIn": true,
1537 | "authenticationExecutions": [
1538 | {
1539 | "authenticator": "conditional-user-configured",
1540 | "authenticatorFlow": false,
1541 | "requirement": "REQUIRED",
1542 | "priority": 10,
1543 | "userSetupAllowed": false,
1544 | "autheticatorFlow": false
1545 | },
1546 | {
1547 | "authenticator": "auth-otp-form",
1548 | "authenticatorFlow": false,
1549 | "requirement": "REQUIRED",
1550 | "priority": 20,
1551 | "userSetupAllowed": false,
1552 | "autheticatorFlow": false
1553 | }
1554 | ]
1555 | },
1556 | {
1557 | "id": "2ff609eb-63b3-419e-a9f2-2d9d7a6a5f2a",
1558 | "alias": "Handle Existing Account",
1559 | "description": "Handle what to do if there is existing account with same email/username like authenticated identity provider",
1560 | "providerId": "basic-flow",
1561 | "topLevel": false,
1562 | "builtIn": true,
1563 | "authenticationExecutions": [
1564 | {
1565 | "authenticator": "idp-confirm-link",
1566 | "authenticatorFlow": false,
1567 | "requirement": "REQUIRED",
1568 | "priority": 10,
1569 | "userSetupAllowed": false,
1570 | "autheticatorFlow": false
1571 | },
1572 | {
1573 | "authenticatorFlow": true,
1574 | "requirement": "REQUIRED",
1575 | "priority": 20,
1576 | "flowAlias": "Account verification options",
1577 | "userSetupAllowed": false,
1578 | "autheticatorFlow": true
1579 | }
1580 | ]
1581 | },
1582 | {
1583 | "id": "177d0497-fb58-4f74-ba5c-4bf162df682f",
1584 | "alias": "Reset - Conditional OTP",
1585 | "description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.",
1586 | "providerId": "basic-flow",
1587 | "topLevel": false,
1588 | "builtIn": true,
1589 | "authenticationExecutions": [
1590 | {
1591 | "authenticator": "conditional-user-configured",
1592 | "authenticatorFlow": false,
1593 | "requirement": "REQUIRED",
1594 | "priority": 10,
1595 | "userSetupAllowed": false,
1596 | "autheticatorFlow": false
1597 | },
1598 | {
1599 | "authenticator": "reset-otp",
1600 | "authenticatorFlow": false,
1601 | "requirement": "REQUIRED",
1602 | "priority": 20,
1603 | "userSetupAllowed": false,
1604 | "autheticatorFlow": false
1605 | }
1606 | ]
1607 | },
1608 | {
1609 | "id": "daf0f8c6-48fb-4a41-a7ca-a28d70feefc7",
1610 | "alias": "User creation or linking",
1611 | "description": "Flow for the existing/non-existing user alternatives",
1612 | "providerId": "basic-flow",
1613 | "topLevel": false,
1614 | "builtIn": true,
1615 | "authenticationExecutions": [
1616 | {
1617 | "authenticatorConfig": "create unique user config",
1618 | "authenticator": "idp-create-user-if-unique",
1619 | "authenticatorFlow": false,
1620 | "requirement": "ALTERNATIVE",
1621 | "priority": 10,
1622 | "userSetupAllowed": false,
1623 | "autheticatorFlow": false
1624 | },
1625 | {
1626 | "authenticatorFlow": true,
1627 | "requirement": "ALTERNATIVE",
1628 | "priority": 20,
1629 | "flowAlias": "Handle Existing Account",
1630 | "userSetupAllowed": false,
1631 | "autheticatorFlow": true
1632 | }
1633 | ]
1634 | },
1635 | {
1636 | "id": "0231915c-3a12-4b8f-a389-3ce58a434f50",
1637 | "alias": "Verify Existing Account by Re-authentication",
1638 | "description": "Reauthentication of existing account",
1639 | "providerId": "basic-flow",
1640 | "topLevel": false,
1641 | "builtIn": true,
1642 | "authenticationExecutions": [
1643 | {
1644 | "authenticator": "idp-username-password-form",
1645 | "authenticatorFlow": false,
1646 | "requirement": "REQUIRED",
1647 | "priority": 10,
1648 | "userSetupAllowed": false,
1649 | "autheticatorFlow": false
1650 | },
1651 | {
1652 | "authenticatorFlow": true,
1653 | "requirement": "CONDITIONAL",
1654 | "priority": 20,
1655 | "flowAlias": "First broker login - Conditional OTP",
1656 | "userSetupAllowed": false,
1657 | "autheticatorFlow": true
1658 | }
1659 | ]
1660 | },
1661 | {
1662 | "id": "a37718d5-0345-4b94-9be5-1fe1ef7caee6",
1663 | "alias": "browser",
1664 | "description": "browser based authentication",
1665 | "providerId": "basic-flow",
1666 | "topLevel": true,
1667 | "builtIn": true,
1668 | "authenticationExecutions": [
1669 | {
1670 | "authenticator": "auth-cookie",
1671 | "authenticatorFlow": false,
1672 | "requirement": "ALTERNATIVE",
1673 | "priority": 10,
1674 | "userSetupAllowed": false,
1675 | "autheticatorFlow": false
1676 | },
1677 | {
1678 | "authenticator": "auth-spnego",
1679 | "authenticatorFlow": false,
1680 | "requirement": "DISABLED",
1681 | "priority": 20,
1682 | "userSetupAllowed": false,
1683 | "autheticatorFlow": false
1684 | },
1685 | {
1686 | "authenticator": "identity-provider-redirector",
1687 | "authenticatorFlow": false,
1688 | "requirement": "ALTERNATIVE",
1689 | "priority": 25,
1690 | "userSetupAllowed": false,
1691 | "autheticatorFlow": false
1692 | },
1693 | {
1694 | "authenticatorFlow": true,
1695 | "requirement": "ALTERNATIVE",
1696 | "priority": 30,
1697 | "flowAlias": "forms",
1698 | "userSetupAllowed": false,
1699 | "autheticatorFlow": true
1700 | }
1701 | ]
1702 | },
1703 | {
1704 | "id": "e1fdeb97-a91c-4b4e-82a3-0a67cbb722f7",
1705 | "alias": "clients",
1706 | "description": "Base authentication for clients",
1707 | "providerId": "client-flow",
1708 | "topLevel": true,
1709 | "builtIn": true,
1710 | "authenticationExecutions": [
1711 | {
1712 | "authenticator": "client-secret",
1713 | "authenticatorFlow": false,
1714 | "requirement": "ALTERNATIVE",
1715 | "priority": 10,
1716 | "userSetupAllowed": false,
1717 | "autheticatorFlow": false
1718 | },
1719 | {
1720 | "authenticator": "client-jwt",
1721 | "authenticatorFlow": false,
1722 | "requirement": "ALTERNATIVE",
1723 | "priority": 20,
1724 | "userSetupAllowed": false,
1725 | "autheticatorFlow": false
1726 | },
1727 | {
1728 | "authenticator": "client-secret-jwt",
1729 | "authenticatorFlow": false,
1730 | "requirement": "ALTERNATIVE",
1731 | "priority": 30,
1732 | "userSetupAllowed": false,
1733 | "autheticatorFlow": false
1734 | },
1735 | {
1736 | "authenticator": "client-x509",
1737 | "authenticatorFlow": false,
1738 | "requirement": "ALTERNATIVE",
1739 | "priority": 40,
1740 | "userSetupAllowed": false,
1741 | "autheticatorFlow": false
1742 | }
1743 | ]
1744 | },
1745 | {
1746 | "id": "93625cc8-4064-475a-a470-677a91c94a99",
1747 | "alias": "direct grant",
1748 | "description": "OpenID Connect Resource Owner Grant",
1749 | "providerId": "basic-flow",
1750 | "topLevel": true,
1751 | "builtIn": true,
1752 | "authenticationExecutions": [
1753 | {
1754 | "authenticator": "direct-grant-validate-username",
1755 | "authenticatorFlow": false,
1756 | "requirement": "REQUIRED",
1757 | "priority": 10,
1758 | "userSetupAllowed": false,
1759 | "autheticatorFlow": false
1760 | },
1761 | {
1762 | "authenticator": "direct-grant-validate-password",
1763 | "authenticatorFlow": false,
1764 | "requirement": "REQUIRED",
1765 | "priority": 20,
1766 | "userSetupAllowed": false,
1767 | "autheticatorFlow": false
1768 | },
1769 | {
1770 | "authenticatorFlow": true,
1771 | "requirement": "CONDITIONAL",
1772 | "priority": 30,
1773 | "flowAlias": "Direct Grant - Conditional OTP",
1774 | "userSetupAllowed": false,
1775 | "autheticatorFlow": true
1776 | }
1777 | ]
1778 | },
1779 | {
1780 | "id": "01533acd-0c26-439e-84b7-deb5638fc9ad",
1781 | "alias": "docker auth",
1782 | "description": "Used by Docker clients to authenticate against the IDP",
1783 | "providerId": "basic-flow",
1784 | "topLevel": true,
1785 | "builtIn": true,
1786 | "authenticationExecutions": [
1787 | {
1788 | "authenticator": "docker-http-basic-authenticator",
1789 | "authenticatorFlow": false,
1790 | "requirement": "REQUIRED",
1791 | "priority": 10,
1792 | "userSetupAllowed": false,
1793 | "autheticatorFlow": false
1794 | }
1795 | ]
1796 | },
1797 | {
1798 | "id": "143e5450-6e74-48e1-9240-66a99e68a09f",
1799 | "alias": "first broker login",
1800 | "description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account",
1801 | "providerId": "basic-flow",
1802 | "topLevel": true,
1803 | "builtIn": true,
1804 | "authenticationExecutions": [
1805 | {
1806 | "authenticatorConfig": "review profile config",
1807 | "authenticator": "idp-review-profile",
1808 | "authenticatorFlow": false,
1809 | "requirement": "REQUIRED",
1810 | "priority": 10,
1811 | "userSetupAllowed": false,
1812 | "autheticatorFlow": false
1813 | },
1814 | {
1815 | "authenticatorFlow": true,
1816 | "requirement": "REQUIRED",
1817 | "priority": 20,
1818 | "flowAlias": "User creation or linking",
1819 | "userSetupAllowed": false,
1820 | "autheticatorFlow": true
1821 | }
1822 | ]
1823 | },
1824 | {
1825 | "id": "d16ff004-a2b4-44e4-a07e-9f8411b5686e",
1826 | "alias": "forms",
1827 | "description": "Username, password, otp and other auth forms.",
1828 | "providerId": "basic-flow",
1829 | "topLevel": false,
1830 | "builtIn": true,
1831 | "authenticationExecutions": [
1832 | {
1833 | "authenticator": "auth-username-password-form",
1834 | "authenticatorFlow": false,
1835 | "requirement": "REQUIRED",
1836 | "priority": 10,
1837 | "userSetupAllowed": false,
1838 | "autheticatorFlow": false
1839 | },
1840 | {
1841 | "authenticatorFlow": true,
1842 | "requirement": "CONDITIONAL",
1843 | "priority": 20,
1844 | "flowAlias": "Browser - Conditional OTP",
1845 | "userSetupAllowed": false,
1846 | "autheticatorFlow": true
1847 | }
1848 | ]
1849 | },
1850 | {
1851 | "id": "7ae94347-b36b-41a1-b97d-1e0577a60234",
1852 | "alias": "http challenge",
1853 | "description": "An authentication flow based on challenge-response HTTP Authentication Schemes",
1854 | "providerId": "basic-flow",
1855 | "topLevel": true,
1856 | "builtIn": true,
1857 | "authenticationExecutions": [
1858 | {
1859 | "authenticator": "no-cookie-redirect",
1860 | "authenticatorFlow": false,
1861 | "requirement": "REQUIRED",
1862 | "priority": 10,
1863 | "userSetupAllowed": false,
1864 | "autheticatorFlow": false
1865 | },
1866 | {
1867 | "authenticatorFlow": true,
1868 | "requirement": "REQUIRED",
1869 | "priority": 20,
1870 | "flowAlias": "Authentication Options",
1871 | "userSetupAllowed": false,
1872 | "autheticatorFlow": true
1873 | }
1874 | ]
1875 | },
1876 | {
1877 | "id": "4b198fe2-be73-4c84-84e5-3ae52136d03d",
1878 | "alias": "registration",
1879 | "description": "registration flow",
1880 | "providerId": "basic-flow",
1881 | "topLevel": true,
1882 | "builtIn": true,
1883 | "authenticationExecutions": [
1884 | {
1885 | "authenticator": "registration-page-form",
1886 | "authenticatorFlow": true,
1887 | "requirement": "REQUIRED",
1888 | "priority": 10,
1889 | "flowAlias": "registration form",
1890 | "userSetupAllowed": false,
1891 | "autheticatorFlow": true
1892 | }
1893 | ]
1894 | },
1895 | {
1896 | "id": "9a246b44-8a6d-42a0-8db0-f6f39c6ec094",
1897 | "alias": "registration form",
1898 | "description": "registration form",
1899 | "providerId": "form-flow",
1900 | "topLevel": false,
1901 | "builtIn": true,
1902 | "authenticationExecutions": [
1903 | {
1904 | "authenticator": "registration-user-creation",
1905 | "authenticatorFlow": false,
1906 | "requirement": "REQUIRED",
1907 | "priority": 20,
1908 | "userSetupAllowed": false,
1909 | "autheticatorFlow": false
1910 | },
1911 | {
1912 | "authenticator": "registration-profile-action",
1913 | "authenticatorFlow": false,
1914 | "requirement": "REQUIRED",
1915 | "priority": 40,
1916 | "userSetupAllowed": false,
1917 | "autheticatorFlow": false
1918 | },
1919 | {
1920 | "authenticator": "registration-password-action",
1921 | "authenticatorFlow": false,
1922 | "requirement": "REQUIRED",
1923 | "priority": 50,
1924 | "userSetupAllowed": false,
1925 | "autheticatorFlow": false
1926 | },
1927 | {
1928 | "authenticator": "registration-recaptcha-action",
1929 | "authenticatorFlow": false,
1930 | "requirement": "DISABLED",
1931 | "priority": 60,
1932 | "userSetupAllowed": false,
1933 | "autheticatorFlow": false
1934 | }
1935 | ]
1936 | },
1937 | {
1938 | "id": "df7c6398-4bca-4098-a143-9941a2600cad",
1939 | "alias": "reset credentials",
1940 | "description": "Reset credentials for a user if they forgot their password or something",
1941 | "providerId": "basic-flow",
1942 | "topLevel": true,
1943 | "builtIn": true,
1944 | "authenticationExecutions": [
1945 | {
1946 | "authenticator": "reset-credentials-choose-user",
1947 | "authenticatorFlow": false,
1948 | "requirement": "REQUIRED",
1949 | "priority": 10,
1950 | "userSetupAllowed": false,
1951 | "autheticatorFlow": false
1952 | },
1953 | {
1954 | "authenticator": "reset-credential-email",
1955 | "authenticatorFlow": false,
1956 | "requirement": "REQUIRED",
1957 | "priority": 20,
1958 | "userSetupAllowed": false,
1959 | "autheticatorFlow": false
1960 | },
1961 | {
1962 | "authenticator": "reset-password",
1963 | "authenticatorFlow": false,
1964 | "requirement": "REQUIRED",
1965 | "priority": 30,
1966 | "userSetupAllowed": false,
1967 | "autheticatorFlow": false
1968 | },
1969 | {
1970 | "authenticatorFlow": true,
1971 | "requirement": "CONDITIONAL",
1972 | "priority": 40,
1973 | "flowAlias": "Reset - Conditional OTP",
1974 | "userSetupAllowed": false,
1975 | "autheticatorFlow": true
1976 | }
1977 | ]
1978 | },
1979 | {
1980 | "id": "894e681c-4e69-40d0-889e-c654b2253679",
1981 | "alias": "saml ecp",
1982 | "description": "SAML ECP Profile Authentication Flow",
1983 | "providerId": "basic-flow",
1984 | "topLevel": true,
1985 | "builtIn": true,
1986 | "authenticationExecutions": [
1987 | {
1988 | "authenticator": "http-basic-authenticator",
1989 | "authenticatorFlow": false,
1990 | "requirement": "REQUIRED",
1991 | "priority": 10,
1992 | "userSetupAllowed": false,
1993 | "autheticatorFlow": false
1994 | }
1995 | ]
1996 | }
1997 | ],
1998 | "authenticatorConfig": [
1999 | {
2000 | "id": "d7e1544b-2a79-49e1-85ce-db56ba7fd683",
2001 | "alias": "create unique user config",
2002 | "config": {
2003 | "require.password.update.after.registration": "false"
2004 | }
2005 | },
2006 | {
2007 | "id": "748c904d-4ad2-4126-838c-4e44a2c9b263",
2008 | "alias": "review profile config",
2009 | "config": {
2010 | "update.profile.on.first.login": "missing"
2011 | }
2012 | }
2013 | ],
2014 | "requiredActions": [
2015 | {
2016 | "alias": "CONFIGURE_TOTP",
2017 | "name": "Configure OTP",
2018 | "providerId": "CONFIGURE_TOTP",
2019 | "enabled": true,
2020 | "defaultAction": false,
2021 | "priority": 10,
2022 | "config": {}
2023 | },
2024 | {
2025 | "alias": "terms_and_conditions",
2026 | "name": "Terms and Conditions",
2027 | "providerId": "terms_and_conditions",
2028 | "enabled": false,
2029 | "defaultAction": false,
2030 | "priority": 20,
2031 | "config": {}
2032 | },
2033 | {
2034 | "alias": "UPDATE_PASSWORD",
2035 | "name": "Update Password",
2036 | "providerId": "UPDATE_PASSWORD",
2037 | "enabled": true,
2038 | "defaultAction": false,
2039 | "priority": 30,
2040 | "config": {}
2041 | },
2042 | {
2043 | "alias": "UPDATE_PROFILE",
2044 | "name": "Update Profile",
2045 | "providerId": "UPDATE_PROFILE",
2046 | "enabled": true,
2047 | "defaultAction": false,
2048 | "priority": 40,
2049 | "config": {}
2050 | },
2051 | {
2052 | "alias": "VERIFY_EMAIL",
2053 | "name": "Verify Email",
2054 | "providerId": "VERIFY_EMAIL",
2055 | "enabled": true,
2056 | "defaultAction": false,
2057 | "priority": 50,
2058 | "config": {}
2059 | },
2060 | {
2061 | "alias": "delete_account",
2062 | "name": "Delete Account",
2063 | "providerId": "delete_account",
2064 | "enabled": false,
2065 | "defaultAction": false,
2066 | "priority": 60,
2067 | "config": {}
2068 | },
2069 | {
2070 | "alias": "update_user_locale",
2071 | "name": "Update User Locale",
2072 | "providerId": "update_user_locale",
2073 | "enabled": true,
2074 | "defaultAction": false,
2075 | "priority": 1000,
2076 | "config": {}
2077 | }
2078 | ],
2079 | "browserFlow": "browser",
2080 | "registrationFlow": "registration",
2081 | "directGrantFlow": "direct grant",
2082 | "resetCredentialsFlow": "reset credentials",
2083 | "clientAuthenticationFlow": "clients",
2084 | "dockerAuthenticationFlow": "docker auth",
2085 | "attributes": {
2086 | "cibaBackchannelTokenDeliveryMode": "poll",
2087 | "cibaExpiresIn": "120",
2088 | "cibaAuthRequestedUserHint": "login_hint",
2089 | "oauth2DeviceCodeLifespan": "600",
2090 | "oauth2DevicePollingInterval": "5",
2091 | "parRequestUriLifespan": "60",
2092 | "cibaInterval": "5"
2093 | },
2094 | "keycloakVersion": "16.1.1",
2095 | "userManagedAccessAllowed": false,
2096 | "clientProfiles": {
2097 | "profiles": []
2098 | },
2099 | "clientPolicies": {
2100 | "policies": []
2101 | }
2102 | }
--------------------------------------------------------------------------------
/src/test/java/com/example/springbootkeycloakadminapi/ApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.springbootkeycloakadminapi;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class ApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------