├── src
├── app
│ ├── secured
│ │ ├── secured.component.css
│ │ ├── secured.component.html
│ │ └── secured.component.ts
│ ├── forbidden
│ │ ├── forbidden.component.css
│ │ ├── forbidden.component.html
│ │ └── forbidden.component.ts
│ ├── not-found
│ │ ├── not-found.component.css
│ │ ├── not-found.component.html
│ │ └── not-found.component.ts
│ ├── secured-role
│ │ ├── home
│ │ │ ├── home.component.css
│ │ │ ├── home.component.html
│ │ │ └── home.component.ts
│ │ ├── secured-role.module.ts
│ │ └── secured-role-routing.module.ts
│ ├── app.component.css
│ ├── group-restricted
│ │ ├── group-restricted-home
│ │ │ ├── group-restricted-home.component.css
│ │ │ ├── group-restricted-home.component.html
│ │ │ └── group-restricted-home.component.ts
│ │ ├── group-restricted-routing.module.ts
│ │ └── group-restricted.module.ts
│ ├── home
│ │ ├── home.component.css
│ │ ├── home.component.html
│ │ └── home.component.ts
│ ├── app.component.html
│ ├── core
│ │ ├── model
│ │ │ └── permission-guard.ts
│ │ ├── interceptor
│ │ │ └── secured-http.interceptor.ts
│ │ ├── guard
│ │ │ └── auth-guard.service.ts
│ │ └── auth
│ │ │ └── keycloak.service.ts
│ ├── app.component.ts
│ ├── app.component.spec.ts
│ ├── app.module.ts
│ └── app-routing.module.ts
├── favicon.ico
├── styles.css
├── environments
│ ├── environment.prod.ts
│ └── environment.ts
├── typings.d.ts
├── assets
│ └── keycloak.json
├── tsconfig.app.json
├── tsconfig.spec.json
├── index.html
├── main.ts
├── test.ts
└── polyfills.ts
├── e2e
├── app.po.ts
├── tsconfig.e2e.json
└── app.e2e-spec.ts
├── browserslist
├── .github
└── FUNDING.yml
├── tsconfig.json
├── protractor.conf.js
├── karma.conf.js
├── package.json
├── tslint.json
├── README.md
├── angular.json
└── config
└── keycloak-auth-realm.json
/src/app/secured/secured.component.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app/forbidden/forbidden.component.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app/not-found/not-found.component.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app/secured-role/home/home.component.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app/app.component.css:
--------------------------------------------------------------------------------
1 | h1 {
2 | color: blue;
3 | }
--------------------------------------------------------------------------------
/src/app/secured/secured.component.html:
--------------------------------------------------------------------------------
1 |
This is a secured page!
2 |
--------------------------------------------------------------------------------
/src/app/forbidden/forbidden.component.html:
--------------------------------------------------------------------------------
1 |
2 | forbidden works!
3 |
4 |
--------------------------------------------------------------------------------
/src/app/group-restricted/group-restricted-home/group-restricted-home.component.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app/not-found/not-found.component.html:
--------------------------------------------------------------------------------
1 |
2 | not-found works!
3 |
4 |
--------------------------------------------------------------------------------
/src/app/secured-role/home/home.component.html:
--------------------------------------------------------------------------------
1 | This is a secured page by role!
2 |
--------------------------------------------------------------------------------
/src/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/czetsuya/keycloak-angular-auth/HEAD/src/favicon.ico
--------------------------------------------------------------------------------
/src/styles.css:
--------------------------------------------------------------------------------
1 | /* You can add global styles to this file, and also import other style files */
2 |
--------------------------------------------------------------------------------
/src/environments/environment.prod.ts:
--------------------------------------------------------------------------------
1 | export const environment = {
2 | production: true
3 | };
4 |
--------------------------------------------------------------------------------
/src/app/group-restricted/group-restricted-home/group-restricted-home.component.html:
--------------------------------------------------------------------------------
1 | This is a secured module home page.
2 |
--------------------------------------------------------------------------------
/src/typings.d.ts:
--------------------------------------------------------------------------------
1 | /* SystemJS module definition */
2 | declare var module: NodeModule;
3 | interface NodeModule {
4 | id: string;
5 | }
6 |
--------------------------------------------------------------------------------
/src/app/home/home.component.css:
--------------------------------------------------------------------------------
1 | .center {
2 | margin: auto;
3 | width: 50%;
4 | border: 3px solid green;
5 | padding: 10px;
6 | }
--------------------------------------------------------------------------------
/src/app/app.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Welcome to {{ title }}!
4 |
5 |
--------------------------------------------------------------------------------
/src/assets/keycloak.json:
--------------------------------------------------------------------------------
1 | {
2 | "realm": "keycloak-angular-auth",
3 | "auth-server-url": "http://localhost:8081/auth/",
4 | "ssl-required": "none",
5 | "resource": "frontend",
6 | "public-client": true,
7 | "confidential-port": 0
8 | }
--------------------------------------------------------------------------------
/e2e/app.po.ts:
--------------------------------------------------------------------------------
1 | import { browser, by, element } from 'protractor';
2 |
3 | export class AppPage {
4 | navigateTo() {
5 | return browser.get('/');
6 | }
7 |
8 | getParagraphText() {
9 | return element(by.css('app-root h1')).getText();
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/app/core/model/permission-guard.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Used in routing to restrict access to a lazily loaded module
3 | */
4 | export interface PermissionGuard {
5 | Role?: string,
6 | Only?: Array,
7 | Except?: Array,
8 | RedirectTo?: string | Function
9 | }
--------------------------------------------------------------------------------
/src/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../out-tsc/app",
5 | "baseUrl": "./",
6 | "types": []
7 | },
8 | "files": [
9 | "main.ts",
10 | "polyfills.ts"
11 | ],
12 | "include": [
13 | "src/**/*.d.ts"
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/e2e/tsconfig.e2e.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../out-tsc/e2e",
5 | "baseUrl": "./",
6 | "module": "commonjs",
7 | "target": "es5",
8 | "types": [
9 | "jasmine",
10 | "jasminewd2",
11 | "node"
12 | ]
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/app/app.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 |
3 | @Component( {
4 | selector: 'app-root',
5 | templateUrl: './app.component.html',
6 | styleUrls: ['./app.component.css']
7 | } )
8 | export class AppComponent {
9 | title = 'Securing Angular Application with Keycloak';
10 | }
11 |
--------------------------------------------------------------------------------
/src/app/secured-role/home/home.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-home',
5 | templateUrl: './home.component.html',
6 | styleUrls: ['./home.component.css']
7 | })
8 | export class HomeComponent implements OnInit {
9 |
10 | constructor() { }
11 |
12 | ngOnInit() {
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/e2e/app.e2e-spec.ts:
--------------------------------------------------------------------------------
1 | import { AppPage } from './app.po';
2 |
3 | describe('keycloak-auth App', () => {
4 | let page: AppPage;
5 |
6 | beforeEach(() => {
7 | page = new AppPage();
8 | });
9 |
10 | it('should display welcome message', () => {
11 | page.navigateTo();
12 | expect(page.getParagraphText()).toEqual('Welcome to app!');
13 | });
14 | });
15 |
--------------------------------------------------------------------------------
/src/app/forbidden/forbidden.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-forbidden',
5 | templateUrl: './forbidden.component.html',
6 | styleUrls: ['./forbidden.component.css']
7 | })
8 | export class ForbiddenComponent implements OnInit {
9 |
10 | constructor() { }
11 |
12 | ngOnInit() {
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/src/app/not-found/not-found.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-not-found',
5 | templateUrl: './not-found.component.html',
6 | styleUrls: ['./not-found.component.css']
7 | })
8 | export class NotFoundComponent implements OnInit {
9 |
10 | constructor() { }
11 |
12 | ngOnInit() {
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/src/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../out-tsc/spec",
5 | "baseUrl": "./",
6 | "types": [
7 | "jasmine",
8 | "node"
9 | ]
10 | },
11 | "files": [
12 | "test.ts",
13 | "polyfills.ts"
14 | ],
15 | "include": [
16 | "**/*.spec.ts",
17 | "**/*.d.ts"
18 | ]
19 | }
20 |
--------------------------------------------------------------------------------
/src/app/secured/secured.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 |
3 | @Component( {
4 | selector: 'app-secured',
5 | templateUrl: './secured.component.html',
6 | styleUrls: ['./secured.component.css']
7 | } )
8 | export class SecuredComponent implements OnInit {
9 |
10 | constructor() { }
11 |
12 | ngOnInit() {
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Secure Angular Application with Keycloak
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/app/secured-role/secured-role.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { CommonModule } from '@angular/common';
3 |
4 | import { SecuredRoleRoutingModule } from './secured-role-routing.module';
5 | import { HomeComponent } from './home/home.component';
6 |
7 | @NgModule({
8 | imports: [
9 | CommonModule,
10 | SecuredRoleRoutingModule
11 | ],
12 | declarations: [HomeComponent]
13 | })
14 | export class SecuredRoleModule { }
15 |
--------------------------------------------------------------------------------
/src/app/group-restricted/group-restricted-home/group-restricted-home.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'app-group-restricted-home',
5 | templateUrl: './group-restricted-home.component.html',
6 | styleUrls: ['./group-restricted-home.component.css']
7 | })
8 | export class GroupRestrictedHomeComponent implements OnInit {
9 |
10 | constructor() { }
11 |
12 | ngOnInit() {
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/browserslist:
--------------------------------------------------------------------------------
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 | # You can see what browsers were selected by your queries by running:
6 | # npx browserslist
7 |
8 | > 0.5%
9 | last 2 versions
10 | Firefox ESR
11 | not dead
12 | not IE 9-11 # For IE 9-11 support, remove 'not'.
--------------------------------------------------------------------------------
/src/app/secured-role/secured-role-routing.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { Routes, RouterModule } from '@angular/router';
3 | import { HomeComponent } from './home/home.component';
4 |
5 | const routes: Routes = [
6 | { path: '', pathMatch: 'full', redirectTo: 'home' },
7 | { path: 'home', component: HomeComponent }
8 | ];
9 |
10 | @NgModule( {
11 | imports: [RouterModule.forChild( routes )],
12 | exports: [RouterModule]
13 | } )
14 | export class SecuredRoleRoutingModule { }
15 |
--------------------------------------------------------------------------------
/src/app/group-restricted/group-restricted-routing.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { Routes, RouterModule } from '@angular/router';
3 |
4 | import { GroupRestrictedHomeComponent } from './group-restricted-home/group-restricted-home.component';
5 |
6 | const routes: Routes = [
7 | { path: '', component: GroupRestrictedHomeComponent }
8 | ];
9 |
10 | @NgModule( {
11 | imports: [RouterModule.forChild( routes )],
12 | exports: [RouterModule]
13 | } )
14 | export class GroupRestrictedRoutingModule { }
15 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: czetsuya
4 | patreon:
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi:
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | custom:
13 |
--------------------------------------------------------------------------------
/src/app/group-restricted/group-restricted.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { CommonModule } from '@angular/common';
3 |
4 | import { GroupRestrictedRoutingModule } from './group-restricted-routing.module';
5 | import { GroupRestrictedHomeComponent } from './group-restricted-home/group-restricted-home.component';
6 |
7 | @NgModule({
8 | imports: [
9 | CommonModule,
10 | GroupRestrictedRoutingModule
11 | ],
12 | declarations: [GroupRestrictedHomeComponent]
13 | })
14 | export class GroupRestrictedModule { }
15 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compileOnSave": false,
3 | "compilerOptions": {
4 | "downlevelIteration": true,
5 | "importHelpers": true,
6 | "outDir": "./dist/out-tsc",
7 | "sourceMap": true,
8 | "declaration": false,
9 | "moduleResolution": "node",
10 | "emitDecoratorMetadata": true,
11 | "experimentalDecorators": true,
12 | "target": "es2015",
13 | "typeRoots": [
14 | "node_modules/@types"
15 | ],
16 | "lib": [
17 | "es2017",
18 | "dom"
19 | ],
20 | "module": "esnext",
21 | "baseUrl": "./"
22 | }
23 | }
--------------------------------------------------------------------------------
/src/environments/environment.ts:
--------------------------------------------------------------------------------
1 | // The file contents for the current environment will overwrite these during build.
2 | // The build system defaults to the dev environment which uses `environment.ts`, but if you do
3 | // `ng build --env=prod` then `environment.prod.ts` will be used instead.
4 | // The list of which env maps to which file can be found in `.angular-cli.json`.
5 |
6 | export const environment = {
7 | baseUrl: 'http://localhost:4200',
8 | production: false,
9 | apiUrl: 'http://localhost:8080/keycloak-auth-api/rest',
10 |
11 | keycloakRealm: 'keycloak-angular-auth',
12 | keycloakClient: 'auth-client',
13 | keycloakBaseUrl: 'http://192.168.1.101:8080/'
14 | };
--------------------------------------------------------------------------------
/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 | import { KeycloakService } from "./app/core/auth/keycloak.service";
8 |
9 | if (environment.production) {
10 | enableProdMode();
11 | }
12 |
13 | KeycloakService.init()
14 | .then(() => {
15 | console.log("kc init ok");
16 | const platform = platformBrowserDynamic();
17 | platform.bootstrapModule( AppModule );
18 | } )
19 | .catch( function( error ) {
20 | console.log( "kc init ko " + JSON.stringify( error ) );
21 | return;
22 | } );
23 |
--------------------------------------------------------------------------------
/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/dist/zone-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: any;
11 |
12 | // First, initialize the Angular testing environment.
13 | getTestBed().initTestEnvironment(
14 | BrowserDynamicTestingModule,
15 | platformBrowserDynamicTesting()
16 | );
17 | // Then we find all the tests.
18 | const context = require.context('./', true, /\.spec\.ts$/);
19 | // And load the modules.
20 | context.keys().map(context);
21 |
--------------------------------------------------------------------------------
/protractor.conf.js:
--------------------------------------------------------------------------------
1 | // Protractor configuration file, see link for more information
2 | // https://github.com/angular/protractor/blob/master/lib/config.ts
3 |
4 | const { SpecReporter } = require('jasmine-spec-reporter');
5 |
6 | exports.config = {
7 | allScriptsTimeout: 11000,
8 | specs: [
9 | './e2e/**/*.e2e-spec.ts'
10 | ],
11 | capabilities: {
12 | 'browserName': 'chrome'
13 | },
14 | directConnect: true,
15 | baseUrl: 'http://localhost:4200/',
16 | framework: 'jasmine',
17 | jasmineNodeOpts: {
18 | showColors: true,
19 | defaultTimeoutInterval: 30000,
20 | print: function() {}
21 | },
22 | onPrepare() {
23 | require('ts-node').register({
24 | project: 'e2e/tsconfig.e2e.json'
25 | });
26 | jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
27 | }
28 | };
29 |
--------------------------------------------------------------------------------
/src/app/home/home.component.html:
--------------------------------------------------------------------------------
1 |
2 |
{{stringify(errors)}}
3 |
This is a public page accessible to anyone.
4 |
User edward should be able to call the api while kerri should throw forbidden error since she doesn't have APIAccess role.
5 |
17 |
18 |
Isekai Anime
19 |
22 |
23 |
--------------------------------------------------------------------------------
/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-istanbul-reporter'),
13 | require('@angular-devkit/build-angular/plugins/karma')
14 | ],
15 | client:{
16 | clearContext: false // leave Jasmine Spec Runner output visible in browser
17 | },
18 | coverageIstanbulReporter: {
19 | dir: require('path').join(__dirname, 'coverage'), reports: [ 'html', 'lcovonly' ],
20 | fixWebpackSourcePaths: true
21 | },
22 |
23 | reporters: ['progress', 'kjhtml'],
24 | port: 9876,
25 | colors: true,
26 | logLevel: config.LOG_INFO,
27 | autoWatch: true,
28 | browsers: ['Chrome'],
29 | singleRun: false
30 | });
31 | };
32 |
--------------------------------------------------------------------------------
/src/app/app.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { TestBed, async } from '@angular/core/testing';
2 | import { AppComponent } from './app.component';
3 | describe('AppComponent', () => {
4 | beforeEach(async(() => {
5 | TestBed.configureTestingModule({
6 | declarations: [
7 | AppComponent
8 | ],
9 | }).compileComponents();
10 | }));
11 | it('should create the app', async(() => {
12 | const fixture = TestBed.createComponent(AppComponent);
13 | const app = fixture.debugElement.componentInstance;
14 | expect(app).toBeTruthy();
15 | }));
16 | it(`should have as title 'app'`, async(() => {
17 | const fixture = TestBed.createComponent(AppComponent);
18 | const app = fixture.debugElement.componentInstance;
19 | expect(app.title).toEqual('app');
20 | }));
21 | it('should render title in a h1 tag', async(() => {
22 | const fixture = TestBed.createComponent(AppComponent);
23 | fixture.detectChanges();
24 | const compiled = fixture.debugElement.nativeElement;
25 | expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!');
26 | }));
27 | });
28 |
--------------------------------------------------------------------------------
/src/app/home/home.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 |
3 | import { Injectable, Inject } from '@angular/core';
4 | import { HttpClient, HttpErrorResponse, HttpParams } from '@angular/common/http';
5 |
6 | import { KeycloakService } from "app/core/auth/keycloak.service";
7 | import { environment } from 'environments/environment';
8 |
9 | @Component( {
10 | selector: 'app-home',
11 | templateUrl: './home.component.html',
12 | styleUrls: ['./home.component.css']
13 | } )
14 | export class HomeComponent implements OnInit {
15 |
16 | animes: any
17 | errors: any
18 |
19 | constructor( private http: HttpClient ) { }
20 |
21 | ngOnInit() {
22 | }
23 |
24 | getKeycloakService() {
25 | return KeycloakService
26 | }
27 |
28 | callApi() {
29 | this.errors = null;
30 | this.http.get( environment.apiUrl + "/animes" ).subscribe( data => {
31 | this.animes = data
32 | }, ( err: HttpErrorResponse ) => {
33 | this.errors = err
34 | } );
35 | }
36 |
37 | stringify( val ) {
38 | return JSON.stringify( val );
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/src/app/core/interceptor/secured-http.interceptor.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import { HttpInterceptor, HttpHandler, HttpRequest, HttpEvent, HttpResponse } from '@angular/common/http';
3 |
4 | import { Observable } from 'rxjs/Observable';
5 | import 'rxjs/add/operator/do';
6 |
7 | import { KeycloakService } from 'app/core/auth/keycloak.service';
8 |
9 | @Injectable()
10 | export class SecuredHttpInterceptor implements HttpInterceptor {
11 |
12 | /**
13 | * Intercepts the http request and add the bearer token of the currently logged user.
14 | *
15 | * @param request http request
16 | * @param next http handler
17 | */
18 | intercept( request: HttpRequest, next: HttpHandler ): Observable> {
19 | //const started = Date.now();
20 | if ( KeycloakService.auth.authz != null && KeycloakService.auth.loggedIn && KeycloakService.auth.authz.authenticated ) {
21 | KeycloakService.getToken();
22 | let kcToken = KeycloakService.auth.authz.token;
23 | request = request.clone( {
24 | setHeaders: {
25 | Authorization: 'Bearer ' + kcToken
26 | }
27 | } );
28 | }
29 | return next.handle( request );
30 | }
31 | }
--------------------------------------------------------------------------------
/src/polyfills.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | /**
5 | * Required to support Web Animations `@angular/platform-browser/animations`.
6 | * Needed for: All but Chrome, Firefox and Opera. http://caniuse.com/#feat=web-animation
7 | **/
8 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`.
9 |
10 | /**
11 | * By default, zone.js will patch all possible macroTask and DomEvents
12 | * user can disable parts of macroTask/DomEvents patch by setting following flags
13 | */
14 |
15 | // (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
16 | // (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
17 | // (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
18 |
19 | /*
20 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
21 | * with the following flag, it will bypass `zone.js` patch for IE/Edge
22 | */
23 | // (window as any).__Zone_enable_cross_context_check = true;
24 |
25 | /***************************************************************************************************
26 | * Zone JS is required by default for Angular itself.
27 | */
28 | import 'zone.js/dist/zone'; // Included with Angular CLI.
29 |
30 |
31 |
32 | /***************************************************************************************************
33 | * APPLICATION IMPORTS
34 | */
35 |
--------------------------------------------------------------------------------
/src/app/app.module.ts:
--------------------------------------------------------------------------------
1 | import { BrowserModule } from '@angular/platform-browser';
2 | import { NgModule } from '@angular/core';
3 | import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
4 | import { Routes, RouterModule } from '@angular/router';
5 |
6 | import { AppRoutingModule } from './app-routing.module';
7 | import { SecuredHttpInterceptor } from 'app/core/interceptor/secured-http.interceptor';
8 | import { AuthGuardService } from "app/core/guard/auth-guard.service";
9 | import { KeycloakService } from "./core/auth/keycloak.service";
10 |
11 | import { AppComponent } from './app.component';
12 | import { HomeComponent } from './home/home.component';
13 | import { SecuredComponent } from './secured/secured.component';
14 | import { ForbiddenComponent } from './forbidden/forbidden.component';
15 | import { NotFoundComponent } from './not-found/not-found.component';
16 |
17 | @NgModule( {
18 | declarations: [
19 | AppComponent,
20 | HomeComponent,
21 | SecuredComponent,
22 | ForbiddenComponent,
23 | NotFoundComponent
24 | ],
25 | imports: [
26 | BrowserModule,
27 |
28 | RouterModule,
29 | HttpClientModule,
30 | AppRoutingModule
31 | ],
32 | providers: [
33 | KeycloakService,
34 | AuthGuardService,
35 | {
36 | provide: HTTP_INTERCEPTORS,
37 | useClass: SecuredHttpInterceptor,
38 | multi: true
39 | },
40 | ],
41 | bootstrap: [AppComponent]
42 | } )
43 | export class AppModule { }
44 |
--------------------------------------------------------------------------------
/src/app/app-routing.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { Routes, RouterModule } from '@angular/router';
3 |
4 | import { PermissionGuard } from 'app/core/model/permission-guard';
5 | import { AuthGuardService as AuthGuard } from 'app/core/guard/auth-guard.service';
6 | import { HomeComponent } from './home/home.component';
7 | import { SecuredComponent } from './secured/secured.component';
8 | import { ForbiddenComponent } from './forbidden/forbidden.component';
9 | import { NotFoundComponent } from './not-found/not-found.component';
10 |
11 | export const routes: Routes = [
12 | { path: '', redirectTo: 'home', pathMatch: 'full' },
13 | { path: 'home', component: HomeComponent },
14 | { path: 'secured', canActivate: [AuthGuard], component: SecuredComponent },
15 | {
16 | path: 'secured-role',
17 | canLoad: [AuthGuard],
18 | loadChildren: () => import('app/secured-role/secured-role.module').then(m => m.SecuredRoleModule),
19 | data: {
20 | Permission: {
21 | Role: 'AppRole',
22 | RedirectTo: '403'
23 | } as PermissionGuard
24 | }
25 | },
26 | {
27 | path: 'groupRestricted',
28 | canLoad: [AuthGuard],
29 | loadChildren: () => import('app/group-restricted/group-restricted.module').then(m => m.GroupRestrictedModule),
30 | data: {
31 | Permission: {
32 | Only: ['User'],
33 | RedirectTo: '403'
34 | } as PermissionGuard
35 | }
36 | },
37 |
38 | { path: '403', component: ForbiddenComponent },
39 | { path: '404', component: NotFoundComponent },
40 |
41 | { path: '**', redirectTo: '404' }
42 | ];
43 |
44 | @NgModule({
45 | imports: [RouterModule.forRoot(routes)],
46 | exports: [RouterModule]
47 | })
48 | export class AppRoutingModule { }
49 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "keycloak-angular-auth",
3 | "version": "1.1.0",
4 | "license": "MIT",
5 | "scripts": {
6 | "ng": "ng",
7 | "start": "ng serve",
8 | "build": "ng build --prod",
9 | "test": "ng test",
10 | "lint": "ng lint",
11 | "e2e": "ng e2e"
12 | },
13 | "private": true,
14 | "dependencies": {
15 | "@angular/animations": "^11.0.4",
16 | "@angular/common": "^11.0.4",
17 | "@angular/compiler": "^11.0.4",
18 | "@angular/core": "^11.0.4",
19 | "@angular/forms": "^11.0.4",
20 | "@angular/http": "^7.2.16",
21 | "@angular/platform-browser": "^11.0.4",
22 | "@angular/platform-browser-dynamic": "^11.0.4",
23 | "@angular/router": "^11.0.4",
24 | "core-js": "^3.8.1",
25 | "keycloak-js": "11.0.3",
26 | "npm": "^6.14.9",
27 | "npm-check-updates": "^10.2.5",
28 | "rxjs": "^6.6.3",
29 | "rxjs-compat": "^6.6.3",
30 | "tslib": "^2.0.3",
31 | "zone.js": "~0.11.3"
32 | },
33 | "devDependencies": {
34 | "@angular-devkit/build-angular": "~0.1100.4",
35 | "@angular/cli": "^11.0.4",
36 | "@angular/compiler-cli": "^11.0.4",
37 | "@angular/language-service": "^11.0.4",
38 | "@types/jasmine": "^3.6.2",
39 | "@types/jasminewd2": "~2.0.8",
40 | "@types/node": "^14.14.13",
41 | "angular-ide": "^0.9.76",
42 | "codelyzer": "^6.0.1",
43 | "jasmine-core": "~3.6.0",
44 | "jasmine-spec-reporter": "~6.0.0",
45 | "karma": "~5.2.3",
46 | "karma-chrome-launcher": "~3.1.0",
47 | "karma-coverage-istanbul-reporter": "^3.0.3",
48 | "karma-jasmine": "^4.0.1",
49 | "karma-jasmine-html-reporter": "^1.5.4",
50 | "protractor": "~7.0.0",
51 | "ts-node": "~9.1.1",
52 | "tslint": "~6.1.3",
53 | "typescript": "^4.0.5"
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/app/core/guard/auth-guard.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import { Route, Router, RouterStateSnapshot, ActivatedRouteSnapshot, CanActivate, CanLoad } from '@angular/router';
3 |
4 | import { PermissionGuard } from 'app/core/model/permission-guard';
5 | import { KeycloakService } from 'app/core/auth/keycloak.service';
6 |
7 | @Injectable()
8 | export class AuthGuardService implements CanActivate, CanLoad {
9 |
10 | constructor( public router: Router, private keycloakService: KeycloakService ) {
11 | }
12 |
13 | canActivate( route: ActivatedRouteSnapshot, state: RouterStateSnapshot ): boolean {
14 | let url: string = state.url;
15 | return this.checkLogin( url );
16 | }
17 |
18 | /**
19 | * Checks if a user is logged in before activating the secured page.
20 | * @param url
21 | */
22 | checkLogin( url: string ): boolean {
23 | if ( KeycloakService.auth.loggedIn && KeycloakService.auth.authz.authenticated ) {
24 | return true;
25 |
26 | } else {
27 | KeycloakService.login();
28 | return false;
29 | }
30 | }
31 |
32 | /**
33 | * Checks if the logged in user have enough privilege to load the page. Group can be specified in the app-routing.module routes.
34 | * Note that currently keycloak is not sending the list of roles that's why we are using groups.
35 | * @param route The route
36 | */
37 | canLoad( route: Route ): boolean {
38 | if ( !( KeycloakService.auth.loggedIn && KeycloakService.auth.authz.authenticated ) ) {
39 | KeycloakService.login();
40 | return false;
41 | }
42 |
43 | let data = route.data["Permission"] as PermissionGuard;
44 | console.log( data.Role );
45 | if ( data.Role ) {
46 | let hasDefined = KeycloakService.hasRole( data.Role )
47 | if ( hasDefined )
48 | return true;
49 |
50 | if ( data.RedirectTo && data.RedirectTo !== undefined )
51 | this.router.navigate( [data.RedirectTo] );
52 |
53 | return false;
54 |
55 | } else {
56 | console.log('unrole');
57 |
58 | if ( Array.isArray( data.Only ) && Array.isArray( data.Except ) ) {
59 | throw "Can't use both 'Only' and 'Except' in route data.";
60 | }
61 |
62 | if ( Array.isArray( data.Only ) ) {
63 | let hasDefined = KeycloakService.hasGroups( data.Only )
64 | if ( hasDefined )
65 | return true;
66 |
67 | if ( data.RedirectTo && data.RedirectTo !== undefined )
68 | this.router.navigate( [data.RedirectTo] );
69 |
70 | return false;
71 | }
72 |
73 | if ( Array.isArray( data.Except ) ) {
74 | let hasDefined = KeycloakService.hasGroups( data.Except )
75 | if ( !hasDefined )
76 | return true;
77 |
78 | if ( data.RedirectTo && data.RedirectTo !== undefined )
79 | this.router.navigate( [data.RedirectTo] );
80 |
81 | return false;
82 | }
83 | }
84 | }
85 |
86 | }
--------------------------------------------------------------------------------
/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "rulesDirectory": [
3 | "node_modules/codelyzer"
4 | ],
5 | "rules": {
6 | "arrow-return-shorthand": true,
7 | "callable-types": true,
8 | "class-name": true,
9 | "comment-format": [
10 | true,
11 | "check-space"
12 | ],
13 | "curly": true,
14 | "deprecation": {
15 | "severity": "warn"
16 | },
17 | "eofline": true,
18 | "forin": true,
19 | "import-blacklist": [
20 | true,
21 | "rxjs/Rx"
22 | ],
23 | "import-spacing": true,
24 | "indent": [
25 | true,
26 | "spaces"
27 | ],
28 | "interface-over-type-literal": true,
29 | "label-position": true,
30 | "max-line-length": [
31 | true,
32 | 140
33 | ],
34 | "member-access": false,
35 | "member-ordering": [
36 | true,
37 | {
38 | "order": [
39 | "static-field",
40 | "instance-field",
41 | "static-method",
42 | "instance-method"
43 | ]
44 | }
45 | ],
46 | "no-arg": true,
47 | "no-bitwise": true,
48 | "no-console": [
49 | true,
50 | "debug",
51 | "info",
52 | "time",
53 | "timeEnd",
54 | "trace"
55 | ],
56 | "no-construct": true,
57 | "no-debugger": true,
58 | "no-duplicate-super": true,
59 | "no-empty": false,
60 | "no-empty-interface": true,
61 | "no-eval": true,
62 | "no-inferrable-types": [
63 | true,
64 | "ignore-params"
65 | ],
66 | "no-misused-new": true,
67 | "no-non-null-assertion": true,
68 | "no-shadowed-variable": true,
69 | "no-string-literal": false,
70 | "no-string-throw": true,
71 | "no-switch-case-fall-through": true,
72 | "no-trailing-whitespace": true,
73 | "no-unnecessary-initializer": true,
74 | "no-unused-expression": true,
75 | "no-use-before-declare": true,
76 | "no-var-keyword": true,
77 | "object-literal-sort-keys": false,
78 | "one-line": [
79 | true,
80 | "check-open-brace",
81 | "check-catch",
82 | "check-else",
83 | "check-whitespace"
84 | ],
85 | "prefer-const": true,
86 | "quotemark": [
87 | true,
88 | "single"
89 | ],
90 | "radix": true,
91 | "semicolon": [
92 | true,
93 | "always"
94 | ],
95 | "triple-equals": [
96 | true,
97 | "allow-null-check"
98 | ],
99 | "typedef-whitespace": [
100 | true,
101 | {
102 | "call-signature": "nospace",
103 | "index-signature": "nospace",
104 | "parameter": "nospace",
105 | "property-declaration": "nospace",
106 | "variable-declaration": "nospace"
107 | }
108 | ],
109 | "unified-signatures": true,
110 | "variable-name": false,
111 | "whitespace": [
112 | true,
113 | "check-branch",
114 | "check-decl",
115 | "check-operator",
116 | "check-separator",
117 | "check-type"
118 | ],
119 | "directive-selector": [
120 | true,
121 | "attribute",
122 | "app",
123 | "camelCase"
124 | ],
125 | "component-selector": [
126 | true,
127 | "element",
128 | "app",
129 | "kebab-case"
130 | ],
131 | "no-output-on-prefix": true,
132 | "no-inputs-metadata-property": true,
133 | "no-outputs-metadata-property": true,
134 | "no-host-metadata-property": true,
135 | "no-input-rename": true,
136 | "no-output-rename": true,
137 | "use-lifecycle-interface": true,
138 | "use-pipe-transform-interface": true,
139 | "component-class-suffix": true,
140 | "directive-class-suffix": true
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/src/app/core/auth/keycloak.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 |
3 | import { environment } from 'environments/environment';
4 |
5 | declare var Keycloak: any;
6 |
7 | @Injectable()
8 | export class KeycloakService {
9 |
10 | static auth: any = {};
11 | static redirectUrl: string;
12 |
13 | /**
14 | * Initialized keycloak client
15 | */
16 | static init(): Promise {
17 | let keycloakAuth: any = new Keycloak( 'assets/keycloak.json' );
18 | KeycloakService.auth.loggedIn = false;
19 |
20 | return new Promise(( resolve, reject ) => {
21 | keycloakAuth.init( { onLoad: 'check-sso' } )
22 | .then(() => {
23 | KeycloakService.auth.loggedIn = true;
24 | KeycloakService.auth.authz = keycloakAuth;
25 | KeycloakService.auth.registerUrl = KeycloakService.auth.authz.createRegisterUrl();
26 | KeycloakService.auth.logoutUrl = keycloakAuth.authServerUrl + "/realms/" + environment.keycloakRealm + "/protocol/openid-connect/logout?redirect_uri=" + environment.baseUrl + "/index.html";
27 |
28 | resolve();
29 | } )
30 | .catch(() => {
31 | reject();
32 | } );
33 | } );
34 | }
35 |
36 | /**
37 | * Checks if the logged user is a member of the specified group
38 | *
39 | * @param groupName group name defined in keycloak
40 | */
41 | static hasGroup( groupName: string ): boolean {
42 | return KeycloakService.auth.authz != null && KeycloakService.auth.authz.authenticated && KeycloakService.auth.authz.idTokenParsed.groups.indexOf( "/" + groupName ) !== -1 ? true : false;
43 | }
44 |
45 | /**
46 | * Checks if the logged user is a member of the specified groups
47 | *
48 | * @param groupNames a list of group names defined in keycloak
49 | */
50 | static hasGroups( groupNames: string[] ): boolean {
51 | if ( !groupNames ) {
52 | return false;
53 | }
54 | return groupNames.some( e => {
55 | if ( typeof e === "string" ) {
56 | return KeycloakService.hasGroup( e );
57 | }
58 | } );
59 | }
60 |
61 | /**
62 | * Checks if the logged user has the role specified
63 | *
64 | * @param roleName The name of the role
65 | * @param resource The keycloak client
66 | */
67 | static hasRole( roleName: string, resource?: string ): boolean {
68 | return KeycloakService.auth.authz.hasRealmRole( roleName ) || KeycloakService.auth.authz.hasResourceRole( roleName ) || KeycloakService.auth.authz.hasResourceRole( roleName, resource );
69 | }
70 |
71 | /**
72 | * Logout the current user
73 | */
74 | static logout() {
75 | console.log( '*** LOGOUT' );
76 | KeycloakService.auth.authz.logout( { redirectUri: KeycloakService.auth.logoutUrl } );
77 | KeycloakService.auth.loggedIn = false;
78 | KeycloakService.auth.authz = null;
79 | }
80 |
81 | /**
82 | * Redirects to keycloak login page
83 | */
84 | static login() {
85 | KeycloakService.auth.authz.login();
86 | }
87 |
88 | /**
89 | * Returns the token of the currently logged user
90 | */
91 | static getToken(): Promise {
92 | return new Promise(( resolve, reject ) => {
93 | if ( KeycloakService.auth.authz.token ) {
94 | KeycloakService.auth.authz.updateToken( 5 )
95 | .success(() => {
96 | resolve( KeycloakService.auth.authz.token );
97 | } )
98 | .error(() => {
99 | reject( 'Failed to refresh token' );
100 | } );
101 | }
102 | } );
103 | }
104 |
105 | /**
106 | * Returns true if the current user is logged in
107 | */
108 | static isLogged(): boolean {
109 | return KeycloakService.auth.authz != null && KeycloakService.auth.authz.authenticated;
110 | }
111 |
112 | /**
113 | * Returns keycloak registration url
114 | */
115 | static createRegisterUrl() {
116 | return KeycloakService.auth.registerUrl;
117 | }
118 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://www.gnu.org/licenses/gpl-3.0)
2 |
3 | *If you would like to support these tutorials, you can contribute to my [Patreon account](https://patreon.com/czetsuya)
4 |
5 | # Angular 9 Keycloak Integration
6 |
7 | This is a project template that integrates Keycloak authentication server to an Angular5 project.
8 |
9 | It provides an authentication guard service that can restrict a component from being accessible if a user is not logged in.
10 |
11 | Blog: https://czetsuya-tech.blogspot.com/2019/08/how-to-secure-angular-app-with-keycloak.html
12 |
13 | ## Features
14 |
15 | - Restricts a component from being accessible, if a user is not logged in.
16 | - Restricts access of lazily loaded modules by groups.
17 | - Restricts access of lazily loaded modules by role.
18 |
19 | ## Requirements
20 |
21 | This project was tested on:
22 | - node v12.17.0
23 | - npm v6.15.5
24 | - angular/cli v9.1.7
25 | - Keycloak 11.0.3
26 | - Wildfly 19.0.1
27 |
28 | To update the angular CLI version:
29 |
30 | ```sh
31 | npm uninstall --save-dev angular-cli
32 | npm cache verify
33 | npm install --save-dev @angular/cli@latest
34 | ```
35 |
36 | To update the dependencies
37 |
38 | ```sh
39 | npm i -g npm-check-updates
40 | ncu -u
41 | npm install
42 | ```
43 |
44 | ## Instructions
45 |
46 | ### Keycloak
47 |
48 | #### Docker
49 |
50 | To run Keycloak using docker, open your command prompt and execute:
51 |
52 | ```sh
53 | docker run --name=keycloak_11 -p 8081:8080 -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=admin jboss/keycloak:11.0.3
54 | ```
55 |
56 | - Install keycloak server on your local environment. I'm using version 10.0.1.
57 | - Or use a docker image. To run : docker run --name=keycloak10 -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=kerri -p 8080:8080 jboss/keycloak:10.0.1.
58 | - Login to keycloak and import the realm in config/keycloak-auth-realm.json.
59 | - The import will also create users. Account is edward / edward (with group User, has APIAccess role). kerri / kerri (with role AppRole).
60 | - You can create your own user, just make sure to add him / her to the User group.
61 | - Don't forget to map Group Membership to "groups".
62 |
63 | ### Angular
64 |
65 | - Install keycloak: npm install keycloak-js@latest --save
66 |
67 | ### How-to
68 |
69 | The following are configurations on how to secure routes.
70 |
71 | 1.) To secure a component by authenticated user:
72 |
73 | ```
74 | { path: 'secured', canActivate: [AuthGuard], component: SecuredComponent },
75 | ```
76 |
77 | 2.) To secure a module by group membership:
78 |
79 | ```
80 | {
81 | path: 'groupRestricted',
82 | canLoad: [AuthGuard],
83 | loadChildren: 'app/group-restricted/group-restricted.module#GroupRestrictedModule',
84 | data: {
85 | Permission: {
86 | Only: ['User'],
87 | RedirectTo: '403'
88 | } as PermissionGuard
89 | }
90 | }
91 | ```
92 |
93 | 3.) To secure a module by role membership:
94 |
95 | ```
96 | {
97 | path: 'secured-role',
98 | canLoad: [AuthGuard],
99 | loadChildren: 'app/group-restricted/group-restricted.module#GroupRestrictedModule',
100 | data: {
101 | Permission: {
102 | Only: ['User'],
103 | RedirectTo: '403'
104 | } as PermissionGuard
105 | }
106 | }
107 | ```
108 |
109 | ## Known Issues
110 |
111 | 1.) If you migrated to Keycloak version >=7.0.1, make sure to set the client's accessType to public.
112 |
113 | ## References
114 |
115 | - https://github.com/czetsuya/keycloak-angular-auth
116 | - https://github.com/czetsuya/keycloak-auth-api
117 | - https://www.keycloak.org/
118 | - https://cli.angular.io/
119 | - https://hub.docker.com/r/jboss/keycloak
120 |
121 | ## Notes
122 |
123 | - Keycloak is injected and initialized at main.ts.
124 | - keycloakRealm and keycloakBaseUrl must be set in src/environments/environment.ts.
125 | - src/assets/keycloak.json, is where we defined the keycloak client configuration.
126 |
127 | *Make sure that keycloak is running before running this app on ng serve. This project is calling keycloak from port 8380, you may want to change that to 8080 if you deploy keycloak as default (src/environments/environment.ts).
128 |
129 | ## Authors
130 |
131 | * **Edward P. Legaspi** - *Java Architect* - [czetsuya](https://github.com/czetsuya)
132 |
--------------------------------------------------------------------------------
/angular.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
3 | "version": 1,
4 | "newProjectRoot": "projects",
5 | "projects": {
6 | "keycloak-auth": {
7 | "root": "",
8 | "sourceRoot": "src",
9 | "projectType": "application",
10 | "architect": {
11 | "build": {
12 | "builder": "@angular-devkit/build-angular:browser",
13 | "options": {
14 | "aot": true,
15 | "outputPath": "dist",
16 | "index": "src/index.html",
17 | "main": "src/main.ts",
18 | "tsConfig": "src/tsconfig.app.json",
19 | "polyfills": "src/polyfills.ts",
20 | "assets": [
21 | "src/assets",
22 | "src/favicon.ico"
23 | ],
24 | "styles": [
25 | "src/styles.css"
26 | ],
27 | "scripts": [
28 | "node_modules/keycloak-js/dist/keycloak.js"
29 | ]
30 | },
31 | "configurations": {
32 | "production": {
33 | "budgets": [
34 | {
35 | "type": "anyComponentStyle",
36 | "maximumWarning": "6kb"
37 | }
38 | ],
39 | "optimization": true,
40 | "outputHashing": "all",
41 | "sourceMap": false,
42 | "extractCss": true,
43 | "namedChunks": false,
44 | "aot": true,
45 | "extractLicenses": true,
46 | "vendorChunk": false,
47 | "buildOptimizer": true,
48 | "fileReplacements": [
49 | {
50 | "replace": "src/environments/environment.ts",
51 | "with": "src/environments/environment.prod.ts"
52 | }
53 | ]
54 | }
55 | }
56 | },
57 | "serve": {
58 | "builder": "@angular-devkit/build-angular:dev-server",
59 | "options": {
60 | "browserTarget": "keycloak-auth:build"
61 | },
62 | "configurations": {
63 | "production": {
64 | "browserTarget": "keycloak-auth:build:production"
65 | }
66 | }
67 | },
68 | "extract-i18n": {
69 | "builder": "@angular-devkit/build-angular:extract-i18n",
70 | "options": {
71 | "browserTarget": "keycloak-auth:build"
72 | }
73 | },
74 | "test": {
75 | "builder": "@angular-devkit/build-angular:karma",
76 | "options": {
77 | "main": "src/test.ts",
78 | "karmaConfig": "./karma.conf.js",
79 | "polyfills": "src/polyfills.ts",
80 | "tsConfig": "src/tsconfig.spec.json",
81 | "scripts": [
82 | "node_modules/keycloak-js/dist/keycloak.js"
83 | ],
84 | "styles": [
85 | "src/styles.css"
86 | ],
87 | "assets": [
88 | "src/assets",
89 | "src/favicon.ico"
90 | ]
91 | }
92 | },
93 | "lint": {
94 | "builder": "@angular-devkit/build-angular:tslint",
95 | "options": {
96 | "tsConfig": [
97 | "src/tsconfig.app.json",
98 | "src/tsconfig.spec.json"
99 | ],
100 | "exclude": [
101 | "**/node_modules/**"
102 | ]
103 | }
104 | }
105 | }
106 | },
107 | "keycloak-auth-e2e": {
108 | "root": "e2e",
109 | "sourceRoot": "e2e",
110 | "projectType": "application",
111 | "architect": {
112 | "e2e": {
113 | "builder": "@angular-devkit/build-angular:protractor",
114 | "options": {
115 | "protractorConfig": "./protractor.conf.js",
116 | "devServerTarget": "keycloak-auth:serve"
117 | }
118 | },
119 | "lint": {
120 | "builder": "@angular-devkit/build-angular:tslint",
121 | "options": {
122 | "tsConfig": [
123 | "e2e/tsconfig.e2e.json"
124 | ],
125 | "exclude": [
126 | "**/node_modules/**"
127 | ]
128 | }
129 | }
130 | }
131 | }
132 | },
133 | "defaultProject": "keycloak-auth",
134 | "schematics": {
135 | "@schematics/angular:component": {
136 | "prefix": "app",
137 | "style": "css"
138 | },
139 | "@schematics/angular:directive": {
140 | "prefix": "app"
141 | }
142 | },
143 | "cli": {
144 | "analytics": "eeabae68-8c74-4796-be17-fe5339ab7889"
145 | }
146 | }
--------------------------------------------------------------------------------
/config/keycloak-auth-realm.json:
--------------------------------------------------------------------------------
1 | {
2 | "id" : "keycloak-angular-auth",
3 | "realm" : "keycloak-angular-auth",
4 | "notBefore" : 0,
5 | "revokeRefreshToken" : false,
6 | "refreshTokenMaxReuse" : 0,
7 | "accessTokenLifespan" : 300,
8 | "accessTokenLifespanForImplicitFlow" : 900,
9 | "ssoSessionIdleTimeout" : 1800,
10 | "ssoSessionMaxLifespan" : 36000,
11 | "offlineSessionIdleTimeout" : 2592000,
12 | "accessCodeLifespan" : 60,
13 | "accessCodeLifespanUserAction" : 300,
14 | "accessCodeLifespanLogin" : 1800,
15 | "actionTokenGeneratedByAdminLifespan" : 43200,
16 | "actionTokenGeneratedByUserLifespan" : 300,
17 | "enabled" : true,
18 | "sslRequired" : "none",
19 | "registrationAllowed" : false,
20 | "registrationEmailAsUsername" : false,
21 | "rememberMe" : false,
22 | "verifyEmail" : false,
23 | "loginWithEmailAllowed" : true,
24 | "duplicateEmailsAllowed" : false,
25 | "resetPasswordAllowed" : false,
26 | "editUsernameAllowed" : false,
27 | "bruteForceProtected" : false,
28 | "permanentLockout" : false,
29 | "maxFailureWaitSeconds" : 900,
30 | "minimumQuickLoginWaitSeconds" : 60,
31 | "waitIncrementSeconds" : 60,
32 | "quickLoginCheckMilliSeconds" : 1000,
33 | "maxDeltaTimeSeconds" : 43200,
34 | "failureFactor" : 30,
35 | "roles" : {
36 | "realm" : [ {
37 | "id" : "c0a865e3-c5c3-44e8-9b88-54020cf7e3de",
38 | "name" : "offline_access",
39 | "description" : "${role_offline-access}",
40 | "scopeParamRequired" : true,
41 | "composite" : false,
42 | "clientRole" : false,
43 | "containerId" : "keycloak-auth"
44 | }, {
45 | "id" : "6b0e01e7-cf42-4c89-bba8-f336c1877ce2",
46 | "name" : "uma_authorization",
47 | "description" : "${role_uma_authorization}",
48 | "scopeParamRequired" : false,
49 | "composite" : false,
50 | "clientRole" : false,
51 | "containerId" : "keycloak-auth"
52 | }, {
53 | "id" : "a882f343-e27b-47b9-9f7f-ade694475f9c",
54 | "name" : "APIAccess",
55 | "scopeParamRequired" : false,
56 | "composite" : false,
57 | "clientRole" : false,
58 | "containerId" : "keycloak-auth"
59 | }, {
60 | "id" : "418201b0-2606-4a12-9011-97055cd83cb7",
61 | "name" : "AppRole",
62 | "scopeParamRequired" : false,
63 | "composite" : false,
64 | "clientRole" : false,
65 | "containerId" : "keycloak-auth"
66 | } ],
67 | "client" : {
68 | "auth-client" : [ ],
69 | "realm-management" : [ {
70 | "id" : "9296807e-f24c-47da-ac89-79cf7a399eb6",
71 | "name" : "query-users",
72 | "description" : "${role_query-users}",
73 | "scopeParamRequired" : false,
74 | "composite" : false,
75 | "clientRole" : true,
76 | "containerId" : "091774a7-c1e5-41c2-b906-354d9c5f32e4"
77 | }, {
78 | "id" : "08cf65cf-1af8-409e-851c-5594d6aa19d0",
79 | "name" : "manage-users",
80 | "description" : "${role_manage-users}",
81 | "scopeParamRequired" : false,
82 | "composite" : false,
83 | "clientRole" : true,
84 | "containerId" : "091774a7-c1e5-41c2-b906-354d9c5f32e4"
85 | }, {
86 | "id" : "16eff50d-0c18-4731-b9da-0f2d9fef26ec",
87 | "name" : "impersonation",
88 | "description" : "${role_impersonation}",
89 | "scopeParamRequired" : false,
90 | "composite" : false,
91 | "clientRole" : true,
92 | "containerId" : "091774a7-c1e5-41c2-b906-354d9c5f32e4"
93 | }, {
94 | "id" : "617e9ab6-353d-49ec-93b1-f31181904f2d",
95 | "name" : "view-users",
96 | "description" : "${role_view-users}",
97 | "scopeParamRequired" : false,
98 | "composite" : true,
99 | "composites" : {
100 | "client" : {
101 | "realm-management" : [ "query-users", "query-groups" ]
102 | }
103 | },
104 | "clientRole" : true,
105 | "containerId" : "091774a7-c1e5-41c2-b906-354d9c5f32e4"
106 | }, {
107 | "id" : "387162fb-1d01-4a9b-b8b7-a9cf42eccc6b",
108 | "name" : "manage-realm",
109 | "description" : "${role_manage-realm}",
110 | "scopeParamRequired" : false,
111 | "composite" : false,
112 | "clientRole" : true,
113 | "containerId" : "091774a7-c1e5-41c2-b906-354d9c5f32e4"
114 | }, {
115 | "id" : "5ab62b4f-3b39-4ab5-9f6c-88297a15a229",
116 | "name" : "manage-events",
117 | "description" : "${role_manage-events}",
118 | "scopeParamRequired" : false,
119 | "composite" : false,
120 | "clientRole" : true,
121 | "containerId" : "091774a7-c1e5-41c2-b906-354d9c5f32e4"
122 | }, {
123 | "id" : "8feeee85-e682-4b2d-9465-dfd48baab3f7",
124 | "name" : "create-client",
125 | "description" : "${role_create-client}",
126 | "scopeParamRequired" : false,
127 | "composite" : false,
128 | "clientRole" : true,
129 | "containerId" : "091774a7-c1e5-41c2-b906-354d9c5f32e4"
130 | }, {
131 | "id" : "603a1a7e-a082-4f68-a49c-ca8d905973e7",
132 | "name" : "view-realm",
133 | "description" : "${role_view-realm}",
134 | "scopeParamRequired" : false,
135 | "composite" : false,
136 | "clientRole" : true,
137 | "containerId" : "091774a7-c1e5-41c2-b906-354d9c5f32e4"
138 | }, {
139 | "id" : "ce1a6cce-28a8-4b99-8ffc-ed012c847b72",
140 | "name" : "view-authorization",
141 | "description" : "${role_view-authorization}",
142 | "scopeParamRequired" : false,
143 | "composite" : false,
144 | "clientRole" : true,
145 | "containerId" : "091774a7-c1e5-41c2-b906-354d9c5f32e4"
146 | }, {
147 | "id" : "1cd0d326-17bb-4886-9c8c-9293c2958425",
148 | "name" : "manage-clients",
149 | "description" : "${role_manage-clients}",
150 | "scopeParamRequired" : false,
151 | "composite" : false,
152 | "clientRole" : true,
153 | "containerId" : "091774a7-c1e5-41c2-b906-354d9c5f32e4"
154 | }, {
155 | "id" : "f1cee6e2-b3b8-4c63-81c1-09d41159eba2",
156 | "name" : "manage-authorization",
157 | "description" : "${role_manage-authorization}",
158 | "scopeParamRequired" : false,
159 | "composite" : false,
160 | "clientRole" : true,
161 | "containerId" : "091774a7-c1e5-41c2-b906-354d9c5f32e4"
162 | }, {
163 | "id" : "0118d0b1-96c3-409c-a0d9-6927d33cb29b",
164 | "name" : "view-identity-providers",
165 | "description" : "${role_view-identity-providers}",
166 | "scopeParamRequired" : false,
167 | "composite" : false,
168 | "clientRole" : true,
169 | "containerId" : "091774a7-c1e5-41c2-b906-354d9c5f32e4"
170 | }, {
171 | "id" : "73bc4374-4403-4c21-80d7-d20ff5679f97",
172 | "name" : "query-groups",
173 | "description" : "${role_query-groups}",
174 | "scopeParamRequired" : false,
175 | "composite" : false,
176 | "clientRole" : true,
177 | "containerId" : "091774a7-c1e5-41c2-b906-354d9c5f32e4"
178 | }, {
179 | "id" : "a2601aad-a863-450e-91ec-bc2d5582ae95",
180 | "name" : "manage-identity-providers",
181 | "description" : "${role_manage-identity-providers}",
182 | "scopeParamRequired" : false,
183 | "composite" : false,
184 | "clientRole" : true,
185 | "containerId" : "091774a7-c1e5-41c2-b906-354d9c5f32e4"
186 | }, {
187 | "id" : "58b4aaa0-c3f2-4a0a-b027-4008fb21d700",
188 | "name" : "query-realms",
189 | "description" : "${role_query-realms}",
190 | "scopeParamRequired" : false,
191 | "composite" : false,
192 | "clientRole" : true,
193 | "containerId" : "091774a7-c1e5-41c2-b906-354d9c5f32e4"
194 | }, {
195 | "id" : "e59ba277-c0db-454c-b719-ef008e5eee1a",
196 | "name" : "view-clients",
197 | "description" : "${role_view-clients}",
198 | "scopeParamRequired" : false,
199 | "composite" : true,
200 | "composites" : {
201 | "client" : {
202 | "realm-management" : [ "query-clients" ]
203 | }
204 | },
205 | "clientRole" : true,
206 | "containerId" : "091774a7-c1e5-41c2-b906-354d9c5f32e4"
207 | }, {
208 | "id" : "03cab49c-95d7-4a67-9896-bb30e42eb475",
209 | "name" : "view-events",
210 | "description" : "${role_view-events}",
211 | "scopeParamRequired" : false,
212 | "composite" : false,
213 | "clientRole" : true,
214 | "containerId" : "091774a7-c1e5-41c2-b906-354d9c5f32e4"
215 | }, {
216 | "id" : "3d92594a-863e-4b27-848a-3f63930868de",
217 | "name" : "realm-admin",
218 | "description" : "${role_realm-admin}",
219 | "scopeParamRequired" : false,
220 | "composite" : true,
221 | "composites" : {
222 | "client" : {
223 | "realm-management" : [ "query-users", "manage-users", "impersonation", "view-users", "manage-realm", "manage-events", "create-client", "view-realm", "manage-clients", "view-authorization", "manage-authorization", "view-identity-providers", "query-groups", "query-realms", "manage-identity-providers", "view-events", "view-clients", "query-clients" ]
224 | }
225 | },
226 | "clientRole" : true,
227 | "containerId" : "091774a7-c1e5-41c2-b906-354d9c5f32e4"
228 | }, {
229 | "id" : "039a4a28-cc49-42f1-9157-6e11f3924700",
230 | "name" : "query-clients",
231 | "description" : "${role_query-clients}",
232 | "scopeParamRequired" : false,
233 | "composite" : false,
234 | "clientRole" : true,
235 | "containerId" : "091774a7-c1e5-41c2-b906-354d9c5f32e4"
236 | } ],
237 | "security-admin-console" : [ ],
238 | "admin-cli" : [ ],
239 | "api" : [ ],
240 | "broker" : [ {
241 | "id" : "5985a9dd-7921-4104-ae6e-c8f35ce55b60",
242 | "name" : "read-token",
243 | "description" : "${role_read-token}",
244 | "scopeParamRequired" : false,
245 | "composite" : false,
246 | "clientRole" : true,
247 | "containerId" : "c7961297-dc5a-45f1-8eb0-0e9f3a230319"
248 | } ],
249 | "account" : [ {
250 | "id" : "b839c2e9-0849-48fc-bbbf-3bbb72e1a152",
251 | "name" : "manage-account-links",
252 | "description" : "${role_manage-account-links}",
253 | "scopeParamRequired" : false,
254 | "composite" : false,
255 | "clientRole" : true,
256 | "containerId" : "41806760-b228-424d-be07-f0267b284d73"
257 | }, {
258 | "id" : "f6fd4cba-867e-43a2-ab0b-434df61c79fd",
259 | "name" : "view-profile",
260 | "description" : "${role_view-profile}",
261 | "scopeParamRequired" : false,
262 | "composite" : false,
263 | "clientRole" : true,
264 | "containerId" : "41806760-b228-424d-be07-f0267b284d73"
265 | }, {
266 | "id" : "2ac0227e-33a3-4b3c-bc28-3257882b98a9",
267 | "name" : "manage-account",
268 | "description" : "${role_manage-account}",
269 | "scopeParamRequired" : false,
270 | "composite" : true,
271 | "composites" : {
272 | "client" : {
273 | "account" : [ "manage-account-links" ]
274 | }
275 | },
276 | "clientRole" : true,
277 | "containerId" : "41806760-b228-424d-be07-f0267b284d73"
278 | } ],
279 | "frontend" : [ ]
280 | }
281 | },
282 | "groups" : [ {
283 | "id" : "77936cf4-e4ee-4e48-828d-0a64121c0dae",
284 | "name" : "User",
285 | "path" : "/User",
286 | "attributes" : { },
287 | "realmRoles" : [ "APIAccess", "AppRole" ],
288 | "clientRoles" : { },
289 | "subGroups" : [ ]
290 | } ],
291 | "defaultRoles" : [ "uma_authorization", "offline_access" ],
292 | "requiredCredentials" : [ "password" ],
293 | "otpPolicyType" : "totp",
294 | "otpPolicyAlgorithm" : "HmacSHA1",
295 | "otpPolicyInitialCounter" : 0,
296 | "otpPolicyDigits" : 6,
297 | "otpPolicyLookAheadWindow" : 1,
298 | "otpPolicyPeriod" : 30,
299 | "clients" : [ {
300 | "id" : "41806760-b228-424d-be07-f0267b284d73",
301 | "clientId" : "account",
302 | "name" : "${client_account}",
303 | "baseUrl" : "/auth/realms/keycloak-auth/account",
304 | "surrogateAuthRequired" : false,
305 | "enabled" : true,
306 | "clientAuthenticatorType" : "client-secret",
307 | "secret" : "afd5ea48-7340-4894-9046-24ed0a3c576b",
308 | "defaultRoles" : [ "manage-account", "view-profile" ],
309 | "redirectUris" : [ "/auth/realms/keycloak-auth/account/*" ],
310 | "webOrigins" : [ ],
311 | "notBefore" : 0,
312 | "bearerOnly" : false,
313 | "consentRequired" : false,
314 | "standardFlowEnabled" : true,
315 | "implicitFlowEnabled" : false,
316 | "directAccessGrantsEnabled" : false,
317 | "serviceAccountsEnabled" : false,
318 | "publicClient" : false,
319 | "frontchannelLogout" : false,
320 | "protocol" : "openid-connect",
321 | "attributes" : { },
322 | "fullScopeAllowed" : false,
323 | "nodeReRegistrationTimeout" : 0,
324 | "protocolMappers" : [ {
325 | "id" : "ce28a19e-4a10-48b0-8ae8-b85043d943a8",
326 | "name" : "email",
327 | "protocol" : "openid-connect",
328 | "protocolMapper" : "oidc-usermodel-property-mapper",
329 | "consentRequired" : true,
330 | "consentText" : "${email}",
331 | "config" : {
332 | "userinfo.token.claim" : "true",
333 | "user.attribute" : "email",
334 | "id.token.claim" : "true",
335 | "access.token.claim" : "true",
336 | "claim.name" : "email",
337 | "jsonType.label" : "String"
338 | }
339 | }, {
340 | "id" : "c6fdf46e-31d1-417c-983d-04f221976891",
341 | "name" : "username",
342 | "protocol" : "openid-connect",
343 | "protocolMapper" : "oidc-usermodel-property-mapper",
344 | "consentRequired" : true,
345 | "consentText" : "${username}",
346 | "config" : {
347 | "userinfo.token.claim" : "true",
348 | "user.attribute" : "username",
349 | "id.token.claim" : "true",
350 | "access.token.claim" : "true",
351 | "claim.name" : "preferred_username",
352 | "jsonType.label" : "String"
353 | }
354 | }, {
355 | "id" : "eb2676e9-6806-4cf5-bcec-38a54296b833",
356 | "name" : "family name",
357 | "protocol" : "openid-connect",
358 | "protocolMapper" : "oidc-usermodel-property-mapper",
359 | "consentRequired" : true,
360 | "consentText" : "${familyName}",
361 | "config" : {
362 | "userinfo.token.claim" : "true",
363 | "user.attribute" : "lastName",
364 | "id.token.claim" : "true",
365 | "access.token.claim" : "true",
366 | "claim.name" : "family_name",
367 | "jsonType.label" : "String"
368 | }
369 | }, {
370 | "id" : "a8af4cdd-f9e7-49a5-bd3e-2f328736a104",
371 | "name" : "given name",
372 | "protocol" : "openid-connect",
373 | "protocolMapper" : "oidc-usermodel-property-mapper",
374 | "consentRequired" : true,
375 | "consentText" : "${givenName}",
376 | "config" : {
377 | "userinfo.token.claim" : "true",
378 | "user.attribute" : "firstName",
379 | "id.token.claim" : "true",
380 | "access.token.claim" : "true",
381 | "claim.name" : "given_name",
382 | "jsonType.label" : "String"
383 | }
384 | }, {
385 | "id" : "a3241a6f-88db-4e4f-bd6c-d0c253c3dad3",
386 | "name" : "full name",
387 | "protocol" : "openid-connect",
388 | "protocolMapper" : "oidc-full-name-mapper",
389 | "consentRequired" : true,
390 | "consentText" : "${fullName}",
391 | "config" : {
392 | "id.token.claim" : "true",
393 | "access.token.claim" : "true"
394 | }
395 | }, {
396 | "id" : "df0d2734-d5fd-476c-bb7f-3d9d565df461",
397 | "name" : "role list",
398 | "protocol" : "saml",
399 | "protocolMapper" : "saml-role-list-mapper",
400 | "consentRequired" : false,
401 | "config" : {
402 | "single" : "false",
403 | "attribute.nameformat" : "Basic",
404 | "attribute.name" : "Role"
405 | }
406 | } ],
407 | "useTemplateConfig" : false,
408 | "useTemplateScope" : false,
409 | "useTemplateMappers" : false
410 | }, {
411 | "id" : "4b811aee-ac4f-4272-9e6e-3a430687a4f6",
412 | "clientId" : "admin-cli",
413 | "name" : "${client_admin-cli}",
414 | "surrogateAuthRequired" : false,
415 | "enabled" : true,
416 | "clientAuthenticatorType" : "client-secret",
417 | "secret" : "30362dea-d811-4c62-b485-edea595f094c",
418 | "redirectUris" : [ ],
419 | "webOrigins" : [ ],
420 | "notBefore" : 0,
421 | "bearerOnly" : false,
422 | "consentRequired" : false,
423 | "standardFlowEnabled" : false,
424 | "implicitFlowEnabled" : false,
425 | "directAccessGrantsEnabled" : true,
426 | "serviceAccountsEnabled" : false,
427 | "publicClient" : true,
428 | "frontchannelLogout" : false,
429 | "protocol" : "openid-connect",
430 | "attributes" : { },
431 | "fullScopeAllowed" : false,
432 | "nodeReRegistrationTimeout" : 0,
433 | "protocolMappers" : [ {
434 | "id" : "c3db7215-c223-4f83-a875-ad8d9e11f48b",
435 | "name" : "username",
436 | "protocol" : "openid-connect",
437 | "protocolMapper" : "oidc-usermodel-property-mapper",
438 | "consentRequired" : true,
439 | "consentText" : "${username}",
440 | "config" : {
441 | "userinfo.token.claim" : "true",
442 | "user.attribute" : "username",
443 | "id.token.claim" : "true",
444 | "access.token.claim" : "true",
445 | "claim.name" : "preferred_username",
446 | "jsonType.label" : "String"
447 | }
448 | }, {
449 | "id" : "97bb98fd-b37a-4e25-b2c9-6638b87bdd0b",
450 | "name" : "given name",
451 | "protocol" : "openid-connect",
452 | "protocolMapper" : "oidc-usermodel-property-mapper",
453 | "consentRequired" : true,
454 | "consentText" : "${givenName}",
455 | "config" : {
456 | "userinfo.token.claim" : "true",
457 | "user.attribute" : "firstName",
458 | "id.token.claim" : "true",
459 | "access.token.claim" : "true",
460 | "claim.name" : "given_name",
461 | "jsonType.label" : "String"
462 | }
463 | }, {
464 | "id" : "235ecb7b-fc4f-45fd-a681-02d4ed626f11",
465 | "name" : "email",
466 | "protocol" : "openid-connect",
467 | "protocolMapper" : "oidc-usermodel-property-mapper",
468 | "consentRequired" : true,
469 | "consentText" : "${email}",
470 | "config" : {
471 | "userinfo.token.claim" : "true",
472 | "user.attribute" : "email",
473 | "id.token.claim" : "true",
474 | "access.token.claim" : "true",
475 | "claim.name" : "email",
476 | "jsonType.label" : "String"
477 | }
478 | }, {
479 | "id" : "2a5a8f86-8f79-488b-9c7e-dd58086aae5f",
480 | "name" : "full name",
481 | "protocol" : "openid-connect",
482 | "protocolMapper" : "oidc-full-name-mapper",
483 | "consentRequired" : true,
484 | "consentText" : "${fullName}",
485 | "config" : {
486 | "id.token.claim" : "true",
487 | "access.token.claim" : "true"
488 | }
489 | }, {
490 | "id" : "24fb10f2-5cd0-4377-b7ff-3acc42e8a60e",
491 | "name" : "role list",
492 | "protocol" : "saml",
493 | "protocolMapper" : "saml-role-list-mapper",
494 | "consentRequired" : false,
495 | "config" : {
496 | "single" : "false",
497 | "attribute.nameformat" : "Basic",
498 | "attribute.name" : "Role"
499 | }
500 | }, {
501 | "id" : "bdb1dbdd-b425-4b67-b3fc-65f0915591a8",
502 | "name" : "family name",
503 | "protocol" : "openid-connect",
504 | "protocolMapper" : "oidc-usermodel-property-mapper",
505 | "consentRequired" : true,
506 | "consentText" : "${familyName}",
507 | "config" : {
508 | "userinfo.token.claim" : "true",
509 | "user.attribute" : "lastName",
510 | "id.token.claim" : "true",
511 | "access.token.claim" : "true",
512 | "claim.name" : "family_name",
513 | "jsonType.label" : "String"
514 | }
515 | } ],
516 | "useTemplateConfig" : false,
517 | "useTemplateScope" : false,
518 | "useTemplateMappers" : false
519 | }, {
520 | "id" : "5d6c253e-493c-4113-8eef-c3c635b17ddd",
521 | "clientId" : "api",
522 | "surrogateAuthRequired" : false,
523 | "enabled" : true,
524 | "clientAuthenticatorType" : "client-secret",
525 | "secret" : "dbc38483-dca3-4dab-b424-dfb1f42fb13b",
526 | "redirectUris" : [ ],
527 | "webOrigins" : [ ],
528 | "notBefore" : 0,
529 | "bearerOnly" : true,
530 | "consentRequired" : false,
531 | "standardFlowEnabled" : true,
532 | "implicitFlowEnabled" : false,
533 | "directAccessGrantsEnabled" : true,
534 | "serviceAccountsEnabled" : false,
535 | "publicClient" : false,
536 | "frontchannelLogout" : false,
537 | "protocol" : "openid-connect",
538 | "attributes" : {
539 | "saml.assertion.signature" : "false",
540 | "saml.force.post.binding" : "false",
541 | "saml.multivalued.roles" : "false",
542 | "saml.encrypt" : "false",
543 | "saml_force_name_id_format" : "false",
544 | "saml.client.signature" : "false",
545 | "saml.authnstatement" : "false",
546 | "saml.server.signature" : "false",
547 | "saml.server.signature.keyinfo.ext" : "false",
548 | "saml.onetimeuse.condition" : "false"
549 | },
550 | "fullScopeAllowed" : true,
551 | "nodeReRegistrationTimeout" : -1,
552 | "protocolMappers" : [ {
553 | "id" : "ac3b5c98-c917-42b7-acaf-16dc10f36b60",
554 | "name" : "given name",
555 | "protocol" : "openid-connect",
556 | "protocolMapper" : "oidc-usermodel-property-mapper",
557 | "consentRequired" : true,
558 | "consentText" : "${givenName}",
559 | "config" : {
560 | "userinfo.token.claim" : "true",
561 | "user.attribute" : "firstName",
562 | "id.token.claim" : "true",
563 | "access.token.claim" : "true",
564 | "claim.name" : "given_name",
565 | "jsonType.label" : "String"
566 | }
567 | }, {
568 | "id" : "5eb221f7-16a4-412d-a9e7-1dac8b393941",
569 | "name" : "role list",
570 | "protocol" : "saml",
571 | "protocolMapper" : "saml-role-list-mapper",
572 | "consentRequired" : false,
573 | "config" : {
574 | "single" : "false",
575 | "attribute.nameformat" : "Basic",
576 | "attribute.name" : "Role"
577 | }
578 | }, {
579 | "id" : "141d8ae0-73fd-4486-ac3e-def170d18419",
580 | "name" : "family name",
581 | "protocol" : "openid-connect",
582 | "protocolMapper" : "oidc-usermodel-property-mapper",
583 | "consentRequired" : true,
584 | "consentText" : "${familyName}",
585 | "config" : {
586 | "userinfo.token.claim" : "true",
587 | "user.attribute" : "lastName",
588 | "id.token.claim" : "true",
589 | "access.token.claim" : "true",
590 | "claim.name" : "family_name",
591 | "jsonType.label" : "String"
592 | }
593 | }, {
594 | "id" : "d0652d34-a73e-4034-8dcf-e74c80fc2010",
595 | "name" : "full name",
596 | "protocol" : "openid-connect",
597 | "protocolMapper" : "oidc-full-name-mapper",
598 | "consentRequired" : true,
599 | "consentText" : "${fullName}",
600 | "config" : {
601 | "id.token.claim" : "true",
602 | "access.token.claim" : "true"
603 | }
604 | }, {
605 | "id" : "2d4d50c9-e6d9-413c-99a0-47361043a43a",
606 | "name" : "username",
607 | "protocol" : "openid-connect",
608 | "protocolMapper" : "oidc-usermodel-property-mapper",
609 | "consentRequired" : true,
610 | "consentText" : "${username}",
611 | "config" : {
612 | "userinfo.token.claim" : "true",
613 | "user.attribute" : "username",
614 | "id.token.claim" : "true",
615 | "access.token.claim" : "true",
616 | "claim.name" : "preferred_username",
617 | "jsonType.label" : "String"
618 | }
619 | }, {
620 | "id" : "595f1ab8-84fd-41c0-9afc-2c08fe035aea",
621 | "name" : "email",
622 | "protocol" : "openid-connect",
623 | "protocolMapper" : "oidc-usermodel-property-mapper",
624 | "consentRequired" : true,
625 | "consentText" : "${email}",
626 | "config" : {
627 | "userinfo.token.claim" : "true",
628 | "user.attribute" : "email",
629 | "id.token.claim" : "true",
630 | "access.token.claim" : "true",
631 | "claim.name" : "email",
632 | "jsonType.label" : "String"
633 | }
634 | } ],
635 | "useTemplateConfig" : false,
636 | "useTemplateScope" : false,
637 | "useTemplateMappers" : false
638 | }, {
639 | "id" : "0cea9ee9-e4da-4d78-bbf7-af32bd395365",
640 | "clientId" : "auth-client",
641 | "surrogateAuthRequired" : false,
642 | "enabled" : true,
643 | "clientAuthenticatorType" : "client-secret",
644 | "secret" : "c547900d-7307-499f-ad92-162977bdde8c",
645 | "redirectUris" : [ "*" ],
646 | "webOrigins" : [ "http://localhost:8080", "http://localhost:8080/*", "http://localhost:4200/*", "http://localhost:4200" ],
647 | "notBefore" : 0,
648 | "bearerOnly" : false,
649 | "consentRequired" : false,
650 | "standardFlowEnabled" : true,
651 | "implicitFlowEnabled" : false,
652 | "directAccessGrantsEnabled" : true,
653 | "serviceAccountsEnabled" : false,
654 | "publicClient" : true,
655 | "frontchannelLogout" : false,
656 | "protocol" : "openid-connect",
657 | "attributes" : {
658 | "saml.assertion.signature" : "false",
659 | "saml.force.post.binding" : "false",
660 | "saml.multivalued.roles" : "false",
661 | "saml.encrypt" : "false",
662 | "saml_force_name_id_format" : "false",
663 | "saml.client.signature" : "false",
664 | "saml.authnstatement" : "false",
665 | "saml.server.signature" : "false",
666 | "saml.server.signature.keyinfo.ext" : "false",
667 | "saml.onetimeuse.condition" : "false"
668 | },
669 | "fullScopeAllowed" : true,
670 | "nodeReRegistrationTimeout" : -1,
671 | "protocolMappers" : [ {
672 | "id" : "d538bf88-bc21-4a39-9f5e-00c4396b8f8c",
673 | "name" : "family name",
674 | "protocol" : "openid-connect",
675 | "protocolMapper" : "oidc-usermodel-property-mapper",
676 | "consentRequired" : true,
677 | "consentText" : "${familyName}",
678 | "config" : {
679 | "userinfo.token.claim" : "true",
680 | "user.attribute" : "lastName",
681 | "id.token.claim" : "true",
682 | "access.token.claim" : "true",
683 | "claim.name" : "family_name",
684 | "jsonType.label" : "String"
685 | }
686 | }, {
687 | "id" : "dd976db5-7dbd-49b7-9a58-818fa49c9326",
688 | "name" : "full name",
689 | "protocol" : "openid-connect",
690 | "protocolMapper" : "oidc-full-name-mapper",
691 | "consentRequired" : true,
692 | "consentText" : "${fullName}",
693 | "config" : {
694 | "id.token.claim" : "true",
695 | "access.token.claim" : "true"
696 | }
697 | }, {
698 | "id" : "3874b154-267b-4840-ba0b-9c1eae69c598",
699 | "name" : "username",
700 | "protocol" : "openid-connect",
701 | "protocolMapper" : "oidc-usermodel-property-mapper",
702 | "consentRequired" : true,
703 | "consentText" : "${username}",
704 | "config" : {
705 | "userinfo.token.claim" : "true",
706 | "user.attribute" : "username",
707 | "id.token.claim" : "true",
708 | "access.token.claim" : "true",
709 | "claim.name" : "preferred_username",
710 | "jsonType.label" : "String"
711 | }
712 | }, {
713 | "id" : "d66ebba8-be14-4955-9632-11f200179701",
714 | "name" : "groups",
715 | "protocol" : "openid-connect",
716 | "protocolMapper" : "oidc-group-membership-mapper",
717 | "consentRequired" : false,
718 | "config" : {
719 | "full.path" : "true",
720 | "id.token.claim" : "true",
721 | "access.token.claim" : "true",
722 | "claim.name" : "groups",
723 | "userinfo.token.claim" : "true"
724 | }
725 | }, {
726 | "id" : "685a1183-e0b4-4a2b-8e5f-26544c794fac",
727 | "name" : "role list",
728 | "protocol" : "saml",
729 | "protocolMapper" : "saml-role-list-mapper",
730 | "consentRequired" : false,
731 | "config" : {
732 | "single" : "false",
733 | "attribute.nameformat" : "Basic",
734 | "attribute.name" : "Role"
735 | }
736 | }, {
737 | "id" : "ad183054-d553-4e17-bcd2-7431d789e946",
738 | "name" : "email",
739 | "protocol" : "openid-connect",
740 | "protocolMapper" : "oidc-usermodel-property-mapper",
741 | "consentRequired" : true,
742 | "consentText" : "${email}",
743 | "config" : {
744 | "userinfo.token.claim" : "true",
745 | "user.attribute" : "email",
746 | "id.token.claim" : "true",
747 | "access.token.claim" : "true",
748 | "claim.name" : "email",
749 | "jsonType.label" : "String"
750 | }
751 | }, {
752 | "id" : "8850468e-7e44-45f2-8104-22caa036db44",
753 | "name" : "given name",
754 | "protocol" : "openid-connect",
755 | "protocolMapper" : "oidc-usermodel-property-mapper",
756 | "consentRequired" : true,
757 | "consentText" : "${givenName}",
758 | "config" : {
759 | "userinfo.token.claim" : "true",
760 | "user.attribute" : "firstName",
761 | "id.token.claim" : "true",
762 | "access.token.claim" : "true",
763 | "claim.name" : "given_name",
764 | "jsonType.label" : "String"
765 | }
766 | } ],
767 | "useTemplateConfig" : false,
768 | "useTemplateScope" : false,
769 | "useTemplateMappers" : false
770 | }, {
771 | "id" : "c7961297-dc5a-45f1-8eb0-0e9f3a230319",
772 | "clientId" : "broker",
773 | "name" : "${client_broker}",
774 | "surrogateAuthRequired" : false,
775 | "enabled" : true,
776 | "clientAuthenticatorType" : "client-secret",
777 | "secret" : "509a1b0f-1681-4394-8d92-b27a61b4bdec",
778 | "redirectUris" : [ ],
779 | "webOrigins" : [ ],
780 | "notBefore" : 0,
781 | "bearerOnly" : false,
782 | "consentRequired" : false,
783 | "standardFlowEnabled" : true,
784 | "implicitFlowEnabled" : false,
785 | "directAccessGrantsEnabled" : false,
786 | "serviceAccountsEnabled" : false,
787 | "publicClient" : false,
788 | "frontchannelLogout" : false,
789 | "protocol" : "openid-connect",
790 | "attributes" : { },
791 | "fullScopeAllowed" : false,
792 | "nodeReRegistrationTimeout" : 0,
793 | "protocolMappers" : [ {
794 | "id" : "006c3c8e-57c0-4268-ba26-1a0aa14e895a",
795 | "name" : "full name",
796 | "protocol" : "openid-connect",
797 | "protocolMapper" : "oidc-full-name-mapper",
798 | "consentRequired" : true,
799 | "consentText" : "${fullName}",
800 | "config" : {
801 | "id.token.claim" : "true",
802 | "access.token.claim" : "true"
803 | }
804 | }, {
805 | "id" : "2376262f-55a2-4f34-b436-306aabe889cd",
806 | "name" : "family name",
807 | "protocol" : "openid-connect",
808 | "protocolMapper" : "oidc-usermodel-property-mapper",
809 | "consentRequired" : true,
810 | "consentText" : "${familyName}",
811 | "config" : {
812 | "userinfo.token.claim" : "true",
813 | "user.attribute" : "lastName",
814 | "id.token.claim" : "true",
815 | "access.token.claim" : "true",
816 | "claim.name" : "family_name",
817 | "jsonType.label" : "String"
818 | }
819 | }, {
820 | "id" : "b19c0615-a325-47d7-8a0c-e3805bb712e7",
821 | "name" : "role list",
822 | "protocol" : "saml",
823 | "protocolMapper" : "saml-role-list-mapper",
824 | "consentRequired" : false,
825 | "config" : {
826 | "single" : "false",
827 | "attribute.nameformat" : "Basic",
828 | "attribute.name" : "Role"
829 | }
830 | }, {
831 | "id" : "485e7120-cb62-4def-8442-d88a917c6490",
832 | "name" : "given name",
833 | "protocol" : "openid-connect",
834 | "protocolMapper" : "oidc-usermodel-property-mapper",
835 | "consentRequired" : true,
836 | "consentText" : "${givenName}",
837 | "config" : {
838 | "userinfo.token.claim" : "true",
839 | "user.attribute" : "firstName",
840 | "id.token.claim" : "true",
841 | "access.token.claim" : "true",
842 | "claim.name" : "given_name",
843 | "jsonType.label" : "String"
844 | }
845 | }, {
846 | "id" : "4e605183-2813-42ff-bd18-71b7c90d9f7c",
847 | "name" : "username",
848 | "protocol" : "openid-connect",
849 | "protocolMapper" : "oidc-usermodel-property-mapper",
850 | "consentRequired" : true,
851 | "consentText" : "${username}",
852 | "config" : {
853 | "userinfo.token.claim" : "true",
854 | "user.attribute" : "username",
855 | "id.token.claim" : "true",
856 | "access.token.claim" : "true",
857 | "claim.name" : "preferred_username",
858 | "jsonType.label" : "String"
859 | }
860 | }, {
861 | "id" : "d15807dd-bf37-4603-ba82-aca17577f787",
862 | "name" : "email",
863 | "protocol" : "openid-connect",
864 | "protocolMapper" : "oidc-usermodel-property-mapper",
865 | "consentRequired" : true,
866 | "consentText" : "${email}",
867 | "config" : {
868 | "userinfo.token.claim" : "true",
869 | "user.attribute" : "email",
870 | "id.token.claim" : "true",
871 | "access.token.claim" : "true",
872 | "claim.name" : "email",
873 | "jsonType.label" : "String"
874 | }
875 | } ],
876 | "useTemplateConfig" : false,
877 | "useTemplateScope" : false,
878 | "useTemplateMappers" : false
879 | }, {
880 | "id" : "6dadf824-3ac4-4248-ad52-fdba8733ab36",
881 | "clientId" : "frontend",
882 | "surrogateAuthRequired" : false,
883 | "enabled" : true,
884 | "clientAuthenticatorType" : "client-secret",
885 | "secret" : "36cdf012-1793-4094-9fb0-91c268ee7b47",
886 | "redirectUris" : [ "*" ],
887 | "webOrigins" : [ "*"],
888 | "notBefore" : 0,
889 | "bearerOnly" : false,
890 | "consentRequired" : false,
891 | "standardFlowEnabled" : true,
892 | "implicitFlowEnabled" : false,
893 | "directAccessGrantsEnabled" : true,
894 | "serviceAccountsEnabled" : false,
895 | "publicClient" : true,
896 | "frontchannelLogout" : false,
897 | "protocol" : "openid-connect",
898 | "attributes" : {
899 | "saml.assertion.signature" : "false",
900 | "saml.force.post.binding" : "false",
901 | "saml.multivalued.roles" : "false",
902 | "saml.encrypt" : "false",
903 | "saml_force_name_id_format" : "false",
904 | "saml.client.signature" : "false",
905 | "saml.authnstatement" : "false",
906 | "saml.server.signature" : "false",
907 | "saml.server.signature.keyinfo.ext" : "false",
908 | "saml.onetimeuse.condition" : "false"
909 | },
910 | "fullScopeAllowed" : true,
911 | "nodeReRegistrationTimeout" : -1,
912 | "protocolMappers" : [ {
913 | "id" : "196495a1-97c4-4b7e-81cf-1192c293652a",
914 | "name" : "email",
915 | "protocol" : "openid-connect",
916 | "protocolMapper" : "oidc-usermodel-property-mapper",
917 | "consentRequired" : true,
918 | "consentText" : "${email}",
919 | "config" : {
920 | "userinfo.token.claim" : "true",
921 | "user.attribute" : "email",
922 | "id.token.claim" : "true",
923 | "access.token.claim" : "true",
924 | "claim.name" : "email",
925 | "jsonType.label" : "String"
926 | }
927 | }, {
928 | "id" : "546baca2-3a37-47b0-86af-9aefc77cb270",
929 | "name" : "username",
930 | "protocol" : "openid-connect",
931 | "protocolMapper" : "oidc-usermodel-property-mapper",
932 | "consentRequired" : true,
933 | "consentText" : "${username}",
934 | "config" : {
935 | "userinfo.token.claim" : "true",
936 | "user.attribute" : "username",
937 | "id.token.claim" : "true",
938 | "access.token.claim" : "true",
939 | "claim.name" : "preferred_username",
940 | "jsonType.label" : "String"
941 | }
942 | }, {
943 | "id" : "d27a252a-38c5-47b7-bcc6-01043c7c3faa",
944 | "name" : "family name",
945 | "protocol" : "openid-connect",
946 | "protocolMapper" : "oidc-usermodel-property-mapper",
947 | "consentRequired" : true,
948 | "consentText" : "${familyName}",
949 | "config" : {
950 | "userinfo.token.claim" : "true",
951 | "user.attribute" : "lastName",
952 | "id.token.claim" : "true",
953 | "access.token.claim" : "true",
954 | "claim.name" : "family_name",
955 | "jsonType.label" : "String"
956 | }
957 | }, {
958 | "id" : "241def7b-2a67-4f67-b5da-bf29d0da22c5",
959 | "name" : "role list",
960 | "protocol" : "saml",
961 | "protocolMapper" : "saml-role-list-mapper",
962 | "consentRequired" : false,
963 | "config" : {
964 | "single" : "false",
965 | "attribute.nameformat" : "Basic",
966 | "attribute.name" : "Role"
967 | }
968 | }, {
969 | "id" : "f2a52a43-989a-4d69-bbc2-1d521cb81a84",
970 | "name" : "full name",
971 | "protocol" : "openid-connect",
972 | "protocolMapper" : "oidc-full-name-mapper",
973 | "consentRequired" : true,
974 | "consentText" : "${fullName}",
975 | "config" : {
976 | "id.token.claim" : "true",
977 | "access.token.claim" : "true"
978 | }
979 | }, {
980 | "id" : "80bb0400-40dd-4e9e-8227-74ee70267144",
981 | "name" : "groups",
982 | "protocol" : "openid-connect",
983 | "protocolMapper" : "oidc-group-membership-mapper",
984 | "consentRequired" : false,
985 | "config" : {
986 | "full.path" : "true",
987 | "id.token.claim" : "true",
988 | "access.token.claim" : "true",
989 | "claim.name" : "groups",
990 | "userinfo.token.claim" : "true"
991 | }
992 | }, {
993 | "id" : "d7c63234-b96d-438d-9d08-0b3282797eaf",
994 | "name" : "given name",
995 | "protocol" : "openid-connect",
996 | "protocolMapper" : "oidc-usermodel-property-mapper",
997 | "consentRequired" : true,
998 | "consentText" : "${givenName}",
999 | "config" : {
1000 | "userinfo.token.claim" : "true",
1001 | "user.attribute" : "firstName",
1002 | "id.token.claim" : "true",
1003 | "access.token.claim" : "true",
1004 | "claim.name" : "given_name",
1005 | "jsonType.label" : "String"
1006 | }
1007 | } ],
1008 | "useTemplateConfig" : false,
1009 | "useTemplateScope" : false,
1010 | "useTemplateMappers" : false
1011 | }, {
1012 | "id" : "091774a7-c1e5-41c2-b906-354d9c5f32e4",
1013 | "clientId" : "realm-management",
1014 | "name" : "${client_realm-management}",
1015 | "surrogateAuthRequired" : false,
1016 | "enabled" : true,
1017 | "clientAuthenticatorType" : "client-secret",
1018 | "secret" : "c719671d-8b87-414d-938d-18119b04a11f",
1019 | "redirectUris" : [ ],
1020 | "webOrigins" : [ ],
1021 | "notBefore" : 0,
1022 | "bearerOnly" : true,
1023 | "consentRequired" : false,
1024 | "standardFlowEnabled" : true,
1025 | "implicitFlowEnabled" : false,
1026 | "directAccessGrantsEnabled" : false,
1027 | "serviceAccountsEnabled" : false,
1028 | "publicClient" : false,
1029 | "frontchannelLogout" : false,
1030 | "protocol" : "openid-connect",
1031 | "attributes" : { },
1032 | "fullScopeAllowed" : false,
1033 | "nodeReRegistrationTimeout" : 0,
1034 | "protocolMappers" : [ {
1035 | "id" : "180ad8af-db8b-4d12-b12c-d186fdfdaf71",
1036 | "name" : "username",
1037 | "protocol" : "openid-connect",
1038 | "protocolMapper" : "oidc-usermodel-property-mapper",
1039 | "consentRequired" : true,
1040 | "consentText" : "${username}",
1041 | "config" : {
1042 | "userinfo.token.claim" : "true",
1043 | "user.attribute" : "username",
1044 | "id.token.claim" : "true",
1045 | "access.token.claim" : "true",
1046 | "claim.name" : "preferred_username",
1047 | "jsonType.label" : "String"
1048 | }
1049 | }, {
1050 | "id" : "1dae2592-7cbe-4973-839a-3f45c92af5c7",
1051 | "name" : "email",
1052 | "protocol" : "openid-connect",
1053 | "protocolMapper" : "oidc-usermodel-property-mapper",
1054 | "consentRequired" : true,
1055 | "consentText" : "${email}",
1056 | "config" : {
1057 | "userinfo.token.claim" : "true",
1058 | "user.attribute" : "email",
1059 | "id.token.claim" : "true",
1060 | "access.token.claim" : "true",
1061 | "claim.name" : "email",
1062 | "jsonType.label" : "String"
1063 | }
1064 | }, {
1065 | "id" : "d5bd0a98-15ea-4ff6-a773-d4ff806820e0",
1066 | "name" : "family name",
1067 | "protocol" : "openid-connect",
1068 | "protocolMapper" : "oidc-usermodel-property-mapper",
1069 | "consentRequired" : true,
1070 | "consentText" : "${familyName}",
1071 | "config" : {
1072 | "userinfo.token.claim" : "true",
1073 | "user.attribute" : "lastName",
1074 | "id.token.claim" : "true",
1075 | "access.token.claim" : "true",
1076 | "claim.name" : "family_name",
1077 | "jsonType.label" : "String"
1078 | }
1079 | }, {
1080 | "id" : "ec8a8018-2c8c-4da3-8524-e147a62d7863",
1081 | "name" : "role list",
1082 | "protocol" : "saml",
1083 | "protocolMapper" : "saml-role-list-mapper",
1084 | "consentRequired" : false,
1085 | "config" : {
1086 | "single" : "false",
1087 | "attribute.nameformat" : "Basic",
1088 | "attribute.name" : "Role"
1089 | }
1090 | }, {
1091 | "id" : "1bc20dcc-cb52-4851-b735-e60269f6bbfc",
1092 | "name" : "full name",
1093 | "protocol" : "openid-connect",
1094 | "protocolMapper" : "oidc-full-name-mapper",
1095 | "consentRequired" : true,
1096 | "consentText" : "${fullName}",
1097 | "config" : {
1098 | "id.token.claim" : "true",
1099 | "access.token.claim" : "true"
1100 | }
1101 | }, {
1102 | "id" : "2b8d9277-9830-4c9c-85ea-2db8ea98fe66",
1103 | "name" : "given name",
1104 | "protocol" : "openid-connect",
1105 | "protocolMapper" : "oidc-usermodel-property-mapper",
1106 | "consentRequired" : true,
1107 | "consentText" : "${givenName}",
1108 | "config" : {
1109 | "userinfo.token.claim" : "true",
1110 | "user.attribute" : "firstName",
1111 | "id.token.claim" : "true",
1112 | "access.token.claim" : "true",
1113 | "claim.name" : "given_name",
1114 | "jsonType.label" : "String"
1115 | }
1116 | } ],
1117 | "useTemplateConfig" : false,
1118 | "useTemplateScope" : false,
1119 | "useTemplateMappers" : false
1120 | }, {
1121 | "id" : "0dd0443b-3964-45a0-a2d9-806064fb9682",
1122 | "clientId" : "security-admin-console",
1123 | "name" : "${client_security-admin-console}",
1124 | "baseUrl" : "/auth/admin/keycloak-auth/console/index.html",
1125 | "surrogateAuthRequired" : false,
1126 | "enabled" : true,
1127 | "clientAuthenticatorType" : "client-secret",
1128 | "secret" : "e150fb45-7fb2-4159-852a-b56a8843a21e",
1129 | "redirectUris" : [ "/auth/admin/keycloak-auth/console/*" ],
1130 | "webOrigins" : [ ],
1131 | "notBefore" : 0,
1132 | "bearerOnly" : false,
1133 | "consentRequired" : false,
1134 | "standardFlowEnabled" : true,
1135 | "implicitFlowEnabled" : false,
1136 | "directAccessGrantsEnabled" : false,
1137 | "serviceAccountsEnabled" : false,
1138 | "publicClient" : true,
1139 | "frontchannelLogout" : false,
1140 | "protocol" : "openid-connect",
1141 | "attributes" : { },
1142 | "fullScopeAllowed" : false,
1143 | "nodeReRegistrationTimeout" : 0,
1144 | "protocolMappers" : [ {
1145 | "id" : "88b7a34a-886f-491f-abf7-58188f79e67d",
1146 | "name" : "role list",
1147 | "protocol" : "saml",
1148 | "protocolMapper" : "saml-role-list-mapper",
1149 | "consentRequired" : false,
1150 | "config" : {
1151 | "single" : "false",
1152 | "attribute.nameformat" : "Basic",
1153 | "attribute.name" : "Role"
1154 | }
1155 | }, {
1156 | "id" : "8142e086-a0a0-4da8-9f55-560d9f0917f2",
1157 | "name" : "username",
1158 | "protocol" : "openid-connect",
1159 | "protocolMapper" : "oidc-usermodel-property-mapper",
1160 | "consentRequired" : true,
1161 | "consentText" : "${username}",
1162 | "config" : {
1163 | "userinfo.token.claim" : "true",
1164 | "user.attribute" : "username",
1165 | "id.token.claim" : "true",
1166 | "access.token.claim" : "true",
1167 | "claim.name" : "preferred_username",
1168 | "jsonType.label" : "String"
1169 | }
1170 | }, {
1171 | "id" : "73e78d96-945a-4cda-80b3-fc8696353c77",
1172 | "name" : "full name",
1173 | "protocol" : "openid-connect",
1174 | "protocolMapper" : "oidc-full-name-mapper",
1175 | "consentRequired" : true,
1176 | "consentText" : "${fullName}",
1177 | "config" : {
1178 | "id.token.claim" : "true",
1179 | "access.token.claim" : "true"
1180 | }
1181 | }, {
1182 | "id" : "1330a8e9-e6bc-48ac-a48e-503f3ad54deb",
1183 | "name" : "locale",
1184 | "protocol" : "openid-connect",
1185 | "protocolMapper" : "oidc-usermodel-attribute-mapper",
1186 | "consentRequired" : false,
1187 | "consentText" : "${locale}",
1188 | "config" : {
1189 | "userinfo.token.claim" : "true",
1190 | "user.attribute" : "locale",
1191 | "id.token.claim" : "true",
1192 | "access.token.claim" : "true",
1193 | "claim.name" : "locale",
1194 | "jsonType.label" : "String"
1195 | }
1196 | }, {
1197 | "id" : "0de1d2b3-7056-461f-84f3-8cfbaac368cd",
1198 | "name" : "email",
1199 | "protocol" : "openid-connect",
1200 | "protocolMapper" : "oidc-usermodel-property-mapper",
1201 | "consentRequired" : true,
1202 | "consentText" : "${email}",
1203 | "config" : {
1204 | "userinfo.token.claim" : "true",
1205 | "user.attribute" : "email",
1206 | "id.token.claim" : "true",
1207 | "access.token.claim" : "true",
1208 | "claim.name" : "email",
1209 | "jsonType.label" : "String"
1210 | }
1211 | }, {
1212 | "id" : "feaa037b-777e-4148-b787-3e4852ab38b9",
1213 | "name" : "family name",
1214 | "protocol" : "openid-connect",
1215 | "protocolMapper" : "oidc-usermodel-property-mapper",
1216 | "consentRequired" : true,
1217 | "consentText" : "${familyName}",
1218 | "config" : {
1219 | "userinfo.token.claim" : "true",
1220 | "user.attribute" : "lastName",
1221 | "id.token.claim" : "true",
1222 | "access.token.claim" : "true",
1223 | "claim.name" : "family_name",
1224 | "jsonType.label" : "String"
1225 | }
1226 | }, {
1227 | "id" : "de6da351-9c23-4987-a66a-6e9db93bb2b8",
1228 | "name" : "given name",
1229 | "protocol" : "openid-connect",
1230 | "protocolMapper" : "oidc-usermodel-property-mapper",
1231 | "consentRequired" : true,
1232 | "consentText" : "${givenName}",
1233 | "config" : {
1234 | "userinfo.token.claim" : "true",
1235 | "user.attribute" : "firstName",
1236 | "id.token.claim" : "true",
1237 | "access.token.claim" : "true",
1238 | "claim.name" : "given_name",
1239 | "jsonType.label" : "String"
1240 | }
1241 | } ],
1242 | "useTemplateConfig" : false,
1243 | "useTemplateScope" : false,
1244 | "useTemplateMappers" : false
1245 | } ],
1246 | "clientTemplates" : [ ],
1247 | "browserSecurityHeaders" : {
1248 | "xContentTypeOptions" : "nosniff",
1249 | "xRobotsTag" : "none",
1250 | "xFrameOptions" : "SAMEORIGIN",
1251 | "xXSSProtection" : "1; mode=block",
1252 | "contentSecurityPolicy" : "frame-src 'self'; frame-ancestors 'self'; object-src 'none';",
1253 | "strictTransportSecurity" : "max-age=31536000; includeSubDomains"
1254 | },
1255 | "smtpServer" : { },
1256 | "eventsEnabled" : false,
1257 | "eventsListeners" : [ "jboss-logging" ],
1258 | "enabledEventTypes" : [ ],
1259 | "adminEventsEnabled" : false,
1260 | "adminEventsDetailsEnabled" : false,
1261 | "components" : {
1262 | "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy" : [ {
1263 | "id" : "ee5f9194-ea5e-48c4-84e8-7dab2aab8f4f",
1264 | "name" : "Full Scope Disabled",
1265 | "providerId" : "scope",
1266 | "subType" : "anonymous",
1267 | "subComponents" : { },
1268 | "config" : { }
1269 | }, {
1270 | "id" : "9834634f-eca7-4c02-9de5-340e4088bd9f",
1271 | "name" : "Trusted Hosts",
1272 | "providerId" : "trusted-hosts",
1273 | "subType" : "anonymous",
1274 | "subComponents" : { },
1275 | "config" : {
1276 | "host-sending-registration-request-must-match" : [ "true" ],
1277 | "client-uris-must-match" : [ "true" ]
1278 | }
1279 | }, {
1280 | "id" : "29b50684-675a-49a6-8824-db03af4408bd",
1281 | "name" : "Allowed Client Templates",
1282 | "providerId" : "allowed-client-templates",
1283 | "subType" : "authenticated",
1284 | "subComponents" : { },
1285 | "config" : { }
1286 | }, {
1287 | "id" : "b59c6981-3641-47e2-a955-dac71096d836",
1288 | "name" : "Allowed Protocol Mapper Types",
1289 | "providerId" : "allowed-protocol-mappers",
1290 | "subType" : "anonymous",
1291 | "subComponents" : { },
1292 | "config" : {
1293 | "allowed-protocol-mapper-types" : [ "oidc-full-name-mapper", "saml-role-list-mapper", "oidc-usermodel-property-mapper", "saml-user-property-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-address-mapper", "saml-user-attribute-mapper", "oidc-usermodel-attribute-mapper" ],
1294 | "consent-required-for-all-mappers" : [ "true" ]
1295 | }
1296 | }, {
1297 | "id" : "7f86f9ec-7c6f-4fc6-8bef-2b543285d39e",
1298 | "name" : "Allowed Protocol Mapper Types",
1299 | "providerId" : "allowed-protocol-mappers",
1300 | "subType" : "authenticated",
1301 | "subComponents" : { },
1302 | "config" : {
1303 | "allowed-protocol-mapper-types" : [ "oidc-full-name-mapper", "oidc-usermodel-property-mapper", "oidc-usermodel-attribute-mapper", "oidc-address-mapper", "saml-role-list-mapper", "saml-user-attribute-mapper", "oidc-sha256-pairwise-sub-mapper", "saml-user-property-mapper" ],
1304 | "consent-required-for-all-mappers" : [ "true" ]
1305 | }
1306 | }, {
1307 | "id" : "22aa78f0-ee01-4829-be0a-d8162a2decdd",
1308 | "name" : "Allowed Client Templates",
1309 | "providerId" : "allowed-client-templates",
1310 | "subType" : "anonymous",
1311 | "subComponents" : { },
1312 | "config" : { }
1313 | }, {
1314 | "id" : "082cd3a4-53f8-4ab5-a166-ad3cebcc5e7c",
1315 | "name" : "Consent Required",
1316 | "providerId" : "consent-required",
1317 | "subType" : "anonymous",
1318 | "subComponents" : { },
1319 | "config" : { }
1320 | }, {
1321 | "id" : "26b12bab-c84f-4ef7-9d71-e94ebd1c6434",
1322 | "name" : "Max Clients Limit",
1323 | "providerId" : "max-clients",
1324 | "subType" : "anonymous",
1325 | "subComponents" : { },
1326 | "config" : {
1327 | "max-clients" : [ "200" ]
1328 | }
1329 | } ],
1330 | "org.keycloak.keys.KeyProvider" : [ {
1331 | "id" : "3cd8351b-db2e-4fcc-b113-4b62bcf02f9a",
1332 | "name" : "rsa-generated",
1333 | "providerId" : "rsa-generated",
1334 | "subComponents" : { },
1335 | "config" : {
1336 | "privateKey" : [ "MIIEpAIBAAKCAQEAmQMFtS3JYRZfbO7DyUshFvbdUvnoxqeH1RMtBxm28DLI39Rx8Ak9qe5dUI7ATqq0/55cSOtsiAT+K+yBO6NUp8Dbk5L2M4aSY7/uMl+/TsCV5feD90GzTxoDO4hvhHpv6pafkF6ux9oRS4Q0tvJ53ToAzFE7lPdxDSViRaj9d0ocC0jrIHu1SXOufSnOr1DI23gqd6Erph94uSyUYUU26V0YjrdKgcfUmmgkc7n9cNCudzCSsXNA4b+TSIRmc08w6zjxZMGtEBbxl/tyX8jCYk6RMWHgRNCkTfSL0UARDH2x6FnVqjMo9OAsFVTEav6wpUiA6GGenclcaFK1EEKe4wIDAQABAoIBAQCVKzgeSHPhnaEMHr1qeT7aF3LvWMmRGXQ3yskD+hK5mpjwdTlarHecOdBpH7HlP1DTPvxy7mjRNiTgh2H51SJLpJ2sAgLZeqEuc8dw/p0P1nqMRkA2BawcOpzaJgmp2n9O8ObAJT45gaOIvmtxy3P4s3phtfPjJ1PkYAStKrFn36nay74m9mAEMgGy4Y2RUzb9QLDFXHXmL10ZGcllJtRP2UGoX08zsWzrS8VOUdAQiJqVg6MxZL9m3vSduw8C1RvZIy3nLcmssOohFqt2GDgsCWFASNiwitQGCmMdRW4yYEdnL9mO1jDrjHSe2PhHwT2u+qjwG3QTW1jMjF+CHLqhAoGBANYyTp8q8SGqDD0zFGXzATbxsT5J2Zu51gUfQ9WG1THz1Tb3gwWmK2lPe8WmD+niheOUUherybuOLdMvjJrX4eU9BP4qn0CfKORyzN9+z6/0dHB8bADPp2B8q6FLiV8hUYmR9+wTmw3NbR74uIJf18CtDxNMyNObzNORcPcWpmATAoGBALbfzY6FjW8AhHLHxtVgihWZf2J31CeUJdNk/dLMq1KQh0tP6z0BJPkluq3l0ShMOp3TMo6SP/dCDNFqkXdR7N7EGJp2ZPMRiX0hx+uz+Tw2FDCC2cf43ALV2t8/nLFd0V4pyh1tARwg+Q8LvDtfkNcJzQciW1bwV7y7cDl6vL/xAoGAX9wv14gOVnSV+aWskVvJxV8xZaEDZHAs2in938fyDeMEHw9yccrGTuElkXUaVh/sr8cnXjShmfCtjYAQOxQ2orNGUsGcd/1C/cpq6fME28hZfCYS5+IHFGV3Ij5+AjcVGK5c+ChmEi1Hkr7ZRG/ETRSmVIrereViK6VBmzNlzkUCgYBGSB707kjb50P/5N16tf57rKFzU4A6scoTw1V1hWk2cws8G3vZ1y3BfwmOuas3pIxGiZt9haGFwmGwvhcn11mEh7K48lV7wTqo16nA4UshI9uAhVlzbCYKBOx4LjdnRxom6UKfKnxpthZh/O2bl+/PZRnh6wdVk0r04siPnqcZ0QKBgQCjkMZJZzrEaJ3GX2rhMfMikgkOdCp5IeENaoJArNkG1aAt3/RpeRmRWU4CdGl0J2r7U7NonHcg11711Wh8HtfmE0pc43dPV6063+/IIZ1dGVjEqxL6DAzMS1VzLjrxLm3CHRIGclxq26ZorGX57s9KG37tVkqr3hSqzBxb7dN1rQ==" ],
1337 | "certificate" : [ "MIICqTCCAZECBgFi/OYlgzANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1rZXljbG9hay1hdXRoMB4XDTE4MDQyNTEzMDEwNFoXDTI4MDQyNTEzMDI0NFowGDEWMBQGA1UEAwwNa2V5Y2xvYWstYXV0aDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJkDBbUtyWEWX2zuw8lLIRb23VL56Manh9UTLQcZtvAyyN/UcfAJPanuXVCOwE6qtP+eXEjrbIgE/ivsgTujVKfA25OS9jOGkmO/7jJfv07AleX3g/dBs08aAzuIb4R6b+qWn5BersfaEUuENLbyed06AMxRO5T3cQ0lYkWo/XdKHAtI6yB7tUlzrn0pzq9QyNt4KnehK6YfeLkslGFFNuldGI63SoHH1JpoJHO5/XDQrncwkrFzQOG/k0iEZnNPMOs48WTBrRAW8Zf7cl/IwmJOkTFh4ETQpE30i9FAEQx9sehZ1aozKPTgLBVUxGr+sKVIgOhhnp3JXGhStRBCnuMCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAG/kj/3ricMRrwMdbgQT+3Mg9CxaQvgnbTAs/d/AxVIdwgLYP37b+oRyjcSUimrfivbtNNT6rvnTyH+IuRuS9t17LBrMKNEkO9LSKbhiqPWDOLG+HKdQeP1ZUwMu1+ZDeQqwobH7LYCh2A/Nq9mPnRPdAB3IZfophZgZ9IaIBuVY8ti2GR7nzU2z2/jmK6+0hU9LMPPgHz+Y7YWtDLERvqhHhhGPEKTRaeS0zOEwrvhsjTZ71TJocCFzAK4DUgQMqemsRu2U9SgqGodxCKwXXD8Mmr+4Hk0fv2Ibs+aI1TkWHnWGfeHeTAigS6eWiCyVvUNbjzUB0Rc2Y+pvH5p+qAg==" ],
1338 | "priority" : [ "100" ]
1339 | }
1340 | }, {
1341 | "id" : "c2d08706-2d4c-4c3b-96f3-3392e7d9b8b5",
1342 | "name" : "hmac-generated",
1343 | "providerId" : "hmac-generated",
1344 | "subComponents" : { },
1345 | "config" : {
1346 | "kid" : [ "252bd953-6077-4904-b2f0-62fce8c00086" ],
1347 | "secret" : [ "eUwVfsWmt0J18WyryES8DhsQZRdvKzw4Ow0YNBZbfWY" ],
1348 | "priority" : [ "100" ]
1349 | }
1350 | }, {
1351 | "id" : "46545b77-5f78-4fe1-b893-d1639a5983ec",
1352 | "name" : "aes-generated",
1353 | "providerId" : "aes-generated",
1354 | "subComponents" : { },
1355 | "config" : {
1356 | "kid" : [ "26286150-2816-4e7f-bc7e-755bbad18081" ],
1357 | "secret" : [ "OHEL4KDwwEiIV-N2LH_XFg" ],
1358 | "priority" : [ "100" ]
1359 | }
1360 | } ]
1361 | },
1362 | "internationalizationEnabled" : false,
1363 | "supportedLocales" : [ ],
1364 | "authenticationFlows" : [ {
1365 | "id" : "c0bcdd99-2ba0-4b53-9a30-12ff002b1957",
1366 | "alias" : "Handle Existing Account",
1367 | "description" : "Handle what to do if there is existing account with same email/username like authenticated identity provider",
1368 | "providerId" : "basic-flow",
1369 | "topLevel" : false,
1370 | "builtIn" : true,
1371 | "authenticationExecutions" : [ {
1372 | "authenticator" : "idp-confirm-link",
1373 | "requirement" : "REQUIRED",
1374 | "priority" : 10,
1375 | "userSetupAllowed" : false,
1376 | "autheticatorFlow" : false
1377 | }, {
1378 | "authenticator" : "idp-email-verification",
1379 | "requirement" : "ALTERNATIVE",
1380 | "priority" : 20,
1381 | "userSetupAllowed" : false,
1382 | "autheticatorFlow" : false
1383 | }, {
1384 | "requirement" : "ALTERNATIVE",
1385 | "priority" : 30,
1386 | "flowAlias" : "Verify Existing Account by Re-authentication",
1387 | "userSetupAllowed" : false,
1388 | "autheticatorFlow" : true
1389 | } ]
1390 | }, {
1391 | "id" : "14ecbd97-17d5-4ead-8847-a3ca45ffd324",
1392 | "alias" : "Verify Existing Account by Re-authentication",
1393 | "description" : "Reauthentication of existing account",
1394 | "providerId" : "basic-flow",
1395 | "topLevel" : false,
1396 | "builtIn" : true,
1397 | "authenticationExecutions" : [ {
1398 | "authenticator" : "idp-username-password-form",
1399 | "requirement" : "REQUIRED",
1400 | "priority" : 10,
1401 | "userSetupAllowed" : false,
1402 | "autheticatorFlow" : false
1403 | }, {
1404 | "authenticator" : "auth-otp-form",
1405 | "requirement" : "OPTIONAL",
1406 | "priority" : 20,
1407 | "userSetupAllowed" : false,
1408 | "autheticatorFlow" : false
1409 | } ]
1410 | }, {
1411 | "id" : "ff9b5e71-6503-4898-90e7-e93db4d6352f",
1412 | "alias" : "browser",
1413 | "description" : "browser based authentication",
1414 | "providerId" : "basic-flow",
1415 | "topLevel" : true,
1416 | "builtIn" : true,
1417 | "authenticationExecutions" : [ {
1418 | "authenticator" : "auth-cookie",
1419 | "requirement" : "ALTERNATIVE",
1420 | "priority" : 10,
1421 | "userSetupAllowed" : false,
1422 | "autheticatorFlow" : false
1423 | }, {
1424 | "authenticator" : "auth-spnego",
1425 | "requirement" : "DISABLED",
1426 | "priority" : 20,
1427 | "userSetupAllowed" : false,
1428 | "autheticatorFlow" : false
1429 | }, {
1430 | "authenticator" : "identity-provider-redirector",
1431 | "requirement" : "ALTERNATIVE",
1432 | "priority" : 25,
1433 | "userSetupAllowed" : false,
1434 | "autheticatorFlow" : false
1435 | }, {
1436 | "requirement" : "ALTERNATIVE",
1437 | "priority" : 30,
1438 | "flowAlias" : "forms",
1439 | "userSetupAllowed" : false,
1440 | "autheticatorFlow" : true
1441 | } ]
1442 | }, {
1443 | "id" : "7a443b54-6eff-4573-8f1d-f8b65083f49f",
1444 | "alias" : "clients",
1445 | "description" : "Base authentication for clients",
1446 | "providerId" : "client-flow",
1447 | "topLevel" : true,
1448 | "builtIn" : true,
1449 | "authenticationExecutions" : [ {
1450 | "authenticator" : "client-secret",
1451 | "requirement" : "ALTERNATIVE",
1452 | "priority" : 10,
1453 | "userSetupAllowed" : false,
1454 | "autheticatorFlow" : false
1455 | }, {
1456 | "authenticator" : "client-jwt",
1457 | "requirement" : "ALTERNATIVE",
1458 | "priority" : 20,
1459 | "userSetupAllowed" : false,
1460 | "autheticatorFlow" : false
1461 | } ]
1462 | }, {
1463 | "id" : "64ed9d0a-37c6-4fa8-82ed-e38cdf9edd6f",
1464 | "alias" : "direct grant",
1465 | "description" : "OpenID Connect Resource Owner Grant",
1466 | "providerId" : "basic-flow",
1467 | "topLevel" : true,
1468 | "builtIn" : true,
1469 | "authenticationExecutions" : [ {
1470 | "authenticator" : "direct-grant-validate-username",
1471 | "requirement" : "REQUIRED",
1472 | "priority" : 10,
1473 | "userSetupAllowed" : false,
1474 | "autheticatorFlow" : false
1475 | }, {
1476 | "authenticator" : "direct-grant-validate-password",
1477 | "requirement" : "REQUIRED",
1478 | "priority" : 20,
1479 | "userSetupAllowed" : false,
1480 | "autheticatorFlow" : false
1481 | }, {
1482 | "authenticator" : "direct-grant-validate-otp",
1483 | "requirement" : "OPTIONAL",
1484 | "priority" : 30,
1485 | "userSetupAllowed" : false,
1486 | "autheticatorFlow" : false
1487 | } ]
1488 | }, {
1489 | "id" : "af8cd545-f632-4974-86b2-7d407b481ed3",
1490 | "alias" : "docker auth",
1491 | "description" : "Used by Docker clients to authenticate against the IDP",
1492 | "providerId" : "basic-flow",
1493 | "topLevel" : true,
1494 | "builtIn" : true,
1495 | "authenticationExecutions" : [ {
1496 | "authenticator" : "docker-http-basic-authenticator",
1497 | "requirement" : "REQUIRED",
1498 | "priority" : 10,
1499 | "userSetupAllowed" : false,
1500 | "autheticatorFlow" : false
1501 | } ]
1502 | }, {
1503 | "id" : "6a2ed4b2-4afc-420a-93c4-9d86659c02e5",
1504 | "alias" : "first broker login",
1505 | "description" : "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account",
1506 | "providerId" : "basic-flow",
1507 | "topLevel" : true,
1508 | "builtIn" : true,
1509 | "authenticationExecutions" : [ {
1510 | "authenticatorConfig" : "review profile config",
1511 | "authenticator" : "idp-review-profile",
1512 | "requirement" : "REQUIRED",
1513 | "priority" : 10,
1514 | "userSetupAllowed" : false,
1515 | "autheticatorFlow" : false
1516 | }, {
1517 | "authenticatorConfig" : "create unique user config",
1518 | "authenticator" : "idp-create-user-if-unique",
1519 | "requirement" : "ALTERNATIVE",
1520 | "priority" : 20,
1521 | "userSetupAllowed" : false,
1522 | "autheticatorFlow" : false
1523 | }, {
1524 | "requirement" : "ALTERNATIVE",
1525 | "priority" : 30,
1526 | "flowAlias" : "Handle Existing Account",
1527 | "userSetupAllowed" : false,
1528 | "autheticatorFlow" : true
1529 | } ]
1530 | }, {
1531 | "id" : "16603278-1fc1-4a09-83e0-4b5a1dbf5284",
1532 | "alias" : "forms",
1533 | "description" : "Username, password, otp and other auth forms.",
1534 | "providerId" : "basic-flow",
1535 | "topLevel" : false,
1536 | "builtIn" : true,
1537 | "authenticationExecutions" : [ {
1538 | "authenticator" : "auth-username-password-form",
1539 | "requirement" : "REQUIRED",
1540 | "priority" : 10,
1541 | "userSetupAllowed" : false,
1542 | "autheticatorFlow" : false
1543 | }, {
1544 | "authenticator" : "auth-otp-form",
1545 | "requirement" : "OPTIONAL",
1546 | "priority" : 20,
1547 | "userSetupAllowed" : false,
1548 | "autheticatorFlow" : false
1549 | } ]
1550 | }, {
1551 | "id" : "67111c63-53b5-47d2-92e2-c0b89a8332b7",
1552 | "alias" : "registration",
1553 | "description" : "registration flow",
1554 | "providerId" : "basic-flow",
1555 | "topLevel" : true,
1556 | "builtIn" : true,
1557 | "authenticationExecutions" : [ {
1558 | "authenticator" : "registration-page-form",
1559 | "requirement" : "REQUIRED",
1560 | "priority" : 10,
1561 | "flowAlias" : "registration form",
1562 | "userSetupAllowed" : false,
1563 | "autheticatorFlow" : true
1564 | } ]
1565 | }, {
1566 | "id" : "8478f7de-8551-49c6-9655-7d2482b76277",
1567 | "alias" : "registration form",
1568 | "description" : "registration form",
1569 | "providerId" : "form-flow",
1570 | "topLevel" : false,
1571 | "builtIn" : true,
1572 | "authenticationExecutions" : [ {
1573 | "authenticator" : "registration-user-creation",
1574 | "requirement" : "REQUIRED",
1575 | "priority" : 20,
1576 | "userSetupAllowed" : false,
1577 | "autheticatorFlow" : false
1578 | }, {
1579 | "authenticator" : "registration-profile-action",
1580 | "requirement" : "REQUIRED",
1581 | "priority" : 40,
1582 | "userSetupAllowed" : false,
1583 | "autheticatorFlow" : false
1584 | }, {
1585 | "authenticator" : "registration-password-action",
1586 | "requirement" : "REQUIRED",
1587 | "priority" : 50,
1588 | "userSetupAllowed" : false,
1589 | "autheticatorFlow" : false
1590 | }, {
1591 | "authenticator" : "registration-recaptcha-action",
1592 | "requirement" : "DISABLED",
1593 | "priority" : 60,
1594 | "userSetupAllowed" : false,
1595 | "autheticatorFlow" : false
1596 | } ]
1597 | }, {
1598 | "id" : "3047169d-5bef-492f-b63b-c1a348fbf2f5",
1599 | "alias" : "reset credentials",
1600 | "description" : "Reset credentials for a user if they forgot their password or something",
1601 | "providerId" : "basic-flow",
1602 | "topLevel" : true,
1603 | "builtIn" : true,
1604 | "authenticationExecutions" : [ {
1605 | "authenticator" : "reset-credentials-choose-user",
1606 | "requirement" : "REQUIRED",
1607 | "priority" : 10,
1608 | "userSetupAllowed" : false,
1609 | "autheticatorFlow" : false
1610 | }, {
1611 | "authenticator" : "reset-credential-email",
1612 | "requirement" : "REQUIRED",
1613 | "priority" : 20,
1614 | "userSetupAllowed" : false,
1615 | "autheticatorFlow" : false
1616 | }, {
1617 | "authenticator" : "reset-password",
1618 | "requirement" : "REQUIRED",
1619 | "priority" : 30,
1620 | "userSetupAllowed" : false,
1621 | "autheticatorFlow" : false
1622 | }, {
1623 | "authenticator" : "reset-otp",
1624 | "requirement" : "OPTIONAL",
1625 | "priority" : 40,
1626 | "userSetupAllowed" : false,
1627 | "autheticatorFlow" : false
1628 | } ]
1629 | }, {
1630 | "id" : "9f63dde2-22e6-4103-b6d2-1e4341f41714",
1631 | "alias" : "saml ecp",
1632 | "description" : "SAML ECP Profile Authentication Flow",
1633 | "providerId" : "basic-flow",
1634 | "topLevel" : true,
1635 | "builtIn" : true,
1636 | "authenticationExecutions" : [ {
1637 | "authenticator" : "http-basic-authenticator",
1638 | "requirement" : "REQUIRED",
1639 | "priority" : 10,
1640 | "userSetupAllowed" : false,
1641 | "autheticatorFlow" : false
1642 | } ]
1643 | } ],
1644 | "authenticatorConfig" : [ {
1645 | "id" : "932ae279-8127-4413-b906-2a6f91edfdf4",
1646 | "alias" : "create unique user config",
1647 | "config" : {
1648 | "require.password.update.after.registration" : "false"
1649 | }
1650 | }, {
1651 | "id" : "5a2ab0b0-aadc-4c24-915b-633ca08a2b1e",
1652 | "alias" : "review profile config",
1653 | "config" : {
1654 | "update.profile.on.first.login" : "missing"
1655 | }
1656 | } ],
1657 | "requiredActions" : [ {
1658 | "alias" : "CONFIGURE_TOTP",
1659 | "name" : "Configure OTP",
1660 | "providerId" : "CONFIGURE_TOTP",
1661 | "enabled" : true,
1662 | "defaultAction" : false,
1663 | "config" : { }
1664 | }, {
1665 | "alias" : "UPDATE_PASSWORD",
1666 | "name" : "Update Password",
1667 | "providerId" : "UPDATE_PASSWORD",
1668 | "enabled" : true,
1669 | "defaultAction" : false,
1670 | "config" : { }
1671 | }, {
1672 | "alias" : "UPDATE_PROFILE",
1673 | "name" : "Update Profile",
1674 | "providerId" : "UPDATE_PROFILE",
1675 | "enabled" : true,
1676 | "defaultAction" : false,
1677 | "config" : { }
1678 | }, {
1679 | "alias" : "VERIFY_EMAIL",
1680 | "name" : "Verify Email",
1681 | "providerId" : "VERIFY_EMAIL",
1682 | "enabled" : true,
1683 | "defaultAction" : false,
1684 | "config" : { }
1685 | }, {
1686 | "alias" : "terms_and_conditions",
1687 | "name" : "Terms and Conditions",
1688 | "providerId" : "terms_and_conditions",
1689 | "enabled" : false,
1690 | "defaultAction" : false,
1691 | "config" : { }
1692 | } ],
1693 | "browserFlow" : "browser",
1694 | "registrationFlow" : "registration",
1695 | "directGrantFlow" : "direct grant",
1696 | "resetCredentialsFlow" : "reset credentials",
1697 | "clientAuthenticationFlow" : "clients",
1698 | "dockerAuthenticationFlow" : "docker auth",
1699 | "attributes" : {
1700 | "_browser_header.xXSSProtection" : "1; mode=block",
1701 | "_browser_header.xFrameOptions" : "SAMEORIGIN",
1702 | "_browser_header.strictTransportSecurity" : "max-age=31536000; includeSubDomains",
1703 | "permanentLockout" : "false",
1704 | "quickLoginCheckMilliSeconds" : "1000",
1705 | "_browser_header.xRobotsTag" : "none",
1706 | "maxFailureWaitSeconds" : "900",
1707 | "minimumQuickLoginWaitSeconds" : "60",
1708 | "failureFactor" : "30",
1709 | "actionTokenGeneratedByUserLifespan" : "300",
1710 | "maxDeltaTimeSeconds" : "43200",
1711 | "_browser_header.xContentTypeOptions" : "nosniff",
1712 | "actionTokenGeneratedByAdminLifespan" : "43200",
1713 | "bruteForceProtected" : "false",
1714 | "_browser_header.contentSecurityPolicy" : "frame-src 'self'; frame-ancestors 'self'; object-src 'none';",
1715 | "waitIncrementSeconds" : "60"
1716 | },
1717 | "keycloakVersion" : "3.4.1.Final",
1718 | "users" : [ {
1719 | "id" : "d2bd7092-cfcf-481f-8ecb-a5e04b3341e6",
1720 | "createdTimestamp" : 1524827271585,
1721 | "username" : "edward",
1722 | "enabled" : true,
1723 | "totp" : false,
1724 | "emailVerified" : true,
1725 | "credentials" : [ {
1726 | "type" : "password",
1727 | "hashedSaltedValue" : "BP/hD+Dt17UTy1R8cO1echlrRn/pu+SP0mYBr0vspk3vfUYkurdaM1+U4Qb/XjR/ka71pr8KgRVBgZMblIOwWw==",
1728 | "salt" : "+7ytWL8uZ1jBHod+sx+aow==",
1729 | "hashIterations" : 27500,
1730 | "counter" : 0,
1731 | "algorithm" : "pbkdf2-sha256",
1732 | "digits" : 0,
1733 | "period" : 0,
1734 | "createdDate" : 1524827277635,
1735 | "config" : { }
1736 | } ],
1737 | "disableableCredentialTypes" : [ "password" ],
1738 | "requiredActions" : [ ],
1739 | "realmRoles" : [ "uma_authorization", "offline_access" ],
1740 | "clientRoles" : {
1741 | "account" : [ "view-profile", "manage-account" ]
1742 | },
1743 | "notBefore" : 0,
1744 | "groups" : [ "/User" ]
1745 | }, {
1746 | "id" : "b3fed88c-e83c-479d-954f-d366e4bbff89",
1747 | "createdTimestamp" : 1525076884559,
1748 | "username" : "kerri",
1749 | "enabled" : true,
1750 | "totp" : false,
1751 | "emailVerified" : true,
1752 | "credentials" : [ {
1753 | "type" : "password",
1754 | "hashedSaltedValue" : "xAf0nhDuoNdzAiR5o+14ivdGJUpQzzYjnHWZF96te8c4QTNBXZAPyjb09V+0SFEkoiOJ2un7Y730Sjx+hWNJtA==",
1755 | "salt" : "aWh0ew+3I3ih8Tah1rdTQg==",
1756 | "hashIterations" : 27500,
1757 | "counter" : 0,
1758 | "algorithm" : "pbkdf2-sha256",
1759 | "digits" : 0,
1760 | "period" : 0,
1761 | "createdDate" : 1525076894957,
1762 | "config" : { }
1763 | } ],
1764 | "disableableCredentialTypes" : [ "password" ],
1765 | "requiredActions" : [ ],
1766 | "realmRoles" : [ "uma_authorization", "offline_access", "AppRole" ],
1767 | "clientRoles" : {
1768 | "account" : [ "view-profile", "manage-account" ]
1769 | },
1770 | "notBefore" : 0,
1771 | "groups" : [ ]
1772 | } ]
1773 | }
--------------------------------------------------------------------------------