├── .github └── FUNDING.yml ├── README.md ├── angular.json ├── browserslist ├── config └── keycloak-auth-realm.json ├── e2e ├── app.e2e-spec.ts ├── app.po.ts └── tsconfig.e2e.json ├── karma.conf.js ├── package-lock.json ├── package.json ├── protractor.conf.js ├── src ├── app │ ├── app-routing.module.ts │ ├── app.component.css │ ├── app.component.html │ ├── app.component.spec.ts │ ├── app.component.ts │ ├── app.module.ts │ ├── core │ │ ├── auth │ │ │ └── keycloak.service.ts │ │ ├── guard │ │ │ └── auth-guard.service.ts │ │ ├── interceptor │ │ │ └── secured-http.interceptor.ts │ │ └── model │ │ │ └── permission-guard.ts │ ├── forbidden │ │ ├── forbidden.component.css │ │ ├── forbidden.component.html │ │ └── forbidden.component.ts │ ├── 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 │ ├── 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-routing.module.ts │ │ └── secured-role.module.ts │ └── secured │ │ ├── secured.component.css │ │ ├── secured.component.html │ │ └── secured.component.ts ├── assets │ └── keycloak.json ├── environments │ ├── environment.prod.ts │ └── environment.ts ├── favicon.ico ├── index.html ├── main.ts ├── polyfills.ts ├── styles.css ├── test.ts ├── tsconfig.app.json ├── tsconfig.spec.json └── typings.d.ts ├── tsconfig.json └── tslint.json /.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 | -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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'. -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /src/app/app.component.css: -------------------------------------------------------------------------------- 1 | h1 { 2 | color: blue; 3 | } -------------------------------------------------------------------------------- /src/app/app.component.html: -------------------------------------------------------------------------------- 1 | 2 |
2 | forbidden works! 3 |
4 | -------------------------------------------------------------------------------- /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/group-restricted/group-restricted-home/group-restricted-home.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/czetsuya/keycloak-angular-auth/6bd4a69372270d18f9549cfe6354339d13611b1e/src/app/group-restricted/group-restricted-home/group-restricted-home.component.css -------------------------------------------------------------------------------- /src/app/group-restricted/group-restricted-home/group-restricted-home.component.html: -------------------------------------------------------------------------------- 1 |This is a secured module home page.
2 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/home/home.component.html: -------------------------------------------------------------------------------- 1 |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 |2 | not-found works! 3 |
4 | -------------------------------------------------------------------------------- /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/app/secured-role/home/home.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/czetsuya/keycloak-angular-auth/6bd4a69372270d18f9549cfe6354339d13611b1e/src/app/secured-role/home/home.component.css -------------------------------------------------------------------------------- /src/app/secured-role/home/home.component.html: -------------------------------------------------------------------------------- 1 |This is a secured page by role!
2 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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/secured/secured.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/czetsuya/keycloak-angular-auth/6bd4a69372270d18f9549cfe6354339d13611b1e/src/app/secured/secured.component.css -------------------------------------------------------------------------------- /src/app/secured/secured.component.html: -------------------------------------------------------------------------------- 1 |This is a secured page!
2 | -------------------------------------------------------------------------------- /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/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 | } -------------------------------------------------------------------------------- /src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true 3 | }; 4 | -------------------------------------------------------------------------------- /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/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/czetsuya/keycloak-angular-auth/6bd4a69372270d18f9549cfe6354339d13611b1e/src/favicon.ico -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |