├── .gitignore ├── README.md ├── oauth2-authorization-code-demo ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── programming │ │ └── techie │ │ └── authcode │ │ ├── DemoApplication.java │ │ └── controller │ │ ├── HomeController.java │ │ └── HomeRestController.java │ └── resources │ ├── application.properties │ └── templates │ └── home.html ├── oauth2-client-credentials-demo ├── microservice-1 │ ├── pom.xml │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── programming │ │ │ └── techie │ │ │ └── microservice1 │ │ │ ├── Microservice1Application.java │ │ │ ├── config │ │ │ └── SecurityConfig.java │ │ │ └── controller │ │ │ └── Controller1.java │ │ └── resources │ │ └── application.properties └── pom.xml ├── oauth2-pkce-demo ├── README.md ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── programming │ │ └── techie │ │ └── pkce │ │ ├── Oauth2PKCEDemoApplication.java │ │ ├── config │ │ └── SecurityConfig.java │ │ └── controller │ │ └── HomeRestController.java │ └── resources │ ├── application.properties │ └── frontend │ ├── .browserslistrc │ ├── .editorconfig │ ├── README.md │ ├── angular.json │ ├── karma.conf.js │ ├── package-lock.json │ ├── package.json │ ├── src │ ├── app │ │ ├── app-routing.module.ts │ │ ├── app.component.css │ │ ├── app.component.html │ │ ├── app.component.spec.ts │ │ ├── app.component.ts │ │ ├── app.module.ts │ │ ├── app.service.ts │ │ └── auth.config.ts │ ├── assets │ │ └── .gitkeep │ ├── environments │ │ ├── environment.prod.ts │ │ └── environment.ts │ ├── favicon.ico │ ├── index.html │ ├── main.ts │ ├── polyfills.ts │ ├── styles.css │ └── test.ts │ ├── tsconfig.app.json │ ├── tsconfig.json │ └── tsconfig.spec.json ├── pom.xml └── realm-export.json /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | 35 | ### Node Modules ### 36 | !**/src/main/resources/frontend/node_modules 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Spring Security OAuth2 Keycloak Demo 2 | 3 | This repository contains source code to demonstrate OAuth2 features using Spring Security and KeyCloak Authorization Server 4 | 5 | After you checked out the project, run the following command: 6 | 7 | `mvn clean verify` 8 | 9 | This project contains examples for 3 OAuth2 Grant Types 10 | 11 | - Authorization Code Flow (oauth2-authorization-code-demo) 12 | - PKCE Authorization Code Flow (oauth2-pkce-demo) 13 | - Client Credentials Flow (oauth2-client-credentials-demo) 14 | 15 | - ### Run Keycloak 16 | - Download Keycloak from https://www.keycloak.org/downloads 17 | - If you are using standalone version, run the following command, by making sure you are inside the bin directory 18 | `standalone.bat -Djboss.http.port=`, you can provide whatever port number you like. 19 | 20 | - ### Importing Realm 21 | - Instead of creating the realm, you can make use of the `realm-export.json` file to import all the realm details into your Keycloak instance. 22 | -------------------------------------------------------------------------------- /oauth2-authorization-code-demo/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | spring-security-oauth2-keycloak 7 | org.programming.techie 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | oauth2-authorization-code-demo 13 | 14 | 15 | 21 16 | 21 17 | 18 | 19 | 20 | 21 | org.springframework.boot 22 | spring-boot-starter-thymeleaf 23 | 24 | 25 | org.springframework.boot 26 | spring-boot-starter-web 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-oauth2-client 31 | 32 | 33 | org.springframework.boot 34 | spring-boot-starter-test 35 | test 36 | 37 | 38 | 39 | 40 | 41 | 42 | org.springframework.boot 43 | spring-boot-maven-plugin 44 | 45 | 46 | org.apache.maven.plugins 47 | maven-compiler-plugin 48 | 49 | 21 50 | 21 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /oauth2-authorization-code-demo/src/main/java/com/programming/techie/authcode/DemoApplication.java: -------------------------------------------------------------------------------- 1 | package com.programming.techie.authcode; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class DemoApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(DemoApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /oauth2-authorization-code-demo/src/main/java/com/programming/techie/authcode/controller/HomeController.java: -------------------------------------------------------------------------------- 1 | package com.programming.techie.authcode.controller; 2 | 3 | import org.springframework.stereotype.Controller; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | 6 | @Controller 7 | public class HomeController { 8 | 9 | @GetMapping("/home") 10 | public String home() { 11 | return "home"; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /oauth2-authorization-code-demo/src/main/java/com/programming/techie/authcode/controller/HomeRestController.java: -------------------------------------------------------------------------------- 1 | package com.programming.techie.authcode.controller; 2 | 3 | import org.springframework.web.bind.annotation.GetMapping; 4 | import org.springframework.web.bind.annotation.RestController; 5 | 6 | @RestController 7 | public class HomeRestController { 8 | @GetMapping("/hello") 9 | public String hello() { 10 | return "hello"; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /oauth2-authorization-code-demo/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=8080 2 | 3 | spring.security.oauth2.client.registration.oauth2-demo-thymeleaf-client.client-id=oauth2-demo-thymeleaf-client 4 | spring.security.oauth2.client.registration.oauth2-demo-thymeleaf-client.client-secret=ULJ45uoLTTpNjkPZEIPEzy7xu7TsM4dY 5 | spring.security.oauth2.client.registration.oauth2-demo-thymeleaf-client.scope=openid, profile, roles 6 | spring.security.oauth2.client.registration.oauth2-demo-thymeleaf-client.authorization-grant-type=authorization_code 7 | spring.security.oauth2.client.registration.oauth2-demo-thymeleaf-client.redirect-uri=http://localhost:8080/login/oauth2/code/oauth2-demo-thymeleaf-client 8 | 9 | spring.security.oauth2.client.provider.oauth2-demo-thymeleaf-client.issuer-uri=http://localhost:8180/realms/oauth2-demo-realm 10 | -------------------------------------------------------------------------------- /oauth2-authorization-code-demo/src/main/resources/templates/home.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Welcome to Oauth2 Spring MVC Demo App

