├── .mvn └── wrapper │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── src └── main │ ├── resources │ ├── templates │ │ ├── app.html │ │ ├── admin.html │ │ └── index.html │ └── application.yml │ └── java │ └── demo │ └── SpringBoot2App.java ├── .gitignore ├── readme.md ├── pom.xml ├── mvnw.cmd ├── mvnw └── demo-realm.json /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thomasdarimont/spring-boot-2-keycloak-oauth-example/HEAD/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.2/apache-maven-3.5.2-bin.zip 2 | -------------------------------------------------------------------------------- /src/main/resources/templates/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | App 5 | 6 | 7 |

My cool App

8 |
9 |

Current User

10 |
11 | Home 12 | 13 | -------------------------------------------------------------------------------- /src/main/resources/templates/admin.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Admin Area 5 | 6 | 7 |

My cool App (Admin)

8 |
9 |

Current User

10 |
11 | Home 12 | 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ -------------------------------------------------------------------------------- /src/main/resources/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | Demo App 7 | 8 | 9 | 15 | 16 |
17 | 19 | 20 | 21 |
22 | 23 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # PoC for Spring Boot 2 + Spring Security 5 + Keycloak 3.4.3 2 | 3 | This example project uses the OpenID Connect support in Spring Security 5 without using the Keycloak adapter 4 | and is inspired by [this](http://info.michael-simons.eu/2017/12/28/use-keycloak-with-your-spring-boot-2-application/) blog post by Michael Simons. 5 | 6 | Features: 7 | - SSO / SLO 8 | - Support for extracting roles from Keycloak AccessToken 9 | - Link to Keycloak Account page with back-link to the application 10 | 11 | ## Setup 12 | 13 | Import the `demo` realm into Keycloak via 14 | 15 | ``` 16 | bin/standalone.sh -Dkeycloak.migration.action=import 17 | -Dkeycloak.migration.provider=singleFile -Dkeycloak.migration.file=/path/to/demo-realm.json 18 | -Dkeycloak.migration.strategy=OVERWRITE_EXISTING 19 | ``` 20 | 21 | Keycloak is assumed to run on port 8080 on localhost. 22 | The demo realm contains two users `tester` and `admin` both with password `test`. 23 | 24 | The example runs on port 8082. 25 | 26 | -------------------------------------------------------------------------------- /src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8082 3 | 4 | kc: 5 | base-url: http://localhost:8080/auth 6 | realm: demo 7 | realm-url: ${kc.base-url}/realms/${kc.realm} 8 | 9 | spring: 10 | security: 11 | oauth2: 12 | client: 13 | registration: 14 | demo: 15 | client-id: app-demo 16 | client-name: Demo App 17 | client-secret: e3f519b4-0272-4261-9912-8b7453ac4ecd 18 | provider: keycloak 19 | authorization-grant-type: authorization_code 20 | scope: openid, profile 21 | redirect-uri-template: "{baseUrl}/login/oauth2/code/{registrationId}" 22 | provider: 23 | keycloak: 24 | authorization-uri: ${kc.realm-url}/protocol/openid-connect/auth 25 | jwk-set-uri: ${kc.realm-url}/protocol/openid-connect/certs 26 | token-uri: ${kc.realm-url}/protocol/openid-connect/token 27 | # would be cool if there was a end-session-uri to propagate logouts 28 | 29 | # User info endpoint not needed since Keycloak uses self-contained value tokens 30 | # user-info-uri: ${kc.realm-url}/protocol/openid-connect/userinfo 31 | user-name-attribute: preferred_username -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | de.tdlabs.training 8 | spring-boot-2-oauth-example 9 | 0.0.1-SNAPSHOT 10 | jar 11 | 12 | spring-boot-2-oauth-example 13 | Demo project for Spring Boot 14 | 15 | 16 | org.springframework.boot 17 | spring-boot-starter-parent 18 | 2.0.1.RELEASE 19 | 20 | 21 | 22 | 23 | UTF-8 24 | UTF-8 25 | 1.8 26 | Finchley.M9 27 | 28 | 29 | 30 | 31 | 32 | org.springframework.boot 33 | spring-boot-starter-web 34 | 35 | 36 | 37 | org.springframework.boot 38 | spring-boot-starter-thymeleaf 39 | 40 | 41 | 42 | org.thymeleaf.extras 43 | thymeleaf-extras-springsecurity4 44 | 45 | 46 | 47 | org.springframework.boot 48 | spring-boot-starter-security 49 | 50 | 51 | 52 | org.springframework.security 53 | spring-security-oauth2-client 54 | 55 | 56 | org.springframework.security 57 | spring-security-oauth2-jose 58 | 59 | 60 | 61 | org.projectlombok 62 | lombok 63 | true 64 | 65 | 66 | 67 | org.springframework.boot 68 | spring-boot-devtools 69 | true 70 | runtime 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | org.springframework.cloud 79 | spring-cloud-dependencies 80 | ${spring-cloud.version} 81 | pom 82 | import 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | org.springframework.boot 91 | spring-boot-maven-plugin 92 | 93 | 94 | 95 | 96 | 97 | 98 | spring-snapshots 99 | Spring Snapshots 100 | https://repo.spring.io/snapshot 101 | 102 | true 103 | 104 | 105 | 106 | spring-milestones 107 | Spring Milestones 108 | https://repo.spring.io/milestone 109 | 110 | false 111 | 112 | 113 | 114 | 115 | 116 | 117 | spring-snapshots 118 | Spring Snapshots 119 | https://repo.spring.io/snapshot 120 | 121 | true 122 | 123 | 124 | 125 | spring-milestones 126 | Spring Milestones 127 | https://repo.spring.io/milestone 128 | 129 | false 130 | 131 | 132 | 133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /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 http://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 Maven2 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 key stroke 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 enable echoing my setting MAVEN_BATCH_ECHO to 'on' 39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 40 | 41 | @REM set %HOME% to equivalent of $HOME 42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 43 | 44 | @REM Execute a user defined script before this one 45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 49 | :skipRcPre 50 | 51 | @setlocal 52 | 53 | set ERROR_CODE=0 54 | 55 | @REM To isolate internal variables from possible post scripts, we use another setlocal 56 | @setlocal 57 | 58 | @REM ==== START VALIDATION ==== 59 | if not "%JAVA_HOME%" == "" goto OkJHome 60 | 61 | echo. 62 | echo Error: JAVA_HOME not found in your environment. >&2 63 | echo Please set the JAVA_HOME variable in your environment to match the >&2 64 | echo location of your Java installation. >&2 65 | echo. 66 | goto error 67 | 68 | :OkJHome 69 | if exist "%JAVA_HOME%\bin\java.exe" goto init 70 | 71 | echo. 72 | echo Error: JAVA_HOME is set to an invalid directory. >&2 73 | echo JAVA_HOME = "%JAVA_HOME%" >&2 74 | echo Please set the JAVA_HOME variable in your environment to match the >&2 75 | echo location of your Java installation. >&2 76 | echo. 77 | goto error 78 | 79 | @REM ==== END VALIDATION ==== 80 | 81 | :init 82 | 83 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 84 | @REM Fallback to current working directory if not found. 85 | 86 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 87 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 88 | 89 | set EXEC_DIR=%CD% 90 | set WDIR=%EXEC_DIR% 91 | :findBaseDir 92 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 93 | cd .. 94 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 95 | set WDIR=%CD% 96 | goto findBaseDir 97 | 98 | :baseDirFound 99 | set MAVEN_PROJECTBASEDIR=%WDIR% 100 | cd "%EXEC_DIR%" 101 | goto endDetectBaseDir 102 | 103 | :baseDirNotFound 104 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 105 | cd "%EXEC_DIR%" 106 | 107 | :endDetectBaseDir 108 | 109 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 110 | 111 | @setlocal EnableExtensions EnableDelayedExpansion 112 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 113 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 114 | 115 | :endReadAdditionalConfig 116 | 117 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 118 | 119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 121 | 122 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 123 | if ERRORLEVEL 1 goto error 124 | goto end 125 | 126 | :error 127 | set ERROR_CODE=1 128 | 129 | :end 130 | @endlocal & set ERROR_CODE=%ERROR_CODE% 131 | 132 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 133 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 134 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 135 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 136 | :skipRcPost 137 | 138 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 139 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 140 | 141 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 142 | 143 | exit /B %ERROR_CODE% 144 | -------------------------------------------------------------------------------- /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 | # http://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 | # Maven2 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 /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 59 | if [ -z "$JAVA_HOME" ]; then 60 | if [ -x "/usr/libexec/java_home" ]; then 61 | export JAVA_HOME="`/usr/libexec/java_home`" 62 | else 63 | export JAVA_HOME="/Library/Java/Home" 64 | fi 65 | fi 66 | ;; 67 | esac 68 | 69 | if [ -z "$JAVA_HOME" ] ; then 70 | if [ -r /etc/gentoo-release ] ; then 71 | JAVA_HOME=`java-config --jre-home` 72 | fi 73 | fi 74 | 75 | if [ -z "$M2_HOME" ] ; then 76 | ## resolve links - $0 may be a link to maven's home 77 | PRG="$0" 78 | 79 | # need this for relative symlinks 80 | while [ -h "$PRG" ] ; do 81 | ls=`ls -ld "$PRG"` 82 | link=`expr "$ls" : '.*-> \(.*\)$'` 83 | if expr "$link" : '/.*' > /dev/null; then 84 | PRG="$link" 85 | else 86 | PRG="`dirname "$PRG"`/$link" 87 | fi 88 | done 89 | 90 | saveddir=`pwd` 91 | 92 | M2_HOME=`dirname "$PRG"`/.. 93 | 94 | # make it fully qualified 95 | M2_HOME=`cd "$M2_HOME" && pwd` 96 | 97 | cd "$saveddir" 98 | # echo Using m2 at $M2_HOME 99 | fi 100 | 101 | # For Cygwin, ensure paths are in UNIX format before anything is touched 102 | if $cygwin ; then 103 | [ -n "$M2_HOME" ] && 104 | M2_HOME=`cygpath --unix "$M2_HOME"` 105 | [ -n "$JAVA_HOME" ] && 106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 107 | [ -n "$CLASSPATH" ] && 108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 109 | fi 110 | 111 | # For Migwn, ensure paths are in UNIX format before anything is touched 112 | if $mingw ; then 113 | [ -n "$M2_HOME" ] && 114 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 115 | [ -n "$JAVA_HOME" ] && 116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 117 | # TODO classpath? 118 | fi 119 | 120 | if [ -z "$JAVA_HOME" ]; then 121 | javaExecutable="`which javac`" 122 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 123 | # readlink(1) is not available as standard on Solaris 10. 124 | readLink=`which readlink` 125 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 126 | if $darwin ; then 127 | javaHome="`dirname \"$javaExecutable\"`" 128 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 129 | else 130 | javaExecutable="`readlink -f \"$javaExecutable\"`" 131 | fi 132 | javaHome="`dirname \"$javaExecutable\"`" 133 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 134 | JAVA_HOME="$javaHome" 135 | export JAVA_HOME 136 | fi 137 | fi 138 | fi 139 | 140 | if [ -z "$JAVACMD" ] ; then 141 | if [ -n "$JAVA_HOME" ] ; then 142 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 143 | # IBM's JDK on AIX uses strange locations for the executables 144 | JAVACMD="$JAVA_HOME/jre/sh/java" 145 | else 146 | JAVACMD="$JAVA_HOME/bin/java" 147 | fi 148 | else 149 | JAVACMD="`which java`" 150 | fi 151 | fi 152 | 153 | if [ ! -x "$JAVACMD" ] ; then 154 | echo "Error: JAVA_HOME is not defined correctly." >&2 155 | echo " We cannot execute $JAVACMD" >&2 156 | exit 1 157 | fi 158 | 159 | if [ -z "$JAVA_HOME" ] ; then 160 | echo "Warning: JAVA_HOME environment variable is not set." 161 | fi 162 | 163 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 164 | 165 | # traverses directory structure from process work directory to filesystem root 166 | # first directory with .mvn subdirectory is considered project base directory 167 | find_maven_basedir() { 168 | 169 | if [ -z "$1" ] 170 | then 171 | echo "Path not specified to find_maven_basedir" 172 | return 1 173 | fi 174 | 175 | basedir="$1" 176 | wdir="$1" 177 | while [ "$wdir" != '/' ] ; do 178 | if [ -d "$wdir"/.mvn ] ; then 179 | basedir=$wdir 180 | break 181 | fi 182 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 183 | if [ -d "${wdir}" ]; then 184 | wdir=`cd "$wdir/.."; pwd` 185 | fi 186 | # end of workaround 187 | done 188 | echo "${basedir}" 189 | } 190 | 191 | # concatenates all lines of a file 192 | concat_lines() { 193 | if [ -f "$1" ]; then 194 | echo "$(tr -s '\n' ' ' < "$1")" 195 | fi 196 | } 197 | 198 | BASE_DIR=`find_maven_basedir "$(pwd)"` 199 | if [ -z "$BASE_DIR" ]; then 200 | exit 1; 201 | fi 202 | 203 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 204 | echo $MAVEN_PROJECTBASEDIR 205 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 206 | 207 | # For Cygwin, switch paths to Windows format before running java 208 | if $cygwin; then 209 | [ -n "$M2_HOME" ] && 210 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 211 | [ -n "$JAVA_HOME" ] && 212 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 213 | [ -n "$CLASSPATH" ] && 214 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 215 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 216 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` 217 | fi 218 | 219 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 220 | 221 | exec "$JAVACMD" \ 222 | $MAVEN_OPTS \ 223 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 224 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 225 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 226 | -------------------------------------------------------------------------------- /src/main/java/demo/SpringBoot2App.java: -------------------------------------------------------------------------------- 1 | package demo; 2 | 3 | import static org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI; 4 | 5 | import java.security.Principal; 6 | import java.util.Collection; 7 | import java.util.Collections; 8 | import java.util.LinkedHashSet; 9 | import java.util.List; 10 | import java.util.Map; 11 | import java.util.Set; 12 | 13 | import javax.servlet.http.HttpServletRequest; 14 | import javax.servlet.http.HttpServletResponse; 15 | 16 | import org.springframework.beans.factory.annotation.Value; 17 | import org.springframework.boot.SpringApplication; 18 | import org.springframework.boot.autoconfigure.SpringBootApplication; 19 | import org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientProperties; 20 | import org.springframework.context.annotation.Bean; 21 | import org.springframework.context.annotation.Configuration; 22 | import org.springframework.http.ResponseEntity; 23 | import org.springframework.security.access.prepost.PreAuthorize; 24 | import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; 25 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 26 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 27 | import org.springframework.security.config.http.SessionCreationPolicy; 28 | import org.springframework.security.core.Authentication; 29 | import org.springframework.security.core.GrantedAuthority; 30 | import org.springframework.security.core.annotation.AuthenticationPrincipal; 31 | import org.springframework.security.core.authority.AuthorityUtils; 32 | import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper; 33 | import org.springframework.security.core.authority.mapping.SimpleAuthorityMapper; 34 | import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; 35 | import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest; 36 | import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService; 37 | import org.springframework.security.oauth2.core.OAuth2AuthenticationException; 38 | import org.springframework.security.oauth2.core.OAuth2Error; 39 | import org.springframework.security.oauth2.core.OAuth2ErrorCodes; 40 | import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser; 41 | import org.springframework.security.oauth2.core.oidc.user.OidcUser; 42 | import org.springframework.security.oauth2.jwt.Jwt; 43 | import org.springframework.security.oauth2.jwt.JwtDecoder; 44 | import org.springframework.security.oauth2.jwt.JwtException; 45 | import org.springframework.security.oauth2.jwt.NimbusJwtDecoderJwkSupport; 46 | import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler; 47 | import org.springframework.stereotype.Controller; 48 | import org.springframework.ui.Model; 49 | import org.springframework.util.CollectionUtils; 50 | import org.springframework.web.bind.annotation.GetMapping; 51 | import org.springframework.web.client.RestTemplate; 52 | import org.springframework.web.servlet.ModelAndView; 53 | import org.springframework.web.util.UriComponentsBuilder; 54 | 55 | import lombok.RequiredArgsConstructor; 56 | import lombok.extern.slf4j.Slf4j; 57 | 58 | @SpringBootApplication 59 | public class SpringBoot2App { 60 | 61 | public static void main(String[] args) { 62 | SpringApplication.run(SpringBoot2App.class, args); 63 | } 64 | } 65 | 66 | @Configuration 67 | @EnableGlobalMethodSecurity(prePostEnabled = true) 68 | class WebSecurityConfig { 69 | 70 | @Bean 71 | public WebSecurityConfigurerAdapter webSecurityConfigurer( // 72 | @Value("${kc.realm}") String realm, // 73 | KeycloakOauth2UserService keycloakOidcUserService, // 74 | KeycloakLogoutHandler keycloakLogoutHandler // 75 | ) { 76 | return new WebSecurityConfigurerAdapter() { 77 | @Override 78 | public void configure(HttpSecurity http) throws Exception { 79 | 80 | http 81 | // Configure session management to your needs. 82 | // I need this as a basis for a classic, server side rendered application 83 | .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED).and() 84 | // Depends on your taste. You can configure single paths here 85 | // or allow everything a I did and then use method based security 86 | // like in the controller below 87 | .authorizeRequests().anyRequest().permitAll().and() 88 | // Propagate logouts via /logout to Keycloak 89 | .logout().addLogoutHandler(keycloakLogoutHandler).and() 90 | // This is the point where OAuth2 login of Spring 5 gets enabled 91 | .oauth2Login().userInfoEndpoint().oidcUserService(keycloakOidcUserService).and() 92 | // I don't want a page with different clients as login options 93 | // So i use the constant from OAuth2AuthorizationRequestRedirectFilter 94 | // plus the configured realm as immediate redirect to Keycloak 95 | .loginPage(DEFAULT_AUTHORIZATION_REQUEST_BASE_URI + "/" + realm); 96 | } 97 | }; 98 | } 99 | 100 | @Bean 101 | KeycloakOauth2UserService keycloakOidcUserService(OAuth2ClientProperties oauth2ClientProperties) { 102 | 103 | // TODO use default JwtDecoder - where to grab? 104 | NimbusJwtDecoderJwkSupport jwtDecoder = new NimbusJwtDecoderJwkSupport( 105 | oauth2ClientProperties.getProvider().get("keycloak").getJwkSetUri()); 106 | 107 | SimpleAuthorityMapper authoritiesMapper = new SimpleAuthorityMapper(); 108 | authoritiesMapper.setConvertToUpperCase(true); 109 | 110 | return new KeycloakOauth2UserService(jwtDecoder, authoritiesMapper); 111 | } 112 | 113 | @Bean 114 | KeycloakLogoutHandler keycloakLogoutHandler() { 115 | return new KeycloakLogoutHandler(new RestTemplate()); 116 | } 117 | } 118 | 119 | @RequiredArgsConstructor 120 | class KeycloakOauth2UserService extends OidcUserService { 121 | 122 | private final OAuth2Error INVALID_REQUEST = new OAuth2Error(OAuth2ErrorCodes.INVALID_REQUEST); 123 | 124 | private final JwtDecoder jwtDecoder; 125 | 126 | private final GrantedAuthoritiesMapper authoritiesMapper; 127 | 128 | /** 129 | * Augments {@link OidcUserService#loadUser(OidcUserRequest)} to add authorities 130 | * provided by Keycloak. 131 | * 132 | * Needed because {@link OidcUserService#loadUser(OidcUserRequest)} (currently) 133 | * does not provide a hook for adding custom authorities from a 134 | * {@link OidcUserRequest}. 135 | */ 136 | @Override 137 | public OidcUser loadUser(OidcUserRequest userRequest) throws OAuth2AuthenticationException { 138 | 139 | OidcUser user = super.loadUser(userRequest); 140 | 141 | Set authorities = new LinkedHashSet<>(); 142 | authorities.addAll(user.getAuthorities()); 143 | authorities.addAll(extractKeycloakAuthorities(userRequest)); 144 | 145 | return new DefaultOidcUser(authorities, userRequest.getIdToken(), user.getUserInfo(), "preferred_username"); 146 | } 147 | 148 | /** 149 | * Extracts {@link GrantedAuthority GrantedAuthorities} from the AccessToken in 150 | * the {@link OidcUserRequest}. 151 | * 152 | * @param userRequest 153 | * @return 154 | */ 155 | private Collection extractKeycloakAuthorities(OidcUserRequest userRequest) { 156 | 157 | Jwt token = parseJwt(userRequest.getAccessToken().getTokenValue()); 158 | 159 | // Would be great if Spring Security would provide something like a plugable 160 | // OidcUserRequestAuthoritiesExtractor interface to hide the junk below... 161 | 162 | @SuppressWarnings("unchecked") 163 | Map resourceMap = (Map) token.getClaims().get("resource_access"); 164 | String clientId = userRequest.getClientRegistration().getClientId(); 165 | 166 | @SuppressWarnings("unchecked") 167 | Map> clientResource = (Map>) resourceMap.get(clientId); 168 | if (CollectionUtils.isEmpty(clientResource)) { 169 | return Collections.emptyList(); 170 | } 171 | 172 | @SuppressWarnings("unchecked") 173 | List clientRoles = (List) clientResource.get("roles"); 174 | if (CollectionUtils.isEmpty(clientRoles)) { 175 | return Collections.emptyList(); 176 | } 177 | 178 | Collection authorities = AuthorityUtils 179 | .createAuthorityList(clientRoles.toArray(new String[0])); 180 | if (authoritiesMapper == null) { 181 | return authorities; 182 | } 183 | 184 | return authoritiesMapper.mapAuthorities(authorities); 185 | } 186 | 187 | private Jwt parseJwt(String accessTokenValue) { 188 | try { 189 | // Token is already verified by spring security infrastructure 190 | return jwtDecoder.decode(accessTokenValue); 191 | } catch (JwtException e) { 192 | throw new OAuth2AuthenticationException(INVALID_REQUEST, e); 193 | } 194 | } 195 | } 196 | 197 | /** 198 | * Propagates logouts to Keycloak. 199 | * 200 | * Necessary because Spring Security 5 (currently) doesn't support 201 | * end-session-endpoints. 202 | */ 203 | @Slf4j 204 | @RequiredArgsConstructor 205 | class KeycloakLogoutHandler extends SecurityContextLogoutHandler { 206 | 207 | private final RestTemplate restTemplate; 208 | 209 | @Override 210 | public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { 211 | super.logout(request, response, authentication); 212 | 213 | propagateLogoutToKeycloak((OidcUser) authentication.getPrincipal()); 214 | } 215 | 216 | private void propagateLogoutToKeycloak(OidcUser user) { 217 | 218 | String endSessionEndpoint = user.getIssuer() + "/protocol/openid-connect/logout"; 219 | 220 | UriComponentsBuilder builder = UriComponentsBuilder // 221 | .fromUriString(endSessionEndpoint) // 222 | .queryParam("id_token_hint", user.getIdToken().getTokenValue()); 223 | 224 | ResponseEntity logoutResponse = restTemplate.getForEntity(builder.toUriString(), String.class); 225 | if (logoutResponse.getStatusCode().is2xxSuccessful()) { 226 | log.info("Successfulley logged out in Keycloak"); 227 | } else { 228 | log.info("Could not propagate logout to Keycloak"); 229 | } 230 | } 231 | } 232 | 233 | @Controller 234 | class DemoController { 235 | 236 | @PreAuthorize("hasRole('ROLE_USER')") 237 | @GetMapping("/protected") 238 | public ModelAndView protectedPage(Principal principal) { 239 | return new ModelAndView("app", Collections.singletonMap("principal", principal)); 240 | } 241 | 242 | @PreAuthorize("hasRole('ROLE_ADMIN')") 243 | @GetMapping("/admin") 244 | public ModelAndView adminPage(Principal principal) { 245 | return new ModelAndView("admin", Collections.singletonMap("principal", principal)); 246 | } 247 | 248 | @GetMapping("/") 249 | public String unprotectedPage(Model model, Principal principal) { 250 | model.addAttribute("principal", principal); 251 | return "index"; 252 | } 253 | 254 | @GetMapping("/account") 255 | public String redirectToAccountPage(@AuthenticationPrincipal OAuth2AuthenticationToken authToken) { 256 | 257 | if (authToken == null) { 258 | return "redirect:/"; 259 | } 260 | 261 | OidcUser user = (OidcUser) authToken.getPrincipal(); 262 | 263 | // Provides a back-link to the application 264 | return "redirect:" + user.getIssuer() + "/account?referrer=" + user.getIdToken().getAuthorizedParty(); 265 | } 266 | } -------------------------------------------------------------------------------- /demo-realm.json: -------------------------------------------------------------------------------- 1 | { 2 | "id" : "demo", 3 | "realm" : "demo", 4 | "notBefore" : 0, 5 | "revokeRefreshToken" : false, 6 | "refreshTokenMaxReuse" : 0, 7 | "accessTokenLifespan" : 300, 8 | "accessTokenLifespanForImplicitFlow" : 900, 9 | "ssoSessionIdleTimeout" : 1800, 10 | "ssoSessionMaxLifespan" : 36000, 11 | "offlineSessionIdleTimeout" : 2592000, 12 | "accessCodeLifespan" : 60, 13 | "accessCodeLifespanUserAction" : 300, 14 | "accessCodeLifespanLogin" : 1800, 15 | "actionTokenGeneratedByAdminLifespan" : 43200, 16 | "actionTokenGeneratedByUserLifespan" : 300, 17 | "enabled" : true, 18 | "sslRequired" : "external", 19 | "registrationAllowed" : false, 20 | "registrationEmailAsUsername" : false, 21 | "rememberMe" : false, 22 | "verifyEmail" : false, 23 | "loginWithEmailAllowed" : true, 24 | "duplicateEmailsAllowed" : false, 25 | "resetPasswordAllowed" : false, 26 | "editUsernameAllowed" : false, 27 | "bruteForceProtected" : false, 28 | "permanentLockout" : false, 29 | "maxFailureWaitSeconds" : 900, 30 | "minimumQuickLoginWaitSeconds" : 60, 31 | "waitIncrementSeconds" : 60, 32 | "quickLoginCheckMilliSeconds" : 1000, 33 | "maxDeltaTimeSeconds" : 43200, 34 | "failureFactor" : 30, 35 | "roles" : { 36 | "realm" : [ { 37 | "id" : "9cec708f-b60c-4e72-87bd-bd6cc270804f", 38 | "name" : "offline_access", 39 | "description" : "${role_offline-access}", 40 | "scopeParamRequired" : true, 41 | "composite" : false, 42 | "clientRole" : false, 43 | "containerId" : "demo" 44 | }, { 45 | "id" : "b377ec00-d24e-481c-88d1-fc236fcbb4f8", 46 | "name" : "uma_authorization", 47 | "description" : "${role_uma_authorization}", 48 | "scopeParamRequired" : false, 49 | "composite" : false, 50 | "clientRole" : false, 51 | "containerId" : "demo" 52 | } ], 53 | "client" : { 54 | "realm-management" : [ { 55 | "id" : "e20d8308-6e6e-4814-8b6c-f31e429d83d8", 56 | "name" : "query-clients", 57 | "description" : "${role_query-clients}", 58 | "scopeParamRequired" : false, 59 | "composite" : false, 60 | "clientRole" : true, 61 | "containerId" : "4e57a54d-42c8-400e-9cc1-95a36fbe02fd" 62 | }, { 63 | "id" : "b64456f6-a12d-455d-8f91-5b2a508d1326", 64 | "name" : "view-identity-providers", 65 | "description" : "${role_view-identity-providers}", 66 | "scopeParamRequired" : false, 67 | "composite" : false, 68 | "clientRole" : true, 69 | "containerId" : "4e57a54d-42c8-400e-9cc1-95a36fbe02fd" 70 | }, { 71 | "id" : "968aa5a6-220f-4c73-a1d9-d1eb4b3f7f20", 72 | "name" : "query-groups", 73 | "description" : "${role_query-groups}", 74 | "scopeParamRequired" : false, 75 | "composite" : false, 76 | "clientRole" : true, 77 | "containerId" : "4e57a54d-42c8-400e-9cc1-95a36fbe02fd" 78 | }, { 79 | "id" : "54db3285-f76c-462f-9dea-3f0da29a8277", 80 | "name" : "view-events", 81 | "description" : "${role_view-events}", 82 | "scopeParamRequired" : false, 83 | "composite" : false, 84 | "clientRole" : true, 85 | "containerId" : "4e57a54d-42c8-400e-9cc1-95a36fbe02fd" 86 | }, { 87 | "id" : "f63004bf-394b-426f-b609-19ca807f3a57", 88 | "name" : "manage-users", 89 | "description" : "${role_manage-users}", 90 | "scopeParamRequired" : false, 91 | "composite" : false, 92 | "clientRole" : true, 93 | "containerId" : "4e57a54d-42c8-400e-9cc1-95a36fbe02fd" 94 | }, { 95 | "id" : "273b678a-2018-4480-9007-b0b5d318019e", 96 | "name" : "query-users", 97 | "description" : "${role_query-users}", 98 | "scopeParamRequired" : false, 99 | "composite" : false, 100 | "clientRole" : true, 101 | "containerId" : "4e57a54d-42c8-400e-9cc1-95a36fbe02fd" 102 | }, { 103 | "id" : "b0bcfe2c-e426-4cc8-8161-f6608203409b", 104 | "name" : "view-users", 105 | "description" : "${role_view-users}", 106 | "scopeParamRequired" : false, 107 | "composite" : true, 108 | "composites" : { 109 | "client" : { 110 | "realm-management" : [ "query-groups", "query-users" ] 111 | } 112 | }, 113 | "clientRole" : true, 114 | "containerId" : "4e57a54d-42c8-400e-9cc1-95a36fbe02fd" 115 | }, { 116 | "id" : "4f2d2465-9e75-4975-8748-ec2bbb2f1b96", 117 | "name" : "query-realms", 118 | "description" : "${role_query-realms}", 119 | "scopeParamRequired" : false, 120 | "composite" : false, 121 | "clientRole" : true, 122 | "containerId" : "4e57a54d-42c8-400e-9cc1-95a36fbe02fd" 123 | }, { 124 | "id" : "65c72650-d874-4a6b-a065-4558a3e2fc6a", 125 | "name" : "create-client", 126 | "description" : "${role_create-client}", 127 | "scopeParamRequired" : false, 128 | "composite" : false, 129 | "clientRole" : true, 130 | "containerId" : "4e57a54d-42c8-400e-9cc1-95a36fbe02fd" 131 | }, { 132 | "id" : "a56996bc-9589-476b-9e54-88b5e6355fca", 133 | "name" : "manage-clients", 134 | "description" : "${role_manage-clients}", 135 | "scopeParamRequired" : false, 136 | "composite" : false, 137 | "clientRole" : true, 138 | "containerId" : "4e57a54d-42c8-400e-9cc1-95a36fbe02fd" 139 | }, { 140 | "id" : "6e8e2d8d-1632-4893-8428-3ec4c438bead", 141 | "name" : "view-clients", 142 | "description" : "${role_view-clients}", 143 | "scopeParamRequired" : false, 144 | "composite" : true, 145 | "composites" : { 146 | "client" : { 147 | "realm-management" : [ "query-clients" ] 148 | } 149 | }, 150 | "clientRole" : true, 151 | "containerId" : "4e57a54d-42c8-400e-9cc1-95a36fbe02fd" 152 | }, { 153 | "id" : "25c953c3-a411-4237-8501-7b8ebef5988f", 154 | "name" : "manage-realm", 155 | "description" : "${role_manage-realm}", 156 | "scopeParamRequired" : false, 157 | "composite" : false, 158 | "clientRole" : true, 159 | "containerId" : "4e57a54d-42c8-400e-9cc1-95a36fbe02fd" 160 | }, { 161 | "id" : "dc1a53ec-d0e1-441f-8e72-8ca411ab21a0", 162 | "name" : "view-authorization", 163 | "description" : "${role_view-authorization}", 164 | "scopeParamRequired" : false, 165 | "composite" : false, 166 | "clientRole" : true, 167 | "containerId" : "4e57a54d-42c8-400e-9cc1-95a36fbe02fd" 168 | }, { 169 | "id" : "30bbf430-98a6-46d5-a25c-48992aebd848", 170 | "name" : "realm-admin", 171 | "description" : "${role_realm-admin}", 172 | "scopeParamRequired" : false, 173 | "composite" : true, 174 | "composites" : { 175 | "client" : { 176 | "realm-management" : [ "query-clients", "query-groups", "view-identity-providers", "view-events", "manage-users", "query-users", "query-realms", "view-users", "create-client", "manage-clients", "view-clients", "manage-realm", "view-authorization", "manage-events", "impersonation", "manage-authorization", "view-realm", "manage-identity-providers" ] 177 | } 178 | }, 179 | "clientRole" : true, 180 | "containerId" : "4e57a54d-42c8-400e-9cc1-95a36fbe02fd" 181 | }, { 182 | "id" : "2f93f784-ece8-4205-a9c2-b933b6beee09", 183 | "name" : "manage-events", 184 | "description" : "${role_manage-events}", 185 | "scopeParamRequired" : false, 186 | "composite" : false, 187 | "clientRole" : true, 188 | "containerId" : "4e57a54d-42c8-400e-9cc1-95a36fbe02fd" 189 | }, { 190 | "id" : "eb6ab687-958a-4c24-a97d-569e31101c41", 191 | "name" : "manage-authorization", 192 | "description" : "${role_manage-authorization}", 193 | "scopeParamRequired" : false, 194 | "composite" : false, 195 | "clientRole" : true, 196 | "containerId" : "4e57a54d-42c8-400e-9cc1-95a36fbe02fd" 197 | }, { 198 | "id" : "e4d149d9-5c8e-4f1c-9a40-ac371aaf3794", 199 | "name" : "impersonation", 200 | "description" : "${role_impersonation}", 201 | "scopeParamRequired" : false, 202 | "composite" : false, 203 | "clientRole" : true, 204 | "containerId" : "4e57a54d-42c8-400e-9cc1-95a36fbe02fd" 205 | }, { 206 | "id" : "3f9d491f-7df0-4f91-ab0d-5f5531b41f9d", 207 | "name" : "view-realm", 208 | "description" : "${role_view-realm}", 209 | "scopeParamRequired" : false, 210 | "composite" : false, 211 | "clientRole" : true, 212 | "containerId" : "4e57a54d-42c8-400e-9cc1-95a36fbe02fd" 213 | }, { 214 | "id" : "11ba2522-4090-431b-9842-0e9f31884d0a", 215 | "name" : "manage-identity-providers", 216 | "description" : "${role_manage-identity-providers}", 217 | "scopeParamRequired" : false, 218 | "composite" : false, 219 | "clientRole" : true, 220 | "containerId" : "4e57a54d-42c8-400e-9cc1-95a36fbe02fd" 221 | } ], 222 | "security-admin-console" : [ ], 223 | "admin-cli" : [ ], 224 | "app-demo" : [ { 225 | "id" : "57b84603-ceef-4a48-bd08-f46467eb7bd9", 226 | "name" : "admin", 227 | "scopeParamRequired" : false, 228 | "composite" : false, 229 | "clientRole" : true, 230 | "containerId" : "ec2975dc-bde7-4012-89c4-06a499c00235" 231 | }, { 232 | "id" : "754c1364-9444-4477-bcc1-b07794bee2fc", 233 | "name" : "user", 234 | "scopeParamRequired" : false, 235 | "composite" : false, 236 | "clientRole" : true, 237 | "containerId" : "ec2975dc-bde7-4012-89c4-06a499c00235" 238 | } ], 239 | "broker" : [ { 240 | "id" : "f08f6cf6-09ed-41f6-9c05-164dc8f8ab5e", 241 | "name" : "read-token", 242 | "description" : "${role_read-token}", 243 | "scopeParamRequired" : false, 244 | "composite" : false, 245 | "clientRole" : true, 246 | "containerId" : "0536d12c-2c36-444a-898b-ed7b527aac76" 247 | } ], 248 | "account" : [ { 249 | "id" : "c4cf29c5-3375-45d1-acd2-5962af1c733a", 250 | "name" : "manage-account", 251 | "description" : "${role_manage-account}", 252 | "scopeParamRequired" : false, 253 | "composite" : true, 254 | "composites" : { 255 | "client" : { 256 | "account" : [ "manage-account-links" ] 257 | } 258 | }, 259 | "clientRole" : true, 260 | "containerId" : "2e441b12-8370-49b8-b8aa-2c7546144b4e" 261 | }, { 262 | "id" : "5d703753-792e-4167-ad2b-c5b7f6a959d7", 263 | "name" : "view-profile", 264 | "description" : "${role_view-profile}", 265 | "scopeParamRequired" : false, 266 | "composite" : false, 267 | "clientRole" : true, 268 | "containerId" : "2e441b12-8370-49b8-b8aa-2c7546144b4e" 269 | }, { 270 | "id" : "8eb0ae88-2819-47ab-9a93-6ff34b43ae88", 271 | "name" : "manage-account-links", 272 | "description" : "${role_manage-account-links}", 273 | "scopeParamRequired" : false, 274 | "composite" : false, 275 | "clientRole" : true, 276 | "containerId" : "2e441b12-8370-49b8-b8aa-2c7546144b4e" 277 | } ] 278 | } 279 | }, 280 | "groups" : [ ], 281 | "defaultRoles" : [ "offline_access", "uma_authorization" ], 282 | "requiredCredentials" : [ "password" ], 283 | "otpPolicyType" : "totp", 284 | "otpPolicyAlgorithm" : "HmacSHA1", 285 | "otpPolicyInitialCounter" : 0, 286 | "otpPolicyDigits" : 6, 287 | "otpPolicyLookAheadWindow" : 1, 288 | "otpPolicyPeriod" : 30, 289 | "otpSupportedApplications" : [ "FreeOTP", "Google Authenticator" ], 290 | "users" : [ { 291 | "id" : "8d7a7207-94c0-4ba7-ac3a-efb79412dd44", 292 | "createdTimestamp" : 1523988975613, 293 | "username" : "admin", 294 | "enabled" : true, 295 | "totp" : false, 296 | "emailVerified" : false, 297 | "firstName" : "Arno", 298 | "lastName" : "Admin", 299 | "email" : "tom+admin@localhost", 300 | "credentials" : [ { 301 | "type" : "password", 302 | "hashedSaltedValue" : "ZcC45qA9JiFQYuJau1w/pxfBmZusDDoCO0Sx4z+uFWdE4CA1FUibOqpqHh21GwRKcdRSseqrBBaaPbBznIWYRQ==", 303 | "salt" : "sTMbn/fDpC/KX549o9XoHg==", 304 | "hashIterations" : 27500, 305 | "counter" : 0, 306 | "algorithm" : "pbkdf2-sha256", 307 | "digits" : 0, 308 | "period" : 0, 309 | "createdDate" : 1523988982527, 310 | "config" : { } 311 | } ], 312 | "disableableCredentialTypes" : [ "password" ], 313 | "requiredActions" : [ ], 314 | "realmRoles" : [ "offline_access", "uma_authorization" ], 315 | "clientRoles" : { 316 | "app-demo" : [ "admin", "user" ], 317 | "account" : [ "manage-account", "view-profile" ] 318 | }, 319 | "notBefore" : 0, 320 | "groups" : [ ] 321 | }, { 322 | "id" : "91591318-6c82-4250-b6fb-9a5e257959a5", 323 | "createdTimestamp" : 1523983635756, 324 | "username" : "tester", 325 | "enabled" : true, 326 | "totp" : false, 327 | "emailVerified" : false, 328 | "firstName" : "Theo", 329 | "lastName" : "Tester", 330 | "email" : "tom+test@localhost", 331 | "credentials" : [ { 332 | "type" : "password", 333 | "hashedSaltedValue" : "h/aCiQS3fdB/euTSwOz/ww/+L0b6c9WGsRsMMSPr899rQIFLlIhjWjAgA9BbRAKsSLfo+nsNUKaXGfhwgi2r7g==", 334 | "salt" : "W3mOjqoG8mctglGSgbYSKQ==", 335 | "hashIterations" : 27500, 336 | "counter" : 0, 337 | "algorithm" : "pbkdf2-sha256", 338 | "digits" : 0, 339 | "period" : 0, 340 | "createdDate" : 1523983645059, 341 | "config" : { } 342 | } ], 343 | "disableableCredentialTypes" : [ "password" ], 344 | "requiredActions" : [ ], 345 | "realmRoles" : [ "offline_access", "uma_authorization" ], 346 | "clientRoles" : { 347 | "app-demo" : [ "user" ], 348 | "account" : [ "manage-account", "view-profile" ] 349 | }, 350 | "notBefore" : 0, 351 | "groups" : [ ] 352 | } ], 353 | "clients" : [ { 354 | "id" : "2e441b12-8370-49b8-b8aa-2c7546144b4e", 355 | "clientId" : "account", 356 | "name" : "${client_account}", 357 | "baseUrl" : "/auth/realms/demo/account", 358 | "surrogateAuthRequired" : false, 359 | "enabled" : true, 360 | "clientAuthenticatorType" : "client-secret", 361 | "secret" : "85e4ed69-3da1-4d34-ba4e-31980b4b386d", 362 | "defaultRoles" : [ "view-profile", "manage-account" ], 363 | "redirectUris" : [ "/auth/realms/demo/account/*" ], 364 | "webOrigins" : [ ], 365 | "notBefore" : 0, 366 | "bearerOnly" : false, 367 | "consentRequired" : false, 368 | "standardFlowEnabled" : true, 369 | "implicitFlowEnabled" : false, 370 | "directAccessGrantsEnabled" : false, 371 | "serviceAccountsEnabled" : false, 372 | "publicClient" : false, 373 | "frontchannelLogout" : false, 374 | "protocol" : "openid-connect", 375 | "attributes" : { }, 376 | "fullScopeAllowed" : false, 377 | "nodeReRegistrationTimeout" : 0, 378 | "protocolMappers" : [ { 379 | "id" : "61173bf1-f182-4c08-81f1-45ded5285a96", 380 | "name" : "given name", 381 | "protocol" : "openid-connect", 382 | "protocolMapper" : "oidc-usermodel-property-mapper", 383 | "consentRequired" : true, 384 | "consentText" : "${givenName}", 385 | "config" : { 386 | "userinfo.token.claim" : "true", 387 | "user.attribute" : "firstName", 388 | "id.token.claim" : "true", 389 | "access.token.claim" : "true", 390 | "claim.name" : "given_name", 391 | "jsonType.label" : "String" 392 | } 393 | }, { 394 | "id" : "3fc7edb3-23e1-4211-9a71-61700c849841", 395 | "name" : "family name", 396 | "protocol" : "openid-connect", 397 | "protocolMapper" : "oidc-usermodel-property-mapper", 398 | "consentRequired" : true, 399 | "consentText" : "${familyName}", 400 | "config" : { 401 | "userinfo.token.claim" : "true", 402 | "user.attribute" : "lastName", 403 | "id.token.claim" : "true", 404 | "access.token.claim" : "true", 405 | "claim.name" : "family_name", 406 | "jsonType.label" : "String" 407 | } 408 | }, { 409 | "id" : "33bcaadd-4cae-44fd-8f53-cfbb9b1804a3", 410 | "name" : "email", 411 | "protocol" : "openid-connect", 412 | "protocolMapper" : "oidc-usermodel-property-mapper", 413 | "consentRequired" : true, 414 | "consentText" : "${email}", 415 | "config" : { 416 | "userinfo.token.claim" : "true", 417 | "user.attribute" : "email", 418 | "id.token.claim" : "true", 419 | "access.token.claim" : "true", 420 | "claim.name" : "email", 421 | "jsonType.label" : "String" 422 | } 423 | }, { 424 | "id" : "b7ea4f28-5d0c-4ec3-b03f-bef776943c65", 425 | "name" : "username", 426 | "protocol" : "openid-connect", 427 | "protocolMapper" : "oidc-usermodel-property-mapper", 428 | "consentRequired" : true, 429 | "consentText" : "${username}", 430 | "config" : { 431 | "userinfo.token.claim" : "true", 432 | "user.attribute" : "username", 433 | "id.token.claim" : "true", 434 | "access.token.claim" : "true", 435 | "claim.name" : "preferred_username", 436 | "jsonType.label" : "String" 437 | } 438 | }, { 439 | "id" : "493cb2a0-3b7d-46de-9aa4-e9b36e9b75c5", 440 | "name" : "role list", 441 | "protocol" : "saml", 442 | "protocolMapper" : "saml-role-list-mapper", 443 | "consentRequired" : false, 444 | "config" : { 445 | "single" : "false", 446 | "attribute.nameformat" : "Basic", 447 | "attribute.name" : "Role" 448 | } 449 | }, { 450 | "id" : "f2e9d26c-4703-4fac-b5d5-cbbb8cbf9fbc", 451 | "name" : "full name", 452 | "protocol" : "openid-connect", 453 | "protocolMapper" : "oidc-full-name-mapper", 454 | "consentRequired" : true, 455 | "consentText" : "${fullName}", 456 | "config" : { 457 | "id.token.claim" : "true", 458 | "access.token.claim" : "true" 459 | } 460 | } ], 461 | "useTemplateConfig" : false, 462 | "useTemplateScope" : false, 463 | "useTemplateMappers" : false 464 | }, { 465 | "id" : "c0d68b59-146c-462e-910d-eae82c190c61", 466 | "clientId" : "admin-cli", 467 | "name" : "${client_admin-cli}", 468 | "surrogateAuthRequired" : false, 469 | "enabled" : true, 470 | "clientAuthenticatorType" : "client-secret", 471 | "secret" : "e4491867-8a42-4ca4-93ee-34a898ea6775", 472 | "redirectUris" : [ ], 473 | "webOrigins" : [ ], 474 | "notBefore" : 0, 475 | "bearerOnly" : false, 476 | "consentRequired" : false, 477 | "standardFlowEnabled" : false, 478 | "implicitFlowEnabled" : false, 479 | "directAccessGrantsEnabled" : true, 480 | "serviceAccountsEnabled" : false, 481 | "publicClient" : true, 482 | "frontchannelLogout" : false, 483 | "protocol" : "openid-connect", 484 | "attributes" : { }, 485 | "fullScopeAllowed" : false, 486 | "nodeReRegistrationTimeout" : 0, 487 | "protocolMappers" : [ { 488 | "id" : "e005a327-9dcb-447d-80c2-f7c668d0afaa", 489 | "name" : "full name", 490 | "protocol" : "openid-connect", 491 | "protocolMapper" : "oidc-full-name-mapper", 492 | "consentRequired" : true, 493 | "consentText" : "${fullName}", 494 | "config" : { 495 | "id.token.claim" : "true", 496 | "access.token.claim" : "true" 497 | } 498 | }, { 499 | "id" : "a4cab9da-4684-4bdb-8351-abf2d9428845", 500 | "name" : "given name", 501 | "protocol" : "openid-connect", 502 | "protocolMapper" : "oidc-usermodel-property-mapper", 503 | "consentRequired" : true, 504 | "consentText" : "${givenName}", 505 | "config" : { 506 | "userinfo.token.claim" : "true", 507 | "user.attribute" : "firstName", 508 | "id.token.claim" : "true", 509 | "access.token.claim" : "true", 510 | "claim.name" : "given_name", 511 | "jsonType.label" : "String" 512 | } 513 | }, { 514 | "id" : "b2fc3109-62de-4b87-8c31-29e895329f93", 515 | "name" : "family name", 516 | "protocol" : "openid-connect", 517 | "protocolMapper" : "oidc-usermodel-property-mapper", 518 | "consentRequired" : true, 519 | "consentText" : "${familyName}", 520 | "config" : { 521 | "userinfo.token.claim" : "true", 522 | "user.attribute" : "lastName", 523 | "id.token.claim" : "true", 524 | "access.token.claim" : "true", 525 | "claim.name" : "family_name", 526 | "jsonType.label" : "String" 527 | } 528 | }, { 529 | "id" : "90622937-00bc-4e2e-a5d6-3f573712b2d2", 530 | "name" : "username", 531 | "protocol" : "openid-connect", 532 | "protocolMapper" : "oidc-usermodel-property-mapper", 533 | "consentRequired" : true, 534 | "consentText" : "${username}", 535 | "config" : { 536 | "userinfo.token.claim" : "true", 537 | "user.attribute" : "username", 538 | "id.token.claim" : "true", 539 | "access.token.claim" : "true", 540 | "claim.name" : "preferred_username", 541 | "jsonType.label" : "String" 542 | } 543 | }, { 544 | "id" : "4960d696-da1f-4fd2-8e15-49cdad809b03", 545 | "name" : "email", 546 | "protocol" : "openid-connect", 547 | "protocolMapper" : "oidc-usermodel-property-mapper", 548 | "consentRequired" : true, 549 | "consentText" : "${email}", 550 | "config" : { 551 | "userinfo.token.claim" : "true", 552 | "user.attribute" : "email", 553 | "id.token.claim" : "true", 554 | "access.token.claim" : "true", 555 | "claim.name" : "email", 556 | "jsonType.label" : "String" 557 | } 558 | }, { 559 | "id" : "c175c2f3-d399-4171-a46a-ac74a5b835f0", 560 | "name" : "role list", 561 | "protocol" : "saml", 562 | "protocolMapper" : "saml-role-list-mapper", 563 | "consentRequired" : false, 564 | "config" : { 565 | "single" : "false", 566 | "attribute.nameformat" : "Basic", 567 | "attribute.name" : "Role" 568 | } 569 | } ], 570 | "useTemplateConfig" : false, 571 | "useTemplateScope" : false, 572 | "useTemplateMappers" : false 573 | }, { 574 | "id" : "ec2975dc-bde7-4012-89c4-06a499c00235", 575 | "clientId" : "app-demo", 576 | "baseUrl" : "http://localhost:8082/", 577 | "surrogateAuthRequired" : false, 578 | "enabled" : true, 579 | "clientAuthenticatorType" : "client-secret", 580 | "secret" : "e3f519b4-0272-4261-9912-8b7453ac4ecd", 581 | "redirectUris" : [ "http://localhost:8082/*" ], 582 | "webOrigins" : [ "http://localhost:8082" ], 583 | "notBefore" : 0, 584 | "bearerOnly" : false, 585 | "consentRequired" : false, 586 | "standardFlowEnabled" : true, 587 | "implicitFlowEnabled" : false, 588 | "directAccessGrantsEnabled" : true, 589 | "serviceAccountsEnabled" : false, 590 | "publicClient" : false, 591 | "frontchannelLogout" : false, 592 | "protocol" : "openid-connect", 593 | "attributes" : { 594 | "saml.assertion.signature" : "false", 595 | "saml.force.post.binding" : "false", 596 | "saml.multivalued.roles" : "false", 597 | "saml.encrypt" : "false", 598 | "saml_force_name_id_format" : "false", 599 | "saml.client.signature" : "false", 600 | "saml.authnstatement" : "false", 601 | "saml.server.signature" : "false", 602 | "saml.server.signature.keyinfo.ext" : "false", 603 | "saml.onetimeuse.condition" : "false" 604 | }, 605 | "fullScopeAllowed" : true, 606 | "nodeReRegistrationTimeout" : -1, 607 | "protocolMappers" : [ { 608 | "id" : "f632a9a7-5cff-4254-9941-82fabfdb3216", 609 | "name" : "role list", 610 | "protocol" : "saml", 611 | "protocolMapper" : "saml-role-list-mapper", 612 | "consentRequired" : false, 613 | "config" : { 614 | "single" : "false", 615 | "attribute.nameformat" : "Basic", 616 | "attribute.name" : "Role" 617 | } 618 | }, { 619 | "id" : "488d9ab7-7585-41dc-9d09-dd6d639b7a24", 620 | "name" : "username", 621 | "protocol" : "openid-connect", 622 | "protocolMapper" : "oidc-usermodel-property-mapper", 623 | "consentRequired" : true, 624 | "consentText" : "${username}", 625 | "config" : { 626 | "userinfo.token.claim" : "true", 627 | "user.attribute" : "username", 628 | "id.token.claim" : "true", 629 | "access.token.claim" : "true", 630 | "claim.name" : "preferred_username", 631 | "jsonType.label" : "String" 632 | } 633 | }, { 634 | "id" : "de28c7ae-a613-4f9d-8edb-1b9aa507efb9", 635 | "name" : "email", 636 | "protocol" : "openid-connect", 637 | "protocolMapper" : "oidc-usermodel-property-mapper", 638 | "consentRequired" : true, 639 | "consentText" : "${email}", 640 | "config" : { 641 | "userinfo.token.claim" : "true", 642 | "user.attribute" : "email", 643 | "id.token.claim" : "true", 644 | "access.token.claim" : "true", 645 | "claim.name" : "email", 646 | "jsonType.label" : "String" 647 | } 648 | }, { 649 | "id" : "6611aecf-daad-4ad2-aa74-c33de47037b0", 650 | "name" : "full name", 651 | "protocol" : "openid-connect", 652 | "protocolMapper" : "oidc-full-name-mapper", 653 | "consentRequired" : true, 654 | "consentText" : "${fullName}", 655 | "config" : { 656 | "id.token.claim" : "true", 657 | "access.token.claim" : "true" 658 | } 659 | }, { 660 | "id" : "cb5a11ce-3311-4a78-9061-e6221184b6f5", 661 | "name" : "given name", 662 | "protocol" : "openid-connect", 663 | "protocolMapper" : "oidc-usermodel-property-mapper", 664 | "consentRequired" : true, 665 | "consentText" : "${givenName}", 666 | "config" : { 667 | "userinfo.token.claim" : "true", 668 | "user.attribute" : "firstName", 669 | "id.token.claim" : "true", 670 | "access.token.claim" : "true", 671 | "claim.name" : "given_name", 672 | "jsonType.label" : "String" 673 | } 674 | }, { 675 | "id" : "4ec046bf-9c35-44ac-9395-fcda434fc061", 676 | "name" : "family name", 677 | "protocol" : "openid-connect", 678 | "protocolMapper" : "oidc-usermodel-property-mapper", 679 | "consentRequired" : true, 680 | "consentText" : "${familyName}", 681 | "config" : { 682 | "userinfo.token.claim" : "true", 683 | "user.attribute" : "lastName", 684 | "id.token.claim" : "true", 685 | "access.token.claim" : "true", 686 | "claim.name" : "family_name", 687 | "jsonType.label" : "String" 688 | } 689 | } ], 690 | "useTemplateConfig" : false, 691 | "useTemplateScope" : false, 692 | "useTemplateMappers" : false 693 | }, { 694 | "id" : "0536d12c-2c36-444a-898b-ed7b527aac76", 695 | "clientId" : "broker", 696 | "name" : "${client_broker}", 697 | "surrogateAuthRequired" : false, 698 | "enabled" : true, 699 | "clientAuthenticatorType" : "client-secret", 700 | "secret" : "577625be-1736-4bee-9bb2-608aff465c64", 701 | "redirectUris" : [ ], 702 | "webOrigins" : [ ], 703 | "notBefore" : 0, 704 | "bearerOnly" : false, 705 | "consentRequired" : false, 706 | "standardFlowEnabled" : true, 707 | "implicitFlowEnabled" : false, 708 | "directAccessGrantsEnabled" : false, 709 | "serviceAccountsEnabled" : false, 710 | "publicClient" : false, 711 | "frontchannelLogout" : false, 712 | "protocol" : "openid-connect", 713 | "attributes" : { }, 714 | "fullScopeAllowed" : false, 715 | "nodeReRegistrationTimeout" : 0, 716 | "protocolMappers" : [ { 717 | "id" : "5f5e550c-ff29-482d-bb1f-0215d6bf081d", 718 | "name" : "family name", 719 | "protocol" : "openid-connect", 720 | "protocolMapper" : "oidc-usermodel-property-mapper", 721 | "consentRequired" : true, 722 | "consentText" : "${familyName}", 723 | "config" : { 724 | "userinfo.token.claim" : "true", 725 | "user.attribute" : "lastName", 726 | "id.token.claim" : "true", 727 | "access.token.claim" : "true", 728 | "claim.name" : "family_name", 729 | "jsonType.label" : "String" 730 | } 731 | }, { 732 | "id" : "9239d7be-795f-4307-b0fe-ae0635fc367f", 733 | "name" : "full name", 734 | "protocol" : "openid-connect", 735 | "protocolMapper" : "oidc-full-name-mapper", 736 | "consentRequired" : true, 737 | "consentText" : "${fullName}", 738 | "config" : { 739 | "id.token.claim" : "true", 740 | "access.token.claim" : "true" 741 | } 742 | }, { 743 | "id" : "c7be1c7e-a0d2-4fe3-869c-de00d694f067", 744 | "name" : "email", 745 | "protocol" : "openid-connect", 746 | "protocolMapper" : "oidc-usermodel-property-mapper", 747 | "consentRequired" : true, 748 | "consentText" : "${email}", 749 | "config" : { 750 | "userinfo.token.claim" : "true", 751 | "user.attribute" : "email", 752 | "id.token.claim" : "true", 753 | "access.token.claim" : "true", 754 | "claim.name" : "email", 755 | "jsonType.label" : "String" 756 | } 757 | }, { 758 | "id" : "e0c76ba5-d83d-4366-9b16-7b334fa587d4", 759 | "name" : "role list", 760 | "protocol" : "saml", 761 | "protocolMapper" : "saml-role-list-mapper", 762 | "consentRequired" : false, 763 | "config" : { 764 | "single" : "false", 765 | "attribute.nameformat" : "Basic", 766 | "attribute.name" : "Role" 767 | } 768 | }, { 769 | "id" : "d97fa215-8d04-466b-8c19-a7c5f14ed1fa", 770 | "name" : "username", 771 | "protocol" : "openid-connect", 772 | "protocolMapper" : "oidc-usermodel-property-mapper", 773 | "consentRequired" : true, 774 | "consentText" : "${username}", 775 | "config" : { 776 | "userinfo.token.claim" : "true", 777 | "user.attribute" : "username", 778 | "id.token.claim" : "true", 779 | "access.token.claim" : "true", 780 | "claim.name" : "preferred_username", 781 | "jsonType.label" : "String" 782 | } 783 | }, { 784 | "id" : "b5359a60-d80b-4c5d-aa7c-ff3d1959aa9b", 785 | "name" : "given name", 786 | "protocol" : "openid-connect", 787 | "protocolMapper" : "oidc-usermodel-property-mapper", 788 | "consentRequired" : true, 789 | "consentText" : "${givenName}", 790 | "config" : { 791 | "userinfo.token.claim" : "true", 792 | "user.attribute" : "firstName", 793 | "id.token.claim" : "true", 794 | "access.token.claim" : "true", 795 | "claim.name" : "given_name", 796 | "jsonType.label" : "String" 797 | } 798 | } ], 799 | "useTemplateConfig" : false, 800 | "useTemplateScope" : false, 801 | "useTemplateMappers" : false 802 | }, { 803 | "id" : "4e57a54d-42c8-400e-9cc1-95a36fbe02fd", 804 | "clientId" : "realm-management", 805 | "name" : "${client_realm-management}", 806 | "surrogateAuthRequired" : false, 807 | "enabled" : true, 808 | "clientAuthenticatorType" : "client-secret", 809 | "secret" : "05f5e2a2-83c9-45be-bc8b-7d9c2a924ed4", 810 | "redirectUris" : [ ], 811 | "webOrigins" : [ ], 812 | "notBefore" : 0, 813 | "bearerOnly" : true, 814 | "consentRequired" : false, 815 | "standardFlowEnabled" : true, 816 | "implicitFlowEnabled" : false, 817 | "directAccessGrantsEnabled" : false, 818 | "serviceAccountsEnabled" : false, 819 | "publicClient" : false, 820 | "frontchannelLogout" : false, 821 | "protocol" : "openid-connect", 822 | "attributes" : { }, 823 | "fullScopeAllowed" : false, 824 | "nodeReRegistrationTimeout" : 0, 825 | "protocolMappers" : [ { 826 | "id" : "b699f558-b852-4013-a8c2-177abf9a8353", 827 | "name" : "full name", 828 | "protocol" : "openid-connect", 829 | "protocolMapper" : "oidc-full-name-mapper", 830 | "consentRequired" : true, 831 | "consentText" : "${fullName}", 832 | "config" : { 833 | "id.token.claim" : "true", 834 | "access.token.claim" : "true" 835 | } 836 | }, { 837 | "id" : "1377d3f0-8587-4458-8252-1f740f00dbe1", 838 | "name" : "email", 839 | "protocol" : "openid-connect", 840 | "protocolMapper" : "oidc-usermodel-property-mapper", 841 | "consentRequired" : true, 842 | "consentText" : "${email}", 843 | "config" : { 844 | "userinfo.token.claim" : "true", 845 | "user.attribute" : "email", 846 | "id.token.claim" : "true", 847 | "access.token.claim" : "true", 848 | "claim.name" : "email", 849 | "jsonType.label" : "String" 850 | } 851 | }, { 852 | "id" : "ca0e2b5c-6580-4949-80bd-fb3b87a0c7b5", 853 | "name" : "role list", 854 | "protocol" : "saml", 855 | "protocolMapper" : "saml-role-list-mapper", 856 | "consentRequired" : false, 857 | "config" : { 858 | "single" : "false", 859 | "attribute.nameformat" : "Basic", 860 | "attribute.name" : "Role" 861 | } 862 | }, { 863 | "id" : "101f9558-3e9c-4f34-b11b-b7e9f6ee7645", 864 | "name" : "family name", 865 | "protocol" : "openid-connect", 866 | "protocolMapper" : "oidc-usermodel-property-mapper", 867 | "consentRequired" : true, 868 | "consentText" : "${familyName}", 869 | "config" : { 870 | "userinfo.token.claim" : "true", 871 | "user.attribute" : "lastName", 872 | "id.token.claim" : "true", 873 | "access.token.claim" : "true", 874 | "claim.name" : "family_name", 875 | "jsonType.label" : "String" 876 | } 877 | }, { 878 | "id" : "be6fa79f-ade5-44c9-afa0-93b8170c47b9", 879 | "name" : "username", 880 | "protocol" : "openid-connect", 881 | "protocolMapper" : "oidc-usermodel-property-mapper", 882 | "consentRequired" : true, 883 | "consentText" : "${username}", 884 | "config" : { 885 | "userinfo.token.claim" : "true", 886 | "user.attribute" : "username", 887 | "id.token.claim" : "true", 888 | "access.token.claim" : "true", 889 | "claim.name" : "preferred_username", 890 | "jsonType.label" : "String" 891 | } 892 | }, { 893 | "id" : "b5d07f15-6a26-4350-9bf9-54d5359c0706", 894 | "name" : "given name", 895 | "protocol" : "openid-connect", 896 | "protocolMapper" : "oidc-usermodel-property-mapper", 897 | "consentRequired" : true, 898 | "consentText" : "${givenName}", 899 | "config" : { 900 | "userinfo.token.claim" : "true", 901 | "user.attribute" : "firstName", 902 | "id.token.claim" : "true", 903 | "access.token.claim" : "true", 904 | "claim.name" : "given_name", 905 | "jsonType.label" : "String" 906 | } 907 | } ], 908 | "useTemplateConfig" : false, 909 | "useTemplateScope" : false, 910 | "useTemplateMappers" : false 911 | }, { 912 | "id" : "8878b917-5b73-4950-b014-8100b0c405ed", 913 | "clientId" : "security-admin-console", 914 | "name" : "${client_security-admin-console}", 915 | "baseUrl" : "/auth/admin/demo/console/index.html", 916 | "surrogateAuthRequired" : false, 917 | "enabled" : true, 918 | "clientAuthenticatorType" : "client-secret", 919 | "secret" : "351b34ac-3a0f-4f09-af5a-6b9278c09b85", 920 | "redirectUris" : [ "/auth/admin/demo/console/*" ], 921 | "webOrigins" : [ ], 922 | "notBefore" : 0, 923 | "bearerOnly" : false, 924 | "consentRequired" : false, 925 | "standardFlowEnabled" : true, 926 | "implicitFlowEnabled" : false, 927 | "directAccessGrantsEnabled" : false, 928 | "serviceAccountsEnabled" : false, 929 | "publicClient" : true, 930 | "frontchannelLogout" : false, 931 | "protocol" : "openid-connect", 932 | "attributes" : { }, 933 | "fullScopeAllowed" : false, 934 | "nodeReRegistrationTimeout" : 0, 935 | "protocolMappers" : [ { 936 | "id" : "9a97567c-d9d6-4f5c-8d0f-ed1e060e598a", 937 | "name" : "role list", 938 | "protocol" : "saml", 939 | "protocolMapper" : "saml-role-list-mapper", 940 | "consentRequired" : false, 941 | "config" : { 942 | "single" : "false", 943 | "attribute.nameformat" : "Basic", 944 | "attribute.name" : "Role" 945 | } 946 | }, { 947 | "id" : "6dae9b5b-0948-4591-a69f-51a1590e892f", 948 | "name" : "username", 949 | "protocol" : "openid-connect", 950 | "protocolMapper" : "oidc-usermodel-property-mapper", 951 | "consentRequired" : true, 952 | "consentText" : "${username}", 953 | "config" : { 954 | "userinfo.token.claim" : "true", 955 | "user.attribute" : "username", 956 | "id.token.claim" : "true", 957 | "access.token.claim" : "true", 958 | "claim.name" : "preferred_username", 959 | "jsonType.label" : "String" 960 | } 961 | }, { 962 | "id" : "085240de-a1c4-4735-af6a-2c565e9612cf", 963 | "name" : "email", 964 | "protocol" : "openid-connect", 965 | "protocolMapper" : "oidc-usermodel-property-mapper", 966 | "consentRequired" : true, 967 | "consentText" : "${email}", 968 | "config" : { 969 | "userinfo.token.claim" : "true", 970 | "user.attribute" : "email", 971 | "id.token.claim" : "true", 972 | "access.token.claim" : "true", 973 | "claim.name" : "email", 974 | "jsonType.label" : "String" 975 | } 976 | }, { 977 | "id" : "594a456d-2cdb-49a3-8c40-05145a406f92", 978 | "name" : "family name", 979 | "protocol" : "openid-connect", 980 | "protocolMapper" : "oidc-usermodel-property-mapper", 981 | "consentRequired" : true, 982 | "consentText" : "${familyName}", 983 | "config" : { 984 | "userinfo.token.claim" : "true", 985 | "user.attribute" : "lastName", 986 | "id.token.claim" : "true", 987 | "access.token.claim" : "true", 988 | "claim.name" : "family_name", 989 | "jsonType.label" : "String" 990 | } 991 | }, { 992 | "id" : "00f77d41-e3d3-443d-9e0f-098379d88ca7", 993 | "name" : "given name", 994 | "protocol" : "openid-connect", 995 | "protocolMapper" : "oidc-usermodel-property-mapper", 996 | "consentRequired" : true, 997 | "consentText" : "${givenName}", 998 | "config" : { 999 | "userinfo.token.claim" : "true", 1000 | "user.attribute" : "firstName", 1001 | "id.token.claim" : "true", 1002 | "access.token.claim" : "true", 1003 | "claim.name" : "given_name", 1004 | "jsonType.label" : "String" 1005 | } 1006 | }, { 1007 | "id" : "b12cbc25-fe43-4597-84e5-77b506712186", 1008 | "name" : "full name", 1009 | "protocol" : "openid-connect", 1010 | "protocolMapper" : "oidc-full-name-mapper", 1011 | "consentRequired" : true, 1012 | "consentText" : "${fullName}", 1013 | "config" : { 1014 | "id.token.claim" : "true", 1015 | "access.token.claim" : "true" 1016 | } 1017 | }, { 1018 | "id" : "08f6ee38-4048-407a-8baa-a2e770ae5123", 1019 | "name" : "locale", 1020 | "protocol" : "openid-connect", 1021 | "protocolMapper" : "oidc-usermodel-attribute-mapper", 1022 | "consentRequired" : false, 1023 | "consentText" : "${locale}", 1024 | "config" : { 1025 | "userinfo.token.claim" : "true", 1026 | "user.attribute" : "locale", 1027 | "id.token.claim" : "true", 1028 | "access.token.claim" : "true", 1029 | "claim.name" : "locale", 1030 | "jsonType.label" : "String" 1031 | } 1032 | } ], 1033 | "useTemplateConfig" : false, 1034 | "useTemplateScope" : false, 1035 | "useTemplateMappers" : false 1036 | } ], 1037 | "clientTemplates" : [ ], 1038 | "browserSecurityHeaders" : { 1039 | "xContentTypeOptions" : "nosniff", 1040 | "xRobotsTag" : "none", 1041 | "xFrameOptions" : "SAMEORIGIN", 1042 | "xXSSProtection" : "1; mode=block", 1043 | "contentSecurityPolicy" : "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", 1044 | "strictTransportSecurity" : "max-age=31536000; includeSubDomains" 1045 | }, 1046 | "smtpServer" : { }, 1047 | "eventsEnabled" : false, 1048 | "eventsListeners" : [ "jboss-logging" ], 1049 | "enabledEventTypes" : [ ], 1050 | "adminEventsEnabled" : false, 1051 | "adminEventsDetailsEnabled" : false, 1052 | "components" : { 1053 | "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy" : [ { 1054 | "id" : "6908d5c3-07a7-4c00-91d7-462affb7425a", 1055 | "name" : "Consent Required", 1056 | "providerId" : "consent-required", 1057 | "subType" : "anonymous", 1058 | "subComponents" : { }, 1059 | "config" : { } 1060 | }, { 1061 | "id" : "f2fbbda7-bc89-474c-80cd-c7817d27e852", 1062 | "name" : "Allowed Client Templates", 1063 | "providerId" : "allowed-client-templates", 1064 | "subType" : "anonymous", 1065 | "subComponents" : { }, 1066 | "config" : { } 1067 | }, { 1068 | "id" : "e98e7d78-69d1-4f78-86a9-6aac95c7ce28", 1069 | "name" : "Trusted Hosts", 1070 | "providerId" : "trusted-hosts", 1071 | "subType" : "anonymous", 1072 | "subComponents" : { }, 1073 | "config" : { 1074 | "host-sending-registration-request-must-match" : [ "true" ], 1075 | "client-uris-must-match" : [ "true" ] 1076 | } 1077 | }, { 1078 | "id" : "9643017a-e4a3-435e-9c92-a14298a5f7ed", 1079 | "name" : "Allowed Protocol Mapper Types", 1080 | "providerId" : "allowed-protocol-mappers", 1081 | "subType" : "anonymous", 1082 | "subComponents" : { }, 1083 | "config" : { 1084 | "allowed-protocol-mapper-types" : [ "saml-user-attribute-mapper", "saml-user-property-mapper", "saml-role-list-mapper", "oidc-usermodel-attribute-mapper", "oidc-full-name-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-usermodel-property-mapper", "oidc-address-mapper" ], 1085 | "consent-required-for-all-mappers" : [ "true" ] 1086 | } 1087 | }, { 1088 | "id" : "a72ad67b-392d-462b-a24d-359584948a39", 1089 | "name" : "Max Clients Limit", 1090 | "providerId" : "max-clients", 1091 | "subType" : "anonymous", 1092 | "subComponents" : { }, 1093 | "config" : { 1094 | "max-clients" : [ "200" ] 1095 | } 1096 | }, { 1097 | "id" : "39d518a7-6678-415f-aee0-497ddf0bbb8f", 1098 | "name" : "Allowed Protocol Mapper Types", 1099 | "providerId" : "allowed-protocol-mappers", 1100 | "subType" : "authenticated", 1101 | "subComponents" : { }, 1102 | "config" : { 1103 | "allowed-protocol-mapper-types" : [ "oidc-usermodel-property-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-full-name-mapper", "oidc-address-mapper", "saml-role-list-mapper", "saml-user-attribute-mapper", "oidc-usermodel-attribute-mapper", "saml-user-property-mapper" ], 1104 | "consent-required-for-all-mappers" : [ "true" ] 1105 | } 1106 | }, { 1107 | "id" : "f690379c-6479-4533-ac55-660d4d519849", 1108 | "name" : "Full Scope Disabled", 1109 | "providerId" : "scope", 1110 | "subType" : "anonymous", 1111 | "subComponents" : { }, 1112 | "config" : { } 1113 | }, { 1114 | "id" : "fda00934-5922-4028-9e7c-c123100c248f", 1115 | "name" : "Allowed Client Templates", 1116 | "providerId" : "allowed-client-templates", 1117 | "subType" : "authenticated", 1118 | "subComponents" : { }, 1119 | "config" : { } 1120 | } ], 1121 | "org.keycloak.keys.KeyProvider" : [ { 1122 | "id" : "1cf453a3-7702-4d4d-8614-72c1fc6b17b6", 1123 | "name" : "hmac-generated", 1124 | "providerId" : "hmac-generated", 1125 | "subComponents" : { }, 1126 | "config" : { 1127 | "kid" : [ "012044b2-dfa4-49cb-a4c5-916c19f9b96e" ], 1128 | "secret" : [ "nEC6RCMTKBsF49bfzb3Vv21Vh4TLEaFiRAfvQp2YOOE" ], 1129 | "priority" : [ "100" ] 1130 | } 1131 | }, { 1132 | "id" : "83881f72-2def-46a5-b8ba-99ad0b1e4c95", 1133 | "name" : "rsa-generated", 1134 | "providerId" : "rsa-generated", 1135 | "subComponents" : { }, 1136 | "config" : { 1137 | "privateKey" : [ "MIIEowIBAAKCAQEAjc06HxUS54Afmxiw0GXEcD8LS05UVU5KF0hc77CPuT6Sj9atTc1ccRinc24QuE2YdTtYGpELsYGkyul+5r6849vbCsQdcrq1JpLhre/renbjUWz9wBqlphIwPcAR7sSJKHnh+g5K+iOQ7AQaiJGo+tlZrXKfERnahTNVWaZHCIM+82oUvyFaXhV0XyhxQy9RtDq47GnWEgZ9xCvCWPDZJjG6Gm/6rIfZpdqqN5h8GqsOoCUxnLJS0XZP/8Gt/oZF/Y8yMKrOigs83hm1ireMFZDsGgp+z/8+m92CpbASSbO5HXbphO9LZQTZ0BFHHH7DBjF9QZeifQbUH1tyGMzDLQIDAQABAoIBAAavkHf6tGN55QOZDG0m/zYTouKwFMXY5SFn5gnfF0eyrZJemtk6P4uNkAefPuaRsgiE/chy4kxCQpTWoYcboyhTK2a8jG7mYrgo4L8kusORa3JhYy11lC3aWa/vqGjLl3PzGzaBCgP1PVYDc4TQ6Vi6esH0z48s2uLA4ttRPbQm+gJWMTmJpLNydDUBzuQT6OERald4/Ssp0qgZm0Y5WUu0mMiRT8LhNMzJNbZt3S/a22lKA1G/HpyaFD9Fb5hq09TyJqHefzbrWCg6sch8+tKvH6mxqHV2TmrLUtMHzW7tC0tkMh2MShzqqEIYNVFuqzAMEzNczrAYk2L1J2u0JjkCgYEAzWzZW3w9IGAq2yfCiHic3WpgWyadZGHJXRq/x7bkXxowtaHi2A4yc4x0obGbSvqPvFRlYt2v9f5XLmDGLVvS34BeHbZIEK1GUV+5lpzejJ1GkYdSnhPquLbmRkDrYG1a/dU4DLSKvKc45jmhwRdheeTvFW3z1XZqshrTIxBwwLsCgYEAsLZvShoO9M5uhWCnsvMZ6gRm7Nw5FmCfZm0WM1Cj9mWngFCcWhxZEheTOhiqNcnGi8e8xlDJAI4iimUD4ZRqeTs/CIvbHNq8DICf6aSMAaba+jxycEzVu/xZsNkzV1SaKcPll+fjV8vRKA0JAaioQMkrmhRCsu/ODNjo4MYd4TcCgYB3b8oQfvOrVz6TnVJltnq94ZOUa6cnLhO9pkfK/nNZOAkKEc2qgNakiA1n1bPMrFHV1dv815fvFqnptSqERNceS6xs6gaMa7JurZFiGGLsrqTRCDTo4/uc2fqY7jXsIqi83LNx76aaeT+D3A5IDigGjyzS8NLMUcVHOIF56Z0k8QKBgAstLrLAHSwMll7nMxQVXhE4AA6BCzdIGyzOP3Y1ZnliCosKDimA231ScmRdRP6r6VvT4TOlzmCznKmmI+2zhlxui9kNh2k2yGf+Bp8vYg+ErxrekdpacbY3CrEtu5qNZka39iB6cR2PbYYb9PLe6O1YC+Lt3x4UHrMfUPNOdHtXAoGBAKpncRXGyL05nnzFvK68BfoxSpd4aJk0Wkr9nOxZGFJj8v/LeUuxN6LOGqw4z8Sfdx3AI/6+JJAWk9sUlQ4ejAMFwR67UXI1eLkvs5x+U9g6DaZUMpgTUQhkfinZ3b822L6B20O+5Xz6aOGDbcWR+X/MAyj/gfnYR/TvXCq5v+sE" ], 1138 | "certificate" : [ "MIIClzCCAX8CBgFi1H8iNDANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARkZW1vMB4XDTE4MDQxNzE2NDM0NFoXDTI4MDQxNzE2NDUyNFowDzENMAsGA1UEAwwEZGVtbzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAI3NOh8VEueAH5sYsNBlxHA/C0tOVFVOShdIXO+wj7k+ko/WrU3NXHEYp3NuELhNmHU7WBqRC7GBpMrpfua+vOPb2wrEHXK6tSaS4a3v63p241Fs/cAapaYSMD3AEe7EiSh54foOSvojkOwEGoiRqPrZWa1ynxEZ2oUzVVmmRwiDPvNqFL8hWl4VdF8ocUMvUbQ6uOxp1hIGfcQrwljw2SYxuhpv+qyH2aXaqjeYfBqrDqAlMZyyUtF2T//Brf6GRf2PMjCqzooLPN4ZtYq3jBWQ7BoKfs//PpvdgqWwEkmzuR126YTvS2UE2dARRxx+wwYxfUGXon0G1B9bchjMwy0CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAavonr2grkWPCSLDRRCyTly2q/By5FYhkN5Bu7c2pxQy/k1OKJUBz+GIPxSL6MrPmHoWHM9fpD9nLCa1VHbHkEiu9p0c+2CDPVAyYvVbADVdgL+xp19TMyvETMfS1tJKVyJbqL8RsxzjWm1qI19VmVWNNHUGXpuPp35DL5tL/RkooY6+oNamsiNwR6xXmfqY7l6w8HA4y8It3yaeHy6N2ffjI/2AtXTyISuEEv1Lybr5op4jKRYLqv+ly7aBeNIGGnHFXlGyCqv8dSWSYXA1S83x4LeTHrj7rAC4fORY2Q5VNmhUAYYE5Vy+zxAHSoQn+cEf2qJsr9xRlYy8nzyXukw==" ], 1139 | "priority" : [ "100" ] 1140 | } 1141 | }, { 1142 | "id" : "46800710-eced-4804-a79e-32f7c5797b04", 1143 | "name" : "aes-generated", 1144 | "providerId" : "aes-generated", 1145 | "subComponents" : { }, 1146 | "config" : { 1147 | "kid" : [ "2b922283-df55-4424-8bef-3f2ff5ba0bfa" ], 1148 | "secret" : [ "Ry49w356XdzGeEQbsupsvA" ], 1149 | "priority" : [ "100" ] 1150 | } 1151 | } ] 1152 | }, 1153 | "internationalizationEnabled" : false, 1154 | "supportedLocales" : [ ], 1155 | "authenticationFlows" : [ { 1156 | "id" : "a48d9b79-b52f-4d29-b831-ecb9098352ad", 1157 | "alias" : "Handle Existing Account", 1158 | "description" : "Handle what to do if there is existing account with same email/username like authenticated identity provider", 1159 | "providerId" : "basic-flow", 1160 | "topLevel" : false, 1161 | "builtIn" : true, 1162 | "authenticationExecutions" : [ { 1163 | "authenticator" : "idp-confirm-link", 1164 | "requirement" : "REQUIRED", 1165 | "priority" : 10, 1166 | "userSetupAllowed" : false, 1167 | "autheticatorFlow" : false 1168 | }, { 1169 | "authenticator" : "idp-email-verification", 1170 | "requirement" : "ALTERNATIVE", 1171 | "priority" : 20, 1172 | "userSetupAllowed" : false, 1173 | "autheticatorFlow" : false 1174 | }, { 1175 | "requirement" : "ALTERNATIVE", 1176 | "priority" : 30, 1177 | "flowAlias" : "Verify Existing Account by Re-authentication", 1178 | "userSetupAllowed" : false, 1179 | "autheticatorFlow" : true 1180 | } ] 1181 | }, { 1182 | "id" : "03731267-4cd9-478d-ac04-403d1d832d46", 1183 | "alias" : "Verify Existing Account by Re-authentication", 1184 | "description" : "Reauthentication of existing account", 1185 | "providerId" : "basic-flow", 1186 | "topLevel" : false, 1187 | "builtIn" : true, 1188 | "authenticationExecutions" : [ { 1189 | "authenticator" : "idp-username-password-form", 1190 | "requirement" : "REQUIRED", 1191 | "priority" : 10, 1192 | "userSetupAllowed" : false, 1193 | "autheticatorFlow" : false 1194 | }, { 1195 | "authenticator" : "auth-otp-form", 1196 | "requirement" : "OPTIONAL", 1197 | "priority" : 20, 1198 | "userSetupAllowed" : false, 1199 | "autheticatorFlow" : false 1200 | } ] 1201 | }, { 1202 | "id" : "bb3fec2b-49dc-4ca3-bb31-8acb74b3e1bd", 1203 | "alias" : "browser", 1204 | "description" : "browser based authentication", 1205 | "providerId" : "basic-flow", 1206 | "topLevel" : true, 1207 | "builtIn" : true, 1208 | "authenticationExecutions" : [ { 1209 | "authenticator" : "auth-cookie", 1210 | "requirement" : "ALTERNATIVE", 1211 | "priority" : 10, 1212 | "userSetupAllowed" : false, 1213 | "autheticatorFlow" : false 1214 | }, { 1215 | "authenticator" : "auth-spnego", 1216 | "requirement" : "DISABLED", 1217 | "priority" : 20, 1218 | "userSetupAllowed" : false, 1219 | "autheticatorFlow" : false 1220 | }, { 1221 | "authenticator" : "identity-provider-redirector", 1222 | "requirement" : "ALTERNATIVE", 1223 | "priority" : 25, 1224 | "userSetupAllowed" : false, 1225 | "autheticatorFlow" : false 1226 | }, { 1227 | "requirement" : "ALTERNATIVE", 1228 | "priority" : 30, 1229 | "flowAlias" : "forms", 1230 | "userSetupAllowed" : false, 1231 | "autheticatorFlow" : true 1232 | } ] 1233 | }, { 1234 | "id" : "84567fef-a17f-424c-9f30-c5ae041beeee", 1235 | "alias" : "clients", 1236 | "description" : "Base authentication for clients", 1237 | "providerId" : "client-flow", 1238 | "topLevel" : true, 1239 | "builtIn" : true, 1240 | "authenticationExecutions" : [ { 1241 | "authenticator" : "client-secret", 1242 | "requirement" : "ALTERNATIVE", 1243 | "priority" : 10, 1244 | "userSetupAllowed" : false, 1245 | "autheticatorFlow" : false 1246 | }, { 1247 | "authenticator" : "client-jwt", 1248 | "requirement" : "ALTERNATIVE", 1249 | "priority" : 20, 1250 | "userSetupAllowed" : false, 1251 | "autheticatorFlow" : false 1252 | } ] 1253 | }, { 1254 | "id" : "731a2721-79ff-46ec-8dcb-ea7d19f86d33", 1255 | "alias" : "direct grant", 1256 | "description" : "OpenID Connect Resource Owner Grant", 1257 | "providerId" : "basic-flow", 1258 | "topLevel" : true, 1259 | "builtIn" : true, 1260 | "authenticationExecutions" : [ { 1261 | "authenticator" : "direct-grant-validate-username", 1262 | "requirement" : "REQUIRED", 1263 | "priority" : 10, 1264 | "userSetupAllowed" : false, 1265 | "autheticatorFlow" : false 1266 | }, { 1267 | "authenticator" : "direct-grant-validate-password", 1268 | "requirement" : "REQUIRED", 1269 | "priority" : 20, 1270 | "userSetupAllowed" : false, 1271 | "autheticatorFlow" : false 1272 | }, { 1273 | "authenticator" : "direct-grant-validate-otp", 1274 | "requirement" : "OPTIONAL", 1275 | "priority" : 30, 1276 | "userSetupAllowed" : false, 1277 | "autheticatorFlow" : false 1278 | } ] 1279 | }, { 1280 | "id" : "3c5c6d83-ccb5-420d-8370-253c43a6d598", 1281 | "alias" : "docker auth", 1282 | "description" : "Used by Docker clients to authenticate against the IDP", 1283 | "providerId" : "basic-flow", 1284 | "topLevel" : true, 1285 | "builtIn" : true, 1286 | "authenticationExecutions" : [ { 1287 | "authenticator" : "docker-http-basic-authenticator", 1288 | "requirement" : "REQUIRED", 1289 | "priority" : 10, 1290 | "userSetupAllowed" : false, 1291 | "autheticatorFlow" : false 1292 | } ] 1293 | }, { 1294 | "id" : "81f1a3b5-7737-4351-a4bd-25e98b536798", 1295 | "alias" : "first broker login", 1296 | "description" : "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", 1297 | "providerId" : "basic-flow", 1298 | "topLevel" : true, 1299 | "builtIn" : true, 1300 | "authenticationExecutions" : [ { 1301 | "authenticatorConfig" : "review profile config", 1302 | "authenticator" : "idp-review-profile", 1303 | "requirement" : "REQUIRED", 1304 | "priority" : 10, 1305 | "userSetupAllowed" : false, 1306 | "autheticatorFlow" : false 1307 | }, { 1308 | "authenticatorConfig" : "create unique user config", 1309 | "authenticator" : "idp-create-user-if-unique", 1310 | "requirement" : "ALTERNATIVE", 1311 | "priority" : 20, 1312 | "userSetupAllowed" : false, 1313 | "autheticatorFlow" : false 1314 | }, { 1315 | "requirement" : "ALTERNATIVE", 1316 | "priority" : 30, 1317 | "flowAlias" : "Handle Existing Account", 1318 | "userSetupAllowed" : false, 1319 | "autheticatorFlow" : true 1320 | } ] 1321 | }, { 1322 | "id" : "46ba7967-ea06-45e3-98af-11200a34473e", 1323 | "alias" : "forms", 1324 | "description" : "Username, password, otp and other auth forms.", 1325 | "providerId" : "basic-flow", 1326 | "topLevel" : false, 1327 | "builtIn" : true, 1328 | "authenticationExecutions" : [ { 1329 | "authenticator" : "auth-username-password-form", 1330 | "requirement" : "REQUIRED", 1331 | "priority" : 10, 1332 | "userSetupAllowed" : false, 1333 | "autheticatorFlow" : false 1334 | }, { 1335 | "authenticator" : "auth-otp-form", 1336 | "requirement" : "OPTIONAL", 1337 | "priority" : 20, 1338 | "userSetupAllowed" : false, 1339 | "autheticatorFlow" : false 1340 | } ] 1341 | }, { 1342 | "id" : "4f2620ae-bb89-4d85-b81e-6e5d20c78a47", 1343 | "alias" : "registration", 1344 | "description" : "registration flow", 1345 | "providerId" : "basic-flow", 1346 | "topLevel" : true, 1347 | "builtIn" : true, 1348 | "authenticationExecutions" : [ { 1349 | "authenticator" : "registration-page-form", 1350 | "requirement" : "REQUIRED", 1351 | "priority" : 10, 1352 | "flowAlias" : "registration form", 1353 | "userSetupAllowed" : false, 1354 | "autheticatorFlow" : true 1355 | } ] 1356 | }, { 1357 | "id" : "7fb032fb-dac9-4ea8-9d63-678753437440", 1358 | "alias" : "registration form", 1359 | "description" : "registration form", 1360 | "providerId" : "form-flow", 1361 | "topLevel" : false, 1362 | "builtIn" : true, 1363 | "authenticationExecutions" : [ { 1364 | "authenticator" : "registration-user-creation", 1365 | "requirement" : "REQUIRED", 1366 | "priority" : 20, 1367 | "userSetupAllowed" : false, 1368 | "autheticatorFlow" : false 1369 | }, { 1370 | "authenticator" : "registration-profile-action", 1371 | "requirement" : "REQUIRED", 1372 | "priority" : 40, 1373 | "userSetupAllowed" : false, 1374 | "autheticatorFlow" : false 1375 | }, { 1376 | "authenticator" : "registration-password-action", 1377 | "requirement" : "REQUIRED", 1378 | "priority" : 50, 1379 | "userSetupAllowed" : false, 1380 | "autheticatorFlow" : false 1381 | }, { 1382 | "authenticator" : "registration-recaptcha-action", 1383 | "requirement" : "DISABLED", 1384 | "priority" : 60, 1385 | "userSetupAllowed" : false, 1386 | "autheticatorFlow" : false 1387 | } ] 1388 | }, { 1389 | "id" : "75600e80-cae6-4347-a506-ddf6477cd7e9", 1390 | "alias" : "reset credentials", 1391 | "description" : "Reset credentials for a user if they forgot their password or something", 1392 | "providerId" : "basic-flow", 1393 | "topLevel" : true, 1394 | "builtIn" : true, 1395 | "authenticationExecutions" : [ { 1396 | "authenticator" : "reset-credentials-choose-user", 1397 | "requirement" : "REQUIRED", 1398 | "priority" : 10, 1399 | "userSetupAllowed" : false, 1400 | "autheticatorFlow" : false 1401 | }, { 1402 | "authenticator" : "reset-credential-email", 1403 | "requirement" : "REQUIRED", 1404 | "priority" : 20, 1405 | "userSetupAllowed" : false, 1406 | "autheticatorFlow" : false 1407 | }, { 1408 | "authenticator" : "reset-password", 1409 | "requirement" : "REQUIRED", 1410 | "priority" : 30, 1411 | "userSetupAllowed" : false, 1412 | "autheticatorFlow" : false 1413 | }, { 1414 | "authenticator" : "reset-otp", 1415 | "requirement" : "OPTIONAL", 1416 | "priority" : 40, 1417 | "userSetupAllowed" : false, 1418 | "autheticatorFlow" : false 1419 | } ] 1420 | }, { 1421 | "id" : "4990dbc0-bb0b-48b5-8f72-945adcf77d39", 1422 | "alias" : "saml ecp", 1423 | "description" : "SAML ECP Profile Authentication Flow", 1424 | "providerId" : "basic-flow", 1425 | "topLevel" : true, 1426 | "builtIn" : true, 1427 | "authenticationExecutions" : [ { 1428 | "authenticator" : "http-basic-authenticator", 1429 | "requirement" : "REQUIRED", 1430 | "priority" : 10, 1431 | "userSetupAllowed" : false, 1432 | "autheticatorFlow" : false 1433 | } ] 1434 | } ], 1435 | "authenticatorConfig" : [ { 1436 | "id" : "da120730-f96f-4a0b-9f97-48d63823b067", 1437 | "alias" : "create unique user config", 1438 | "config" : { 1439 | "require.password.update.after.registration" : "false" 1440 | } 1441 | }, { 1442 | "id" : "0c76ade9-f703-4606-bae9-28f0bf131e11", 1443 | "alias" : "review profile config", 1444 | "config" : { 1445 | "update.profile.on.first.login" : "missing" 1446 | } 1447 | } ], 1448 | "requiredActions" : [ { 1449 | "alias" : "CONFIGURE_TOTP", 1450 | "name" : "Configure OTP", 1451 | "providerId" : "CONFIGURE_TOTP", 1452 | "enabled" : true, 1453 | "defaultAction" : false, 1454 | "config" : { } 1455 | }, { 1456 | "alias" : "UPDATE_PASSWORD", 1457 | "name" : "Update Password", 1458 | "providerId" : "UPDATE_PASSWORD", 1459 | "enabled" : true, 1460 | "defaultAction" : false, 1461 | "config" : { } 1462 | }, { 1463 | "alias" : "UPDATE_PROFILE", 1464 | "name" : "Update Profile", 1465 | "providerId" : "UPDATE_PROFILE", 1466 | "enabled" : true, 1467 | "defaultAction" : false, 1468 | "config" : { } 1469 | }, { 1470 | "alias" : "VERIFY_EMAIL", 1471 | "name" : "Verify Email", 1472 | "providerId" : "VERIFY_EMAIL", 1473 | "enabled" : true, 1474 | "defaultAction" : false, 1475 | "config" : { } 1476 | }, { 1477 | "alias" : "terms_and_conditions", 1478 | "name" : "Terms and Conditions", 1479 | "providerId" : "terms_and_conditions", 1480 | "enabled" : false, 1481 | "defaultAction" : false, 1482 | "config" : { } 1483 | } ], 1484 | "browserFlow" : "browser", 1485 | "registrationFlow" : "registration", 1486 | "directGrantFlow" : "direct grant", 1487 | "resetCredentialsFlow" : "reset credentials", 1488 | "clientAuthenticationFlow" : "clients", 1489 | "dockerAuthenticationFlow" : "docker auth", 1490 | "attributes" : { 1491 | "_browser_header.xXSSProtection" : "1; mode=block", 1492 | "_browser_header.xFrameOptions" : "SAMEORIGIN", 1493 | "_browser_header.strictTransportSecurity" : "max-age=31536000; includeSubDomains", 1494 | "permanentLockout" : "false", 1495 | "quickLoginCheckMilliSeconds" : "1000", 1496 | "_browser_header.xRobotsTag" : "none", 1497 | "maxFailureWaitSeconds" : "900", 1498 | "minimumQuickLoginWaitSeconds" : "60", 1499 | "failureFactor" : "30", 1500 | "actionTokenGeneratedByUserLifespan" : "300", 1501 | "maxDeltaTimeSeconds" : "43200", 1502 | "_browser_header.xContentTypeOptions" : "nosniff", 1503 | "actionTokenGeneratedByAdminLifespan" : "43200", 1504 | "bruteForceProtected" : "false", 1505 | "_browser_header.contentSecurityPolicy" : "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", 1506 | "waitIncrementSeconds" : "60" 1507 | }, 1508 | "keycloakVersion" : "3.4.3.Final" 1509 | } --------------------------------------------------------------------------------