From 07dc4d12727729731d8b8f1ea2ebb6ce3d99ec6c Mon Sep 17 00:00:00 2001 From: "kateryna.hrytsaenko" Date: Sun, 24 Mar 2024 22:18:28 +0200 Subject: [PATCH 01/33] BAEL-7445, generate schema with plugin --- .../gradle-avro/.gitattributes | 9 + .../gradle-avro/.gitignore | 5 + .../gradle-avro/README.md | 1 + .../gradle-avro/build.gradle | 25 ++ .../gradle-avro/gradle/libs.versions.toml | 12 + .../gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 43462 bytes .../gradle/wrapper/gradle-wrapper.properties | 7 + .../gradle-customization/gradle-avro/gradlew | 249 ++++++++++++++++++ .../gradle-avro/gradlew.bat | 92 +++++++ .../gradle-avro/settings.gradle | 2 + .../gradle-avro/src/main/avro/user.avsc | 10 + .../AvroCodeGenerationUnitTest.java | 26 ++ 12 files changed, 438 insertions(+) create mode 100644 gradle-modules/gradle-customization/gradle-avro/.gitattributes create mode 100644 gradle-modules/gradle-customization/gradle-avro/.gitignore create mode 100644 gradle-modules/gradle-customization/gradle-avro/README.md create mode 100644 gradle-modules/gradle-customization/gradle-avro/build.gradle create mode 100644 gradle-modules/gradle-customization/gradle-avro/gradle/libs.versions.toml create mode 100644 gradle-modules/gradle-customization/gradle-avro/gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle-modules/gradle-customization/gradle-avro/gradle/wrapper/gradle-wrapper.properties create mode 100755 gradle-modules/gradle-customization/gradle-avro/gradlew create mode 100644 gradle-modules/gradle-customization/gradle-avro/gradlew.bat create mode 100644 gradle-modules/gradle-customization/gradle-avro/settings.gradle create mode 100644 gradle-modules/gradle-customization/gradle-avro/src/main/avro/user.avsc create mode 100644 gradle-modules/gradle-customization/gradle-avro/src/test/java/com.baeldung.avro/AvroCodeGenerationUnitTest.java diff --git a/gradle-modules/gradle-customization/gradle-avro/.gitattributes b/gradle-modules/gradle-customization/gradle-avro/.gitattributes new file mode 100644 index 0000000000..097f9f98d9 --- /dev/null +++ b/gradle-modules/gradle-customization/gradle-avro/.gitattributes @@ -0,0 +1,9 @@ +# +# https://help.github.com/articles/dealing-with-line-endings/ +# +# Linux start script should use lf +/gradlew text eol=lf + +# These are Windows script files and should use crlf +*.bat text eol=crlf + diff --git a/gradle-modules/gradle-customization/gradle-avro/.gitignore b/gradle-modules/gradle-customization/gradle-avro/.gitignore new file mode 100644 index 0000000000..1b6985c009 --- /dev/null +++ b/gradle-modules/gradle-customization/gradle-avro/.gitignore @@ -0,0 +1,5 @@ +# Ignore Gradle project-specific cache directory +.gradle + +# Ignore Gradle build output directory +build diff --git a/gradle-modules/gradle-customization/gradle-avro/README.md b/gradle-modules/gradle-customization/gradle-avro/README.md new file mode 100644 index 0000000000..5616cce48b --- /dev/null +++ b/gradle-modules/gradle-customization/gradle-avro/README.md @@ -0,0 +1 @@ +## Relevant Articles diff --git a/gradle-modules/gradle-customization/gradle-avro/build.gradle b/gradle-modules/gradle-customization/gradle-avro/build.gradle new file mode 100644 index 0000000000..a81886cc22 --- /dev/null +++ b/gradle-modules/gradle-customization/gradle-avro/build.gradle @@ -0,0 +1,25 @@ +plugins { + id 'java' + alias libs.plugins.avro +} + +repositories { + mavenCentral() +} + +dependencies { + implementation libs.avro + // Use JUnit Jupiter for testing. + testImplementation libs.junit.jupiter + + testRuntimeOnly 'org.junit.platform:junit-platform-launcher' + +} + +sourceCompatibility = JavaVersion.VERSION_21 +targetCompatibility = JavaVersion.VERSION_21 + +tasks.named('test') { + // Use JUnit Platform for unit tests. + useJUnitPlatform() +} diff --git a/gradle-modules/gradle-customization/gradle-avro/gradle/libs.versions.toml b/gradle-modules/gradle-customization/gradle-avro/gradle/libs.versions.toml new file mode 100644 index 0000000000..6c2cee93b8 --- /dev/null +++ b/gradle-modules/gradle-customization/gradle-avro/gradle/libs.versions.toml @@ -0,0 +1,12 @@ +# This file was generated by the Gradle 'init' task. +# https://docs.gradle.org/current/userguide/platforms.html#sub::toml-dependencies-format + +[versions] +junit-jupiter = "5.10.0" + +[libraries] +junit-jupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit-jupiter" } +avro = {module = "org.apache.avro:avro", version = "1.11.0"} + +[plugins] +avro = { id = "com.github.davidmc24.gradle.plugin.avro", version = "1.9.1" } diff --git a/gradle-modules/gradle-customization/gradle-avro/gradle/wrapper/gradle-wrapper.jar b/gradle-modules/gradle-customization/gradle-avro/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..d64cd4917707c1f8861d8cb53dd15194d4248596 GIT binary patch literal 43462 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 literal 0 HcmV?d00001 diff --git a/gradle-modules/gradle-customization/gradle-avro/gradle/wrapper/gradle-wrapper.properties b/gradle-modules/gradle-customization/gradle-avro/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000..1af9e0930b --- /dev/null +++ b/gradle-modules/gradle-customization/gradle-avro/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradle-modules/gradle-customization/gradle-avro/gradlew b/gradle-modules/gradle-customization/gradle-avro/gradlew new file mode 100755 index 0000000000..1aa94a4269 --- /dev/null +++ b/gradle-modules/gradle-customization/gradle-avro/gradlew @@ -0,0 +1,249 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradle-modules/gradle-customization/gradle-avro/gradlew.bat b/gradle-modules/gradle-customization/gradle-avro/gradlew.bat new file mode 100644 index 0000000000..93e3f59f13 --- /dev/null +++ b/gradle-modules/gradle-customization/gradle-avro/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/gradle-modules/gradle-customization/gradle-avro/settings.gradle b/gradle-modules/gradle-customization/gradle-avro/settings.gradle new file mode 100644 index 0000000000..640d0840ef --- /dev/null +++ b/gradle-modules/gradle-customization/gradle-avro/settings.gradle @@ -0,0 +1,2 @@ +rootProject.name = 'gradle-avro' + diff --git a/gradle-modules/gradle-customization/gradle-avro/src/main/avro/user.avsc b/gradle-modules/gradle-customization/gradle-avro/src/main/avro/user.avsc new file mode 100644 index 0000000000..0936672532 --- /dev/null +++ b/gradle-modules/gradle-customization/gradle-avro/src/main/avro/user.avsc @@ -0,0 +1,10 @@ +{ + "type": "record", + "name": "User", + "namespace": "com.example", + "fields": [ + { "name": "firstName", "type": "string" }, + { "name": "lastName", "type": "string" }, + { "name": "phoneNumber", "type": "string" } + ] +} diff --git a/gradle-modules/gradle-customization/gradle-avro/src/test/java/com.baeldung.avro/AvroCodeGenerationUnitTest.java b/gradle-modules/gradle-customization/gradle-avro/src/test/java/com.baeldung.avro/AvroCodeGenerationUnitTest.java new file mode 100644 index 0000000000..57b3b98bb8 --- /dev/null +++ b/gradle-modules/gradle-customization/gradle-avro/src/test/java/com.baeldung.avro/AvroCodeGenerationUnitTest.java @@ -0,0 +1,26 @@ +package com.baeldung.avro; + +import com.example.User; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class AvroCodeGenerationUnitTest { + + @Test + void givenUserData_whenObjectCreated_thenDataShouldMatch() { + final String firstName = "John"; + final String lastName = "Doe"; + final String phoneNumber = "+380659443235"; + + User user = User.newBuilder() + .setFirstName(firstName) + .setLastName(lastName) + .setPhoneNumber(phoneNumber) + .build(); + + assertEquals(firstName, user.getFirstName()); + assertEquals(lastName, user.getLastName()); + assertEquals(phoneNumber, user.getPhoneNumber()); + } +} From 8753641feefd024a5d60cef1d9f3e95eecd694c5 Mon Sep 17 00:00:00 2001 From: "kateryna.hrytsaenko" Date: Sun, 24 Mar 2024 22:51:46 +0200 Subject: [PATCH 02/33] BAEL-7445, add custom task --- .../gradle-avro/build.gradle | 38 +++++++++++++++++++ .../gradle-avro/gradle/libs.versions.toml | 4 +- .../gradle-avro/src/main/avro/user.avsc | 25 ++++++++---- .../gradle-avro/src/main/custom/Pet.avsc | 11 ++++++ .../AvroCodeGenerationUnitTest.java | 26 ++++++++++++- 5 files changed, 93 insertions(+), 11 deletions(-) create mode 100644 gradle-modules/gradle-customization/gradle-avro/src/main/custom/Pet.avsc diff --git a/gradle-modules/gradle-customization/gradle-avro/build.gradle b/gradle-modules/gradle-customization/gradle-avro/build.gradle index a81886cc22..7a9565cb0c 100644 --- a/gradle-modules/gradle-customization/gradle-avro/build.gradle +++ b/gradle-modules/gradle-customization/gradle-avro/build.gradle @@ -1,3 +1,9 @@ +buildscript { + dependencies { + classpath libs.avro.tools + } +} + plugins { id 'java' alias libs.plugins.avro @@ -16,9 +22,41 @@ dependencies { } +import org.apache.avro.tool.SpecificCompilerTool + sourceCompatibility = JavaVersion.VERSION_21 targetCompatibility = JavaVersion.VERSION_21 +def avroSchemasDir = "src/main/custom" +def avroCodeGenerationDir = "build/generated-main-avro-custom-java" + +// Add the generated Avro Java code to the Gradle source files. +sourceSets.main.java.srcDirs += [avroCodeGenerationDir] + +tasks.register('customAvroCodeGeneration') { + // Define the task inputs and outputs for the Gradle up-to-date checks. + inputs.dir(avroSchemasDir) + outputs.dir(avroCodeGenerationDir) + // The Avro code generation logs to the standard streams. Redirect the standard streams to the Gradle log. + logging.captureStandardOutput(LogLevel.INFO); + logging.captureStandardError(LogLevel.ERROR) + doLast { + // Run the Avro code generation. + new SpecificCompilerTool().run(System.in, System.out, System.err, List.of( + "-encoding", "UTF-8", + "-string", + "-fieldVisibility", "private", + "-noSetters", + "schema", "$projectDir/$avroSchemasDir".toString(), "$projectDir/$avroCodeGenerationDir".toString() + )) + } +} + +tasks.withType(JavaCompile).configureEach { + // Make Java compilation tasks depend on the Avro code generation task. + dependsOn('customAvroCodeGeneration') +} + tasks.named('test') { // Use JUnit Platform for unit tests. useJUnitPlatform() diff --git a/gradle-modules/gradle-customization/gradle-avro/gradle/libs.versions.toml b/gradle-modules/gradle-customization/gradle-avro/gradle/libs.versions.toml index 6c2cee93b8..8a2b7df961 100644 --- a/gradle-modules/gradle-customization/gradle-avro/gradle/libs.versions.toml +++ b/gradle-modules/gradle-customization/gradle-avro/gradle/libs.versions.toml @@ -3,10 +3,12 @@ [versions] junit-jupiter = "5.10.0" +avro = "1.11.0" [libraries] junit-jupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit-jupiter" } -avro = {module = "org.apache.avro:avro", version = "1.11.0"} +avro = {module = "org.apache.avro:avro", version.ref = "avro"} +avro-tools = {module = "org.apache.avro:avro-tools", version.ref = "avro"} [plugins] avro = { id = "com.github.davidmc24.gradle.plugin.avro", version = "1.9.1" } diff --git a/gradle-modules/gradle-customization/gradle-avro/src/main/avro/user.avsc b/gradle-modules/gradle-customization/gradle-avro/src/main/avro/user.avsc index 0936672532..7f9cde4d9e 100644 --- a/gradle-modules/gradle-customization/gradle-avro/src/main/avro/user.avsc +++ b/gradle-modules/gradle-customization/gradle-avro/src/main/avro/user.avsc @@ -1,10 +1,19 @@ { - "type": "record", - "name": "User", - "namespace": "com.example", - "fields": [ - { "name": "firstName", "type": "string" }, - { "name": "lastName", "type": "string" }, - { "name": "phoneNumber", "type": "string" } - ] + "type": "record", + "name": "User", + "namespace": "avro", + "fields": [ + { + "name": "firstName", + "type": "string" + }, + { + "name": "lastName", + "type": "string" + }, + { + "name": "phoneNumber", + "type": "string" + } + ] } diff --git a/gradle-modules/gradle-customization/gradle-avro/src/main/custom/Pet.avsc b/gradle-modules/gradle-customization/gradle-avro/src/main/custom/Pet.avsc new file mode 100644 index 0000000000..e510de2189 --- /dev/null +++ b/gradle-modules/gradle-customization/gradle-avro/src/main/custom/Pet.avsc @@ -0,0 +1,11 @@ +{ + "type": "record", + "name": "Pet", + "namespace": "custom.avro", + "fields": [ + { "name": "petId", "type": "string" }, + { "name": "name", "type": "string" }, + { "name": "species", "type": "string" }, + { "name": "age", "type": "int" } + ] +} diff --git a/gradle-modules/gradle-customization/gradle-avro/src/test/java/com.baeldung.avro/AvroCodeGenerationUnitTest.java b/gradle-modules/gradle-customization/gradle-avro/src/test/java/com.baeldung.avro/AvroCodeGenerationUnitTest.java index 57b3b98bb8..4c63836c65 100644 --- a/gradle-modules/gradle-customization/gradle-avro/src/test/java/com.baeldung.avro/AvroCodeGenerationUnitTest.java +++ b/gradle-modules/gradle-customization/gradle-avro/src/test/java/com.baeldung.avro/AvroCodeGenerationUnitTest.java @@ -1,6 +1,7 @@ package com.baeldung.avro; -import com.example.User; +import avro.User; +import custom.avro.Pet; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -8,7 +9,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; public class AvroCodeGenerationUnitTest { @Test - void givenUserData_whenObjectCreated_thenDataShouldMatch() { + void givenUserData_whenJavaClassGeneratedWithPlugin_thenDataShouldMatch() { final String firstName = "John"; final String lastName = "Doe"; final String phoneNumber = "+380659443235"; @@ -23,4 +24,25 @@ public class AvroCodeGenerationUnitTest { assertEquals(lastName, user.getLastName()); assertEquals(phoneNumber, user.getPhoneNumber()); } + + @Test + void givenUserData_whenJavaClassGeneratedWithTask_thenDataShouldMatch() { + final String petId = "123"; + final String name = "Fluffy"; + final String species = "Cat"; + final int age = 3; + + Pet pet = Pet.newBuilder() + .setPetId(petId) + .setName(name) + .setSpecies(species) + .setAge(age) + .build(); + + // Assertions to verify the values + assertEquals(petId, pet.getPetId()); + assertEquals(name, pet.getName()); + assertEquals(species, pet.getSpecies()); + assertEquals(age, pet.getAge()); + } } From 2d762f3f83fae4bc30fe38a190251d864dd53844 Mon Sep 17 00:00:00 2001 From: "kateryna.hrytsaenko" Date: Sun, 24 Mar 2024 22:52:51 +0200 Subject: [PATCH 03/33] BAEL-7445, rename the schema --- .../gradle-avro/src/main/custom/{Pet.avsc => pet.avsc} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename gradle-modules/gradle-customization/gradle-avro/src/main/custom/{Pet.avsc => pet.avsc} (100%) diff --git a/gradle-modules/gradle-customization/gradle-avro/src/main/custom/Pet.avsc b/gradle-modules/gradle-customization/gradle-avro/src/main/custom/pet.avsc similarity index 100% rename from gradle-modules/gradle-customization/gradle-avro/src/main/custom/Pet.avsc rename to gradle-modules/gradle-customization/gradle-avro/src/main/custom/pet.avsc From 63df143479e4661cb46cae640964ae5a5dbae022 Mon Sep 17 00:00:00 2001 From: "kateryna.hrytsaenko" Date: Mon, 25 Mar 2024 12:56:43 +0200 Subject: [PATCH 04/33] BAEL-7445, fix the formatting for pet schema and remove redurant comment --- .../gradle-avro/src/main/custom/pet.avsc | 20 +++++++++++++++---- .../AvroCodeGenerationUnitTest.java | 1 - 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/gradle-modules/gradle-customization/gradle-avro/src/main/custom/pet.avsc b/gradle-modules/gradle-customization/gradle-avro/src/main/custom/pet.avsc index e510de2189..427093feb5 100644 --- a/gradle-modules/gradle-customization/gradle-avro/src/main/custom/pet.avsc +++ b/gradle-modules/gradle-customization/gradle-avro/src/main/custom/pet.avsc @@ -3,9 +3,21 @@ "name": "Pet", "namespace": "custom.avro", "fields": [ - { "name": "petId", "type": "string" }, - { "name": "name", "type": "string" }, - { "name": "species", "type": "string" }, - { "name": "age", "type": "int" } + { + "name": "petId", + "type": "string" + }, + { + "name": "name", + "type": "string" + }, + { + "name": "species", + "type": "string" + }, + { + "name": "age", + "type": "int" + } ] } diff --git a/gradle-modules/gradle-customization/gradle-avro/src/test/java/com.baeldung.avro/AvroCodeGenerationUnitTest.java b/gradle-modules/gradle-customization/gradle-avro/src/test/java/com.baeldung.avro/AvroCodeGenerationUnitTest.java index 4c63836c65..f3d40a9f66 100644 --- a/gradle-modules/gradle-customization/gradle-avro/src/test/java/com.baeldung.avro/AvroCodeGenerationUnitTest.java +++ b/gradle-modules/gradle-customization/gradle-avro/src/test/java/com.baeldung.avro/AvroCodeGenerationUnitTest.java @@ -39,7 +39,6 @@ public class AvroCodeGenerationUnitTest { .setAge(age) .build(); - // Assertions to verify the values assertEquals(petId, pet.getPetId()); assertEquals(name, pet.getName()); assertEquals(species, pet.getSpecies()); From a2a1068b139fda80fb9e5f1e809dfb383d935c44 Mon Sep 17 00:00:00 2001 From: Abhijeet Mohan Date: Tue, 16 Apr 2024 15:21:17 +0000 Subject: [PATCH 05/33] [BAEL-7441] Fixing EOFException in Java --- .../core-java-exceptions-4/README.md | 1 + .../exception/eof/EOFExceptionDemo.java | 16 +++++++++ .../exception/eof/EOFExceptionDemo2.java | 22 ++++++++++++ .../exception/eof/EOFExceptionDemo3.java | 19 ++++++++++ .../eof/EOFExceptionDemo2UnitTest.java | 35 ++++++++++++++++++ .../eof/EOFExceptionDemo3UnitTest.java | 35 ++++++++++++++++++ .../eof/EOFExceptionDemoUnitTest.java | 36 +++++++++++++++++++ 7 files changed, 164 insertions(+) create mode 100644 core-java-modules/core-java-exceptions-4/src/main/java/com/baeldung/exception/eof/EOFExceptionDemo.java create mode 100644 core-java-modules/core-java-exceptions-4/src/main/java/com/baeldung/exception/eof/EOFExceptionDemo2.java create mode 100644 core-java-modules/core-java-exceptions-4/src/main/java/com/baeldung/exception/eof/EOFExceptionDemo3.java create mode 100644 core-java-modules/core-java-exceptions-4/src/test/java/com/baeldung/exception/eof/EOFExceptionDemo2UnitTest.java create mode 100644 core-java-modules/core-java-exceptions-4/src/test/java/com/baeldung/exception/eof/EOFExceptionDemo3UnitTest.java create mode 100644 core-java-modules/core-java-exceptions-4/src/test/java/com/baeldung/exception/eof/EOFExceptionDemoUnitTest.java diff --git a/core-java-modules/core-java-exceptions-4/README.md b/core-java-modules/core-java-exceptions-4/README.md index dc76b90fc7..f95e6991f0 100644 --- a/core-java-modules/core-java-exceptions-4/README.md +++ b/core-java-modules/core-java-exceptions-4/README.md @@ -10,4 +10,5 @@ This module contains articles about core java exceptions - [Get the Current Stack Trace in Java](https://www.baeldung.com/java-get-current-stack-trace) - [Errors and Exceptions in Java](https://www.baeldung.com/java-errors-vs-exceptions) - [Fix the IllegalArgumentException: No enum const class](https://www.baeldung.com/java-fix-no-enum-const-class) +- [How to Fix EOFException in Java](https://www.baeldung.com/java-fix-eofexception) - [[<-- Prev]](../core-java-exceptions-3) diff --git a/core-java-modules/core-java-exceptions-4/src/main/java/com/baeldung/exception/eof/EOFExceptionDemo.java b/core-java-modules/core-java-exceptions-4/src/main/java/com/baeldung/exception/eof/EOFExceptionDemo.java new file mode 100644 index 0000000000..9e1d687022 --- /dev/null +++ b/core-java-modules/core-java-exceptions-4/src/main/java/com/baeldung/exception/eof/EOFExceptionDemo.java @@ -0,0 +1,16 @@ +package com.baeldung.exception.eof; + +import java.io.DataInputStream; +import java.io.InputStream; +import java.io.ByteArrayInputStream; + +public class EOFExceptionDemo { + public static void readInput() throws Exception { + InputStream is = new ByteArrayInputStream("123".getBytes()); + DataInputStream in = new DataInputStream(is); + while (true) { + char value = (char)in.readByte(); + System.out.println("Input value: " + value); + } + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-exceptions-4/src/main/java/com/baeldung/exception/eof/EOFExceptionDemo2.java b/core-java-modules/core-java-exceptions-4/src/main/java/com/baeldung/exception/eof/EOFExceptionDemo2.java new file mode 100644 index 0000000000..837bd4583f --- /dev/null +++ b/core-java-modules/core-java-exceptions-4/src/main/java/com/baeldung/exception/eof/EOFExceptionDemo2.java @@ -0,0 +1,22 @@ +package com.baeldung.exception.eof; + +import java.io.DataInputStream; +import java.io.InputStream; +import java.io.ByteArrayInputStream; +import java.io.EOFException; + +public class EOFExceptionDemo2 { + public static void readInput() throws Exception { + InputStream is = new ByteArrayInputStream("123".getBytes()); + DataInputStream in = new DataInputStream(is); + while (true) { + try { + char value = (char)in.readByte(); + System.out.println("Input value: " + value); + } catch (EOFException e) { + System.out.println("End of file"); + break; + } + } + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-exceptions-4/src/main/java/com/baeldung/exception/eof/EOFExceptionDemo3.java b/core-java-modules/core-java-exceptions-4/src/main/java/com/baeldung/exception/eof/EOFExceptionDemo3.java new file mode 100644 index 0000000000..ade729c096 --- /dev/null +++ b/core-java-modules/core-java-exceptions-4/src/main/java/com/baeldung/exception/eof/EOFExceptionDemo3.java @@ -0,0 +1,19 @@ +package com.baeldung.exception.eof; + +import java.io.DataInputStream; +import java.io.InputStream; +import java.util.Scanner; +import java.io.ByteArrayInputStream; + +public class EOFExceptionDemo3 { + public static void readInput() { + InputStream is = new ByteArrayInputStream("1 2 3".getBytes()); + Scanner sc = new Scanner(is); + while (sc.hasNextInt()) { + int value = sc.nextInt(); + System.out.println("Input value: " + value); + } + System.out.println("End of file"); + sc.close(); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-exceptions-4/src/test/java/com/baeldung/exception/eof/EOFExceptionDemo2UnitTest.java b/core-java-modules/core-java-exceptions-4/src/test/java/com/baeldung/exception/eof/EOFExceptionDemo2UnitTest.java new file mode 100644 index 0000000000..b3969c01cb --- /dev/null +++ b/core-java-modules/core-java-exceptions-4/src/test/java/com/baeldung/exception/eof/EOFExceptionDemo2UnitTest.java @@ -0,0 +1,35 @@ +package com.baeldung.exception.eof; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.AfterEach; +import java.io.PrintStream; +import java.io.ByteArrayOutputStream; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class EOFExceptionDemo2UnitTest { + + private final PrintStream standardOut = System.out; + private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream(); + + @BeforeEach + public void setUp() { + System.setOut(new PrintStream(outputStreamCaptor)); + } + + @AfterEach + public void tearDown() { + System.setOut(standardOut); + } + + @Test + void readInput()throws Exception { + EOFExceptionDemo2.readInput(); + String expectedOuput = "Input value: 1"; + expectedOuput += "\n" + "Input value: 2"; + expectedOuput += "\n" + "Input value: 3"; + expectedOuput += "\n" + "End of file"; + assertEquals(expectedOuput, outputStreamCaptor.toString() + .trim()); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-exceptions-4/src/test/java/com/baeldung/exception/eof/EOFExceptionDemo3UnitTest.java b/core-java-modules/core-java-exceptions-4/src/test/java/com/baeldung/exception/eof/EOFExceptionDemo3UnitTest.java new file mode 100644 index 0000000000..313bd3159d --- /dev/null +++ b/core-java-modules/core-java-exceptions-4/src/test/java/com/baeldung/exception/eof/EOFExceptionDemo3UnitTest.java @@ -0,0 +1,35 @@ +package com.baeldung.exception.eof; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.AfterEach; +import java.io.PrintStream; +import java.io.ByteArrayOutputStream; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class EOFExceptionDemo3UnitTest { + + private final PrintStream standardOut = System.out; + private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream(); + + @BeforeEach + public void setUp() { + System.setOut(new PrintStream(outputStreamCaptor)); + } + + @AfterEach + public void tearDown() { + System.setOut(standardOut); + } + + @Test + void readInput() { + EOFExceptionDemo3.readInput(); + String expectedOuput = "Input value: 1"; + expectedOuput += "\n" + "Input value: 2"; + expectedOuput += "\n" + "Input value: 3"; + expectedOuput += "\n" + "End of file"; + assertEquals(expectedOuput, outputStreamCaptor.toString() + .trim()); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-exceptions-4/src/test/java/com/baeldung/exception/eof/EOFExceptionDemoUnitTest.java b/core-java-modules/core-java-exceptions-4/src/test/java/com/baeldung/exception/eof/EOFExceptionDemoUnitTest.java new file mode 100644 index 0000000000..41275523e1 --- /dev/null +++ b/core-java-modules/core-java-exceptions-4/src/test/java/com/baeldung/exception/eof/EOFExceptionDemoUnitTest.java @@ -0,0 +1,36 @@ +package com.baeldung.exception.eof; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.AfterEach; +import java.io.EOFException; +import java.io.PrintStream; +import java.io.ByteArrayOutputStream; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class EOFExceptionDemoUnitTest { + + private final PrintStream standardOut = System.out; + private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream(); + + @BeforeEach + public void setUp() { + System.setOut(new PrintStream(outputStreamCaptor)); + } + + @AfterEach + public void tearDown() { + System.setOut(standardOut); + } + + @Test + void readInput_throwsEOFException() { + assertThrows(EOFException.class, () -> EOFExceptionDemo.readInput()); + String expectedOuput = "Input value: 1"; + expectedOuput += "\n" + "Input value: 2"; + expectedOuput += "\n" + "Input value: 3"; + assertEquals(expectedOuput, outputStreamCaptor.toString() + .trim()); + } +} \ No newline at end of file From bae34509b4efadc69953411447bc234912cff2ff Mon Sep 17 00:00:00 2001 From: michaelin007 Date: Sat, 20 Apr 2024 08:48:53 +0000 Subject: [PATCH 06/33] Generate QR Code in Java using QR-Code-Generator --- .../spring-boot-libraries/pom.xml | 6 ++++ .../baeldung/barcodes/BarcodesController.java | 12 ++++--- .../generators/QRCodegenGenerator.java | 36 +++++++++++++++++++ 3 files changed, 49 insertions(+), 5 deletions(-) create mode 100644 spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/barcodes/generators/QRCodegenGenerator.java diff --git a/spring-boot-modules/spring-boot-libraries/pom.xml b/spring-boot-modules/spring-boot-libraries/pom.xml index 021c74ddc0..ba5c87c782 100644 --- a/spring-boot-modules/spring-boot-libraries/pom.xml +++ b/spring-boot-modules/spring-boot-libraries/pom.xml @@ -131,6 +131,11 @@ jcache ${caffeine.version} + + io.nayuki + qrcodegen + ${qrcodegen.version} + @@ -239,6 +244,7 @@ 8.9.0 0.10.3 3.1.8 + 1.8.0 \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/barcodes/BarcodesController.java b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/barcodes/BarcodesController.java index a1318c0519..6ecdf6a63a 100644 --- a/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/barcodes/BarcodesController.java +++ b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/barcodes/BarcodesController.java @@ -1,10 +1,6 @@ package com.baeldung.barcodes; -import com.baeldung.barcodes.generators.BarbecueBarcodeGenerator; -import com.baeldung.barcodes.generators.Barcode4jBarcodeGenerator; -import com.baeldung.barcodes.generators.QRGenBarcodeGenerator; -import com.baeldung.barcodes.generators.ZxingBarcodeGenerator; -import com.baeldung.barcodes.generators.ZxingBarcodeGeneratorWithText; +import com.baeldung.barcodes.generators.*; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; @@ -108,4 +104,10 @@ public class BarcodesController { private ResponseEntity okResponse(BufferedImage image) { return new ResponseEntity<>(image, HttpStatus.OK); } + + //QRCodegen + @PostMapping(value = "/qrcodegen/qrcode", produces = MediaType.IMAGE_PNG_VALUE) + public ResponseEntity qrcodegenQRCode(@RequestBody String barcode) throws Exception { + return okResponse(QRCodegenGenerator.generateQrcode(barcode)); + } } diff --git a/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/barcodes/generators/QRCodegenGenerator.java b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/barcodes/generators/QRCodegenGenerator.java new file mode 100644 index 0000000000..55f7d0bc77 --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/barcodes/generators/QRCodegenGenerator.java @@ -0,0 +1,36 @@ +package com.baeldung.barcodes.generators; + +import io.nayuki.qrcodegen.QrCode; + +import java.awt.image.BufferedImage; +import java.util.Objects; + +public class QRCodegenGenerator { + + public static BufferedImage generateQrcode(String barcodeText) throws Exception { + QrCode qrCode = QrCode.encodeText(barcodeText, QrCode.Ecc.MEDIUM); + BufferedImage img = toImage(qrCode, 4, 10); + return img; + } + + public static BufferedImage toImage(QrCode qr, int scale, int border) { + return toImage(qr, scale, border, 0xFFFFFF, 0x000000); + } + + private static BufferedImage toImage(QrCode qr, int scale, int border, int lightColor, int darkColor) { + Objects.requireNonNull(qr); + if (scale <= 0 || border < 0) + throw new IllegalArgumentException("Value out of range"); + if (border > Integer.MAX_VALUE / 2 || qr.size + border * 2L > Integer.MAX_VALUE / scale) + throw new IllegalArgumentException("Scale or border too large"); + + BufferedImage result = new BufferedImage((qr.size + border * 2) * scale, (qr.size + border * 2) * scale, BufferedImage.TYPE_INT_RGB); + for (int y = 0; y < result.getHeight(); y++) { + for (int x = 0; x < result.getWidth(); x++) { + boolean color = qr.getModule(x / scale - border, y / scale - border); + result.setRGB(x, y, color ? darkColor : lightColor); + } + } + return result; + } +} From 4e3259175a9e1dfad0484458cdb068f25736631c Mon Sep 17 00:00:00 2001 From: michaelin007 Date: Sat, 20 Apr 2024 08:55:42 +0000 Subject: [PATCH 07/33] Generate QR Code in Java using QR-Code-Generator --- .../java/com/baeldung/barcodes/BarcodesController.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/barcodes/BarcodesController.java b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/barcodes/BarcodesController.java index 6ecdf6a63a..8942e93d8b 100644 --- a/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/barcodes/BarcodesController.java +++ b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/barcodes/BarcodesController.java @@ -1,6 +1,11 @@ package com.baeldung.barcodes; -import com.baeldung.barcodes.generators.*; +import com.baeldung.barcodes.generators.BarbecueBarcodeGenerator; +import com.baeldung.barcodes.generators.Barcode4jBarcodeGenerator; +import com.baeldung.barcodes.generators.QRGenBarcodeGenerator; +import com.baeldung.barcodes.generators.ZxingBarcodeGenerator; +import com.baeldung.barcodes.generators.ZxingBarcodeGeneratorWithText; +import com.baeldung.barcodes.generators.QRCodegenGenerator; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; From eb4996272bbc2cac7f502cf550815cd36b8ef569 Mon Sep 17 00:00:00 2001 From: ch4mpy Date: Fri, 19 Apr 2024 23:09:30 -1000 Subject: [PATCH 08/33] BAEL-7704 : (CONFIGURATION) BAEL-7704 : Update to latest spring-addons. Fix conf: authentication converter was no used by the security filter-chain. Add docker compose file for a Keycloak instance with an imported realm. --- .../spring-security-oauth2-testing/.env | 1 + .../compose.yml | 23 + .../keycloak/import/baeldung-realm.json | 1827 +++++++++++++++++ .../keycloak/import/baeldung-users-0.json | 50 + .../spring-security-oauth2-testing/pom.xml | 60 +- .../reactive-resource-server/pom.xml | 1 + .../ReactiveResourceServerApplication.java | 61 +- .../src/main/resources/application.yaml | 6 - .../src/main/resources/application.yml | 11 + .../src/main/resources/banner.txt | 16 + ...ecurityTestGreetingControllerUnitTest.java | 24 +- .../servlet-resource-server/pom.xml | 1 + .../ServletResourceServerApplication.java | 28 +- .../src/main/resources/application.properties | 1 - .../src/main/resources/application.yml | 11 + .../src/main/resources/banner.txt | 16 + ...pringAddonsGreetingControllerUnitTest.java | 4 +- ...ecurityTestGreetingControllerUnitTest.java | 24 +- 18 files changed, 2065 insertions(+), 100 deletions(-) create mode 100644 spring-security-modules/spring-security-oauth2-testing/.env create mode 100644 spring-security-modules/spring-security-oauth2-testing/compose.yml create mode 100644 spring-security-modules/spring-security-oauth2-testing/keycloak/import/baeldung-realm.json create mode 100644 spring-security-modules/spring-security-oauth2-testing/keycloak/import/baeldung-users-0.json delete mode 100644 spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/main/resources/application.yaml create mode 100644 spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/main/resources/application.yml create mode 100644 spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/main/resources/banner.txt delete mode 100644 spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/main/resources/application.properties create mode 100644 spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/main/resources/application.yml create mode 100644 spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/main/resources/banner.txt diff --git a/spring-security-modules/spring-security-oauth2-testing/.env b/spring-security-modules/spring-security-oauth2-testing/.env new file mode 100644 index 0000000000..c4c692acb6 --- /dev/null +++ b/spring-security-modules/spring-security-oauth2-testing/.env @@ -0,0 +1 @@ +KEYCLOAK_ADMIN_PASSWORD=admin \ No newline at end of file diff --git a/spring-security-modules/spring-security-oauth2-testing/compose.yml b/spring-security-modules/spring-security-oauth2-testing/compose.yml new file mode 100644 index 0000000000..aa6b019360 --- /dev/null +++ b/spring-security-modules/spring-security-oauth2-testing/compose.yml @@ -0,0 +1,23 @@ +name: baeldung-testing-oauth2 +services: + + keycloak: + image: quay.io/keycloak/keycloak:24.0.0 + volumes: + - ./keycloak/import/:/opt/keycloak/data/import/ + command: + - start-dev + - --import-realm + ports: + - 8080:8080 + environment: + KEYCLOAK_ADMIN: admin + KEYCLOAK_ADMIN_PASSWORD: ${KEYCLOAK_ADMIN_PASSWORD} + KC_HTTP_PORT: 8080 + KC_HOSTNAME_URL: http://localhost:8080 + KC_HOSTNAME_ADMIN_URL: http://localhost:8080 + KC_HTTP_RELATIVE_PATH: / + #KC_LOG_LEVEL: DEBUG + container_name: baeldung-testing-oauth2 + extra_hosts: + - "host.docker.internal:host-gateway" \ No newline at end of file diff --git a/spring-security-modules/spring-security-oauth2-testing/keycloak/import/baeldung-realm.json b/spring-security-modules/spring-security-oauth2-testing/keycloak/import/baeldung-realm.json new file mode 100644 index 0000000000..616f0c1f74 --- /dev/null +++ b/spring-security-modules/spring-security-oauth2-testing/keycloak/import/baeldung-realm.json @@ -0,0 +1,1827 @@ +{ + "id" : "7a046c8d-77b1-4851-b4a9-e3a25a17e431", + "realm" : "baeldung", + "notBefore" : 0, + "defaultSignatureAlgorithm" : "RS256", + "revokeRefreshToken" : false, + "refreshTokenMaxReuse" : 0, + "accessTokenLifespan" : 300, + "accessTokenLifespanForImplicitFlow" : 900, + "ssoSessionIdleTimeout" : 1800, + "ssoSessionMaxLifespan" : 36000, + "ssoSessionIdleTimeoutRememberMe" : 0, + "ssoSessionMaxLifespanRememberMe" : 0, + "offlineSessionIdleTimeout" : 2592000, + "offlineSessionMaxLifespanEnabled" : false, + "offlineSessionMaxLifespan" : 5184000, + "clientSessionIdleTimeout" : 0, + "clientSessionMaxLifespan" : 0, + "clientOfflineSessionIdleTimeout" : 0, + "clientOfflineSessionMaxLifespan" : 0, + "accessCodeLifespan" : 60, + "accessCodeLifespanUserAction" : 300, + "accessCodeLifespanLogin" : 1800, + "actionTokenGeneratedByAdminLifespan" : 43200, + "actionTokenGeneratedByUserLifespan" : 300, + "oauth2DeviceCodeLifespan" : 600, + "oauth2DevicePollingInterval" : 5, + "enabled" : true, + "sslRequired" : "external", + "registrationAllowed" : false, + "registrationEmailAsUsername" : false, + "rememberMe" : false, + "verifyEmail" : false, + "loginWithEmailAllowed" : true, + "duplicateEmailsAllowed" : false, + "resetPasswordAllowed" : false, + "editUsernameAllowed" : false, + "bruteForceProtected" : false, + "permanentLockout" : false, + "maxTemporaryLockouts" : 0, + "maxFailureWaitSeconds" : 900, + "minimumQuickLoginWaitSeconds" : 60, + "waitIncrementSeconds" : 60, + "quickLoginCheckMilliSeconds" : 1000, + "maxDeltaTimeSeconds" : 43200, + "failureFactor" : 30, + "roles" : { + "realm" : [ { + "id" : "4ad869c1-56f3-45fd-b345-f107f2834de1", + "name" : "AUTHORIZED_PERSONNEL", + "description" : "", + "composite" : false, + "clientRole" : false, + "containerId" : "7a046c8d-77b1-4851-b4a9-e3a25a17e431", + "attributes" : { } + }, { + "id" : "bfdf00fe-5111-404b-858c-50dcb8a63e61", + "name" : "default-roles-baeldung", + "description" : "${role_default-roles}", + "composite" : true, + "composites" : { + "realm" : [ "offline_access", "uma_authorization" ], + "client" : { + "account" : [ "view-profile", "manage-account" ] + } + }, + "clientRole" : false, + "containerId" : "7a046c8d-77b1-4851-b4a9-e3a25a17e431", + "attributes" : { } + }, { + "id" : "96fbbf77-c81e-472b-bb2e-184713dfffde", + "name" : "uma_authorization", + "description" : "${role_uma_authorization}", + "composite" : false, + "clientRole" : false, + "containerId" : "7a046c8d-77b1-4851-b4a9-e3a25a17e431", + "attributes" : { } + }, { + "id" : "cec72467-237c-4ae9-ae1d-ca84ff51b404", + "name" : "offline_access", + "description" : "${role_offline-access}", + "composite" : false, + "clientRole" : false, + "containerId" : "7a046c8d-77b1-4851-b4a9-e3a25a17e431", + "attributes" : { } + } ], + "client" : { + "realm-management" : [ { + "id" : "955d707a-3baa-4462-a53c-83ff73b30a12", + "name" : "view-realm", + "description" : "${role_view-realm}", + "composite" : false, + "clientRole" : true, + "containerId" : "4720b673-8d8b-4709-b695-88d6c17e8edf", + "attributes" : { } + }, { + "id" : "81cbcb10-8e84-431e-8da8-07219be8d93d", + "name" : "view-clients", + "description" : "${role_view-clients}", + "composite" : true, + "composites" : { + "client" : { + "realm-management" : [ "query-clients" ] + } + }, + "clientRole" : true, + "containerId" : "4720b673-8d8b-4709-b695-88d6c17e8edf", + "attributes" : { } + }, { + "id" : "fa1adc6d-7b86-4dc6-a120-57eee9a4fe93", + "name" : "create-client", + "description" : "${role_create-client}", + "composite" : false, + "clientRole" : true, + "containerId" : "4720b673-8d8b-4709-b695-88d6c17e8edf", + "attributes" : { } + }, { + "id" : "be5a19cb-fa00-486a-abfa-eb0dc86680fb", + "name" : "view-users", + "description" : "${role_view-users}", + "composite" : true, + "composites" : { + "client" : { + "realm-management" : [ "query-users", "query-groups" ] + } + }, + "clientRole" : true, + "containerId" : "4720b673-8d8b-4709-b695-88d6c17e8edf", + "attributes" : { } + }, { + "id" : "d76de5c9-10f2-4b68-9850-a16d9b2dd35a", + "name" : "manage-identity-providers", + "description" : "${role_manage-identity-providers}", + "composite" : false, + "clientRole" : true, + "containerId" : "4720b673-8d8b-4709-b695-88d6c17e8edf", + "attributes" : { } + }, { + "id" : "6339f747-4f89-4e67-9c77-420524135d96", + "name" : "manage-authorization", + "description" : "${role_manage-authorization}", + "composite" : false, + "clientRole" : true, + "containerId" : "4720b673-8d8b-4709-b695-88d6c17e8edf", + "attributes" : { } + }, { + "id" : "c9d5af42-6742-49cf-bd01-a730f4c3cc2e", + "name" : "impersonation", + "description" : "${role_impersonation}", + "composite" : false, + "clientRole" : true, + "containerId" : "4720b673-8d8b-4709-b695-88d6c17e8edf", + "attributes" : { } + }, { + "id" : "56dccfed-9379-4cfb-a720-b9b9e1745048", + "name" : "view-identity-providers", + "description" : "${role_view-identity-providers}", + "composite" : false, + "clientRole" : true, + "containerId" : "4720b673-8d8b-4709-b695-88d6c17e8edf", + "attributes" : { } + }, { + "id" : "e10c568f-c50f-4ee4-88cf-43f0c4a1dc2c", + "name" : "manage-realm", + "description" : "${role_manage-realm}", + "composite" : false, + "clientRole" : true, + "containerId" : "4720b673-8d8b-4709-b695-88d6c17e8edf", + "attributes" : { } + }, { + "id" : "d12dcfc2-b649-4c11-ac55-41d6ab10f5c6", + "name" : "query-users", + "description" : "${role_query-users}", + "composite" : false, + "clientRole" : true, + "containerId" : "4720b673-8d8b-4709-b695-88d6c17e8edf", + "attributes" : { } + }, { + "id" : "57977d45-f810-400a-81ca-63a9bdddd3b9", + "name" : "query-realms", + "description" : "${role_query-realms}", + "composite" : false, + "clientRole" : true, + "containerId" : "4720b673-8d8b-4709-b695-88d6c17e8edf", + "attributes" : { } + }, { + "id" : "e14dfabc-3f03-42cf-a716-5261b7002914", + "name" : "query-groups", + "description" : "${role_query-groups}", + "composite" : false, + "clientRole" : true, + "containerId" : "4720b673-8d8b-4709-b695-88d6c17e8edf", + "attributes" : { } + }, { + "id" : "800d272c-1327-485c-9d2f-576f3d9a0178", + "name" : "view-authorization", + "description" : "${role_view-authorization}", + "composite" : false, + "clientRole" : true, + "containerId" : "4720b673-8d8b-4709-b695-88d6c17e8edf", + "attributes" : { } + }, { + "id" : "fdc10176-42c0-4b58-968a-35bfd5dbce20", + "name" : "view-events", + "description" : "${role_view-events}", + "composite" : false, + "clientRole" : true, + "containerId" : "4720b673-8d8b-4709-b695-88d6c17e8edf", + "attributes" : { } + }, { + "id" : "23393ccd-3b70-4de8-9e00-0adbb11851ce", + "name" : "manage-users", + "description" : "${role_manage-users}", + "composite" : false, + "clientRole" : true, + "containerId" : "4720b673-8d8b-4709-b695-88d6c17e8edf", + "attributes" : { } + }, { + "id" : "01a3847f-7602-400d-bedd-7545618559f3", + "name" : "manage-clients", + "description" : "${role_manage-clients}", + "composite" : false, + "clientRole" : true, + "containerId" : "4720b673-8d8b-4709-b695-88d6c17e8edf", + "attributes" : { } + }, { + "id" : "7d8ac9c4-6d1b-4861-a0b9-0479cbd55b14", + "name" : "query-clients", + "description" : "${role_query-clients}", + "composite" : false, + "clientRole" : true, + "containerId" : "4720b673-8d8b-4709-b695-88d6c17e8edf", + "attributes" : { } + }, { + "id" : "788677b0-3fbf-457d-8b62-25f305b86bcf", + "name" : "manage-events", + "description" : "${role_manage-events}", + "composite" : false, + "clientRole" : true, + "containerId" : "4720b673-8d8b-4709-b695-88d6c17e8edf", + "attributes" : { } + }, { + "id" : "642d82d5-1071-47a9-aca9-d0fbd28d0328", + "name" : "realm-admin", + "description" : "${role_realm-admin}", + "composite" : true, + "composites" : { + "client" : { + "realm-management" : [ "view-realm", "view-clients", "create-client", "view-users", "manage-identity-providers", "manage-authorization", "impersonation", "view-identity-providers", "manage-realm", "query-users", "query-realms", "view-authorization", "query-groups", "view-events", "manage-users", "manage-clients", "query-clients", "manage-events" ] + } + }, + "clientRole" : true, + "containerId" : "4720b673-8d8b-4709-b695-88d6c17e8edf", + "attributes" : { } + } ], + "security-admin-console" : [ ], + "admin-cli" : [ ], + "baeldung-confidential" : [ ], + "account-console" : [ ], + "broker" : [ { + "id" : "9043c535-f6d3-44dc-8c48-d3983e04a93b", + "name" : "read-token", + "description" : "${role_read-token}", + "composite" : false, + "clientRole" : true, + "containerId" : "cb2ee74f-fb36-4f21-82bb-4928966ea449", + "attributes" : { } + } ], + "account" : [ { + "id" : "4a188a41-39d9-47e6-b8de-6d9b42c7a414", + "name" : "view-profile", + "description" : "${role_view-profile}", + "composite" : false, + "clientRole" : true, + "containerId" : "1b64b350-3ef8-4be6-b9ab-c53463b2fd1b", + "attributes" : { } + }, { + "id" : "da24f251-0c13-4035-84f1-16c5a3301ea6", + "name" : "view-consent", + "description" : "${role_view-consent}", + "composite" : false, + "clientRole" : true, + "containerId" : "1b64b350-3ef8-4be6-b9ab-c53463b2fd1b", + "attributes" : { } + }, { + "id" : "26edbb7d-dd9f-4dd4-a282-a6e886e38302", + "name" : "manage-account-links", + "description" : "${role_manage-account-links}", + "composite" : false, + "clientRole" : true, + "containerId" : "1b64b350-3ef8-4be6-b9ab-c53463b2fd1b", + "attributes" : { } + }, { + "id" : "b2c98d1e-4a85-4e11-901d-0207e9793acf", + "name" : "manage-consent", + "description" : "${role_manage-consent}", + "composite" : true, + "composites" : { + "client" : { + "account" : [ "view-consent" ] + } + }, + "clientRole" : true, + "containerId" : "1b64b350-3ef8-4be6-b9ab-c53463b2fd1b", + "attributes" : { } + }, { + "id" : "f244eb36-cf20-4e96-8233-fee1ee8da72e", + "name" : "manage-account", + "description" : "${role_manage-account}", + "composite" : true, + "composites" : { + "client" : { + "account" : [ "manage-account-links" ] + } + }, + "clientRole" : true, + "containerId" : "1b64b350-3ef8-4be6-b9ab-c53463b2fd1b", + "attributes" : { } + }, { + "id" : "a5ca4c2f-d8ad-4c8c-bfd4-1173dd7c1338", + "name" : "view-groups", + "description" : "${role_view-groups}", + "composite" : false, + "clientRole" : true, + "containerId" : "1b64b350-3ef8-4be6-b9ab-c53463b2fd1b", + "attributes" : { } + }, { + "id" : "83f4a43c-07cd-43d5-af99-7825ea603ca9", + "name" : "view-applications", + "description" : "${role_view-applications}", + "composite" : false, + "clientRole" : true, + "containerId" : "1b64b350-3ef8-4be6-b9ab-c53463b2fd1b", + "attributes" : { } + }, { + "id" : "18642f4e-1e2a-4023-9947-7a425d8ed76e", + "name" : "delete-account", + "description" : "${role_delete-account}", + "composite" : false, + "clientRole" : true, + "containerId" : "1b64b350-3ef8-4be6-b9ab-c53463b2fd1b", + "attributes" : { } + } ] + } + }, + "groups" : [ ], + "defaultRole" : { + "id" : "bfdf00fe-5111-404b-858c-50dcb8a63e61", + "name" : "default-roles-baeldung", + "description" : "${role_default-roles}", + "composite" : true, + "clientRole" : false, + "containerId" : "7a046c8d-77b1-4851-b4a9-e3a25a17e431" + }, + "requiredCredentials" : [ "password" ], + "otpPolicyType" : "totp", + "otpPolicyAlgorithm" : "HmacSHA1", + "otpPolicyInitialCounter" : 0, + "otpPolicyDigits" : 6, + "otpPolicyLookAheadWindow" : 1, + "otpPolicyPeriod" : 30, + "otpPolicyCodeReusable" : false, + "otpSupportedApplications" : [ "totpAppFreeOTPName", "totpAppGoogleName", "totpAppMicrosoftAuthenticatorName" ], + "localizationTexts" : { }, + "webAuthnPolicyRpEntityName" : "keycloak", + "webAuthnPolicySignatureAlgorithms" : [ "ES256" ], + "webAuthnPolicyRpId" : "", + "webAuthnPolicyAttestationConveyancePreference" : "not specified", + "webAuthnPolicyAuthenticatorAttachment" : "not specified", + "webAuthnPolicyRequireResidentKey" : "not specified", + "webAuthnPolicyUserVerificationRequirement" : "not specified", + "webAuthnPolicyCreateTimeout" : 0, + "webAuthnPolicyAvoidSameAuthenticatorRegister" : false, + "webAuthnPolicyAcceptableAaguids" : [ ], + "webAuthnPolicyExtraOrigins" : [ ], + "webAuthnPolicyPasswordlessRpEntityName" : "keycloak", + "webAuthnPolicyPasswordlessSignatureAlgorithms" : [ "ES256" ], + "webAuthnPolicyPasswordlessRpId" : "", + "webAuthnPolicyPasswordlessAttestationConveyancePreference" : "not specified", + "webAuthnPolicyPasswordlessAuthenticatorAttachment" : "not specified", + "webAuthnPolicyPasswordlessRequireResidentKey" : "not specified", + "webAuthnPolicyPasswordlessUserVerificationRequirement" : "not specified", + "webAuthnPolicyPasswordlessCreateTimeout" : 0, + "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister" : false, + "webAuthnPolicyPasswordlessAcceptableAaguids" : [ ], + "webAuthnPolicyPasswordlessExtraOrigins" : [ ], + "scopeMappings" : [ { + "clientScope" : "offline_access", + "roles" : [ "offline_access" ] + } ], + "clientScopeMappings" : { + "account" : [ { + "client" : "account-console", + "roles" : [ "manage-account", "view-groups" ] + } ] + }, + "clients" : [ { + "id" : "1b64b350-3ef8-4be6-b9ab-c53463b2fd1b", + "clientId" : "account", + "name" : "${client_account}", + "rootUrl" : "${authBaseUrl}", + "baseUrl" : "/realms/baeldung/account/", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ "/realms/baeldung/account/*" ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "post.logout.redirect.uris" : "+" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "4beaa749-404c-4a6a-9b04-72df4f9066a4", + "clientId" : "account-console", + "name" : "${client_account-console}", + "rootUrl" : "${authBaseUrl}", + "baseUrl" : "/realms/baeldung/account/", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ "/realms/baeldung/account/*" ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "post.logout.redirect.uris" : "+", + "pkce.code.challenge.method" : "S256" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "protocolMappers" : [ { + "id" : "84f0fe2c-8381-4cd1-afa7-508c5cd6c83c", + "name" : "audience resolve", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-audience-resolve-mapper", + "consentRequired" : false, + "config" : { } + } ], + "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "d2a180a9-6ed6-42fd-a476-2ba0948cae8f", + "clientId" : "admin-cli", + "name" : "${client_admin-cli}", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : false, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : true, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "3172d7e0-ac9f-4728-ba8c-e1d35c6e14a4", + "clientId" : "baeldung-confidential", + "name" : "", + "description" : "", + "rootUrl" : "", + "adminUrl" : "", + "baseUrl" : "", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "secret" : "secret", + "redirectUris" : ["https://oauth.pstmn.io/v1/callback", "http://localhost:8080/*", "https://localhost:8080/*", "http://localhost:8081/*", "https://localhost:8081/*", "http://localhost:8082/*", "https://localhost:8082/*" ], + "webOrigins" : [ "+" ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : false, + "frontchannelLogout" : true, + "protocol" : "openid-connect", + "attributes" : { + "oidc.ciba.grant.enabled" : "false", + "client.secret.creation.time" : "1713615347", + "backchannel.logout.session.required" : "true", + "post.logout.redirect.uris" : "+", + "oauth2.device.authorization.grant.enabled" : "false", + "backchannel.logout.revoke.offline.tokens" : "false" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : true, + "nodeReRegistrationTimeout" : -1, + "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "cb2ee74f-fb36-4f21-82bb-4928966ea449", + "clientId" : "broker", + "name" : "${client_broker}", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : true, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : false, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "4720b673-8d8b-4709-b695-88d6c17e8edf", + "clientId" : "realm-management", + "name" : "${client_realm-management}", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : true, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : false, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "8c99b1f8-439f-4c01-ac62-bf4b852a3585", + "clientId" : "security-admin-console", + "name" : "${client_security-admin-console}", + "rootUrl" : "${authAdminUrl}", + "baseUrl" : "/admin/baeldung/console/", + "surrogateAuthRequired" : false, + "enabled" : true, + "alwaysDisplayInConsole" : false, + "clientAuthenticatorType" : "client-secret", + "redirectUris" : [ "/admin/baeldung/console/*" ], + "webOrigins" : [ "+" ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { + "post.logout.redirect.uris" : "+", + "pkce.code.challenge.method" : "S256" + }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "protocolMappers" : [ { + "id" : "4a39a186-0bc6-46c8-9605-940ab6af0ec4", + "name" : "locale", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "locale", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "locale", + "jsonType.label" : "String" + } + } ], + "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + } ], + "clientScopes" : [ { + "id" : "98fd7e67-c4fc-4e6a-bb9c-6e27d99bbbb2", + "name" : "phone", + "description" : "OpenID Connect built-in scope: phone", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${phoneScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "1cdb5d11-fcc5-48ee-9acc-b8d980b607a5", + "name" : "phone number", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "phoneNumber", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "phone_number", + "jsonType.label" : "String" + } + }, { + "id" : "f3258684-171e-47f9-a9d0-96434e91ee6a", + "name" : "phone number verified", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "phoneNumberVerified", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "phone_number_verified", + "jsonType.label" : "boolean" + } + } ] + }, { + "id" : "20843100-3f9b-4c50-8dc6-86e6d64fbc3d", + "name" : "role_list", + "description" : "SAML role list", + "protocol" : "saml", + "attributes" : { + "consent.screen.text" : "${samlRoleListScopeConsentText}", + "display.on.consent.screen" : "true" + }, + "protocolMappers" : [ { + "id" : "fabf3bec-72b8-4035-84a7-f368417446ef", + "name" : "role list", + "protocol" : "saml", + "protocolMapper" : "saml-role-list-mapper", + "consentRequired" : false, + "config" : { + "single" : "false", + "attribute.nameformat" : "Basic", + "attribute.name" : "Role" + } + } ] + }, { + "id" : "3a0949bd-8a64-44b3-8f21-0b8c41cf44d8", + "name" : "address", + "description" : "OpenID Connect built-in scope: address", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${addressScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "38838b81-804d-47d1-9aad-92d5107b1653", + "name" : "address", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-address-mapper", + "consentRequired" : false, + "config" : { + "user.attribute.formatted" : "formatted", + "user.attribute.country" : "country", + "introspection.token.claim" : "true", + "user.attribute.postal_code" : "postal_code", + "userinfo.token.claim" : "true", + "user.attribute.street" : "street", + "id.token.claim" : "true", + "user.attribute.region" : "region", + "access.token.claim" : "true", + "user.attribute.locality" : "locality" + } + } ] + }, { + "id" : "4bc0f7a9-7009-48f4-aeee-198c705d4e90", + "name" : "profile", + "description" : "OpenID Connect built-in scope: profile", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${profileScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "ed2fc2c9-d27e-4d2c-b877-4bc817fd54bf", + "name" : "family name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "lastName", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "family_name", + "jsonType.label" : "String" + } + }, { + "id" : "c1278964-7ee9-4619-a8a4-461ef8fce69b", + "name" : "nickname", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "nickname", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "nickname", + "jsonType.label" : "String" + } + }, { + "id" : "bf7b6bfb-0c2a-4826-8ee2-52cc409534f2", + "name" : "picture", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "picture", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "picture", + "jsonType.label" : "String" + } + }, { + "id" : "85bdea58-50c5-4d63-952d-ab0e1e861244", + "name" : "username", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "username", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "preferred_username", + "jsonType.label" : "String" + } + }, { + "id" : "c945557c-e480-4f09-b9fa-62c05a26cb05", + "name" : "updated at", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "updatedAt", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "updated_at", + "jsonType.label" : "long" + } + }, { + "id" : "184fc94a-c750-4bc0-be3f-0501365bc1fd", + "name" : "full name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-full-name-mapper", + "consentRequired" : false, + "config" : { + "id.token.claim" : "true", + "introspection.token.claim" : "true", + "access.token.claim" : "true", + "userinfo.token.claim" : "true" + } + }, { + "id" : "40162254-ac26-4b36-a5d5-538d33612c80", + "name" : "zoneinfo", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "zoneinfo", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "zoneinfo", + "jsonType.label" : "String" + } + }, { + "id" : "a85df9ca-5a7f-4035-96a1-bd55dcdbe5be", + "name" : "gender", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "gender", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "gender", + "jsonType.label" : "String" + } + }, { + "id" : "8d02d6e1-89b1-4777-8ce6-5bc6a1fb9f30", + "name" : "middle name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "middleName", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "middle_name", + "jsonType.label" : "String" + } + }, { + "id" : "bf65a00b-5112-4bd4-b540-de0fa4912c65", + "name" : "website", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "website", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "website", + "jsonType.label" : "String" + } + }, { + "id" : "5eddbe1e-e274-4543-8606-a8fd3d5f793b", + "name" : "locale", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "locale", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "locale", + "jsonType.label" : "String" + } + }, { + "id" : "54300fc6-0c26-42e0-89bb-844955488008", + "name" : "given name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "firstName", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "given_name", + "jsonType.label" : "String" + } + }, { + "id" : "89ccaf97-a0a8-4221-9174-17a7e475ebc7", + "name" : "birthdate", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "birthdate", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "birthdate", + "jsonType.label" : "String" + } + }, { + "id" : "58e90cb8-25c5-4e81-a5ed-a9de481fab17", + "name" : "profile", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "profile", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "profile", + "jsonType.label" : "String" + } + } ] + }, { + "id" : "2d434173-8b6e-4959-ad8f-c7185bc9b433", + "name" : "email", + "description" : "OpenID Connect built-in scope: email", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${emailScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "84dad65d-8413-44c0-95f4-f3d64035e7b6", + "name" : "email verified", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-property-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "emailVerified", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "email_verified", + "jsonType.label" : "boolean" + } + }, { + "id" : "89ac6a7f-9435-41ed-83eb-34a366429a6f", + "name" : "email", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "email", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "email", + "jsonType.label" : "String" + } + } ] + }, { + "id" : "51307312-9b48-4ae9-ad92-7cbc0ff4c6c3", + "name" : "web-origins", + "description" : "OpenID Connect scope for add allowed web origins to the access token", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "false", + "display.on.consent.screen" : "false", + "consent.screen.text" : "" + }, + "protocolMappers" : [ { + "id" : "6f6d1690-df96-4774-ae4a-2d349461f02a", + "name" : "allowed web origins", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-allowed-origins-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "access.token.claim" : "true" + } + } ] + }, { + "id" : "3bec9041-170c-4c6d-a35e-be7a51442aef", + "name" : "microprofile-jwt", + "description" : "Microprofile - JWT built-in scope", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "false" + }, + "protocolMappers" : [ { + "id" : "52e647ff-3bb4-47ee-b67d-0cd24bb66c5b", + "name" : "groups", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-realm-role-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "multivalued" : "true", + "user.attribute" : "foo", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "groups", + "jsonType.label" : "String" + } + }, { + "id" : "027afd1d-3d34-49df-bf43-00adddfec15a", + "name" : "upn", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "userinfo.token.claim" : "true", + "user.attribute" : "username", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "upn", + "jsonType.label" : "String" + } + } ] + }, { + "id" : "159dc3dc-a659-4cb8-9271-809834a42d8e", + "name" : "acr", + "description" : "OpenID Connect scope for add acr (authentication context class reference) to the token", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "false", + "display.on.consent.screen" : "false" + }, + "protocolMappers" : [ { + "id" : "5dbfb5d7-c181-4e47-85e8-13ad0610c43b", + "name" : "acr loa level", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-acr-mapper", + "consentRequired" : false, + "config" : { + "id.token.claim" : "true", + "introspection.token.claim" : "true", + "access.token.claim" : "true" + } + } ] + }, { + "id" : "46c52714-3bb6-4db9-a360-0839703c1f8e", + "name" : "roles", + "description" : "OpenID Connect scope for add user roles to the access token", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "false", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${rolesScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "0b274bf6-89f0-4d3c-a635-eb3943d062ee", + "name" : "realm roles", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-realm-role-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "multivalued" : "true", + "user.attribute" : "foo", + "access.token.claim" : "true", + "claim.name" : "realm_access.roles", + "jsonType.label" : "String" + } + }, { + "id" : "e70cd96f-6d15-4c46-978a-359f1832b7c2", + "name" : "audience resolve", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-audience-resolve-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "access.token.claim" : "true" + } + }, { + "id" : "6a19a6ab-4035-4c43-b9e5-253339bb491b", + "name" : "client roles", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-client-role-mapper", + "consentRequired" : false, + "config" : { + "introspection.token.claim" : "true", + "multivalued" : "true", + "user.attribute" : "foo", + "access.token.claim" : "true", + "claim.name" : "resource_access.${client_id}.roles", + "jsonType.label" : "String" + } + } ] + }, { + "id" : "4d1dfa4a-c1cc-45ad-ade5-7ac2fabfc5d3", + "name" : "offline_access", + "description" : "OpenID Connect built-in scope: offline_access", + "protocol" : "openid-connect", + "attributes" : { + "consent.screen.text" : "${offlineAccessScopeConsentText}", + "display.on.consent.screen" : "true" + } + } ], + "defaultDefaultClientScopes" : [ "role_list", "profile", "email", "roles", "web-origins", "acr" ], + "defaultOptionalClientScopes" : [ "offline_access", "address", "phone", "microprofile-jwt" ], + "browserSecurityHeaders" : { + "contentSecurityPolicyReportOnly" : "", + "xContentTypeOptions" : "nosniff", + "referrerPolicy" : "no-referrer", + "xRobotsTag" : "none", + "xFrameOptions" : "SAMEORIGIN", + "contentSecurityPolicy" : "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "xXSSProtection" : "1; mode=block", + "strictTransportSecurity" : "max-age=31536000; includeSubDomains" + }, + "smtpServer" : { }, + "eventsEnabled" : true, + "eventsExpiration" : 900, + "eventsListeners" : [ "jboss-logging" ], + "enabledEventTypes" : [ "SEND_RESET_PASSWORD", "UPDATE_CONSENT_ERROR", "GRANT_CONSENT", "VERIFY_PROFILE_ERROR", "REMOVE_TOTP", "REVOKE_GRANT", "UPDATE_TOTP", "LOGIN_ERROR", "CLIENT_LOGIN", "RESET_PASSWORD_ERROR", "IMPERSONATE_ERROR", "CODE_TO_TOKEN_ERROR", "CUSTOM_REQUIRED_ACTION", "OAUTH2_DEVICE_CODE_TO_TOKEN_ERROR", "RESTART_AUTHENTICATION", "IMPERSONATE", "UPDATE_PROFILE_ERROR", "LOGIN", "OAUTH2_DEVICE_VERIFY_USER_CODE", "UPDATE_PASSWORD_ERROR", "CLIENT_INITIATED_ACCOUNT_LINKING", "OAUTH2_EXTENSION_GRANT", "USER_DISABLED_BY_PERMANENT_LOCKOUT", "TOKEN_EXCHANGE", "AUTHREQID_TO_TOKEN", "LOGOUT", "REGISTER", "DELETE_ACCOUNT_ERROR", "CLIENT_REGISTER", "IDENTITY_PROVIDER_LINK_ACCOUNT", "USER_DISABLED_BY_TEMPORARY_LOCKOUT", "DELETE_ACCOUNT", "UPDATE_PASSWORD", "CLIENT_DELETE", "FEDERATED_IDENTITY_LINK_ERROR", "IDENTITY_PROVIDER_FIRST_LOGIN", "CLIENT_DELETE_ERROR", "VERIFY_EMAIL", "CLIENT_LOGIN_ERROR", "RESTART_AUTHENTICATION_ERROR", "EXECUTE_ACTIONS", "REMOVE_FEDERATED_IDENTITY_ERROR", "TOKEN_EXCHANGE_ERROR", "PERMISSION_TOKEN", "SEND_IDENTITY_PROVIDER_LINK_ERROR", "EXECUTE_ACTION_TOKEN_ERROR", "OAUTH2_EXTENSION_GRANT_ERROR", "SEND_VERIFY_EMAIL", "OAUTH2_DEVICE_AUTH", "EXECUTE_ACTIONS_ERROR", "REMOVE_FEDERATED_IDENTITY", "OAUTH2_DEVICE_CODE_TO_TOKEN", "IDENTITY_PROVIDER_POST_LOGIN", "IDENTITY_PROVIDER_LINK_ACCOUNT_ERROR", "OAUTH2_DEVICE_VERIFY_USER_CODE_ERROR", "UPDATE_EMAIL", "REGISTER_ERROR", "REVOKE_GRANT_ERROR", "EXECUTE_ACTION_TOKEN", "LOGOUT_ERROR", "UPDATE_EMAIL_ERROR", "CLIENT_UPDATE_ERROR", "AUTHREQID_TO_TOKEN_ERROR", "UPDATE_PROFILE", "CLIENT_REGISTER_ERROR", "FEDERATED_IDENTITY_LINK", "SEND_IDENTITY_PROVIDER_LINK", "SEND_VERIFY_EMAIL_ERROR", "RESET_PASSWORD", "CLIENT_INITIATED_ACCOUNT_LINKING_ERROR", "OAUTH2_DEVICE_AUTH_ERROR", "UPDATE_CONSENT", "REMOVE_TOTP_ERROR", "VERIFY_EMAIL_ERROR", "SEND_RESET_PASSWORD_ERROR", "CLIENT_UPDATE", "CUSTOM_REQUIRED_ACTION_ERROR", "IDENTITY_PROVIDER_POST_LOGIN_ERROR", "UPDATE_TOTP_ERROR", "CODE_TO_TOKEN", "VERIFY_PROFILE", "GRANT_CONSENT_ERROR", "IDENTITY_PROVIDER_FIRST_LOGIN_ERROR" ], + "adminEventsEnabled" : true, + "adminEventsDetailsEnabled" : true, + "identityProviders" : [ ], + "identityProviderMappers" : [ ], + "components" : { + "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy" : [ { + "id" : "c07dff7f-77fc-4381-a458-9c56515c5c98", + "name" : "Allowed Client Scopes", + "providerId" : "allowed-client-templates", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "allow-default-scopes" : [ "true" ] + } + }, { + "id" : "d9662eb8-e8bb-4ae5-a625-c8c616d8967a", + "name" : "Consent Required", + "providerId" : "consent-required", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { } + }, { + "id" : "03f2b651-fdea-4a7a-88e8-f169f5a7f892", + "name" : "Allowed Protocol Mapper Types", + "providerId" : "allowed-protocol-mappers", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "allowed-protocol-mapper-types" : [ "oidc-usermodel-attribute-mapper", "oidc-usermodel-property-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-full-name-mapper", "oidc-address-mapper", "saml-user-attribute-mapper", "saml-user-property-mapper", "saml-role-list-mapper" ] + } + }, { + "id" : "0c7278cb-1e59-407e-9187-fa147ce96f82", + "name" : "Full Scope Disabled", + "providerId" : "scope", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { } + }, { + "id" : "a3c48cf1-67be-41fb-a852-6efe25560fcf", + "name" : "Max Clients Limit", + "providerId" : "max-clients", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "max-clients" : [ "200" ] + } + }, { + "id" : "b0f72ad6-c65d-4132-912f-6e5ba9c48466", + "name" : "Trusted Hosts", + "providerId" : "trusted-hosts", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "host-sending-registration-request-must-match" : [ "true" ], + "client-uris-must-match" : [ "true" ] + } + }, { + "id" : "717bea7a-bc0a-4d2a-9ea2-cbe670f1833e", + "name" : "Allowed Protocol Mapper Types", + "providerId" : "allowed-protocol-mappers", + "subType" : "authenticated", + "subComponents" : { }, + "config" : { + "allowed-protocol-mapper-types" : [ "oidc-full-name-mapper", "oidc-usermodel-attribute-mapper", "oidc-usermodel-property-mapper", "saml-role-list-mapper", "saml-user-attribute-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-address-mapper", "saml-user-property-mapper" ] + } + }, { + "id" : "b1fa36d7-8ef0-4501-a495-215b90bd0699", + "name" : "Allowed Client Scopes", + "providerId" : "allowed-client-templates", + "subType" : "authenticated", + "subComponents" : { }, + "config" : { + "allow-default-scopes" : [ "true" ] + } + } ], + "org.keycloak.keys.KeyProvider" : [ { + "id" : "04a18d35-45bd-458d-9bc8-939db56e337d", + "name" : "aes-generated", + "providerId" : "aes-generated", + "subComponents" : { }, + "config" : { + "kid" : [ "3eaa2cde-31c2-409e-9e0e-b8f9ecf76704" ], + "secret" : [ "7BdqNadvG1OQs7Z4qJfvaQ" ], + "priority" : [ "100" ] + } + }, { + "id" : "ce00dbf1-1d6d-44da-84c0-1ed88d712801", + "name" : "rsa-generated", + "providerId" : "rsa-generated", + "subComponents" : { }, + "config" : { + "privateKey" : [ "MIIEogIBAAKCAQEAp0WHWge6QpqVZfKr2kg1esRlHsSZfcGX8uu2pyB2NsXPjuaE0HqEN+OMsQsRR/rjbQkpPYG9sGur0nqNXhV/ErHIlMCmV2Hx8RoLWkVvpqrhnKH+0cBwm8dS83ZN0u5Q4xF1i6a/6FdZx0W45UrE/MZzlqB58I/EyaqZ4H6Id8MXp7W2Fuzw+Q2cKc1MxKx6MzhLJZShIXt8PTjueX5rRfYerdPbixq0E1vWA9Xcatt2mn/xIMo8illBk7fSPvzYv7YKsLtg1Cn43fU/mi63oBckb55D1uYzs2SgnzvRUX8eR6ndq/7CvZaGO3e3WN6FbowpE+wAbMZoXjlKRiHtPwIDAQABAoIBAAxcY/swNQB1AfNNsotn6KPQ3ZQffSRA6SSnbJD/Ih08EvGBcXEijKDArQXsRnOmQ6YsFiMYclcWLdVY/xdjyUctYiAz+Fbeww1JGmuqU+ziFdgIVJdVfDzWxvd815VtzQZqpOAUC3x08Ap8yYQQOWxgkewgocI4LZelhseDMjx/TIScOmuUWmFRwQ7HUP93OKV1oWC4lMAC4LTnqCqlnsk2L563+Q7T2jXUpznlJ6UoTSpu1Msllh+AxqkvZXvAwbFeYoDksWVUaY+gHAQkihgWMGIEmiBun9TsP4NUkpQuWXq1OHE6KBldaJPP3OProN2Z/gDgXDmKVVEf718m+YkCgYEA5KoroazEAIAjZ1L+t39DYNhv87eDnz/y2lRboD3InMFtE36rBPBIOTGiK3GKaIXh6b8VPOXXA5By2SnERIMfzdusmdknTREbC9Ca/ix5RyE/MqflGjqhcsEu1vWe/L7LYNrmTeOryR8E3rLSsrfmIFRKC+9ufsWlahttzW3D5ksCgYEAu0SLIqTmLfcwmIEngU044o5OZw7QtHaDJmNEv5n4cKXJHmCa3mK+IIIb7f3YIw4nyRQVKjbppAM1bLKT5RpqvHCxVIwjGbvhJ7l7QlBXmcx6x9n18ZPFdA8exUwm56sgixlrfUIHUMH1TFbGSFqIm5bAJwjFwqz3gXzSVU0rTF0CgYAjrCiCYGFzcooTZG84UTJBuYI9kzOFdIR+awqgRQM28TYDBI/JhXK++W9DN8NP6xMDVDwL9A9HDxHbrxhfV9VuWAblOWtYKoL9pN2JKYcCAb3KOUcUgHEPZfPYtRjIdTtlMMEdBZeXGK+5zkvwdaABCyVCF2g1fr//fafzlFwrYQKBgHtJcvhJ66hTVtDwJpv/xPWSjpdWr5w/cbRyIi6qJV+0JaY0H4FNLLKmNdEHD6Z0iUjeSdjS8hqiaie3oZpxO9f3sSdiYzFr+Z13hWhxEFsWvbaZDkwO5y2zTqTBr9NRXEl3YMbEE6DdMKsjbcLwp4MXSkXohpnV2dSL4sV52omZAoGAFY1w9JGkTwJ0rG/R+Yx3qcRhoHY7YA2PMSYIyB9E5d923L6bi1GRSwhNLO+lW0eWA8ekHiQLnqDmNJl708oJBGUwo/Zr7U9jowsqQIaSE8VgU6dfdhbScMI5vpmSrlQRyV0UveLvCsEAx/Rvl4y+dQneaEoNqEKSd7Hml2tjx7g=" ], + "keyUse" : [ "SIG" ], + "certificate" : [ "MIICnzCCAYcCBgGO+25VozANBgkqhkiG9w0BAQsFADATMREwDwYDVQQDDAhiYWVsZHVuZzAeFw0yNDA0MjAxMjEzMTVaFw0zNDA0MjAxMjE0NTVaMBMxETAPBgNVBAMMCGJhZWxkdW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp0WHWge6QpqVZfKr2kg1esRlHsSZfcGX8uu2pyB2NsXPjuaE0HqEN+OMsQsRR/rjbQkpPYG9sGur0nqNXhV/ErHIlMCmV2Hx8RoLWkVvpqrhnKH+0cBwm8dS83ZN0u5Q4xF1i6a/6FdZx0W45UrE/MZzlqB58I/EyaqZ4H6Id8MXp7W2Fuzw+Q2cKc1MxKx6MzhLJZShIXt8PTjueX5rRfYerdPbixq0E1vWA9Xcatt2mn/xIMo8illBk7fSPvzYv7YKsLtg1Cn43fU/mi63oBckb55D1uYzs2SgnzvRUX8eR6ndq/7CvZaGO3e3WN6FbowpE+wAbMZoXjlKRiHtPwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQB091NLrtrT+JSmLfyv+LvFIPIaOu07kWHbueqjKbOinQ2ouBfMnOA9Ojm/17w8CIt/h6VIBzoi3H9Huq15dnGoiIcQIzvAiq8XSewnVfnyvFeq830LVAiTEEDRQLqKVT1PiRZEj64XGyRM3lX0Xp+CXG8z3Qc4OVFrHdb/nUIbfDAmxsWRymTm5p2E5GTJPlr/gON/AHPAHIzmgk5HD9PqBPpMQRHN9/y8vkeIPh9gEj8oUYsM6MPEKrbQIDBqnr8UaxPaMtJF+cjg36VB0SJ9c1w0DBWeND/UNFq47aNWMSND5O9qX0eJxVTqxFAFia0V2WUZk17Pd6pzLKkZQb94" ], + "priority" : [ "100" ] + } + }, { + "id" : "fa8ee6a3-d95e-4ec9-856a-0962208b6bcc", + "name" : "rsa-enc-generated", + "providerId" : "rsa-enc-generated", + "subComponents" : { }, + "config" : { + "privateKey" : [ "MIIEowIBAAKCAQEAsZNPlXoVvt4RsbkFu3giJB3W3qDxEGsAIvOQqLFKP4o1oFJY4L4K5ljUbGABMiq0fQEVTj1mAZAwqJ/J+mnv5OhkUfTDpAt0LactZRPqz7RyfRwmSTL3r/kCtFZn5WQZA//Z6q3zdm7ARxH3Dq9+cMARIe1k7dblWlX+8A5Qk8Ka9Ie6SfwqlTsv4EMTmIhUjj/UyEAWLhSLrk/gA3PQyw/OUEWJTM946AWmPcMtWJRFDbMsj00G1sgrmRuIa0zmXpLj+Zr1Kby9GBU/x60EKtONtXiX8IvIKFm8mKI40q8va6jI71wqUB7OtDZ1a+iF1h8TJ+X5Q2ARPo0li3iEUQIDAQABAoIBADhe57ovZdzP+TT+Y9P12Hy3nkDRPYV1OjdeM5NhqIzQLqLk0UMTATnLhC+dMHQA+4fdQqqyMgIYCGJXS1J7s8Rqg4JC3aJjYm+lrPLz5iwmf9u4hmzhSaCqv1GJRnUbGBfdbguiSfHUSaSmDtQyIMThK+8lwc8A05EgUIxbNvgYnEOEdavlyCq4HdMiDPSjpdHSdC8NpaQkAVULB3QXofm5SQm4ioED/trVjHyjl80i9ysDKSPPzqpye4lFCqmclni1U78V2w4E/uVOG8+MczZkS4otPG99QoELGuqLaVmq9rAx624owUAY3r7ecCL2lSHyjzJwBkrBFLenlSI4A6sCgYEA7tPcbOYPt2a7ih1nase6aC5rwTk62lpe9cuNpVCRmKKlX9glLLcFjNz+75LSyj4TXvg52vcZv3JmsULUeE30rPVr9hgIeuEnsPCc4HLJ40aVaEyhVVwg5ofy3++/8Ys0PR2blZ674/jFgxbB537t81QxQd5WtD9Zh+w7Tiiw40sCgYEAvlf4qvjKW6kaOpmIe4S7wWY9/FhbgHq3sKLltfzOGY0GTWGFZtJ7uzgDvOkEVAIyopEDKfkBL3Sok5ic8MpQOARCa1HXjm8+dtQ1SkNxDsGC//DpouHefkvwUNeKYPV2n4CckirUMmvSqWz4oWAA5u0C2eg0pwvlavMpRKN1mVMCgYB7Klt09biJNrvk4IEi+lnRvI7pmSAW16A9Vnp4FPLhKo/qu8eAJesA2D/JQYjfr9/BjHYZzHFE4DTBmduFJ37Va8P/qClHZbJYd94PimM/iHkozsws/1QgT2AbyMLOSKHqGsjQAoqXaQZDMotRXY5NfM/iTk2cq0b66AM1rZp7vQKBgQCpBc1XZV2sT1lvN+8uYAuqDXR1pLB8QnzjaYO6Oyd5IPW7uSGQ0M/2zCLlmbWyM9Fq8oJwvyECVwFrL1YNrFnXpFCmpCJZ5Qb+1ioMLB81DzmYtQGDFjdQx3Y7E2tZ9h7EPJzMXyPXMk/7Cz0tb+bdKRIjFkPLIpEyi4LV5KEE6QKBgF7Hs1jnR+/3wVK2NG+Ek5bOwOn7wNtwpfhHpj+Auwk7B9mzoor01L6UTw+LDMtQoohfqOJhM1xZcn2MJdhZhkWvSpavEyuY886A8RVtL44rh/kCHy/M4d9AQoiSz5mIYOdiiskbepG+jaIoweUvWxLmcWLWgV3H8syyqJR/vf30" ], + "keyUse" : [ "ENC" ], + "certificate" : [ "MIICnzCCAYcCBgGO+25WEDANBgkqhkiG9w0BAQsFADATMREwDwYDVQQDDAhiYWVsZHVuZzAeFw0yNDA0MjAxMjEzMTZaFw0zNDA0MjAxMjE0NTZaMBMxETAPBgNVBAMMCGJhZWxkdW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsZNPlXoVvt4RsbkFu3giJB3W3qDxEGsAIvOQqLFKP4o1oFJY4L4K5ljUbGABMiq0fQEVTj1mAZAwqJ/J+mnv5OhkUfTDpAt0LactZRPqz7RyfRwmSTL3r/kCtFZn5WQZA//Z6q3zdm7ARxH3Dq9+cMARIe1k7dblWlX+8A5Qk8Ka9Ie6SfwqlTsv4EMTmIhUjj/UyEAWLhSLrk/gA3PQyw/OUEWJTM946AWmPcMtWJRFDbMsj00G1sgrmRuIa0zmXpLj+Zr1Kby9GBU/x60EKtONtXiX8IvIKFm8mKI40q8va6jI71wqUB7OtDZ1a+iF1h8TJ+X5Q2ARPo0li3iEUQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQCT9Jua67qgsClibdgvEfX3BKLl+JXVbFjyYKfBhP85DIk/tzfeYi1UZilWGPWlnprhp5GnwZXPeqVsLCNM+ypdYN8RGBs6K48wVQoetf92GPh9eCQMq2FSAVKShsgkolKifyuZo8oQu6Na92V5EsjUV7hEB4G3jXOisrO/MjN+Ja9eRXru1L2n7bOrKtYRlYeNI8CZvc63jRPkq1fRutcmpqMRPDjMYuM9wUvkZwewqo8WSf51DDKBah5W83XLbTp5jX0bH1NZc3BNHnNerR3iMGPSa6rcKPsC3lL1mZluNVhQExyli1S1f7QmUc1BYxr3zi2uVCKkci5gRenDywws" ], + "priority" : [ "100" ], + "algorithm" : [ "RSA-OAEP" ] + } + }, { + "id" : "0866f9d1-3c22-432c-95d4-65378e739b89", + "name" : "hmac-generated-hs512", + "providerId" : "hmac-generated", + "subComponents" : { }, + "config" : { + "kid" : [ "749eb77a-a3d7-45b2-bc40-3bf80faf2fc7" ], + "secret" : [ "YmaVXh3blZqVaqpgeLyGI5JUzV8Vc41XFb7RcUaChNmAN-f61pqz7nE6edgQj_NS-TVVsvlq9qouKcd-5_oGugmvCXZ-Dp5gzcKe4EA-voOEV4pvJ7VXRWuH6QBDCaXyDiknEVtIx20ycjC4F8Ch10_n8so87mwMuVA6zD8Y-oM" ], + "priority" : [ "100" ], + "algorithm" : [ "HS512" ] + } + } ] + }, + "internationalizationEnabled" : false, + "supportedLocales" : [ ], + "authenticationFlows" : [ { + "id" : "92fc572a-6443-4d62-989d-dc6147aed6a6", + "alias" : "Account verification options", + "description" : "Method with which to verity the existing account", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "idp-email-verification", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "ALTERNATIVE", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "Verify Existing Account by Re-authentication", + "userSetupAllowed" : false + } ] + }, { + "id" : "17dce980-92a5-4dab-84b6-29f0ffe91e2f", + "alias" : "Browser - Conditional OTP", + "description" : "Flow to determine if the OTP is required for the authentication", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "auth-otp-form", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "9fdb023c-7959-4e7c-b745-d0bcfc6e1f87", + "alias" : "Direct Grant - Conditional OTP", + "description" : "Flow to determine if the OTP is required for the authentication", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "direct-grant-validate-otp", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "336dbe24-c5ec-44c0-bf56-1b811b451fdf", + "alias" : "First broker login - Conditional OTP", + "description" : "Flow to determine if the OTP is required for the authentication", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "auth-otp-form", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "3a87da1e-2fdf-4d15-8c93-8e8d69fc2774", + "alias" : "Handle Existing Account", + "description" : "Handle what to do if there is existing account with same email/username like authenticated identity provider", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "idp-confirm-link", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "Account verification options", + "userSetupAllowed" : false + } ] + }, { + "id" : "77bd3109-c34e-4165-b9f7-cb6d19aa7fe3", + "alias" : "Reset - Conditional OTP", + "description" : "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "conditional-user-configured", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "reset-otp", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "ee4b2165-c1be-43ca-96c8-b2302d78b38a", + "alias" : "User creation or linking", + "description" : "Flow for the existing/non-existing user alternatives", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticatorConfig" : "create unique user config", + "authenticator" : "idp-create-user-if-unique", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "ALTERNATIVE", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "Handle Existing Account", + "userSetupAllowed" : false + } ] + }, { + "id" : "0116eec2-8a17-4de9-b75f-caa26e52bdf0", + "alias" : "Verify Existing Account by Re-authentication", + "description" : "Reauthentication of existing account", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "idp-username-password-form", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "CONDITIONAL", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "First broker login - Conditional OTP", + "userSetupAllowed" : false + } ] + }, { + "id" : "de8794bd-3ad0-42e9-861f-85fcb6cb1db6", + "alias" : "browser", + "description" : "browser based authentication", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "auth-cookie", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "auth-spnego", + "authenticatorFlow" : false, + "requirement" : "DISABLED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "identity-provider-redirector", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 25, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "ALTERNATIVE", + "priority" : 30, + "autheticatorFlow" : true, + "flowAlias" : "forms", + "userSetupAllowed" : false + } ] + }, { + "id" : "9f6aa9f1-134b-4efe-84c4-ba9b7f4e8368", + "alias" : "clients", + "description" : "Base authentication for clients", + "providerId" : "client-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "client-secret", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "client-jwt", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "client-secret-jwt", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 30, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "client-x509", + "authenticatorFlow" : false, + "requirement" : "ALTERNATIVE", + "priority" : 40, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "692ddf3c-2813-46ef-b364-fcba9d70f5a4", + "alias" : "direct grant", + "description" : "OpenID Connect Resource Owner Grant", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "direct-grant-validate-username", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "direct-grant-validate-password", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "CONDITIONAL", + "priority" : 30, + "autheticatorFlow" : true, + "flowAlias" : "Direct Grant - Conditional OTP", + "userSetupAllowed" : false + } ] + }, { + "id" : "257e18b2-be1c-4ab2-8dd7-68a83817ca8a", + "alias" : "docker auth", + "description" : "Used by Docker clients to authenticate against the IDP", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "docker-http-basic-authenticator", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "fe879ee4-eec5-4034-9b78-82636f614123", + "alias" : "first broker login", + "description" : "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticatorConfig" : "review profile config", + "authenticator" : "idp-review-profile", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "User creation or linking", + "userSetupAllowed" : false + } ] + }, { + "id" : "2e6f09af-a3f6-415a-8d38-dfc1708e82ff", + "alias" : "forms", + "description" : "Username, password, otp and other auth forms.", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "auth-username-password-form", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "CONDITIONAL", + "priority" : 20, + "autheticatorFlow" : true, + "flowAlias" : "Browser - Conditional OTP", + "userSetupAllowed" : false + } ] + }, { + "id" : "cac2a81c-7933-4e1c-a91b-1a5e4d8ba873", + "alias" : "registration", + "description" : "registration flow", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "registration-page-form", + "authenticatorFlow" : true, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : true, + "flowAlias" : "registration form", + "userSetupAllowed" : false + } ] + }, { + "id" : "76b893b1-6b16-4e7c-a945-b86b63c983fb", + "alias" : "registration form", + "description" : "registration form", + "providerId" : "form-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "registration-user-creation", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "registration-password-action", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 50, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "registration-recaptcha-action", + "authenticatorFlow" : false, + "requirement" : "DISABLED", + "priority" : 60, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "registration-terms-and-conditions", + "authenticatorFlow" : false, + "requirement" : "DISABLED", + "priority" : 70, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + }, { + "id" : "8c1ba21b-218d-406d-a936-c935f41e7bef", + "alias" : "reset credentials", + "description" : "Reset credentials for a user if they forgot their password or something", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "reset-credentials-choose-user", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "reset-credential-email", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 20, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticator" : "reset-password", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 30, + "autheticatorFlow" : false, + "userSetupAllowed" : false + }, { + "authenticatorFlow" : true, + "requirement" : "CONDITIONAL", + "priority" : 40, + "autheticatorFlow" : true, + "flowAlias" : "Reset - Conditional OTP", + "userSetupAllowed" : false + } ] + }, { + "id" : "6df47204-9532-4b3e-821f-9a5255b9c305", + "alias" : "saml ecp", + "description" : "SAML ECP Profile Authentication Flow", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "http-basic-authenticator", + "authenticatorFlow" : false, + "requirement" : "REQUIRED", + "priority" : 10, + "autheticatorFlow" : false, + "userSetupAllowed" : false + } ] + } ], + "authenticatorConfig" : [ { + "id" : "793b40f2-0912-40f4-b570-a75015fb9eb0", + "alias" : "create unique user config", + "config" : { + "require.password.update.after.registration" : "false" + } + }, { + "id" : "3ff115f7-7108-4b17-8868-1d390ec3a480", + "alias" : "review profile config", + "config" : { + "update.profile.on.first.login" : "missing" + } + } ], + "requiredActions" : [ { + "alias" : "CONFIGURE_TOTP", + "name" : "Configure OTP", + "providerId" : "CONFIGURE_TOTP", + "enabled" : true, + "defaultAction" : false, + "priority" : 10, + "config" : { } + }, { + "alias" : "TERMS_AND_CONDITIONS", + "name" : "Terms and Conditions", + "providerId" : "TERMS_AND_CONDITIONS", + "enabled" : false, + "defaultAction" : false, + "priority" : 20, + "config" : { } + }, { + "alias" : "UPDATE_PASSWORD", + "name" : "Update Password", + "providerId" : "UPDATE_PASSWORD", + "enabled" : true, + "defaultAction" : false, + "priority" : 30, + "config" : { } + }, { + "alias" : "UPDATE_PROFILE", + "name" : "Update Profile", + "providerId" : "UPDATE_PROFILE", + "enabled" : true, + "defaultAction" : false, + "priority" : 40, + "config" : { } + }, { + "alias" : "VERIFY_EMAIL", + "name" : "Verify Email", + "providerId" : "VERIFY_EMAIL", + "enabled" : true, + "defaultAction" : false, + "priority" : 50, + "config" : { } + }, { + "alias" : "delete_account", + "name" : "Delete Account", + "providerId" : "delete_account", + "enabled" : false, + "defaultAction" : false, + "priority" : 60, + "config" : { } + }, { + "alias" : "webauthn-register", + "name" : "Webauthn Register", + "providerId" : "webauthn-register", + "enabled" : true, + "defaultAction" : false, + "priority" : 70, + "config" : { } + }, { + "alias" : "webauthn-register-passwordless", + "name" : "Webauthn Register Passwordless", + "providerId" : "webauthn-register-passwordless", + "enabled" : true, + "defaultAction" : false, + "priority" : 80, + "config" : { } + }, { + "alias" : "VERIFY_PROFILE", + "name" : "Verify Profile", + "providerId" : "VERIFY_PROFILE", + "enabled" : true, + "defaultAction" : false, + "priority" : 90, + "config" : { } + }, { + "alias" : "update_user_locale", + "name" : "Update User Locale", + "providerId" : "update_user_locale", + "enabled" : true, + "defaultAction" : false, + "priority" : 1000, + "config" : { } + } ], + "browserFlow" : "browser", + "registrationFlow" : "registration", + "directGrantFlow" : "direct grant", + "resetCredentialsFlow" : "reset credentials", + "clientAuthenticationFlow" : "clients", + "dockerAuthenticationFlow" : "docker auth", + "firstBrokerLoginFlow" : "first broker login", + "attributes" : { + "cibaBackchannelTokenDeliveryMode" : "poll", + "cibaAuthRequestedUserHint" : "login_hint", + "oauth2DevicePollingInterval" : "5", + "clientOfflineSessionMaxLifespan" : "0", + "clientSessionIdleTimeout" : "0", + "clientOfflineSessionIdleTimeout" : "0", + "cibaInterval" : "5", + "realmReusableOtpCode" : "false", + "cibaExpiresIn" : "120", + "oauth2DeviceCodeLifespan" : "600", + "parRequestUriLifespan" : "60", + "clientSessionMaxLifespan" : "0", + "adminEventsExpiration" : "900" + }, + "keycloakVersion" : "24.0.0", + "userManagedAccessAllowed" : false, + "clientProfiles" : { + "profiles" : [ ] + }, + "clientPolicies" : { + "policies" : [ ] + } +} \ No newline at end of file diff --git a/spring-security-modules/spring-security-oauth2-testing/keycloak/import/baeldung-users-0.json b/spring-security-modules/spring-security-oauth2-testing/keycloak/import/baeldung-users-0.json new file mode 100644 index 0000000000..20a78548df --- /dev/null +++ b/spring-security-modules/spring-security-oauth2-testing/keycloak/import/baeldung-users-0.json @@ -0,0 +1,50 @@ +{ + "realm" : "baeldung", + "users" : [ { + "id" : "bb83bd5b-b895-49aa-b62e-fde8ff8d5e64", + "username" : "authorized", + "firstName" : "authorized", + "lastName" : "user", + "email" : "authorized@baeldung.gg", + "emailVerified" : true, + "createdTimestamp" : 1713615702990, + "enabled" : true, + "totp" : false, + "credentials" : [ { + "id" : "23d3b6ce-fa3c-4f6e-9b09-e7b3cefa00f6", + "type" : "password", + "userLabel" : "My password", + "createdDate" : 1713615715678, + "secretData" : "{\"value\":\"lCZEOiVbCynSkCWiWe67/5/PybB+Om5mhi6SynpGFPB+r2b+QEKNYsB7ibO2f1ur9UB2aMO7jfoBYQdTJMcHbQ==\",\"salt\":\"hrIbqMOt0L7PPEYh/PsLNQ==\",\"additionalParameters\":{}}", + "credentialData" : "{\"hashIterations\":210000,\"algorithm\":\"pbkdf2-sha512\",\"additionalParameters\":{}}" + } ], + "disableableCredentialTypes" : [ ], + "requiredActions" : [ ], + "realmRoles" : [ "AUTHORIZED_PERSONNEL", "default-roles-baeldung" ], + "notBefore" : 0, + "groups" : [ ] + }, { + "id" : "d205d854-547c-43cf-a02d-fd6c385b128b", + "username" : "forbidden", + "firstName" : "forbidden", + "lastName" : "user", + "email" : "forbidden@baeldung.gg", + "emailVerified" : true, + "createdTimestamp" : 1713615781285, + "enabled" : true, + "totp" : false, + "credentials" : [ { + "id" : "2fa8244c-fba9-43d9-ab4d-80804ca26f6f", + "type" : "password", + "userLabel" : "My password", + "createdDate" : 1713615795357, + "secretData" : "{\"value\":\"sOUpOdi8yf31YbMEub+tAF7N55QHjrPjg48mO3/C1zGaAxLUYdLodf4upuy6w7eBuRrFaVa1m4mRe6wkWtmLIw==\",\"salt\":\"OMbZn6ojNyZdp6/k/72B/A==\",\"additionalParameters\":{}}", + "credentialData" : "{\"hashIterations\":210000,\"algorithm\":\"pbkdf2-sha512\",\"additionalParameters\":{}}" + } ], + "disableableCredentialTypes" : [ ], + "requiredActions" : [ ], + "realmRoles" : [ "default-roles-baeldung" ], + "notBefore" : 0, + "groups" : [ ] + } ] +} \ No newline at end of file diff --git a/spring-security-modules/spring-security-oauth2-testing/pom.xml b/spring-security-modules/spring-security-oauth2-testing/pom.xml index 1f1c441cf5..b2c59d5a98 100644 --- a/spring-security-modules/spring-security-oauth2-testing/pom.xml +++ b/spring-security-modules/spring-security-oauth2-testing/pom.xml @@ -1,38 +1,38 @@ - 4.0.0 - spring-security-oauth2-testing - spring-security-oauth2-testing - pom - spring-security 6 oauth testing sample project + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + spring-security-oauth2-testing + spring-security-oauth2-testing + pom + spring-security 6 oauth testing sample project - - com.baeldung - parent-boot-3 - 0.0.1-SNAPSHOT - ../../parent-boot-3 - + + com.baeldung + parent-boot-3 + 0.0.1-SNAPSHOT + ../../parent-boot-3 + - - - - com.c4-soft.springaddons - spring-addons-oauth2-test - ${spring-addons.version} - - - + + + + com.c4-soft.springaddons + spring-addons-oauth2-test + ${spring-addons.version} + + + - - reactive-resource-server - servlet-resource-server - + + reactive-resource-server + servlet-resource-server + - - 7.1.10 - 17 - + + 7.6.12 + 17 + \ No newline at end of file diff --git a/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/pom.xml b/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/pom.xml index c4badf9caa..f22ebd1bd7 100644 --- a/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/pom.xml +++ b/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/pom.xml @@ -12,6 +12,7 @@ com.baeldung spring-security-oauth2-testing 0.0.1-SNAPSHOT + .. diff --git a/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/main/java/com/baeldung/ReactiveResourceServerApplication.java b/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/main/java/com/baeldung/ReactiveResourceServerApplication.java index 5dd9268092..185cdb9f15 100644 --- a/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/main/java/com/baeldung/ReactiveResourceServerApplication.java +++ b/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/main/java/com/baeldung/ReactiveResourceServerApplication.java @@ -1,7 +1,5 @@ package com.baeldung; -import static org.springframework.security.config.Customizer.withDefaults; - import java.nio.charset.Charset; import java.util.List; import java.util.Map; @@ -17,6 +15,7 @@ import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.authentication.AbstractAuthenticationToken; import org.springframework.security.authentication.AnonymousAuthenticationToken; import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException; import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity; @@ -52,22 +51,22 @@ public class ReactiveResourceServerApplication { @EnableReactiveMethodSecurity static class SecurityConfig { @Bean - SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { - http.oauth2ResourceServer(resourceServer -> resourceServer.jwt(withDefaults())); + SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http, Converter> authenticationConverter) { + http.oauth2ResourceServer(resourceServer -> resourceServer.jwt(jwtResourceServer -> jwtResourceServer.jwtAuthenticationConverter(authenticationConverter))); http.securityContextRepository(NoOpServerSecurityContextRepository.getInstance()); http.csrf(CsrfSpec::disable); - http.exceptionHandling(eh -> eh - .accessDeniedHandler((var exchange, var ex) -> exchange.getPrincipal().flatMap(principal -> { - final var response = exchange.getResponse(); - response.setStatusCode( - principal instanceof AnonymousAuthenticationToken ? HttpStatus.UNAUTHORIZED - : HttpStatus.FORBIDDEN); - response.getHeaders().setContentType(MediaType.TEXT_PLAIN); - final var dataBufferFactory = response.bufferFactory(); - final var buffer = dataBufferFactory.wrap(ex.getMessage().getBytes(Charset.defaultCharset())); - return response.writeWith(Mono.just(buffer)) - .doOnError(error -> DataBufferUtils.release(buffer)); - }))); + http.exceptionHandling(eh -> eh.accessDeniedHandler((var exchange, var ex) -> exchange.getPrincipal() + .flatMap(principal -> { + final var response = exchange.getResponse(); + response.setStatusCode(principal instanceof AnonymousAuthenticationToken ? HttpStatus.UNAUTHORIZED : HttpStatus.FORBIDDEN); + response.getHeaders() + .setContentType(MediaType.TEXT_PLAIN); + final var dataBufferFactory = response.bufferFactory(); + final var buffer = dataBufferFactory.wrap(ex.getMessage() + .getBytes(Charset.defaultCharset())); + return response.writeWith(Mono.just(buffer)) + .doOnError(error -> DataBufferUtils.release(buffer)); + }))); // @formatter:off http.authorizeExchange(req -> req @@ -84,17 +83,18 @@ public class ReactiveResourceServerApplication { @Bean ReactiveJwtAuthoritiesConverter realmRoles2AuthoritiesConverter() { return (Jwt jwt) -> { - final var realmRoles = Optional.of(jwt.getClaimAsMap("realm_access")).orElse(Map.of()); + final var realmRoles = Optional.of(jwt.getClaimAsMap("realm_access")) + .orElse(Map.of()); @SuppressWarnings("unchecked") final var roles = (List) realmRoles.getOrDefault("roles", List.of()); - return Flux.fromStream(roles.stream()).map(SimpleGrantedAuthority::new) - .map(GrantedAuthority.class::cast); + return Flux.fromStream(roles.stream()) + .map(SimpleGrantedAuthority::new) + .map(GrantedAuthority.class::cast); }; } @Bean - ReactiveJwtAuthenticationConverter authenticationConverter( - Converter> authoritiesConverter) { + ReactiveJwtAuthenticationConverter authenticationConverter(Converter> authoritiesConverter) { final var authenticationConverter = new ReactiveJwtAuthenticationConverter(); authenticationConverter.setPrincipalClaimName(StandardClaimNames.PREFERRED_USERNAME); authenticationConverter.setJwtGrantedAuthoritiesConverter(authoritiesConverter); @@ -106,10 +106,12 @@ public class ReactiveResourceServerApplication { public static class MessageService { public Mono greet() { - return ReactiveSecurityContextHolder.getContext().map(ctx -> { - final var who = (JwtAuthenticationToken) ctx.getAuthentication(); - return "Hello %s! You are granted with %s.".formatted(who.getName(), who.getAuthorities()); - }).switchIfEmpty(Mono.error(new AuthenticationCredentialsNotFoundException("Security context is empty"))); + return ReactiveSecurityContextHolder.getContext() + .map(ctx -> { + final var who = (JwtAuthenticationToken) ctx.getAuthentication(); + return "Hello %s! You are granted with %s.".formatted(who.getName(), who.getAuthorities()); + }) + .switchIfEmpty(Mono.error(new AuthenticationCredentialsNotFoundException("Security context is empty"))); } @PreAuthorize("hasRole('AUTHORIZED_PERSONNEL')") @@ -125,18 +127,21 @@ public class ReactiveResourceServerApplication { @GetMapping("/greet") public Mono> greet() { - return messageService.greet().map(ResponseEntity::ok); + return messageService.greet() + .map(ResponseEntity::ok); } @GetMapping("/secured-route") public Mono> securedRoute() { - return messageService.getSecret().map(ResponseEntity::ok); + return messageService.getSecret() + .map(ResponseEntity::ok); } @GetMapping("/secured-method") @PreAuthorize("hasRole('AUTHORIZED_PERSONNEL')") public Mono> securedMethod() { - return messageService.getSecret().map(ResponseEntity::ok); + return messageService.getSecret() + .map(ResponseEntity::ok); } } diff --git a/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/main/resources/application.yaml b/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/main/resources/application.yaml deleted file mode 100644 index 01e655e1b3..0000000000 --- a/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/main/resources/application.yaml +++ /dev/null @@ -1,6 +0,0 @@ -spring: - security: - oauth2: - resourceserver: - jwt: - issuer-uri: https://localhost:8443/realms/master diff --git a/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/main/resources/application.yml b/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/main/resources/application.yml new file mode 100644 index 0000000000..dcda50e07d --- /dev/null +++ b/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/main/resources/application.yml @@ -0,0 +1,11 @@ +server: + port: 8082 + +spring: + application: + name: reactive-resource-server + security: + oauth2: + resourceserver: + jwt: + issuer-uri: http://localhost:8080/realms/baeldung diff --git a/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/main/resources/banner.txt b/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/main/resources/banner.txt new file mode 100644 index 0000000000..cdecee35fb --- /dev/null +++ b/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/main/resources/banner.txt @@ -0,0 +1,16 @@ +${AnsiColor.GREEN} _____ _ _ +${AnsiColor.GREEN} | __ \ | | (_) +${AnsiColor.GREEN} | |__) |___ __ _ ___| |_ ___ _____ _ __ ___ ___ ___ _ _ _ __ ___ ___ ___ ___ _ ____ _____ _ __ +${AnsiColor.GREEN} | _ // _ \/ _` |/ __| __| \ \ / / _ \ | '__/ _ \/ __|/ _ \| | | | '__/ __/ _ \ / __|/ _ \ '__\ \ / / _ \ '__| +${AnsiColor.GREEN} | | \ \ __/ (_| | (__| |_| |\ V / __/ | | | __/\__ \ (_) | |_| | | | (_| __/ \__ \ __/ | \ V / __/ | +${AnsiColor.GREEN} |_| \_\___|\__,_|\___|\__|_| \_/ \___| |_| \___||___/\___/ \__,_|_| \___\___| |___/\___|_| \_/ \___|_| +${AnsiColor.GREEN} +${AnsiColor.GREEN} +${AnsiColor.BLUE} __ __ __ ______ __ __ ______ +${AnsiColor.BLUE} _____/ /_ / // / ____ ___ ____ / ____ \_____/ // / _________ / __/ /_ _________ ____ ___ +${AnsiColor.BLUE} / ___/ __ \/ // /_/ __ `__ \/ __ \/ / __ `/ ___/ // /_______/ ___/ __ \/ /_/ __// ___/ __ \/ __ `__ \ +${AnsiColor.BLUE}/ /__/ / / /__ __/ / / / / / /_/ / / /_/ / /__/__ __/_____(__ ) /_/ / __/ /__/ /__/ /_/ / / / / / / +${AnsiColor.BLUE}\___/_/ /_/ /_/ /_/ /_/ /_/ .___/\ \__,_/\___/ /_/ /____/\____/_/ \__(_)___/\____/_/ /_/ /_/ +${AnsiColor.BLUE} /_/ \____/ +${AnsiColor.RED}Spring Boot ${spring-boot.formatted-version} +${AnsiColor.BLACK} \ No newline at end of file diff --git a/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/test/java/com/baeldung/SpringSecurityTestGreetingControllerUnitTest.java b/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/test/java/com/baeldung/SpringSecurityTestGreetingControllerUnitTest.java index c7a0659cf1..3c1185b826 100644 --- a/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/test/java/com/baeldung/SpringSecurityTestGreetingControllerUnitTest.java +++ b/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/test/java/com/baeldung/SpringSecurityTestGreetingControllerUnitTest.java @@ -3,8 +3,6 @@ package com.baeldung; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.mockAuthentication; -import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.mockJwt; import java.util.List; @@ -16,6 +14,7 @@ import org.springframework.security.authentication.AnonymousAuthenticationToken; import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.oauth2.core.oidc.StandardClaimNames; +import org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers; import org.springframework.test.web.reactive.server.WebTestClient; import com.baeldung.ReactiveResourceServerApplication.GreetingController; @@ -40,7 +39,7 @@ class SpringSecurityTestGreetingControllerUnitTest { @Test void givenRequestIsAnonymous_whenGetGreet_thenUnauthorized() { - api.mutateWith(mockAuthentication(ANONYMOUS_AUTHENTICATION)) + api.mutateWith(SecurityMockServerConfigurers.mockAuthentication(ANONYMOUS_AUTHENTICATION)) .get() .uri("/greet") .exchange() @@ -53,7 +52,8 @@ class SpringSecurityTestGreetingControllerUnitTest { final var greeting = "Whatever the service returns"; when(messageService.greet()).thenReturn(Mono.just(greeting)); - api.mutateWith(mockJwt().authorities(List.of(new SimpleGrantedAuthority("admin"), new SimpleGrantedAuthority("ROLE_AUTHORIZED_PERSONNEL"))) + api.mutateWith(SecurityMockServerConfigurers.mockJwt() + .authorities(List.of(new SimpleGrantedAuthority("admin"), new SimpleGrantedAuthority("ROLE_AUTHORIZED_PERSONNEL"))) .jwt(jwt -> jwt.claim(StandardClaimNames.PREFERRED_USERNAME, "ch4mpy"))) .get() .uri("/greet") @@ -73,7 +73,7 @@ class SpringSecurityTestGreetingControllerUnitTest { @Test void givenRequestIsAnonymous_whenGetSecuredRoute_thenUnauthorized() { - api.mutateWith(mockAuthentication(ANONYMOUS_AUTHENTICATION)) + api.mutateWith(SecurityMockServerConfigurers.mockAuthentication(ANONYMOUS_AUTHENTICATION)) .get() .uri("/secured-route") .exchange() @@ -86,7 +86,8 @@ class SpringSecurityTestGreetingControllerUnitTest { final var secret = "Secret!"; when(messageService.getSecret()).thenReturn(Mono.just(secret)); - api.mutateWith(mockJwt().authorities(new SimpleGrantedAuthority("ROLE_AUTHORIZED_PERSONNEL"))) + api.mutateWith(SecurityMockServerConfigurers.mockJwt() + .authorities(new SimpleGrantedAuthority("ROLE_AUTHORIZED_PERSONNEL"))) .get() .uri("/secured-route") .exchange() @@ -98,7 +99,8 @@ class SpringSecurityTestGreetingControllerUnitTest { @Test void givenUserIsNotGrantedWithRoleAuthorizedPersonnel_whenGetSecuredRoute_thenForbidden() { - api.mutateWith(mockJwt().authorities(new SimpleGrantedAuthority("admin"))) + api.mutateWith(SecurityMockServerConfigurers.mockJwt() + .authorities(new SimpleGrantedAuthority("admin"))) .get() .uri("/secured-route") .exchange() @@ -113,7 +115,7 @@ class SpringSecurityTestGreetingControllerUnitTest { @Test void givenRequestIsAnonymous_whenGetSecuredMethod_thenUnauthorized() { - api.mutateWith(mockAuthentication(ANONYMOUS_AUTHENTICATION)) + api.mutateWith(SecurityMockServerConfigurers.mockAuthentication(ANONYMOUS_AUTHENTICATION)) .get() .uri("/secured-method") .exchange() @@ -126,7 +128,8 @@ class SpringSecurityTestGreetingControllerUnitTest { final var secret = "Secret!"; when(messageService.getSecret()).thenReturn(Mono.just(secret)); - api.mutateWith(mockJwt().authorities(new SimpleGrantedAuthority("ROLE_AUTHORIZED_PERSONNEL"))) + api.mutateWith(SecurityMockServerConfigurers.mockJwt() + .authorities(new SimpleGrantedAuthority("ROLE_AUTHORIZED_PERSONNEL"))) .get() .uri("/secured-method") .exchange() @@ -138,7 +141,8 @@ class SpringSecurityTestGreetingControllerUnitTest { @Test void givenUserIsNotGrantedWithRoleAuthorizedPersonnel_whenGetSecuredMethod_thenForbidden() { - api.mutateWith(mockJwt().authorities(new SimpleGrantedAuthority("admin"))) + api.mutateWith(SecurityMockServerConfigurers.mockJwt() + .authorities(new SimpleGrantedAuthority("admin"))) .get() .uri("/secured-method") .exchange() diff --git a/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/pom.xml b/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/pom.xml index 25bd8a396c..ddd6c1d313 100644 --- a/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/pom.xml +++ b/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/pom.xml @@ -12,6 +12,7 @@ com.baeldung spring-security-oauth2-testing 0.0.1-SNAPSHOT + .. diff --git a/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/main/java/com/baeldung/ServletResourceServerApplication.java b/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/main/java/com/baeldung/ServletResourceServerApplication.java index 7887089458..a0928e9149 100644 --- a/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/main/java/com/baeldung/ServletResourceServerApplication.java +++ b/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/main/java/com/baeldung/ServletResourceServerApplication.java @@ -1,7 +1,5 @@ package com.baeldung; -import static org.springframework.security.config.Customizer.withDefaults; - import java.util.Collection; import java.util.List; import java.util.Map; @@ -16,6 +14,7 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.authentication.AbstractAuthenticationToken; import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; @@ -48,8 +47,8 @@ public class ServletResourceServerApplication { @EnableWebSecurity static class SecurityConf { @Bean - SecurityFilterChain filterChain(HttpSecurity http) throws Exception { - http.oauth2ResourceServer(resourceServer -> resourceServer.jwt(withDefaults())); + SecurityFilterChain filterChain(HttpSecurity http, Converter authenticationConverter) throws Exception { + http.oauth2ResourceServer(resourceServer -> resourceServer.jwt(jwtResourceServer -> jwtResourceServer.jwtAuthenticationConverter(authenticationConverter))); http.sessionManagement(sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS)); http.csrf(AbstractHttpConfigurer::disable); http.exceptionHandling(eh -> eh.authenticationEntryPoint((request, response, authException) -> { @@ -57,11 +56,11 @@ public class ServletResourceServerApplication { response.sendError(HttpStatus.UNAUTHORIZED.value(), HttpStatus.UNAUTHORIZED.getReasonPhrase()); })); - // @formatter:off - http.authorizeHttpRequests(req -> req - .requestMatchers(new AntPathRequestMatcher("/secured-route")).hasRole("AUTHORIZED_PERSONNEL") - .anyRequest().authenticated()); - // @formatter:on + // @formatter:off + http.authorizeHttpRequests(req -> req + .requestMatchers(new AntPathRequestMatcher("/secured-route")).hasRole("AUTHORIZED_PERSONNEL") + .anyRequest().authenticated()); + // @formatter:on return http.build(); } @@ -72,10 +71,14 @@ public class ServletResourceServerApplication { @Bean JwtAuthoritiesConverter realmRoles2AuthoritiesConverter() { return (Jwt jwt) -> { - final var realmRoles = Optional.of(jwt.getClaimAsMap("realm_access")).orElse(Map.of()); + final var realmRoles = Optional.of(jwt.getClaimAsMap("realm_access")) + .orElse(Map.of()); @SuppressWarnings("unchecked") final var roles = (List) realmRoles.getOrDefault("roles", List.of()); - return roles.stream().map(SimpleGrantedAuthority::new).map(GrantedAuthority.class::cast).toList(); + return roles.stream() + .map(SimpleGrantedAuthority::new) + .map(GrantedAuthority.class::cast) + .toList(); }; } @@ -92,7 +95,8 @@ public class ServletResourceServerApplication { public static class MessageService { public String greet() { - final var who = (JwtAuthenticationToken) SecurityContextHolder.getContext().getAuthentication(); + final var who = (JwtAuthenticationToken) SecurityContextHolder.getContext() + .getAuthentication(); return "Hello %s! You are granted with %s.".formatted(who.getName(), who.getAuthorities()); } diff --git a/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/main/resources/application.properties b/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/main/resources/application.properties deleted file mode 100644 index 998f6303aa..0000000000 --- a/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ -spring.security.oauth2.resourceserver.jwt.issuer-uri=https://localhost:8443/realms/master diff --git a/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/main/resources/application.yml b/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/main/resources/application.yml new file mode 100644 index 0000000000..8335931381 --- /dev/null +++ b/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/main/resources/application.yml @@ -0,0 +1,11 @@ +server: + port: 8081 + +spring: + application: + name: servlet-resource-server + security: + oauth2: + resourceserver: + jwt: + issuer-uri: http://localhost:8080/realms/baeldung diff --git a/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/main/resources/banner.txt b/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/main/resources/banner.txt new file mode 100644 index 0000000000..23e0e9c9cd --- /dev/null +++ b/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/main/resources/banner.txt @@ -0,0 +1,16 @@ +${AnsiColor.GREEN} _____ _ _ +${AnsiColor.GREEN} / ____| | | | | +${AnsiColor.GREEN} | (___ ___ _ ____ _| | ___| |_ _ __ ___ ___ ___ _ _ _ __ ___ ___ ___ ___ _ ____ _____ _ __ +${AnsiColor.GREEN} \___ \ / _ \ '__\ \ / / |/ _ \ __| | '__/ _ \/ __|/ _ \| | | | '__/ __/ _ \ / __|/ _ \ '__\ \ / / _ \ '__| +${AnsiColor.GREEN} ____) | __/ | \ V /| | __/ |_ | | | __/\__ \ (_) | |_| | | | (_| __/ \__ \ __/ | \ V / __/ | +${AnsiColor.GREEN} |_____/ \___|_| \_/ |_|\___|\__| |_| \___||___/\___/ \__,_|_| \___\___| |___/\___|_| \_/ \___|_| +${AnsiColor.GREEN} +${AnsiColor.GREEN} +${AnsiColor.BLUE} __ __ __ ______ __ __ ______ +${AnsiColor.BLUE} _____/ /_ / // / ____ ___ ____ / ____ \_____/ // / _________ / __/ /_ _________ ____ ___ +${AnsiColor.BLUE} / ___/ __ \/ // /_/ __ `__ \/ __ \/ / __ `/ ___/ // /_______/ ___/ __ \/ /_/ __// ___/ __ \/ __ `__ \ +${AnsiColor.BLUE}/ /__/ / / /__ __/ / / / / / /_/ / / /_/ / /__/__ __/_____(__ ) /_/ / __/ /__/ /__/ /_/ / / / / / / +${AnsiColor.BLUE}\___/_/ /_/ /_/ /_/ /_/ /_/ .___/\ \__,_/\___/ /_/ /____/\____/_/ \__(_)___/\____/_/ /_/ /_/ +${AnsiColor.BLUE} /_/ \____/ +${AnsiColor.RED}Spring Boot ${spring-boot.formatted-version} +${AnsiColor.BLACK} \ No newline at end of file diff --git a/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/test/java/com/baeldung/SpringAddonsGreetingControllerUnitTest.java b/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/test/java/com/baeldung/SpringAddonsGreetingControllerUnitTest.java index 2534d9919a..2a47a919dd 100644 --- a/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/test/java/com/baeldung/SpringAddonsGreetingControllerUnitTest.java +++ b/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/test/java/com/baeldung/SpringAddonsGreetingControllerUnitTest.java @@ -44,9 +44,7 @@ class SpringAddonsGreetingControllerUnitTest { } @ParameterizedTest - @AuthenticationSource({ - @WithMockAuthentication(authorities = { "admin", "ROLE_AUTHORIZED_PERSONNEL" }, name = "ch4mpy"), - @WithMockAuthentication(authorities = { "uncle", "PIRATE" }, name = "tonton-pirate") }) + @AuthenticationSource({ @WithMockAuthentication(authorities = { "admin", "ROLE_AUTHORIZED_PERSONNEL" }, name = "ch4mpy"), @WithMockAuthentication(authorities = { "uncle", "PIRATE" }, name = "tonton-pirate") }) void givenUserIsAuthenticated_whenGetGreet_thenOk(@ParameterizedAuthentication Authentication auth) throws Exception { final var greeting = "Whatever the service returns"; when(messageService.greet()).thenReturn(greeting); diff --git a/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/test/java/com/baeldung/SpringSecurityTestGreetingControllerUnitTest.java b/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/test/java/com/baeldung/SpringSecurityTestGreetingControllerUnitTest.java index 0e710bcc9f..ce57342ef6 100644 --- a/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/test/java/com/baeldung/SpringSecurityTestGreetingControllerUnitTest.java +++ b/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/test/java/com/baeldung/SpringSecurityTestGreetingControllerUnitTest.java @@ -3,8 +3,6 @@ package com.baeldung; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.anonymous; -import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.jwt; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -17,6 +15,7 @@ import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.oauth2.core.oidc.StandardClaimNames; +import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors; import org.springframework.test.web.servlet.MockMvc; import com.baeldung.ServletResourceServerApplication.GreetingController; @@ -38,7 +37,7 @@ class SpringSecurityTestGreetingControllerUnitTest { @Test void givenRequestIsAnonymous_whenGetGreet_thenUnauthorized() throws Exception { - api.perform(get("/greet").with(anonymous())) + api.perform(get("/greet").with(SecurityMockMvcRequestPostProcessors.anonymous())) .andExpect(status().isUnauthorized()); } @@ -47,7 +46,8 @@ class SpringSecurityTestGreetingControllerUnitTest { final var greeting = "Whatever the service returns"; when(messageService.greet()).thenReturn(greeting); - api.perform(get("/greet").with(jwt().authorities(List.of(new SimpleGrantedAuthority("admin"), new SimpleGrantedAuthority("ROLE_AUTHORIZED_PERSONNEL"))) + api.perform(get("/greet").with(SecurityMockMvcRequestPostProcessors.jwt() + .authorities(List.of(new SimpleGrantedAuthority("admin"), new SimpleGrantedAuthority("ROLE_AUTHORIZED_PERSONNEL"))) .jwt(jwt -> jwt.claim(StandardClaimNames.PREFERRED_USERNAME, "ch4mpy")))) .andExpect(status().isOk()) .andExpect(content().string(greeting)); @@ -62,7 +62,7 @@ class SpringSecurityTestGreetingControllerUnitTest { @Test void givenRequestIsAnonymous_whenGetSecuredRoute_thenUnauthorized() throws Exception { - api.perform(get("/secured-route").with(anonymous())) + api.perform(get("/secured-route").with(SecurityMockMvcRequestPostProcessors.anonymous())) .andExpect(status().isUnauthorized()); } @@ -71,14 +71,16 @@ class SpringSecurityTestGreetingControllerUnitTest { final var secret = "Secret!"; when(messageService.getSecret()).thenReturn(secret); - api.perform(get("/secured-route").with(jwt().authorities(new SimpleGrantedAuthority("ROLE_AUTHORIZED_PERSONNEL")))) + api.perform(get("/secured-route").with(SecurityMockMvcRequestPostProcessors.jwt() + .authorities(new SimpleGrantedAuthority("ROLE_AUTHORIZED_PERSONNEL")))) .andExpect(status().isOk()) .andExpect(content().string(secret)); } @Test void givenUserIsNotGrantedWithRoleAuthorizedPersonnel_whenGetSecuredRoute_thenForbidden() throws Exception { - api.perform(get("/secured-route").with(jwt().authorities(new SimpleGrantedAuthority("admin")))) + api.perform(get("/secured-route").with(SecurityMockMvcRequestPostProcessors.jwt() + .authorities(new SimpleGrantedAuthority("admin")))) .andExpect(status().isForbidden()); } @@ -89,7 +91,7 @@ class SpringSecurityTestGreetingControllerUnitTest { @Test void givenRequestIsAnonymous_whenGetSecuredMethod_thenUnauthorized() throws Exception { - api.perform(get("/secured-method").with(anonymous())) + api.perform(get("/secured-method").with(SecurityMockMvcRequestPostProcessors.anonymous())) .andExpect(status().isUnauthorized()); } @@ -98,14 +100,16 @@ class SpringSecurityTestGreetingControllerUnitTest { final var secret = "Secret!"; when(messageService.getSecret()).thenReturn(secret); - api.perform(get("/secured-method").with(jwt().authorities(new SimpleGrantedAuthority("ROLE_AUTHORIZED_PERSONNEL")))) + api.perform(get("/secured-method").with(SecurityMockMvcRequestPostProcessors.jwt() + .authorities(new SimpleGrantedAuthority("ROLE_AUTHORIZED_PERSONNEL")))) .andExpect(status().isOk()) .andExpect(content().string(secret)); } @Test void givenUserIsNotGrantedWithRoleAuthorizedPersonnel_whenGetSecuredMethod_thenForbidden() throws Exception { - api.perform(get("/secured-method").with(jwt().authorities(new SimpleGrantedAuthority("admin")))) + api.perform(get("/secured-method").with(SecurityMockMvcRequestPostProcessors.jwt() + .authorities(new SimpleGrantedAuthority("admin")))) .andExpect(status().isForbidden()); } From f80faa08c82ea602419f04fc9d37ca41297b4fb3 Mon Sep 17 00:00:00 2001 From: ch4mpy Date: Sun, 21 Apr 2024 16:38:05 -1000 Subject: [PATCH 09/33] BAEL-7704 : (CONFIGURATION) format resources --- .../keycloak/import/baeldung-realm.json | 4158 +++++++++-------- .../keycloak/import/baeldung-users-0.json | 108 +- .../reactive-resource-server/pom.xml | 108 +- .../src/test/resources/ch4mpy.json | 26 +- .../src/test/resources/tonton-pirate.json | 26 +- .../servlet-resource-server/pom.xml | 108 +- .../src/test/resources/ch4mpy.json | 26 +- .../src/test/resources/tonton-pirate.json | 26 +- 8 files changed, 2553 insertions(+), 2033 deletions(-) diff --git a/spring-security-modules/spring-security-oauth2-testing/keycloak/import/baeldung-realm.json b/spring-security-modules/spring-security-oauth2-testing/keycloak/import/baeldung-realm.json index 616f0c1f74..decb2f52b5 100644 --- a/spring-security-modules/spring-security-oauth2-testing/keycloak/import/baeldung-realm.json +++ b/spring-security-modules/spring-security-oauth2-testing/keycloak/import/baeldung-realm.json @@ -1,1827 +1,2335 @@ { - "id" : "7a046c8d-77b1-4851-b4a9-e3a25a17e431", - "realm" : "baeldung", - "notBefore" : 0, - "defaultSignatureAlgorithm" : "RS256", - "revokeRefreshToken" : false, - "refreshTokenMaxReuse" : 0, - "accessTokenLifespan" : 300, - "accessTokenLifespanForImplicitFlow" : 900, - "ssoSessionIdleTimeout" : 1800, - "ssoSessionMaxLifespan" : 36000, - "ssoSessionIdleTimeoutRememberMe" : 0, - "ssoSessionMaxLifespanRememberMe" : 0, - "offlineSessionIdleTimeout" : 2592000, - "offlineSessionMaxLifespanEnabled" : false, - "offlineSessionMaxLifespan" : 5184000, - "clientSessionIdleTimeout" : 0, - "clientSessionMaxLifespan" : 0, - "clientOfflineSessionIdleTimeout" : 0, - "clientOfflineSessionMaxLifespan" : 0, - "accessCodeLifespan" : 60, - "accessCodeLifespanUserAction" : 300, - "accessCodeLifespanLogin" : 1800, - "actionTokenGeneratedByAdminLifespan" : 43200, - "actionTokenGeneratedByUserLifespan" : 300, - "oauth2DeviceCodeLifespan" : 600, - "oauth2DevicePollingInterval" : 5, - "enabled" : true, - "sslRequired" : "external", - "registrationAllowed" : false, - "registrationEmailAsUsername" : false, - "rememberMe" : false, - "verifyEmail" : false, - "loginWithEmailAllowed" : true, - "duplicateEmailsAllowed" : false, - "resetPasswordAllowed" : false, - "editUsernameAllowed" : false, - "bruteForceProtected" : false, - "permanentLockout" : false, - "maxTemporaryLockouts" : 0, - "maxFailureWaitSeconds" : 900, - "minimumQuickLoginWaitSeconds" : 60, - "waitIncrementSeconds" : 60, - "quickLoginCheckMilliSeconds" : 1000, - "maxDeltaTimeSeconds" : 43200, - "failureFactor" : 30, - "roles" : { - "realm" : [ { - "id" : "4ad869c1-56f3-45fd-b345-f107f2834de1", - "name" : "AUTHORIZED_PERSONNEL", - "description" : "", - "composite" : false, - "clientRole" : false, - "containerId" : "7a046c8d-77b1-4851-b4a9-e3a25a17e431", - "attributes" : { } - }, { - "id" : "bfdf00fe-5111-404b-858c-50dcb8a63e61", - "name" : "default-roles-baeldung", - "description" : "${role_default-roles}", - "composite" : true, - "composites" : { - "realm" : [ "offline_access", "uma_authorization" ], - "client" : { - "account" : [ "view-profile", "manage-account" ] - } - }, - "clientRole" : false, - "containerId" : "7a046c8d-77b1-4851-b4a9-e3a25a17e431", - "attributes" : { } - }, { - "id" : "96fbbf77-c81e-472b-bb2e-184713dfffde", - "name" : "uma_authorization", - "description" : "${role_uma_authorization}", - "composite" : false, - "clientRole" : false, - "containerId" : "7a046c8d-77b1-4851-b4a9-e3a25a17e431", - "attributes" : { } - }, { - "id" : "cec72467-237c-4ae9-ae1d-ca84ff51b404", - "name" : "offline_access", - "description" : "${role_offline-access}", - "composite" : false, - "clientRole" : false, - "containerId" : "7a046c8d-77b1-4851-b4a9-e3a25a17e431", - "attributes" : { } - } ], - "client" : { - "realm-management" : [ { - "id" : "955d707a-3baa-4462-a53c-83ff73b30a12", - "name" : "view-realm", - "description" : "${role_view-realm}", - "composite" : false, - "clientRole" : true, - "containerId" : "4720b673-8d8b-4709-b695-88d6c17e8edf", - "attributes" : { } - }, { - "id" : "81cbcb10-8e84-431e-8da8-07219be8d93d", - "name" : "view-clients", - "description" : "${role_view-clients}", - "composite" : true, - "composites" : { - "client" : { - "realm-management" : [ "query-clients" ] - } - }, - "clientRole" : true, - "containerId" : "4720b673-8d8b-4709-b695-88d6c17e8edf", - "attributes" : { } - }, { - "id" : "fa1adc6d-7b86-4dc6-a120-57eee9a4fe93", - "name" : "create-client", - "description" : "${role_create-client}", - "composite" : false, - "clientRole" : true, - "containerId" : "4720b673-8d8b-4709-b695-88d6c17e8edf", - "attributes" : { } - }, { - "id" : "be5a19cb-fa00-486a-abfa-eb0dc86680fb", - "name" : "view-users", - "description" : "${role_view-users}", - "composite" : true, - "composites" : { - "client" : { - "realm-management" : [ "query-users", "query-groups" ] - } - }, - "clientRole" : true, - "containerId" : "4720b673-8d8b-4709-b695-88d6c17e8edf", - "attributes" : { } - }, { - "id" : "d76de5c9-10f2-4b68-9850-a16d9b2dd35a", - "name" : "manage-identity-providers", - "description" : "${role_manage-identity-providers}", - "composite" : false, - "clientRole" : true, - "containerId" : "4720b673-8d8b-4709-b695-88d6c17e8edf", - "attributes" : { } - }, { - "id" : "6339f747-4f89-4e67-9c77-420524135d96", - "name" : "manage-authorization", - "description" : "${role_manage-authorization}", - "composite" : false, - "clientRole" : true, - "containerId" : "4720b673-8d8b-4709-b695-88d6c17e8edf", - "attributes" : { } - }, { - "id" : "c9d5af42-6742-49cf-bd01-a730f4c3cc2e", - "name" : "impersonation", - "description" : "${role_impersonation}", - "composite" : false, - "clientRole" : true, - "containerId" : "4720b673-8d8b-4709-b695-88d6c17e8edf", - "attributes" : { } - }, { - "id" : "56dccfed-9379-4cfb-a720-b9b9e1745048", - "name" : "view-identity-providers", - "description" : "${role_view-identity-providers}", - "composite" : false, - "clientRole" : true, - "containerId" : "4720b673-8d8b-4709-b695-88d6c17e8edf", - "attributes" : { } - }, { - "id" : "e10c568f-c50f-4ee4-88cf-43f0c4a1dc2c", - "name" : "manage-realm", - "description" : "${role_manage-realm}", - "composite" : false, - "clientRole" : true, - "containerId" : "4720b673-8d8b-4709-b695-88d6c17e8edf", - "attributes" : { } - }, { - "id" : "d12dcfc2-b649-4c11-ac55-41d6ab10f5c6", - "name" : "query-users", - "description" : "${role_query-users}", - "composite" : false, - "clientRole" : true, - "containerId" : "4720b673-8d8b-4709-b695-88d6c17e8edf", - "attributes" : { } - }, { - "id" : "57977d45-f810-400a-81ca-63a9bdddd3b9", - "name" : "query-realms", - "description" : "${role_query-realms}", - "composite" : false, - "clientRole" : true, - "containerId" : "4720b673-8d8b-4709-b695-88d6c17e8edf", - "attributes" : { } - }, { - "id" : "e14dfabc-3f03-42cf-a716-5261b7002914", - "name" : "query-groups", - "description" : "${role_query-groups}", - "composite" : false, - "clientRole" : true, - "containerId" : "4720b673-8d8b-4709-b695-88d6c17e8edf", - "attributes" : { } - }, { - "id" : "800d272c-1327-485c-9d2f-576f3d9a0178", - "name" : "view-authorization", - "description" : "${role_view-authorization}", - "composite" : false, - "clientRole" : true, - "containerId" : "4720b673-8d8b-4709-b695-88d6c17e8edf", - "attributes" : { } - }, { - "id" : "fdc10176-42c0-4b58-968a-35bfd5dbce20", - "name" : "view-events", - "description" : "${role_view-events}", - "composite" : false, - "clientRole" : true, - "containerId" : "4720b673-8d8b-4709-b695-88d6c17e8edf", - "attributes" : { } - }, { - "id" : "23393ccd-3b70-4de8-9e00-0adbb11851ce", - "name" : "manage-users", - "description" : "${role_manage-users}", - "composite" : false, - "clientRole" : true, - "containerId" : "4720b673-8d8b-4709-b695-88d6c17e8edf", - "attributes" : { } - }, { - "id" : "01a3847f-7602-400d-bedd-7545618559f3", - "name" : "manage-clients", - "description" : "${role_manage-clients}", - "composite" : false, - "clientRole" : true, - "containerId" : "4720b673-8d8b-4709-b695-88d6c17e8edf", - "attributes" : { } - }, { - "id" : "7d8ac9c4-6d1b-4861-a0b9-0479cbd55b14", - "name" : "query-clients", - "description" : "${role_query-clients}", - "composite" : false, - "clientRole" : true, - "containerId" : "4720b673-8d8b-4709-b695-88d6c17e8edf", - "attributes" : { } - }, { - "id" : "788677b0-3fbf-457d-8b62-25f305b86bcf", - "name" : "manage-events", - "description" : "${role_manage-events}", - "composite" : false, - "clientRole" : true, - "containerId" : "4720b673-8d8b-4709-b695-88d6c17e8edf", - "attributes" : { } - }, { - "id" : "642d82d5-1071-47a9-aca9-d0fbd28d0328", - "name" : "realm-admin", - "description" : "${role_realm-admin}", - "composite" : true, - "composites" : { - "client" : { - "realm-management" : [ "view-realm", "view-clients", "create-client", "view-users", "manage-identity-providers", "manage-authorization", "impersonation", "view-identity-providers", "manage-realm", "query-users", "query-realms", "view-authorization", "query-groups", "view-events", "manage-users", "manage-clients", "query-clients", "manage-events" ] - } - }, - "clientRole" : true, - "containerId" : "4720b673-8d8b-4709-b695-88d6c17e8edf", - "attributes" : { } - } ], - "security-admin-console" : [ ], - "admin-cli" : [ ], - "baeldung-confidential" : [ ], - "account-console" : [ ], - "broker" : [ { - "id" : "9043c535-f6d3-44dc-8c48-d3983e04a93b", - "name" : "read-token", - "description" : "${role_read-token}", - "composite" : false, - "clientRole" : true, - "containerId" : "cb2ee74f-fb36-4f21-82bb-4928966ea449", - "attributes" : { } - } ], - "account" : [ { - "id" : "4a188a41-39d9-47e6-b8de-6d9b42c7a414", - "name" : "view-profile", - "description" : "${role_view-profile}", - "composite" : false, - "clientRole" : true, - "containerId" : "1b64b350-3ef8-4be6-b9ab-c53463b2fd1b", - "attributes" : { } - }, { - "id" : "da24f251-0c13-4035-84f1-16c5a3301ea6", - "name" : "view-consent", - "description" : "${role_view-consent}", - "composite" : false, - "clientRole" : true, - "containerId" : "1b64b350-3ef8-4be6-b9ab-c53463b2fd1b", - "attributes" : { } - }, { - "id" : "26edbb7d-dd9f-4dd4-a282-a6e886e38302", - "name" : "manage-account-links", - "description" : "${role_manage-account-links}", - "composite" : false, - "clientRole" : true, - "containerId" : "1b64b350-3ef8-4be6-b9ab-c53463b2fd1b", - "attributes" : { } - }, { - "id" : "b2c98d1e-4a85-4e11-901d-0207e9793acf", - "name" : "manage-consent", - "description" : "${role_manage-consent}", - "composite" : true, - "composites" : { - "client" : { - "account" : [ "view-consent" ] - } - }, - "clientRole" : true, - "containerId" : "1b64b350-3ef8-4be6-b9ab-c53463b2fd1b", - "attributes" : { } - }, { - "id" : "f244eb36-cf20-4e96-8233-fee1ee8da72e", - "name" : "manage-account", - "description" : "${role_manage-account}", - "composite" : true, - "composites" : { - "client" : { - "account" : [ "manage-account-links" ] - } - }, - "clientRole" : true, - "containerId" : "1b64b350-3ef8-4be6-b9ab-c53463b2fd1b", - "attributes" : { } - }, { - "id" : "a5ca4c2f-d8ad-4c8c-bfd4-1173dd7c1338", - "name" : "view-groups", - "description" : "${role_view-groups}", - "composite" : false, - "clientRole" : true, - "containerId" : "1b64b350-3ef8-4be6-b9ab-c53463b2fd1b", - "attributes" : { } - }, { - "id" : "83f4a43c-07cd-43d5-af99-7825ea603ca9", - "name" : "view-applications", - "description" : "${role_view-applications}", - "composite" : false, - "clientRole" : true, - "containerId" : "1b64b350-3ef8-4be6-b9ab-c53463b2fd1b", - "attributes" : { } - }, { - "id" : "18642f4e-1e2a-4023-9947-7a425d8ed76e", - "name" : "delete-account", - "description" : "${role_delete-account}", - "composite" : false, - "clientRole" : true, - "containerId" : "1b64b350-3ef8-4be6-b9ab-c53463b2fd1b", - "attributes" : { } - } ] - } - }, - "groups" : [ ], - "defaultRole" : { - "id" : "bfdf00fe-5111-404b-858c-50dcb8a63e61", - "name" : "default-roles-baeldung", - "description" : "${role_default-roles}", - "composite" : true, - "clientRole" : false, - "containerId" : "7a046c8d-77b1-4851-b4a9-e3a25a17e431" - }, - "requiredCredentials" : [ "password" ], - "otpPolicyType" : "totp", - "otpPolicyAlgorithm" : "HmacSHA1", - "otpPolicyInitialCounter" : 0, - "otpPolicyDigits" : 6, - "otpPolicyLookAheadWindow" : 1, - "otpPolicyPeriod" : 30, - "otpPolicyCodeReusable" : false, - "otpSupportedApplications" : [ "totpAppFreeOTPName", "totpAppGoogleName", "totpAppMicrosoftAuthenticatorName" ], - "localizationTexts" : { }, - "webAuthnPolicyRpEntityName" : "keycloak", - "webAuthnPolicySignatureAlgorithms" : [ "ES256" ], - "webAuthnPolicyRpId" : "", - "webAuthnPolicyAttestationConveyancePreference" : "not specified", - "webAuthnPolicyAuthenticatorAttachment" : "not specified", - "webAuthnPolicyRequireResidentKey" : "not specified", - "webAuthnPolicyUserVerificationRequirement" : "not specified", - "webAuthnPolicyCreateTimeout" : 0, - "webAuthnPolicyAvoidSameAuthenticatorRegister" : false, - "webAuthnPolicyAcceptableAaguids" : [ ], - "webAuthnPolicyExtraOrigins" : [ ], - "webAuthnPolicyPasswordlessRpEntityName" : "keycloak", - "webAuthnPolicyPasswordlessSignatureAlgorithms" : [ "ES256" ], - "webAuthnPolicyPasswordlessRpId" : "", - "webAuthnPolicyPasswordlessAttestationConveyancePreference" : "not specified", - "webAuthnPolicyPasswordlessAuthenticatorAttachment" : "not specified", - "webAuthnPolicyPasswordlessRequireResidentKey" : "not specified", - "webAuthnPolicyPasswordlessUserVerificationRequirement" : "not specified", - "webAuthnPolicyPasswordlessCreateTimeout" : 0, - "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister" : false, - "webAuthnPolicyPasswordlessAcceptableAaguids" : [ ], - "webAuthnPolicyPasswordlessExtraOrigins" : [ ], - "scopeMappings" : [ { - "clientScope" : "offline_access", - "roles" : [ "offline_access" ] - } ], - "clientScopeMappings" : { - "account" : [ { - "client" : "account-console", - "roles" : [ "manage-account", "view-groups" ] - } ] - }, - "clients" : [ { - "id" : "1b64b350-3ef8-4be6-b9ab-c53463b2fd1b", - "clientId" : "account", - "name" : "${client_account}", - "rootUrl" : "${authBaseUrl}", - "baseUrl" : "/realms/baeldung/account/", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "redirectUris" : [ "/realms/baeldung/account/*" ], - "webOrigins" : [ ], - "notBefore" : 0, - "bearerOnly" : false, - "consentRequired" : false, - "standardFlowEnabled" : true, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : false, - "serviceAccountsEnabled" : false, - "publicClient" : true, - "frontchannelLogout" : false, - "protocol" : "openid-connect", - "attributes" : { - "post.logout.redirect.uris" : "+" - }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : false, - "nodeReRegistrationTimeout" : 0, - "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] - }, { - "id" : "4beaa749-404c-4a6a-9b04-72df4f9066a4", - "clientId" : "account-console", - "name" : "${client_account-console}", - "rootUrl" : "${authBaseUrl}", - "baseUrl" : "/realms/baeldung/account/", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "redirectUris" : [ "/realms/baeldung/account/*" ], - "webOrigins" : [ ], - "notBefore" : 0, - "bearerOnly" : false, - "consentRequired" : false, - "standardFlowEnabled" : true, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : false, - "serviceAccountsEnabled" : false, - "publicClient" : true, - "frontchannelLogout" : false, - "protocol" : "openid-connect", - "attributes" : { - "post.logout.redirect.uris" : "+", - "pkce.code.challenge.method" : "S256" - }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : false, - "nodeReRegistrationTimeout" : 0, - "protocolMappers" : [ { - "id" : "84f0fe2c-8381-4cd1-afa7-508c5cd6c83c", - "name" : "audience resolve", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-audience-resolve-mapper", - "consentRequired" : false, - "config" : { } - } ], - "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] - }, { - "id" : "d2a180a9-6ed6-42fd-a476-2ba0948cae8f", - "clientId" : "admin-cli", - "name" : "${client_admin-cli}", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "redirectUris" : [ ], - "webOrigins" : [ ], - "notBefore" : 0, - "bearerOnly" : false, - "consentRequired" : false, - "standardFlowEnabled" : false, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : true, - "serviceAccountsEnabled" : false, - "publicClient" : true, - "frontchannelLogout" : false, - "protocol" : "openid-connect", - "attributes" : { }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : false, - "nodeReRegistrationTimeout" : 0, - "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] - }, { - "id" : "3172d7e0-ac9f-4728-ba8c-e1d35c6e14a4", - "clientId" : "baeldung-confidential", - "name" : "", - "description" : "", - "rootUrl" : "", - "adminUrl" : "", - "baseUrl" : "", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "secret" : "secret", - "redirectUris" : ["https://oauth.pstmn.io/v1/callback", "http://localhost:8080/*", "https://localhost:8080/*", "http://localhost:8081/*", "https://localhost:8081/*", "http://localhost:8082/*", "https://localhost:8082/*" ], - "webOrigins" : [ "+" ], - "notBefore" : 0, - "bearerOnly" : false, - "consentRequired" : false, - "standardFlowEnabled" : true, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : false, - "serviceAccountsEnabled" : false, - "publicClient" : false, - "frontchannelLogout" : true, - "protocol" : "openid-connect", - "attributes" : { - "oidc.ciba.grant.enabled" : "false", - "client.secret.creation.time" : "1713615347", - "backchannel.logout.session.required" : "true", - "post.logout.redirect.uris" : "+", - "oauth2.device.authorization.grant.enabled" : "false", - "backchannel.logout.revoke.offline.tokens" : "false" - }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : true, - "nodeReRegistrationTimeout" : -1, - "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] - }, { - "id" : "cb2ee74f-fb36-4f21-82bb-4928966ea449", - "clientId" : "broker", - "name" : "${client_broker}", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "redirectUris" : [ ], - "webOrigins" : [ ], - "notBefore" : 0, - "bearerOnly" : true, - "consentRequired" : false, - "standardFlowEnabled" : true, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : false, - "serviceAccountsEnabled" : false, - "publicClient" : false, - "frontchannelLogout" : false, - "protocol" : "openid-connect", - "attributes" : { }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : false, - "nodeReRegistrationTimeout" : 0, - "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] - }, { - "id" : "4720b673-8d8b-4709-b695-88d6c17e8edf", - "clientId" : "realm-management", - "name" : "${client_realm-management}", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "redirectUris" : [ ], - "webOrigins" : [ ], - "notBefore" : 0, - "bearerOnly" : true, - "consentRequired" : false, - "standardFlowEnabled" : true, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : false, - "serviceAccountsEnabled" : false, - "publicClient" : false, - "frontchannelLogout" : false, - "protocol" : "openid-connect", - "attributes" : { }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : false, - "nodeReRegistrationTimeout" : 0, - "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] - }, { - "id" : "8c99b1f8-439f-4c01-ac62-bf4b852a3585", - "clientId" : "security-admin-console", - "name" : "${client_security-admin-console}", - "rootUrl" : "${authAdminUrl}", - "baseUrl" : "/admin/baeldung/console/", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "redirectUris" : [ "/admin/baeldung/console/*" ], - "webOrigins" : [ "+" ], - "notBefore" : 0, - "bearerOnly" : false, - "consentRequired" : false, - "standardFlowEnabled" : true, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : false, - "serviceAccountsEnabled" : false, - "publicClient" : true, - "frontchannelLogout" : false, - "protocol" : "openid-connect", - "attributes" : { - "post.logout.redirect.uris" : "+", - "pkce.code.challenge.method" : "S256" - }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : false, - "nodeReRegistrationTimeout" : 0, - "protocolMappers" : [ { - "id" : "4a39a186-0bc6-46c8-9605-940ab6af0ec4", - "name" : "locale", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "introspection.token.claim" : "true", - "userinfo.token.claim" : "true", - "user.attribute" : "locale", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "locale", - "jsonType.label" : "String" - } - } ], - "defaultClientScopes" : [ "web-origins", "acr", "profile", "roles", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] - } ], - "clientScopes" : [ { - "id" : "98fd7e67-c4fc-4e6a-bb9c-6e27d99bbbb2", - "name" : "phone", - "description" : "OpenID Connect built-in scope: phone", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "true", - "display.on.consent.screen" : "true", - "consent.screen.text" : "${phoneScopeConsentText}" - }, - "protocolMappers" : [ { - "id" : "1cdb5d11-fcc5-48ee-9acc-b8d980b607a5", - "name" : "phone number", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "introspection.token.claim" : "true", - "userinfo.token.claim" : "true", - "user.attribute" : "phoneNumber", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "phone_number", - "jsonType.label" : "String" - } - }, { - "id" : "f3258684-171e-47f9-a9d0-96434e91ee6a", - "name" : "phone number verified", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "introspection.token.claim" : "true", - "userinfo.token.claim" : "true", - "user.attribute" : "phoneNumberVerified", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "phone_number_verified", - "jsonType.label" : "boolean" - } - } ] - }, { - "id" : "20843100-3f9b-4c50-8dc6-86e6d64fbc3d", - "name" : "role_list", - "description" : "SAML role list", - "protocol" : "saml", - "attributes" : { - "consent.screen.text" : "${samlRoleListScopeConsentText}", - "display.on.consent.screen" : "true" - }, - "protocolMappers" : [ { - "id" : "fabf3bec-72b8-4035-84a7-f368417446ef", - "name" : "role list", - "protocol" : "saml", - "protocolMapper" : "saml-role-list-mapper", - "consentRequired" : false, - "config" : { - "single" : "false", - "attribute.nameformat" : "Basic", - "attribute.name" : "Role" - } - } ] - }, { - "id" : "3a0949bd-8a64-44b3-8f21-0b8c41cf44d8", - "name" : "address", - "description" : "OpenID Connect built-in scope: address", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "true", - "display.on.consent.screen" : "true", - "consent.screen.text" : "${addressScopeConsentText}" - }, - "protocolMappers" : [ { - "id" : "38838b81-804d-47d1-9aad-92d5107b1653", - "name" : "address", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-address-mapper", - "consentRequired" : false, - "config" : { - "user.attribute.formatted" : "formatted", - "user.attribute.country" : "country", - "introspection.token.claim" : "true", - "user.attribute.postal_code" : "postal_code", - "userinfo.token.claim" : "true", - "user.attribute.street" : "street", - "id.token.claim" : "true", - "user.attribute.region" : "region", - "access.token.claim" : "true", - "user.attribute.locality" : "locality" - } - } ] - }, { - "id" : "4bc0f7a9-7009-48f4-aeee-198c705d4e90", - "name" : "profile", - "description" : "OpenID Connect built-in scope: profile", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "true", - "display.on.consent.screen" : "true", - "consent.screen.text" : "${profileScopeConsentText}" - }, - "protocolMappers" : [ { - "id" : "ed2fc2c9-d27e-4d2c-b877-4bc817fd54bf", - "name" : "family name", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "introspection.token.claim" : "true", - "userinfo.token.claim" : "true", - "user.attribute" : "lastName", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "family_name", - "jsonType.label" : "String" - } - }, { - "id" : "c1278964-7ee9-4619-a8a4-461ef8fce69b", - "name" : "nickname", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "introspection.token.claim" : "true", - "userinfo.token.claim" : "true", - "user.attribute" : "nickname", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "nickname", - "jsonType.label" : "String" - } - }, { - "id" : "bf7b6bfb-0c2a-4826-8ee2-52cc409534f2", - "name" : "picture", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "introspection.token.claim" : "true", - "userinfo.token.claim" : "true", - "user.attribute" : "picture", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "picture", - "jsonType.label" : "String" - } - }, { - "id" : "85bdea58-50c5-4d63-952d-ab0e1e861244", - "name" : "username", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "introspection.token.claim" : "true", - "userinfo.token.claim" : "true", - "user.attribute" : "username", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "preferred_username", - "jsonType.label" : "String" - } - }, { - "id" : "c945557c-e480-4f09-b9fa-62c05a26cb05", - "name" : "updated at", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "introspection.token.claim" : "true", - "userinfo.token.claim" : "true", - "user.attribute" : "updatedAt", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "updated_at", - "jsonType.label" : "long" - } - }, { - "id" : "184fc94a-c750-4bc0-be3f-0501365bc1fd", - "name" : "full name", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-full-name-mapper", - "consentRequired" : false, - "config" : { - "id.token.claim" : "true", - "introspection.token.claim" : "true", - "access.token.claim" : "true", - "userinfo.token.claim" : "true" - } - }, { - "id" : "40162254-ac26-4b36-a5d5-538d33612c80", - "name" : "zoneinfo", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "introspection.token.claim" : "true", - "userinfo.token.claim" : "true", - "user.attribute" : "zoneinfo", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "zoneinfo", - "jsonType.label" : "String" - } - }, { - "id" : "a85df9ca-5a7f-4035-96a1-bd55dcdbe5be", - "name" : "gender", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "introspection.token.claim" : "true", - "userinfo.token.claim" : "true", - "user.attribute" : "gender", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "gender", - "jsonType.label" : "String" - } - }, { - "id" : "8d02d6e1-89b1-4777-8ce6-5bc6a1fb9f30", - "name" : "middle name", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "introspection.token.claim" : "true", - "userinfo.token.claim" : "true", - "user.attribute" : "middleName", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "middle_name", - "jsonType.label" : "String" - } - }, { - "id" : "bf65a00b-5112-4bd4-b540-de0fa4912c65", - "name" : "website", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "introspection.token.claim" : "true", - "userinfo.token.claim" : "true", - "user.attribute" : "website", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "website", - "jsonType.label" : "String" - } - }, { - "id" : "5eddbe1e-e274-4543-8606-a8fd3d5f793b", - "name" : "locale", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "introspection.token.claim" : "true", - "userinfo.token.claim" : "true", - "user.attribute" : "locale", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "locale", - "jsonType.label" : "String" - } - }, { - "id" : "54300fc6-0c26-42e0-89bb-844955488008", - "name" : "given name", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "introspection.token.claim" : "true", - "userinfo.token.claim" : "true", - "user.attribute" : "firstName", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "given_name", - "jsonType.label" : "String" - } - }, { - "id" : "89ccaf97-a0a8-4221-9174-17a7e475ebc7", - "name" : "birthdate", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "introspection.token.claim" : "true", - "userinfo.token.claim" : "true", - "user.attribute" : "birthdate", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "birthdate", - "jsonType.label" : "String" - } - }, { - "id" : "58e90cb8-25c5-4e81-a5ed-a9de481fab17", - "name" : "profile", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "introspection.token.claim" : "true", - "userinfo.token.claim" : "true", - "user.attribute" : "profile", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "profile", - "jsonType.label" : "String" - } - } ] - }, { - "id" : "2d434173-8b6e-4959-ad8f-c7185bc9b433", - "name" : "email", - "description" : "OpenID Connect built-in scope: email", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "true", - "display.on.consent.screen" : "true", - "consent.screen.text" : "${emailScopeConsentText}" - }, - "protocolMappers" : [ { - "id" : "84dad65d-8413-44c0-95f4-f3d64035e7b6", - "name" : "email verified", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-property-mapper", - "consentRequired" : false, - "config" : { - "introspection.token.claim" : "true", - "userinfo.token.claim" : "true", - "user.attribute" : "emailVerified", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "email_verified", - "jsonType.label" : "boolean" - } - }, { - "id" : "89ac6a7f-9435-41ed-83eb-34a366429a6f", - "name" : "email", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "introspection.token.claim" : "true", - "userinfo.token.claim" : "true", - "user.attribute" : "email", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "email", - "jsonType.label" : "String" - } - } ] - }, { - "id" : "51307312-9b48-4ae9-ad92-7cbc0ff4c6c3", - "name" : "web-origins", - "description" : "OpenID Connect scope for add allowed web origins to the access token", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "false", - "display.on.consent.screen" : "false", - "consent.screen.text" : "" - }, - "protocolMappers" : [ { - "id" : "6f6d1690-df96-4774-ae4a-2d349461f02a", - "name" : "allowed web origins", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-allowed-origins-mapper", - "consentRequired" : false, - "config" : { - "introspection.token.claim" : "true", - "access.token.claim" : "true" - } - } ] - }, { - "id" : "3bec9041-170c-4c6d-a35e-be7a51442aef", - "name" : "microprofile-jwt", - "description" : "Microprofile - JWT built-in scope", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "true", - "display.on.consent.screen" : "false" - }, - "protocolMappers" : [ { - "id" : "52e647ff-3bb4-47ee-b67d-0cd24bb66c5b", - "name" : "groups", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-realm-role-mapper", - "consentRequired" : false, - "config" : { - "introspection.token.claim" : "true", - "multivalued" : "true", - "user.attribute" : "foo", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "groups", - "jsonType.label" : "String" - } - }, { - "id" : "027afd1d-3d34-49df-bf43-00adddfec15a", - "name" : "upn", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "introspection.token.claim" : "true", - "userinfo.token.claim" : "true", - "user.attribute" : "username", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "upn", - "jsonType.label" : "String" - } - } ] - }, { - "id" : "159dc3dc-a659-4cb8-9271-809834a42d8e", - "name" : "acr", - "description" : "OpenID Connect scope for add acr (authentication context class reference) to the token", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "false", - "display.on.consent.screen" : "false" - }, - "protocolMappers" : [ { - "id" : "5dbfb5d7-c181-4e47-85e8-13ad0610c43b", - "name" : "acr loa level", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-acr-mapper", - "consentRequired" : false, - "config" : { - "id.token.claim" : "true", - "introspection.token.claim" : "true", - "access.token.claim" : "true" - } - } ] - }, { - "id" : "46c52714-3bb6-4db9-a360-0839703c1f8e", - "name" : "roles", - "description" : "OpenID Connect scope for add user roles to the access token", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "false", - "display.on.consent.screen" : "true", - "consent.screen.text" : "${rolesScopeConsentText}" - }, - "protocolMappers" : [ { - "id" : "0b274bf6-89f0-4d3c-a635-eb3943d062ee", - "name" : "realm roles", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-realm-role-mapper", - "consentRequired" : false, - "config" : { - "introspection.token.claim" : "true", - "multivalued" : "true", - "user.attribute" : "foo", - "access.token.claim" : "true", - "claim.name" : "realm_access.roles", - "jsonType.label" : "String" - } - }, { - "id" : "e70cd96f-6d15-4c46-978a-359f1832b7c2", - "name" : "audience resolve", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-audience-resolve-mapper", - "consentRequired" : false, - "config" : { - "introspection.token.claim" : "true", - "access.token.claim" : "true" - } - }, { - "id" : "6a19a6ab-4035-4c43-b9e5-253339bb491b", - "name" : "client roles", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-client-role-mapper", - "consentRequired" : false, - "config" : { - "introspection.token.claim" : "true", - "multivalued" : "true", - "user.attribute" : "foo", - "access.token.claim" : "true", - "claim.name" : "resource_access.${client_id}.roles", - "jsonType.label" : "String" - } - } ] - }, { - "id" : "4d1dfa4a-c1cc-45ad-ade5-7ac2fabfc5d3", - "name" : "offline_access", - "description" : "OpenID Connect built-in scope: offline_access", - "protocol" : "openid-connect", - "attributes" : { - "consent.screen.text" : "${offlineAccessScopeConsentText}", - "display.on.consent.screen" : "true" - } - } ], - "defaultDefaultClientScopes" : [ "role_list", "profile", "email", "roles", "web-origins", "acr" ], - "defaultOptionalClientScopes" : [ "offline_access", "address", "phone", "microprofile-jwt" ], - "browserSecurityHeaders" : { - "contentSecurityPolicyReportOnly" : "", - "xContentTypeOptions" : "nosniff", - "referrerPolicy" : "no-referrer", - "xRobotsTag" : "none", - "xFrameOptions" : "SAMEORIGIN", - "contentSecurityPolicy" : "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", - "xXSSProtection" : "1; mode=block", - "strictTransportSecurity" : "max-age=31536000; includeSubDomains" - }, - "smtpServer" : { }, - "eventsEnabled" : true, - "eventsExpiration" : 900, - "eventsListeners" : [ "jboss-logging" ], - "enabledEventTypes" : [ "SEND_RESET_PASSWORD", "UPDATE_CONSENT_ERROR", "GRANT_CONSENT", "VERIFY_PROFILE_ERROR", "REMOVE_TOTP", "REVOKE_GRANT", "UPDATE_TOTP", "LOGIN_ERROR", "CLIENT_LOGIN", "RESET_PASSWORD_ERROR", "IMPERSONATE_ERROR", "CODE_TO_TOKEN_ERROR", "CUSTOM_REQUIRED_ACTION", "OAUTH2_DEVICE_CODE_TO_TOKEN_ERROR", "RESTART_AUTHENTICATION", "IMPERSONATE", "UPDATE_PROFILE_ERROR", "LOGIN", "OAUTH2_DEVICE_VERIFY_USER_CODE", "UPDATE_PASSWORD_ERROR", "CLIENT_INITIATED_ACCOUNT_LINKING", "OAUTH2_EXTENSION_GRANT", "USER_DISABLED_BY_PERMANENT_LOCKOUT", "TOKEN_EXCHANGE", "AUTHREQID_TO_TOKEN", "LOGOUT", "REGISTER", "DELETE_ACCOUNT_ERROR", "CLIENT_REGISTER", "IDENTITY_PROVIDER_LINK_ACCOUNT", "USER_DISABLED_BY_TEMPORARY_LOCKOUT", "DELETE_ACCOUNT", "UPDATE_PASSWORD", "CLIENT_DELETE", "FEDERATED_IDENTITY_LINK_ERROR", "IDENTITY_PROVIDER_FIRST_LOGIN", "CLIENT_DELETE_ERROR", "VERIFY_EMAIL", "CLIENT_LOGIN_ERROR", "RESTART_AUTHENTICATION_ERROR", "EXECUTE_ACTIONS", "REMOVE_FEDERATED_IDENTITY_ERROR", "TOKEN_EXCHANGE_ERROR", "PERMISSION_TOKEN", "SEND_IDENTITY_PROVIDER_LINK_ERROR", "EXECUTE_ACTION_TOKEN_ERROR", "OAUTH2_EXTENSION_GRANT_ERROR", "SEND_VERIFY_EMAIL", "OAUTH2_DEVICE_AUTH", "EXECUTE_ACTIONS_ERROR", "REMOVE_FEDERATED_IDENTITY", "OAUTH2_DEVICE_CODE_TO_TOKEN", "IDENTITY_PROVIDER_POST_LOGIN", "IDENTITY_PROVIDER_LINK_ACCOUNT_ERROR", "OAUTH2_DEVICE_VERIFY_USER_CODE_ERROR", "UPDATE_EMAIL", "REGISTER_ERROR", "REVOKE_GRANT_ERROR", "EXECUTE_ACTION_TOKEN", "LOGOUT_ERROR", "UPDATE_EMAIL_ERROR", "CLIENT_UPDATE_ERROR", "AUTHREQID_TO_TOKEN_ERROR", "UPDATE_PROFILE", "CLIENT_REGISTER_ERROR", "FEDERATED_IDENTITY_LINK", "SEND_IDENTITY_PROVIDER_LINK", "SEND_VERIFY_EMAIL_ERROR", "RESET_PASSWORD", "CLIENT_INITIATED_ACCOUNT_LINKING_ERROR", "OAUTH2_DEVICE_AUTH_ERROR", "UPDATE_CONSENT", "REMOVE_TOTP_ERROR", "VERIFY_EMAIL_ERROR", "SEND_RESET_PASSWORD_ERROR", "CLIENT_UPDATE", "CUSTOM_REQUIRED_ACTION_ERROR", "IDENTITY_PROVIDER_POST_LOGIN_ERROR", "UPDATE_TOTP_ERROR", "CODE_TO_TOKEN", "VERIFY_PROFILE", "GRANT_CONSENT_ERROR", "IDENTITY_PROVIDER_FIRST_LOGIN_ERROR" ], - "adminEventsEnabled" : true, - "adminEventsDetailsEnabled" : true, - "identityProviders" : [ ], - "identityProviderMappers" : [ ], - "components" : { - "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy" : [ { - "id" : "c07dff7f-77fc-4381-a458-9c56515c5c98", - "name" : "Allowed Client Scopes", - "providerId" : "allowed-client-templates", - "subType" : "anonymous", - "subComponents" : { }, - "config" : { - "allow-default-scopes" : [ "true" ] - } - }, { - "id" : "d9662eb8-e8bb-4ae5-a625-c8c616d8967a", - "name" : "Consent Required", - "providerId" : "consent-required", - "subType" : "anonymous", - "subComponents" : { }, - "config" : { } - }, { - "id" : "03f2b651-fdea-4a7a-88e8-f169f5a7f892", - "name" : "Allowed Protocol Mapper Types", - "providerId" : "allowed-protocol-mappers", - "subType" : "anonymous", - "subComponents" : { }, - "config" : { - "allowed-protocol-mapper-types" : [ "oidc-usermodel-attribute-mapper", "oidc-usermodel-property-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-full-name-mapper", "oidc-address-mapper", "saml-user-attribute-mapper", "saml-user-property-mapper", "saml-role-list-mapper" ] - } - }, { - "id" : "0c7278cb-1e59-407e-9187-fa147ce96f82", - "name" : "Full Scope Disabled", - "providerId" : "scope", - "subType" : "anonymous", - "subComponents" : { }, - "config" : { } - }, { - "id" : "a3c48cf1-67be-41fb-a852-6efe25560fcf", - "name" : "Max Clients Limit", - "providerId" : "max-clients", - "subType" : "anonymous", - "subComponents" : { }, - "config" : { - "max-clients" : [ "200" ] - } - }, { - "id" : "b0f72ad6-c65d-4132-912f-6e5ba9c48466", - "name" : "Trusted Hosts", - "providerId" : "trusted-hosts", - "subType" : "anonymous", - "subComponents" : { }, - "config" : { - "host-sending-registration-request-must-match" : [ "true" ], - "client-uris-must-match" : [ "true" ] - } - }, { - "id" : "717bea7a-bc0a-4d2a-9ea2-cbe670f1833e", - "name" : "Allowed Protocol Mapper Types", - "providerId" : "allowed-protocol-mappers", - "subType" : "authenticated", - "subComponents" : { }, - "config" : { - "allowed-protocol-mapper-types" : [ "oidc-full-name-mapper", "oidc-usermodel-attribute-mapper", "oidc-usermodel-property-mapper", "saml-role-list-mapper", "saml-user-attribute-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-address-mapper", "saml-user-property-mapper" ] - } - }, { - "id" : "b1fa36d7-8ef0-4501-a495-215b90bd0699", - "name" : "Allowed Client Scopes", - "providerId" : "allowed-client-templates", - "subType" : "authenticated", - "subComponents" : { }, - "config" : { - "allow-default-scopes" : [ "true" ] - } - } ], - "org.keycloak.keys.KeyProvider" : [ { - "id" : "04a18d35-45bd-458d-9bc8-939db56e337d", - "name" : "aes-generated", - "providerId" : "aes-generated", - "subComponents" : { }, - "config" : { - "kid" : [ "3eaa2cde-31c2-409e-9e0e-b8f9ecf76704" ], - "secret" : [ "7BdqNadvG1OQs7Z4qJfvaQ" ], - "priority" : [ "100" ] - } - }, { - "id" : "ce00dbf1-1d6d-44da-84c0-1ed88d712801", - "name" : "rsa-generated", - "providerId" : "rsa-generated", - "subComponents" : { }, - "config" : { - "privateKey" : [ "MIIEogIBAAKCAQEAp0WHWge6QpqVZfKr2kg1esRlHsSZfcGX8uu2pyB2NsXPjuaE0HqEN+OMsQsRR/rjbQkpPYG9sGur0nqNXhV/ErHIlMCmV2Hx8RoLWkVvpqrhnKH+0cBwm8dS83ZN0u5Q4xF1i6a/6FdZx0W45UrE/MZzlqB58I/EyaqZ4H6Id8MXp7W2Fuzw+Q2cKc1MxKx6MzhLJZShIXt8PTjueX5rRfYerdPbixq0E1vWA9Xcatt2mn/xIMo8illBk7fSPvzYv7YKsLtg1Cn43fU/mi63oBckb55D1uYzs2SgnzvRUX8eR6ndq/7CvZaGO3e3WN6FbowpE+wAbMZoXjlKRiHtPwIDAQABAoIBAAxcY/swNQB1AfNNsotn6KPQ3ZQffSRA6SSnbJD/Ih08EvGBcXEijKDArQXsRnOmQ6YsFiMYclcWLdVY/xdjyUctYiAz+Fbeww1JGmuqU+ziFdgIVJdVfDzWxvd815VtzQZqpOAUC3x08Ap8yYQQOWxgkewgocI4LZelhseDMjx/TIScOmuUWmFRwQ7HUP93OKV1oWC4lMAC4LTnqCqlnsk2L563+Q7T2jXUpznlJ6UoTSpu1Msllh+AxqkvZXvAwbFeYoDksWVUaY+gHAQkihgWMGIEmiBun9TsP4NUkpQuWXq1OHE6KBldaJPP3OProN2Z/gDgXDmKVVEf718m+YkCgYEA5KoroazEAIAjZ1L+t39DYNhv87eDnz/y2lRboD3InMFtE36rBPBIOTGiK3GKaIXh6b8VPOXXA5By2SnERIMfzdusmdknTREbC9Ca/ix5RyE/MqflGjqhcsEu1vWe/L7LYNrmTeOryR8E3rLSsrfmIFRKC+9ufsWlahttzW3D5ksCgYEAu0SLIqTmLfcwmIEngU044o5OZw7QtHaDJmNEv5n4cKXJHmCa3mK+IIIb7f3YIw4nyRQVKjbppAM1bLKT5RpqvHCxVIwjGbvhJ7l7QlBXmcx6x9n18ZPFdA8exUwm56sgixlrfUIHUMH1TFbGSFqIm5bAJwjFwqz3gXzSVU0rTF0CgYAjrCiCYGFzcooTZG84UTJBuYI9kzOFdIR+awqgRQM28TYDBI/JhXK++W9DN8NP6xMDVDwL9A9HDxHbrxhfV9VuWAblOWtYKoL9pN2JKYcCAb3KOUcUgHEPZfPYtRjIdTtlMMEdBZeXGK+5zkvwdaABCyVCF2g1fr//fafzlFwrYQKBgHtJcvhJ66hTVtDwJpv/xPWSjpdWr5w/cbRyIi6qJV+0JaY0H4FNLLKmNdEHD6Z0iUjeSdjS8hqiaie3oZpxO9f3sSdiYzFr+Z13hWhxEFsWvbaZDkwO5y2zTqTBr9NRXEl3YMbEE6DdMKsjbcLwp4MXSkXohpnV2dSL4sV52omZAoGAFY1w9JGkTwJ0rG/R+Yx3qcRhoHY7YA2PMSYIyB9E5d923L6bi1GRSwhNLO+lW0eWA8ekHiQLnqDmNJl708oJBGUwo/Zr7U9jowsqQIaSE8VgU6dfdhbScMI5vpmSrlQRyV0UveLvCsEAx/Rvl4y+dQneaEoNqEKSd7Hml2tjx7g=" ], - "keyUse" : [ "SIG" ], - "certificate" : [ "MIICnzCCAYcCBgGO+25VozANBgkqhkiG9w0BAQsFADATMREwDwYDVQQDDAhiYWVsZHVuZzAeFw0yNDA0MjAxMjEzMTVaFw0zNDA0MjAxMjE0NTVaMBMxETAPBgNVBAMMCGJhZWxkdW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp0WHWge6QpqVZfKr2kg1esRlHsSZfcGX8uu2pyB2NsXPjuaE0HqEN+OMsQsRR/rjbQkpPYG9sGur0nqNXhV/ErHIlMCmV2Hx8RoLWkVvpqrhnKH+0cBwm8dS83ZN0u5Q4xF1i6a/6FdZx0W45UrE/MZzlqB58I/EyaqZ4H6Id8MXp7W2Fuzw+Q2cKc1MxKx6MzhLJZShIXt8PTjueX5rRfYerdPbixq0E1vWA9Xcatt2mn/xIMo8illBk7fSPvzYv7YKsLtg1Cn43fU/mi63oBckb55D1uYzs2SgnzvRUX8eR6ndq/7CvZaGO3e3WN6FbowpE+wAbMZoXjlKRiHtPwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQB091NLrtrT+JSmLfyv+LvFIPIaOu07kWHbueqjKbOinQ2ouBfMnOA9Ojm/17w8CIt/h6VIBzoi3H9Huq15dnGoiIcQIzvAiq8XSewnVfnyvFeq830LVAiTEEDRQLqKVT1PiRZEj64XGyRM3lX0Xp+CXG8z3Qc4OVFrHdb/nUIbfDAmxsWRymTm5p2E5GTJPlr/gON/AHPAHIzmgk5HD9PqBPpMQRHN9/y8vkeIPh9gEj8oUYsM6MPEKrbQIDBqnr8UaxPaMtJF+cjg36VB0SJ9c1w0DBWeND/UNFq47aNWMSND5O9qX0eJxVTqxFAFia0V2WUZk17Pd6pzLKkZQb94" ], - "priority" : [ "100" ] - } - }, { - "id" : "fa8ee6a3-d95e-4ec9-856a-0962208b6bcc", - "name" : "rsa-enc-generated", - "providerId" : "rsa-enc-generated", - "subComponents" : { }, - "config" : { - "privateKey" : [ "MIIEowIBAAKCAQEAsZNPlXoVvt4RsbkFu3giJB3W3qDxEGsAIvOQqLFKP4o1oFJY4L4K5ljUbGABMiq0fQEVTj1mAZAwqJ/J+mnv5OhkUfTDpAt0LactZRPqz7RyfRwmSTL3r/kCtFZn5WQZA//Z6q3zdm7ARxH3Dq9+cMARIe1k7dblWlX+8A5Qk8Ka9Ie6SfwqlTsv4EMTmIhUjj/UyEAWLhSLrk/gA3PQyw/OUEWJTM946AWmPcMtWJRFDbMsj00G1sgrmRuIa0zmXpLj+Zr1Kby9GBU/x60EKtONtXiX8IvIKFm8mKI40q8va6jI71wqUB7OtDZ1a+iF1h8TJ+X5Q2ARPo0li3iEUQIDAQABAoIBADhe57ovZdzP+TT+Y9P12Hy3nkDRPYV1OjdeM5NhqIzQLqLk0UMTATnLhC+dMHQA+4fdQqqyMgIYCGJXS1J7s8Rqg4JC3aJjYm+lrPLz5iwmf9u4hmzhSaCqv1GJRnUbGBfdbguiSfHUSaSmDtQyIMThK+8lwc8A05EgUIxbNvgYnEOEdavlyCq4HdMiDPSjpdHSdC8NpaQkAVULB3QXofm5SQm4ioED/trVjHyjl80i9ysDKSPPzqpye4lFCqmclni1U78V2w4E/uVOG8+MczZkS4otPG99QoELGuqLaVmq9rAx624owUAY3r7ecCL2lSHyjzJwBkrBFLenlSI4A6sCgYEA7tPcbOYPt2a7ih1nase6aC5rwTk62lpe9cuNpVCRmKKlX9glLLcFjNz+75LSyj4TXvg52vcZv3JmsULUeE30rPVr9hgIeuEnsPCc4HLJ40aVaEyhVVwg5ofy3++/8Ys0PR2blZ674/jFgxbB537t81QxQd5WtD9Zh+w7Tiiw40sCgYEAvlf4qvjKW6kaOpmIe4S7wWY9/FhbgHq3sKLltfzOGY0GTWGFZtJ7uzgDvOkEVAIyopEDKfkBL3Sok5ic8MpQOARCa1HXjm8+dtQ1SkNxDsGC//DpouHefkvwUNeKYPV2n4CckirUMmvSqWz4oWAA5u0C2eg0pwvlavMpRKN1mVMCgYB7Klt09biJNrvk4IEi+lnRvI7pmSAW16A9Vnp4FPLhKo/qu8eAJesA2D/JQYjfr9/BjHYZzHFE4DTBmduFJ37Va8P/qClHZbJYd94PimM/iHkozsws/1QgT2AbyMLOSKHqGsjQAoqXaQZDMotRXY5NfM/iTk2cq0b66AM1rZp7vQKBgQCpBc1XZV2sT1lvN+8uYAuqDXR1pLB8QnzjaYO6Oyd5IPW7uSGQ0M/2zCLlmbWyM9Fq8oJwvyECVwFrL1YNrFnXpFCmpCJZ5Qb+1ioMLB81DzmYtQGDFjdQx3Y7E2tZ9h7EPJzMXyPXMk/7Cz0tb+bdKRIjFkPLIpEyi4LV5KEE6QKBgF7Hs1jnR+/3wVK2NG+Ek5bOwOn7wNtwpfhHpj+Auwk7B9mzoor01L6UTw+LDMtQoohfqOJhM1xZcn2MJdhZhkWvSpavEyuY886A8RVtL44rh/kCHy/M4d9AQoiSz5mIYOdiiskbepG+jaIoweUvWxLmcWLWgV3H8syyqJR/vf30" ], - "keyUse" : [ "ENC" ], - "certificate" : [ "MIICnzCCAYcCBgGO+25WEDANBgkqhkiG9w0BAQsFADATMREwDwYDVQQDDAhiYWVsZHVuZzAeFw0yNDA0MjAxMjEzMTZaFw0zNDA0MjAxMjE0NTZaMBMxETAPBgNVBAMMCGJhZWxkdW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsZNPlXoVvt4RsbkFu3giJB3W3qDxEGsAIvOQqLFKP4o1oFJY4L4K5ljUbGABMiq0fQEVTj1mAZAwqJ/J+mnv5OhkUfTDpAt0LactZRPqz7RyfRwmSTL3r/kCtFZn5WQZA//Z6q3zdm7ARxH3Dq9+cMARIe1k7dblWlX+8A5Qk8Ka9Ie6SfwqlTsv4EMTmIhUjj/UyEAWLhSLrk/gA3PQyw/OUEWJTM946AWmPcMtWJRFDbMsj00G1sgrmRuIa0zmXpLj+Zr1Kby9GBU/x60EKtONtXiX8IvIKFm8mKI40q8va6jI71wqUB7OtDZ1a+iF1h8TJ+X5Q2ARPo0li3iEUQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQCT9Jua67qgsClibdgvEfX3BKLl+JXVbFjyYKfBhP85DIk/tzfeYi1UZilWGPWlnprhp5GnwZXPeqVsLCNM+ypdYN8RGBs6K48wVQoetf92GPh9eCQMq2FSAVKShsgkolKifyuZo8oQu6Na92V5EsjUV7hEB4G3jXOisrO/MjN+Ja9eRXru1L2n7bOrKtYRlYeNI8CZvc63jRPkq1fRutcmpqMRPDjMYuM9wUvkZwewqo8WSf51DDKBah5W83XLbTp5jX0bH1NZc3BNHnNerR3iMGPSa6rcKPsC3lL1mZluNVhQExyli1S1f7QmUc1BYxr3zi2uVCKkci5gRenDywws" ], - "priority" : [ "100" ], - "algorithm" : [ "RSA-OAEP" ] - } - }, { - "id" : "0866f9d1-3c22-432c-95d4-65378e739b89", - "name" : "hmac-generated-hs512", - "providerId" : "hmac-generated", - "subComponents" : { }, - "config" : { - "kid" : [ "749eb77a-a3d7-45b2-bc40-3bf80faf2fc7" ], - "secret" : [ "YmaVXh3blZqVaqpgeLyGI5JUzV8Vc41XFb7RcUaChNmAN-f61pqz7nE6edgQj_NS-TVVsvlq9qouKcd-5_oGugmvCXZ-Dp5gzcKe4EA-voOEV4pvJ7VXRWuH6QBDCaXyDiknEVtIx20ycjC4F8Ch10_n8so87mwMuVA6zD8Y-oM" ], - "priority" : [ "100" ], - "algorithm" : [ "HS512" ] - } - } ] - }, - "internationalizationEnabled" : false, - "supportedLocales" : [ ], - "authenticationFlows" : [ { - "id" : "92fc572a-6443-4d62-989d-dc6147aed6a6", - "alias" : "Account verification options", - "description" : "Method with which to verity the existing account", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "idp-email-verification", - "authenticatorFlow" : false, - "requirement" : "ALTERNATIVE", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticatorFlow" : true, - "requirement" : "ALTERNATIVE", - "priority" : 20, - "autheticatorFlow" : true, - "flowAlias" : "Verify Existing Account by Re-authentication", - "userSetupAllowed" : false - } ] - }, { - "id" : "17dce980-92a5-4dab-84b6-29f0ffe91e2f", - "alias" : "Browser - Conditional OTP", - "description" : "Flow to determine if the OTP is required for the authentication", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "conditional-user-configured", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "auth-otp-form", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 20, - "autheticatorFlow" : false, - "userSetupAllowed" : false - } ] - }, { - "id" : "9fdb023c-7959-4e7c-b745-d0bcfc6e1f87", - "alias" : "Direct Grant - Conditional OTP", - "description" : "Flow to determine if the OTP is required for the authentication", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "conditional-user-configured", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "direct-grant-validate-otp", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 20, - "autheticatorFlow" : false, - "userSetupAllowed" : false - } ] - }, { - "id" : "336dbe24-c5ec-44c0-bf56-1b811b451fdf", - "alias" : "First broker login - Conditional OTP", - "description" : "Flow to determine if the OTP is required for the authentication", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "conditional-user-configured", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "auth-otp-form", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 20, - "autheticatorFlow" : false, - "userSetupAllowed" : false - } ] - }, { - "id" : "3a87da1e-2fdf-4d15-8c93-8e8d69fc2774", - "alias" : "Handle Existing Account", - "description" : "Handle what to do if there is existing account with same email/username like authenticated identity provider", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "idp-confirm-link", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticatorFlow" : true, - "requirement" : "REQUIRED", - "priority" : 20, - "autheticatorFlow" : true, - "flowAlias" : "Account verification options", - "userSetupAllowed" : false - } ] - }, { - "id" : "77bd3109-c34e-4165-b9f7-cb6d19aa7fe3", - "alias" : "Reset - Conditional OTP", - "description" : "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "conditional-user-configured", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "reset-otp", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 20, - "autheticatorFlow" : false, - "userSetupAllowed" : false - } ] - }, { - "id" : "ee4b2165-c1be-43ca-96c8-b2302d78b38a", - "alias" : "User creation or linking", - "description" : "Flow for the existing/non-existing user alternatives", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticatorConfig" : "create unique user config", - "authenticator" : "idp-create-user-if-unique", - "authenticatorFlow" : false, - "requirement" : "ALTERNATIVE", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticatorFlow" : true, - "requirement" : "ALTERNATIVE", - "priority" : 20, - "autheticatorFlow" : true, - "flowAlias" : "Handle Existing Account", - "userSetupAllowed" : false - } ] - }, { - "id" : "0116eec2-8a17-4de9-b75f-caa26e52bdf0", - "alias" : "Verify Existing Account by Re-authentication", - "description" : "Reauthentication of existing account", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "idp-username-password-form", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticatorFlow" : true, - "requirement" : "CONDITIONAL", - "priority" : 20, - "autheticatorFlow" : true, - "flowAlias" : "First broker login - Conditional OTP", - "userSetupAllowed" : false - } ] - }, { - "id" : "de8794bd-3ad0-42e9-861f-85fcb6cb1db6", - "alias" : "browser", - "description" : "browser based authentication", - "providerId" : "basic-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "auth-cookie", - "authenticatorFlow" : false, - "requirement" : "ALTERNATIVE", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "auth-spnego", - "authenticatorFlow" : false, - "requirement" : "DISABLED", - "priority" : 20, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "identity-provider-redirector", - "authenticatorFlow" : false, - "requirement" : "ALTERNATIVE", - "priority" : 25, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticatorFlow" : true, - "requirement" : "ALTERNATIVE", - "priority" : 30, - "autheticatorFlow" : true, - "flowAlias" : "forms", - "userSetupAllowed" : false - } ] - }, { - "id" : "9f6aa9f1-134b-4efe-84c4-ba9b7f4e8368", - "alias" : "clients", - "description" : "Base authentication for clients", - "providerId" : "client-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "client-secret", - "authenticatorFlow" : false, - "requirement" : "ALTERNATIVE", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "client-jwt", - "authenticatorFlow" : false, - "requirement" : "ALTERNATIVE", - "priority" : 20, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "client-secret-jwt", - "authenticatorFlow" : false, - "requirement" : "ALTERNATIVE", - "priority" : 30, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "client-x509", - "authenticatorFlow" : false, - "requirement" : "ALTERNATIVE", - "priority" : 40, - "autheticatorFlow" : false, - "userSetupAllowed" : false - } ] - }, { - "id" : "692ddf3c-2813-46ef-b364-fcba9d70f5a4", - "alias" : "direct grant", - "description" : "OpenID Connect Resource Owner Grant", - "providerId" : "basic-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "direct-grant-validate-username", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "direct-grant-validate-password", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 20, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticatorFlow" : true, - "requirement" : "CONDITIONAL", - "priority" : 30, - "autheticatorFlow" : true, - "flowAlias" : "Direct Grant - Conditional OTP", - "userSetupAllowed" : false - } ] - }, { - "id" : "257e18b2-be1c-4ab2-8dd7-68a83817ca8a", - "alias" : "docker auth", - "description" : "Used by Docker clients to authenticate against the IDP", - "providerId" : "basic-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "docker-http-basic-authenticator", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - } ] - }, { - "id" : "fe879ee4-eec5-4034-9b78-82636f614123", - "alias" : "first broker login", - "description" : "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", - "providerId" : "basic-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticatorConfig" : "review profile config", - "authenticator" : "idp-review-profile", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticatorFlow" : true, - "requirement" : "REQUIRED", - "priority" : 20, - "autheticatorFlow" : true, - "flowAlias" : "User creation or linking", - "userSetupAllowed" : false - } ] - }, { - "id" : "2e6f09af-a3f6-415a-8d38-dfc1708e82ff", - "alias" : "forms", - "description" : "Username, password, otp and other auth forms.", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "auth-username-password-form", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticatorFlow" : true, - "requirement" : "CONDITIONAL", - "priority" : 20, - "autheticatorFlow" : true, - "flowAlias" : "Browser - Conditional OTP", - "userSetupAllowed" : false - } ] - }, { - "id" : "cac2a81c-7933-4e1c-a91b-1a5e4d8ba873", - "alias" : "registration", - "description" : "registration flow", - "providerId" : "basic-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "registration-page-form", - "authenticatorFlow" : true, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : true, - "flowAlias" : "registration form", - "userSetupAllowed" : false - } ] - }, { - "id" : "76b893b1-6b16-4e7c-a945-b86b63c983fb", - "alias" : "registration form", - "description" : "registration form", - "providerId" : "form-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "registration-user-creation", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 20, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "registration-password-action", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 50, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "registration-recaptcha-action", - "authenticatorFlow" : false, - "requirement" : "DISABLED", - "priority" : 60, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "registration-terms-and-conditions", - "authenticatorFlow" : false, - "requirement" : "DISABLED", - "priority" : 70, - "autheticatorFlow" : false, - "userSetupAllowed" : false - } ] - }, { - "id" : "8c1ba21b-218d-406d-a936-c935f41e7bef", - "alias" : "reset credentials", - "description" : "Reset credentials for a user if they forgot their password or something", - "providerId" : "basic-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "reset-credentials-choose-user", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "reset-credential-email", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 20, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticator" : "reset-password", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 30, - "autheticatorFlow" : false, - "userSetupAllowed" : false - }, { - "authenticatorFlow" : true, - "requirement" : "CONDITIONAL", - "priority" : 40, - "autheticatorFlow" : true, - "flowAlias" : "Reset - Conditional OTP", - "userSetupAllowed" : false - } ] - }, { - "id" : "6df47204-9532-4b3e-821f-9a5255b9c305", - "alias" : "saml ecp", - "description" : "SAML ECP Profile Authentication Flow", - "providerId" : "basic-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "http-basic-authenticator", - "authenticatorFlow" : false, - "requirement" : "REQUIRED", - "priority" : 10, - "autheticatorFlow" : false, - "userSetupAllowed" : false - } ] - } ], - "authenticatorConfig" : [ { - "id" : "793b40f2-0912-40f4-b570-a75015fb9eb0", - "alias" : "create unique user config", - "config" : { - "require.password.update.after.registration" : "false" - } - }, { - "id" : "3ff115f7-7108-4b17-8868-1d390ec3a480", - "alias" : "review profile config", - "config" : { - "update.profile.on.first.login" : "missing" - } - } ], - "requiredActions" : [ { - "alias" : "CONFIGURE_TOTP", - "name" : "Configure OTP", - "providerId" : "CONFIGURE_TOTP", - "enabled" : true, - "defaultAction" : false, - "priority" : 10, - "config" : { } - }, { - "alias" : "TERMS_AND_CONDITIONS", - "name" : "Terms and Conditions", - "providerId" : "TERMS_AND_CONDITIONS", - "enabled" : false, - "defaultAction" : false, - "priority" : 20, - "config" : { } - }, { - "alias" : "UPDATE_PASSWORD", - "name" : "Update Password", - "providerId" : "UPDATE_PASSWORD", - "enabled" : true, - "defaultAction" : false, - "priority" : 30, - "config" : { } - }, { - "alias" : "UPDATE_PROFILE", - "name" : "Update Profile", - "providerId" : "UPDATE_PROFILE", - "enabled" : true, - "defaultAction" : false, - "priority" : 40, - "config" : { } - }, { - "alias" : "VERIFY_EMAIL", - "name" : "Verify Email", - "providerId" : "VERIFY_EMAIL", - "enabled" : true, - "defaultAction" : false, - "priority" : 50, - "config" : { } - }, { - "alias" : "delete_account", - "name" : "Delete Account", - "providerId" : "delete_account", - "enabled" : false, - "defaultAction" : false, - "priority" : 60, - "config" : { } - }, { - "alias" : "webauthn-register", - "name" : "Webauthn Register", - "providerId" : "webauthn-register", - "enabled" : true, - "defaultAction" : false, - "priority" : 70, - "config" : { } - }, { - "alias" : "webauthn-register-passwordless", - "name" : "Webauthn Register Passwordless", - "providerId" : "webauthn-register-passwordless", - "enabled" : true, - "defaultAction" : false, - "priority" : 80, - "config" : { } - }, { - "alias" : "VERIFY_PROFILE", - "name" : "Verify Profile", - "providerId" : "VERIFY_PROFILE", - "enabled" : true, - "defaultAction" : false, - "priority" : 90, - "config" : { } - }, { - "alias" : "update_user_locale", - "name" : "Update User Locale", - "providerId" : "update_user_locale", - "enabled" : true, - "defaultAction" : false, - "priority" : 1000, - "config" : { } - } ], - "browserFlow" : "browser", - "registrationFlow" : "registration", - "directGrantFlow" : "direct grant", - "resetCredentialsFlow" : "reset credentials", - "clientAuthenticationFlow" : "clients", - "dockerAuthenticationFlow" : "docker auth", - "firstBrokerLoginFlow" : "first broker login", - "attributes" : { - "cibaBackchannelTokenDeliveryMode" : "poll", - "cibaAuthRequestedUserHint" : "login_hint", - "oauth2DevicePollingInterval" : "5", - "clientOfflineSessionMaxLifespan" : "0", - "clientSessionIdleTimeout" : "0", - "clientOfflineSessionIdleTimeout" : "0", - "cibaInterval" : "5", - "realmReusableOtpCode" : "false", - "cibaExpiresIn" : "120", - "oauth2DeviceCodeLifespan" : "600", - "parRequestUriLifespan" : "60", - "clientSessionMaxLifespan" : "0", - "adminEventsExpiration" : "900" - }, - "keycloakVersion" : "24.0.0", - "userManagedAccessAllowed" : false, - "clientProfiles" : { - "profiles" : [ ] - }, - "clientPolicies" : { - "policies" : [ ] - } + "id": "7a046c8d-77b1-4851-b4a9-e3a25a17e431", + "realm": "baeldung", + "notBefore": 0, + "defaultSignatureAlgorithm": "RS256", + "revokeRefreshToken": false, + "refreshTokenMaxReuse": 0, + "accessTokenLifespan": 300, + "accessTokenLifespanForImplicitFlow": 900, + "ssoSessionIdleTimeout": 1800, + "ssoSessionMaxLifespan": 36000, + "ssoSessionIdleTimeoutRememberMe": 0, + "ssoSessionMaxLifespanRememberMe": 0, + "offlineSessionIdleTimeout": 2592000, + "offlineSessionMaxLifespanEnabled": false, + "offlineSessionMaxLifespan": 5184000, + "clientSessionIdleTimeout": 0, + "clientSessionMaxLifespan": 0, + "clientOfflineSessionIdleTimeout": 0, + "clientOfflineSessionMaxLifespan": 0, + "accessCodeLifespan": 60, + "accessCodeLifespanUserAction": 300, + "accessCodeLifespanLogin": 1800, + "actionTokenGeneratedByAdminLifespan": 43200, + "actionTokenGeneratedByUserLifespan": 300, + "oauth2DeviceCodeLifespan": 600, + "oauth2DevicePollingInterval": 5, + "enabled": true, + "sslRequired": "external", + "registrationAllowed": false, + "registrationEmailAsUsername": false, + "rememberMe": false, + "verifyEmail": false, + "loginWithEmailAllowed": true, + "duplicateEmailsAllowed": false, + "resetPasswordAllowed": false, + "editUsernameAllowed": false, + "bruteForceProtected": false, + "permanentLockout": false, + "maxTemporaryLockouts": 0, + "maxFailureWaitSeconds": 900, + "minimumQuickLoginWaitSeconds": 60, + "waitIncrementSeconds": 60, + "quickLoginCheckMilliSeconds": 1000, + "maxDeltaTimeSeconds": 43200, + "failureFactor": 30, + "roles": { + "realm": [ + { + "id": "4ad869c1-56f3-45fd-b345-f107f2834de1", + "name": "AUTHORIZED_PERSONNEL", + "description": "", + "composite": false, + "clientRole": false, + "containerId": "7a046c8d-77b1-4851-b4a9-e3a25a17e431", + "attributes": {} + }, + { + "id": "bfdf00fe-5111-404b-858c-50dcb8a63e61", + "name": "default-roles-baeldung", + "description": "${role_default-roles}", + "composite": true, + "composites": { + "realm": [ + "offline_access", + "uma_authorization" + ], + "client": { + "account": [ + "view-profile", + "manage-account" + ] + } + }, + "clientRole": false, + "containerId": "7a046c8d-77b1-4851-b4a9-e3a25a17e431", + "attributes": {} + }, + { + "id": "96fbbf77-c81e-472b-bb2e-184713dfffde", + "name": "uma_authorization", + "description": "${role_uma_authorization}", + "composite": false, + "clientRole": false, + "containerId": "7a046c8d-77b1-4851-b4a9-e3a25a17e431", + "attributes": {} + }, + { + "id": "cec72467-237c-4ae9-ae1d-ca84ff51b404", + "name": "offline_access", + "description": "${role_offline-access}", + "composite": false, + "clientRole": false, + "containerId": "7a046c8d-77b1-4851-b4a9-e3a25a17e431", + "attributes": {} + } + ], + "client": { + "realm-management": [ + { + "id": "955d707a-3baa-4462-a53c-83ff73b30a12", + "name": "view-realm", + "description": "${role_view-realm}", + "composite": false, + "clientRole": true, + "containerId": "4720b673-8d8b-4709-b695-88d6c17e8edf", + "attributes": {} + }, + { + "id": "81cbcb10-8e84-431e-8da8-07219be8d93d", + "name": "view-clients", + "description": "${role_view-clients}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "query-clients" + ] + } + }, + "clientRole": true, + "containerId": "4720b673-8d8b-4709-b695-88d6c17e8edf", + "attributes": {} + }, + { + "id": "fa1adc6d-7b86-4dc6-a120-57eee9a4fe93", + "name": "create-client", + "description": "${role_create-client}", + "composite": false, + "clientRole": true, + "containerId": "4720b673-8d8b-4709-b695-88d6c17e8edf", + "attributes": {} + }, + { + "id": "be5a19cb-fa00-486a-abfa-eb0dc86680fb", + "name": "view-users", + "description": "${role_view-users}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "query-users", + "query-groups" + ] + } + }, + "clientRole": true, + "containerId": "4720b673-8d8b-4709-b695-88d6c17e8edf", + "attributes": {} + }, + { + "id": "d76de5c9-10f2-4b68-9850-a16d9b2dd35a", + "name": "manage-identity-providers", + "description": "${role_manage-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "4720b673-8d8b-4709-b695-88d6c17e8edf", + "attributes": {} + }, + { + "id": "6339f747-4f89-4e67-9c77-420524135d96", + "name": "manage-authorization", + "description": "${role_manage-authorization}", + "composite": false, + "clientRole": true, + "containerId": "4720b673-8d8b-4709-b695-88d6c17e8edf", + "attributes": {} + }, + { + "id": "c9d5af42-6742-49cf-bd01-a730f4c3cc2e", + "name": "impersonation", + "description": "${role_impersonation}", + "composite": false, + "clientRole": true, + "containerId": "4720b673-8d8b-4709-b695-88d6c17e8edf", + "attributes": {} + }, + { + "id": "56dccfed-9379-4cfb-a720-b9b9e1745048", + "name": "view-identity-providers", + "description": "${role_view-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "4720b673-8d8b-4709-b695-88d6c17e8edf", + "attributes": {} + }, + { + "id": "e10c568f-c50f-4ee4-88cf-43f0c4a1dc2c", + "name": "manage-realm", + "description": "${role_manage-realm}", + "composite": false, + "clientRole": true, + "containerId": "4720b673-8d8b-4709-b695-88d6c17e8edf", + "attributes": {} + }, + { + "id": "d12dcfc2-b649-4c11-ac55-41d6ab10f5c6", + "name": "query-users", + "description": "${role_query-users}", + "composite": false, + "clientRole": true, + "containerId": "4720b673-8d8b-4709-b695-88d6c17e8edf", + "attributes": {} + }, + { + "id": "57977d45-f810-400a-81ca-63a9bdddd3b9", + "name": "query-realms", + "description": "${role_query-realms}", + "composite": false, + "clientRole": true, + "containerId": "4720b673-8d8b-4709-b695-88d6c17e8edf", + "attributes": {} + }, + { + "id": "e14dfabc-3f03-42cf-a716-5261b7002914", + "name": "query-groups", + "description": "${role_query-groups}", + "composite": false, + "clientRole": true, + "containerId": "4720b673-8d8b-4709-b695-88d6c17e8edf", + "attributes": {} + }, + { + "id": "800d272c-1327-485c-9d2f-576f3d9a0178", + "name": "view-authorization", + "description": "${role_view-authorization}", + "composite": false, + "clientRole": true, + "containerId": "4720b673-8d8b-4709-b695-88d6c17e8edf", + "attributes": {} + }, + { + "id": "fdc10176-42c0-4b58-968a-35bfd5dbce20", + "name": "view-events", + "description": "${role_view-events}", + "composite": false, + "clientRole": true, + "containerId": "4720b673-8d8b-4709-b695-88d6c17e8edf", + "attributes": {} + }, + { + "id": "23393ccd-3b70-4de8-9e00-0adbb11851ce", + "name": "manage-users", + "description": "${role_manage-users}", + "composite": false, + "clientRole": true, + "containerId": "4720b673-8d8b-4709-b695-88d6c17e8edf", + "attributes": {} + }, + { + "id": "01a3847f-7602-400d-bedd-7545618559f3", + "name": "manage-clients", + "description": "${role_manage-clients}", + "composite": false, + "clientRole": true, + "containerId": "4720b673-8d8b-4709-b695-88d6c17e8edf", + "attributes": {} + }, + { + "id": "7d8ac9c4-6d1b-4861-a0b9-0479cbd55b14", + "name": "query-clients", + "description": "${role_query-clients}", + "composite": false, + "clientRole": true, + "containerId": "4720b673-8d8b-4709-b695-88d6c17e8edf", + "attributes": {} + }, + { + "id": "788677b0-3fbf-457d-8b62-25f305b86bcf", + "name": "manage-events", + "description": "${role_manage-events}", + "composite": false, + "clientRole": true, + "containerId": "4720b673-8d8b-4709-b695-88d6c17e8edf", + "attributes": {} + }, + { + "id": "642d82d5-1071-47a9-aca9-d0fbd28d0328", + "name": "realm-admin", + "description": "${role_realm-admin}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "view-realm", + "view-clients", + "create-client", + "view-users", + "manage-identity-providers", + "manage-authorization", + "impersonation", + "view-identity-providers", + "manage-realm", + "query-users", + "query-realms", + "view-authorization", + "query-groups", + "view-events", + "manage-users", + "manage-clients", + "query-clients", + "manage-events" + ] + } + }, + "clientRole": true, + "containerId": "4720b673-8d8b-4709-b695-88d6c17e8edf", + "attributes": {} + } + ], + "security-admin-console": [], + "admin-cli": [], + "baeldung-confidential": [], + "account-console": [], + "broker": [ + { + "id": "9043c535-f6d3-44dc-8c48-d3983e04a93b", + "name": "read-token", + "description": "${role_read-token}", + "composite": false, + "clientRole": true, + "containerId": "cb2ee74f-fb36-4f21-82bb-4928966ea449", + "attributes": {} + } + ], + "account": [ + { + "id": "4a188a41-39d9-47e6-b8de-6d9b42c7a414", + "name": "view-profile", + "description": "${role_view-profile}", + "composite": false, + "clientRole": true, + "containerId": "1b64b350-3ef8-4be6-b9ab-c53463b2fd1b", + "attributes": {} + }, + { + "id": "da24f251-0c13-4035-84f1-16c5a3301ea6", + "name": "view-consent", + "description": "${role_view-consent}", + "composite": false, + "clientRole": true, + "containerId": "1b64b350-3ef8-4be6-b9ab-c53463b2fd1b", + "attributes": {} + }, + { + "id": "26edbb7d-dd9f-4dd4-a282-a6e886e38302", + "name": "manage-account-links", + "description": "${role_manage-account-links}", + "composite": false, + "clientRole": true, + "containerId": "1b64b350-3ef8-4be6-b9ab-c53463b2fd1b", + "attributes": {} + }, + { + "id": "b2c98d1e-4a85-4e11-901d-0207e9793acf", + "name": "manage-consent", + "description": "${role_manage-consent}", + "composite": true, + "composites": { + "client": { + "account": [ + "view-consent" + ] + } + }, + "clientRole": true, + "containerId": "1b64b350-3ef8-4be6-b9ab-c53463b2fd1b", + "attributes": {} + }, + { + "id": "f244eb36-cf20-4e96-8233-fee1ee8da72e", + "name": "manage-account", + "description": "${role_manage-account}", + "composite": true, + "composites": { + "client": { + "account": [ + "manage-account-links" + ] + } + }, + "clientRole": true, + "containerId": "1b64b350-3ef8-4be6-b9ab-c53463b2fd1b", + "attributes": {} + }, + { + "id": "a5ca4c2f-d8ad-4c8c-bfd4-1173dd7c1338", + "name": "view-groups", + "description": "${role_view-groups}", + "composite": false, + "clientRole": true, + "containerId": "1b64b350-3ef8-4be6-b9ab-c53463b2fd1b", + "attributes": {} + }, + { + "id": "83f4a43c-07cd-43d5-af99-7825ea603ca9", + "name": "view-applications", + "description": "${role_view-applications}", + "composite": false, + "clientRole": true, + "containerId": "1b64b350-3ef8-4be6-b9ab-c53463b2fd1b", + "attributes": {} + }, + { + "id": "18642f4e-1e2a-4023-9947-7a425d8ed76e", + "name": "delete-account", + "description": "${role_delete-account}", + "composite": false, + "clientRole": true, + "containerId": "1b64b350-3ef8-4be6-b9ab-c53463b2fd1b", + "attributes": {} + } + ] + } + }, + "groups": [], + "defaultRole": { + "id": "bfdf00fe-5111-404b-858c-50dcb8a63e61", + "name": "default-roles-baeldung", + "description": "${role_default-roles}", + "composite": true, + "clientRole": false, + "containerId": "7a046c8d-77b1-4851-b4a9-e3a25a17e431" + }, + "requiredCredentials": [ + "password" + ], + "otpPolicyType": "totp", + "otpPolicyAlgorithm": "HmacSHA1", + "otpPolicyInitialCounter": 0, + "otpPolicyDigits": 6, + "otpPolicyLookAheadWindow": 1, + "otpPolicyPeriod": 30, + "otpPolicyCodeReusable": false, + "otpSupportedApplications": [ + "totpAppFreeOTPName", + "totpAppGoogleName", + "totpAppMicrosoftAuthenticatorName" + ], + "localizationTexts": {}, + "webAuthnPolicyRpEntityName": "keycloak", + "webAuthnPolicySignatureAlgorithms": [ + "ES256" + ], + "webAuthnPolicyRpId": "", + "webAuthnPolicyAttestationConveyancePreference": "not specified", + "webAuthnPolicyAuthenticatorAttachment": "not specified", + "webAuthnPolicyRequireResidentKey": "not specified", + "webAuthnPolicyUserVerificationRequirement": "not specified", + "webAuthnPolicyCreateTimeout": 0, + "webAuthnPolicyAvoidSameAuthenticatorRegister": false, + "webAuthnPolicyAcceptableAaguids": [], + "webAuthnPolicyExtraOrigins": [], + "webAuthnPolicyPasswordlessRpEntityName": "keycloak", + "webAuthnPolicyPasswordlessSignatureAlgorithms": [ + "ES256" + ], + "webAuthnPolicyPasswordlessRpId": "", + "webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified", + "webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified", + "webAuthnPolicyPasswordlessRequireResidentKey": "not specified", + "webAuthnPolicyPasswordlessUserVerificationRequirement": "not specified", + "webAuthnPolicyPasswordlessCreateTimeout": 0, + "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false, + "webAuthnPolicyPasswordlessAcceptableAaguids": [], + "webAuthnPolicyPasswordlessExtraOrigins": [], + "scopeMappings": [ + { + "clientScope": "offline_access", + "roles": [ + "offline_access" + ] + } + ], + "clientScopeMappings": { + "account": [ + { + "client": "account-console", + "roles": [ + "manage-account", + "view-groups" + ] + } + ] + }, + "clients": [ + { + "id": "1b64b350-3ef8-4be6-b9ab-c53463b2fd1b", + "clientId": "account", + "name": "${client_account}", + "rootUrl": "${authBaseUrl}", + "baseUrl": "/realms/baeldung/account/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [ + "/realms/baeldung/account/*" + ], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "post.logout.redirect.uris": "+" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "4beaa749-404c-4a6a-9b04-72df4f9066a4", + "clientId": "account-console", + "name": "${client_account-console}", + "rootUrl": "${authBaseUrl}", + "baseUrl": "/realms/baeldung/account/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [ + "/realms/baeldung/account/*" + ], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "post.logout.redirect.uris": "+", + "pkce.code.challenge.method": "S256" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "84f0fe2c-8381-4cd1-afa7-508c5cd6c83c", + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": false, + "config": {} + } + ], + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "d2a180a9-6ed6-42fd-a476-2ba0948cae8f", + "clientId": "admin-cli", + "name": "${client_admin-cli}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": false, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "3172d7e0-ac9f-4728-ba8c-e1d35c6e14a4", + "clientId": "baeldung-confidential", + "name": "", + "description": "", + "rootUrl": "", + "adminUrl": "", + "baseUrl": "", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "secret", + "redirectUris": [ + "https://oauth.pstmn.io/v1/callback", + "http://localhost:8080/*", + "https://localhost:8080/*", + "http://localhost:8081/*", + "https://localhost:8081/*", + "http://localhost:8082/*", + "https://localhost:8082/*" + ], + "webOrigins": [ + "+" + ], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": true, + "protocol": "openid-connect", + "attributes": { + "oidc.ciba.grant.enabled": "false", + "client.secret.creation.time": "1713615347", + "backchannel.logout.session.required": "true", + "post.logout.redirect.uris": "+", + "oauth2.device.authorization.grant.enabled": "false", + "backchannel.logout.revoke.offline.tokens": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "cb2ee74f-fb36-4f21-82bb-4928966ea449", + "clientId": "broker", + "name": "${client_broker}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": true, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "4720b673-8d8b-4709-b695-88d6c17e8edf", + "clientId": "realm-management", + "name": "${client_realm-management}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": true, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "8c99b1f8-439f-4c01-ac62-bf4b852a3585", + "clientId": "security-admin-console", + "name": "${client_security-admin-console}", + "rootUrl": "${authAdminUrl}", + "baseUrl": "/admin/baeldung/console/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [ + "/admin/baeldung/console/*" + ], + "webOrigins": [ + "+" + ], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "post.logout.redirect.uris": "+", + "pkce.code.challenge.method": "S256" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "4a39a186-0bc6-46c8-9605-940ab6af0ec4", + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + } + ], + "clientScopes": [ + { + "id": "98fd7e67-c4fc-4e6a-bb9c-6e27d99bbbb2", + "name": "phone", + "description": "OpenID Connect built-in scope: phone", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${phoneScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "1cdb5d11-fcc5-48ee-9acc-b8d980b607a5", + "name": "phone number", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "phoneNumber", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number", + "jsonType.label": "String" + } + }, + { + "id": "f3258684-171e-47f9-a9d0-96434e91ee6a", + "name": "phone number verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "phoneNumberVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number_verified", + "jsonType.label": "boolean" + } + } + ] + }, + { + "id": "20843100-3f9b-4c50-8dc6-86e6d64fbc3d", + "name": "role_list", + "description": "SAML role list", + "protocol": "saml", + "attributes": { + "consent.screen.text": "${samlRoleListScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "id": "fabf3bec-72b8-4035-84a7-f368417446ef", + "name": "role list", + "protocol": "saml", + "protocolMapper": "saml-role-list-mapper", + "consentRequired": false, + "config": { + "single": "false", + "attribute.nameformat": "Basic", + "attribute.name": "Role" + } + } + ] + }, + { + "id": "3a0949bd-8a64-44b3-8f21-0b8c41cf44d8", + "name": "address", + "description": "OpenID Connect built-in scope: address", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${addressScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "38838b81-804d-47d1-9aad-92d5107b1653", + "name": "address", + "protocol": "openid-connect", + "protocolMapper": "oidc-address-mapper", + "consentRequired": false, + "config": { + "user.attribute.formatted": "formatted", + "user.attribute.country": "country", + "introspection.token.claim": "true", + "user.attribute.postal_code": "postal_code", + "userinfo.token.claim": "true", + "user.attribute.street": "street", + "id.token.claim": "true", + "user.attribute.region": "region", + "access.token.claim": "true", + "user.attribute.locality": "locality" + } + } + ] + }, + { + "id": "4bc0f7a9-7009-48f4-aeee-198c705d4e90", + "name": "profile", + "description": "OpenID Connect built-in scope: profile", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${profileScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "ed2fc2c9-d27e-4d2c-b877-4bc817fd54bf", + "name": "family name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "lastName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "family_name", + "jsonType.label": "String" + } + }, + { + "id": "c1278964-7ee9-4619-a8a4-461ef8fce69b", + "name": "nickname", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "nickname", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "nickname", + "jsonType.label": "String" + } + }, + { + "id": "bf7b6bfb-0c2a-4826-8ee2-52cc409534f2", + "name": "picture", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "picture", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "picture", + "jsonType.label": "String" + } + }, + { + "id": "85bdea58-50c5-4d63-952d-ab0e1e861244", + "name": "username", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "preferred_username", + "jsonType.label": "String" + } + }, + { + "id": "c945557c-e480-4f09-b9fa-62c05a26cb05", + "name": "updated at", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "updatedAt", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "updated_at", + "jsonType.label": "long" + } + }, + { + "id": "184fc94a-c750-4bc0-be3f-0501365bc1fd", + "name": "full name", + "protocol": "openid-connect", + "protocolMapper": "oidc-full-name-mapper", + "consentRequired": false, + "config": { + "id.token.claim": "true", + "introspection.token.claim": "true", + "access.token.claim": "true", + "userinfo.token.claim": "true" + } + }, + { + "id": "40162254-ac26-4b36-a5d5-538d33612c80", + "name": "zoneinfo", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "zoneinfo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "zoneinfo", + "jsonType.label": "String" + } + }, + { + "id": "a85df9ca-5a7f-4035-96a1-bd55dcdbe5be", + "name": "gender", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "gender", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "gender", + "jsonType.label": "String" + } + }, + { + "id": "8d02d6e1-89b1-4777-8ce6-5bc6a1fb9f30", + "name": "middle name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "middleName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "middle_name", + "jsonType.label": "String" + } + }, + { + "id": "bf65a00b-5112-4bd4-b540-de0fa4912c65", + "name": "website", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "website", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "website", + "jsonType.label": "String" + } + }, + { + "id": "5eddbe1e-e274-4543-8606-a8fd3d5f793b", + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + }, + { + "id": "54300fc6-0c26-42e0-89bb-844955488008", + "name": "given name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "firstName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "given_name", + "jsonType.label": "String" + } + }, + { + "id": "89ccaf97-a0a8-4221-9174-17a7e475ebc7", + "name": "birthdate", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "birthdate", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "birthdate", + "jsonType.label": "String" + } + }, + { + "id": "58e90cb8-25c5-4e81-a5ed-a9de481fab17", + "name": "profile", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "profile", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "profile", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "2d434173-8b6e-4959-ad8f-c7185bc9b433", + "name": "email", + "description": "OpenID Connect built-in scope: email", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${emailScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "84dad65d-8413-44c0-95f4-f3d64035e7b6", + "name": "email verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "emailVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email_verified", + "jsonType.label": "boolean" + } + }, + { + "id": "89ac6a7f-9435-41ed-83eb-34a366429a6f", + "name": "email", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "email", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "51307312-9b48-4ae9-ad92-7cbc0ff4c6c3", + "name": "web-origins", + "description": "OpenID Connect scope for add allowed web origins to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "false", + "consent.screen.text": "" + }, + "protocolMappers": [ + { + "id": "6f6d1690-df96-4774-ae4a-2d349461f02a", + "name": "allowed web origins", + "protocol": "openid-connect", + "protocolMapper": "oidc-allowed-origins-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "access.token.claim": "true" + } + } + ] + }, + { + "id": "3bec9041-170c-4c6d-a35e-be7a51442aef", + "name": "microprofile-jwt", + "description": "Microprofile - JWT built-in scope", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "52e647ff-3bb4-47ee-b67d-0cd24bb66c5b", + "name": "groups", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "multivalued": "true", + "user.attribute": "foo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "groups", + "jsonType.label": "String" + } + }, + { + "id": "027afd1d-3d34-49df-bf43-00adddfec15a", + "name": "upn", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "upn", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "159dc3dc-a659-4cb8-9271-809834a42d8e", + "name": "acr", + "description": "OpenID Connect scope for add acr (authentication context class reference) to the token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "5dbfb5d7-c181-4e47-85e8-13ad0610c43b", + "name": "acr loa level", + "protocol": "openid-connect", + "protocolMapper": "oidc-acr-mapper", + "consentRequired": false, + "config": { + "id.token.claim": "true", + "introspection.token.claim": "true", + "access.token.claim": "true" + } + } + ] + }, + { + "id": "46c52714-3bb6-4db9-a360-0839703c1f8e", + "name": "roles", + "description": "OpenID Connect scope for add user roles to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "true", + "consent.screen.text": "${rolesScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "0b274bf6-89f0-4d3c-a635-eb3943d062ee", + "name": "realm roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "multivalued": "true", + "user.attribute": "foo", + "access.token.claim": "true", + "claim.name": "realm_access.roles", + "jsonType.label": "String" + } + }, + { + "id": "e70cd96f-6d15-4c46-978a-359f1832b7c2", + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "access.token.claim": "true" + } + }, + { + "id": "6a19a6ab-4035-4c43-b9e5-253339bb491b", + "name": "client roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-client-role-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "multivalued": "true", + "user.attribute": "foo", + "access.token.claim": "true", + "claim.name": "resource_access.${client_id}.roles", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "4d1dfa4a-c1cc-45ad-ade5-7ac2fabfc5d3", + "name": "offline_access", + "description": "OpenID Connect built-in scope: offline_access", + "protocol": "openid-connect", + "attributes": { + "consent.screen.text": "${offlineAccessScopeConsentText}", + "display.on.consent.screen": "true" + } + } + ], + "defaultDefaultClientScopes": [ + "role_list", + "profile", + "email", + "roles", + "web-origins", + "acr" + ], + "defaultOptionalClientScopes": [ + "offline_access", + "address", + "phone", + "microprofile-jwt" + ], + "browserSecurityHeaders": { + "contentSecurityPolicyReportOnly": "", + "xContentTypeOptions": "nosniff", + "referrerPolicy": "no-referrer", + "xRobotsTag": "none", + "xFrameOptions": "SAMEORIGIN", + "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "xXSSProtection": "1; mode=block", + "strictTransportSecurity": "max-age=31536000; includeSubDomains" + }, + "smtpServer": {}, + "eventsEnabled": true, + "eventsExpiration": 900, + "eventsListeners": [ + "jboss-logging" + ], + "enabledEventTypes": [ + "SEND_RESET_PASSWORD", + "UPDATE_CONSENT_ERROR", + "GRANT_CONSENT", + "VERIFY_PROFILE_ERROR", + "REMOVE_TOTP", + "REVOKE_GRANT", + "UPDATE_TOTP", + "LOGIN_ERROR", + "CLIENT_LOGIN", + "RESET_PASSWORD_ERROR", + "IMPERSONATE_ERROR", + "CODE_TO_TOKEN_ERROR", + "CUSTOM_REQUIRED_ACTION", + "OAUTH2_DEVICE_CODE_TO_TOKEN_ERROR", + "RESTART_AUTHENTICATION", + "IMPERSONATE", + "UPDATE_PROFILE_ERROR", + "LOGIN", + "OAUTH2_DEVICE_VERIFY_USER_CODE", + "UPDATE_PASSWORD_ERROR", + "CLIENT_INITIATED_ACCOUNT_LINKING", + "OAUTH2_EXTENSION_GRANT", + "USER_DISABLED_BY_PERMANENT_LOCKOUT", + "TOKEN_EXCHANGE", + "AUTHREQID_TO_TOKEN", + "LOGOUT", + "REGISTER", + "DELETE_ACCOUNT_ERROR", + "CLIENT_REGISTER", + "IDENTITY_PROVIDER_LINK_ACCOUNT", + "USER_DISABLED_BY_TEMPORARY_LOCKOUT", + "DELETE_ACCOUNT", + "UPDATE_PASSWORD", + "CLIENT_DELETE", + "FEDERATED_IDENTITY_LINK_ERROR", + "IDENTITY_PROVIDER_FIRST_LOGIN", + "CLIENT_DELETE_ERROR", + "VERIFY_EMAIL", + "CLIENT_LOGIN_ERROR", + "RESTART_AUTHENTICATION_ERROR", + "EXECUTE_ACTIONS", + "REMOVE_FEDERATED_IDENTITY_ERROR", + "TOKEN_EXCHANGE_ERROR", + "PERMISSION_TOKEN", + "SEND_IDENTITY_PROVIDER_LINK_ERROR", + "EXECUTE_ACTION_TOKEN_ERROR", + "OAUTH2_EXTENSION_GRANT_ERROR", + "SEND_VERIFY_EMAIL", + "OAUTH2_DEVICE_AUTH", + "EXECUTE_ACTIONS_ERROR", + "REMOVE_FEDERATED_IDENTITY", + "OAUTH2_DEVICE_CODE_TO_TOKEN", + "IDENTITY_PROVIDER_POST_LOGIN", + "IDENTITY_PROVIDER_LINK_ACCOUNT_ERROR", + "OAUTH2_DEVICE_VERIFY_USER_CODE_ERROR", + "UPDATE_EMAIL", + "REGISTER_ERROR", + "REVOKE_GRANT_ERROR", + "EXECUTE_ACTION_TOKEN", + "LOGOUT_ERROR", + "UPDATE_EMAIL_ERROR", + "CLIENT_UPDATE_ERROR", + "AUTHREQID_TO_TOKEN_ERROR", + "UPDATE_PROFILE", + "CLIENT_REGISTER_ERROR", + "FEDERATED_IDENTITY_LINK", + "SEND_IDENTITY_PROVIDER_LINK", + "SEND_VERIFY_EMAIL_ERROR", + "RESET_PASSWORD", + "CLIENT_INITIATED_ACCOUNT_LINKING_ERROR", + "OAUTH2_DEVICE_AUTH_ERROR", + "UPDATE_CONSENT", + "REMOVE_TOTP_ERROR", + "VERIFY_EMAIL_ERROR", + "SEND_RESET_PASSWORD_ERROR", + "CLIENT_UPDATE", + "CUSTOM_REQUIRED_ACTION_ERROR", + "IDENTITY_PROVIDER_POST_LOGIN_ERROR", + "UPDATE_TOTP_ERROR", + "CODE_TO_TOKEN", + "VERIFY_PROFILE", + "GRANT_CONSENT_ERROR", + "IDENTITY_PROVIDER_FIRST_LOGIN_ERROR" + ], + "adminEventsEnabled": true, + "adminEventsDetailsEnabled": true, + "identityProviders": [], + "identityProviderMappers": [], + "components": { + "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [ + { + "id": "c07dff7f-77fc-4381-a458-9c56515c5c98", + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allow-default-scopes": [ + "true" + ] + } + }, + { + "id": "d9662eb8-e8bb-4ae5-a625-c8c616d8967a", + "name": "Consent Required", + "providerId": "consent-required", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "03f2b651-fdea-4a7a-88e8-f169f5a7f892", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "oidc-usermodel-attribute-mapper", + "oidc-usermodel-property-mapper", + "oidc-sha256-pairwise-sub-mapper", + "oidc-full-name-mapper", + "oidc-address-mapper", + "saml-user-attribute-mapper", + "saml-user-property-mapper", + "saml-role-list-mapper" + ] + } + }, + { + "id": "0c7278cb-1e59-407e-9187-fa147ce96f82", + "name": "Full Scope Disabled", + "providerId": "scope", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "a3c48cf1-67be-41fb-a852-6efe25560fcf", + "name": "Max Clients Limit", + "providerId": "max-clients", + "subType": "anonymous", + "subComponents": {}, + "config": { + "max-clients": [ + "200" + ] + } + }, + { + "id": "b0f72ad6-c65d-4132-912f-6e5ba9c48466", + "name": "Trusted Hosts", + "providerId": "trusted-hosts", + "subType": "anonymous", + "subComponents": {}, + "config": { + "host-sending-registration-request-must-match": [ + "true" + ], + "client-uris-must-match": [ + "true" + ] + } + }, + { + "id": "717bea7a-bc0a-4d2a-9ea2-cbe670f1833e", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "oidc-full-name-mapper", + "oidc-usermodel-attribute-mapper", + "oidc-usermodel-property-mapper", + "saml-role-list-mapper", + "saml-user-attribute-mapper", + "oidc-sha256-pairwise-sub-mapper", + "oidc-address-mapper", + "saml-user-property-mapper" + ] + } + }, + { + "id": "b1fa36d7-8ef0-4501-a495-215b90bd0699", + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allow-default-scopes": [ + "true" + ] + } + } + ], + "org.keycloak.keys.KeyProvider": [ + { + "id": "04a18d35-45bd-458d-9bc8-939db56e337d", + "name": "aes-generated", + "providerId": "aes-generated", + "subComponents": {}, + "config": { + "kid": [ + "3eaa2cde-31c2-409e-9e0e-b8f9ecf76704" + ], + "secret": [ + "7BdqNadvG1OQs7Z4qJfvaQ" + ], + "priority": [ + "100" + ] + } + }, + { + "id": "ce00dbf1-1d6d-44da-84c0-1ed88d712801", + "name": "rsa-generated", + "providerId": "rsa-generated", + "subComponents": {}, + "config": { + "privateKey": [ + "MIIEogIBAAKCAQEAp0WHWge6QpqVZfKr2kg1esRlHsSZfcGX8uu2pyB2NsXPjuaE0HqEN+OMsQsRR/rjbQkpPYG9sGur0nqNXhV/ErHIlMCmV2Hx8RoLWkVvpqrhnKH+0cBwm8dS83ZN0u5Q4xF1i6a/6FdZx0W45UrE/MZzlqB58I/EyaqZ4H6Id8MXp7W2Fuzw+Q2cKc1MxKx6MzhLJZShIXt8PTjueX5rRfYerdPbixq0E1vWA9Xcatt2mn/xIMo8illBk7fSPvzYv7YKsLtg1Cn43fU/mi63oBckb55D1uYzs2SgnzvRUX8eR6ndq/7CvZaGO3e3WN6FbowpE+wAbMZoXjlKRiHtPwIDAQABAoIBAAxcY/swNQB1AfNNsotn6KPQ3ZQffSRA6SSnbJD/Ih08EvGBcXEijKDArQXsRnOmQ6YsFiMYclcWLdVY/xdjyUctYiAz+Fbeww1JGmuqU+ziFdgIVJdVfDzWxvd815VtzQZqpOAUC3x08Ap8yYQQOWxgkewgocI4LZelhseDMjx/TIScOmuUWmFRwQ7HUP93OKV1oWC4lMAC4LTnqCqlnsk2L563+Q7T2jXUpznlJ6UoTSpu1Msllh+AxqkvZXvAwbFeYoDksWVUaY+gHAQkihgWMGIEmiBun9TsP4NUkpQuWXq1OHE6KBldaJPP3OProN2Z/gDgXDmKVVEf718m+YkCgYEA5KoroazEAIAjZ1L+t39DYNhv87eDnz/y2lRboD3InMFtE36rBPBIOTGiK3GKaIXh6b8VPOXXA5By2SnERIMfzdusmdknTREbC9Ca/ix5RyE/MqflGjqhcsEu1vWe/L7LYNrmTeOryR8E3rLSsrfmIFRKC+9ufsWlahttzW3D5ksCgYEAu0SLIqTmLfcwmIEngU044o5OZw7QtHaDJmNEv5n4cKXJHmCa3mK+IIIb7f3YIw4nyRQVKjbppAM1bLKT5RpqvHCxVIwjGbvhJ7l7QlBXmcx6x9n18ZPFdA8exUwm56sgixlrfUIHUMH1TFbGSFqIm5bAJwjFwqz3gXzSVU0rTF0CgYAjrCiCYGFzcooTZG84UTJBuYI9kzOFdIR+awqgRQM28TYDBI/JhXK++W9DN8NP6xMDVDwL9A9HDxHbrxhfV9VuWAblOWtYKoL9pN2JKYcCAb3KOUcUgHEPZfPYtRjIdTtlMMEdBZeXGK+5zkvwdaABCyVCF2g1fr//fafzlFwrYQKBgHtJcvhJ66hTVtDwJpv/xPWSjpdWr5w/cbRyIi6qJV+0JaY0H4FNLLKmNdEHD6Z0iUjeSdjS8hqiaie3oZpxO9f3sSdiYzFr+Z13hWhxEFsWvbaZDkwO5y2zTqTBr9NRXEl3YMbEE6DdMKsjbcLwp4MXSkXohpnV2dSL4sV52omZAoGAFY1w9JGkTwJ0rG/R+Yx3qcRhoHY7YA2PMSYIyB9E5d923L6bi1GRSwhNLO+lW0eWA8ekHiQLnqDmNJl708oJBGUwo/Zr7U9jowsqQIaSE8VgU6dfdhbScMI5vpmSrlQRyV0UveLvCsEAx/Rvl4y+dQneaEoNqEKSd7Hml2tjx7g=" + ], + "keyUse": [ + "SIG" + ], + "certificate": [ + "MIICnzCCAYcCBgGO+25VozANBgkqhkiG9w0BAQsFADATMREwDwYDVQQDDAhiYWVsZHVuZzAeFw0yNDA0MjAxMjEzMTVaFw0zNDA0MjAxMjE0NTVaMBMxETAPBgNVBAMMCGJhZWxkdW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp0WHWge6QpqVZfKr2kg1esRlHsSZfcGX8uu2pyB2NsXPjuaE0HqEN+OMsQsRR/rjbQkpPYG9sGur0nqNXhV/ErHIlMCmV2Hx8RoLWkVvpqrhnKH+0cBwm8dS83ZN0u5Q4xF1i6a/6FdZx0W45UrE/MZzlqB58I/EyaqZ4H6Id8MXp7W2Fuzw+Q2cKc1MxKx6MzhLJZShIXt8PTjueX5rRfYerdPbixq0E1vWA9Xcatt2mn/xIMo8illBk7fSPvzYv7YKsLtg1Cn43fU/mi63oBckb55D1uYzs2SgnzvRUX8eR6ndq/7CvZaGO3e3WN6FbowpE+wAbMZoXjlKRiHtPwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQB091NLrtrT+JSmLfyv+LvFIPIaOu07kWHbueqjKbOinQ2ouBfMnOA9Ojm/17w8CIt/h6VIBzoi3H9Huq15dnGoiIcQIzvAiq8XSewnVfnyvFeq830LVAiTEEDRQLqKVT1PiRZEj64XGyRM3lX0Xp+CXG8z3Qc4OVFrHdb/nUIbfDAmxsWRymTm5p2E5GTJPlr/gON/AHPAHIzmgk5HD9PqBPpMQRHN9/y8vkeIPh9gEj8oUYsM6MPEKrbQIDBqnr8UaxPaMtJF+cjg36VB0SJ9c1w0DBWeND/UNFq47aNWMSND5O9qX0eJxVTqxFAFia0V2WUZk17Pd6pzLKkZQb94" + ], + "priority": [ + "100" + ] + } + }, + { + "id": "fa8ee6a3-d95e-4ec9-856a-0962208b6bcc", + "name": "rsa-enc-generated", + "providerId": "rsa-enc-generated", + "subComponents": {}, + "config": { + "privateKey": [ + "MIIEowIBAAKCAQEAsZNPlXoVvt4RsbkFu3giJB3W3qDxEGsAIvOQqLFKP4o1oFJY4L4K5ljUbGABMiq0fQEVTj1mAZAwqJ/J+mnv5OhkUfTDpAt0LactZRPqz7RyfRwmSTL3r/kCtFZn5WQZA//Z6q3zdm7ARxH3Dq9+cMARIe1k7dblWlX+8A5Qk8Ka9Ie6SfwqlTsv4EMTmIhUjj/UyEAWLhSLrk/gA3PQyw/OUEWJTM946AWmPcMtWJRFDbMsj00G1sgrmRuIa0zmXpLj+Zr1Kby9GBU/x60EKtONtXiX8IvIKFm8mKI40q8va6jI71wqUB7OtDZ1a+iF1h8TJ+X5Q2ARPo0li3iEUQIDAQABAoIBADhe57ovZdzP+TT+Y9P12Hy3nkDRPYV1OjdeM5NhqIzQLqLk0UMTATnLhC+dMHQA+4fdQqqyMgIYCGJXS1J7s8Rqg4JC3aJjYm+lrPLz5iwmf9u4hmzhSaCqv1GJRnUbGBfdbguiSfHUSaSmDtQyIMThK+8lwc8A05EgUIxbNvgYnEOEdavlyCq4HdMiDPSjpdHSdC8NpaQkAVULB3QXofm5SQm4ioED/trVjHyjl80i9ysDKSPPzqpye4lFCqmclni1U78V2w4E/uVOG8+MczZkS4otPG99QoELGuqLaVmq9rAx624owUAY3r7ecCL2lSHyjzJwBkrBFLenlSI4A6sCgYEA7tPcbOYPt2a7ih1nase6aC5rwTk62lpe9cuNpVCRmKKlX9glLLcFjNz+75LSyj4TXvg52vcZv3JmsULUeE30rPVr9hgIeuEnsPCc4HLJ40aVaEyhVVwg5ofy3++/8Ys0PR2blZ674/jFgxbB537t81QxQd5WtD9Zh+w7Tiiw40sCgYEAvlf4qvjKW6kaOpmIe4S7wWY9/FhbgHq3sKLltfzOGY0GTWGFZtJ7uzgDvOkEVAIyopEDKfkBL3Sok5ic8MpQOARCa1HXjm8+dtQ1SkNxDsGC//DpouHefkvwUNeKYPV2n4CckirUMmvSqWz4oWAA5u0C2eg0pwvlavMpRKN1mVMCgYB7Klt09biJNrvk4IEi+lnRvI7pmSAW16A9Vnp4FPLhKo/qu8eAJesA2D/JQYjfr9/BjHYZzHFE4DTBmduFJ37Va8P/qClHZbJYd94PimM/iHkozsws/1QgT2AbyMLOSKHqGsjQAoqXaQZDMotRXY5NfM/iTk2cq0b66AM1rZp7vQKBgQCpBc1XZV2sT1lvN+8uYAuqDXR1pLB8QnzjaYO6Oyd5IPW7uSGQ0M/2zCLlmbWyM9Fq8oJwvyECVwFrL1YNrFnXpFCmpCJZ5Qb+1ioMLB81DzmYtQGDFjdQx3Y7E2tZ9h7EPJzMXyPXMk/7Cz0tb+bdKRIjFkPLIpEyi4LV5KEE6QKBgF7Hs1jnR+/3wVK2NG+Ek5bOwOn7wNtwpfhHpj+Auwk7B9mzoor01L6UTw+LDMtQoohfqOJhM1xZcn2MJdhZhkWvSpavEyuY886A8RVtL44rh/kCHy/M4d9AQoiSz5mIYOdiiskbepG+jaIoweUvWxLmcWLWgV3H8syyqJR/vf30" + ], + "keyUse": [ + "ENC" + ], + "certificate": [ + "MIICnzCCAYcCBgGO+25WEDANBgkqhkiG9w0BAQsFADATMREwDwYDVQQDDAhiYWVsZHVuZzAeFw0yNDA0MjAxMjEzMTZaFw0zNDA0MjAxMjE0NTZaMBMxETAPBgNVBAMMCGJhZWxkdW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsZNPlXoVvt4RsbkFu3giJB3W3qDxEGsAIvOQqLFKP4o1oFJY4L4K5ljUbGABMiq0fQEVTj1mAZAwqJ/J+mnv5OhkUfTDpAt0LactZRPqz7RyfRwmSTL3r/kCtFZn5WQZA//Z6q3zdm7ARxH3Dq9+cMARIe1k7dblWlX+8A5Qk8Ka9Ie6SfwqlTsv4EMTmIhUjj/UyEAWLhSLrk/gA3PQyw/OUEWJTM946AWmPcMtWJRFDbMsj00G1sgrmRuIa0zmXpLj+Zr1Kby9GBU/x60EKtONtXiX8IvIKFm8mKI40q8va6jI71wqUB7OtDZ1a+iF1h8TJ+X5Q2ARPo0li3iEUQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQCT9Jua67qgsClibdgvEfX3BKLl+JXVbFjyYKfBhP85DIk/tzfeYi1UZilWGPWlnprhp5GnwZXPeqVsLCNM+ypdYN8RGBs6K48wVQoetf92GPh9eCQMq2FSAVKShsgkolKifyuZo8oQu6Na92V5EsjUV7hEB4G3jXOisrO/MjN+Ja9eRXru1L2n7bOrKtYRlYeNI8CZvc63jRPkq1fRutcmpqMRPDjMYuM9wUvkZwewqo8WSf51DDKBah5W83XLbTp5jX0bH1NZc3BNHnNerR3iMGPSa6rcKPsC3lL1mZluNVhQExyli1S1f7QmUc1BYxr3zi2uVCKkci5gRenDywws" + ], + "priority": [ + "100" + ], + "algorithm": [ + "RSA-OAEP" + ] + } + }, + { + "id": "0866f9d1-3c22-432c-95d4-65378e739b89", + "name": "hmac-generated-hs512", + "providerId": "hmac-generated", + "subComponents": {}, + "config": { + "kid": [ + "749eb77a-a3d7-45b2-bc40-3bf80faf2fc7" + ], + "secret": [ + "YmaVXh3blZqVaqpgeLyGI5JUzV8Vc41XFb7RcUaChNmAN-f61pqz7nE6edgQj_NS-TVVsvlq9qouKcd-5_oGugmvCXZ-Dp5gzcKe4EA-voOEV4pvJ7VXRWuH6QBDCaXyDiknEVtIx20ycjC4F8Ch10_n8so87mwMuVA6zD8Y-oM" + ], + "priority": [ + "100" + ], + "algorithm": [ + "HS512" + ] + } + } + ] + }, + "internationalizationEnabled": false, + "supportedLocales": [], + "authenticationFlows": [ + { + "id": "92fc572a-6443-4d62-989d-dc6147aed6a6", + "alias": "Account verification options", + "description": "Method with which to verity the existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-email-verification", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "ALTERNATIVE", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Verify Existing Account by Re-authentication", + "userSetupAllowed": false + } + ] + }, + { + "id": "17dce980-92a5-4dab-84b6-29f0ffe91e2f", + "alias": "Browser - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "auth-otp-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "9fdb023c-7959-4e7c-b745-d0bcfc6e1f87", + "alias": "Direct Grant - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "direct-grant-validate-otp", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "336dbe24-c5ec-44c0-bf56-1b811b451fdf", + "alias": "First broker login - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "auth-otp-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "3a87da1e-2fdf-4d15-8c93-8e8d69fc2774", + "alias": "Handle Existing Account", + "description": "Handle what to do if there is existing account with same email/username like authenticated identity provider", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-confirm-link", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Account verification options", + "userSetupAllowed": false + } + ] + }, + { + "id": "77bd3109-c34e-4165-b9f7-cb6d19aa7fe3", + "alias": "Reset - Conditional OTP", + "description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "reset-otp", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "ee4b2165-c1be-43ca-96c8-b2302d78b38a", + "alias": "User creation or linking", + "description": "Flow for the existing/non-existing user alternatives", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "create unique user config", + "authenticator": "idp-create-user-if-unique", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "ALTERNATIVE", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Handle Existing Account", + "userSetupAllowed": false + } + ] + }, + { + "id": "0116eec2-8a17-4de9-b75f-caa26e52bdf0", + "alias": "Verify Existing Account by Re-authentication", + "description": "Reauthentication of existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-username-password-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "First broker login - Conditional OTP", + "userSetupAllowed": false + } + ] + }, + { + "id": "de8794bd-3ad0-42e9-861f-85fcb6cb1db6", + "alias": "browser", + "description": "browser based authentication", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-cookie", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "auth-spnego", + "authenticatorFlow": false, + "requirement": "DISABLED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "identity-provider-redirector", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 25, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "ALTERNATIVE", + "priority": 30, + "autheticatorFlow": true, + "flowAlias": "forms", + "userSetupAllowed": false + } + ] + }, + { + "id": "9f6aa9f1-134b-4efe-84c4-ba9b7f4e8368", + "alias": "clients", + "description": "Base authentication for clients", + "providerId": "client-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "client-secret", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "client-jwt", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "client-secret-jwt", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 30, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "client-x509", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 40, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "692ddf3c-2813-46ef-b364-fcba9d70f5a4", + "alias": "direct grant", + "description": "OpenID Connect Resource Owner Grant", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "direct-grant-validate-username", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "direct-grant-validate-password", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 30, + "autheticatorFlow": true, + "flowAlias": "Direct Grant - Conditional OTP", + "userSetupAllowed": false + } + ] + }, + { + "id": "257e18b2-be1c-4ab2-8dd7-68a83817ca8a", + "alias": "docker auth", + "description": "Used by Docker clients to authenticate against the IDP", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "docker-http-basic-authenticator", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "fe879ee4-eec5-4034-9b78-82636f614123", + "alias": "first broker login", + "description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "review profile config", + "authenticator": "idp-review-profile", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "User creation or linking", + "userSetupAllowed": false + } + ] + }, + { + "id": "2e6f09af-a3f6-415a-8d38-dfc1708e82ff", + "alias": "forms", + "description": "Username, password, otp and other auth forms.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-username-password-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Browser - Conditional OTP", + "userSetupAllowed": false + } + ] + }, + { + "id": "cac2a81c-7933-4e1c-a91b-1a5e4d8ba873", + "alias": "registration", + "description": "registration flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-page-form", + "authenticatorFlow": true, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": true, + "flowAlias": "registration form", + "userSetupAllowed": false + } + ] + }, + { + "id": "76b893b1-6b16-4e7c-a945-b86b63c983fb", + "alias": "registration form", + "description": "registration form", + "providerId": "form-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-user-creation", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "registration-password-action", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 50, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "registration-recaptcha-action", + "authenticatorFlow": false, + "requirement": "DISABLED", + "priority": 60, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "registration-terms-and-conditions", + "authenticatorFlow": false, + "requirement": "DISABLED", + "priority": 70, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "8c1ba21b-218d-406d-a936-c935f41e7bef", + "alias": "reset credentials", + "description": "Reset credentials for a user if they forgot their password or something", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "reset-credentials-choose-user", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "reset-credential-email", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "reset-password", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 30, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 40, + "autheticatorFlow": true, + "flowAlias": "Reset - Conditional OTP", + "userSetupAllowed": false + } + ] + }, + { + "id": "6df47204-9532-4b3e-821f-9a5255b9c305", + "alias": "saml ecp", + "description": "SAML ECP Profile Authentication Flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "http-basic-authenticator", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + } + ], + "authenticatorConfig": [ + { + "id": "793b40f2-0912-40f4-b570-a75015fb9eb0", + "alias": "create unique user config", + "config": { + "require.password.update.after.registration": "false" + } + }, + { + "id": "3ff115f7-7108-4b17-8868-1d390ec3a480", + "alias": "review profile config", + "config": { + "update.profile.on.first.login": "missing" + } + } + ], + "requiredActions": [ + { + "alias": "CONFIGURE_TOTP", + "name": "Configure OTP", + "providerId": "CONFIGURE_TOTP", + "enabled": true, + "defaultAction": false, + "priority": 10, + "config": {} + }, + { + "alias": "TERMS_AND_CONDITIONS", + "name": "Terms and Conditions", + "providerId": "TERMS_AND_CONDITIONS", + "enabled": false, + "defaultAction": false, + "priority": 20, + "config": {} + }, + { + "alias": "UPDATE_PASSWORD", + "name": "Update Password", + "providerId": "UPDATE_PASSWORD", + "enabled": true, + "defaultAction": false, + "priority": 30, + "config": {} + }, + { + "alias": "UPDATE_PROFILE", + "name": "Update Profile", + "providerId": "UPDATE_PROFILE", + "enabled": true, + "defaultAction": false, + "priority": 40, + "config": {} + }, + { + "alias": "VERIFY_EMAIL", + "name": "Verify Email", + "providerId": "VERIFY_EMAIL", + "enabled": true, + "defaultAction": false, + "priority": 50, + "config": {} + }, + { + "alias": "delete_account", + "name": "Delete Account", + "providerId": "delete_account", + "enabled": false, + "defaultAction": false, + "priority": 60, + "config": {} + }, + { + "alias": "webauthn-register", + "name": "Webauthn Register", + "providerId": "webauthn-register", + "enabled": true, + "defaultAction": false, + "priority": 70, + "config": {} + }, + { + "alias": "webauthn-register-passwordless", + "name": "Webauthn Register Passwordless", + "providerId": "webauthn-register-passwordless", + "enabled": true, + "defaultAction": false, + "priority": 80, + "config": {} + }, + { + "alias": "VERIFY_PROFILE", + "name": "Verify Profile", + "providerId": "VERIFY_PROFILE", + "enabled": true, + "defaultAction": false, + "priority": 90, + "config": {} + }, + { + "alias": "update_user_locale", + "name": "Update User Locale", + "providerId": "update_user_locale", + "enabled": true, + "defaultAction": false, + "priority": 1000, + "config": {} + } + ], + "browserFlow": "browser", + "registrationFlow": "registration", + "directGrantFlow": "direct grant", + "resetCredentialsFlow": "reset credentials", + "clientAuthenticationFlow": "clients", + "dockerAuthenticationFlow": "docker auth", + "firstBrokerLoginFlow": "first broker login", + "attributes": { + "cibaBackchannelTokenDeliveryMode": "poll", + "cibaAuthRequestedUserHint": "login_hint", + "oauth2DevicePollingInterval": "5", + "clientOfflineSessionMaxLifespan": "0", + "clientSessionIdleTimeout": "0", + "clientOfflineSessionIdleTimeout": "0", + "cibaInterval": "5", + "realmReusableOtpCode": "false", + "cibaExpiresIn": "120", + "oauth2DeviceCodeLifespan": "600", + "parRequestUriLifespan": "60", + "clientSessionMaxLifespan": "0", + "adminEventsExpiration": "900" + }, + "keycloakVersion": "24.0.0", + "userManagedAccessAllowed": false, + "clientProfiles": { + "profiles": [] + }, + "clientPolicies": { + "policies": [] + } } \ No newline at end of file diff --git a/spring-security-modules/spring-security-oauth2-testing/keycloak/import/baeldung-users-0.json b/spring-security-modules/spring-security-oauth2-testing/keycloak/import/baeldung-users-0.json index 20a78548df..1d43a9eecc 100644 --- a/spring-security-modules/spring-security-oauth2-testing/keycloak/import/baeldung-users-0.json +++ b/spring-security-modules/spring-security-oauth2-testing/keycloak/import/baeldung-users-0.json @@ -1,50 +1,62 @@ { - "realm" : "baeldung", - "users" : [ { - "id" : "bb83bd5b-b895-49aa-b62e-fde8ff8d5e64", - "username" : "authorized", - "firstName" : "authorized", - "lastName" : "user", - "email" : "authorized@baeldung.gg", - "emailVerified" : true, - "createdTimestamp" : 1713615702990, - "enabled" : true, - "totp" : false, - "credentials" : [ { - "id" : "23d3b6ce-fa3c-4f6e-9b09-e7b3cefa00f6", - "type" : "password", - "userLabel" : "My password", - "createdDate" : 1713615715678, - "secretData" : "{\"value\":\"lCZEOiVbCynSkCWiWe67/5/PybB+Om5mhi6SynpGFPB+r2b+QEKNYsB7ibO2f1ur9UB2aMO7jfoBYQdTJMcHbQ==\",\"salt\":\"hrIbqMOt0L7PPEYh/PsLNQ==\",\"additionalParameters\":{}}", - "credentialData" : "{\"hashIterations\":210000,\"algorithm\":\"pbkdf2-sha512\",\"additionalParameters\":{}}" - } ], - "disableableCredentialTypes" : [ ], - "requiredActions" : [ ], - "realmRoles" : [ "AUTHORIZED_PERSONNEL", "default-roles-baeldung" ], - "notBefore" : 0, - "groups" : [ ] - }, { - "id" : "d205d854-547c-43cf-a02d-fd6c385b128b", - "username" : "forbidden", - "firstName" : "forbidden", - "lastName" : "user", - "email" : "forbidden@baeldung.gg", - "emailVerified" : true, - "createdTimestamp" : 1713615781285, - "enabled" : true, - "totp" : false, - "credentials" : [ { - "id" : "2fa8244c-fba9-43d9-ab4d-80804ca26f6f", - "type" : "password", - "userLabel" : "My password", - "createdDate" : 1713615795357, - "secretData" : "{\"value\":\"sOUpOdi8yf31YbMEub+tAF7N55QHjrPjg48mO3/C1zGaAxLUYdLodf4upuy6w7eBuRrFaVa1m4mRe6wkWtmLIw==\",\"salt\":\"OMbZn6ojNyZdp6/k/72B/A==\",\"additionalParameters\":{}}", - "credentialData" : "{\"hashIterations\":210000,\"algorithm\":\"pbkdf2-sha512\",\"additionalParameters\":{}}" - } ], - "disableableCredentialTypes" : [ ], - "requiredActions" : [ ], - "realmRoles" : [ "default-roles-baeldung" ], - "notBefore" : 0, - "groups" : [ ] - } ] + "realm": "baeldung", + "users": [ + { + "id": "bb83bd5b-b895-49aa-b62e-fde8ff8d5e64", + "username": "authorized", + "firstName": "authorized", + "lastName": "user", + "email": "authorized@baeldung.gg", + "emailVerified": true, + "createdTimestamp": 1713615702990, + "enabled": true, + "totp": false, + "credentials": [ + { + "id": "23d3b6ce-fa3c-4f6e-9b09-e7b3cefa00f6", + "type": "password", + "userLabel": "My password", + "createdDate": 1713615715678, + "secretData": "{\"value\":\"lCZEOiVbCynSkCWiWe67/5/PybB+Om5mhi6SynpGFPB+r2b+QEKNYsB7ibO2f1ur9UB2aMO7jfoBYQdTJMcHbQ==\",\"salt\":\"hrIbqMOt0L7PPEYh/PsLNQ==\",\"additionalParameters\":{}}", + "credentialData": "{\"hashIterations\":210000,\"algorithm\":\"pbkdf2-sha512\",\"additionalParameters\":{}}" + } + ], + "disableableCredentialTypes": [], + "requiredActions": [], + "realmRoles": [ + "AUTHORIZED_PERSONNEL", + "default-roles-baeldung" + ], + "notBefore": 0, + "groups": [] + }, + { + "id": "d205d854-547c-43cf-a02d-fd6c385b128b", + "username": "forbidden", + "firstName": "forbidden", + "lastName": "user", + "email": "forbidden@baeldung.gg", + "emailVerified": true, + "createdTimestamp": 1713615781285, + "enabled": true, + "totp": false, + "credentials": [ + { + "id": "2fa8244c-fba9-43d9-ab4d-80804ca26f6f", + "type": "password", + "userLabel": "My password", + "createdDate": 1713615795357, + "secretData": "{\"value\":\"sOUpOdi8yf31YbMEub+tAF7N55QHjrPjg48mO3/C1zGaAxLUYdLodf4upuy6w7eBuRrFaVa1m4mRe6wkWtmLIw==\",\"salt\":\"OMbZn6ojNyZdp6/k/72B/A==\",\"additionalParameters\":{}}", + "credentialData": "{\"hashIterations\":210000,\"algorithm\":\"pbkdf2-sha512\",\"additionalParameters\":{}}" + } + ], + "disableableCredentialTypes": [], + "requiredActions": [], + "realmRoles": [ + "default-roles-baeldung" + ], + "notBefore": 0, + "groups": [] + } + ] } \ No newline at end of file diff --git a/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/pom.xml b/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/pom.xml index f22ebd1bd7..f284f5bf15 100644 --- a/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/pom.xml +++ b/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/pom.xml @@ -1,61 +1,61 @@ - 4.0.0 - com.baeldung.spring-security-modules.testing - reactive-resource-server - reactive-resource-server - Demo project for Spring Boot reactive resource-server + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + com.baeldung.spring-security-modules.testing + reactive-resource-server + reactive-resource-server + Demo project for Spring Boot reactive resource-server - - com.baeldung - spring-security-oauth2-testing - 0.0.1-SNAPSHOT - .. - + + com.baeldung + spring-security-oauth2-testing + 0.0.1-SNAPSHOT + .. + - - - org.springframework.boot - spring-boot-starter-oauth2-resource-server - - - org.springframework.boot - spring-boot-starter-webflux - - - org.projectlombok - lombok - true - - - org.springframework.boot - spring-boot-starter-test - test - - - com.c4-soft.springaddons - spring-addons-oauth2-test - test - - + + + org.springframework.boot + spring-boot-starter-oauth2-resource-server + + + org.springframework.boot + spring-boot-starter-webflux + + + org.projectlombok + lombok + true + + + org.springframework.boot + spring-boot-starter-test + test + + + com.c4-soft.springaddons + spring-addons-oauth2-test + test + + - - - - org.springframework.boot - spring-boot-maven-plugin - - - - org.projectlombok - lombok - - - - - - + + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.projectlombok + lombok + + + + + + \ No newline at end of file diff --git a/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/test/resources/ch4mpy.json b/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/test/resources/ch4mpy.json index 22f7bb2cea..5a39971eab 100644 --- a/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/test/resources/ch4mpy.json +++ b/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/test/resources/ch4mpy.json @@ -1,15 +1,15 @@ { - "iss": "https://localhost:8443/realms/master", - "sub": "281c4558-550c-413b-9972-2d2e5bde6b9b", - "iat": 1695992542, - "exp": 1695992642, - "preferred_username": "ch4mpy", - "realm_access": { - "roles": [ - "admin", - "ROLE_AUTHORIZED_PERSONNEL" - ] - }, - "email": "ch4mp@c4-soft.com", - "scope": "openid email" + "iss": "https://localhost:8443/realms/master", + "sub": "281c4558-550c-413b-9972-2d2e5bde6b9b", + "iat": 1695992542, + "exp": 1695992642, + "preferred_username": "ch4mpy", + "realm_access": { + "roles": [ + "admin", + "ROLE_AUTHORIZED_PERSONNEL" + ] + }, + "email": "ch4mp@c4-soft.com", + "scope": "openid email" } \ No newline at end of file diff --git a/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/test/resources/tonton-pirate.json b/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/test/resources/tonton-pirate.json index 13a422f6fd..eff989f2c3 100644 --- a/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/test/resources/tonton-pirate.json +++ b/spring-security-modules/spring-security-oauth2-testing/reactive-resource-server/src/test/resources/tonton-pirate.json @@ -1,15 +1,15 @@ { - "iss": "https://localhost:8443/realms/master", - "sub": "2d2e5bde6b9b-550c-413b-9972-281c4558", - "iat": 1695992551, - "exp": 1695992651, - "preferred_username": "tonton-pirate", - "realm_access": { - "roles": [ - "uncle", - "PIRATE" - ] - }, - "email": "tonton-pirate@c4-soft.com", - "scope": "openid email" + "iss": "https://localhost:8443/realms/master", + "sub": "2d2e5bde6b9b-550c-413b-9972-281c4558", + "iat": 1695992551, + "exp": 1695992651, + "preferred_username": "tonton-pirate", + "realm_access": { + "roles": [ + "uncle", + "PIRATE" + ] + }, + "email": "tonton-pirate@c4-soft.com", + "scope": "openid email" } \ No newline at end of file diff --git a/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/pom.xml b/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/pom.xml index ddd6c1d313..75175fe1aa 100644 --- a/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/pom.xml +++ b/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/pom.xml @@ -1,61 +1,61 @@ - 4.0.0 - com.baeldung.spring-security-modules.testing - servlet-resource-server - servlet-resource-server - Demo project for Spring Boot servlet resource-server + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + com.baeldung.spring-security-modules.testing + servlet-resource-server + servlet-resource-server + Demo project for Spring Boot servlet resource-server - - com.baeldung - spring-security-oauth2-testing - 0.0.1-SNAPSHOT - .. - + + com.baeldung + spring-security-oauth2-testing + 0.0.1-SNAPSHOT + .. + - - - org.springframework.boot - spring-boot-starter-oauth2-resource-server - - - org.springframework.boot - spring-boot-starter-web - - - org.projectlombok - lombok - true - - - org.springframework.boot - spring-boot-starter-test - test - - - com.c4-soft.springaddons - spring-addons-oauth2-test - test - - + + + org.springframework.boot + spring-boot-starter-oauth2-resource-server + + + org.springframework.boot + spring-boot-starter-web + + + org.projectlombok + lombok + true + + + org.springframework.boot + spring-boot-starter-test + test + + + com.c4-soft.springaddons + spring-addons-oauth2-test + test + + - - - - org.springframework.boot - spring-boot-maven-plugin - - - - org.projectlombok - lombok - - - - - - + + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.projectlombok + lombok + + + + + + diff --git a/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/test/resources/ch4mpy.json b/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/test/resources/ch4mpy.json index 22f7bb2cea..5a39971eab 100644 --- a/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/test/resources/ch4mpy.json +++ b/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/test/resources/ch4mpy.json @@ -1,15 +1,15 @@ { - "iss": "https://localhost:8443/realms/master", - "sub": "281c4558-550c-413b-9972-2d2e5bde6b9b", - "iat": 1695992542, - "exp": 1695992642, - "preferred_username": "ch4mpy", - "realm_access": { - "roles": [ - "admin", - "ROLE_AUTHORIZED_PERSONNEL" - ] - }, - "email": "ch4mp@c4-soft.com", - "scope": "openid email" + "iss": "https://localhost:8443/realms/master", + "sub": "281c4558-550c-413b-9972-2d2e5bde6b9b", + "iat": 1695992542, + "exp": 1695992642, + "preferred_username": "ch4mpy", + "realm_access": { + "roles": [ + "admin", + "ROLE_AUTHORIZED_PERSONNEL" + ] + }, + "email": "ch4mp@c4-soft.com", + "scope": "openid email" } \ No newline at end of file diff --git a/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/test/resources/tonton-pirate.json b/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/test/resources/tonton-pirate.json index 13a422f6fd..eff989f2c3 100644 --- a/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/test/resources/tonton-pirate.json +++ b/spring-security-modules/spring-security-oauth2-testing/servlet-resource-server/src/test/resources/tonton-pirate.json @@ -1,15 +1,15 @@ { - "iss": "https://localhost:8443/realms/master", - "sub": "2d2e5bde6b9b-550c-413b-9972-281c4558", - "iat": 1695992551, - "exp": 1695992651, - "preferred_username": "tonton-pirate", - "realm_access": { - "roles": [ - "uncle", - "PIRATE" - ] - }, - "email": "tonton-pirate@c4-soft.com", - "scope": "openid email" + "iss": "https://localhost:8443/realms/master", + "sub": "2d2e5bde6b9b-550c-413b-9972-281c4558", + "iat": 1695992551, + "exp": 1695992651, + "preferred_username": "tonton-pirate", + "realm_access": { + "roles": [ + "uncle", + "PIRATE" + ] + }, + "email": "tonton-pirate@c4-soft.com", + "scope": "openid email" } \ No newline at end of file From 8193ddf31430cd92f55cc61252aa5e3590401753 Mon Sep 17 00:00:00 2001 From: Bipin kumar Date: Wed, 24 Apr 2024 14:25:24 +0530 Subject: [PATCH 10/33] JAVA-32170_M_02: Changes made for Fix formatting of POMs (#16117) --- maven-modules/maven-reactor/pom.xml | 2 +- maven-modules/maven-repositories/pom.xml | 2 +- .../maven-simple/parent-project/pom.xml | 2 +- .../parent-project/webapp/pom.xml | 2 +- maven-modules/maven-simple/pom.xml | 2 +- maven-modules/maven-surefire-plugin/pom.xml | 2 +- maven-modules/maven-war-plugin/pom.xml | 2 +- maven-modules/multimodulemavenproject/pom.xml | 2 +- maven-modules/resume-from/business/pom.xml | 2 ++ maven-modules/resume-from/lib/pom.xml | 5 ++-- maven-modules/resume-from/pom.xml | 2 +- maven-modules/spring-bom/pom.xml | 1 + maven-modules/versions-maven-plugin/pom.xml | 2 +- messaging-modules/apache-camel/pom.xml | 2 +- messaging-modules/pom.xml | 2 +- messaging-modules/spring-apache-camel/pom.xml | 2 +- messaging-modules/spring-jms/pom.xml | 2 +- .../event-driven-microservice/pom.xml | 23 +++++++------------ microservices-modules/helidon/pom.xml | 2 +- microservices-modules/micronaut/pom.xml | 2 +- microservices-modules/microprofile/pom.xml | 2 +- microservices-modules/pom.xml | 2 +- microservices-modules/rest-express/pom.xml | 2 +- muleesb/pom.xml | 2 +- mybatis/pom.xml | 1 - 25 files changed, 34 insertions(+), 38 deletions(-) diff --git a/maven-modules/maven-reactor/pom.xml b/maven-modules/maven-reactor/pom.xml index debbcda803..cf4adac16e 100644 --- a/maven-modules/maven-reactor/pom.xml +++ b/maven-modules/maven-reactor/pom.xml @@ -5,8 +5,8 @@ 4.0.0 maven-reactor 1.0-SNAPSHOT - maven-reactor pom + maven-reactor Sample multi-module project to explain maven reactor diff --git a/maven-modules/maven-repositories/pom.xml b/maven-modules/maven-repositories/pom.xml index c9c7ba9a8b..78da14f876 100644 --- a/maven-modules/maven-repositories/pom.xml +++ b/maven-modules/maven-repositories/pom.xml @@ -5,8 +5,8 @@ 4.0.0 maven-repositories 1.0.0-SNAPSHOT - maven-repositories pom + maven-repositories com.baeldung diff --git a/maven-modules/maven-simple/parent-project/pom.xml b/maven-modules/maven-simple/parent-project/pom.xml index 2f28eff49f..3374ed133a 100644 --- a/maven-modules/maven-simple/parent-project/pom.xml +++ b/maven-modules/maven-simple/parent-project/pom.xml @@ -5,8 +5,8 @@ 4.0.0 parent-project 1.0-SNAPSHOT - parent-project pom + parent-project com.baeldung diff --git a/maven-modules/maven-simple/parent-project/webapp/pom.xml b/maven-modules/maven-simple/parent-project/webapp/pom.xml index d0596a4503..b119c1c4c1 100644 --- a/maven-modules/maven-simple/parent-project/webapp/pom.xml +++ b/maven-modules/maven-simple/parent-project/webapp/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 webapp - webapp war + webapp parent-project diff --git a/maven-modules/maven-simple/pom.xml b/maven-modules/maven-simple/pom.xml index fe59259758..155c32bee3 100644 --- a/maven-modules/maven-simple/pom.xml +++ b/maven-modules/maven-simple/pom.xml @@ -4,9 +4,9 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 maven-simple - maven-simple 1.0.0-SNAPSHOT pom + maven-simple com.baeldung diff --git a/maven-modules/maven-surefire-plugin/pom.xml b/maven-modules/maven-surefire-plugin/pom.xml index 840ffab077..ce2e380aae 100644 --- a/maven-modules/maven-surefire-plugin/pom.xml +++ b/maven-modules/maven-surefire-plugin/pom.xml @@ -5,8 +5,8 @@ 4.0.0 maven-surefire-plugin 0.0.1-SNAPSHOT - maven-surefire-plugin jar + maven-surefire-plugin com.baeldung diff --git a/maven-modules/maven-war-plugin/pom.xml b/maven-modules/maven-war-plugin/pom.xml index 04188b8995..df3889e47c 100644 --- a/maven-modules/maven-war-plugin/pom.xml +++ b/maven-modules/maven-war-plugin/pom.xml @@ -6,8 +6,8 @@ com.baeldung maven-war-plugin 0.0.1-SNAPSHOT - maven-war-plugin war + maven-war-plugin diff --git a/maven-modules/multimodulemavenproject/pom.xml b/maven-modules/multimodulemavenproject/pom.xml index 5a6eea7cf4..b2dfe1afa7 100644 --- a/maven-modules/multimodulemavenproject/pom.xml +++ b/maven-modules/multimodulemavenproject/pom.xml @@ -6,8 +6,8 @@ com.baeldung.multimodulemavenproject multimodulemavenproject 1.0 - multimodulemavenproject pom + multimodulemavenproject - io.orkes.demo - event-driven-microservice - 0.1 - - event-driven-microservice - Demo Project for Orkes Conductor on Spring Boot - - - org.springframework.boot spring-boot-starter-web - io.orkes.conductor orkes-conductor-client ${conductor.client.version} - org.springdoc springdoc-openapi-starter-webmvc-ui ${springdoc-openapi-webmvc-ui.version} - org.projectlombok lombok true - org.springframework.boot spring-boot-starter-test diff --git a/microservices-modules/helidon/pom.xml b/microservices-modules/helidon/pom.xml index ca2cafb7d3..894867c6a7 100644 --- a/microservices-modules/helidon/pom.xml +++ b/microservices-modules/helidon/pom.xml @@ -5,8 +5,8 @@ 4.0.0 com.baeldung.helidon helidon - helidon pom + helidon com.baeldung diff --git a/microservices-modules/micronaut/pom.xml b/microservices-modules/micronaut/pom.xml index 641b23d5e6..c1c669f107 100644 --- a/microservices-modules/micronaut/pom.xml +++ b/microservices-modules/micronaut/pom.xml @@ -6,8 +6,8 @@ com.baeldung.micronaut micronaut 0.1 - micronaut ${packaging} + micronaut com.baeldung diff --git a/microservices-modules/microprofile/pom.xml b/microservices-modules/microprofile/pom.xml index b2ce768748..54a4bd5c09 100644 --- a/microservices-modules/microprofile/pom.xml +++ b/microservices-modules/microprofile/pom.xml @@ -5,8 +5,8 @@ 4.0.0 microprofile 1.0-SNAPSHOT - microprofile war + microprofile com.baeldung diff --git a/microservices-modules/pom.xml b/microservices-modules/pom.xml index 0f0baac488..40279454a0 100644 --- a/microservices-modules/pom.xml +++ b/microservices-modules/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 microservices-modules - microservices-modules pom + microservices-modules com.baeldung diff --git a/microservices-modules/rest-express/pom.xml b/microservices-modules/rest-express/pom.xml index be1c142a94..50b8802342 100644 --- a/microservices-modules/rest-express/pom.xml +++ b/microservices-modules/rest-express/pom.xml @@ -5,8 +5,8 @@ 4.0.0 rest-express 1.0.0-SNAPSHOT - rest-express jar + rest-express A Basic, MongoDB-backed Service Suite https://github.com/RestExpress/RestExpress-Scaffold + + org.mapstruct + mapstruct-processor + ${mapstruct.version} + + + org.openjdk.jmh + jmh-generator-annprocess + ${jmh.version} + + + 14 + 14 + + + + + + + 2.2.0 + 1.19.3 + + + \ No newline at end of file diff --git a/core-java-modules/core-java-lang-6/src/test/java/com/baeldung/setenvironment/SettingChildProcessEnvironmentVariableUnitTest.java b/core-java-modules/core-java-lang-7/src/test/java/com/baeldung/setenvironment/SettingChildProcessEnvironmentVariableUnitTest.java similarity index 100% rename from core-java-modules/core-java-lang-6/src/test/java/com/baeldung/setenvironment/SettingChildProcessEnvironmentVariableUnitTest.java rename to core-java-modules/core-java-lang-7/src/test/java/com/baeldung/setenvironment/SettingChildProcessEnvironmentVariableUnitTest.java diff --git a/core-java-modules/core-java-lang-6/src/test/java/com/baeldung/setenvironment/SettingDockerEnvironmentVariableUnitTest.java b/core-java-modules/core-java-lang-7/src/test/java/com/baeldung/setenvironment/SettingDockerEnvironmentVariableUnitTest.java similarity index 100% rename from core-java-modules/core-java-lang-6/src/test/java/com/baeldung/setenvironment/SettingDockerEnvironmentVariableUnitTest.java rename to core-java-modules/core-java-lang-7/src/test/java/com/baeldung/setenvironment/SettingDockerEnvironmentVariableUnitTest.java diff --git a/core-java-modules/core-java-lang-6/src/test/java/com/baeldung/setenvironment/SettingSameProcessEnvironmentVariableUnitTest.java b/core-java-modules/core-java-lang-7/src/test/java/com/baeldung/setenvironment/SettingSameProcessEnvironmentVariableUnitTest.java similarity index 100% rename from core-java-modules/core-java-lang-6/src/test/java/com/baeldung/setenvironment/SettingSameProcessEnvironmentVariableUnitTest.java rename to core-java-modules/core-java-lang-7/src/test/java/com/baeldung/setenvironment/SettingSameProcessEnvironmentVariableUnitTest.java diff --git a/core-java-modules/core-java-lang-6/src/test/java/com/baeldung/setenvironment/SettingTestcontainerVariableUnitTest.java b/core-java-modules/core-java-lang-7/src/test/java/com/baeldung/setenvironment/SettingTestcontainerVariableUnitTest.java similarity index 100% rename from core-java-modules/core-java-lang-6/src/test/java/com/baeldung/setenvironment/SettingTestcontainerVariableUnitTest.java rename to core-java-modules/core-java-lang-7/src/test/java/com/baeldung/setenvironment/SettingTestcontainerVariableUnitTest.java From 211df8196faf7f9d4d7e1615cabf726a524f5422 Mon Sep 17 00:00:00 2001 From: vunamtien Date: Thu, 25 Apr 2024 23:01:54 +0700 Subject: [PATCH 18/33] [BAEL-7767] Convert-between-ZonedDateTime-and-Date (#16490) --- .../DateAndZonedDateTimeConverter.java | 17 +++++++++++ ...DateAndZonedDateTimeConverterUnitTest.java | 28 +++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 core-java-modules/core-java-datetime-conversion-2/src/main/java/com/baeldung/convertdateandzoneddatetime/DateAndZonedDateTimeConverter.java create mode 100644 core-java-modules/core-java-datetime-conversion-2/src/test/java/com/baeldung/convertdateandzoneddatetime/DateAndZonedDateTimeConverterUnitTest.java diff --git a/core-java-modules/core-java-datetime-conversion-2/src/main/java/com/baeldung/convertdateandzoneddatetime/DateAndZonedDateTimeConverter.java b/core-java-modules/core-java-datetime-conversion-2/src/main/java/com/baeldung/convertdateandzoneddatetime/DateAndZonedDateTimeConverter.java new file mode 100644 index 0000000000..e33d200856 --- /dev/null +++ b/core-java-modules/core-java-datetime-conversion-2/src/main/java/com/baeldung/convertdateandzoneddatetime/DateAndZonedDateTimeConverter.java @@ -0,0 +1,17 @@ +package com.baeldung.convertdateandzoneddatetime; + +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.util.Date; + +public class DateAndZonedDateTimeConverter { + + public static Date convertToDate(ZonedDateTime zonedDateTime) { + return Date.from(zonedDateTime.toInstant()); + } + + public static ZonedDateTime convertToZonedDateTime(Date date, ZoneId zone) { + return date.toInstant().atZone(zone); + } + +} diff --git a/core-java-modules/core-java-datetime-conversion-2/src/test/java/com/baeldung/convertdateandzoneddatetime/DateAndZonedDateTimeConverterUnitTest.java b/core-java-modules/core-java-datetime-conversion-2/src/test/java/com/baeldung/convertdateandzoneddatetime/DateAndZonedDateTimeConverterUnitTest.java new file mode 100644 index 0000000000..3c1a9c9426 --- /dev/null +++ b/core-java-modules/core-java-datetime-conversion-2/src/test/java/com/baeldung/convertdateandzoneddatetime/DateAndZonedDateTimeConverterUnitTest.java @@ -0,0 +1,28 @@ +package com.baeldung.convertdateandzoneddatetime; + +import org.junit.jupiter.api.Test; + +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.util.Date; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class DateAndZonedDateTimeConverterUnitTest { + + @Test + public void givenZonedDateTime_whenConvertToDate_thenCorrect() { + ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("UTC")); + Date date = DateAndZonedDateTimeConverter.convertToDate(zdt); + assertEquals(Date.from(zdt.toInstant()), date); + } + + @Test + public void givenDate_whenConvertToZonedDateTime_thenCorrect() { + Date date = new Date(); + ZoneId zoneId = ZoneId.of("UTC"); + ZonedDateTime zdt = DateAndZonedDateTimeConverter.convertToZonedDateTime(date, zoneId); + assertEquals(date.toInstant().atZone(zoneId), zdt); + } + +} From 7a5cbf397125651c2aab6c70269808d6e7483ca9 Mon Sep 17 00:00:00 2001 From: Mo Helmy <135069400+BenHelmyBen@users.noreply.github.com> Date: Thu, 25 Apr 2024 18:20:58 +0200 Subject: [PATCH 19/33] This commit is related to BAEL-7854 (#16489) This commit aims to add a test class named "HashMapCharacterCountUnitTest". --- .../HashMapCharacterCountUnitTest.java | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 core-java-modules/core-java-string-operations-9/src/test/java/com/baeldung/hashmapcharactercount/HashMapCharacterCountUnitTest.java diff --git a/core-java-modules/core-java-string-operations-9/src/test/java/com/baeldung/hashmapcharactercount/HashMapCharacterCountUnitTest.java b/core-java-modules/core-java-string-operations-9/src/test/java/com/baeldung/hashmapcharactercount/HashMapCharacterCountUnitTest.java new file mode 100644 index 0000000000..7f3e390c80 --- /dev/null +++ b/core-java-modules/core-java-string-operations-9/src/test/java/com/baeldung/hashmapcharactercount/HashMapCharacterCountUnitTest.java @@ -0,0 +1,38 @@ +package com.baeldung.hashmapcharactercount; + +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static java.util.stream.Collectors.toMap; +import static org.junit.Assert.assertEquals; + +public class HashMapCharacterCountUnitTest { + String str = "abcaadcbcb"; + + @Test + public void givenString_whenUsingStreams_thenVerifyCounts() { + Map charCount = str.chars() + .boxed() + .collect(toMap( + k -> (char) k.intValue(), + v -> 1, + Integer::sum)); + + assertEquals(3, charCount.get('a').intValue()); + } + + @Test + public void givenString_whenUsingLooping_thenVerifyCounts() { + Map charCount = new HashMap<>(); + for (char c : str.toCharArray()) { + charCount.merge(c, + 1, + Integer::sum); + } + assertEquals(3, charCount.get('a').intValue()); + } + + +} From c571579a557368c4b412a6121935539fbff167ab Mon Sep 17 00:00:00 2001 From: ACHRAF TAITAI <43656331+achraftt@users.noreply.github.com> Date: Thu, 25 Apr 2024 18:36:41 +0200 Subject: [PATCH 20/33] Bael 7839 (#16426) * BAEL-7765: How to fix JsonParseException: Unexpected character (code 115) when parsing unquoted JSON in Jackson * BAEL-7839: Converting Image to BufferedImage in Java * BAEL-7839: Converting Image to BufferedImage in Java --- .../ImageToBufferedImage.java | 15 +-------------- .../ImageToBufferedImageIntegrationTest.java | 15 --------------- 2 files changed, 1 insertion(+), 29 deletions(-) diff --git a/image-processing/src/main/java/com/baeldung/imageprocessing/imagetobufferedimage/ImageToBufferedImage.java b/image-processing/src/main/java/com/baeldung/imageprocessing/imagetobufferedimage/ImageToBufferedImage.java index f3a4491adf..2be8c0b1a4 100644 --- a/image-processing/src/main/java/com/baeldung/imageprocessing/imagetobufferedimage/ImageToBufferedImage.java +++ b/image-processing/src/main/java/com/baeldung/imageprocessing/imagetobufferedimage/ImageToBufferedImage.java @@ -1,10 +1,7 @@ package com.baeldung.imageprocessing.imagetobufferedimage; -import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; -import java.io.File; -import java.io.IOException; public class ImageToBufferedImage { @@ -25,17 +22,7 @@ public class ImageToBufferedImage { if (image instanceof BufferedImage) { return (BufferedImage) image; } else { - throw new ClassCastException("Image type is not compatible with BufferedImage"); - } - } - - // Method 3: Using ImageIO Class - public BufferedImage convertUsingImageIO(String filePath) throws IOException { - try { - File file = new File(filePath); - return ImageIO.read(file); - } catch (Exception e) { - throw new IOException("Error reading image file: " + e.getMessage()); + throw new ClassCastException("Image type is not compatible with BufferedImage."); } } } diff --git a/image-processing/src/test/java/com/baeldung/image/resize/imagetobufferedimage/ImageToBufferedImageIntegrationTest.java b/image-processing/src/test/java/com/baeldung/image/resize/imagetobufferedimage/ImageToBufferedImageIntegrationTest.java index a5dd11de06..137c709d5f 100644 --- a/image-processing/src/test/java/com/baeldung/image/resize/imagetobufferedimage/ImageToBufferedImageIntegrationTest.java +++ b/image-processing/src/test/java/com/baeldung/image/resize/imagetobufferedimage/ImageToBufferedImageIntegrationTest.java @@ -50,20 +50,5 @@ public class ImageToBufferedImageIntegrationTest { Image image = new ImageIcon("src/main/resources/images/baeldung.png").getImage(); converter.convertUsingCasting(image); } - - @Test - public void whenConvertUsingImageIOWithValidFile_thenImageGeneratedWithoutError() throws IOException { - ImageToBufferedImage converter = new ImageToBufferedImage(); - BufferedImage bufferedImage = converter.convertUsingImageIO("src/main/resources/images/sampleImage.jpg"); - assertNotNull(bufferedImage); - assertEquals(image.getWidth(null), bufferedImage.getWidth()); - assertEquals(image.getHeight(null), bufferedImage.getHeight()); - } - - @Test(expected = IOException.class) - public void whenConvertUsingImageIOWithInvalidFile_thenImageGeneratedWithError() throws IOException { - ImageToBufferedImage converter = new ImageToBufferedImage(); - converter.convertUsingImageIO("invalid_file.jpg"); - } } From 3088ff9e3b361f7f3c4ade111287bbf463bbc5a0 Mon Sep 17 00:00:00 2001 From: vunamtien Date: Fri, 26 Apr 2024 04:13:36 +0700 Subject: [PATCH 21/33] [JAVA-31836] Split-or-move-core-java-string-operations-7 (#16481) --- core-java-modules/core-java-string-operations-7/README.md | 1 - core-java-modules/core-java-string-operations-9/README.md | 1 + .../CheckIfStringBuilderContainsCharUnitTest.java | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename core-java-modules/{core-java-string-operations-7 => core-java-string-operations-9}/src/test/java/com/baeldung/stringbuilderhaschar/CheckIfStringBuilderContainsCharUnitTest.java (92%) diff --git a/core-java-modules/core-java-string-operations-7/README.md b/core-java-modules/core-java-string-operations-7/README.md index 97249b1a8b..0ef528f162 100644 --- a/core-java-modules/core-java-string-operations-7/README.md +++ b/core-java-modules/core-java-string-operations-7/README.md @@ -6,7 +6,6 @@ - [Check if a String Contains a Number Value in Java](https://www.baeldung.com/java-string-number-presence) - [String’s Maximum Length in Java](https://www.baeldung.com/java-strings-maximum-length) - [Java’s String.length() and String.getBytes().length](https://www.baeldung.com/java-string-length-vs-getbytes-length) -- [Check If a Java StringBuilder Object Contains a Character](https://www.baeldung.com/java-check-stringbuilder-object-contains-character) - [Comparing One String With Multiple Values in One Expression in Java](https://www.baeldung.com/java-compare-string-multiple-values-one-expression) - [Regular Expression for Password Validation in Java](https://www.baeldung.com/java-regex-password-validation) - [Mask an Email Address and Phone Number in Java](https://www.baeldung.com/java-mask-email-address-phone-number) diff --git a/core-java-modules/core-java-string-operations-9/README.md b/core-java-modules/core-java-string-operations-9/README.md index aab4178988..a7e3f6de58 100644 --- a/core-java-modules/core-java-string-operations-9/README.md +++ b/core-java-modules/core-java-string-operations-9/README.md @@ -6,4 +6,5 @@ - [UTF-8 Validation in Java](https://www.baeldung.com/java-utf-8-validation) - [Simple Morse Code Translation in Java](https://www.baeldung.com/java-morse-code-english-translate) - [How to Determine if a String Contains Invalid Encoded Characters](https://www.baeldung.com/java-check-string-contains-invalid-encoded-characters) +- [Check If a Java StringBuilder Object Contains a Character](https://www.baeldung.com/java-check-stringbuilder-object-contains-character) - More articles: [[<-- prev]](../core-java-string-operations-8) diff --git a/core-java-modules/core-java-string-operations-7/src/test/java/com/baeldung/stringbuilderhaschar/CheckIfStringBuilderContainsCharUnitTest.java b/core-java-modules/core-java-string-operations-9/src/test/java/com/baeldung/stringbuilderhaschar/CheckIfStringBuilderContainsCharUnitTest.java similarity index 92% rename from core-java-modules/core-java-string-operations-7/src/test/java/com/baeldung/stringbuilderhaschar/CheckIfStringBuilderContainsCharUnitTest.java rename to core-java-modules/core-java-string-operations-9/src/test/java/com/baeldung/stringbuilderhaschar/CheckIfStringBuilderContainsCharUnitTest.java index 8d95b5533a..31740152e5 100644 --- a/core-java-modules/core-java-string-operations-7/src/test/java/com/baeldung/stringbuilderhaschar/CheckIfStringBuilderContainsCharUnitTest.java +++ b/core-java-modules/core-java-string-operations-9/src/test/java/com/baeldung/stringbuilderhaschar/CheckIfStringBuilderContainsCharUnitTest.java @@ -2,7 +2,7 @@ package com.baeldung.stringbuilderhaschar; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertTrue; public class CheckIfStringBuilderContainsCharUnitTest { From 0bc686a11e9698da352366111d783d2befedbe91 Mon Sep 17 00:00:00 2001 From: vunamtien Date: Fri, 26 Apr 2024 04:40:46 +0700 Subject: [PATCH 22/33] [JAVA-31848] Split-or-move-core-java-collections-5 (#16482) --- .../core-java-collections-5/README.md | 2 - .../core-java-collections-6/README.md | 3 + .../CheckIfListContainsEnumUnitTest.java | 114 ++++++++--------- .../RemoveQueueElementsUnitTest.java | 120 +++++++++--------- 4 files changed, 120 insertions(+), 119 deletions(-) rename core-java-modules/{core-java-collections-5 => core-java-collections-6}/src/test/java/com/baeldung/checkiflistcontainsenum/CheckIfListContainsEnumUnitTest.java (96%) rename core-java-modules/{core-java-collections-5 => core-java-collections-6}/src/test/java/com/baeldung/removequeueelements/RemoveQueueElementsUnitTest.java (96%) diff --git a/core-java-modules/core-java-collections-5/README.md b/core-java-modules/core-java-collections-5/README.md index e1ad221a31..1608b96775 100644 --- a/core-java-modules/core-java-collections-5/README.md +++ b/core-java-modules/core-java-collections-5/README.md @@ -7,10 +7,8 @@ - [Creating Custom Iterator in Java](https://www.baeldung.com/java-creating-custom-iterator) - [Difference Between Arrays.sort() and Collections.sort()](https://www.baeldung.com/java-arrays-collections-sort-methods) - [Skipping the First Iteration in Java](https://www.baeldung.com/java-skip-first-iteration) -- [Remove Elements From a Queue Using Loop](https://www.baeldung.com/java-remove-elements-queue) - [Intro to Vector Class in Java](https://www.baeldung.com/java-vector-guide) - [Time Complexity of Java Collections Sort in Java](https://www.baeldung.com/java-time-complexity-collections-sort) -- [Check if List Contains at Least One Enum](https://www.baeldung.com/java-list-check-enum-presence) - [Comparison of for Loops and Iterators](https://www.baeldung.com/java-for-loops-vs-iterators) - [PriorityQueue iterator() Method in Java](https://www.baeldung.com/java-priorityqueue-iterator) - [Immutable vs Unmodifiable Collection in Java](https://www.baeldung.com/java-collection-immutable-unmodifiable-differences) diff --git a/core-java-modules/core-java-collections-6/README.md b/core-java-modules/core-java-collections-6/README.md index 7165bedce3..88356ca4d3 100644 --- a/core-java-modules/core-java-collections-6/README.md +++ b/core-java-modules/core-java-collections-6/README.md @@ -4,4 +4,7 @@ ### Relevant Articles: - [Iterator vs forEach() in Java](https://www.baeldung.com/java-iterator-vs-foreach) +- [Remove Elements From a Queue Using Loop](https://www.baeldung.com/java-remove-elements-queue) +- [Check if List Contains at Least One Enum](https://www.baeldung.com/java-list-check-enum-presence) + - More articles: [[<-- prev]](/core-java-modules/core-java-collections-5) diff --git a/core-java-modules/core-java-collections-5/src/test/java/com/baeldung/checkiflistcontainsenum/CheckIfListContainsEnumUnitTest.java b/core-java-modules/core-java-collections-6/src/test/java/com/baeldung/checkiflistcontainsenum/CheckIfListContainsEnumUnitTest.java similarity index 96% rename from core-java-modules/core-java-collections-5/src/test/java/com/baeldung/checkiflistcontainsenum/CheckIfListContainsEnumUnitTest.java rename to core-java-modules/core-java-collections-6/src/test/java/com/baeldung/checkiflistcontainsenum/CheckIfListContainsEnumUnitTest.java index 0b9fd356e2..2d87d0ca47 100644 --- a/core-java-modules/core-java-collections-5/src/test/java/com/baeldung/checkiflistcontainsenum/CheckIfListContainsEnumUnitTest.java +++ b/core-java-modules/core-java-collections-6/src/test/java/com/baeldung/checkiflistcontainsenum/CheckIfListContainsEnumUnitTest.java @@ -1,57 +1,57 @@ -package com.baeldung.checkiflistcontainsenum; - -import org.junit.Assert; -import org.junit.Test; - -import java.util.*; - -public class CheckIfListContainsEnumUnitTest { - private final List> data = new ArrayList<>(); - - public CheckIfListContainsEnumUnitTest() { - Map map = new HashMap<>(); - map.put("Name", "John"); - map.put("Age", 25); - map.put("Position", Position.DEVELOPER); - - data.add(map); - } - - @Test - public void givenDataList_whenUsingLoop_thenCheckIfListContainsEnum() { - boolean containsEnumValue = false; - - for (Map entry : data) { - Object positionValue = entry.get("Position"); - if (Arrays.asList(Position.values()).contains(positionValue)) { - containsEnumValue = true; - break; - } - } - - Assert.assertTrue(containsEnumValue); - } - - @Test - public void givenDataList_whenUsingStream_thenCheckIfListContainsEnum() { - boolean containsEnumValue = data.stream() - .map(entry -> entry.get("Position")) - .anyMatch(position -> Arrays.asList(Position.values()).contains(position)); - - Assert.assertTrue(containsEnumValue); - } - - @Test - public void givenDataList_whenUsingDisjointMethod_thenCheckIfListContainsEnum() { - List positionValues = data.stream() - .map(entry -> (Position) entry.get("Position")) - .toList(); - - boolean containsEnumValue = !Collections.disjoint(Arrays.asList(Position.values()), positionValues); - Assert.assertTrue(containsEnumValue); - } - - public enum Position { - DEVELOPER, MANAGER, ANALYST - } -} +package com.baeldung.checkiflistcontainsenum; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.*; + +public class CheckIfListContainsEnumUnitTest { + private final List> data = new ArrayList<>(); + + public CheckIfListContainsEnumUnitTest() { + Map map = new HashMap<>(); + map.put("Name", "John"); + map.put("Age", 25); + map.put("Position", Position.DEVELOPER); + + data.add(map); + } + + @Test + public void givenDataList_whenUsingLoop_thenCheckIfListContainsEnum() { + boolean containsEnumValue = false; + + for (Map entry : data) { + Object positionValue = entry.get("Position"); + if (Arrays.asList(Position.values()).contains(positionValue)) { + containsEnumValue = true; + break; + } + } + + Assert.assertTrue(containsEnumValue); + } + + @Test + public void givenDataList_whenUsingStream_thenCheckIfListContainsEnum() { + boolean containsEnumValue = data.stream() + .map(entry -> entry.get("Position")) + .anyMatch(position -> Arrays.asList(Position.values()).contains(position)); + + Assert.assertTrue(containsEnumValue); + } + + @Test + public void givenDataList_whenUsingDisjointMethod_thenCheckIfListContainsEnum() { + List positionValues = data.stream() + .map(entry -> (Position) entry.get("Position")) + .toList(); + + boolean containsEnumValue = !Collections.disjoint(Arrays.asList(Position.values()), positionValues); + Assert.assertTrue(containsEnumValue); + } + + public enum Position { + DEVELOPER, MANAGER, ANALYST + } +} diff --git a/core-java-modules/core-java-collections-5/src/test/java/com/baeldung/removequeueelements/RemoveQueueElementsUnitTest.java b/core-java-modules/core-java-collections-6/src/test/java/com/baeldung/removequeueelements/RemoveQueueElementsUnitTest.java similarity index 96% rename from core-java-modules/core-java-collections-5/src/test/java/com/baeldung/removequeueelements/RemoveQueueElementsUnitTest.java rename to core-java-modules/core-java-collections-6/src/test/java/com/baeldung/removequeueelements/RemoveQueueElementsUnitTest.java index 38fdc58099..b574853d50 100644 --- a/core-java-modules/core-java-collections-5/src/test/java/com/baeldung/removequeueelements/RemoveQueueElementsUnitTest.java +++ b/core-java-modules/core-java-collections-6/src/test/java/com/baeldung/removequeueelements/RemoveQueueElementsUnitTest.java @@ -1,60 +1,60 @@ -package com.baeldung.removequeueelements; - -import org.junit.Test; - -import java.util.LinkedList; -import java.util.Queue; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; - -public class RemoveQueueElementsUnitTest { - @Test - public void givenQueueWithEvenAndOddNumbers_whenRemovingEvenNumbers_thenOddNumbersRemain() { - Queue queue = new LinkedList<>(); - Queue oddElementsQueue = new LinkedList<>(); - queue.add(1); - queue.add(2); - queue.add(3); - queue.add(4); - queue.add(5); - - while (queue.peek() != null) { - int element = queue.remove(); - if (element % 2 != 0) { - oddElementsQueue.add(element); - } - } - - assertEquals(3, oddElementsQueue.size()); - assertTrue(oddElementsQueue.contains(1)); - assertTrue(oddElementsQueue.contains(3)); - assertTrue(oddElementsQueue.contains(5)); - } - - @Test - public void givenStringQueue_whenRemovingStringsThatStartWithA_thenStringElementsRemain() { - Queue queue = new LinkedList<>(); - Queue stringElementsQueue = new LinkedList<>(); - queue.add("Apple"); - queue.add("Banana"); - queue.add("Orange"); - queue.add("Grape"); - queue.add("Mango"); - - - while (queue.peek() != null) { - String element = queue.remove(); - if (!element.startsWith("A")) { - stringElementsQueue.add(element); - } - } - - assertEquals(4, stringElementsQueue.size()); - assertTrue(stringElementsQueue.contains("Banana")); - assertTrue(stringElementsQueue.contains("Orange")); - assertTrue(stringElementsQueue.contains("Grape")); - assertTrue(stringElementsQueue.contains("Mango")); - } - -} +package com.baeldung.removequeueelements; + +import org.junit.Test; + +import java.util.LinkedList; +import java.util.Queue; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class RemoveQueueElementsUnitTest { + @Test + public void givenQueueWithEvenAndOddNumbers_whenRemovingEvenNumbers_thenOddNumbersRemain() { + Queue queue = new LinkedList<>(); + Queue oddElementsQueue = new LinkedList<>(); + queue.add(1); + queue.add(2); + queue.add(3); + queue.add(4); + queue.add(5); + + while (queue.peek() != null) { + int element = queue.remove(); + if (element % 2 != 0) { + oddElementsQueue.add(element); + } + } + + assertEquals(3, oddElementsQueue.size()); + assertTrue(oddElementsQueue.contains(1)); + assertTrue(oddElementsQueue.contains(3)); + assertTrue(oddElementsQueue.contains(5)); + } + + @Test + public void givenStringQueue_whenRemovingStringsThatStartWithA_thenStringElementsRemain() { + Queue queue = new LinkedList<>(); + Queue stringElementsQueue = new LinkedList<>(); + queue.add("Apple"); + queue.add("Banana"); + queue.add("Orange"); + queue.add("Grape"); + queue.add("Mango"); + + + while (queue.peek() != null) { + String element = queue.remove(); + if (!element.startsWith("A")) { + stringElementsQueue.add(element); + } + } + + assertEquals(4, stringElementsQueue.size()); + assertTrue(stringElementsQueue.contains("Banana")); + assertTrue(stringElementsQueue.contains("Orange")); + assertTrue(stringElementsQueue.contains("Grape")); + assertTrue(stringElementsQueue.contains("Mango")); + } + +} From 4293cfdd975337a923ebb3c758585ab7bed1f53c Mon Sep 17 00:00:00 2001 From: timis1 <12120641+timis1@users.noreply.github.com> Date: Fri, 26 Apr 2024 10:15:18 +0300 Subject: [PATCH 23/33] JAVA-34111 Revert the changes done in spring-data-jpa-simple module (#16493) --- .../spring-data-jpa-repo-2/README.md | 2 +- .../spring-data-jpa-repo-2/pom.xml | 4 ---- .../spring-data-jpa-repo-3/README.md | 1 - .../spring-data-jpa-repo-3/pom.xml | 5 ----- .../spring-data-jpa-repo/README.md | 1 - .../com/baeldung/simple/service/IFooService.java | 7 ------- .../spring-data-jpa-simple/README.md | 5 ++++- .../spring-data-jpa-simple/pom.xml | 10 ++++++++++ .../PaginationSortingApplication.java | 0 .../config/PersistenceProductConfiguration.java | 0 .../jpa/paginationsorting/model/Product.java | 0 .../repository/ProductRepository.java | 0 .../jpa/schemageneration/AccountApplication.java | 0 .../jpa/schemageneration/HibernateUtil.java | 0 .../jpa/schemageneration/model/Account.java | 0 .../schemageneration/model/AccountSetting.java | 0 .../repository/AccountRepository.java | 0 .../repository/AccountSettingRepository.java | 0 .../com/baeldung/jpa}/simple/JpaApplication.java | 4 ++-- .../jpa}/simple/config/PersistenceConfig.java | 4 ++-- .../com/baeldung/jpa/simple/model}/Book.java | 2 +- .../java/com/baeldung/jpa/simple/model}/Foo.java | 2 +- .../com/baeldung/jpa/simple/model}/User.java | 2 +- .../simple/repository/BookListRepository.java | 4 ++-- .../BookPagingAndSortingRepository.java | 4 ++-- .../baeldung/jpa}/simple/repository/IFooDAO.java | 4 ++-- .../jpa}/simple/repository/UserRepository.java | 4 ++-- .../simple/repository/UserRepositoryCustom.java | 4 ++-- .../repository/UserRepositoryCustomImpl.java | 4 ++-- .../baeldung/jpa}/simple/service/FooService.java | 6 +++--- .../baeldung/jpa/simple/service/IFooService.java | 7 +++++++ .../resources/pagination-sorting-db.properties | 0 .../main/resources/schema-generation.properties | 0 .../ProductRepositoryIntegrationTest.java | 0 .../BookListRepositoryIntegrationTest.java | 11 ++++++----- ...agingAndSortingRepositoryIntegrationTest.java | 16 +++++++++------- .../jpa}/simple/FooServiceIntegrationTest.java | 6 +++--- .../simple/UserRepositoryIntegrationTest.java | 6 +++--- 38 files changed, 65 insertions(+), 60 deletions(-) delete mode 100644 persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/simple/service/IFooService.java rename persistence-modules/{spring-data-jpa-repo-3 => spring-data-jpa-simple}/src/main/java/com/baeldung/jpa/paginationsorting/PaginationSortingApplication.java (100%) rename persistence-modules/{spring-data-jpa-repo-3 => spring-data-jpa-simple}/src/main/java/com/baeldung/jpa/paginationsorting/config/PersistenceProductConfiguration.java (100%) rename persistence-modules/{spring-data-jpa-repo-3 => spring-data-jpa-simple}/src/main/java/com/baeldung/jpa/paginationsorting/model/Product.java (100%) rename persistence-modules/{spring-data-jpa-repo-3 => spring-data-jpa-simple}/src/main/java/com/baeldung/jpa/paginationsorting/repository/ProductRepository.java (100%) rename persistence-modules/{spring-data-jpa-repo-2 => spring-data-jpa-simple}/src/main/java/com/baeldung/jpa/schemageneration/AccountApplication.java (100%) rename persistence-modules/{spring-data-jpa-repo-2 => spring-data-jpa-simple}/src/main/java/com/baeldung/jpa/schemageneration/HibernateUtil.java (100%) rename persistence-modules/{spring-data-jpa-repo-2 => spring-data-jpa-simple}/src/main/java/com/baeldung/jpa/schemageneration/model/Account.java (100%) rename persistence-modules/{spring-data-jpa-repo-2 => spring-data-jpa-simple}/src/main/java/com/baeldung/jpa/schemageneration/model/AccountSetting.java (100%) rename persistence-modules/{spring-data-jpa-repo-2 => spring-data-jpa-simple}/src/main/java/com/baeldung/jpa/schemageneration/repository/AccountRepository.java (100%) rename persistence-modules/{spring-data-jpa-repo-2 => spring-data-jpa-simple}/src/main/java/com/baeldung/jpa/schemageneration/repository/AccountSettingRepository.java (100%) rename persistence-modules/{spring-data-jpa-repo/src/main/java/com/baeldung => spring-data-jpa-simple/src/main/java/com/baeldung/jpa}/simple/JpaApplication.java (79%) rename persistence-modules/{spring-data-jpa-repo/src/main/java/com/baeldung => spring-data-jpa-simple/src/main/java/com/baeldung/jpa}/simple/config/PersistenceConfig.java (96%) rename persistence-modules/{spring-data-jpa-repo/src/main/java/com/baeldung/simple/entity => spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/model}/Book.java (96%) rename persistence-modules/{spring-data-jpa-repo/src/main/java/com/baeldung/simple/entity => spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/model}/Foo.java (97%) rename persistence-modules/{spring-data-jpa-repo/src/main/java/com/baeldung/simple/entity => spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/model}/User.java (97%) rename persistence-modules/{spring-data-jpa-repo/src/main/java/com/baeldung => spring-data-jpa-simple/src/main/java/com/baeldung/jpa}/simple/repository/BookListRepository.java (76%) rename persistence-modules/{spring-data-jpa-repo/src/main/java/com/baeldung => spring-data-jpa-simple/src/main/java/com/baeldung/jpa}/simple/repository/BookPagingAndSortingRepository.java (84%) rename persistence-modules/{spring-data-jpa-repo/src/main/java/com/baeldung => spring-data-jpa-simple/src/main/java/com/baeldung/jpa}/simple/repository/IFooDAO.java (82%) rename persistence-modules/{spring-data-jpa-repo/src/main/java/com/baeldung => spring-data-jpa-simple/src/main/java/com/baeldung/jpa}/simple/repository/UserRepository.java (94%) rename persistence-modules/{spring-data-jpa-repo/src/main/java/com/baeldung => spring-data-jpa-simple/src/main/java/com/baeldung/jpa}/simple/repository/UserRepositoryCustom.java (77%) rename persistence-modules/{spring-data-jpa-repo/src/main/java/com/baeldung => spring-data-jpa-simple/src/main/java/com/baeldung/jpa}/simple/repository/UserRepositoryCustomImpl.java (95%) rename persistence-modules/{spring-data-jpa-repo/src/main/java/com/baeldung => spring-data-jpa-simple/src/main/java/com/baeldung/jpa}/simple/service/FooService.java (68%) create mode 100644 persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/service/IFooService.java rename persistence-modules/{spring-data-jpa-repo-3 => spring-data-jpa-simple}/src/main/resources/pagination-sorting-db.properties (100%) rename persistence-modules/{spring-data-jpa-repo-2 => spring-data-jpa-simple}/src/main/resources/schema-generation.properties (100%) rename persistence-modules/{spring-data-jpa-repo-3 => spring-data-jpa-simple}/src/test/java/com/baeldung/jpa/paginationsorting/ProductRepositoryIntegrationTest.java (100%) rename persistence-modules/{spring-data-jpa-repo/src/test/java/com/baeldung => spring-data-jpa-simple/src/test/java/com/baeldung/jpa}/simple/BookListRepositoryIntegrationTest.java (77%) rename persistence-modules/{spring-data-jpa-repo/src/test/java/com/baeldung => spring-data-jpa-simple/src/test/java/com/baeldung/jpa}/simple/BookPagingAndSortingRepositoryIntegrationTest.java (75%) rename persistence-modules/{spring-data-jpa-repo/src/test/java/com/baeldung => spring-data-jpa-simple/src/test/java/com/baeldung/jpa}/simple/FooServiceIntegrationTest.java (86%) rename persistence-modules/{spring-data-jpa-repo/src/test/java/com/baeldung => spring-data-jpa-simple/src/test/java/com/baeldung/jpa}/simple/UserRepositoryIntegrationTest.java (97%) diff --git a/persistence-modules/spring-data-jpa-repo-2/README.md b/persistence-modules/spring-data-jpa-repo-2/README.md index 7ce69dbc4c..d377104c02 100644 --- a/persistence-modules/spring-data-jpa-repo-2/README.md +++ b/persistence-modules/spring-data-jpa-repo-2/README.md @@ -8,5 +8,5 @@ - [Differences Between Spring Data JPA findFirst() and findTop()](https://www.baeldung.com/spring-data-jpa-findfirst-vs-findtop) - [Difference Between findBy and findAllBy in Spring Data JPA](https://www.baeldung.com/spring-data-jpa-find-by-vs-find-all-by) - [Calling Stored Procedures from Spring Data JPA Repositories](https://www.baeldung.com/spring-data-jpa-stored-procedures) -- [Generate Database Schema with Spring Data JPA](https://www.baeldung.com/spring-data-jpa-generate-db-schema) + - More articles: [[<-- prev]](../spring-data-jpa-repo) diff --git a/persistence-modules/spring-data-jpa-repo-2/pom.xml b/persistence-modules/spring-data-jpa-repo-2/pom.xml index d48ecebb98..12519088b5 100644 --- a/persistence-modules/spring-data-jpa-repo-2/pom.xml +++ b/persistence-modules/spring-data-jpa-repo-2/pom.xml @@ -58,10 +58,6 @@ ${querydsl.version} provided - - org.hibernate.orm - hibernate-ant - diff --git a/persistence-modules/spring-data-jpa-repo-3/README.md b/persistence-modules/spring-data-jpa-repo-3/README.md index 4d793d9fee..dbd7b67e2c 100644 --- a/persistence-modules/spring-data-jpa-repo-3/README.md +++ b/persistence-modules/spring-data-jpa-repo-3/README.md @@ -9,5 +9,4 @@ This module contains articles about Spring Data JPA. - [Difference Between findBy and findOneBy in Spring Data JPA](https://www.baeldung.com/spring-data-jpa-findby-vs-findoneby) - [How to Get Last Record in Spring Data JPA](https://www.baeldung.com/spring-data-jpa-last-record) - [Refresh and Fetch an Entity After Save in JPA](https://www.baeldung.com/spring-data-jpa-refresh-fetch-entity-after-save) -- [Pagination and Sorting using Spring Data JPA](https://www.baeldung.com/spring-data-jpa-pagination-sorting) - More articles: [[<-- prev]](../spring-data-jpa-repo-2) diff --git a/persistence-modules/spring-data-jpa-repo-3/pom.xml b/persistence-modules/spring-data-jpa-repo-3/pom.xml index ee4a1ce29c..5c57606d31 100644 --- a/persistence-modules/spring-data-jpa-repo-3/pom.xml +++ b/persistence-modules/spring-data-jpa-repo-3/pom.xml @@ -32,11 +32,6 @@ spring-boot-starter-test test - - com.google.guava - guava - ${guava.version} - com.baeldung.spring.data.jpa.naturalid.Application diff --git a/persistence-modules/spring-data-jpa-repo/README.md b/persistence-modules/spring-data-jpa-repo/README.md index c6c82c5846..ffbd57d7f6 100644 --- a/persistence-modules/spring-data-jpa-repo/README.md +++ b/persistence-modules/spring-data-jpa-repo/README.md @@ -3,7 +3,6 @@ This module contains articles about repositories in Spring Data JPA ### Relevant Articles: -- [Introduction to Spring Data JPA](https://www.baeldung.com/the-persistence-layer-with-spring-data-jpa) - [Case Insensitive Queries with Spring Data Repository](https://www.baeldung.com/spring-data-case-insensitive-queries) - [Spring Data – CrudRepository save() Method](https://www.baeldung.com/spring-data-crud-repository-save) - [Spring Data JPA – Adding a Method in All Repositories](https://www.baeldung.com/spring-data-jpa-method-in-all-repositories) diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/simple/service/IFooService.java b/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/simple/service/IFooService.java deleted file mode 100644 index 867b0770a0..0000000000 --- a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/simple/service/IFooService.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.baeldung.simple.service; - -import com.baeldung.simple.entity.Foo; - -public interface IFooService { - Foo create(Foo foo); -} \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-simple/README.md b/persistence-modules/spring-data-jpa-simple/README.md index 4b09ffac28..4d96acb0f4 100644 --- a/persistence-modules/spring-data-jpa-simple/README.md +++ b/persistence-modules/spring-data-jpa-simple/README.md @@ -8,10 +8,13 @@ This module contains articles about Spring Data JPA that are also part of an Ebo Since this is a module tied to an e-book, it should **not** be moved or used to store the code for any further article. ### Relevant Articles +- [Introduction to Spring Data JPA](https://www.baeldung.com/the-persistence-layer-with-spring-data-jpa) - [Customizing the Result of JPA Queries with Aggregation Functions](https://www.baeldung.com/jpa-queries-custom-result-with-aggregation-functions) - [CrudRepository, JpaRepository, and PagingAndSortingRepository in Spring Data](https://www.baeldung.com/spring-data-repositories) - [New CRUD Repository Interfaces in Spring Data 3](https://www.baeldung.com/spring-data-3-crud-repository-interfaces) - [Derived Query Methods in Spring Data JPA Repositories](https://www.baeldung.com/spring-data-derived-queries) - [Spring Data JPA @Query](https://www.baeldung.com/spring-data-jpa-query) - [Spring Data JPA Projections](https://www.baeldung.com/spring-data-jpa-projections) -- [Spring Data JPA @Modifying Annotation](https://www.baeldung.com/spring-data-jpa-modifying-annotation) \ No newline at end of file +- [Spring Data JPA @Modifying Annotation](https://www.baeldung.com/spring-data-jpa-modifying-annotation) +- [Generate Database Schema with Spring Data JPA](https://www.baeldung.com/spring-data-jpa-generate-db-schema) +- [Pagination and Sorting using Spring Data JPA](https://www.baeldung.com/spring-data-jpa-pagination-sorting) \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-simple/pom.xml b/persistence-modules/spring-data-jpa-simple/pom.xml index 300815bca8..dc59b1fd22 100644 --- a/persistence-modules/spring-data-jpa-simple/pom.xml +++ b/persistence-modules/spring-data-jpa-simple/pom.xml @@ -43,11 +43,21 @@ org.springframework spring-oxm + + com.google.guava + guava + ${guava.version} + jakarta.xml.bind jakarta.xml.bind-api ${jakarta.xml.bind.version} + + org.hibernate.orm + hibernate-ant + ${hibernate.version} + diff --git a/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/jpa/paginationsorting/PaginationSortingApplication.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/paginationsorting/PaginationSortingApplication.java similarity index 100% rename from persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/jpa/paginationsorting/PaginationSortingApplication.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/paginationsorting/PaginationSortingApplication.java diff --git a/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/jpa/paginationsorting/config/PersistenceProductConfiguration.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/paginationsorting/config/PersistenceProductConfiguration.java similarity index 100% rename from persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/jpa/paginationsorting/config/PersistenceProductConfiguration.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/paginationsorting/config/PersistenceProductConfiguration.java diff --git a/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/jpa/paginationsorting/model/Product.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/paginationsorting/model/Product.java similarity index 100% rename from persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/jpa/paginationsorting/model/Product.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/paginationsorting/model/Product.java diff --git a/persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/jpa/paginationsorting/repository/ProductRepository.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/paginationsorting/repository/ProductRepository.java similarity index 100% rename from persistence-modules/spring-data-jpa-repo-3/src/main/java/com/baeldung/jpa/paginationsorting/repository/ProductRepository.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/paginationsorting/repository/ProductRepository.java diff --git a/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/jpa/schemageneration/AccountApplication.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/schemageneration/AccountApplication.java similarity index 100% rename from persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/jpa/schemageneration/AccountApplication.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/schemageneration/AccountApplication.java diff --git a/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/jpa/schemageneration/HibernateUtil.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/schemageneration/HibernateUtil.java similarity index 100% rename from persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/jpa/schemageneration/HibernateUtil.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/schemageneration/HibernateUtil.java diff --git a/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/jpa/schemageneration/model/Account.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/schemageneration/model/Account.java similarity index 100% rename from persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/jpa/schemageneration/model/Account.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/schemageneration/model/Account.java diff --git a/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/jpa/schemageneration/model/AccountSetting.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/schemageneration/model/AccountSetting.java similarity index 100% rename from persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/jpa/schemageneration/model/AccountSetting.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/schemageneration/model/AccountSetting.java diff --git a/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/jpa/schemageneration/repository/AccountRepository.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/schemageneration/repository/AccountRepository.java similarity index 100% rename from persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/jpa/schemageneration/repository/AccountRepository.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/schemageneration/repository/AccountRepository.java diff --git a/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/jpa/schemageneration/repository/AccountSettingRepository.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/schemageneration/repository/AccountSettingRepository.java similarity index 100% rename from persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/jpa/schemageneration/repository/AccountSettingRepository.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/schemageneration/repository/AccountSettingRepository.java diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/simple/JpaApplication.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/JpaApplication.java similarity index 79% rename from persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/simple/JpaApplication.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/JpaApplication.java index ec7ac3ed1e..39efef714d 100644 --- a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/simple/JpaApplication.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/JpaApplication.java @@ -1,11 +1,11 @@ -package com.baeldung.simple; +package com.baeldung.jpa.simple; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; @SpringBootApplication -@EnableJpaRepositories("com.baeldung.simple.repository") +@EnableJpaRepositories("com.baeldung.jpa.simple.repository") public class JpaApplication { public static void main(String[] args) { diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/simple/config/PersistenceConfig.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/config/PersistenceConfig.java similarity index 96% rename from persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/simple/config/PersistenceConfig.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/config/PersistenceConfig.java index 44aea6a620..b142933240 100644 --- a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/simple/config/PersistenceConfig.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/config/PersistenceConfig.java @@ -1,4 +1,4 @@ -package com.baeldung.simple.config; +package com.baeldung.jpa.simple.config; import java.util.Properties; @@ -32,7 +32,7 @@ public class PersistenceConfig { public LocalContainerEntityManagerFactoryBean entityManagerFactory() { final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); em.setDataSource(dataSource()); - em.setPackagesToScan("com.baeldung.simple.entity"); + em.setPackagesToScan("com.baeldung.jpa.simple.model"); final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); em.setJpaVendorAdapter(vendorAdapter); diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/simple/entity/Book.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/model/Book.java similarity index 96% rename from persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/simple/entity/Book.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/model/Book.java index 1de1df9985..30e9003b2f 100644 --- a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/simple/entity/Book.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/model/Book.java @@ -1,4 +1,4 @@ -package com.baeldung.simple.entity; +package com.baeldung.jpa.simple.model; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/simple/entity/Foo.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/model/Foo.java similarity index 97% rename from persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/simple/entity/Foo.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/model/Foo.java index 3652e3633a..5cabacf389 100644 --- a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/simple/entity/Foo.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/model/Foo.java @@ -1,4 +1,4 @@ -package com.baeldung.simple.entity; +package com.baeldung.jpa.simple.model; import java.io.Serializable; diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/simple/entity/User.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/model/User.java similarity index 97% rename from persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/simple/entity/User.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/model/User.java index b902609d27..f9a2db8437 100644 --- a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/simple/entity/User.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/model/User.java @@ -1,4 +1,4 @@ -package com.baeldung.simple.entity; +package com.baeldung.jpa.simple.model; import java.time.ZonedDateTime; diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/simple/repository/BookListRepository.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/repository/BookListRepository.java similarity index 76% rename from persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/simple/repository/BookListRepository.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/repository/BookListRepository.java index 33816a0ff1..e7a781defd 100644 --- a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/simple/repository/BookListRepository.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/repository/BookListRepository.java @@ -1,11 +1,11 @@ -package com.baeldung.simple.repository; +package com.baeldung.jpa.simple.repository; import java.util.List; import org.springframework.data.repository.ListCrudRepository; import org.springframework.stereotype.Repository; -import com.baeldung.simple.entity.Book; +import com.baeldung.jpa.simple.model.Book; @Repository public interface BookListRepository extends ListCrudRepository { diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/simple/repository/BookPagingAndSortingRepository.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/repository/BookPagingAndSortingRepository.java similarity index 84% rename from persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/simple/repository/BookPagingAndSortingRepository.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/repository/BookPagingAndSortingRepository.java index b4e13d9384..b802406c1b 100644 --- a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/simple/repository/BookPagingAndSortingRepository.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/repository/BookPagingAndSortingRepository.java @@ -1,4 +1,4 @@ -package com.baeldung.simple.repository; +package com.baeldung.jpa.simple.repository; import java.util.List; @@ -7,7 +7,7 @@ import org.springframework.data.repository.ListCrudRepository; import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.stereotype.Repository; -import com.baeldung.simple.entity.Book; +import com.baeldung.jpa.simple.model.Book; @Repository public interface BookPagingAndSortingRepository extends PagingAndSortingRepository, ListCrudRepository { diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/simple/repository/IFooDAO.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/repository/IFooDAO.java similarity index 82% rename from persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/simple/repository/IFooDAO.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/repository/IFooDAO.java index f879385b62..20123c73cd 100644 --- a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/simple/repository/IFooDAO.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/repository/IFooDAO.java @@ -1,10 +1,10 @@ -package com.baeldung.simple.repository; +package com.baeldung.jpa.simple.repository; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; -import com.baeldung.simple.entity.Foo; +import com.baeldung.jpa.simple.model.Foo; public interface IFooDAO extends JpaRepository { diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/simple/repository/UserRepository.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/repository/UserRepository.java similarity index 94% rename from persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/simple/repository/UserRepository.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/repository/UserRepository.java index 930051b168..368a0bcb5b 100644 --- a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/simple/repository/UserRepository.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/repository/UserRepository.java @@ -1,4 +1,4 @@ -package com.baeldung.simple.repository; +package com.baeldung.jpa.simple.repository; import java.time.ZonedDateTime; import java.util.Collection; @@ -6,7 +6,7 @@ import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; -import com.baeldung.simple.entity.User; +import com.baeldung.jpa.simple.model.User; public interface UserRepository extends JpaRepository, UserRepositoryCustom { diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/simple/repository/UserRepositoryCustom.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/repository/UserRepositoryCustom.java similarity index 77% rename from persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/simple/repository/UserRepositoryCustom.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/repository/UserRepositoryCustom.java index 4254ab535d..e4e1a3e73b 100644 --- a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/simple/repository/UserRepositoryCustom.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/repository/UserRepositoryCustom.java @@ -1,11 +1,11 @@ -package com.baeldung.simple.repository; +package com.baeldung.jpa.simple.repository; import java.util.Collection; import java.util.List; import java.util.Set; import java.util.function.Predicate; -import com.baeldung.simple.entity.User; +import com.baeldung.jpa.simple.model.User; public interface UserRepositoryCustom { diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/simple/repository/UserRepositoryCustomImpl.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/repository/UserRepositoryCustomImpl.java similarity index 95% rename from persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/simple/repository/UserRepositoryCustomImpl.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/repository/UserRepositoryCustomImpl.java index a97a67dc2c..b702735b97 100644 --- a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/simple/repository/UserRepositoryCustomImpl.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/repository/UserRepositoryCustomImpl.java @@ -1,4 +1,4 @@ -package com.baeldung.simple.repository; +package com.baeldung.jpa.simple.repository; import java.util.ArrayList; import java.util.Collection; @@ -7,7 +7,7 @@ import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; -import com.baeldung.simple.entity.User; +import com.baeldung.jpa.simple.model.User; import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; diff --git a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/simple/service/FooService.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/service/FooService.java similarity index 68% rename from persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/simple/service/FooService.java rename to persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/service/FooService.java index aa9f48aec2..93d405c689 100644 --- a/persistence-modules/spring-data-jpa-repo/src/main/java/com/baeldung/simple/service/FooService.java +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/service/FooService.java @@ -1,10 +1,10 @@ -package com.baeldung.simple.service; +package com.baeldung.jpa.simple.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import com.baeldung.simple.entity.Foo; -import com.baeldung.simple.repository.IFooDAO; +import com.baeldung.jpa.simple.model.Foo; +import com.baeldung.jpa.simple.repository.IFooDAO; @Service public class FooService implements IFooService { diff --git a/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/service/IFooService.java b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/service/IFooService.java new file mode 100644 index 0000000000..f2950b81fb --- /dev/null +++ b/persistence-modules/spring-data-jpa-simple/src/main/java/com/baeldung/jpa/simple/service/IFooService.java @@ -0,0 +1,7 @@ +package com.baeldung.jpa.simple.service; + +import com.baeldung.jpa.simple.model.Foo; + +public interface IFooService { + Foo create(Foo foo); +} \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-repo-3/src/main/resources/pagination-sorting-db.properties b/persistence-modules/spring-data-jpa-simple/src/main/resources/pagination-sorting-db.properties similarity index 100% rename from persistence-modules/spring-data-jpa-repo-3/src/main/resources/pagination-sorting-db.properties rename to persistence-modules/spring-data-jpa-simple/src/main/resources/pagination-sorting-db.properties diff --git a/persistence-modules/spring-data-jpa-repo-2/src/main/resources/schema-generation.properties b/persistence-modules/spring-data-jpa-simple/src/main/resources/schema-generation.properties similarity index 100% rename from persistence-modules/spring-data-jpa-repo-2/src/main/resources/schema-generation.properties rename to persistence-modules/spring-data-jpa-simple/src/main/resources/schema-generation.properties diff --git a/persistence-modules/spring-data-jpa-repo-3/src/test/java/com/baeldung/jpa/paginationsorting/ProductRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/paginationsorting/ProductRepositoryIntegrationTest.java similarity index 100% rename from persistence-modules/spring-data-jpa-repo-3/src/test/java/com/baeldung/jpa/paginationsorting/ProductRepositoryIntegrationTest.java rename to persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/paginationsorting/ProductRepositoryIntegrationTest.java diff --git a/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/simple/BookListRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/simple/BookListRepositoryIntegrationTest.java similarity index 77% rename from persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/simple/BookListRepositoryIntegrationTest.java rename to persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/simple/BookListRepositoryIntegrationTest.java index abb4604588..f393e305bc 100644 --- a/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/simple/BookListRepositoryIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/simple/BookListRepositoryIntegrationTest.java @@ -1,15 +1,16 @@ -package com.baeldung.simple; +package com.baeldung.jpa.simple; + +import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.Arrays; import java.util.List; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import com.baeldung.simple.entity.Book; -import com.baeldung.simple.repository.BookListRepository; +import com.baeldung.jpa.simple.model.Book; +import com.baeldung.jpa.simple.repository.BookListRepository; @SpringBootTest(classes = JpaApplication.class) class BookListRepositoryIntegrationTest { @@ -25,6 +26,6 @@ class BookListRepositoryIntegrationTest { bookListRepository.saveAll(Arrays.asList(book1, book2, book3)); List books = bookListRepository.findBooksByAuthor("John Doe"); - Assertions.assertEquals(3, books.size()); + assertEquals(3, books.size()); } } \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/simple/BookPagingAndSortingRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/simple/BookPagingAndSortingRepositoryIntegrationTest.java similarity index 75% rename from persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/simple/BookPagingAndSortingRepositoryIntegrationTest.java rename to persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/simple/BookPagingAndSortingRepositoryIntegrationTest.java index dbf183c7a9..390308b5ba 100644 --- a/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/simple/BookPagingAndSortingRepositoryIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/simple/BookPagingAndSortingRepositoryIntegrationTest.java @@ -1,9 +1,11 @@ -package com.baeldung.simple; +package com.baeldung.jpa.simple; + +import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.Arrays; import java.util.List; -import org.junit.jupiter.api.Assertions; + import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @@ -11,8 +13,8 @@ import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; -import com.baeldung.simple.entity.Book; -import com.baeldung.simple.repository.BookPagingAndSortingRepository; +import com.baeldung.jpa.simple.model.Book; +import com.baeldung.jpa.simple.repository.BookPagingAndSortingRepository; @SpringBootTest class BookPagingAndSortingRepositoryIntegrationTest { @@ -29,8 +31,8 @@ class BookPagingAndSortingRepositoryIntegrationTest { Pageable pageable = PageRequest.of(0, 2, Sort.by("title").descending()); List books = bookPagingAndSortingRepository.findBooksByAuthor("John Miller", pageable); - Assertions.assertEquals(2, books.size()); - Assertions.assertEquals(book3.getId(), books.get(0).getId()); - Assertions.assertEquals(book2.getId(), books.get(1).getId()); + assertEquals(2, books.size()); + assertEquals(book3.getId(), books.get(0).getId()); + assertEquals(book2.getId(), books.get(1).getId()); } } \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/simple/FooServiceIntegrationTest.java b/persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/simple/FooServiceIntegrationTest.java similarity index 86% rename from persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/simple/FooServiceIntegrationTest.java rename to persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/simple/FooServiceIntegrationTest.java index 412827462d..d4a4c2a2f7 100644 --- a/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/simple/FooServiceIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/simple/FooServiceIntegrationTest.java @@ -1,4 +1,4 @@ -package com.baeldung.simple; +package com.baeldung.jpa.simple; import javax.sql.DataSource; @@ -10,8 +10,8 @@ import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; -import com.baeldung.simple.entity.Foo; -import com.baeldung.simple.service.IFooService; +import com.baeldung.jpa.simple.model.Foo; +import com.baeldung.jpa.simple.service.IFooService; @RunWith(SpringRunner.class) @ContextConfiguration(classes = { JpaApplication.class}) diff --git a/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/simple/UserRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/simple/UserRepositoryIntegrationTest.java similarity index 97% rename from persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/simple/UserRepositoryIntegrationTest.java rename to persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/simple/UserRepositoryIntegrationTest.java index fb29d9494d..c690d601e2 100644 --- a/persistence-modules/spring-data-jpa-repo/src/test/java/com/baeldung/simple/UserRepositoryIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-simple/src/test/java/com/baeldung/jpa/simple/UserRepositoryIntegrationTest.java @@ -1,4 +1,4 @@ -package com.baeldung.simple; +package com.baeldung.jpa.simple; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -14,8 +14,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit.jupiter.SpringExtension; -import com.baeldung.simple.entity.User; -import com.baeldung.simple.repository.UserRepository; +import com.baeldung.jpa.simple.model.User; +import com.baeldung.jpa.simple.repository.UserRepository; @ExtendWith(SpringExtension.class) @SpringBootTest(classes = JpaApplication.class) From 4f8c2316bb2ef4d03bc0e2cd1242d197bc630cc1 Mon Sep 17 00:00:00 2001 From: Ana Peterlic Date: Fri, 26 Apr 2024 16:40:39 +0200 Subject: [PATCH 24/33] Change int to double --- .../algorithms/integerstreammedian/MedianOfIntegerStream.java | 4 ++-- .../integerstreammedian/MedianOfIntegerStream2.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/algorithms-modules/algorithms-miscellaneous-5/src/main/java/com/baeldung/algorithms/integerstreammedian/MedianOfIntegerStream.java b/algorithms-modules/algorithms-miscellaneous-5/src/main/java/com/baeldung/algorithms/integerstreammedian/MedianOfIntegerStream.java index 9d3b699956..d3fde8a827 100644 --- a/algorithms-modules/algorithms-miscellaneous-5/src/main/java/com/baeldung/algorithms/integerstreammedian/MedianOfIntegerStream.java +++ b/algorithms-modules/algorithms-miscellaneous-5/src/main/java/com/baeldung/algorithms/integerstreammedian/MedianOfIntegerStream.java @@ -29,13 +29,13 @@ public class MedianOfIntegerStream { } double getMedian() { - int median; + double median; if (minHeap.size() < maxHeap.size()) { median = maxHeap.peek(); } else if (minHeap.size() > maxHeap.size()) { median = minHeap.peek(); } else { - median = (minHeap.peek() + maxHeap.peek()) / 2; + median = (minHeap.peek() + maxHeap.peek()) / 2.0; } return median; } diff --git a/algorithms-modules/algorithms-miscellaneous-5/src/main/java/com/baeldung/algorithms/integerstreammedian/MedianOfIntegerStream2.java b/algorithms-modules/algorithms-miscellaneous-5/src/main/java/com/baeldung/algorithms/integerstreammedian/MedianOfIntegerStream2.java index 8aa7e6f6af..a28709c2d6 100644 --- a/algorithms-modules/algorithms-miscellaneous-5/src/main/java/com/baeldung/algorithms/integerstreammedian/MedianOfIntegerStream2.java +++ b/algorithms-modules/algorithms-miscellaneous-5/src/main/java/com/baeldung/algorithms/integerstreammedian/MedianOfIntegerStream2.java @@ -25,11 +25,11 @@ public class MedianOfIntegerStream2 { } double getMedian() { - int median; + double median; if (minHeap.size() > maxHeap.size()) { median = minHeap.peek(); } else { - median = (minHeap.peek() + maxHeap.peek()) / 2; + median = (minHeap.peek() + maxHeap.peek()) / 2.0; } return median; } From bb22793bd144893bed386baa9899ea5fb9cfdb5f Mon Sep 17 00:00:00 2001 From: Harry9656 Date: Fri, 26 Apr 2024 16:57:33 +0200 Subject: [PATCH 25/33] JAVA-33989: Migrate k8s-operator to heavy profile (#16477) --- kubernetes-modules/pom.xml | 2 +- pom.xml | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/kubernetes-modules/pom.xml b/kubernetes-modules/pom.xml index 986e15b541..caa2dd4f44 100644 --- a/kubernetes-modules/pom.xml +++ b/kubernetes-modules/pom.xml @@ -17,7 +17,7 @@ k8s-admission-controller kubernetes-spring k8s-java-heap-dump - k8s-operator + diff --git a/pom.xml b/pom.xml index 4b2f8306fe..0ca592b21c 100644 --- a/pom.xml +++ b/pom.xml @@ -448,6 +448,7 @@ apache-spark jhipster-modules spring-cloud-modules/spring-cloud-azure + kubernetes-modules/k8s-operator web-modules/restx libraries-testing @@ -576,6 +577,7 @@ jhipster-modules spring-cloud-modules/spring-cloud-azure web-modules/restx + kubernetes-modules/k8s-operator From 0522022a0843b39144a539ed917ad0bc997b79ec Mon Sep 17 00:00:00 2001 From: Eugene Kovko <37694937+eukovko@users.noreply.github.com> Date: Fri, 26 Apr 2024 18:29:33 +0200 Subject: [PATCH 26/33] Bael 7892 (#16491) * BAEL-7892: Test for comparing numbers * BAEL-7892: Added a test for floating point numbers * BAEL-7892: Fix typos --- ...ringNumbersOfDifferentClassesUnitTest.java | 158 ++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 core-java-modules/core-java-numbers-7/src/test/java/com/baeldung/comparenumbers/ComparingNumbersOfDifferentClassesUnitTest.java diff --git a/core-java-modules/core-java-numbers-7/src/test/java/com/baeldung/comparenumbers/ComparingNumbersOfDifferentClassesUnitTest.java b/core-java-modules/core-java-numbers-7/src/test/java/com/baeldung/comparenumbers/ComparingNumbersOfDifferentClassesUnitTest.java new file mode 100644 index 0000000000..a196075f5a --- /dev/null +++ b/core-java-modules/core-java-numbers-7/src/test/java/com/baeldung/comparenumbers/ComparingNumbersOfDifferentClassesUnitTest.java @@ -0,0 +1,158 @@ +package com.baeldung.comparenumbers; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.stream.Stream; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.ValueSource; + +class ComparingNumbersOfDifferentClassesUnitTest { + + @ValueSource(strings = {"1", "2", "3", "4", "5"}) + @ParameterizedTest + void givenSameNumbersButDifferentPrimitives_WhenCheckEquality_ThenTheyEqual(String number) { + int integerNumber = Integer.parseInt(number); + long longNumber = Long.parseLong(number); + assertEquals(longNumber, integerNumber); + } + + @ValueSource(strings = {"1", "2", "3", "4", "5"}) + @ParameterizedTest + void givenSameNumbersButDifferentPrimitivesWithIntegerOverflow_WhenCheckEquality_ThenTheyNotEqual(String number) { + int integerNumber = Integer.MAX_VALUE + Integer.parseInt(number); + long longNumber = Integer.MAX_VALUE + Long.parseLong(number); + assertNotEquals(longNumber, integerNumber); + } + + @ValueSource(strings = {"1", "2", "3", "4", "5"}) + @ParameterizedTest + void givenSameNumbersButDifferentPrimitivesTypes_WhenCheckEquality_ThenTheyEqual(String number) { + int integerNumber = Integer.parseInt(number); + double doubleNumber = Double.parseDouble(number); + assertEquals(doubleNumber, integerNumber); + } + + @ValueSource(strings = {"1", "2", "3", "4", "5"}) + @ParameterizedTest + void givenDifferentNumbersButDifferentPrimitivesTypes_WhenCheckEquality_ThenTheyNotEqual(String number) { + int integerNumber = Integer.parseInt(number); + double doubleNumber = Double.parseDouble(number) + 0.0000000000001; + assertNotEquals(doubleNumber, integerNumber); + } + + @Test + void givenSameNumbersButDifferentPrimitivesWithLongOverflow_WhenCheckEquality_ThenTheyEqual() { + long longValue = BigInteger.valueOf(Long.MAX_VALUE) + .add(BigInteger.ONE) + .multiply(BigInteger.TWO).longValue(); + int integerValue = BigInteger.valueOf(Long.MAX_VALUE) + .add(BigInteger.ONE).intValue(); + assertThat(longValue).isEqualTo(integerValue); + } + @Test + void givenSameNumbersButDifferentPrimitivesWithDoubleOverflow_WhenCheckEquality_ThenTheyEqual() { + double firstDoubleValue = BigDecimal.valueOf(Double.MAX_VALUE).add(BigDecimal.valueOf(42)).doubleValue(); + double secondDoubleValue = BigDecimal.valueOf(Double.MAX_VALUE).doubleValue(); + assertEquals(firstDoubleValue, secondDoubleValue); + } + + @Test + void givenSameNumbersWithDoubleRoundingErrors_WhenCheckEquality_ThenTheyNotEqual() { + double doubleValue = 0.3 / 0.1; + int integerValue = 30 / 10; + assertNotEquals(doubleValue, integerValue); + } + + @ValueSource(strings = {"1", "2", "3", "4", "5"}) + @ParameterizedTest + void givenSameNumbersButDifferentWrappers_WhenCheckEquality_ThenTheyNotEqual(String number) { + Integer integerNumber = Integer.valueOf(number); + Long longNumber = Long.valueOf(number); + assertNotEquals(longNumber, integerNumber); + } + + @ValueSource(strings = {"1", "2", "3", "4", "5"}) + @ParameterizedTest + void givenSameNumbersButWrapperTypes_WhenCheckEquality_ThenTheyNotEqual(String number) { + Float floatNumber = Float.valueOf(number); + Integer integerNumber = Integer.valueOf(number); + assertNotEquals(floatNumber, integerNumber); + } + + @MethodSource("numbersWithDifferentScaleProvider") + @ParameterizedTest + void givenBigDecimalsWithDifferentScale_WhenCheckEquality_ThenTheyNotEqual(String firstNumber, + String secondNumber) { + BigDecimal firstBigDecimal = new BigDecimal(firstNumber); + BigDecimal secondBigDecimal = new BigDecimal(secondNumber); + + assertNotEquals(firstBigDecimal, secondBigDecimal); + } + + @MethodSource("numbersWithDifferentScaleProvider") + @ParameterizedTest + void givenBigDecimalsWithDifferentScale_WhenCompare_ThenTheyEqual(String firstNumber, + String secondNumber) { + BigDecimal firstBigDecimal = new BigDecimal(firstNumber); + BigDecimal secondBigDecimal = new BigDecimal(secondNumber); + + assertEquals(0, firstBigDecimal.compareTo(secondBigDecimal)); + } + + @MethodSource("numbersWithDifferentScaleProvider") + @ParameterizedTest + void givenBigDecimalsWithDifferentScale_WhenCompareWithAssertJ_ThenTheyEqual(String firstNumber, + String secondNumber) { + BigDecimal firstBigDecimal = new BigDecimal(firstNumber); + BigDecimal secondBigDecimal = new BigDecimal(secondNumber); + + assertThat(firstBigDecimal).isEqualByComparingTo(secondBigDecimal); + } + + + @MethodSource("numbersWithSameScaleProvider") + @ParameterizedTest + void givenBigDecimalsWithSameScale_WhenCheckEquality_ThenTheyEqual(String firstNumber, + String secondNumber) { + BigDecimal firstBigDecimal = new BigDecimal(firstNumber); + BigDecimal secondBigDecimal = new BigDecimal(secondNumber); + + assertEquals(firstBigDecimal, secondBigDecimal); + } + + @MethodSource("numbersWithSameScaleProvider") + @ParameterizedTest + void givenBigDecimalsWithSameScale_WhenCompare_ThenTheyEqual(String firstNumber, + String secondNumber) { + BigDecimal firstBigDecimal = new BigDecimal(firstNumber); + BigDecimal secondBigDecimal = new BigDecimal(secondNumber); + + assertEquals(0, firstBigDecimal.compareTo(secondBigDecimal)); + } + + + static Stream numbersWithDifferentScaleProvider() { + return Stream.of( + Arguments.of("0", "0.0"), Arguments.of("1", "1.0"), + Arguments.of("2", "2.0"), Arguments.of("3", "3.0"), + Arguments.of("4", "4.0"), Arguments.of("5", "5.0"), + Arguments.of("6", "6.0"), Arguments.of("7", "7.0") + ); + } + + static Stream numbersWithSameScaleProvider() { + return Stream.of( + Arguments.of("0", "0"), Arguments.of("1", "1"), + Arguments.of("2", "2"), Arguments.of("3", "3"), + Arguments.of("4", "4"), Arguments.of("5", "5"), + Arguments.of("6", "6"), Arguments.of("7", "7") + ); + } +} From 2d4598d82d0e5c36b6b725b80982e94f160c37a6 Mon Sep 17 00:00:00 2001 From: Eugene Kovko <37694937+eukovko@users.noreply.github.com> Date: Fri, 26 Apr 2024 18:41:27 +0200 Subject: [PATCH 27/33] Bael 7891 (#16494) * BAEL-7891: Test for equality vs identity * BAEL-7891: Fixed formatting * BAEL-7891: Fixed a type and a bug --- .../equalsvssame/EqualsVsSameUnitTest.java | 57 +++++++++++++++++++ .../baeldung/junit/equalsvssame/Person.java | 21 +++++++ 2 files changed, 78 insertions(+) create mode 100644 testing-modules/junit-5-basics-2/src/test/java/com/baeldung/junit/equalsvssame/EqualsVsSameUnitTest.java create mode 100644 testing-modules/junit-5-basics-2/src/test/java/com/baeldung/junit/equalsvssame/Person.java diff --git a/testing-modules/junit-5-basics-2/src/test/java/com/baeldung/junit/equalsvssame/EqualsVsSameUnitTest.java b/testing-modules/junit-5-basics-2/src/test/java/com/baeldung/junit/equalsvssame/EqualsVsSameUnitTest.java new file mode 100644 index 0000000000..2019f44185 --- /dev/null +++ b/testing-modules/junit-5-basics-2/src/test/java/com/baeldung/junit/equalsvssame/EqualsVsSameUnitTest.java @@ -0,0 +1,57 @@ +package com.baeldung.junit.equalsvssame; + + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotSame; +import static org.junit.jupiter.api.Assertions.assertSame; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +class EqualsVsSameUnitTest { + + @ParameterizedTest + @ValueSource(strings = {"Hello", "World"}) + void givenAString_WhenCompare_ThenItEqualsAndSame(String string) { + assertEquals(string, string); + assertSame(string, string); + } + + public boolean equals(Object obj) { + return (this == obj); + } + + @ParameterizedTest + @ValueSource(strings = {"Hello", "World"}) + void givenAStrings_WhenCompareNewStrings_ThenItEqualsButNotSame(String string) { + assertEquals(new String(string), new String(string)); + assertNotSame(new String(string), new String(string)); + } + + @ParameterizedTest + @ValueSource(strings = {"Hello", "World"}) + void givenAString_WhenCompareInJava_ThenItEqualsAndSame(String string) { + assertTrue(string.equals(string)); + assertTrue(string == string); + } + + @ParameterizedTest + @ValueSource(strings = {"Hello", "World"}) + void givenAStrings_WhenCompareNewStringsInJava_ThenItEqualsButNotSame(String string) { + assertTrue(new String(string).equals(new String(string))); + assertFalse(new String(string) == new String(string)); + } + + @Test + void givePeople_WhenCompareWithoutOverridingEquals_TheyNotEqual() { + Person firstPerson = new Person("John", "Doe"); + Person secondPerson = new Person("John", "Doe"); + assertNotEquals(firstPerson, secondPerson); + } + + +} diff --git a/testing-modules/junit-5-basics-2/src/test/java/com/baeldung/junit/equalsvssame/Person.java b/testing-modules/junit-5-basics-2/src/test/java/com/baeldung/junit/equalsvssame/Person.java new file mode 100644 index 0000000000..2c0e0a34d8 --- /dev/null +++ b/testing-modules/junit-5-basics-2/src/test/java/com/baeldung/junit/equalsvssame/Person.java @@ -0,0 +1,21 @@ +package com.baeldung.junit.equalsvssame; + +public class Person { + + private final String firstName; + private final String lastName; + + public Person(String firstName, String lastName) { + this.firstName = firstName; + this.lastName = lastName; + } + + public String getFirstName() { + return firstName; + } + + public String getLastName() { + return lastName; + } +} + From 55e3ff793ee8b2223fe1e6b7c94655e1b763045b Mon Sep 17 00:00:00 2001 From: Eugene Kovko <37694937+eukovko@users.noreply.github.com> Date: Fri, 26 Apr 2024 18:42:44 +0200 Subject: [PATCH 28/33] Bael 7882 (#16500) * BAEL-7882: Test for finding the index of the smallest number * BAEL-7882: Added new test cases * BAEL-7882: Added an example with Apache Commons --- .../pom.xml | 8 ++ .../SmallestElementIndexUnitTest.java | 132 ++++++++++++++++++ 2 files changed, 140 insertions(+) create mode 100644 core-java-modules/core-java-arrays-operations-basic-2/src/test/java/com/baeldung/array/smallestindex/SmallestElementIndexUnitTest.java diff --git a/core-java-modules/core-java-arrays-operations-basic-2/pom.xml b/core-java-modules/core-java-arrays-operations-basic-2/pom.xml index 354da6d7ff..27ebc9166b 100644 --- a/core-java-modules/core-java-arrays-operations-basic-2/pom.xml +++ b/core-java-modules/core-java-arrays-operations-basic-2/pom.xml @@ -13,4 +13,12 @@ 0.0.1-SNAPSHOT + + + org.apache.commons + commons-lang3 + 3.14.0 + + + \ No newline at end of file diff --git a/core-java-modules/core-java-arrays-operations-basic-2/src/test/java/com/baeldung/array/smallestindex/SmallestElementIndexUnitTest.java b/core-java-modules/core-java-arrays-operations-basic-2/src/test/java/com/baeldung/array/smallestindex/SmallestElementIndexUnitTest.java new file mode 100644 index 0000000000..9f8299b9e5 --- /dev/null +++ b/core-java-modules/core-java-arrays-operations-basic-2/src/test/java/com/baeldung/array/smallestindex/SmallestElementIndexUnitTest.java @@ -0,0 +1,132 @@ +package com.baeldung.array.smallestindex; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; +import org.apache.commons.lang3.ArrayUtils; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +class SmallestElementIndexUnitTest { + + @ParameterizedTest + @MethodSource("primitiveProvider") + void givenArray_whenUsingForLoop_thenGetCorrectResult(int[] array, int expectedIndex) { + int minValue = Integer.MAX_VALUE; + int minIndex = -1; + for (int i = 0; i < array.length; i++) { + if (array[i] < minValue) { + minValue = array[i]; + minIndex = i; + } + } + assertThat(minIndex).isEqualTo(expectedIndex); + } + + @ParameterizedTest + @MethodSource("primitiveProvider") + void givenArray_whenUsingForLoopAndLookForIndex_thenGetCorrectResult(int[] array, int expectedIndex) { + int minValue = Integer.MAX_VALUE; + for (int number : array) { + if (number < minValue) { + minValue = number; + } + } + int minIndex = -1; + for (int i = 0; i < array.length; i++) { + if (array[i] == minValue) { + minIndex = i; + break; + } + } + assertThat(minIndex).isEqualTo(expectedIndex); + } + + @ParameterizedTest + @MethodSource("primitiveProvider") + void givenArray_whenUsingIntStreamAndLookForIndex_thenGetCorrectResult(int[] array, int expectedIndex) { + int minValue = Arrays.stream(array).min().orElse(Integer.MAX_VALUE); + int minIndex = -1; + for (int i = 0; i < array.length; i++) { + if (array[i] == minValue) { + minIndex = i; + break; + } + } + assertThat(minIndex).isEqualTo(expectedIndex); + } + + @ParameterizedTest + @MethodSource("primitiveProvider") + void givenArray_whenUsingIntStreamAndLookForIndexWithIntStream_thenGetCorrectResult(int[] array, int expectedIndex) { + int minValue = Arrays.stream(array).min().orElse(Integer.MAX_VALUE); + int minIndex = IntStream.range(0, array.length) + .filter(index -> array[index] == minValue) + .findFirst().orElse(-1); + assertThat(minIndex).isEqualTo(expectedIndex); + } + + @ParameterizedTest + @MethodSource("primitiveProvider") + void givenArray_whenUsingIntStreamAndLookForIndexWithArrayUtils_thenGetCorrectResult(int[] array, int expectedIndex) { + int minValue = Arrays.stream(array).min().orElse(Integer.MAX_VALUE); + int minIndex = ArrayUtils.indexOf(array, minValue); + assertThat(minIndex).isEqualTo(expectedIndex); + } + + @ParameterizedTest + @MethodSource("referenceTypesProvider") + void givenArray_whenUsingReduce_thenGetCorrectResult(Integer[] array, int expectedIndex) { + int minValue = Arrays.stream(array).reduce(Integer.MAX_VALUE, Integer::min); + int minIndex = ArrayUtils.indexOf(array, minValue); + assertThat(minIndex).isEqualTo(expectedIndex); + } + + @ParameterizedTest + @MethodSource("referenceTypesProvider") + void givenArray_whenUsingReduceAndList_thenGetCorrectResult(Integer[] array, int expectedIndex) { + List list = Arrays.asList(array); + int minValue = list.stream().reduce(Integer.MAX_VALUE, Integer::min); + int index = list.indexOf(minValue); + assertThat(index).isEqualTo(expectedIndex); + } + + @ParameterizedTest + @MethodSource("primitiveProvider") + void givenArray_whenUsingReduceWithRange_thenGetCorrectResult(int[] array, int expectedIndex) { + int index = IntStream.range(0, array.length) + .reduce((a, b) -> array[a] <= array[b] ? a : b) + .orElse(-1); + assertThat(index).isEqualTo(expectedIndex); + } + + @ParameterizedTest + @MethodSource("primitiveProvider") + void givenArray_whenUsingPrimitiveStreams_thenGetCorrectResult(int[] array, int expectedIndex) { + List list = Arrays.stream(array).boxed().collect(Collectors.toList()); + int minValue = Arrays.stream(array).min().orElse(Integer.MAX_VALUE); + int index = list.indexOf(minValue); + assertThat(index).isEqualTo(expectedIndex); + } + + static Stream primitiveProvider() { + return Stream.of( + Arguments.of(new int[]{585, 190, 201, 82, 332}, 3), + Arguments.of(new int[]{1, 1, 1}, 0), + Arguments.of(new int[]{}, -1) + ); + } + + static Stream referenceTypesProvider() { + return Stream.of( + Arguments.of(new Integer[]{585, 190, 201, 82, 332}, 3), + Arguments.of(new Integer[]{1, 1, 1}, 0), + Arguments.of(new Integer[]{}, -1) + ); + } +} From 197353bb52cf015b92d6418139697c6fae26e6a0 Mon Sep 17 00:00:00 2001 From: Eugene Kovko <37694937+eukovko@users.noreply.github.com> Date: Fri, 26 Apr 2024 19:23:02 +0200 Subject: [PATCH 29/33] BAEL-7880: Tests for flattening array (#16496) * BAEL-7880: Tests for flattening array * BAEL-7880: Additonal tests for flattening array * BAEL-7880: Fix formatting --- .../array/flatarray/FlatArrayUnitTest.java | 130 ++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 core-java-modules/core-java-arrays-operations-basic-2/src/test/java/com/baeldung/array/flatarray/FlatArrayUnitTest.java diff --git a/core-java-modules/core-java-arrays-operations-basic-2/src/test/java/com/baeldung/array/flatarray/FlatArrayUnitTest.java b/core-java-modules/core-java-arrays-operations-basic-2/src/test/java/com/baeldung/array/flatarray/FlatArrayUnitTest.java new file mode 100644 index 0000000000..5d67c68a37 --- /dev/null +++ b/core-java-modules/core-java-arrays-operations-basic-2/src/test/java/com/baeldung/array/flatarray/FlatArrayUnitTest.java @@ -0,0 +1,130 @@ +package com.baeldung.array.flatarray; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +class FlatArrayUnitTest { + + @ParameterizedTest + @MethodSource("arrayProvider") + void giveTwoDimensionalArray_whenFlatWithStream_thenGetCorrectResult(int[][] initialArray, + int[] expected) { + int[] actual = Arrays.stream(initialArray).flatMapToInt(Arrays::stream).toArray(); + assertThat(actual).containsExactly(expected); + } + + @ParameterizedTest + @MethodSource("arrayProvider") + void giveTwoDimensionalArray_whenFlatWithForLoopAndAdditionalList_thenGetCorrectResult(int[][] initialArray, + int[] intArray) { + List expected = Arrays.stream(intArray).boxed().collect(Collectors.toList()); + List actual = new ArrayList<>(); + for (int[] numbers : initialArray) { + for (int number : numbers) { + actual.add(number); + } + } + assertThat(actual).isEqualTo(expected); + } + + @ParameterizedTest + @MethodSource("arrayProvider") + void giveTwoDimensionalArray_whenFlatWithForLoopAndLists_thenGetCorrectResult(int[][] initialArray, + int[] intArray) { + List expected = Arrays.stream(intArray).boxed().collect(Collectors.toList()); + List actual = new ArrayList<>(); + for (int[] numbers : initialArray) { + List listOfNumbers = Arrays.stream(numbers).boxed().collect(Collectors.toList()); + actual.addAll(listOfNumbers); + } + assertThat(actual).isEqualTo(expected); + } + + @ParameterizedTest + @MethodSource("arrayProvider") + void giveTwoDimensionalArray_whenFlatWithArrayCopy_thenGetCorrectResult(int[][] initialArray, + int[] expected) { + int[] actual = new int[]{}; + int position = 0; + for (int[] numbers : initialArray) { + if (actual.length < position + numbers.length) { + int[] newArray = new int[actual.length + numbers.length]; + System.arraycopy(actual, 0, newArray, 0, actual.length); + actual = newArray; + } + System.arraycopy(numbers, 0, actual, position, numbers.length); + position += numbers.length; + } + assertThat(actual).isEqualTo(expected); + } + + @ParameterizedTest + @MethodSource("arrayProvider") + void giveTwoDimensionalArray_whenFlatWithArrayCopyAndTotalNumberOfElements_thenGetCorrectResult(int[][] initialArray, + int[] expected) { + int totalNumberOfElements = 0; + for (int[] numbers : initialArray) { + totalNumberOfElements += numbers.length; + } + int[] actual = new int[totalNumberOfElements]; + int position = 0; + for (int[] numbers : initialArray) { + System.arraycopy(numbers, 0, actual, position, numbers.length); + position += numbers.length; + } + assertThat(actual).isEqualTo(expected); + } + + @ParameterizedTest + @MethodSource("arrayProvider") + void giveTwoDimensionalArray_whenFlatWithForLoopAndTotalNumberOfElements_thenGetCorrectResult(int[][] initialArray, + int[] expected) { + int totalNumberOfElements = 0; + for (int[] numbers : initialArray) { + totalNumberOfElements += numbers.length; + } + int[] actual = new int[totalNumberOfElements]; + int position = 0; + for (int[] numbers : initialArray) { + for (int number : numbers) { + actual[position] = number; + ++position; + } + } + assertThat(actual).isEqualTo(expected); + } + + + static Stream arrayProvider() { + return Stream.of( + Arguments.of( + new int[][]{ + {805, 902, 259, 162, 775}, + {278, 216, 0, 72, 663}, + {185, 390, 537, 909, 918}, + {150, 782, 282, 482, 401}, + {244, 685, 643, 364, 307}, + {483, 939, 750, 190, 424}, + {44, 160, 290, 963, 881} + }, + new int[]{ + 805, 902, 259, 162, 775, + 278, 216, 0, 72, 663, + 185, 390, 537, 909, 918, + 150, 782, 282, 482, 401, + 244, 685, 643, 364, 307, + 483, 939, 750, 190, 424, + 44, 160, 290, 963, 881 + } + ) + ); + } +} From b17f9029a15d09d2f84ac56bacb7b532d12313f9 Mon Sep 17 00:00:00 2001 From: vunamtien Date: Sat, 27 Apr 2024 04:51:19 +0700 Subject: [PATCH 30/33] [JAVA-31850] Split-or-move-core-java-lang-6 (#16484) * [JAVA-31850] Split-or-move-core-java-lang-6 * [JAVA-31850] Split-or-move-core-java-lang-6: Fix missing dependency version of core-java-lang-7 --- core-java-modules/core-java-lang-6/README.md | 2 -- core-java-modules/core-java-lang-7/README.md | 4 ++++ core-java-modules/core-java-lang-7/pom.xml | 12 ++++++++---- .../compressbytes/CompressByteArrayUtil.java | 0 .../com/baeldung/randominset/RandomInSetUtil.java | 0 .../compressbytes/CompressByteArrayUnitTest.java | 0 core-java-modules/pom.xml | 1 + 7 files changed, 13 insertions(+), 6 deletions(-) rename core-java-modules/{core-java-lang-6 => core-java-lang-7}/src/main/java/com/baeldung/compressbytes/CompressByteArrayUtil.java (100%) rename core-java-modules/{core-java-lang-6 => core-java-lang-7}/src/main/java/com/baeldung/randominset/RandomInSetUtil.java (100%) rename core-java-modules/{core-java-lang-6 => core-java-lang-7}/src/test/java/com/baeldung/compressbytes/CompressByteArrayUnitTest.java (100%) diff --git a/core-java-modules/core-java-lang-6/README.md b/core-java-modules/core-java-lang-6/README.md index 5319dd15f7..de5b0d09c5 100644 --- a/core-java-modules/core-java-lang-6/README.md +++ b/core-java-modules/core-java-lang-6/README.md @@ -6,11 +6,9 @@ This module contains articles about core features in the Java language - [Convert One Enum to Another Enum in Java](https://www.baeldung.com/java-convert-enums) - [What Is the Maximum Depth of the Java Call Stack?](https://www.baeldung.com/java-call-stack-max-depth) -- [Get a Random Element From a Set in Java](https://www.baeldung.com/java-set-draw-sample) - [Stop Executing Further Code in Java](https://www.baeldung.com/java-stop-running-code) - [Using the Apache Commons Lang 3 for Comparing Objects in Java](https://www.baeldung.com/java-apache-commons-lang-3-compare-objects) - [Return First Non-null Value in Java](https://www.baeldung.com/java-first-non-null) -- [Compress and Uncompress Byte Array Using Deflater/Inflater](https://www.baeldung.com/java-compress-uncompress-byte-array) - [Static Final Variables in Java](https://www.baeldung.com/java-static-final-variables) - [What Is the Error: “Non-static method cannot be referenced from a static context”?](https://www.baeldung.com/java-non-static-method-cannot-be-referenced-from-a-static-context) - [Recursively Sum the Integers in an Array](https://www.baeldung.com/java-recursive-sum-integer-array) diff --git a/core-java-modules/core-java-lang-7/README.md b/core-java-modules/core-java-lang-7/README.md index 7874da33ce..467485668f 100644 --- a/core-java-modules/core-java-lang-7/README.md +++ b/core-java-modules/core-java-lang-7/README.md @@ -5,3 +5,7 @@ This module contains articles about core features in the Java language ### Relevant Articles: - [Set an Environment Variable at Runtime in Java](https://www.baeldung.com/java-set-environment-variable-runtime) +- [Get a Random Element From a Set in Java](https://www.baeldung.com/java-set-draw-sample) +- [Compress and Uncompress Byte Array Using Deflater/Inflater](https://www.baeldung.com/java-compress-uncompress-byte-array) + +[[<-- Prev]](/core-java-modules/core-java-lang-6) diff --git a/core-java-modules/core-java-lang-7/pom.xml b/core-java-modules/core-java-lang-7/pom.xml index 577e36f7c4..886b01c475 100644 --- a/core-java-modules/core-java-lang-7/pom.xml +++ b/core-java-modules/core-java-lang-7/pom.xml @@ -1,9 +1,11 @@ - + 4.0.0 - core-java-lang-6 + core-java-lang-7 + jar + core-java-lang-7 com.baeldung.core-java-modules @@ -61,6 +63,8 @@ 2.2.0 1.19.3 + 1.6.0.Beta1 + 1.37 \ No newline at end of file diff --git a/core-java-modules/core-java-lang-6/src/main/java/com/baeldung/compressbytes/CompressByteArrayUtil.java b/core-java-modules/core-java-lang-7/src/main/java/com/baeldung/compressbytes/CompressByteArrayUtil.java similarity index 100% rename from core-java-modules/core-java-lang-6/src/main/java/com/baeldung/compressbytes/CompressByteArrayUtil.java rename to core-java-modules/core-java-lang-7/src/main/java/com/baeldung/compressbytes/CompressByteArrayUtil.java diff --git a/core-java-modules/core-java-lang-6/src/main/java/com/baeldung/randominset/RandomInSetUtil.java b/core-java-modules/core-java-lang-7/src/main/java/com/baeldung/randominset/RandomInSetUtil.java similarity index 100% rename from core-java-modules/core-java-lang-6/src/main/java/com/baeldung/randominset/RandomInSetUtil.java rename to core-java-modules/core-java-lang-7/src/main/java/com/baeldung/randominset/RandomInSetUtil.java diff --git a/core-java-modules/core-java-lang-6/src/test/java/com/baeldung/compressbytes/CompressByteArrayUnitTest.java b/core-java-modules/core-java-lang-7/src/test/java/com/baeldung/compressbytes/CompressByteArrayUnitTest.java similarity index 100% rename from core-java-modules/core-java-lang-6/src/test/java/com/baeldung/compressbytes/CompressByteArrayUnitTest.java rename to core-java-modules/core-java-lang-7/src/test/java/com/baeldung/compressbytes/CompressByteArrayUnitTest.java diff --git a/core-java-modules/pom.xml b/core-java-modules/pom.xml index 665b0b931d..6b4edaf7f2 100644 --- a/core-java-modules/pom.xml +++ b/core-java-modules/pom.xml @@ -144,6 +144,7 @@ core-java-lang-4 core-java-lang-5 core-java-lang-6 + core-java-lang-7 core-java-lang-math core-java-lang-math-2 core-java-lang-math-4 From a393395bf16591e70139d42213bf1f09f2c3c117 Mon Sep 17 00:00:00 2001 From: Harry9656 Date: Sat, 27 Apr 2024 00:37:22 +0200 Subject: [PATCH 31/33] JAVA-34093: Fix spring-boot-persistance-2 junit-jupiter failures (#16497) --- ...ingBootJdbiApplicationIntegrationTest.java | 15 +++++------ ...gOraclePoolingApplicationC3P0LiveTest.java | 11 +++----- ...clePoolingApplicationHikariCPLiveTest.java | 11 +++----- ...raclePoolingApplicationOracleLiveTest.java | 11 +++----- ...lePoolingApplicationOracleUCPLiveTest.java | 7 ++--- .../CustomerControllerIntegrationTest.java | 27 +++++++++---------- .../states/UserEntityIntegrationTest.java | 9 +++---- ...otTomcatConnectionPoolIntegrationTest.java | 16 +++++------ 8 files changed, 43 insertions(+), 64 deletions(-) diff --git a/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/boot/jdbi/SpringBootJdbiApplicationIntegrationTest.java b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/boot/jdbi/SpringBootJdbiApplicationIntegrationTest.java index 948d197f14..63acb95188 100644 --- a/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/boot/jdbi/SpringBootJdbiApplicationIntegrationTest.java +++ b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/boot/jdbi/SpringBootJdbiApplicationIntegrationTest.java @@ -7,11 +7,9 @@ import static org.junit.Assert.assertTrue; import java.util.ArrayList; import java.util.List; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; import com.baeldung.boot.jdbi.dao.CarMakerDao; import com.baeldung.boot.jdbi.dao.CarModelDao; @@ -21,10 +19,9 @@ import com.baeldung.boot.jdbi.service.CarMakerService; import lombok.extern.slf4j.Slf4j; -@RunWith(SpringRunner.class) @SpringBootTest(classes = {SpringBootJdbiApplication.class, JdbiConfiguration.class}) @Slf4j -public class SpringBootJdbiApplicationIntegrationTest { +class SpringBootJdbiApplicationIntegrationTest { @Autowired @@ -37,7 +34,7 @@ public class SpringBootJdbiApplicationIntegrationTest { private CarMakerService carMakerService; @Test - public void givenNewCarMaker_whenInsertNewCarMaker_thenSuccess() { + void givenNewCarMaker_whenInsertNewCarMaker_thenSuccess() { assertNotNull(carMakerDao); @@ -51,7 +48,7 @@ public class SpringBootJdbiApplicationIntegrationTest { } @Test - public void givenNewCarMakers_whenInsertNewCarMakers_thenSuccess() { + void givenNewCarMakers_whenInsertNewCarMakers_thenSuccess() { assertNotNull(carMakerDao); @@ -74,7 +71,7 @@ public class SpringBootJdbiApplicationIntegrationTest { @Test - public void givenExistingCarMaker_whenFindById_thenReturnExistingCarMaker() { + void givenExistingCarMaker_whenFindById_thenReturnExistingCarMaker() { CarMaker maker = carMakerDao.findById(1L); assertThat(maker).isNotNull(); @@ -83,7 +80,7 @@ public class SpringBootJdbiApplicationIntegrationTest { } @Test - public void givenExistingCarMaker_whenBulkInsertFails_thenRollback() { + void givenExistingCarMaker_whenBulkInsertFails_thenRollback() { CarMaker maker = carMakerDao.findById(1L); CarModel m1 = CarModel.builder() diff --git a/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationC3P0LiveTest.java b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationC3P0LiveTest.java index 5a2d3f2d29..d793244d56 100644 --- a/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationC3P0LiveTest.java +++ b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationC3P0LiveTest.java @@ -4,23 +4,20 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import javax.sql.DataSource; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.junit4.SpringRunner; -@RunWith(SpringRunner.class) @SpringBootTest(classes = {SpringOraclePoolingApplication.class}) @ActiveProfiles({"oracle-pooling-basic", "c3p0"}) -public class SpringOraclePoolingApplicationC3P0LiveTest { +class SpringOraclePoolingApplicationC3P0LiveTest { @Autowired private DataSource dataSource; - @Test - public void givenC3p0Configuration_thenBuildsComboPooledDataSource() { + @Test + void givenC3p0Configuration_thenBuildsComboPooledDataSource() { assertTrue(dataSource instanceof com.mchange.v2.c3p0.ComboPooledDataSource); } diff --git a/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationHikariCPLiveTest.java b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationHikariCPLiveTest.java index ab8fc1e121..d5732a55e2 100644 --- a/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationHikariCPLiveTest.java +++ b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationHikariCPLiveTest.java @@ -4,23 +4,20 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import javax.sql.DataSource; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.junit4.SpringRunner; -@RunWith(SpringRunner.class) @SpringBootTest(classes = {SpringOraclePoolingApplication.class}) @ActiveProfiles("oracle-pooling-basic") -public class SpringOraclePoolingApplicationHikariCPLiveTest { +class SpringOraclePoolingApplicationHikariCPLiveTest { @Autowired private DataSource dataSource; - @Test - public void givenHikariCPConfiguration_thenBuildsHikariCP() { + @Test + void givenHikariCPConfiguration_thenBuildsHikariCP() { assertTrue(dataSource instanceof com.zaxxer.hikari.HikariDataSource); } diff --git a/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationOracleLiveTest.java b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationOracleLiveTest.java index 229375dadd..2f94156fcf 100644 --- a/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationOracleLiveTest.java +++ b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationOracleLiveTest.java @@ -4,23 +4,20 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import javax.sql.DataSource; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.junit4.SpringRunner; -@RunWith(SpringRunner.class) @SpringBootTest(classes = {SpringOraclePoolingApplication.class}) @ActiveProfiles({"oracle-pooling-basic", "oracle"}) -public class SpringOraclePoolingApplicationOracleLiveTest { +class SpringOraclePoolingApplicationOracleLiveTest { @Autowired private DataSource dataSource; - @Test - public void givenOracleConfiguration_thenBuildsOracleDataSource() { + @Test + void givenOracleConfiguration_thenBuildsOracleDataSource() { assertTrue(dataSource instanceof oracle.jdbc.pool.OracleDataSource); } diff --git a/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationOracleUCPLiveTest.java b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationOracleUCPLiveTest.java index 6ef780fcef..35f2a1bd3b 100644 --- a/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationOracleUCPLiveTest.java +++ b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationOracleUCPLiveTest.java @@ -4,15 +4,12 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import javax.sql.DataSource; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit4.SpringRunner; -@RunWith(SpringRunner.class) @SpringBootTest(classes = {SpringOraclePoolingApplication.class}) @ActiveProfiles({"oracle-pooling-basic"}) @TestPropertySource(properties = "spring.datasource.type=oracle.ucp.jdbc.PoolDataSource") @@ -21,7 +18,7 @@ public class SpringOraclePoolingApplicationOracleUCPLiveTest { @Autowired private DataSource dataSource; - @Test + @Test public void givenOracleUCPConfiguration_thenBuildsOraclePoolDataSource() { assertTrue(dataSource instanceof oracle.ucp.jdbc.PoolDataSource); } diff --git a/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/springboothsqldb/application/tests/CustomerControllerIntegrationTest.java b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/springboothsqldb/application/tests/CustomerControllerIntegrationTest.java index bdd9a19b68..0709f1814a 100644 --- a/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/springboothsqldb/application/tests/CustomerControllerIntegrationTest.java +++ b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/springboothsqldb/application/tests/CustomerControllerIntegrationTest.java @@ -1,13 +1,8 @@ package com.baeldung.springboothsqldb.application.tests; -import com.baeldung.springboothsqldb.application.entities.Customer; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.ObjectWriter; -import com.fasterxml.jackson.databind.SerializationFeature; -import java.nio.charset.Charset; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; @@ -17,23 +12,27 @@ import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.result.MockMvcResultMatchers; -@RunWith(SpringRunner.class) +import com.baeldung.springboothsqldb.application.entities.Customer; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectWriter; +import com.fasterxml.jackson.databind.SerializationFeature; + @SpringBootTest @AutoConfigureMockMvc -public class CustomerControllerIntegrationTest { +class CustomerControllerIntegrationTest { private static MediaType MEDIA_TYPE_JSON; @Autowired private MockMvc mockMvc; - @Before - public void setUpJsonMediaType() { + @BeforeEach + void setUpJsonMediaType() { MEDIA_TYPE_JSON = new MediaType(MediaType.APPLICATION_JSON.getType(), MediaType.APPLICATION_JSON.getSubtype()); } @Test - public void whenPostHttpRequesttoCustomers_thenStatusOK() throws Exception { + void whenPostHttpRequesttoCustomers_thenStatusOK() throws Exception { Customer customer = new Customer("John", "john@domain.com"); ObjectMapper mapper = new ObjectMapper(); mapper.configure(SerializationFeature.WRAP_ROOT_VALUE, false); @@ -50,7 +49,7 @@ public class CustomerControllerIntegrationTest { } @Test - public void whenGetHttpRequesttoCustomers_thenStatusOK() throws Exception { + void whenGetHttpRequesttoCustomers_thenStatusOK() throws Exception { this.mockMvc .perform(MockMvcRequestBuilders.get("/customers")) diff --git a/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/states/UserEntityIntegrationTest.java b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/states/UserEntityIntegrationTest.java index 0ce3ff34ce..ddc81446c1 100644 --- a/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/states/UserEntityIntegrationTest.java +++ b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/states/UserEntityIntegrationTest.java @@ -1,20 +1,17 @@ package com.baeldung.states; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.junit.jupiter.api.Test; -import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; import jakarta.persistence.EntityManagerFactory; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -@RunWith(SpringRunner.class) @SpringBootTest class UserEntityIntegrationTest { @Autowired diff --git a/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/tomcatconnectionpool/test/application/SpringBootTomcatConnectionPoolIntegrationTest.java b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/tomcatconnectionpool/test/application/SpringBootTomcatConnectionPoolIntegrationTest.java index 4422c27150..e9ca90b008 100644 --- a/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/tomcatconnectionpool/test/application/SpringBootTomcatConnectionPoolIntegrationTest.java +++ b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/tomcatconnectionpool/test/application/SpringBootTomcatConnectionPoolIntegrationTest.java @@ -1,27 +1,25 @@ package com.baeldung.tomcatconnectionpool.test.application; +import static org.assertj.core.api.Assertions.assertThat; + import javax.sql.DataSource; -import org.junit.Test; -import org.junit.runner.RunWith; + +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit4.SpringRunner; import com.baeldung.tomcatconnectionpool.application.SpringBootConsoleApplication; -import static org.assertj.core.api.Assertions.*; -import org.springframework.boot.test.context.SpringBootTest; - -@RunWith(SpringRunner.class) @SpringBootTest(classes = {SpringBootConsoleApplication.class}) @TestPropertySource(properties = "spring.datasource.type=org.apache.tomcat.jdbc.pool.DataSource") -public class SpringBootTomcatConnectionPoolIntegrationTest { +class SpringBootTomcatConnectionPoolIntegrationTest { @Autowired private DataSource dataSource; @Test - public void givenTomcatConnectionPoolInstance_whenCheckedPoolClassName_thenCorrect() { + void givenTomcatConnectionPoolInstance_whenCheckedPoolClassName_thenCorrect() { assertThat(dataSource.getClass().getName()).isEqualTo("org.apache.tomcat.jdbc.pool.DataSource"); } } From 267bd5409218ad0a36a2a203e046b2c8a70894af Mon Sep 17 00:00:00 2001 From: Lucian Snare Date: Fri, 26 Apr 2024 23:31:20 -0400 Subject: [PATCH 32/33] BAEL-7735: Add test case demonstrating TestNG SoftAssert (#16443) * BAEL-7735: Add test case demonstrating TestNG SoftAssert * Update package * Move Book and BookService to separate classes --- .../com/baeldung/testng/softassert/Book.java | 34 +++++++++++++++ .../testng/softassert/BookService.java | 5 +++ .../softassert/SoftAssertionUnitTest.java | 43 +++++++++++++++++++ 3 files changed, 82 insertions(+) create mode 100644 testing-modules/testng/src/test/java/com/baeldung/testng/softassert/Book.java create mode 100644 testing-modules/testng/src/test/java/com/baeldung/testng/softassert/BookService.java create mode 100644 testing-modules/testng/src/test/java/com/baeldung/testng/softassert/SoftAssertionUnitTest.java diff --git a/testing-modules/testng/src/test/java/com/baeldung/testng/softassert/Book.java b/testing-modules/testng/src/test/java/com/baeldung/testng/softassert/Book.java new file mode 100644 index 0000000000..22eedfee29 --- /dev/null +++ b/testing-modules/testng/src/test/java/com/baeldung/testng/softassert/Book.java @@ -0,0 +1,34 @@ +package com.baeldung.testng.softassert; + +public class Book { + private String isbn; + private String title; + private String author; + + public Book() { + } + + public String getIsbn() { + return isbn; + } + + public void setIsbn(String isbn) { + this.isbn = isbn; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } +} diff --git a/testing-modules/testng/src/test/java/com/baeldung/testng/softassert/BookService.java b/testing-modules/testng/src/test/java/com/baeldung/testng/softassert/BookService.java new file mode 100644 index 0000000000..f6e1be6dcb --- /dev/null +++ b/testing-modules/testng/src/test/java/com/baeldung/testng/softassert/BookService.java @@ -0,0 +1,5 @@ +package com.baeldung.testng.softassert; + +public interface BookService { + Book getBook(String isbn); +} diff --git a/testing-modules/testng/src/test/java/com/baeldung/testng/softassert/SoftAssertionUnitTest.java b/testing-modules/testng/src/test/java/com/baeldung/testng/softassert/SoftAssertionUnitTest.java new file mode 100644 index 0000000000..f4b296e122 --- /dev/null +++ b/testing-modules/testng/src/test/java/com/baeldung/testng/softassert/SoftAssertionUnitTest.java @@ -0,0 +1,43 @@ +package com.baeldung.testng.softassert; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertTrue; + +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; +import org.testng.asserts.SoftAssert; + +public class SoftAssertionUnitTest { + + private BookService bookService; + + @BeforeMethod + void setup() { + bookService = mock(BookService.class); + Book book = new Book(); + when(bookService.getBook(any())) + .thenReturn(book); + } + + @Test + void givenBookWithNullFields_whenUsingMultipleAssertions_thenUseSoftAssert() { + Book gatsby = bookService.getBook("9780743273565"); + + // Traditional assertions - uncomment to see the test fail, only running the first assertion + // assertNotNull(gatsby.isbn, "ISBN"); + // assertNotNull(gatsby.title, "title"); + // assertNotNull(gatsby.author, "author"); + + // SoftAssert - uncomment to see the test fail, but with all assertions run + // SoftAssert softAssert = new SoftAssert(); + // softAssert.assertNotNull(gatsby.isbn, "ISBN"); + // softAssert.assertNotNull(gatsby.title, "title"); + // softAssert.assertNotNull(gatsby.author, "author"); + // softAssert.assertAll(); + } +} From 54aee18a7f1ea088a45c5741b4b7ad88c4424cc3 Mon Sep 17 00:00:00 2001 From: Azhwani <13301425+azhwani@users.noreply.github.com> Date: Sat, 27 Apr 2024 11:56:24 +0200 Subject: [PATCH 33/33] BAEL-7783: Assert properties of custom exceptions with catchThrowableOfType in AssertJ (#16442) --- .../exceptions/CityNotFoundException.java | 22 +++++++++++++++++++ .../assertj/exceptions/CityUtils.java | 17 ++++++++++++++ .../exceptions/Java8StyleAssertions.java | 22 ++++++++++++++++++- 3 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 testing-modules/assertion-libraries/src/main/java/com/baeldung/assertj/exceptions/CityNotFoundException.java create mode 100644 testing-modules/assertion-libraries/src/main/java/com/baeldung/assertj/exceptions/CityUtils.java diff --git a/testing-modules/assertion-libraries/src/main/java/com/baeldung/assertj/exceptions/CityNotFoundException.java b/testing-modules/assertion-libraries/src/main/java/com/baeldung/assertj/exceptions/CityNotFoundException.java new file mode 100644 index 0000000000..e233ee737a --- /dev/null +++ b/testing-modules/assertion-libraries/src/main/java/com/baeldung/assertj/exceptions/CityNotFoundException.java @@ -0,0 +1,22 @@ +package com.baeldung.assertj.exceptions; + +public class CityNotFoundException extends RuntimeException { + + private String city; + private String message; + + CityNotFoundException(String city, String message) { + this.city = city; + this.message = message; + } + + public String getCity() { + return city; + } + + @Override + public String getMessage() { + return message; + } + +} diff --git a/testing-modules/assertion-libraries/src/main/java/com/baeldung/assertj/exceptions/CityUtils.java b/testing-modules/assertion-libraries/src/main/java/com/baeldung/assertj/exceptions/CityUtils.java new file mode 100644 index 0000000000..9e9544a2a1 --- /dev/null +++ b/testing-modules/assertion-libraries/src/main/java/com/baeldung/assertj/exceptions/CityUtils.java @@ -0,0 +1,17 @@ +package com.baeldung.assertj.exceptions; + +import java.util.Arrays; +import java.util.List; + +public final class CityUtils { + + private static final List CITIES = Arrays.asList("Tamassint", "London", "Madrid", "New york"); + + public static String search(String searchedCity) { + return CITIES.stream() + .filter(searchedCity::equals) + .findFirst() + .orElseThrow(() -> new CityNotFoundException(searchedCity, "The specified city is not found")); + } + +} diff --git a/testing-modules/assertion-libraries/src/test/java/com/baeldung/assertj/exceptions/Java8StyleAssertions.java b/testing-modules/assertion-libraries/src/test/java/com/baeldung/assertj/exceptions/Java8StyleAssertions.java index 4d4e2aedfc..54e41edf92 100644 --- a/testing-modules/assertion-libraries/src/test/java/com/baeldung/assertj/exceptions/Java8StyleAssertions.java +++ b/testing-modules/assertion-libraries/src/test/java/com/baeldung/assertj/exceptions/Java8StyleAssertions.java @@ -1,13 +1,15 @@ package com.baeldung.assertj.exceptions; -import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.catchThrowable; +import static org.assertj.core.api.Assertions.catchThrowableOfType; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; + import org.junit.Test; public class Java8StyleAssertions { @@ -63,4 +65,22 @@ public class Java8StyleAssertions { .hasMessageContaining("/ by zero"); } + + @Test + public void whenUsingCatchThrowableOfType_thenAssertField() { + String givenCity = "Paris"; + CityNotFoundException exception = catchThrowableOfType(() -> CityUtils.search(givenCity), CityNotFoundException.class); + + assertThat(exception.getCity()).isEqualTo(givenCity); + assertThat(exception.getMessage()).isEqualTo("The specified city is not found"); + } + + @Test + public void whenUsingAssertThatThrownBy_thenAssertField() { + String givenCity = "Geneva"; + assertThatThrownBy(() -> CityUtils.search(givenCity)).isInstanceOf(CityNotFoundException.class) + .extracting("city") + .isEqualTo(givenCity); + } + }