4 | 5 | 6 | -------------------------------------------------------------------------------- /oauth2-client-credentials-demo/microservice-1/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | oauth2-client-credentials-demo 7 | org.programming.techie 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | org.programming.techie.microservice-1 13 | microservice-1 14 | 15 | 16 | 21 17 | 21 18 | 19 | 20 | 21 | 22 | org.springframework.boot 23 | spring-boot-starter-oauth2-resource-server 24 | 25 | 26 | org.springframework.boot 27 | spring-boot-starter-security 28 | 29 | 30 | 31 | org.springframework.boot 32 | spring-boot-starter-web 33 | 34 | 35 | 36 | org.springframework.boot 37 | spring-boot-starter-test 38 | test 39 | 40 | 41 | 42 | 43 | 44 | 45 | org.springframework.boot 46 | spring-boot-maven-plugin 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /oauth2-client-credentials-demo/microservice-1/src/main/java/com/programming/techie/microservice1/Microservice1Application.java: -------------------------------------------------------------------------------- 1 | package com.programming.techie.microservice1; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class Microservice1Application { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(Microservice1Application.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /oauth2-client-credentials-demo/microservice-1/src/main/java/com/programming/techie/microservice1/config/SecurityConfig.java: -------------------------------------------------------------------------------- 1 | package com.programming.techie.microservice1.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.security.config.Customizer; 6 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 7 | import org.springframework.security.config.annotation.web.configurers.CsrfConfigurer; 8 | import org.springframework.security.config.http.SessionCreationPolicy; 9 | import org.springframework.security.web.SecurityFilterChain; 10 | 11 | @Configuration 12 | public class SecurityConfig { 13 | 14 | @Bean 15 | public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception { 16 | return httpSecurity.cors(Customizer.withDefaults()) 17 | .csrf(CsrfConfigurer::disable) 18 | .authorizeHttpRequests(httpRequests -> httpRequests.anyRequest().authenticated()) 19 | .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) 20 | .oauth2ResourceServer(oauth2ResourceServer -> oauth2ResourceServer.jwt(Customizer.withDefaults())) 21 | .build(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /oauth2-client-credentials-demo/microservice-1/src/main/java/com/programming/techie/microservice1/controller/Controller1.java: -------------------------------------------------------------------------------- 1 | package com.programming.techie.microservice1.controller; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.ResponseStatus; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | @RestController 9 | public class Controller1 { 10 | 11 | @GetMapping("/microservice1/home") 12 | @ResponseStatus(HttpStatus.OK) 13 | public String hello() { 14 | return "Hello"; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /oauth2-client-credentials-demo/microservice-1/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=8083 2 | spring.security.oauth2.resourceserver.jwt.jwk-set-uri=http://localhost:8180/realms/oauth2-demo-realm/protocol/openid-connect/certs 3 | -------------------------------------------------------------------------------- /oauth2-client-credentials-demo/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | spring-security-oauth2-keycloak 7 | org.programming.techie 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | oauth2-client-credentials-demo 13 | pom 14 | 15 | microservice-1 16 | 17 | 18 | 19 | 21 20 | 21 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /oauth2-pkce-demo/README.md: -------------------------------------------------------------------------------- 1 | # Spring Boot Angular Keycloak Oauth2 PKCE Example 2 | 3 | This repository contains source code to demonstrate how to implement Authorization Code Flow (PKCE) using Spring Boot, Angular and Keycloak. 4 | 5 | ## Instructions to run the project 6 | 7 | - ### Run Keycloak 8 | - Download Keycloak from https://www.keycloak.org/downloads 9 | - If you are using standalone version, run the following command, by making sure you are inside the bin directory 10 | `standalone.bat -Djboss.http.port=`, you can provide whatever port number you like. 11 | 12 | - ### Importing Realm 13 | - Instead of creating the realm, you can make use of the `realm-export.json` file to import all the realm details into your Keycloak instance. 14 | 15 | - ### Spring Boot Project 16 | - Pre-Requisite: Make sure the Keycloak server is running. 17 | - Run `mvn clean verify` 18 | - Run `Oauth2PKCEDemoApplication` class. 19 | 20 | - ### Running Angular Project 21 | - Go to the `src/main/resources/frontend` and run `npm install` 22 | - Start the server using `npm start` command. 23 | - Open `http://localhost:4200` 24 | -------------------------------------------------------------------------------- /oauth2-pkce-demo/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | spring-security-oauth2-keycloak 7 | org.programming.techie 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | oauth2-pkce-demo 13 | 14 | 15 | 21 16 | 21 17 | 18 | 19 | 20 | 21 | org.springframework.boot 22 | spring-boot-starter-oauth2-resource-server 23 | 24 | 25 | org.springframework.security 26 | spring-security-oauth2-jose 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-security 31 | 32 | 33 | org.springframework.boot 34 | spring-boot-starter-web 35 | 36 | 37 | 38 | org.springframework.boot 39 | spring-boot-starter-test 40 | test 41 | 42 | 43 | org.springframework.security 44 | spring-security-test 45 | test 46 | 47 | 48 | 49 | 50 | 51 | 52 | org.springframework.boot 53 | spring-boot-maven-plugin 54 | 55 | 56 | org.apache.maven.plugins 57 | maven-compiler-plugin 58 | 59 | 21 60 | 21 61 | 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /oauth2-pkce-demo/src/main/java/com/programming/techie/pkce/Oauth2PKCEDemoApplication.java: -------------------------------------------------------------------------------- 1 | package com.programming.techie.pkce; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class Oauth2PKCEDemoApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(Oauth2PKCEDemoApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /oauth2-pkce-demo/src/main/java/com/programming/techie/pkce/config/SecurityConfig.java: -------------------------------------------------------------------------------- 1 | package com.programming.techie.pkce.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.security.config.Customizer; 6 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 7 | import org.springframework.security.config.http.SessionCreationPolicy; 8 | import org.springframework.security.web.SecurityFilterChain; 9 | 10 | @Configuration 11 | public class SecurityConfig { 12 | 13 | @Bean 14 | public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception { 15 | return httpSecurity.cors(Customizer.withDefaults()) 16 | .csrf(csrf -> csrf.ignoringRequestMatchers("/api/home/**")) 17 | .authorizeHttpRequests(httpRequests -> httpRequests.anyRequest().authenticated()) 18 | .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) 19 | .oauth2ResourceServer(oauth2ResourceServer -> oauth2ResourceServer.jwt(Customizer.withDefaults())) 20 | .build(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /oauth2-pkce-demo/src/main/java/com/programming/techie/pkce/controller/HomeRestController.java: -------------------------------------------------------------------------------- 1 | package com.programming.techie.pkce.controller; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.*; 5 | 6 | @RestController 7 | @RequestMapping("/api/home") 8 | @CrossOrigin(origins = "*") 9 | public class HomeRestController { 10 | 11 | @GetMapping 12 | @ResponseStatus(HttpStatus.OK) 13 | public String home() { 14 | return "Hello"; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /oauth2-pkce-demo/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.security.oauth2.resourceserver.jwt.jwk-set-uri=http://localhost:8180/realms/oauth2-demo-realm/protocol/openid-connect/certs 2 | -------------------------------------------------------------------------------- /oauth2-pkce-demo/src/main/resources/frontend/.browserslistrc: -------------------------------------------------------------------------------- 1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below. 2 | # For additional information regarding the format and rule options, please see: 3 | # https://github.com/browserslist/browserslist#queries 4 | 5 | # For the full list of supported browsers by the Angular framework, please see: 6 | # https://angular.io/guide/browser-support 7 | 8 | # You can see what browsers were selected by your queries by running: 9 | # npx browserslist 10 | 11 | last 1 Chrome version 12 | last 1 Firefox version 13 | last 2 Edge major versions 14 | last 2 Safari major versions 15 | last 2 iOS major versions 16 | Firefox ESR 17 | not IE 11 # Angular supports IE 11 only as an opt-in. To opt-in, remove the 'not' prefix on this line. 18 | -------------------------------------------------------------------------------- /oauth2-pkce-demo/src/main/resources/frontend/.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.ts] 12 | quote_type = single 13 | 14 | [*.md] 15 | max_line_length = off 16 | trim_trailing_whitespace = false 17 | -------------------------------------------------------------------------------- /oauth2-pkce-demo/src/main/resources/frontend/README.md: -------------------------------------------------------------------------------- 1 | # Frontend 2 | 3 | This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 12.0.2. 4 | 5 | ## Development server 6 | 7 | Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. 8 | 9 | ## Code scaffolding 10 | 11 | Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. 12 | 13 | ## Build 14 | 15 | Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. 16 | 17 | ## Running unit tests 18 | 19 | Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). 20 | 21 | ## Running end-to-end tests 22 | 23 | Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities. 24 | 25 | ## Further help 26 | 27 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page. 28 | -------------------------------------------------------------------------------- /oauth2-pkce-demo/src/main/resources/frontend/angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "version": 1, 4 | "newProjectRoot": "projects", 5 | "projects": { 6 | "frontend": { 7 | "projectType": "application", 8 | "schematics": { 9 | "@schematics/angular:application": { 10 | "strict": true 11 | } 12 | }, 13 | "root": "", 14 | "sourceRoot": "src", 15 | "prefix": "app", 16 | "architect": { 17 | "build": { 18 | "builder": "@angular-devkit/build-angular:browser", 19 | "options": { 20 | "outputPath": "dist/frontend", 21 | "index": "src/index.html", 22 | "main": "src/main.ts", 23 | "polyfills": "src/polyfills.ts", 24 | "tsConfig": "tsconfig.app.json", 25 | "assets": [ 26 | "src/favicon.ico", 27 | "src/assets" 28 | ], 29 | "styles": [ 30 | "src/styles.css" 31 | ], 32 | "scripts": [] 33 | }, 34 | "configurations": { 35 | "production": { 36 | "budgets": [ 37 | { 38 | "type": "initial", 39 | "maximumWarning": "500kb", 40 | "maximumError": "1mb" 41 | }, 42 | { 43 | "type": "anyComponentStyle", 44 | "maximumWarning": "2kb", 45 | "maximumError": "4kb" 46 | } 47 | ], 48 | "fileReplacements": [ 49 | { 50 | "replace": "src/environments/environment.ts", 51 | "with": "src/environments/environment.prod.ts" 52 | } 53 | ], 54 | "outputHashing": "all" 55 | }, 56 | "development": { 57 | "buildOptimizer": false, 58 | "optimization": false, 59 | "vendorChunk": true, 60 | "extractLicenses": false, 61 | "sourceMap": true, 62 | "namedChunks": true 63 | } 64 | }, 65 | "defaultConfiguration": "production" 66 | }, 67 | "serve": { 68 | "builder": "@angular-devkit/build-angular:dev-server", 69 | "configurations": { 70 | "production": { 71 | "browserTarget": "frontend:build:production" 72 | }, 73 | "development": { 74 | "browserTarget": "frontend:build:development" 75 | } 76 | }, 77 | "defaultConfiguration": "development" 78 | }, 79 | "extract-i18n": { 80 | "builder": "@angular-devkit/build-angular:extract-i18n", 81 | "options": { 82 | "browserTarget": "frontend:build" 83 | } 84 | }, 85 | "test": { 86 | "builder": "@angular-devkit/build-angular:karma", 87 | "options": { 88 | "main": "src/test.ts", 89 | "polyfills": "src/polyfills.ts", 90 | "tsConfig": "tsconfig.spec.json", 91 | "karmaConfig": "karma.conf.js", 92 | "assets": [ 93 | "src/favicon.ico", 94 | "src/assets" 95 | ], 96 | "styles": [ 97 | "src/styles.css" 98 | ], 99 | "scripts": [] 100 | } 101 | } 102 | } 103 | } 104 | }, 105 | "defaultProject": "frontend" 106 | } 107 | -------------------------------------------------------------------------------- /oauth2-pkce-demo/src/main/resources/frontend/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client: { 16 | jasmine: { 17 | // you can add configuration options for Jasmine here 18 | // the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html 19 | // for example, you can disable the random execution with `random: false` 20 | // or set a specific seed with `seed: 4321` 21 | }, 22 | clearContext: false // leave Jasmine Spec Runner output visible in browser 23 | }, 24 | jasmineHtmlReporter: { 25 | suppressAll: true // removes the duplicated traces 26 | }, 27 | coverageReporter: { 28 | dir: require('path').join(__dirname, './coverage/frontend'), 29 | subdir: '.', 30 | reporters: [ 31 | { type: 'html' }, 32 | { type: 'text-summary' } 33 | ] 34 | }, 35 | reporters: ['progress', 'kjhtml'], 36 | port: 9876, 37 | colors: true, 38 | logLevel: config.LOG_INFO, 39 | autoWatch: true, 40 | browsers: ['Chrome'], 41 | singleRun: false, 42 | restartOnFileChange: true 43 | }); 44 | }; 45 | -------------------------------------------------------------------------------- /oauth2-pkce-demo/src/main/resources/frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "frontend", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "ng": "ng", 6 | "start": "ng serve", 7 | "build": "ng build", 8 | "watch": "ng build --watch --configuration development", 9 | "test": "ng test" 10 | }, 11 | "private": true, 12 | "dependencies": { 13 | "@angular/animations": "~12.0.2", 14 | "@angular/common": "~12.0.2", 15 | "@angular/compiler": "~12.0.2", 16 | "@angular/core": "~12.0.2", 17 | "@angular/forms": "~12.0.2", 18 | "@angular/platform-browser": "~12.0.2", 19 | "@angular/platform-browser-dynamic": "~12.0.2", 20 | "@angular/router": "~12.0.2", 21 | "angular-oauth2-oidc": "^10.0.3", 22 | "rxjs": "~6.6.0", 23 | "tslib": "^2.1.0", 24 | "zone.js": "~0.11.4" 25 | }, 26 | "devDependencies": { 27 | "@angular-devkit/build-angular": "~12.0.2", 28 | "@angular/cli": "~12.0.2", 29 | "@angular/compiler-cli": "~12.0.2", 30 | "@types/jasmine": "~3.6.0", 31 | "@types/node": "^12.11.1", 32 | "jasmine-core": "~3.7.0", 33 | "karma": "~6.3.0", 34 | "karma-chrome-launcher": "~3.1.0", 35 | "karma-coverage": "~2.0.3", 36 | "karma-jasmine": "~4.0.0", 37 | "karma-jasmine-html-reporter": "^1.5.0", 38 | "typescript": "~4.2.3" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /oauth2-pkce-demo/src/main/resources/frontend/src/app/app-routing.module.ts: -------------------------------------------------------------------------------- 1 | import {NgModule} from '@angular/core'; 2 | import {RouterModule, Routes} from '@angular/router'; 3 | 4 | 5 | const routes: Routes = []; 6 | 7 | 8 | @NgModule({ 9 | imports: [RouterModule.forRoot(routes)], 10 | exports: [RouterModule] 11 | }) 12 | export class AppRoutingModule { 13 | } 14 | -------------------------------------------------------------------------------- /oauth2-pkce-demo/src/main/resources/frontend/src/app/app.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaiUpadhyayula/spring-security-oauth2-keycloak-demo/784527696a16a096f83c227324bc747526e6bbfb/oauth2-pkce-demo/src/main/resources/frontend/src/app/app.component.css -------------------------------------------------------------------------------- /oauth2-pkce-demo/src/main/resources/frontend/src/app/app.component.html: -------------------------------------------------------------------------------- 1 | Login 2 |

Refresh the browser after login to view the text

3 |

{{text}}

4 |
5 | Logout 6 | -------------------------------------------------------------------------------- /oauth2-pkce-demo/src/main/resources/frontend/src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { RouterTestingModule } from '@angular/router/testing'; 3 | import { AppComponent } from './app.component'; 4 | 5 | describe('AppComponent', () => { 6 | beforeEach(async () => { 7 | await TestBed.configureTestingModule({ 8 | imports: [ 9 | RouterTestingModule 10 | ], 11 | declarations: [ 12 | AppComponent 13 | ], 14 | }).compileComponents(); 15 | }); 16 | 17 | it('should create the app', () => { 18 | const fixture = TestBed.createComponent(AppComponent); 19 | const app = fixture.componentInstance; 20 | expect(app).toBeTruthy(); 21 | }); 22 | 23 | it(`should have as title 'frontend'`, () => { 24 | const fixture = TestBed.createComponent(AppComponent); 25 | const app = fixture.componentInstance; 26 | expect(app.title).toEqual('frontend'); 27 | }); 28 | 29 | it('should render title', () => { 30 | const fixture = TestBed.createComponent(AppComponent); 31 | fixture.detectChanges(); 32 | const compiled = fixture.nativeElement; 33 | expect(compiled.querySelector('.content span').textContent).toContain('frontend app is running!'); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /oauth2-pkce-demo/src/main/resources/frontend/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | import {OAuthService} from "angular-oauth2-oidc"; 3 | import {authConfig} from "./auth.config"; 4 | import {AppService} from "./app.service"; 5 | 6 | @Component({ 7 | selector: 'app-root', 8 | templateUrl: './app.component.html', 9 | styleUrls: ['./app.component.css'] 10 | }) 11 | export class AppComponent { 12 | title = 'frontend'; 13 | text = ''; 14 | 15 | constructor(private oauthService: OAuthService, private appService: AppService) { 16 | this.configure(); 17 | appService.hello().subscribe(response => { 18 | this.text = response; 19 | }); 20 | } 21 | 22 | login() { 23 | this.oauthService.initCodeFlow(); 24 | } 25 | 26 | private configure() { 27 | this.oauthService.configure(authConfig); 28 | this.oauthService.loadDiscoveryDocumentAndTryLogin(); 29 | } 30 | 31 | logout() { 32 | this.oauthService.logOut(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /oauth2-pkce-demo/src/main/resources/frontend/src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import {BrowserModule} from '@angular/platform-browser'; 2 | import {NgModule} from '@angular/core'; 3 | 4 | import {AppRoutingModule} from './app-routing.module'; 5 | import {AppComponent} from './app.component'; 6 | import {OAuthModule} from "angular-oauth2-oidc"; 7 | import {HttpClientModule} from "@angular/common/http"; 8 | 9 | @NgModule({ 10 | declarations: [ 11 | AppComponent, 12 | ], 13 | imports: [ 14 | BrowserModule, 15 | AppRoutingModule, 16 | HttpClientModule, 17 | OAuthModule.forRoot({ 18 | resourceServer: { 19 | allowedUrls: ['http://localhost:8080/api'], 20 | sendAccessToken: true 21 | } 22 | }), 23 | ], 24 | providers: [], 25 | bootstrap: [AppComponent] 26 | }) 27 | export class AppModule { 28 | } 29 | -------------------------------------------------------------------------------- /oauth2-pkce-demo/src/main/resources/frontend/src/app/app.service.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from '@angular/core'; 2 | import {HttpClient, HttpHeaders} from "@angular/common/http"; 3 | import {Observable} from "rxjs"; 4 | 5 | @Injectable({ 6 | providedIn: 'root' 7 | }) 8 | export class AppService { 9 | 10 | constructor(private httpClient: HttpClient) { 11 | } 12 | 13 | hello(): Observable { 14 | const headers = new HttpHeaders().set('Content-Type', 'text/plain; charset=utf-8'); 15 | return this.httpClient.get("http://localhost:8080/api/home", 16 | {headers, responseType: 'text'}); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /oauth2-pkce-demo/src/main/resources/frontend/src/app/auth.config.ts: -------------------------------------------------------------------------------- 1 | import {AuthConfig} from 'angular-oauth2-oidc'; 2 | 3 | export const authConfig: AuthConfig = { 4 | issuer: 'http://localhost:8180/auth/realms/oauth2-demo-realm', 5 | redirectUri: window.location.origin, 6 | clientId: 'oauth2-demo-pkce-client', 7 | responseType: 'code', 8 | strictDiscoveryDocumentValidation: false, 9 | scope: 'openid profile email offline_access', 10 | } 11 | -------------------------------------------------------------------------------- /oauth2-pkce-demo/src/main/resources/frontend/src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaiUpadhyayula/spring-security-oauth2-keycloak-demo/784527696a16a096f83c227324bc747526e6bbfb/oauth2-pkce-demo/src/main/resources/frontend/src/assets/.gitkeep -------------------------------------------------------------------------------- /oauth2-pkce-demo/src/main/resources/frontend/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true 3 | }; 4 | -------------------------------------------------------------------------------- /oauth2-pkce-demo/src/main/resources/frontend/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // `ng build` replaces `environment.ts` with `environment.prod.ts`. 3 | // The list of file replacements can be found in `angular.json`. 4 | 5 | export const environment = { 6 | production: false 7 | }; 8 | 9 | /* 10 | * For easier debugging in development mode, you can import the following file 11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. 12 | * 13 | * This import should be commented out in production mode because it will have a negative impact 14 | * on performance if an error is thrown. 15 | */ 16 | // import 'zone.js/plugins/zone-error'; // Included with Angular CLI. 17 | -------------------------------------------------------------------------------- /oauth2-pkce-demo/src/main/resources/frontend/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SaiUpadhyayula/spring-security-oauth2-keycloak-demo/784527696a16a096f83c227324bc747526e6bbfb/oauth2-pkce-demo/src/main/resources/frontend/src/favicon.ico -------------------------------------------------------------------------------- /oauth2-pkce-demo/src/main/resources/frontend/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Frontend 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /oauth2-pkce-demo/src/main/resources/frontend/src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic().bootstrapModule(AppModule) 12 | .catch(err => console.error(err)); 13 | -------------------------------------------------------------------------------- /oauth2-pkce-demo/src/main/resources/frontend/src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file includes polyfills needed by Angular and is loaded before the app. 3 | * You can add your own extra polyfills to this file. 4 | * 5 | * This file is divided into 2 sections: 6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 8 | * file. 9 | * 10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), 12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. 13 | * 14 | * Learn more in https://angular.io/guide/browser-support 15 | */ 16 | 17 | /*************************************************************************************************** 18 | * BROWSER POLYFILLS 19 | */ 20 | 21 | /** 22 | * IE11 requires the following for NgClass support on SVG elements 23 | */ 24 | // import 'classlist.js'; // Run `npm install --save classlist.js`. 25 | 26 | /** 27 | * Web Animations `@angular/platform-browser/animations` 28 | * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari. 29 | * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0). 30 | */ 31 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`. 32 | 33 | /** 34 | * By default, zone.js will patch all possible macroTask and DomEvents 35 | * user can disable parts of macroTask/DomEvents patch by setting following flags 36 | * because those flags need to be set before `zone.js` being loaded, and webpack 37 | * will put import in the top of bundle, so user need to create a separate file 38 | * in this directory (for example: zone-flags.ts), and put the following flags 39 | * into that file, and then add the following code before importing zone.js. 40 | * import './zone-flags'; 41 | * 42 | * The flags allowed in zone-flags.ts are listed here. 43 | * 44 | * The following flags will work for all browsers. 45 | * 46 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame 47 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick 48 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames 49 | * 50 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js 51 | * with the following flag, it will bypass `zone.js` patch for IE/Edge 52 | * 53 | * (window as any).__Zone_enable_cross_context_check = true; 54 | * 55 | */ 56 | 57 | /*************************************************************************************************** 58 | * Zone JS is required by default for Angular itself. 59 | */ 60 | import 'zone.js'; // Included with Angular CLI. 61 | 62 | 63 | /*************************************************************************************************** 64 | * APPLICATION IMPORTS 65 | */ 66 | -------------------------------------------------------------------------------- /oauth2-pkce-demo/src/main/resources/frontend/src/styles.css: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | -------------------------------------------------------------------------------- /oauth2-pkce-demo/src/main/resources/frontend/src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js/testing'; 4 | import { getTestBed } from '@angular/core/testing'; 5 | import { 6 | BrowserDynamicTestingModule, 7 | platformBrowserDynamicTesting 8 | } from '@angular/platform-browser-dynamic/testing'; 9 | 10 | declare const require: { 11 | context(path: string, deep?: boolean, filter?: RegExp): { 12 | keys(): string[]; 13 | (id: string): T; 14 | }; 15 | }; 16 | 17 | // First, initialize the Angular testing environment. 18 | getTestBed().initTestEnvironment( 19 | BrowserDynamicTestingModule, 20 | platformBrowserDynamicTesting() 21 | ); 22 | // Then we find all the tests. 23 | const context = require.context('./', true, /\.spec\.ts$/); 24 | // And load the modules. 25 | context.keys().map(context); 26 | -------------------------------------------------------------------------------- /oauth2-pkce-demo/src/main/resources/frontend/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/app", 6 | "types": [] 7 | }, 8 | "files": [ 9 | "src/main.ts", 10 | "src/polyfills.ts" 11 | ], 12 | "include": [ 13 | "src/**/*.d.ts" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /oauth2-pkce-demo/src/main/resources/frontend/tsconfig.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "compileOnSave": false, 4 | "compilerOptions": { 5 | "baseUrl": "./", 6 | "outDir": "./dist/out-tsc", 7 | "forceConsistentCasingInFileNames": true, 8 | "strict": true, 9 | "noImplicitReturns": true, 10 | "noFallthroughCasesInSwitch": true, 11 | "sourceMap": true, 12 | "declaration": false, 13 | "downlevelIteration": true, 14 | "experimentalDecorators": true, 15 | "moduleResolution": "node", 16 | "importHelpers": true, 17 | "target": "es2017", 18 | "module": "es2020", 19 | "lib": [ 20 | "es2018", 21 | "dom" 22 | ] 23 | }, 24 | "angularCompilerOptions": { 25 | "enableI18nLegacyMessageIdFormat": false, 26 | "strictInjectionParameters": true, 27 | "strictInputAccessModifiers": true, 28 | "strictTemplates": true 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /oauth2-pkce-demo/src/main/resources/frontend/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/spec", 6 | "types": [ 7 | "jasmine" 8 | ] 9 | }, 10 | "files": [ 11 | "src/test.ts", 12 | "src/polyfills.ts" 13 | ], 14 | "include": [ 15 | "src/**/*.spec.ts", 16 | "src/**/*.d.ts" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | org.springframework.boot 8 | spring-boot-starter-parent 9 | 3.1.4 10 | 11 | 12 | org.programming.techie 13 | spring-security-oauth2-keycloak 14 | pom 15 | 1.0-SNAPSHOT 16 | 17 | oauth2-client-credentials-demo 18 | oauth2-pkce-demo 19 | oauth2-authorization-code-demo 20 | 21 | 22 | 23 | 21 24 | 21 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /realm-export.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "oauth2-demo-realm", 3 | "realm": "oauth2-demo-realm", 4 | "displayName": "Oauth2 Demo", 5 | "notBefore": 0, 6 | "revokeRefreshToken": false, 7 | "refreshTokenMaxReuse": 0, 8 | "accessTokenLifespan": 300, 9 | "accessTokenLifespanForImplicitFlow": 900, 10 | "ssoSessionIdleTimeout": 1800, 11 | "ssoSessionMaxLifespan": 36000, 12 | "ssoSessionIdleTimeoutRememberMe": 0, 13 | "ssoSessionMaxLifespanRememberMe": 0, 14 | "offlineSessionIdleTimeout": 2592000, 15 | "offlineSessionMaxLifespanEnabled": false, 16 | "offlineSessionMaxLifespan": 5184000, 17 | "clientSessionIdleTimeout": 0, 18 | "clientSessionMaxLifespan": 0, 19 | "accessCodeLifespan": 60, 20 | "accessCodeLifespanUserAction": 300, 21 | "accessCodeLifespanLogin": 1800, 22 | "actionTokenGeneratedByAdminLifespan": 43200, 23 | "actionTokenGeneratedByUserLifespan": 300, 24 | "enabled": true, 25 | "sslRequired": "external", 26 | "registrationAllowed": false, 27 | "registrationEmailAsUsername": false, 28 | "rememberMe": false, 29 | "verifyEmail": false, 30 | "loginWithEmailAllowed": true, 31 | "duplicateEmailsAllowed": false, 32 | "resetPasswordAllowed": false, 33 | "editUsernameAllowed": false, 34 | "bruteForceProtected": false, 35 | "permanentLockout": false, 36 | "maxFailureWaitSeconds": 900, 37 | "minimumQuickLoginWaitSeconds": 60, 38 | "waitIncrementSeconds": 60, 39 | "quickLoginCheckMilliSeconds": 1000, 40 | "maxDeltaTimeSeconds": 43200, 41 | "failureFactor": 30, 42 | "roles": { 43 | "realm": [ 44 | { 45 | "id": "58229dc4-8d91-41f5-bec6-99921f0ba90e", 46 | "name": "offline_access", 47 | "description": "${role_offline-access}", 48 | "composite": false, 49 | "clientRole": false, 50 | "containerId": "oauth2-demo-realm", 51 | "attributes": {} 52 | }, 53 | { 54 | "id": "8b357a39-ee87-43f6-b90d-a7288bc3856f", 55 | "name": "uma_authorization", 56 | "description": "${role_uma_authorization}", 57 | "composite": false, 58 | "clientRole": false, 59 | "containerId": "oauth2-demo-realm", 60 | "attributes": {} 61 | } 62 | ], 63 | "client": { 64 | "realm-management": [ 65 | { 66 | "id": "729b99d8-310a-4f5e-bbf2-97bf3b7055d2", 67 | "name": "manage-authorization", 68 | "description": "${role_manage-authorization}", 69 | "composite": false, 70 | "clientRole": true, 71 | "containerId": "c2963685-912b-44ed-8d8d-647761680cfd", 72 | "attributes": {} 73 | }, 74 | { 75 | "id": "6a5b3a19-7df9-471b-bfb0-9c0e25884231", 76 | "name": "create-client", 77 | "description": "${role_create-client}", 78 | "composite": false, 79 | "clientRole": true, 80 | "containerId": "c2963685-912b-44ed-8d8d-647761680cfd", 81 | "attributes": {} 82 | }, 83 | { 84 | "id": "7c0f36e3-a735-4231-93f3-0ee969826f1f", 85 | "name": "manage-realm", 86 | "description": "${role_manage-realm}", 87 | "composite": false, 88 | "clientRole": true, 89 | "containerId": "c2963685-912b-44ed-8d8d-647761680cfd", 90 | "attributes": {} 91 | }, 92 | { 93 | "id": "7b475c42-6d56-4037-a52a-93766aaa4356", 94 | "name": "view-authorization", 95 | "description": "${role_view-authorization}", 96 | "composite": false, 97 | "clientRole": true, 98 | "containerId": "c2963685-912b-44ed-8d8d-647761680cfd", 99 | "attributes": {} 100 | }, 101 | { 102 | "id": "48f69f72-c7e4-40cb-a04a-9912f72eefe6", 103 | "name": "query-clients", 104 | "description": "${role_query-clients}", 105 | "composite": false, 106 | "clientRole": true, 107 | "containerId": "c2963685-912b-44ed-8d8d-647761680cfd", 108 | "attributes": {} 109 | }, 110 | { 111 | "id": "3fec0d07-a0ef-4b58-a906-c3816bcb38e5", 112 | "name": "view-clients", 113 | "description": "${role_view-clients}", 114 | "composite": true, 115 | "composites": { 116 | "client": { 117 | "realm-management": [ 118 | "query-clients" 119 | ] 120 | } 121 | }, 122 | "clientRole": true, 123 | "containerId": "c2963685-912b-44ed-8d8d-647761680cfd", 124 | "attributes": {} 125 | }, 126 | { 127 | "id": "f1094af3-fb5d-496d-a4b9-698bc8d5949a", 128 | "name": "realm-admin", 129 | "description": "${role_realm-admin}", 130 | "composite": true, 131 | "composites": { 132 | "client": { 133 | "realm-management": [ 134 | "manage-authorization", 135 | "create-client", 136 | "manage-realm", 137 | "query-clients", 138 | "view-authorization", 139 | "view-clients", 140 | "query-groups", 141 | "query-users", 142 | "manage-clients", 143 | "query-realms", 144 | "manage-identity-providers", 145 | "view-events", 146 | "manage-users", 147 | "view-realm", 148 | "impersonation", 149 | "view-identity-providers", 150 | "view-users", 151 | "manage-events" 152 | ] 153 | } 154 | }, 155 | "clientRole": true, 156 | "containerId": "c2963685-912b-44ed-8d8d-647761680cfd", 157 | "attributes": {} 158 | }, 159 | { 160 | "id": "4b8ef909-9089-4804-8947-1ed56723f691", 161 | "name": "query-groups", 162 | "description": "${role_query-groups}", 163 | "composite": false, 164 | "clientRole": true, 165 | "containerId": "c2963685-912b-44ed-8d8d-647761680cfd", 166 | "attributes": {} 167 | }, 168 | { 169 | "id": "5c85f147-1069-48d8-9ae1-2f4e140c1b7a", 170 | "name": "manage-clients", 171 | "description": "${role_manage-clients}", 172 | "composite": false, 173 | "clientRole": true, 174 | "containerId": "c2963685-912b-44ed-8d8d-647761680cfd", 175 | "attributes": {} 176 | }, 177 | { 178 | "id": "25c23be8-14e5-4112-8b47-f5348c95d8e6", 179 | "name": "query-users", 180 | "description": "${role_query-users}", 181 | "composite": false, 182 | "clientRole": true, 183 | "containerId": "c2963685-912b-44ed-8d8d-647761680cfd", 184 | "attributes": {} 185 | }, 186 | { 187 | "id": "12dbd571-c866-4a9f-86cf-e95dc3c44951", 188 | "name": "query-realms", 189 | "description": "${role_query-realms}", 190 | "composite": false, 191 | "clientRole": true, 192 | "containerId": "c2963685-912b-44ed-8d8d-647761680cfd", 193 | "attributes": {} 194 | }, 195 | { 196 | "id": "fbd3310e-1536-45a8-be6e-a42763564528", 197 | "name": "manage-identity-providers", 198 | "description": "${role_manage-identity-providers}", 199 | "composite": false, 200 | "clientRole": true, 201 | "containerId": "c2963685-912b-44ed-8d8d-647761680cfd", 202 | "attributes": {} 203 | }, 204 | { 205 | "id": "45d4a4b4-3e5a-4ac0-9256-e77f3a2c76b6", 206 | "name": "view-events", 207 | "description": "${role_view-events}", 208 | "composite": false, 209 | "clientRole": true, 210 | "containerId": "c2963685-912b-44ed-8d8d-647761680cfd", 211 | "attributes": {} 212 | }, 213 | { 214 | "id": "7e8d2f0e-9e33-4395-aa23-b376430fb6cc", 215 | "name": "manage-users", 216 | "description": "${role_manage-users}", 217 | "composite": false, 218 | "clientRole": true, 219 | "containerId": "c2963685-912b-44ed-8d8d-647761680cfd", 220 | "attributes": {} 221 | }, 222 | { 223 | "id": "8bebe532-c237-4188-9064-1036a54c5dcb", 224 | "name": "view-realm", 225 | "description": "${role_view-realm}", 226 | "composite": false, 227 | "clientRole": true, 228 | "containerId": "c2963685-912b-44ed-8d8d-647761680cfd", 229 | "attributes": {} 230 | }, 231 | { 232 | "id": "9702b05b-6167-4330-a9c7-6121e99152bc", 233 | "name": "impersonation", 234 | "description": "${role_impersonation}", 235 | "composite": false, 236 | "clientRole": true, 237 | "containerId": "c2963685-912b-44ed-8d8d-647761680cfd", 238 | "attributes": {} 239 | }, 240 | { 241 | "id": "b138a8dd-1863-4ed7-92c7-b29e6203e4c0", 242 | "name": "view-users", 243 | "description": "${role_view-users}", 244 | "composite": true, 245 | "composites": { 246 | "client": { 247 | "realm-management": [ 248 | "query-users", 249 | "query-groups" 250 | ] 251 | } 252 | }, 253 | "clientRole": true, 254 | "containerId": "c2963685-912b-44ed-8d8d-647761680cfd", 255 | "attributes": {} 256 | }, 257 | { 258 | "id": "31a733cb-7daf-473c-97d1-522e336bf735", 259 | "name": "view-identity-providers", 260 | "description": "${role_view-identity-providers}", 261 | "composite": false, 262 | "clientRole": true, 263 | "containerId": "c2963685-912b-44ed-8d8d-647761680cfd", 264 | "attributes": {} 265 | }, 266 | { 267 | "id": "b6c47552-6eeb-4185-8f66-805a97341b8f", 268 | "name": "manage-events", 269 | "description": "${role_manage-events}", 270 | "composite": false, 271 | "clientRole": true, 272 | "containerId": "c2963685-912b-44ed-8d8d-647761680cfd", 273 | "attributes": {} 274 | } 275 | ], 276 | "security-admin-console": [], 277 | "admin-cli": [], 278 | "oauth2-demo-pkce-client": [], 279 | "oauth2-client-credentials": [], 280 | "account-console": [], 281 | "broker": [ 282 | { 283 | "id": "7327d41b-8e9c-4a27-9572-a81e251b322d", 284 | "name": "read-token", 285 | "description": "${role_read-token}", 286 | "composite": false, 287 | "clientRole": true, 288 | "containerId": "119b3647-6737-4763-93d6-7d02850d02ea", 289 | "attributes": {} 290 | } 291 | ], 292 | "account": [ 293 | { 294 | "id": "65699a58-890a-48b7-832d-c769fa6e5458", 295 | "name": "view-profile", 296 | "description": "${role_view-profile}", 297 | "composite": false, 298 | "clientRole": true, 299 | "containerId": "d93fc419-8f93-4427-b309-e360a5424426", 300 | "attributes": {} 301 | }, 302 | { 303 | "id": "e3ed95db-c030-4b4b-9ff7-c4c5e7af6c71", 304 | "name": "view-consent", 305 | "description": "${role_view-consent}", 306 | "composite": false, 307 | "clientRole": true, 308 | "containerId": "d93fc419-8f93-4427-b309-e360a5424426", 309 | "attributes": {} 310 | }, 311 | { 312 | "id": "31ef2478-7a7b-4391-bc94-d4067c78625c", 313 | "name": "view-applications", 314 | "description": "${role_view-applications}", 315 | "composite": false, 316 | "clientRole": true, 317 | "containerId": "d93fc419-8f93-4427-b309-e360a5424426", 318 | "attributes": {} 319 | }, 320 | { 321 | "id": "3095a78b-4914-4fb9-8878-80d4771752f4", 322 | "name": "manage-consent", 323 | "description": "${role_manage-consent}", 324 | "composite": true, 325 | "composites": { 326 | "client": { 327 | "account": [ 328 | "view-consent" 329 | ] 330 | } 331 | }, 332 | "clientRole": true, 333 | "containerId": "d93fc419-8f93-4427-b309-e360a5424426", 334 | "attributes": {} 335 | }, 336 | { 337 | "id": "fb1b28e0-a01c-4883-a96e-f8e6fbc55f55", 338 | "name": "manage-account", 339 | "description": "${role_manage-account}", 340 | "composite": true, 341 | "composites": { 342 | "client": { 343 | "account": [ 344 | "manage-account-links" 345 | ] 346 | } 347 | }, 348 | "clientRole": true, 349 | "containerId": "d93fc419-8f93-4427-b309-e360a5424426", 350 | "attributes": {} 351 | }, 352 | { 353 | "id": "2a2d1d8e-a728-468a-a082-57aee789142f", 354 | "name": "manage-account-links", 355 | "description": "${role_manage-account-links}", 356 | "composite": false, 357 | "clientRole": true, 358 | "containerId": "d93fc419-8f93-4427-b309-e360a5424426", 359 | "attributes": {} 360 | } 361 | ], 362 | "oauth2-demo-thymeleaf-client": [] 363 | } 364 | }, 365 | "groups": [], 366 | "defaultRoles": [ 367 | "offline_access", 368 | "uma_authorization" 369 | ], 370 | "requiredCredentials": [ 371 | "password" 372 | ], 373 | "otpPolicyType": "totp", 374 | "otpPolicyAlgorithm": "HmacSHA1", 375 | "otpPolicyInitialCounter": 0, 376 | "otpPolicyDigits": 6, 377 | "otpPolicyLookAheadWindow": 1, 378 | "otpPolicyPeriod": 30, 379 | "otpSupportedApplications": [ 380 | "FreeOTP", 381 | "Google Authenticator" 382 | ], 383 | "webAuthnPolicyRpEntityName": "keycloak", 384 | "webAuthnPolicySignatureAlgorithms": [ 385 | "ES256" 386 | ], 387 | "webAuthnPolicyRpId": "", 388 | "webAuthnPolicyAttestationConveyancePreference": "not specified", 389 | "webAuthnPolicyAuthenticatorAttachment": "not specified", 390 | "webAuthnPolicyRequireResidentKey": "not specified", 391 | "webAuthnPolicyUserVerificationRequirement": "not specified", 392 | "webAuthnPolicyCreateTimeout": 0, 393 | "webAuthnPolicyAvoidSameAuthenticatorRegister": false, 394 | "webAuthnPolicyAcceptableAaguids": [], 395 | "webAuthnPolicyPasswordlessRpEntityName": "keycloak", 396 | "webAuthnPolicyPasswordlessSignatureAlgorithms": [ 397 | "ES256" 398 | ], 399 | "webAuthnPolicyPasswordlessRpId": "", 400 | "webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified", 401 | "webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified", 402 | "webAuthnPolicyPasswordlessRequireResidentKey": "not specified", 403 | "webAuthnPolicyPasswordlessUserVerificationRequirement": "not specified", 404 | "webAuthnPolicyPasswordlessCreateTimeout": 0, 405 | "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false, 406 | "webAuthnPolicyPasswordlessAcceptableAaguids": [], 407 | "users": [ 408 | { 409 | "id": "880830e8-30d4-4941-9b95-99561488d400", 410 | "createdTimestamp": 1622284912888, 411 | "username": "service-account-oauth2-client-credentials", 412 | "enabled": true, 413 | "totp": false, 414 | "emailVerified": false, 415 | "serviceAccountClientId": "oauth2-client-credentials", 416 | "disableableCredentialTypes": [], 417 | "requiredActions": [], 418 | "realmRoles": [ 419 | "offline_access", 420 | "uma_authorization" 421 | ], 422 | "clientRoles": { 423 | "account": [ 424 | "view-profile", 425 | "manage-account" 426 | ] 427 | }, 428 | "notBefore": 0, 429 | "groups": [] 430 | } 431 | ], 432 | "scopeMappings": [ 433 | { 434 | "clientScope": "offline_access", 435 | "roles": [ 436 | "offline_access" 437 | ] 438 | } 439 | ], 440 | "clientScopeMappings": { 441 | "account": [ 442 | { 443 | "client": "account-console", 444 | "roles": [ 445 | "manage-account" 446 | ] 447 | } 448 | ] 449 | }, 450 | "clients": [ 451 | { 452 | "id": "d93fc419-8f93-4427-b309-e360a5424426", 453 | "clientId": "account", 454 | "name": "${client_account}", 455 | "rootUrl": "${authBaseUrl}", 456 | "baseUrl": "/realms/oauth2-demo-realm/account/", 457 | "surrogateAuthRequired": false, 458 | "enabled": true, 459 | "alwaysDisplayInConsole": false, 460 | "clientAuthenticatorType": "client-secret", 461 | "secret": "**********", 462 | "defaultRoles": [ 463 | "view-profile", 464 | "manage-account" 465 | ], 466 | "redirectUris": [ 467 | "/realms/oauth2-demo-realm/account/*" 468 | ], 469 | "webOrigins": [], 470 | "notBefore": 0, 471 | "bearerOnly": false, 472 | "consentRequired": false, 473 | "standardFlowEnabled": true, 474 | "implicitFlowEnabled": false, 475 | "directAccessGrantsEnabled": false, 476 | "serviceAccountsEnabled": false, 477 | "publicClient": false, 478 | "frontchannelLogout": false, 479 | "protocol": "openid-connect", 480 | "attributes": {}, 481 | "authenticationFlowBindingOverrides": {}, 482 | "fullScopeAllowed": false, 483 | "nodeReRegistrationTimeout": 0, 484 | "defaultClientScopes": [ 485 | "web-origins", 486 | "role_list", 487 | "profile", 488 | "roles", 489 | "email" 490 | ], 491 | "optionalClientScopes": [ 492 | "address", 493 | "phone", 494 | "offline_access", 495 | "microprofile-jwt" 496 | ] 497 | }, 498 | { 499 | "id": "d82e21dc-adb5-40b9-9c6c-3f6bd32fc726", 500 | "clientId": "account-console", 501 | "name": "${client_account-console}", 502 | "rootUrl": "${authBaseUrl}", 503 | "baseUrl": "/realms/oauth2-client-demo/account/", 504 | "surrogateAuthRequired": false, 505 | "enabled": true, 506 | "alwaysDisplayInConsole": false, 507 | "clientAuthenticatorType": "client-secret", 508 | "secret": "**********", 509 | "redirectUris": [ 510 | "/realms/oauth2-client-demo/account/*" 511 | ], 512 | "webOrigins": [], 513 | "notBefore": 0, 514 | "bearerOnly": false, 515 | "consentRequired": false, 516 | "standardFlowEnabled": true, 517 | "implicitFlowEnabled": false, 518 | "directAccessGrantsEnabled": false, 519 | "serviceAccountsEnabled": false, 520 | "publicClient": true, 521 | "frontchannelLogout": false, 522 | "protocol": "openid-connect", 523 | "attributes": { 524 | "pkce.code.challenge.method": "S256" 525 | }, 526 | "authenticationFlowBindingOverrides": {}, 527 | "fullScopeAllowed": false, 528 | "nodeReRegistrationTimeout": 0, 529 | "protocolMappers": [ 530 | { 531 | "id": "c8ab3bfa-9eeb-42c6-b32a-0583ec2224cd", 532 | "name": "audience resolve", 533 | "protocol": "openid-connect", 534 | "protocolMapper": "oidc-audience-resolve-mapper", 535 | "consentRequired": false, 536 | "config": {} 537 | } 538 | ], 539 | "defaultClientScopes": [ 540 | "web-origins", 541 | "role_list", 542 | "profile", 543 | "roles", 544 | "email" 545 | ], 546 | "optionalClientScopes": [ 547 | "address", 548 | "phone", 549 | "offline_access", 550 | "microprofile-jwt" 551 | ] 552 | }, 553 | { 554 | "id": "4502c3a2-b460-427d-b232-b0575e9ead43", 555 | "clientId": "admin-cli", 556 | "name": "${client_admin-cli}", 557 | "surrogateAuthRequired": false, 558 | "enabled": true, 559 | "alwaysDisplayInConsole": false, 560 | "clientAuthenticatorType": "client-secret", 561 | "secret": "**********", 562 | "redirectUris": [], 563 | "webOrigins": [], 564 | "notBefore": 0, 565 | "bearerOnly": false, 566 | "consentRequired": false, 567 | "standardFlowEnabled": false, 568 | "implicitFlowEnabled": false, 569 | "directAccessGrantsEnabled": true, 570 | "serviceAccountsEnabled": false, 571 | "publicClient": true, 572 | "frontchannelLogout": false, 573 | "protocol": "openid-connect", 574 | "attributes": {}, 575 | "authenticationFlowBindingOverrides": {}, 576 | "fullScopeAllowed": false, 577 | "nodeReRegistrationTimeout": 0, 578 | "defaultClientScopes": [ 579 | "web-origins", 580 | "role_list", 581 | "profile", 582 | "roles", 583 | "email" 584 | ], 585 | "optionalClientScopes": [ 586 | "address", 587 | "phone", 588 | "offline_access", 589 | "microprofile-jwt" 590 | ] 591 | }, 592 | { 593 | "id": "119b3647-6737-4763-93d6-7d02850d02ea", 594 | "clientId": "broker", 595 | "name": "${client_broker}", 596 | "surrogateAuthRequired": false, 597 | "enabled": true, 598 | "alwaysDisplayInConsole": false, 599 | "clientAuthenticatorType": "client-secret", 600 | "secret": "**********", 601 | "redirectUris": [], 602 | "webOrigins": [], 603 | "notBefore": 0, 604 | "bearerOnly": false, 605 | "consentRequired": false, 606 | "standardFlowEnabled": true, 607 | "implicitFlowEnabled": false, 608 | "directAccessGrantsEnabled": false, 609 | "serviceAccountsEnabled": false, 610 | "publicClient": false, 611 | "frontchannelLogout": false, 612 | "protocol": "openid-connect", 613 | "attributes": {}, 614 | "authenticationFlowBindingOverrides": {}, 615 | "fullScopeAllowed": false, 616 | "nodeReRegistrationTimeout": 0, 617 | "defaultClientScopes": [ 618 | "web-origins", 619 | "role_list", 620 | "profile", 621 | "roles", 622 | "email" 623 | ], 624 | "optionalClientScopes": [ 625 | "address", 626 | "phone", 627 | "offline_access", 628 | "microprofile-jwt" 629 | ] 630 | }, 631 | { 632 | "id": "497b2f7c-c4fa-4724-8a9e-7548d271fd3f", 633 | "clientId": "oauth2-client-credentials", 634 | "surrogateAuthRequired": false, 635 | "enabled": true, 636 | "alwaysDisplayInConsole": false, 637 | "clientAuthenticatorType": "client-secret", 638 | "secret": "**********", 639 | "redirectUris": [], 640 | "webOrigins": [], 641 | "notBefore": 0, 642 | "bearerOnly": false, 643 | "consentRequired": false, 644 | "standardFlowEnabled": false, 645 | "implicitFlowEnabled": false, 646 | "directAccessGrantsEnabled": false, 647 | "serviceAccountsEnabled": true, 648 | "publicClient": false, 649 | "frontchannelLogout": false, 650 | "protocol": "openid-connect", 651 | "attributes": { 652 | "saml.assertion.signature": "false", 653 | "saml.force.post.binding": "false", 654 | "saml.multivalued.roles": "false", 655 | "saml.encrypt": "false", 656 | "saml.server.signature": "false", 657 | "saml.server.signature.keyinfo.ext": "false", 658 | "exclude.session.state.from.auth.response": "false", 659 | "saml_force_name_id_format": "false", 660 | "saml.client.signature": "false", 661 | "tls.client.certificate.bound.access.tokens": "false", 662 | "saml.authnstatement": "false", 663 | "display.on.consent.screen": "false", 664 | "saml.onetimeuse.condition": "false" 665 | }, 666 | "authenticationFlowBindingOverrides": {}, 667 | "fullScopeAllowed": true, 668 | "nodeReRegistrationTimeout": -1, 669 | "protocolMappers": [ 670 | { 671 | "id": "399ef863-052a-49ba-ad7a-1fa95a400a4a", 672 | "name": "Client Host", 673 | "protocol": "openid-connect", 674 | "protocolMapper": "oidc-usersessionmodel-note-mapper", 675 | "consentRequired": false, 676 | "config": { 677 | "user.session.note": "clientHost", 678 | "id.token.claim": "true", 679 | "access.token.claim": "true", 680 | "claim.name": "clientHost", 681 | "jsonType.label": "String" 682 | } 683 | }, 684 | { 685 | "id": "7ac5cf19-53a8-4ae9-81c7-2d21187d1d66", 686 | "name": "Client ID", 687 | "protocol": "openid-connect", 688 | "protocolMapper": "oidc-usersessionmodel-note-mapper", 689 | "consentRequired": false, 690 | "config": { 691 | "user.session.note": "clientId", 692 | "id.token.claim": "true", 693 | "access.token.claim": "true", 694 | "claim.name": "clientId", 695 | "jsonType.label": "String" 696 | } 697 | }, 698 | { 699 | "id": "ea2b9e8c-5fc4-4b8f-8916-c029076e72d4", 700 | "name": "Client IP Address", 701 | "protocol": "openid-connect", 702 | "protocolMapper": "oidc-usersessionmodel-note-mapper", 703 | "consentRequired": false, 704 | "config": { 705 | "user.session.note": "clientAddress", 706 | "id.token.claim": "true", 707 | "access.token.claim": "true", 708 | "claim.name": "clientAddress", 709 | "jsonType.label": "String" 710 | } 711 | } 712 | ], 713 | "defaultClientScopes": [ 714 | "web-origins", 715 | "role_list", 716 | "profile", 717 | "roles", 718 | "email" 719 | ], 720 | "optionalClientScopes": [ 721 | "address", 722 | "phone", 723 | "offline_access", 724 | "microprofile-jwt" 725 | ] 726 | }, 727 | { 728 | "id": "7ce93e25-ff4c-4081-8cc3-a5a99316c783", 729 | "clientId": "oauth2-demo-pkce-client", 730 | "surrogateAuthRequired": false, 731 | "enabled": true, 732 | "alwaysDisplayInConsole": false, 733 | "clientAuthenticatorType": "client-secret", 734 | "secret": "**********", 735 | "redirectUris": [ 736 | "http://localhost:4200" 737 | ], 738 | "webOrigins": [ 739 | "*" 740 | ], 741 | "notBefore": 0, 742 | "bearerOnly": false, 743 | "consentRequired": false, 744 | "standardFlowEnabled": true, 745 | "implicitFlowEnabled": true, 746 | "directAccessGrantsEnabled": false, 747 | "serviceAccountsEnabled": false, 748 | "publicClient": true, 749 | "frontchannelLogout": false, 750 | "protocol": "openid-connect", 751 | "attributes": { 752 | "saml.assertion.signature": "false", 753 | "saml.force.post.binding": "false", 754 | "saml.multivalued.roles": "false", 755 | "saml.encrypt": "false", 756 | "saml.server.signature": "false", 757 | "saml.server.signature.keyinfo.ext": "false", 758 | "exclude.session.state.from.auth.response": "false", 759 | "saml_force_name_id_format": "false", 760 | "saml.client.signature": "false", 761 | "tls.client.certificate.bound.access.tokens": "false", 762 | "saml.authnstatement": "false", 763 | "display.on.consent.screen": "false", 764 | "pkce.code.challenge.method": "S256", 765 | "saml.onetimeuse.condition": "false" 766 | }, 767 | "authenticationFlowBindingOverrides": {}, 768 | "fullScopeAllowed": true, 769 | "nodeReRegistrationTimeout": -1, 770 | "defaultClientScopes": [ 771 | "web-origins", 772 | "role_list", 773 | "profile", 774 | "roles", 775 | "email" 776 | ], 777 | "optionalClientScopes": [ 778 | "address", 779 | "phone", 780 | "offline_access", 781 | "microprofile-jwt" 782 | ] 783 | }, 784 | { 785 | "id": "2863e141-a7c5-47c1-b365-e46fe6ab8ba9", 786 | "clientId": "oauth2-demo-thymeleaf-client", 787 | "surrogateAuthRequired": false, 788 | "enabled": true, 789 | "alwaysDisplayInConsole": false, 790 | "clientAuthenticatorType": "client-secret", 791 | "secret": "**********", 792 | "redirectUris": [ 793 | "http://localhost:8080/login/oauth2/code/oauth2-demo-thymeleaf-client" 794 | ], 795 | "webOrigins": [], 796 | "notBefore": 0, 797 | "bearerOnly": false, 798 | "consentRequired": false, 799 | "standardFlowEnabled": true, 800 | "implicitFlowEnabled": false, 801 | "directAccessGrantsEnabled": false, 802 | "serviceAccountsEnabled": false, 803 | "publicClient": false, 804 | "frontchannelLogout": false, 805 | "protocol": "openid-connect", 806 | "attributes": { 807 | "saml.assertion.signature": "false", 808 | "saml.force.post.binding": "false", 809 | "saml.multivalued.roles": "false", 810 | "saml.encrypt": "false", 811 | "saml.server.signature": "false", 812 | "saml.server.signature.keyinfo.ext": "false", 813 | "exclude.session.state.from.auth.response": "false", 814 | "saml_force_name_id_format": "false", 815 | "saml.client.signature": "false", 816 | "tls.client.certificate.bound.access.tokens": "false", 817 | "saml.authnstatement": "false", 818 | "display.on.consent.screen": "false", 819 | "saml.onetimeuse.condition": "false" 820 | }, 821 | "authenticationFlowBindingOverrides": {}, 822 | "fullScopeAllowed": true, 823 | "nodeReRegistrationTimeout": -1, 824 | "defaultClientScopes": [ 825 | "web-origins", 826 | "role_list", 827 | "profile", 828 | "roles", 829 | "email" 830 | ], 831 | "optionalClientScopes": [ 832 | "address", 833 | "phone", 834 | "offline_access", 835 | "microprofile-jwt" 836 | ] 837 | }, 838 | { 839 | "id": "c2963685-912b-44ed-8d8d-647761680cfd", 840 | "clientId": "realm-management", 841 | "name": "${client_realm-management}", 842 | "surrogateAuthRequired": false, 843 | "enabled": true, 844 | "alwaysDisplayInConsole": false, 845 | "clientAuthenticatorType": "client-secret", 846 | "secret": "**********", 847 | "redirectUris": [], 848 | "webOrigins": [], 849 | "notBefore": 0, 850 | "bearerOnly": true, 851 | "consentRequired": false, 852 | "standardFlowEnabled": true, 853 | "implicitFlowEnabled": false, 854 | "directAccessGrantsEnabled": false, 855 | "serviceAccountsEnabled": false, 856 | "publicClient": false, 857 | "frontchannelLogout": false, 858 | "protocol": "openid-connect", 859 | "attributes": {}, 860 | "authenticationFlowBindingOverrides": {}, 861 | "fullScopeAllowed": false, 862 | "nodeReRegistrationTimeout": 0, 863 | "defaultClientScopes": [ 864 | "web-origins", 865 | "role_list", 866 | "profile", 867 | "roles", 868 | "email" 869 | ], 870 | "optionalClientScopes": [ 871 | "address", 872 | "phone", 873 | "offline_access", 874 | "microprofile-jwt" 875 | ] 876 | }, 877 | { 878 | "id": "187cf018-f614-44a1-b35c-8fbb27f05fbe", 879 | "clientId": "security-admin-console", 880 | "name": "${client_security-admin-console}", 881 | "rootUrl": "${authAdminUrl}", 882 | "baseUrl": "/admin/oauth2-demo-realm/console/", 883 | "surrogateAuthRequired": false, 884 | "enabled": true, 885 | "alwaysDisplayInConsole": false, 886 | "clientAuthenticatorType": "client-secret", 887 | "secret": "**********", 888 | "redirectUris": [ 889 | "/admin/oauth2-demo-realm/console/*" 890 | ], 891 | "webOrigins": [ 892 | "+" 893 | ], 894 | "notBefore": 0, 895 | "bearerOnly": false, 896 | "consentRequired": false, 897 | "standardFlowEnabled": true, 898 | "implicitFlowEnabled": false, 899 | "directAccessGrantsEnabled": false, 900 | "serviceAccountsEnabled": false, 901 | "publicClient": true, 902 | "frontchannelLogout": false, 903 | "protocol": "openid-connect", 904 | "attributes": { 905 | "pkce.code.challenge.method": "S256" 906 | }, 907 | "authenticationFlowBindingOverrides": {}, 908 | "fullScopeAllowed": false, 909 | "nodeReRegistrationTimeout": 0, 910 | "protocolMappers": [ 911 | { 912 | "id": "2085fe3c-2d53-4127-bf2b-6be67f7de5c0", 913 | "name": "locale", 914 | "protocol": "openid-connect", 915 | "protocolMapper": "oidc-usermodel-attribute-mapper", 916 | "consentRequired": false, 917 | "config": { 918 | "userinfo.token.claim": "true", 919 | "user.attribute": "locale", 920 | "id.token.claim": "true", 921 | "access.token.claim": "true", 922 | "claim.name": "locale", 923 | "jsonType.label": "String" 924 | } 925 | } 926 | ], 927 | "defaultClientScopes": [ 928 | "web-origins", 929 | "role_list", 930 | "profile", 931 | "roles", 932 | "email" 933 | ], 934 | "optionalClientScopes": [ 935 | "address", 936 | "phone", 937 | "offline_access", 938 | "microprofile-jwt" 939 | ] 940 | } 941 | ], 942 | "clientScopes": [ 943 | { 944 | "id": "d2e2e6c4-163f-4a17-9f7f-f5f4bcc6b570", 945 | "name": "address", 946 | "description": "OpenID Connect built-in scope: address", 947 | "protocol": "openid-connect", 948 | "attributes": { 949 | "include.in.token.scope": "true", 950 | "display.on.consent.screen": "true", 951 | "consent.screen.text": "${addressScopeConsentText}" 952 | }, 953 | "protocolMappers": [ 954 | { 955 | "id": "0315cbbd-6d82-4c6d-b09e-4e1b88b02b0c", 956 | "name": "address", 957 | "protocol": "openid-connect", 958 | "protocolMapper": "oidc-address-mapper", 959 | "consentRequired": false, 960 | "config": { 961 | "user.attribute.formatted": "formatted", 962 | "user.attribute.country": "country", 963 | "user.attribute.postal_code": "postal_code", 964 | "userinfo.token.claim": "true", 965 | "user.attribute.street": "street", 966 | "id.token.claim": "true", 967 | "user.attribute.region": "region", 968 | "access.token.claim": "true", 969 | "user.attribute.locality": "locality" 970 | } 971 | } 972 | ] 973 | }, 974 | { 975 | "id": "7db62edd-270f-4ed7-b7ea-7037f801fe62", 976 | "name": "email", 977 | "description": "OpenID Connect built-in scope: email", 978 | "protocol": "openid-connect", 979 | "attributes": { 980 | "include.in.token.scope": "true", 981 | "display.on.consent.screen": "true", 982 | "consent.screen.text": "${emailScopeConsentText}" 983 | }, 984 | "protocolMappers": [ 985 | { 986 | "id": "abbf0418-186e-4fd5-a743-4ab8a4f2d954", 987 | "name": "email verified", 988 | "protocol": "openid-connect", 989 | "protocolMapper": "oidc-usermodel-property-mapper", 990 | "consentRequired": false, 991 | "config": { 992 | "userinfo.token.claim": "true", 993 | "user.attribute": "emailVerified", 994 | "id.token.claim": "true", 995 | "access.token.claim": "true", 996 | "claim.name": "email_verified", 997 | "jsonType.label": "boolean" 998 | } 999 | }, 1000 | { 1001 | "id": "a222b36e-e7be-4b86-b75e-7ae512ee1e88", 1002 | "name": "email", 1003 | "protocol": "openid-connect", 1004 | "protocolMapper": "oidc-usermodel-property-mapper", 1005 | "consentRequired": false, 1006 | "config": { 1007 | "userinfo.token.claim": "true", 1008 | "user.attribute": "email", 1009 | "id.token.claim": "true", 1010 | "access.token.claim": "true", 1011 | "claim.name": "email", 1012 | "jsonType.label": "String" 1013 | } 1014 | } 1015 | ] 1016 | }, 1017 | { 1018 | "id": "c62b2e8d-1d0a-48a2-b047-b0eb82c301e4", 1019 | "name": "microprofile-jwt", 1020 | "description": "Microprofile - JWT built-in scope", 1021 | "protocol": "openid-connect", 1022 | "attributes": { 1023 | "include.in.token.scope": "true", 1024 | "display.on.consent.screen": "false" 1025 | }, 1026 | "protocolMappers": [ 1027 | { 1028 | "id": "44e4284d-6a02-4a3e-b843-51a61275addf", 1029 | "name": "upn", 1030 | "protocol": "openid-connect", 1031 | "protocolMapper": "oidc-usermodel-property-mapper", 1032 | "consentRequired": false, 1033 | "config": { 1034 | "userinfo.token.claim": "true", 1035 | "user.attribute": "username", 1036 | "id.token.claim": "true", 1037 | "access.token.claim": "true", 1038 | "claim.name": "upn", 1039 | "jsonType.label": "String" 1040 | } 1041 | }, 1042 | { 1043 | "id": "8f63ee0a-0c7c-4ba3-a0bd-1b32c0e217f9", 1044 | "name": "groups", 1045 | "protocol": "openid-connect", 1046 | "protocolMapper": "oidc-usermodel-realm-role-mapper", 1047 | "consentRequired": false, 1048 | "config": { 1049 | "multivalued": "true", 1050 | "userinfo.token.claim": "true", 1051 | "user.attribute": "foo", 1052 | "id.token.claim": "true", 1053 | "access.token.claim": "true", 1054 | "claim.name": "groups", 1055 | "jsonType.label": "String" 1056 | } 1057 | } 1058 | ] 1059 | }, 1060 | { 1061 | "id": "909a7439-f149-4bbb-bc4a-10e24d5e33e6", 1062 | "name": "offline_access", 1063 | "description": "OpenID Connect built-in scope: offline_access", 1064 | "protocol": "openid-connect", 1065 | "attributes": { 1066 | "consent.screen.text": "${offlineAccessScopeConsentText}", 1067 | "display.on.consent.screen": "true" 1068 | } 1069 | }, 1070 | { 1071 | "id": "c66cf7f4-6e08-49d9-be65-478c5429f871", 1072 | "name": "phone", 1073 | "description": "OpenID Connect built-in scope: phone", 1074 | "protocol": "openid-connect", 1075 | "attributes": { 1076 | "include.in.token.scope": "true", 1077 | "display.on.consent.screen": "true", 1078 | "consent.screen.text": "${phoneScopeConsentText}" 1079 | }, 1080 | "protocolMappers": [ 1081 | { 1082 | "id": "c66f9ee4-552b-475d-97df-a282df27559a", 1083 | "name": "phone number verified", 1084 | "protocol": "openid-connect", 1085 | "protocolMapper": "oidc-usermodel-attribute-mapper", 1086 | "consentRequired": false, 1087 | "config": { 1088 | "userinfo.token.claim": "true", 1089 | "user.attribute": "phoneNumberVerified", 1090 | "id.token.claim": "true", 1091 | "access.token.claim": "true", 1092 | "claim.name": "phone_number_verified", 1093 | "jsonType.label": "boolean" 1094 | } 1095 | }, 1096 | { 1097 | "id": "09dda51d-3410-4352-bd06-bf602fc6f323", 1098 | "name": "phone number", 1099 | "protocol": "openid-connect", 1100 | "protocolMapper": "oidc-usermodel-attribute-mapper", 1101 | "consentRequired": false, 1102 | "config": { 1103 | "userinfo.token.claim": "true", 1104 | "user.attribute": "phoneNumber", 1105 | "id.token.claim": "true", 1106 | "access.token.claim": "true", 1107 | "claim.name": "phone_number", 1108 | "jsonType.label": "String" 1109 | } 1110 | } 1111 | ] 1112 | }, 1113 | { 1114 | "id": "a6a08f9e-2457-40d8-b52e-46129504645e", 1115 | "name": "profile", 1116 | "description": "OpenID Connect built-in scope: profile", 1117 | "protocol": "openid-connect", 1118 | "attributes": { 1119 | "include.in.token.scope": "true", 1120 | "display.on.consent.screen": "true", 1121 | "consent.screen.text": "${profileScopeConsentText}" 1122 | }, 1123 | "protocolMappers": [ 1124 | { 1125 | "id": "25b6c93c-5995-4d46-9361-cfe4ec7869b4", 1126 | "name": "nickname", 1127 | "protocol": "openid-connect", 1128 | "protocolMapper": "oidc-usermodel-attribute-mapper", 1129 | "consentRequired": false, 1130 | "config": { 1131 | "userinfo.token.claim": "true", 1132 | "user.attribute": "nickname", 1133 | "id.token.claim": "true", 1134 | "access.token.claim": "true", 1135 | "claim.name": "nickname", 1136 | "jsonType.label": "String" 1137 | } 1138 | }, 1139 | { 1140 | "id": "c79f938e-71da-4e2f-b7b9-0016f5cea1db", 1141 | "name": "updated at", 1142 | "protocol": "openid-connect", 1143 | "protocolMapper": "oidc-usermodel-attribute-mapper", 1144 | "consentRequired": false, 1145 | "config": { 1146 | "userinfo.token.claim": "true", 1147 | "user.attribute": "updatedAt", 1148 | "id.token.claim": "true", 1149 | "access.token.claim": "true", 1150 | "claim.name": "updated_at", 1151 | "jsonType.label": "String" 1152 | } 1153 | }, 1154 | { 1155 | "id": "c764ffbf-9a9b-479f-b4af-182ceed251e8", 1156 | "name": "full name", 1157 | "protocol": "openid-connect", 1158 | "protocolMapper": "oidc-full-name-mapper", 1159 | "consentRequired": false, 1160 | "config": { 1161 | "id.token.claim": "true", 1162 | "access.token.claim": "true", 1163 | "userinfo.token.claim": "true" 1164 | } 1165 | }, 1166 | { 1167 | "id": "712e112b-c118-47f9-81e0-952cd891ff6c", 1168 | "name": "middle name", 1169 | "protocol": "openid-connect", 1170 | "protocolMapper": "oidc-usermodel-attribute-mapper", 1171 | "consentRequired": false, 1172 | "config": { 1173 | "userinfo.token.claim": "true", 1174 | "user.attribute": "middleName", 1175 | "id.token.claim": "true", 1176 | "access.token.claim": "true", 1177 | "claim.name": "middle_name", 1178 | "jsonType.label": "String" 1179 | } 1180 | }, 1181 | { 1182 | "id": "68e39a6e-f9d9-435b-9ea0-a4556fc02d59", 1183 | "name": "given name", 1184 | "protocol": "openid-connect", 1185 | "protocolMapper": "oidc-usermodel-property-mapper", 1186 | "consentRequired": false, 1187 | "config": { 1188 | "userinfo.token.claim": "true", 1189 | "user.attribute": "firstName", 1190 | "id.token.claim": "true", 1191 | "access.token.claim": "true", 1192 | "claim.name": "given_name", 1193 | "jsonType.label": "String" 1194 | } 1195 | }, 1196 | { 1197 | "id": "5a0d7e26-c953-430c-9858-a394bafa511d", 1198 | "name": "username", 1199 | "protocol": "openid-connect", 1200 | "protocolMapper": "oidc-usermodel-property-mapper", 1201 | "consentRequired": false, 1202 | "config": { 1203 | "userinfo.token.claim": "true", 1204 | "user.attribute": "username", 1205 | "id.token.claim": "true", 1206 | "access.token.claim": "true", 1207 | "claim.name": "preferred_username", 1208 | "jsonType.label": "String" 1209 | } 1210 | }, 1211 | { 1212 | "id": "58ca1e3f-44d1-4577-a8d1-9978d5a4f480", 1213 | "name": "locale", 1214 | "protocol": "openid-connect", 1215 | "protocolMapper": "oidc-usermodel-attribute-mapper", 1216 | "consentRequired": false, 1217 | "config": { 1218 | "userinfo.token.claim": "true", 1219 | "user.attribute": "locale", 1220 | "id.token.claim": "true", 1221 | "access.token.claim": "true", 1222 | "claim.name": "locale", 1223 | "jsonType.label": "String" 1224 | } 1225 | }, 1226 | { 1227 | "id": "d02b46eb-12a9-4da8-a856-da0b0bbf4732", 1228 | "name": "profile", 1229 | "protocol": "openid-connect", 1230 | "protocolMapper": "oidc-usermodel-attribute-mapper", 1231 | "consentRequired": false, 1232 | "config": { 1233 | "userinfo.token.claim": "true", 1234 | "user.attribute": "profile", 1235 | "id.token.claim": "true", 1236 | "access.token.claim": "true", 1237 | "claim.name": "profile", 1238 | "jsonType.label": "String" 1239 | } 1240 | }, 1241 | { 1242 | "id": "76d3bd39-1007-48b7-a898-d56b54ce899e", 1243 | "name": "gender", 1244 | "protocol": "openid-connect", 1245 | "protocolMapper": "oidc-usermodel-attribute-mapper", 1246 | "consentRequired": false, 1247 | "config": { 1248 | "userinfo.token.claim": "true", 1249 | "user.attribute": "gender", 1250 | "id.token.claim": "true", 1251 | "access.token.claim": "true", 1252 | "claim.name": "gender", 1253 | "jsonType.label": "String" 1254 | } 1255 | }, 1256 | { 1257 | "id": "ea1d9fae-204c-4c0c-b469-ddba9160fed7", 1258 | "name": "zoneinfo", 1259 | "protocol": "openid-connect", 1260 | "protocolMapper": "oidc-usermodel-attribute-mapper", 1261 | "consentRequired": false, 1262 | "config": { 1263 | "userinfo.token.claim": "true", 1264 | "user.attribute": "zoneinfo", 1265 | "id.token.claim": "true", 1266 | "access.token.claim": "true", 1267 | "claim.name": "zoneinfo", 1268 | "jsonType.label": "String" 1269 | } 1270 | }, 1271 | { 1272 | "id": "2b5924d8-cb99-4098-b418-131c7ad6f74e", 1273 | "name": "family name", 1274 | "protocol": "openid-connect", 1275 | "protocolMapper": "oidc-usermodel-property-mapper", 1276 | "consentRequired": false, 1277 | "config": { 1278 | "userinfo.token.claim": "true", 1279 | "user.attribute": "lastName", 1280 | "id.token.claim": "true", 1281 | "access.token.claim": "true", 1282 | "claim.name": "family_name", 1283 | "jsonType.label": "String" 1284 | } 1285 | }, 1286 | { 1287 | "id": "4f59f02f-5e06-49bc-889f-42c1a50ead35", 1288 | "name": "picture", 1289 | "protocol": "openid-connect", 1290 | "protocolMapper": "oidc-usermodel-attribute-mapper", 1291 | "consentRequired": false, 1292 | "config": { 1293 | "userinfo.token.claim": "true", 1294 | "user.attribute": "picture", 1295 | "id.token.claim": "true", 1296 | "access.token.claim": "true", 1297 | "claim.name": "picture", 1298 | "jsonType.label": "String" 1299 | } 1300 | }, 1301 | { 1302 | "id": "2005be4a-a246-4b38-a71f-fda6e73b81d9", 1303 | "name": "website", 1304 | "protocol": "openid-connect", 1305 | "protocolMapper": "oidc-usermodel-attribute-mapper", 1306 | "consentRequired": false, 1307 | "config": { 1308 | "userinfo.token.claim": "true", 1309 | "user.attribute": "website", 1310 | "id.token.claim": "true", 1311 | "access.token.claim": "true", 1312 | "claim.name": "website", 1313 | "jsonType.label": "String" 1314 | } 1315 | }, 1316 | { 1317 | "id": "7758033d-6808-47a6-8da0-9dd62f38bfb5", 1318 | "name": "birthdate", 1319 | "protocol": "openid-connect", 1320 | "protocolMapper": "oidc-usermodel-attribute-mapper", 1321 | "consentRequired": false, 1322 | "config": { 1323 | "userinfo.token.claim": "true", 1324 | "user.attribute": "birthdate", 1325 | "id.token.claim": "true", 1326 | "access.token.claim": "true", 1327 | "claim.name": "birthdate", 1328 | "jsonType.label": "String" 1329 | } 1330 | } 1331 | ] 1332 | }, 1333 | { 1334 | "id": "bd891c0e-66bb-4779-94c4-1b868c043cb9", 1335 | "name": "role_list", 1336 | "description": "SAML role list", 1337 | "protocol": "saml", 1338 | "attributes": { 1339 | "consent.screen.text": "${samlRoleListScopeConsentText}", 1340 | "display.on.consent.screen": "true" 1341 | }, 1342 | "protocolMappers": [ 1343 | { 1344 | "id": "d7e1e7f2-cdc5-41cc-af7c-e2cb5f25c224", 1345 | "name": "role list", 1346 | "protocol": "saml", 1347 | "protocolMapper": "saml-role-list-mapper", 1348 | "consentRequired": false, 1349 | "config": { 1350 | "single": "false", 1351 | "attribute.nameformat": "Basic", 1352 | "attribute.name": "Role" 1353 | } 1354 | } 1355 | ] 1356 | }, 1357 | { 1358 | "id": "e1f19da4-5a86-4e9f-9538-c34cf400a792", 1359 | "name": "roles", 1360 | "description": "OpenID Connect scope for add user roles to the access token", 1361 | "protocol": "openid-connect", 1362 | "attributes": { 1363 | "include.in.token.scope": "false", 1364 | "display.on.consent.screen": "true", 1365 | "consent.screen.text": "${rolesScopeConsentText}" 1366 | }, 1367 | "protocolMappers": [ 1368 | { 1369 | "id": "d89b382b-2697-4f88-aaf0-955f92093029", 1370 | "name": "audience resolve", 1371 | "protocol": "openid-connect", 1372 | "protocolMapper": "oidc-audience-resolve-mapper", 1373 | "consentRequired": false, 1374 | "config": {} 1375 | }, 1376 | { 1377 | "id": "4a4cb27e-b6c4-4097-9245-cd1fb2c66eff", 1378 | "name": "realm roles", 1379 | "protocol": "openid-connect", 1380 | "protocolMapper": "oidc-usermodel-realm-role-mapper", 1381 | "consentRequired": false, 1382 | "config": { 1383 | "user.attribute": "foo", 1384 | "access.token.claim": "true", 1385 | "claim.name": "realm_access.roles", 1386 | "jsonType.label": "String", 1387 | "multivalued": "true" 1388 | } 1389 | }, 1390 | { 1391 | "id": "bc9c6717-8937-4e8d-b8c6-871ec97e1f42", 1392 | "name": "client roles", 1393 | "protocol": "openid-connect", 1394 | "protocolMapper": "oidc-usermodel-client-role-mapper", 1395 | "consentRequired": false, 1396 | "config": { 1397 | "user.attribute": "foo", 1398 | "access.token.claim": "true", 1399 | "claim.name": "resource_access.${client_id}.roles", 1400 | "jsonType.label": "String", 1401 | "multivalued": "true" 1402 | } 1403 | } 1404 | ] 1405 | }, 1406 | { 1407 | "id": "d0f5445d-0808-4726-bb3c-961c3187db64", 1408 | "name": "web-origins", 1409 | "description": "OpenID Connect scope for add allowed web origins to the access token", 1410 | "protocol": "openid-connect", 1411 | "attributes": { 1412 | "include.in.token.scope": "false", 1413 | "display.on.consent.screen": "false", 1414 | "consent.screen.text": "" 1415 | }, 1416 | "protocolMappers": [ 1417 | { 1418 | "id": "74068ace-4abf-46c7-8a82-49bc260ddc6c", 1419 | "name": "allowed web origins", 1420 | "protocol": "openid-connect", 1421 | "protocolMapper": "oidc-allowed-origins-mapper", 1422 | "consentRequired": false, 1423 | "config": {} 1424 | } 1425 | ] 1426 | } 1427 | ], 1428 | "defaultDefaultClientScopes": [ 1429 | "role_list", 1430 | "profile", 1431 | "email", 1432 | "roles", 1433 | "web-origins" 1434 | ], 1435 | "defaultOptionalClientScopes": [ 1436 | "offline_access", 1437 | "address", 1438 | "phone", 1439 | "microprofile-jwt" 1440 | ], 1441 | "browserSecurityHeaders": { 1442 | "contentSecurityPolicyReportOnly": "", 1443 | "xContentTypeOptions": "nosniff", 1444 | "xRobotsTag": "none", 1445 | "xFrameOptions": "SAMEORIGIN", 1446 | "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", 1447 | "xXSSProtection": "1; mode=block", 1448 | "strictTransportSecurity": "max-age=31536000; includeSubDomains" 1449 | }, 1450 | "smtpServer": {}, 1451 | "eventsEnabled": false, 1452 | "eventsListeners": [ 1453 | "jboss-logging" 1454 | ], 1455 | "enabledEventTypes": [], 1456 | "adminEventsEnabled": false, 1457 | "adminEventsDetailsEnabled": false, 1458 | "components": { 1459 | "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [ 1460 | { 1461 | "id": "31e163b0-33cc-4d22-851c-3bbde2f735f7", 1462 | "name": "Allowed Client Scopes", 1463 | "providerId": "allowed-client-templates", 1464 | "subType": "anonymous", 1465 | "subComponents": {}, 1466 | "config": { 1467 | "allow-default-scopes": [ 1468 | "true" 1469 | ] 1470 | } 1471 | }, 1472 | { 1473 | "id": "a4278b6a-c0b0-4c19-8ea0-1ab4943d8d01", 1474 | "name": "Trusted Hosts", 1475 | "providerId": "trusted-hosts", 1476 | "subType": "anonymous", 1477 | "subComponents": {}, 1478 | "config": { 1479 | "host-sending-registration-request-must-match": [ 1480 | "true" 1481 | ], 1482 | "client-uris-must-match": [ 1483 | "true" 1484 | ] 1485 | } 1486 | }, 1487 | { 1488 | "id": "77a877a3-2d0a-4c0f-a4e0-2641db266d7f", 1489 | "name": "Full Scope Disabled", 1490 | "providerId": "scope", 1491 | "subType": "anonymous", 1492 | "subComponents": {}, 1493 | "config": {} 1494 | }, 1495 | { 1496 | "id": "33b0e92d-f018-4846-8ef5-354070aa9f12", 1497 | "name": "Allowed Client Scopes", 1498 | "providerId": "allowed-client-templates", 1499 | "subType": "authenticated", 1500 | "subComponents": {}, 1501 | "config": { 1502 | "allow-default-scopes": [ 1503 | "true" 1504 | ] 1505 | } 1506 | }, 1507 | { 1508 | "id": "a5278942-7d32-4cfd-85fd-37f743f3dca0", 1509 | "name": "Consent Required", 1510 | "providerId": "consent-required", 1511 | "subType": "anonymous", 1512 | "subComponents": {}, 1513 | "config": {} 1514 | }, 1515 | { 1516 | "id": "b7367461-f3d1-4061-bc8f-92aabceb9e47", 1517 | "name": "Allowed Protocol Mapper Types", 1518 | "providerId": "allowed-protocol-mappers", 1519 | "subType": "anonymous", 1520 | "subComponents": {}, 1521 | "config": { 1522 | "allowed-protocol-mapper-types": [ 1523 | "oidc-full-name-mapper", 1524 | "oidc-address-mapper", 1525 | "oidc-usermodel-property-mapper", 1526 | "oidc-usermodel-attribute-mapper", 1527 | "saml-user-attribute-mapper", 1528 | "saml-role-list-mapper", 1529 | "saml-user-property-mapper", 1530 | "oidc-sha256-pairwise-sub-mapper" 1531 | ] 1532 | } 1533 | }, 1534 | { 1535 | "id": "332e210b-237b-473a-9a7c-c6a153366b46", 1536 | "name": "Allowed Protocol Mapper Types", 1537 | "providerId": "allowed-protocol-mappers", 1538 | "subType": "authenticated", 1539 | "subComponents": {}, 1540 | "config": { 1541 | "allowed-protocol-mapper-types": [ 1542 | "oidc-usermodel-property-mapper", 1543 | "oidc-sha256-pairwise-sub-mapper", 1544 | "oidc-full-name-mapper", 1545 | "oidc-usermodel-attribute-mapper", 1546 | "saml-user-property-mapper", 1547 | "oidc-address-mapper", 1548 | "saml-user-attribute-mapper", 1549 | "saml-role-list-mapper" 1550 | ] 1551 | } 1552 | }, 1553 | { 1554 | "id": "3c6c0da2-7c4d-478a-a732-3c00c8cd6244", 1555 | "name": "Max Clients Limit", 1556 | "providerId": "max-clients", 1557 | "subType": "anonymous", 1558 | "subComponents": {}, 1559 | "config": { 1560 | "max-clients": [ 1561 | "200" 1562 | ] 1563 | } 1564 | } 1565 | ], 1566 | "org.keycloak.keys.KeyProvider": [ 1567 | { 1568 | "id": "20bbe10c-5011-4ccc-81d9-69890ee93f55", 1569 | "name": "aes-generated", 1570 | "providerId": "aes-generated", 1571 | "subComponents": {}, 1572 | "config": { 1573 | "priority": [ 1574 | "100" 1575 | ] 1576 | } 1577 | }, 1578 | { 1579 | "id": "9ca3e17d-7f45-40c7-9c33-7d3b3fb4d02d", 1580 | "name": "rsa-generated", 1581 | "providerId": "rsa-generated", 1582 | "subComponents": {}, 1583 | "config": { 1584 | "priority": [ 1585 | "100" 1586 | ] 1587 | } 1588 | }, 1589 | { 1590 | "id": "531ac449-14d7-4e72-8c3d-06d48105b9a3", 1591 | "name": "hmac-generated", 1592 | "providerId": "hmac-generated", 1593 | "subComponents": {}, 1594 | "config": { 1595 | "priority": [ 1596 | "100" 1597 | ], 1598 | "algorithm": [ 1599 | "HS256" 1600 | ] 1601 | } 1602 | } 1603 | ] 1604 | }, 1605 | "internationalizationEnabled": false, 1606 | "supportedLocales": [], 1607 | "authenticationFlows": [ 1608 | { 1609 | "id": "dbf4f747-8f9f-4e2a-aa5c-15f3936e8e8d", 1610 | "alias": "Account verification options", 1611 | "description": "Method with which to verity the existing account", 1612 | "providerId": "basic-flow", 1613 | "topLevel": false, 1614 | "builtIn": true, 1615 | "authenticationExecutions": [ 1616 | { 1617 | "authenticator": "idp-email-verification", 1618 | "requirement": "ALTERNATIVE", 1619 | "priority": 10, 1620 | "userSetupAllowed": false, 1621 | "autheticatorFlow": false 1622 | }, 1623 | { 1624 | "requirement": "ALTERNATIVE", 1625 | "priority": 20, 1626 | "flowAlias": "Verify Existing Account by Re-authentication", 1627 | "userSetupAllowed": false, 1628 | "autheticatorFlow": true 1629 | } 1630 | ] 1631 | }, 1632 | { 1633 | "id": "74168dcc-2d8b-4a4d-96d6-1d8a34fd6d0d", 1634 | "alias": "Authentication Options", 1635 | "description": "Authentication options.", 1636 | "providerId": "basic-flow", 1637 | "topLevel": false, 1638 | "builtIn": true, 1639 | "authenticationExecutions": [ 1640 | { 1641 | "authenticator": "basic-auth", 1642 | "requirement": "REQUIRED", 1643 | "priority": 10, 1644 | "userSetupAllowed": false, 1645 | "autheticatorFlow": false 1646 | }, 1647 | { 1648 | "authenticator": "basic-auth-otp", 1649 | "requirement": "DISABLED", 1650 | "priority": 20, 1651 | "userSetupAllowed": false, 1652 | "autheticatorFlow": false 1653 | }, 1654 | { 1655 | "authenticator": "auth-spnego", 1656 | "requirement": "DISABLED", 1657 | "priority": 30, 1658 | "userSetupAllowed": false, 1659 | "autheticatorFlow": false 1660 | } 1661 | ] 1662 | }, 1663 | { 1664 | "id": "2838e1be-ab90-4c26-82fb-0f9b18e31701", 1665 | "alias": "Browser - Conditional OTP", 1666 | "description": "Flow to determine if the OTP is required for the authentication", 1667 | "providerId": "basic-flow", 1668 | "topLevel": false, 1669 | "builtIn": true, 1670 | "authenticationExecutions": [ 1671 | { 1672 | "authenticator": "conditional-user-configured", 1673 | "requirement": "REQUIRED", 1674 | "priority": 10, 1675 | "userSetupAllowed": false, 1676 | "autheticatorFlow": false 1677 | }, 1678 | { 1679 | "authenticator": "auth-otp-form", 1680 | "requirement": "REQUIRED", 1681 | "priority": 20, 1682 | "userSetupAllowed": false, 1683 | "autheticatorFlow": false 1684 | } 1685 | ] 1686 | }, 1687 | { 1688 | "id": "fbd6bb79-fc4a-48d7-809e-85798d04778f", 1689 | "alias": "Direct Grant - Conditional OTP", 1690 | "description": "Flow to determine if the OTP is required for the authentication", 1691 | "providerId": "basic-flow", 1692 | "topLevel": false, 1693 | "builtIn": true, 1694 | "authenticationExecutions": [ 1695 | { 1696 | "authenticator": "conditional-user-configured", 1697 | "requirement": "REQUIRED", 1698 | "priority": 10, 1699 | "userSetupAllowed": false, 1700 | "autheticatorFlow": false 1701 | }, 1702 | { 1703 | "authenticator": "direct-grant-validate-otp", 1704 | "requirement": "REQUIRED", 1705 | "priority": 20, 1706 | "userSetupAllowed": false, 1707 | "autheticatorFlow": false 1708 | } 1709 | ] 1710 | }, 1711 | { 1712 | "id": "f1b84390-6dea-496f-8d7c-ef8014142ec5", 1713 | "alias": "First broker login - Conditional OTP", 1714 | "description": "Flow to determine if the OTP is required for the authentication", 1715 | "providerId": "basic-flow", 1716 | "topLevel": false, 1717 | "builtIn": true, 1718 | "authenticationExecutions": [ 1719 | { 1720 | "authenticator": "conditional-user-configured", 1721 | "requirement": "REQUIRED", 1722 | "priority": 10, 1723 | "userSetupAllowed": false, 1724 | "autheticatorFlow": false 1725 | }, 1726 | { 1727 | "authenticator": "auth-otp-form", 1728 | "requirement": "REQUIRED", 1729 | "priority": 20, 1730 | "userSetupAllowed": false, 1731 | "autheticatorFlow": false 1732 | } 1733 | ] 1734 | }, 1735 | { 1736 | "id": "83c4c9c2-3fc7-4bee-95c0-23659fc1e7f9", 1737 | "alias": "Handle Existing Account", 1738 | "description": "Handle what to do if there is existing account with same email/username like authenticated identity provider", 1739 | "providerId": "basic-flow", 1740 | "topLevel": false, 1741 | "builtIn": true, 1742 | "authenticationExecutions": [ 1743 | { 1744 | "authenticator": "idp-confirm-link", 1745 | "requirement": "REQUIRED", 1746 | "priority": 10, 1747 | "userSetupAllowed": false, 1748 | "autheticatorFlow": false 1749 | }, 1750 | { 1751 | "requirement": "REQUIRED", 1752 | "priority": 20, 1753 | "flowAlias": "Account verification options", 1754 | "userSetupAllowed": false, 1755 | "autheticatorFlow": true 1756 | } 1757 | ] 1758 | }, 1759 | { 1760 | "id": "0b208fa5-81dc-410b-a086-fc4406ff9968", 1761 | "alias": "Reset - Conditional OTP", 1762 | "description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", 1763 | "providerId": "basic-flow", 1764 | "topLevel": false, 1765 | "builtIn": true, 1766 | "authenticationExecutions": [ 1767 | { 1768 | "authenticator": "conditional-user-configured", 1769 | "requirement": "REQUIRED", 1770 | "priority": 10, 1771 | "userSetupAllowed": false, 1772 | "autheticatorFlow": false 1773 | }, 1774 | { 1775 | "authenticator": "reset-otp", 1776 | "requirement": "REQUIRED", 1777 | "priority": 20, 1778 | "userSetupAllowed": false, 1779 | "autheticatorFlow": false 1780 | } 1781 | ] 1782 | }, 1783 | { 1784 | "id": "f0e9c72a-6088-4542-a51a-987aebd85b2a", 1785 | "alias": "User creation or linking", 1786 | "description": "Flow for the existing/non-existing user alternatives", 1787 | "providerId": "basic-flow", 1788 | "topLevel": false, 1789 | "builtIn": true, 1790 | "authenticationExecutions": [ 1791 | { 1792 | "authenticatorConfig": "create unique user config", 1793 | "authenticator": "idp-create-user-if-unique", 1794 | "requirement": "ALTERNATIVE", 1795 | "priority": 10, 1796 | "userSetupAllowed": false, 1797 | "autheticatorFlow": false 1798 | }, 1799 | { 1800 | "requirement": "ALTERNATIVE", 1801 | "priority": 20, 1802 | "flowAlias": "Handle Existing Account", 1803 | "userSetupAllowed": false, 1804 | "autheticatorFlow": true 1805 | } 1806 | ] 1807 | }, 1808 | { 1809 | "id": "a3b206a5-190c-428b-9411-f4a0a74fc84e", 1810 | "alias": "Verify Existing Account by Re-authentication", 1811 | "description": "Reauthentication of existing account", 1812 | "providerId": "basic-flow", 1813 | "topLevel": false, 1814 | "builtIn": true, 1815 | "authenticationExecutions": [ 1816 | { 1817 | "authenticator": "idp-username-password-form", 1818 | "requirement": "REQUIRED", 1819 | "priority": 10, 1820 | "userSetupAllowed": false, 1821 | "autheticatorFlow": false 1822 | }, 1823 | { 1824 | "requirement": "CONDITIONAL", 1825 | "priority": 20, 1826 | "flowAlias": "First broker login - Conditional OTP", 1827 | "userSetupAllowed": false, 1828 | "autheticatorFlow": true 1829 | } 1830 | ] 1831 | }, 1832 | { 1833 | "id": "5de9e12f-bc38-432c-9bcd-2bf010fa605d", 1834 | "alias": "browser", 1835 | "description": "browser based authentication", 1836 | "providerId": "basic-flow", 1837 | "topLevel": true, 1838 | "builtIn": true, 1839 | "authenticationExecutions": [ 1840 | { 1841 | "authenticator": "auth-cookie", 1842 | "requirement": "ALTERNATIVE", 1843 | "priority": 10, 1844 | "userSetupAllowed": false, 1845 | "autheticatorFlow": false 1846 | }, 1847 | { 1848 | "authenticator": "auth-spnego", 1849 | "requirement": "DISABLED", 1850 | "priority": 20, 1851 | "userSetupAllowed": false, 1852 | "autheticatorFlow": false 1853 | }, 1854 | { 1855 | "authenticator": "identity-provider-redirector", 1856 | "requirement": "ALTERNATIVE", 1857 | "priority": 25, 1858 | "userSetupAllowed": false, 1859 | "autheticatorFlow": false 1860 | }, 1861 | { 1862 | "requirement": "ALTERNATIVE", 1863 | "priority": 30, 1864 | "flowAlias": "forms", 1865 | "userSetupAllowed": false, 1866 | "autheticatorFlow": true 1867 | } 1868 | ] 1869 | }, 1870 | { 1871 | "id": "e9c6918a-87ca-4c53-b789-649bd9c5623d", 1872 | "alias": "clients", 1873 | "description": "Base authentication for clients", 1874 | "providerId": "client-flow", 1875 | "topLevel": true, 1876 | "builtIn": true, 1877 | "authenticationExecutions": [ 1878 | { 1879 | "authenticator": "client-secret", 1880 | "requirement": "ALTERNATIVE", 1881 | "priority": 10, 1882 | "userSetupAllowed": false, 1883 | "autheticatorFlow": false 1884 | }, 1885 | { 1886 | "authenticator": "client-jwt", 1887 | "requirement": "ALTERNATIVE", 1888 | "priority": 20, 1889 | "userSetupAllowed": false, 1890 | "autheticatorFlow": false 1891 | }, 1892 | { 1893 | "authenticator": "client-secret-jwt", 1894 | "requirement": "ALTERNATIVE", 1895 | "priority": 30, 1896 | "userSetupAllowed": false, 1897 | "autheticatorFlow": false 1898 | }, 1899 | { 1900 | "authenticator": "client-x509", 1901 | "requirement": "ALTERNATIVE", 1902 | "priority": 40, 1903 | "userSetupAllowed": false, 1904 | "autheticatorFlow": false 1905 | } 1906 | ] 1907 | }, 1908 | { 1909 | "id": "ec53e19c-cfd4-417b-84cd-81a3d6c6b359", 1910 | "alias": "direct grant", 1911 | "description": "OpenID Connect Resource Owner Grant", 1912 | "providerId": "basic-flow", 1913 | "topLevel": true, 1914 | "builtIn": true, 1915 | "authenticationExecutions": [ 1916 | { 1917 | "authenticator": "direct-grant-validate-username", 1918 | "requirement": "REQUIRED", 1919 | "priority": 10, 1920 | "userSetupAllowed": false, 1921 | "autheticatorFlow": false 1922 | }, 1923 | { 1924 | "authenticator": "direct-grant-validate-password", 1925 | "requirement": "REQUIRED", 1926 | "priority": 20, 1927 | "userSetupAllowed": false, 1928 | "autheticatorFlow": false 1929 | }, 1930 | { 1931 | "requirement": "CONDITIONAL", 1932 | "priority": 30, 1933 | "flowAlias": "Direct Grant - Conditional OTP", 1934 | "userSetupAllowed": false, 1935 | "autheticatorFlow": true 1936 | } 1937 | ] 1938 | }, 1939 | { 1940 | "id": "8d2540a3-756a-476f-851e-d56c7a7e9363", 1941 | "alias": "docker auth", 1942 | "description": "Used by Docker clients to authenticate against the IDP", 1943 | "providerId": "basic-flow", 1944 | "topLevel": true, 1945 | "builtIn": true, 1946 | "authenticationExecutions": [ 1947 | { 1948 | "authenticator": "docker-http-basic-authenticator", 1949 | "requirement": "REQUIRED", 1950 | "priority": 10, 1951 | "userSetupAllowed": false, 1952 | "autheticatorFlow": false 1953 | } 1954 | ] 1955 | }, 1956 | { 1957 | "id": "20ba9e54-8d10-4f97-a6ee-10d82286602b", 1958 | "alias": "first broker login", 1959 | "description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", 1960 | "providerId": "basic-flow", 1961 | "topLevel": true, 1962 | "builtIn": true, 1963 | "authenticationExecutions": [ 1964 | { 1965 | "authenticatorConfig": "review profile config", 1966 | "authenticator": "idp-review-profile", 1967 | "requirement": "REQUIRED", 1968 | "priority": 10, 1969 | "userSetupAllowed": false, 1970 | "autheticatorFlow": false 1971 | }, 1972 | { 1973 | "requirement": "REQUIRED", 1974 | "priority": 20, 1975 | "flowAlias": "User creation or linking", 1976 | "userSetupAllowed": false, 1977 | "autheticatorFlow": true 1978 | } 1979 | ] 1980 | }, 1981 | { 1982 | "id": "4e579d59-6a61-4911-ae9f-eef2c56647fc", 1983 | "alias": "forms", 1984 | "description": "Username, password, otp and other auth forms.", 1985 | "providerId": "basic-flow", 1986 | "topLevel": false, 1987 | "builtIn": true, 1988 | "authenticationExecutions": [ 1989 | { 1990 | "authenticator": "auth-username-password-form", 1991 | "requirement": "REQUIRED", 1992 | "priority": 10, 1993 | "userSetupAllowed": false, 1994 | "autheticatorFlow": false 1995 | }, 1996 | { 1997 | "requirement": "CONDITIONAL", 1998 | "priority": 20, 1999 | "flowAlias": "Browser - Conditional OTP", 2000 | "userSetupAllowed": false, 2001 | "autheticatorFlow": true 2002 | } 2003 | ] 2004 | }, 2005 | { 2006 | "id": "8f19f830-068f-48ee-b670-78d442512ef2", 2007 | "alias": "http challenge", 2008 | "description": "An authentication flow based on challenge-response HTTP Authentication Schemes", 2009 | "providerId": "basic-flow", 2010 | "topLevel": true, 2011 | "builtIn": true, 2012 | "authenticationExecutions": [ 2013 | { 2014 | "authenticator": "no-cookie-redirect", 2015 | "requirement": "REQUIRED", 2016 | "priority": 10, 2017 | "userSetupAllowed": false, 2018 | "autheticatorFlow": false 2019 | }, 2020 | { 2021 | "requirement": "REQUIRED", 2022 | "priority": 20, 2023 | "flowAlias": "Authentication Options", 2024 | "userSetupAllowed": false, 2025 | "autheticatorFlow": true 2026 | } 2027 | ] 2028 | }, 2029 | { 2030 | "id": "341cd9c3-c62e-47ac-8176-5023569f9f33", 2031 | "alias": "registration", 2032 | "description": "registration flow", 2033 | "providerId": "basic-flow", 2034 | "topLevel": true, 2035 | "builtIn": true, 2036 | "authenticationExecutions": [ 2037 | { 2038 | "authenticator": "registration-page-form", 2039 | "requirement": "REQUIRED", 2040 | "priority": 10, 2041 | "flowAlias": "registration form", 2042 | "userSetupAllowed": false, 2043 | "autheticatorFlow": true 2044 | } 2045 | ] 2046 | }, 2047 | { 2048 | "id": "e39c3ab1-da62-48d8-967f-daa4eb22cdd0", 2049 | "alias": "registration form", 2050 | "description": "registration form", 2051 | "providerId": "form-flow", 2052 | "topLevel": false, 2053 | "builtIn": true, 2054 | "authenticationExecutions": [ 2055 | { 2056 | "authenticator": "registration-user-creation", 2057 | "requirement": "REQUIRED", 2058 | "priority": 20, 2059 | "userSetupAllowed": false, 2060 | "autheticatorFlow": false 2061 | }, 2062 | { 2063 | "authenticator": "registration-profile-action", 2064 | "requirement": "REQUIRED", 2065 | "priority": 40, 2066 | "userSetupAllowed": false, 2067 | "autheticatorFlow": false 2068 | }, 2069 | { 2070 | "authenticator": "registration-password-action", 2071 | "requirement": "REQUIRED", 2072 | "priority": 50, 2073 | "userSetupAllowed": false, 2074 | "autheticatorFlow": false 2075 | }, 2076 | { 2077 | "authenticator": "registration-recaptcha-action", 2078 | "requirement": "DISABLED", 2079 | "priority": 60, 2080 | "userSetupAllowed": false, 2081 | "autheticatorFlow": false 2082 | } 2083 | ] 2084 | }, 2085 | { 2086 | "id": "7e63a721-a42e-4ad0-9cbd-3f2aa6c2c387", 2087 | "alias": "reset credentials", 2088 | "description": "Reset credentials for a user if they forgot their password or something", 2089 | "providerId": "basic-flow", 2090 | "topLevel": true, 2091 | "builtIn": true, 2092 | "authenticationExecutions": [ 2093 | { 2094 | "authenticator": "reset-credentials-choose-user", 2095 | "requirement": "REQUIRED", 2096 | "priority": 10, 2097 | "userSetupAllowed": false, 2098 | "autheticatorFlow": false 2099 | }, 2100 | { 2101 | "authenticator": "reset-credential-email", 2102 | "requirement": "REQUIRED", 2103 | "priority": 20, 2104 | "userSetupAllowed": false, 2105 | "autheticatorFlow": false 2106 | }, 2107 | { 2108 | "authenticator": "reset-password", 2109 | "requirement": "REQUIRED", 2110 | "priority": 30, 2111 | "userSetupAllowed": false, 2112 | "autheticatorFlow": false 2113 | }, 2114 | { 2115 | "requirement": "CONDITIONAL", 2116 | "priority": 40, 2117 | "flowAlias": "Reset - Conditional OTP", 2118 | "userSetupAllowed": false, 2119 | "autheticatorFlow": true 2120 | } 2121 | ] 2122 | }, 2123 | { 2124 | "id": "d4d4e821-4d8c-4751-b505-1bbb41419718", 2125 | "alias": "saml ecp", 2126 | "description": "SAML ECP Profile Authentication Flow", 2127 | "providerId": "basic-flow", 2128 | "topLevel": true, 2129 | "builtIn": true, 2130 | "authenticationExecutions": [ 2131 | { 2132 | "authenticator": "http-basic-authenticator", 2133 | "requirement": "REQUIRED", 2134 | "priority": 10, 2135 | "userSetupAllowed": false, 2136 | "autheticatorFlow": false 2137 | } 2138 | ] 2139 | } 2140 | ], 2141 | "authenticatorConfig": [ 2142 | { 2143 | "id": "f5a46450-2b3a-4e2e-866b-ad9ec7b0a791", 2144 | "alias": "create unique user config", 2145 | "config": { 2146 | "require.password.update.after.registration": "false" 2147 | } 2148 | }, 2149 | { 2150 | "id": "d2708115-39a0-439b-b36e-8eb88fbbed7e", 2151 | "alias": "review profile config", 2152 | "config": { 2153 | "update.profile.on.first.login": "missing" 2154 | } 2155 | } 2156 | ], 2157 | "requiredActions": [ 2158 | { 2159 | "alias": "CONFIGURE_TOTP", 2160 | "name": "Configure OTP", 2161 | "providerId": "CONFIGURE_TOTP", 2162 | "enabled": true, 2163 | "defaultAction": false, 2164 | "priority": 10, 2165 | "config": {} 2166 | }, 2167 | { 2168 | "alias": "terms_and_conditions", 2169 | "name": "Terms and Conditions", 2170 | "providerId": "terms_and_conditions", 2171 | "enabled": false, 2172 | "defaultAction": false, 2173 | "priority": 20, 2174 | "config": {} 2175 | }, 2176 | { 2177 | "alias": "UPDATE_PASSWORD", 2178 | "name": "Update Password", 2179 | "providerId": "UPDATE_PASSWORD", 2180 | "enabled": true, 2181 | "defaultAction": false, 2182 | "priority": 30, 2183 | "config": {} 2184 | }, 2185 | { 2186 | "alias": "UPDATE_PROFILE", 2187 | "name": "Update Profile", 2188 | "providerId": "UPDATE_PROFILE", 2189 | "enabled": true, 2190 | "defaultAction": false, 2191 | "priority": 40, 2192 | "config": {} 2193 | }, 2194 | { 2195 | "alias": "VERIFY_EMAIL", 2196 | "name": "Verify Email", 2197 | "providerId": "VERIFY_EMAIL", 2198 | "enabled": true, 2199 | "defaultAction": false, 2200 | "priority": 50, 2201 | "config": {} 2202 | }, 2203 | { 2204 | "alias": "update_user_locale", 2205 | "name": "Update User Locale", 2206 | "providerId": "update_user_locale", 2207 | "enabled": true, 2208 | "defaultAction": false, 2209 | "priority": 1000, 2210 | "config": {} 2211 | } 2212 | ], 2213 | "browserFlow": "browser", 2214 | "registrationFlow": "registration", 2215 | "directGrantFlow": "direct grant", 2216 | "resetCredentialsFlow": "reset credentials", 2217 | "clientAuthenticationFlow": "clients", 2218 | "dockerAuthenticationFlow": "docker auth", 2219 | "attributes": { 2220 | "clientSessionIdleTimeout": "0", 2221 | "clientSessionMaxLifespan": "0" 2222 | }, 2223 | "keycloakVersion": "10.0.1", 2224 | "userManagedAccessAllowed": false 2225 | } --------------------------------------------------------------------------------