From f7a0432fdef71fec9648deae073139dc35855460 Mon Sep 17 00:00:00 2001 From: jTendeck Date: Wed, 21 Sep 2022 15:59:32 -0700 Subject: [PATCH 01/48] adds ellipsis to some delete actions --- .../delete-profile.tsx | 2 +- .../products-list/delete-product.tsx | 2 +- .../pages/manager/namespaces/index.tsx | 2 +- src/nextapp/shared/types/query.types.ts | 28 +++++++++---------- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/nextapp/components/authorization-profile-controls/delete-profile.tsx b/src/nextapp/components/authorization-profile-controls/delete-profile.tsx index 1ba885687..0ae5fc76a 100644 --- a/src/nextapp/components/authorization-profile-controls/delete-profile.tsx +++ b/src/nextapp/components/authorization-profile-controls/delete-profile.tsx @@ -54,7 +54,7 @@ const DeleteAuthorizationProfile: React.FC = ({ return ( <> = ({ id, onDeleted }) => { colorScheme="red" data-testid="prd-edit-delete-btn" > - Delete Product + Delete Product... { > - Delete Namespace + Delete Namespace... diff --git a/src/nextapp/shared/types/query.types.ts b/src/nextapp/shared/types/query.types.ts index ab7845e28..eda7151ae 100644 --- a/src/nextapp/shared/types/query.types.ts +++ b/src/nextapp/shared/types/query.types.ts @@ -4482,10 +4482,10 @@ export type Mutation = { grantPermissions?: Maybe>>; revokePermissions?: Maybe; approvePermissions?: Maybe; - /** Authenticate and generate a token for a TemporaryIdentity with the Password Authentication Strategy. */ - authenticateTemporaryIdentityWithPassword?: Maybe; - unauthenticateTemporaryIdentity?: Maybe; - updateAuthenticatedTemporaryIdentity?: Maybe; + /** Authenticate and generate a token for a User with the Password Authentication Strategy. */ + authenticateUserWithPassword?: Maybe; + unauthenticateUser?: Maybe; + updateAuthenticatedUser?: Maybe; }; @@ -5331,14 +5331,14 @@ export type MutationApprovePermissionsArgs = { }; -export type MutationAuthenticateTemporaryIdentityWithPasswordArgs = { +export type MutationAuthenticateUserWithPasswordArgs = { email?: Maybe; password?: Maybe; }; -export type MutationUpdateAuthenticatedTemporaryIdentityArgs = { - data?: Maybe; +export type MutationUpdateAuthenticatedUserArgs = { + data?: Maybe; }; export type Namespace = { @@ -6237,7 +6237,7 @@ export type Query = { getPermissionTicketsForResource?: Maybe>>; /** The version of the Keystone application serving this API. */ appVersion?: Maybe; - authenticatedTemporaryIdentity?: Maybe; + authenticatedUser?: Maybe; }; @@ -8699,16 +8699,16 @@ export type _KsListsMetaInput = { auxiliary?: Maybe; }; -export type AuthenticateTemporaryIdentityOutput = { - __typename?: 'authenticateTemporaryIdentityOutput'; +export type AuthenticateUserOutput = { + __typename?: 'authenticateUserOutput'; /** Used to make subsequent authenticated requests by setting this token in a header: 'Authorization: Bearer '. */ token?: Maybe; - /** Retrieve information on the newly authenticated TemporaryIdentity here. */ - item?: Maybe; + /** Retrieve information on the newly authenticated User here. */ + item?: Maybe; }; -export type UnauthenticateTemporaryIdentityOutput = { - __typename?: 'unauthenticateTemporaryIdentityOutput'; +export type UnauthenticateUserOutput = { + __typename?: 'unauthenticateUserOutput'; /** * `true` when unauthentication succeeds. * NOTE: unauthentication always succeeds when the request has an invalid or missing authentication token. From 61bc4f4200d62430e552143128c8020b444bcd30 Mon Sep 17 00:00:00 2001 From: jTendeck Date: Thu, 22 Sep 2022 13:13:35 -0700 Subject: [PATCH 02/48] add ellipsis to ns-actions --- src/nextapp/components/namespace-actions/namespace-actions.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nextapp/components/namespace-actions/namespace-actions.tsx b/src/nextapp/components/namespace-actions/namespace-actions.tsx index cccc4148d..d91be009a 100644 --- a/src/nextapp/components/namespace-actions/namespace-actions.tsx +++ b/src/nextapp/components/namespace-actions/namespace-actions.tsx @@ -39,7 +39,7 @@ const NamespaceActions: React.FC = ({ name }) => { /> } onClick={handleDelete}> - Delete Namespace + Delete Namespace... From 2422ffb66efb56a0dd6a1461006a33a88dd1a2f7 Mon Sep 17 00:00:00 2001 From: jTendeck Date: Thu, 22 Sep 2022 13:14:47 -0700 Subject: [PATCH 03/48] restore query.types --- src/nextapp/shared/types/query.types.ts | 28 ++++++++++++------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/nextapp/shared/types/query.types.ts b/src/nextapp/shared/types/query.types.ts index eda7151ae..ab7845e28 100644 --- a/src/nextapp/shared/types/query.types.ts +++ b/src/nextapp/shared/types/query.types.ts @@ -4482,10 +4482,10 @@ export type Mutation = { grantPermissions?: Maybe>>; revokePermissions?: Maybe; approvePermissions?: Maybe; - /** Authenticate and generate a token for a User with the Password Authentication Strategy. */ - authenticateUserWithPassword?: Maybe; - unauthenticateUser?: Maybe; - updateAuthenticatedUser?: Maybe; + /** Authenticate and generate a token for a TemporaryIdentity with the Password Authentication Strategy. */ + authenticateTemporaryIdentityWithPassword?: Maybe; + unauthenticateTemporaryIdentity?: Maybe; + updateAuthenticatedTemporaryIdentity?: Maybe; }; @@ -5331,14 +5331,14 @@ export type MutationApprovePermissionsArgs = { }; -export type MutationAuthenticateUserWithPasswordArgs = { +export type MutationAuthenticateTemporaryIdentityWithPasswordArgs = { email?: Maybe; password?: Maybe; }; -export type MutationUpdateAuthenticatedUserArgs = { - data?: Maybe; +export type MutationUpdateAuthenticatedTemporaryIdentityArgs = { + data?: Maybe; }; export type Namespace = { @@ -6237,7 +6237,7 @@ export type Query = { getPermissionTicketsForResource?: Maybe>>; /** The version of the Keystone application serving this API. */ appVersion?: Maybe; - authenticatedUser?: Maybe; + authenticatedTemporaryIdentity?: Maybe; }; @@ -8699,16 +8699,16 @@ export type _KsListsMetaInput = { auxiliary?: Maybe; }; -export type AuthenticateUserOutput = { - __typename?: 'authenticateUserOutput'; +export type AuthenticateTemporaryIdentityOutput = { + __typename?: 'authenticateTemporaryIdentityOutput'; /** Used to make subsequent authenticated requests by setting this token in a header: 'Authorization: Bearer '. */ token?: Maybe; - /** Retrieve information on the newly authenticated User here. */ - item?: Maybe; + /** Retrieve information on the newly authenticated TemporaryIdentity here. */ + item?: Maybe; }; -export type UnauthenticateUserOutput = { - __typename?: 'unauthenticateUserOutput'; +export type UnauthenticateTemporaryIdentityOutput = { + __typename?: 'unauthenticateTemporaryIdentityOutput'; /** * `true` when unauthentication succeeds. * NOTE: unauthentication always succeeds when the request has an invalid or missing authentication token. From f26e96c859257b08dd13c1a80eefda242166fd92 Mon Sep 17 00:00:00 2001 From: ikethecoder Date: Fri, 23 Sep 2022 14:19:08 -0700 Subject: [PATCH 04/48] initial work for online migration of keycloak credentials --- src/auth/auth-oauth2-proxy.js | 33 +++++ src/services/checkKeystoneStatus.ts | 13 ++ .../keycloak/permission-ticket-service.ts | 1 + src/services/keycloak/user-service.ts | 11 ++ src/services/keystone/user.ts | 22 +++ src/services/workflow/index.ts | 2 + src/services/workflow/migrate-user.ts | 127 ++++++++++++++++++ src/test/integrated/workflow/migrate-user.ts | 42 ++++++ 8 files changed, 251 insertions(+) create mode 100644 src/services/checkKeystoneStatus.ts create mode 100644 src/services/workflow/migrate-user.ts create mode 100644 src/test/integrated/workflow/migrate-user.ts diff --git a/src/auth/auth-oauth2-proxy.js b/src/auth/auth-oauth2-proxy.js index 8f5e02aeb..265aa4720 100644 --- a/src/auth/auth-oauth2-proxy.js +++ b/src/auth/auth-oauth2-proxy.js @@ -25,6 +25,7 @@ const { Logger } = require('../logger'); const { UMA2TokenService } = require('../services/uma2'); const { getUma2FromIssuer, Uma2WellKnown } = require('../services/keycloak'); +const { MigrateAuthzUser, MigratePortalUser } = require('../services/workflow'); const toJson = (val) => (val ? JSON.parse(val) : null); @@ -354,6 +355,38 @@ class Oauth2ProxyAuthStrategy { let _results = await _users.adapter.find({ username: username }); + if (_results.length == 0 && username != `${providerUsername}@${provider}`) { + logger.info( + '[migration] %s not found. Migrating %s@%s', + username, + providerUsername, + provider + ); + try { + _results = await _users.adapter.find({ + username: `${providerUsername}@${provider}`, + }); + if (_results.length == 1) { + const oldUser = _results[0]; + // check to see if we need to migrate + await MigrateAuthzUser( + this.keystone, + oldUser.username, + username, + true + ); + await MigratePortalUser(this.keystone, oldUser.username, username); + } + } catch (err) { + logger.error( + '[migration] Error during migration (%s) %s', + username, + err + ); + throw new Error('User migration error'); + } + } + let userId = _results.length == 0 ? null : _results[0].id; if (_results.length == 0) { diff --git a/src/services/checkKeystoneStatus.ts b/src/services/checkKeystoneStatus.ts new file mode 100644 index 000000000..018b31931 --- /dev/null +++ b/src/services/checkKeystoneStatus.ts @@ -0,0 +1,13 @@ +import { logger } from '../logger'; +import { strict as assert } from 'assert'; + +export function checkKeystoneStatus( + ref: string, + errorMessage: string, + result: any +): void { + if ('errors' in result) { + logger.error('[%s] %j', ref, result['errors']); + assert.strictEqual(result['errors'].length, 0, errorMessage); + } +} diff --git a/src/services/keycloak/permission-ticket-service.ts b/src/services/keycloak/permission-ticket-service.ts index d1ba2daa8..af3e9af97 100644 --- a/src/services/keycloak/permission-ticket-service.ts +++ b/src/services/keycloak/permission-ticket-service.ts @@ -143,6 +143,7 @@ export class KeycloakPermissionTicketService { method: 'delete', headers: headers(this.accessToken) as any, }).then(checkStatus); + logger.debug('[deletePermission] DELETED %s', id); } public async getPermission(id: string): Promise { diff --git a/src/services/keycloak/user-service.ts b/src/services/keycloak/user-service.ts index 9f662c0a5..fa5579704 100644 --- a/src/services/keycloak/user-service.ts +++ b/src/services/keycloak/user-service.ts @@ -5,6 +5,7 @@ import KeycloakAdminClient, { default as KcAdminClient, } from '@keycloak/keycloak-admin-client'; import { RoleMappingPayload } from '@keycloak/keycloak-admin-client/lib/defs/roleRepresentation'; +import { checkKeystoneStatus } from '../checkKeystoneStatus'; const logger = Logger('kc.user'); @@ -96,4 +97,14 @@ export class KeycloakUserService { } logger.debug('[syncUserClientRoles] %s OK', id); } + + public async disableUser(id: string): Promise { + logger.debug('[disableUser] %s', id); + await this.kcAdminClient.users.update( + { id }, + { + enabled: false, + } + ); + } } diff --git a/src/services/keystone/user.ts b/src/services/keystone/user.ts index f49d53b52..11c504691 100644 --- a/src/services/keystone/user.ts +++ b/src/services/keystone/user.ts @@ -1,4 +1,5 @@ import { Logger } from '../../logger'; +import { checkKeystoneStatus } from '../checkKeystoneStatus'; import { User } from './types'; const assert = require('assert').strict; @@ -145,3 +146,24 @@ export async function lookupUsersByNamespace( logger.debug('Query [lookupUsersByNamespace] result %j', result); return result.data.usersByNamespace; } + +export async function changeUsername( + context: any, + userId: string, + newUsername: string +): Promise { + const result = await context.executeGraphQL({ + query: `mutation ChangeUsername($userId: ID!, $newUsername: String!) { + updateUser(id: $userId, data: { username: $newUsername } ) { + id + } + }`, + variables: { userId, newUsername }, + }); + if ('errors' in result) { + logger.error('[changeUsername] %s : %s', newUsername, userId); + throw new Error('Failed to change username'); + } + + logger.debug('[changeUsername] RESULT %j', result); +} diff --git a/src/services/workflow/index.ts b/src/services/workflow/index.ts index 255bbcb12..1f35c1aaf 100644 --- a/src/services/workflow/index.ts +++ b/src/services/workflow/index.ts @@ -49,3 +49,5 @@ export { transformActivity, StructuredActivityService, } from './namespace-activity'; + +export { MigrateAuthzUser, MigratePortalUser } from './migrate-user'; diff --git a/src/services/workflow/migrate-user.ts b/src/services/workflow/migrate-user.ts new file mode 100644 index 000000000..26a2ee8c6 --- /dev/null +++ b/src/services/workflow/migrate-user.ts @@ -0,0 +1,127 @@ +import { Logger } from '../../logger'; +import { + KeycloakPermissionTicketService, + KeycloakTokenService, + KeycloakUserService, + PermissionTicket, +} from '../keycloak'; +import { lookupProductEnvironmentServicesBySlug } from '../keystone'; +import { changeUsername, lookupUserByUsername } from '../keystone/user'; +import { getEnvironmentContext } from './get-namespaces'; + +const logger = Logger('wf.MigrateUser'); + +export const MigrateAuthzUser = async ( + context: any, + oldUser: string, + newUser: string, + deleteOldPermissions: boolean +): Promise => { + logger.info( + 'MigrateAuthzUser %s to %s (delete old? %s)', + oldUser, + newUser, + deleteOldPermissions + ); + + const productEnvironmentSlug = process.env.GWA_PROD_ENV_SLUG; + const productEnvironment = await lookupProductEnvironmentServicesBySlug( + context, + productEnvironmentSlug + ); + + const envCtx = await getEnvironmentContext( + context, + productEnvironment.id, + {}, + false + ); + + const tok = new KeycloakTokenService(envCtx.openid.token_endpoint); + const token = await tok.getKeycloakSession( + envCtx.issuerEnvConfig.clientId, + envCtx.issuerEnvConfig.clientSecret + ); + + const permissionApi = new KeycloakPermissionTicketService( + process.env.ISSUER, + token + ); + + const userApi = new KeycloakUserService(process.env.ISSUER); + await userApi.login( + envCtx.issuerEnvConfig.clientId, + envCtx.issuerEnvConfig.clientSecret + ); + + const oldUserId = await userApi.lookupUserByUsername(oldUser); + const newUserId = await userApi.lookupUserByUsername(newUser); + + const resPermsOld = await permissionApi.listPermissions({ + requester: oldUserId, + returnNames: true, + }); + + const resPermsNew = await permissionApi.listPermissions({ + requester: newUserId, + returnNames: true, + }); + + const createPermission = async (perm: PermissionTicket) => { + await permissionApi.createPermission( + perm.resource, + newUserId, + true, + perm.scopeName + ); + }; + + function filterOutAlreadyExisting(p: PermissionTicket): boolean { + return ( + resPermsNew.filter( + (newp) => p.resource === newp.resource && p.scope === newp.scope + ).length == 0 + ); + } + const updates = await Promise.all( + resPermsOld.filter(filterOutAlreadyExisting).map(createPermission) + ); + logger.info( + 'MigrateAuthzUser %s to %s : Copied %d Permissions', + oldUser, + newUser, + updates.length + ); + + if (deleteOldPermissions) { + const deletePermission = async (perm: PermissionTicket) => { + await permissionApi.deletePermission(perm.id); + }; + const deletes = await Promise.all(resPermsOld.map(deletePermission)); + logger.info( + 'MigrateAuthzUser %s to %s : Deleted %d Permissions', + oldUser, + newUser, + deletes.length + ); + + // disable oldUser in authz + userApi.disableUser(oldUserId); + } +}; + +export const MigratePortalUser = async ( + context: any, + oldUsername: string, + newUsername: string +) => { + logger.info('MigratePortalUser %s to %s', oldUsername, newUsername); + + // update the `username` for the user from oldUser and newUsername + const oldUser = (await lookupUserByUsername(context, oldUsername))[0]; + + // change username + await changeUsername(context, oldUser.id, newUsername); + + logger.info('MigratePortalUser %s to %s DONE', oldUsername, newUsername); +}; diff --git a/src/test/integrated/workflow/migrate-user.ts b/src/test/integrated/workflow/migrate-user.ts new file mode 100644 index 000000000..cc7b8f081 --- /dev/null +++ b/src/test/integrated/workflow/migrate-user.ts @@ -0,0 +1,42 @@ +/* +Wire up directly with Keycloak and use the Services +To run: +npm run ts-build +npm run ts-watch +node dist/test/integrated/workflow/migrate-user.js +*/ + +import InitKeystone from '../keystonejs/init'; +import { + MigrateAuthzUser, + MigratePortalUser, +} from '../../../services/workflow'; + +(async () => { + const keystone = await InitKeystone(); + + const ns = 'refactortime'; + const skipAccessControl = true; + + const identity = { + id: null, + name: 'Sample User', + username: 'sample_username', + //namespace: ns, + roles: JSON.stringify(['api-owner']), + scopes: [], + userId: '60c9124f3518951bb519084d', + } as any; + + const ctx = keystone.createContext({ + skipAccessControl, + authentication: { item: identity }, + }); + + if (true) { + //await MigrateAuthzUser(ctx, 'acope@idir', 'acope2@idir', false); + await MigratePortalUser(ctx, 'acopex@idir', 'acope2@idir'); + } + + await keystone.disconnect(); +})(); From 8b07f71d024e4e923fedf36ec138ccca185d24d9 Mon Sep 17 00:00:00 2001 From: ikethecoder Date: Fri, 23 Sep 2022 16:02:03 -0700 Subject: [PATCH 05/48] fix issue with login --- src/auth/auth-oauth2-proxy.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/auth/auth-oauth2-proxy.js b/src/auth/auth-oauth2-proxy.js index 265aa4720..635d1513c 100644 --- a/src/auth/auth-oauth2-proxy.js +++ b/src/auth/auth-oauth2-proxy.js @@ -355,7 +355,10 @@ class Oauth2ProxyAuthStrategy { let _results = await _users.adapter.find({ username: username }); - if (_results.length == 0 && username != `${providerUsername}@${provider}`) { + if ( + _results.length == 0 && + username != `${providerUsername}@${identityProvider}` + ) { logger.info( '[migration] %s not found. Migrating %s@%s', username, @@ -364,7 +367,7 @@ class Oauth2ProxyAuthStrategy { ); try { _results = await _users.adapter.find({ - username: `${providerUsername}@${provider}`, + username: `${providerUsername}@${identityProvider}`, }); if (_results.length == 1) { const oldUser = _results[0]; From ce9e747febe319283aace2153e399ec6324bbcb3 Mon Sep 17 00:00:00 2001 From: ikethecoder Date: Fri, 23 Sep 2022 16:03:23 -0700 Subject: [PATCH 06/48] disable logging for feature deployment --- .github/workflows/ci-build-deploy.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ci-build-deploy.yaml b/.github/workflows/ci-build-deploy.yaml index a2e12c183..2740b40af 100644 --- a/.github/workflows/ci-build-deploy.yaml +++ b/.github/workflows/ci-build-deploy.yaml @@ -271,6 +271,10 @@ jobs: value: '${{ secrets.KEYCLOAK_REALM }}' COOKIE_SECURE: value: 'true' + LOG_LEVEL: + value: 'debug' + DISABLE_LOGGING: + value: 'true' EMAIL_ENABLED: value: 'true' EMAIL_FROM: From 86d9f0c196fc370648f451b9b1b2d4d480cfc121 Mon Sep 17 00:00:00 2001 From: ikethecoder Date: Fri, 23 Sep 2022 16:45:00 -0700 Subject: [PATCH 07/48] disable logging for feature deployment --- src/auth/auth-oauth2-proxy.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/auth/auth-oauth2-proxy.js b/src/auth/auth-oauth2-proxy.js index 635d1513c..533bb3196 100644 --- a/src/auth/auth-oauth2-proxy.js +++ b/src/auth/auth-oauth2-proxy.js @@ -363,7 +363,7 @@ class Oauth2ProxyAuthStrategy { '[migration] %s not found. Migrating %s@%s', username, providerUsername, - provider + identityProvider ); try { _results = await _users.adapter.find({ From 3cb6562be36dc44402421f14ac84af212def1566 Mon Sep 17 00:00:00 2001 From: ikethecoder Date: Fri, 23 Sep 2022 17:55:32 -0700 Subject: [PATCH 08/48] fix issue with login --- src/auth/auth-oauth2-proxy.js | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/auth/auth-oauth2-proxy.js b/src/auth/auth-oauth2-proxy.js index 533bb3196..1948f73dd 100644 --- a/src/auth/auth-oauth2-proxy.js +++ b/src/auth/auth-oauth2-proxy.js @@ -360,10 +360,11 @@ class Oauth2ProxyAuthStrategy { username != `${providerUsername}@${identityProvider}` ) { logger.info( - '[migration] %s not found. Migrating %s@%s', + '[migration] %s not found. Migrate %s@%s access to %s', username, providerUsername, - identityProvider + identityProvider, + username ); try { _results = await _users.adapter.find({ @@ -371,14 +372,12 @@ class Oauth2ProxyAuthStrategy { }); if (_results.length == 1) { const oldUser = _results[0]; + const suctx = this.keystone.createContext({ + skipAccessControl: true, + }); // check to see if we need to migrate - await MigrateAuthzUser( - this.keystone, - oldUser.username, - username, - true - ); - await MigratePortalUser(this.keystone, oldUser.username, username); + await MigrateAuthzUser(suctx, oldUser.username, username, true); + await MigratePortalUser(suctx, oldUser.username, username); } } catch (err) { logger.error( From 988f03b8a990f9e4f3aa7d96bc1e36ed9df0184e Mon Sep 17 00:00:00 2001 From: ikethecoder Date: Fri, 23 Sep 2022 18:20:27 -0700 Subject: [PATCH 09/48] fix incorrect issuer in migration script --- src/services/workflow/migrate-user.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services/workflow/migrate-user.ts b/src/services/workflow/migrate-user.ts index 26a2ee8c6..bd59772b9 100644 --- a/src/services/workflow/migrate-user.ts +++ b/src/services/workflow/migrate-user.ts @@ -44,11 +44,11 @@ export const MigrateAuthzUser = async ( ); const permissionApi = new KeycloakPermissionTicketService( - process.env.ISSUER, + envCtx.openid.issuer, token ); - const userApi = new KeycloakUserService(process.env.ISSUER); + const userApi = new KeycloakUserService(envCtx.openid.issuer); await userApi.login( envCtx.issuerEnvConfig.clientId, envCtx.issuerEnvConfig.clientSecret From 7c28ee21199d564823b9eeb8ce6f20d6f334c74d Mon Sep 17 00:00:00 2001 From: ikethecoder Date: Fri, 30 Sep 2022 11:03:11 -0700 Subject: [PATCH 10/48] change grant access to use email --- src/lists/extensions/UMAPermissionTicket.ts | 48 +++++++++++++++---- .../namespace-access-dialog.tsx | 6 +-- .../namespace-access/users-access.tsx | 9 ++-- src/nextapp/shared/types/query.types.ts | 2 +- src/services/keycloak/user-service.ts | 36 +++++++++++++- src/services/keystone/types.ts | 2 +- 6 files changed, 84 insertions(+), 19 deletions(-) diff --git a/src/lists/extensions/UMAPermissionTicket.ts b/src/lists/extensions/UMAPermissionTicket.ts index 5a6c32295..70adb4a99 100644 --- a/src/lists/extensions/UMAPermissionTicket.ts +++ b/src/lists/extensions/UMAPermissionTicket.ts @@ -9,6 +9,7 @@ import { getResourceSets, getEnvironmentContext } from './Common'; import { strict as assert } from 'assert'; import { Logger } from '../../logger'; import { StructuredActivityService } from '../../services/workflow'; +import { lookupUsersByUsernames } from '../../services/keystone'; const logger = Logger('lists.umaticket'); @@ -29,7 +30,7 @@ type UMAPermissionTicket { const typeUMAPermissionTicketInput = ` input UMAPermissionTicketInput { resourceId: String!, - username: String!, + email: String!, granted: Boolean, scopes: [String]! } @@ -109,7 +110,24 @@ module.exports = { resourceId: args.resourceId, returnNames: true, }; - return await permissionApi.listPermissions(params); + const permissions = await permissionApi.listPermissions(params); + + const usernameList: string[] = permissions.map( + (p) => p.requesterName + ); + + const users = await lookupUsersByUsernames( + context.sudo(), + usernameList + ); + + permissions.forEach((perm) => { + const user = users + .filter((u) => u.username == perm.requesterName) + .pop(); + perm.requesterName = user?.name || perm.requesterName; + }); + return permissions; }, access: EnforcementPoint, }, @@ -145,9 +163,13 @@ module.exports = { envCtx.issuerEnvConfig.clientId, envCtx.issuerEnvConfig.clientSecret ); - const userId = await userApi.lookupUserByUsername( - args.data.username + const users = await userApi.lookupUsersByEmail( + args.data.email, + false ); + assert.strictEqual(users.length, 1, 'Unable to match email'); + const user = users.pop(); + const displayName = user.attributes.display_name || user.email; const result = []; const granted = @@ -159,7 +181,7 @@ module.exports = { for (const scope of scopes) { const permission = await permissionApi.createOrUpdatePermission( args.data.resourceId, - userId, + user.id, granted, scope ); @@ -174,7 +196,7 @@ module.exports = { 'granted', 'namespace access', 'user', - args.data.username, + displayName, scopes ); @@ -215,16 +237,24 @@ module.exports = { returnNames: true, }); - const requesterName = []; + const requesterIds = []; const deletedScopes = []; for (const permId of args.ids) { const foundPerms = perms.filter((perm) => perm.id === permId); assert.strictEqual(foundPerms.length, 1, 'Invalid Permission'); deletedScopes.push(foundPerms[0].scopeName); - requesterName.push(foundPerms[0].requesterName); + requesterIds.push(foundPerms[0].requester); await permissionApi.deletePermission(permId); } + const userApi = new KeycloakUserService(envCtx.openid.issuer); + await userApi.login( + envCtx.issuerEnvConfig.clientId, + envCtx.issuerEnvConfig.clientSecret + ); + const user = await userApi.lookupUserById(requesterIds.pop()); + const displayName = user.attributes.display_name || user.email; + await new StructuredActivityService( context.sudo(), context.authedItem['namespace'] @@ -233,7 +263,7 @@ module.exports = { 'revoked', 'namespace access', 'user', - requesterName.pop(), + displayName, deletedScopes ); diff --git a/src/nextapp/components/namespace-access/namespace-access-dialog.tsx b/src/nextapp/components/namespace-access/namespace-access-dialog.tsx index 1e8124aef..05cdd5db4 100644 --- a/src/nextapp/components/namespace-access/namespace-access-dialog.tsx +++ b/src/nextapp/components/namespace-access/namespace-access-dialog.tsx @@ -77,12 +77,12 @@ const NamespaceAccessDialog: React.FC = ({ - {variant === 'user' ? 'Username' : 'Service Account'} + {variant === 'user' ? 'Email' : 'Service Account'} diff --git a/src/nextapp/components/namespace-access/users-access.tsx b/src/nextapp/components/namespace-access/users-access.tsx index 650af04a5..bd64a2146 100644 --- a/src/nextapp/components/namespace-access/users-access.tsx +++ b/src/nextapp/components/namespace-access/users-access.tsx @@ -73,11 +73,12 @@ const UsersAccess: React.FC = ({ if (isSuccess) { const groupedByRequester = groupBy( data?.getPermissionTicketsForResource, - 'requesterName' + (a) => a.requester + '|' + a.requesterName ); const result = Object.keys(groupedByRequester).map((r) => { + const requesterName = r.split('|')[1]; return { - requesterName: r, + requesterName, scopes: groupedByRequester[r].map((d) => ({ id: d.scope, name: d.scopeName, @@ -94,7 +95,7 @@ const UsersAccess: React.FC = ({ }, [data, isSuccess, search]); const handleGrantAccess = async (form: FormData) => { - const username = form.get('username') as string; + const email = form.get('email') as string; const scopes = form.getAll('scopes') as string[]; try { @@ -102,7 +103,7 @@ const UsersAccess: React.FC = ({ prodEnvId, data: { resourceId, - username, + email, scopes, }, }); diff --git a/src/nextapp/shared/types/query.types.ts b/src/nextapp/shared/types/query.types.ts index ab7845e28..e4e142651 100644 --- a/src/nextapp/shared/types/query.types.ts +++ b/src/nextapp/shared/types/query.types.ts @@ -8268,7 +8268,7 @@ export type UmaPermissionTicket = { export type UmaPermissionTicketInput = { resourceId: Scalars['String']; - username: Scalars['String']; + email: Scalars['String']; granted?: Maybe; scopes: Array>; }; diff --git a/src/services/keycloak/user-service.ts b/src/services/keycloak/user-service.ts index fa5579704..60b711985 100644 --- a/src/services/keycloak/user-service.ts +++ b/src/services/keycloak/user-service.ts @@ -6,6 +6,7 @@ import KeycloakAdminClient, { } from '@keycloak/keycloak-admin-client'; import { RoleMappingPayload } from '@keycloak/keycloak-admin-client/lib/defs/roleRepresentation'; import { checkKeystoneStatus } from '../checkKeystoneStatus'; +import UserRepresentation from '@keycloak/keycloak-admin-client/lib/defs/userRepresentation'; const logger = Logger('kc.user'); @@ -32,13 +33,46 @@ export class KeycloakUserService { logger.debug('[lookupUserByUsername] %s', username); const users = await this.kcAdminClient.users.find({ exact: true, - username: username, + username, }); logger.debug('[lookupUserByUsername] : %j', users); assert.strictEqual(users.length, 1, 'User not found ' + username); return users[0].id; } + public async lookupUserById(id: string): Promise { + logger.debug('[lookupUserById] %s', id); + const user = await this.kcAdminClient.users.findOne({ + id, + }); + logger.debug('[lookupUserById] : %j', user); + return user; + } + + public async lookupUsersByEmail( + email: string, + verified: boolean + ): Promise { + logger.debug('[lookupUserByEmail] %s', email); + const users = ( + await this.kcAdminClient.users.find({ + exact: true, + email, + }) + ) + .filter((user: UserRepresentation) => user.enabled) + .filter( + (user: UserRepresentation) => verified == false || user.emailVerified + ); + logger.debug('[lookupUserByEmail] : %j', users); + assert.strictEqual( + users.length > 0, + true, + 'No suitable match for ' + email + ); + return users; + } + public async login( clientId: string, clientSecret: string diff --git a/src/services/keystone/types.ts b/src/services/keystone/types.ts index ab7845e28..e4e142651 100644 --- a/src/services/keystone/types.ts +++ b/src/services/keystone/types.ts @@ -8268,7 +8268,7 @@ export type UmaPermissionTicket = { export type UmaPermissionTicketInput = { resourceId: Scalars['String']; - username: Scalars['String']; + email: Scalars['String']; granted?: Maybe; scopes: Array>; }; From 305aa00a6c82cc8005c7209a3a703683f1e85911 Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Fri, 30 Sep 2022 12:18:01 -0700 Subject: [PATCH 11/48] 1)Added scenarios for Delete Application 2)Added data-testid for Delete application button 3)Re order the test scenarios --- e2e/cypress/fixtures/developer.json | 14 ++ e2e/cypress/pageObjects/applications.ts | 21 +++ e2e/cypress/pageObjects/consumers.ts | 2 + .../01-delete-application-without-access.ts | 55 +++++++ ...delete-application-with-pending-request.ts | 65 ++++++++ ...elete-application-with-approved-request.ts | 152 ++++++++++++++++++ .../01-create-api.spec.ts | 0 .../02-namespace-preview-mode.ts | 0 .../01-create-api.spec.ts | 0 .../02-team-access.spec.ts | 0 .../03-rqst-access.spec.ts | 0 .../04-access-manager.ts | 0 .../05-namespace-manage.ts | 0 .../06-credential-issuer.ts | 0 .../07-namespace-view.ts | 0 .../08-gateway-config.ts | 0 .../09-content-publish.ts | 0 .../01-create-api.spec.ts | 0 .../02-organization.ts | 0 .../03-documentation.ts | 0 .../04-authorizationProfiles.ts | 0 .../{10-aps-api => 11-aps-api}/05-products.ts | 0 .../06-api-directory.ts | 0 .../07-namespaces.ts | 0 .../pages/devportal/applications/index.tsx | 2 +- 25 files changed, 310 insertions(+), 1 deletion(-) create mode 100644 e2e/cypress/tests/07-delete-application/01-delete-application-without-access.ts create mode 100644 e2e/cypress/tests/07-delete-application/02-delete-application-with-pending-request.ts create mode 100644 e2e/cypress/tests/07-delete-application/03-delete-application-with-approved-request.ts rename e2e/cypress/tests/{08-namespace-preview-mode => 09-namespace-preview-mode}/01-create-api.spec.ts (100%) rename e2e/cypress/tests/{08-namespace-preview-mode => 09-namespace-preview-mode}/02-namespace-preview-mode.ts (100%) rename e2e/cypress/tests/{09-access-permission => 10-access-permission}/01-create-api.spec.ts (100%) rename e2e/cypress/tests/{09-access-permission => 10-access-permission}/02-team-access.spec.ts (100%) rename e2e/cypress/tests/{09-access-permission => 10-access-permission}/03-rqst-access.spec.ts (100%) rename e2e/cypress/tests/{09-access-permission => 10-access-permission}/04-access-manager.ts (100%) rename e2e/cypress/tests/{09-access-permission => 10-access-permission}/05-namespace-manage.ts (100%) rename e2e/cypress/tests/{09-access-permission => 10-access-permission}/06-credential-issuer.ts (100%) rename e2e/cypress/tests/{09-access-permission => 10-access-permission}/07-namespace-view.ts (100%) rename e2e/cypress/tests/{09-access-permission => 10-access-permission}/08-gateway-config.ts (100%) rename e2e/cypress/tests/{09-access-permission => 10-access-permission}/09-content-publish.ts (100%) rename e2e/cypress/tests/{10-aps-api => 11-aps-api}/01-create-api.spec.ts (100%) rename e2e/cypress/tests/{10-aps-api => 11-aps-api}/02-organization.ts (100%) rename e2e/cypress/tests/{10-aps-api => 11-aps-api}/03-documentation.ts (100%) rename e2e/cypress/tests/{10-aps-api => 11-aps-api}/04-authorizationProfiles.ts (100%) rename e2e/cypress/tests/{10-aps-api => 11-aps-api}/05-products.ts (100%) rename e2e/cypress/tests/{10-aps-api => 11-aps-api}/06-api-directory.ts (100%) rename e2e/cypress/tests/{10-aps-api => 11-aps-api}/07-namespaces.ts (100%) diff --git a/e2e/cypress/fixtures/developer.json b/e2e/cypress/fixtures/developer.json index 44e53eb20..e7a77857b 100644 --- a/e2e/cypress/fixtures/developer.json +++ b/e2e/cypress/fixtures/developer.json @@ -73,5 +73,19 @@ "name": "New-Auto Test Product", "environment": "dev" } + }, + "deleteApplication":{ + "application": { + "name": "delete-application-without-access", + "description": "Test application for auto test" + }, + "pendingRequest": { + "name": "delete-application-with-pending-request", + "description": "Test application for auto test" + }, + "approvedRequest": { + "name": "delete-application-with-approved-request", + "description": "Test application for auto test" + } } } \ No newline at end of file diff --git a/e2e/cypress/pageObjects/applications.ts b/e2e/cypress/pageObjects/applications.ts index 0d3ed0188..4b9bf63a0 100644 --- a/e2e/cypress/pageObjects/applications.ts +++ b/e2e/cypress/pageObjects/applications.ts @@ -4,6 +4,7 @@ class ApplicationPage { appName: string = '[data-testid=create-app-name-input]' appDescription: string = '[data-testid=create-app-description-input]' createAppSubmitBtn: string = '[data-testid=create-app-submit-btn]' + applicationTbl = '[role="table"]' createApplication(app: any) { cy.get(this.createAppBtn).first().click() @@ -12,6 +13,26 @@ class ApplicationPage { cy.get(this.createAppSubmitBtn).click() cy.get('table').contains('td', app.name).should('be.visible'); } + + deleteApplication(appName: any) { + cy.get(this.applicationTbl).find('tr').each(($e1, index, $list) => { + let applicationName = $e1.find('td:nth-child(1)').text() + if (applicationName.toLowerCase() === appName.toLowerCase() ) { + cy.wrap($e1).find('button').first().click() + cy.get('[data-testid="delete-application-btn"]').filter(':visible').first().click() + } + }) + } + + checkDeletedApplication(appName: any) { + cy.get(this.applicationTbl).find('tr').each(($e1, index, $list) => { + let applicationName = $e1.find('td:nth-child(1)').text() + debugger + if (applicationName.toLowerCase() === appName.toLowerCase() ) { + assert.fail("Application is not deleted") + } + }) + } } export default ApplicationPage diff --git a/e2e/cypress/pageObjects/consumers.ts b/e2e/cypress/pageObjects/consumers.ts index 001f20356..8a53799e8 100644 --- a/e2e/cypress/pageObjects/consumers.ts +++ b/e2e/cypress/pageObjects/consumers.ts @@ -148,6 +148,8 @@ export default class ConsumersPage { approvePendingRequest() { cy.get(this.approveBtn).click({ force: true }) + cy.wait(1000) + cy.verifyToastMessage("Access request approved") } reviewThePendingRequest() : Boolean{ diff --git a/e2e/cypress/tests/07-delete-application/01-delete-application-without-access.ts b/e2e/cypress/tests/07-delete-application/01-delete-application-without-access.ts new file mode 100644 index 000000000..b38cd330c --- /dev/null +++ b/e2e/cypress/tests/07-delete-application/01-delete-application-without-access.ts @@ -0,0 +1,55 @@ +import ApplicationPage from '../../pageObjects/applications' +import HomePage from '../../pageObjects/home' +import LoginPage from '../../pageObjects/login' +import Products from '../../pageObjects/products' +import ServiceAccountsPage from '../../pageObjects/serviceAccounts' + +describe('Delete application which has no access request spec', () => { + const login = new LoginPage() + const app = new ApplicationPage() + + + before(() => { + cy.visit('/') + cy.deleteAllCookies() + cy.reload() + }) + + beforeEach(() => { + cy.preserveCookies() + cy.fixture('developer').as('developer') + }) + + it('authenticates Harley (developer)', () => { + cy.get('@developer').then(({ user }: any) => { + cy.login(user.credentials.username, user.credentials.password) + }) + }) + + it('creates an application', () => { + cy.visit(app.path) + cy.get('@developer').then(({ deleteApplication }: any) => { + app.createApplication(deleteApplication.application) + }) + }) + + it('Delete application', () => { + cy.visit(app.path) + cy.get('@developer').then(({ deleteApplication }: any) => { + app.deleteApplication(deleteApplication.application.name) + }) + }) + + it('Verify that application is deleted', () => { + cy.get('@developer').then(({ deleteApplication }: any) => { + cy.verifyToastMessage("Application delete") + app.checkDeletedApplication(deleteApplication.application.name) + }) + }) + + after(() => { + cy.logout() + cy.clearLocalStorage({ log: true }) + cy.deleteAllCookies() + }) +}) diff --git a/e2e/cypress/tests/07-delete-application/02-delete-application-with-pending-request.ts b/e2e/cypress/tests/07-delete-application/02-delete-application-with-pending-request.ts new file mode 100644 index 000000000..96a43c7ba --- /dev/null +++ b/e2e/cypress/tests/07-delete-application/02-delete-application-with-pending-request.ts @@ -0,0 +1,65 @@ +import ApiDirectoryPage from '../../pageObjects/apiDirectory' +import ApplicationPage from '../../pageObjects/applications' +import LoginPage from '../../pageObjects/login' +import MyAccessPage from '../../pageObjects/myAccess' + +describe('Delete application which has pending request spec', () => { + const login = new LoginPage() + const app = new ApplicationPage() + const apiDir = new ApiDirectoryPage() + const myAccessPage = new MyAccessPage() + + + before(() => { + cy.visit('/') + cy.deleteAllCookies() + cy.reload() + }) + + beforeEach(() => { + cy.preserveCookies() + cy.fixture('developer').as('developer') + }) + + it('authenticates Harley (developer)', () => { + cy.get('@developer').then(({ user }: any) => { + cy.login(user.credentials.username, user.credentials.password) + }) + }) + + it('creates an application', () => { + cy.visit(app.path) + cy.get('@developer').then(({ deleteApplication }: any) => { + app.createApplication(deleteApplication.pendingRequest) + }) + }) + + it('creates an access request', () => { + cy.visit(apiDir.path) + cy.get('@developer').then(({ product, deleteApplication,accessRequest }: any) => { + apiDir.createAccessRequest(product, deleteApplication.pendingRequest, accessRequest) + myAccessPage.clickOnGenerateSecretButton() + cy.contains("API Key").should('be.visible') + }) + }) + + it('Delete application', () => { + cy.visit(app.path) + cy.get('@developer').then(({ deleteApplication }: any) => { + app.deleteApplication(deleteApplication.pendingRequest.name) + }) + }) + + it('Verify that application is deleted', () => { + cy.get('@developer').then(({ deleteApplication }: any) => { + cy.verifyToastMessage("Application delete") + app.checkDeletedApplication(deleteApplication.pendingRequest.name) + }) + }) + + after(() => { + cy.logout() + cy.clearLocalStorage({ log: true }) + cy.deleteAllCookies() + }) +}) diff --git a/e2e/cypress/tests/07-delete-application/03-delete-application-with-approved-request.ts b/e2e/cypress/tests/07-delete-application/03-delete-application-with-approved-request.ts new file mode 100644 index 000000000..74505d8cd --- /dev/null +++ b/e2e/cypress/tests/07-delete-application/03-delete-application-with-approved-request.ts @@ -0,0 +1,152 @@ +import ApiDirectoryPage from '../../pageObjects/apiDirectory' +import ApplicationPage from '../../pageObjects/applications' +import ConsumersPage from '../../pageObjects/consumers' +import HomePage from '../../pageObjects/home' +import LoginPage from '../../pageObjects/login' +import MyAccessPage from '../../pageObjects/myAccess' + +describe('Delete application which has approved request spec', () => { + const login = new LoginPage() + const app = new ApplicationPage() + const apiDir = new ApiDirectoryPage() + const myAccessPage = new MyAccessPage() + + + before(() => { + cy.visit('/') + cy.deleteAllCookies() + cy.reload() + }) + + beforeEach(() => { + cy.preserveCookies() + cy.fixture('developer').as('developer') + }) + + it('authenticates Harley (developer)', () => { + cy.get('@developer').then(({ user }: any) => { + cy.login(user.credentials.username, user.credentials.password) + }) + }) + + it('creates an application', () => { + cy.visit(app.path) + cy.get('@developer').then(({ deleteApplication }: any) => { + app.createApplication(deleteApplication.approvedRequest) + }) + }) + + it('creates an access request', () => { + cy.visit(apiDir.path) + cy.get('@developer').then(({ product, deleteApplication, accessRequest }: any) => { + apiDir.createAccessRequest(product, deleteApplication.approvedRequest, accessRequest) + myAccessPage.clickOnGenerateSecretButton() + cy.contains("API Key").should('be.visible') + myAccessPage.saveAPIKeyValue() + }) + }) + + after(() => { + cy.clearLocalStorage({ log: true }) + cy.deleteAllCookies() + }) +}) + +describe('Approve Pending Request Spec', () => { + const login = new LoginPage() + const consumers = new ConsumersPage() + const home = new HomePage() + + before(() => { + cy.visit('/') + cy.deleteAllCookies() + cy.reload() + cy.getServiceOrRouteID('services') + cy.getServiceOrRouteID('routes') + }) + + beforeEach(() => { + cy.preserveCookies() + cy.fixture('access-manager').as('access-manager') + cy.fixture('apiowner').as('apiowner') + cy.fixture('developer').as('developer') + cy.fixture('state/store').as('store') + // cy.visit(login.path) + }) + + it('authenticates Mark (Access-Manager)', () => { + cy.get('@access-manager').then(({ user, namespace }: any) => { + cy.login(user.credentials.username, user.credentials.password) + home.useNamespace(namespace); + }) + }) + + it('verify the request details', () => { + cy.visit(consumers.path); + consumers.reviewThePendingRequest() + }) + + it('approves an access request', () => { + consumers.approvePendingRequest() + }) + + after(() => { + cy.logout() + cy.clearLocalStorage({ log: true }) + cy.deleteAllCookies() + }) +}) + +describe('Delete application which has approved request spec', () => { + const login = new LoginPage() + const app = new ApplicationPage() + const apiDir = new ApiDirectoryPage() + const myAccessPage = new MyAccessPage() + + + before(() => { + cy.visit('/') + cy.deleteAllCookies() + cy.reload() + }) + + beforeEach(() => { + cy.preserveCookies() + cy.fixture('developer').as('developer') + cy.fixture('apiowner').as('apiowner') + }) + + it('authenticates Harley (developer)', () => { + cy.get('@developer').then(({ user }: any) => { + cy.login(user.credentials.username, user.credentials.password) + }) + }) + + it('Delete application', () => { + cy.visit(app.path) + cy.get('@developer').then(({ deleteApplication }: any) => { + app.deleteApplication(deleteApplication.approvedRequest.name) + }) + }) + + it('Verify that application is deleted', () => { + cy.get('@developer').then(({ deleteApplication }: any) => { + cy.verifyToastMessage("Application delete") + app.checkDeletedApplication(deleteApplication.approvedRequest.name) + }) + }) + + it('Verify that API is not accessible with the generated API Key when the application is deleted', () => { + cy.get('@apiowner').then(({ product }: any) => { + cy.makeKongRequest(product.environment.config.serviceName, 'GET').then((response) => { + expect(response.status).to.be.equal(500) + }) + }) + }) + + after(() => { + cy.logout() + cy.clearLocalStorage({ log: true }) + cy.deleteAllCookies() + }) +}) diff --git a/e2e/cypress/tests/08-namespace-preview-mode/01-create-api.spec.ts b/e2e/cypress/tests/09-namespace-preview-mode/01-create-api.spec.ts similarity index 100% rename from e2e/cypress/tests/08-namespace-preview-mode/01-create-api.spec.ts rename to e2e/cypress/tests/09-namespace-preview-mode/01-create-api.spec.ts diff --git a/e2e/cypress/tests/08-namespace-preview-mode/02-namespace-preview-mode.ts b/e2e/cypress/tests/09-namespace-preview-mode/02-namespace-preview-mode.ts similarity index 100% rename from e2e/cypress/tests/08-namespace-preview-mode/02-namespace-preview-mode.ts rename to e2e/cypress/tests/09-namespace-preview-mode/02-namespace-preview-mode.ts diff --git a/e2e/cypress/tests/09-access-permission/01-create-api.spec.ts b/e2e/cypress/tests/10-access-permission/01-create-api.spec.ts similarity index 100% rename from e2e/cypress/tests/09-access-permission/01-create-api.spec.ts rename to e2e/cypress/tests/10-access-permission/01-create-api.spec.ts diff --git a/e2e/cypress/tests/09-access-permission/02-team-access.spec.ts b/e2e/cypress/tests/10-access-permission/02-team-access.spec.ts similarity index 100% rename from e2e/cypress/tests/09-access-permission/02-team-access.spec.ts rename to e2e/cypress/tests/10-access-permission/02-team-access.spec.ts diff --git a/e2e/cypress/tests/09-access-permission/03-rqst-access.spec.ts b/e2e/cypress/tests/10-access-permission/03-rqst-access.spec.ts similarity index 100% rename from e2e/cypress/tests/09-access-permission/03-rqst-access.spec.ts rename to e2e/cypress/tests/10-access-permission/03-rqst-access.spec.ts diff --git a/e2e/cypress/tests/09-access-permission/04-access-manager.ts b/e2e/cypress/tests/10-access-permission/04-access-manager.ts similarity index 100% rename from e2e/cypress/tests/09-access-permission/04-access-manager.ts rename to e2e/cypress/tests/10-access-permission/04-access-manager.ts diff --git a/e2e/cypress/tests/09-access-permission/05-namespace-manage.ts b/e2e/cypress/tests/10-access-permission/05-namespace-manage.ts similarity index 100% rename from e2e/cypress/tests/09-access-permission/05-namespace-manage.ts rename to e2e/cypress/tests/10-access-permission/05-namespace-manage.ts diff --git a/e2e/cypress/tests/09-access-permission/06-credential-issuer.ts b/e2e/cypress/tests/10-access-permission/06-credential-issuer.ts similarity index 100% rename from e2e/cypress/tests/09-access-permission/06-credential-issuer.ts rename to e2e/cypress/tests/10-access-permission/06-credential-issuer.ts diff --git a/e2e/cypress/tests/09-access-permission/07-namespace-view.ts b/e2e/cypress/tests/10-access-permission/07-namespace-view.ts similarity index 100% rename from e2e/cypress/tests/09-access-permission/07-namespace-view.ts rename to e2e/cypress/tests/10-access-permission/07-namespace-view.ts diff --git a/e2e/cypress/tests/09-access-permission/08-gateway-config.ts b/e2e/cypress/tests/10-access-permission/08-gateway-config.ts similarity index 100% rename from e2e/cypress/tests/09-access-permission/08-gateway-config.ts rename to e2e/cypress/tests/10-access-permission/08-gateway-config.ts diff --git a/e2e/cypress/tests/09-access-permission/09-content-publish.ts b/e2e/cypress/tests/10-access-permission/09-content-publish.ts similarity index 100% rename from e2e/cypress/tests/09-access-permission/09-content-publish.ts rename to e2e/cypress/tests/10-access-permission/09-content-publish.ts diff --git a/e2e/cypress/tests/10-aps-api/01-create-api.spec.ts b/e2e/cypress/tests/11-aps-api/01-create-api.spec.ts similarity index 100% rename from e2e/cypress/tests/10-aps-api/01-create-api.spec.ts rename to e2e/cypress/tests/11-aps-api/01-create-api.spec.ts diff --git a/e2e/cypress/tests/10-aps-api/02-organization.ts b/e2e/cypress/tests/11-aps-api/02-organization.ts similarity index 100% rename from e2e/cypress/tests/10-aps-api/02-organization.ts rename to e2e/cypress/tests/11-aps-api/02-organization.ts diff --git a/e2e/cypress/tests/10-aps-api/03-documentation.ts b/e2e/cypress/tests/11-aps-api/03-documentation.ts similarity index 100% rename from e2e/cypress/tests/10-aps-api/03-documentation.ts rename to e2e/cypress/tests/11-aps-api/03-documentation.ts diff --git a/e2e/cypress/tests/10-aps-api/04-authorizationProfiles.ts b/e2e/cypress/tests/11-aps-api/04-authorizationProfiles.ts similarity index 100% rename from e2e/cypress/tests/10-aps-api/04-authorizationProfiles.ts rename to e2e/cypress/tests/11-aps-api/04-authorizationProfiles.ts diff --git a/e2e/cypress/tests/10-aps-api/05-products.ts b/e2e/cypress/tests/11-aps-api/05-products.ts similarity index 100% rename from e2e/cypress/tests/10-aps-api/05-products.ts rename to e2e/cypress/tests/11-aps-api/05-products.ts diff --git a/e2e/cypress/tests/10-aps-api/06-api-directory.ts b/e2e/cypress/tests/11-aps-api/06-api-directory.ts similarity index 100% rename from e2e/cypress/tests/10-aps-api/06-api-directory.ts rename to e2e/cypress/tests/11-aps-api/06-api-directory.ts diff --git a/e2e/cypress/tests/10-aps-api/07-namespaces.ts b/e2e/cypress/tests/11-aps-api/07-namespaces.ts similarity index 100% rename from e2e/cypress/tests/10-aps-api/07-namespaces.ts rename to e2e/cypress/tests/11-aps-api/07-namespaces.ts diff --git a/src/nextapp/pages/devportal/applications/index.tsx b/src/nextapp/pages/devportal/applications/index.tsx index 894afccac..b9527b28e 100644 --- a/src/nextapp/pages/devportal/applications/index.tsx +++ b/src/nextapp/pages/devportal/applications/index.tsx @@ -151,7 +151,7 @@ const ApplicationsPage: React.FC< aria-label={`${d.name} actions menu button`} placement="bottom-end" > - + Delete Application From f6eac2f69cda662f6d50b4d4881f3f6bbdc89885 Mon Sep 17 00:00:00 2001 From: ikethecoder Date: Fri, 30 Sep 2022 12:50:43 -0700 Subject: [PATCH 12/48] org group access to use email --- src/controllers/v2/OrganizationController.ts | 2 +- src/controllers/v2/openapi.yaml | 4 --- src/controllers/v2/routes.ts | 1 - src/services/keycloak/group-service.ts | 6 ++--- src/services/keycloak/user-service.ts | 21 +++++++++++++++ src/services/org-groups/group-access.ts | 14 +++++----- src/services/org-groups/org-group-service.ts | 21 +++++++++++---- src/services/org-groups/types.ts | 1 - .../integrated/keystonejs/batch-product.ts | 5 ++-- .../integrated/org-groups/group-access.ts | 26 +++++++++++-------- 10 files changed, 67 insertions(+), 34 deletions(-) diff --git a/src/controllers/v2/OrganizationController.ts b/src/controllers/v2/OrganizationController.ts index f06593b8c..eb6a6112b 100644 --- a/src/controllers/v2/OrganizationController.ts +++ b/src/controllers/v2/OrganizationController.ts @@ -140,7 +140,7 @@ export class OrganizationController extends Controller { const groupAccessService = new GroupAccessService(prodEnv.uma2); await groupAccessService.login(envConfig.clientId, envConfig.clientSecret); - await groupAccessService.createOrUpdateGroupAccess(body); + await groupAccessService.createOrUpdateGroupAccess(body, ['idir']); } /** diff --git a/src/controllers/v2/openapi.yaml b/src/controllers/v2/openapi.yaml index d1752fc1f..018379ebd 100644 --- a/src/controllers/v2/openapi.yaml +++ b/src/controllers/v2/openapi.yaml @@ -464,12 +464,8 @@ components: properties: id: type: string - username: - type: string email: type: string - required: - - username type: object additionalProperties: false GroupMember: diff --git a/src/controllers/v2/routes.ts b/src/controllers/v2/routes.ts index e3af9986b..470142a58 100644 --- a/src/controllers/v2/routes.ts +++ b/src/controllers/v2/routes.ts @@ -283,7 +283,6 @@ const models: TsoaRoute.Models = { "dataType": "refObject", "properties": { "id": {"dataType":"string"}, - "username": {"dataType":"string","required":true}, "email": {"dataType":"string"}, }, "additionalProperties": false, diff --git a/src/services/keycloak/group-service.ts b/src/services/keycloak/group-service.ts index cbbc8c17c..5b5f58438 100644 --- a/src/services/keycloak/group-service.ts +++ b/src/services/keycloak/group-service.ts @@ -197,13 +197,13 @@ export class KeycloakGroupService { return this.kcAdminClient.users.delFromGroup({ id, groupId }); } - public async lookupMemberByUsername(username: string): Promise { + public async lookupMemberByEmail(email: string): Promise { const foundUsers = await this.kcAdminClient.users.find({ - username, + email, exact: true, }); if (foundUsers.length == 0) { - logger.warn('[lookupMemberByUsername] User not found %s', username); + logger.warn('[lookupMemberByEmail] User not found %s', email); } return foundUsers.length == 0 ? null : foundUsers[0].id; } diff --git a/src/services/keycloak/user-service.ts b/src/services/keycloak/user-service.ts index 60b711985..ade8e5cf4 100644 --- a/src/services/keycloak/user-service.ts +++ b/src/services/keycloak/user-service.ts @@ -20,6 +20,10 @@ export class KeycloakUserService { this.kcAdminClient = new KcAdminClient({ baseUrl, realmName }); } + public useAdminClient(client: KcAdminClient) { + this.kcAdminClient = client; + } + // public async findOne(id: string) { // logger.debug('[findOne] %s', id); // const user = await this.kcAdminClient.users.findOne({ @@ -49,6 +53,23 @@ export class KeycloakUserService { return user; } + public async lookupUserIdByEmail( + email: string, + verified: boolean, + identityProviders: string[] + ): Promise { + const user = (await this.lookupUsersByEmail(email, verified)) + .filter(async (user) => { + const userWithAttributes = await this.lookupUserById(user.id); + return identityProviders.includes( + userWithAttributes.attributes.identity_provider + ); + }) + .pop(); + assert.strictEqual(Boolean(user), true, `No suitable match for ${email}`); + return user.id; + } + public async lookupUsersByEmail( email: string, verified: boolean diff --git a/src/services/org-groups/group-access.ts b/src/services/org-groups/group-access.ts index 232798565..d22bbed80 100644 --- a/src/services/org-groups/group-access.ts +++ b/src/services/org-groups/group-access.ts @@ -44,7 +44,8 @@ export class GroupAccessService { } async createOrUpdateGroupAccess( - groupMembership: GroupMembership + groupMembership: GroupMembership, + validIdentityProviders: string[] ): Promise { const access = buildGroupAccess( groupMembership.name, @@ -88,7 +89,8 @@ export class GroupAccessService { await this.orgGroupService.syncMembers( orgGroup, - buildUserReference(groupRole.name, groupMembership.members) + buildUserReference(groupRole.name, groupMembership.members), + validIdentityProviders ); // TODO: Delete any Permissions that are no longer specified for the Policy @@ -235,7 +237,7 @@ export class GroupAccessService { members: [], }; - const members: { [username: string]: GroupMember } = {}; + const members: { [email: string]: GroupMember } = {}; for (const groupPath of fullGroupPaths) { logger.debug('[getGroupAccess] Evaluate %s', groupPath); @@ -254,10 +256,10 @@ export class GroupAccessService { ); roleMembers.forEach((userRef) => { - if (userRef.username in members) { - members[userRef.username].roles.push(root(fullGroupPaths[0])); + if (userRef.email in members) { + members[userRef.email].roles.push(root(fullGroupPaths[0])); } else { - members[userRef.username] = { + members[userRef.email] = { member: userRef, roles: [root(fullGroupPaths[0])], }; diff --git a/src/services/org-groups/org-group-service.ts b/src/services/org-groups/org-group-service.ts index 6089776e0..ee001dd91 100644 --- a/src/services/org-groups/org-group-service.ts +++ b/src/services/org-groups/org-group-service.ts @@ -7,6 +7,7 @@ import { KeycloakClientPolicyService, KeycloakClientService, KeycloakGroupService, + KeycloakUserService, } from '../keycloak'; import GroupRepresentation from '@keycloak/keycloak-admin-client/lib/defs/groupRepresentation'; import ClientScopeRepresentation from '@keycloak/keycloak-admin-client/lib/defs/clientScopeRepresentation'; @@ -61,11 +62,17 @@ function throwError(msg: string) { export class OrgGroupService { private clientId: string; private keycloakService; + private userKeycloakService; private groups: GroupRepresentation[]; constructor(issuerUrl: string) { logger.debug('[OrgGroupService] %s', issuerUrl); this.keycloakService = new KeycloakGroupService(issuerUrl); + + this.userKeycloakService = new KeycloakUserService(issuerUrl); + this.userKeycloakService.useAdminClient( + this.keycloakService.getAdminClient() + ); } public async login( @@ -534,7 +541,6 @@ export class OrgGroupService { } return allGroupMembers.map((user) => ({ id: user.id, - username: user.username, email: user.email, })); } @@ -554,7 +560,8 @@ export class OrgGroupService { public async syncMembers( orgGroup: OrganizationGroup, - memberUsernames: UserReference[] + memberEmails: UserReference[], + validIdentityProviders: string[] ) { const groupIds = this.getGroupBranchToLeaf(orgGroup); const group = groupIds[groupIds.length - 1]; @@ -563,7 +570,7 @@ export class OrgGroupService { '[syncMembers] %s (%s) %j', orgGroup.name, group.id, - memberUsernames + memberEmails ); const currentMembers = (await this.listMembersForLeafOnly(orgGroup)).map( @@ -571,8 +578,12 @@ export class OrgGroupService { ); const desiredMembers = ( await Promise.all( - memberUsernames.map((u) => - this.keycloakService.lookupMemberByUsername(u.username) + memberEmails.map((u) => + this.userKeycloakService.lookupUserIdByEmail( + u.email, + false, + validIdentityProviders + ) ) ) ).filter((s) => s); diff --git a/src/services/org-groups/types.ts b/src/services/org-groups/types.ts index 440e8f160..a1c5fc364 100644 --- a/src/services/org-groups/types.ts +++ b/src/services/org-groups/types.ts @@ -26,7 +26,6 @@ export interface GroupPermission { export interface UserReference { id?: string; - username: string; email?: string; } diff --git a/src/test/integrated/keystonejs/batch-product.ts b/src/test/integrated/keystonejs/batch-product.ts index 634f95fad..45b0970c2 100644 --- a/src/test/integrated/keystonejs/batch-product.ts +++ b/src/test/integrated/keystonejs/batch-product.ts @@ -73,9 +73,10 @@ import { lookupServiceAccessesByEnvironment } from '../../../services/keystone'; appId: '122000000002', environments: [ { + active: false, name: 'dev', - approval: false, - flow: 'public', + approval: true, + flow: 'client-credentials', appId: '12200000', }, ], diff --git a/src/test/integrated/org-groups/group-access.ts b/src/test/integrated/org-groups/group-access.ts index 66b0879be..c1574464c 100644 --- a/src/test/integrated/org-groups/group-access.ts +++ b/src/test/integrated/org-groups/group-access.ts @@ -46,13 +46,17 @@ import { GroupMembership } from '@/services/org-groups/types'; parent: '/ca.bc.gov/ministry-of-citizens-services', members: [ { - member: { username: 'acope@idir' }, - roles: ['data-custodian'], + member: { email: 'aidan.cope@gmail.com' }, + roles: ['organization-admin'], + }, + { + member: { email: 'apsowner@nowhere' }, + roles: ['organization-admin'], }, ], }; - await kc.createOrUpdateGroupAccess(access); + await kc.createOrUpdateGroupAccess(access, ['idir']); } if (false) { @@ -79,7 +83,7 @@ import { GroupMembership } from '@/services/org-groups/types'; ], }; - await kc.createOrUpdateGroupAccess(access); + await kc.createOrUpdateGroupAccess(access, ['idir']); } if (false) { @@ -114,15 +118,15 @@ import { GroupMembership } from '@/services/org-groups/types'; 'namespace', 'erx-demo' ); - await kc.createOrUpdateGroupAccess(access); + await kc.createOrUpdateGroupAccess(access, ['idir']); } - if (false) { + if (true) { o(await kc.getGroupMembership('databc')); - await kc.assignNamespace( - 'ministry-of-citizens-services', - 'databc', - 'erx-demo' - ); + // await kc.assignNamespace( + // 'ministry-of-citizens-services', + // 'databc', + // 'erx-demo' + // ); } if (false) { From 19bb54591fdd07b5d66f70230962ee05740a3b41 Mon Sep 17 00:00:00 2001 From: ikethecoder Date: Fri, 30 Sep 2022 12:52:03 -0700 Subject: [PATCH 13/48] org group access to use email --- src/test/integrated/org-groups/sync-members.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/test/integrated/org-groups/sync-members.ts b/src/test/integrated/org-groups/sync-members.ts index d58732295..e102ad84e 100644 --- a/src/test/integrated/org-groups/sync-members.ts +++ b/src/test/integrated/org-groups/sync-members.ts @@ -27,11 +27,15 @@ import { KeycloakGroupService } from '../../../services/keycloak'; parent: '/data-custodian/ca.bc.gov/ministry-of-citizens-services', }; - await kc.syncMembers(org, [ - { username: 'acope@idir' }, - { username: 'someone_doesnt_exist' }, - { username: 'platform' }, - ]); + await kc.syncMembers( + org, + [ + { email: 'acope@idir' }, + { email: 'someone_doesnt_exist' }, + { email: 'platform' }, + ], + ['idir'] + ); // await kc.syncMembers(org, [{ username: 'acope@idir' }]); From a5a7d84b04d04ef540a7b07a3cbbf9367c27b2f8 Mon Sep 17 00:00:00 2001 From: ikethecoder Date: Fri, 30 Sep 2022 13:27:00 -0700 Subject: [PATCH 14/48] change username write info log --- src/services/keystone/user.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/services/keystone/user.ts b/src/services/keystone/user.ts index 11c504691..840c206f5 100644 --- a/src/services/keystone/user.ts +++ b/src/services/keystone/user.ts @@ -156,6 +156,7 @@ export async function changeUsername( query: `mutation ChangeUsername($userId: ID!, $newUsername: String!) { updateUser(id: $userId, data: { username: $newUsername } ) { id + username } }`, variables: { userId, newUsername }, @@ -165,5 +166,5 @@ export async function changeUsername( throw new Error('Failed to change username'); } - logger.debug('[changeUsername] RESULT %j', result); + logger.info('[changeUsername] RESULT %j', result); } From 73959cbf2764111eff85fa0813f77792c514b337 Mon Sep 17 00:00:00 2001 From: ikethecoder Date: Fri, 30 Sep 2022 13:31:06 -0700 Subject: [PATCH 15/48] hide user policies on service account page for ns access --- .../components/namespace-access/service-accounts-access.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/nextapp/components/namespace-access/service-accounts-access.tsx b/src/nextapp/components/namespace-access/service-accounts-access.tsx index 2bccabea9..f32c9edd0 100644 --- a/src/nextapp/components/namespace-access/service-accounts-access.tsx +++ b/src/nextapp/components/namespace-access/service-accounts-access.tsx @@ -64,7 +64,9 @@ const ServiceAccountsAccess: React.FC = ({ const requests = React.useMemo(() => { if (isSuccess) { - const result = data?.getUmaPoliciesForResource; + const result = data?.getUmaPoliciesForResource.filter((policy) => + Boolean(policy.clients) + ); if (search) { return result.filter((d) => d.name.search(search) >= 0); } From c43f5e3ad73f2db77d55da6455564a0c4ad4b8d3 Mon Sep 17 00:00:00 2001 From: ikethecoder Date: Wed, 5 Oct 2022 15:55:17 -0700 Subject: [PATCH 16/48] upd report with subject name for ns access --- src/services/report/data/ns-access.ts | 16 ++++++++++++++++ src/services/report/output/structure.ts | 7 ++++++- src/services/report/workbook.service.ts | 13 +++++++++++-- src/services/workflow/get-namespaces.ts | 17 +++++++++++------ src/services/workflow/index.ts | 1 + 5 files changed, 45 insertions(+), 9 deletions(-) diff --git a/src/services/report/data/ns-access.ts b/src/services/report/data/ns-access.ts index f4e8a87c1..8c41fc233 100644 --- a/src/services/report/data/ns-access.ts +++ b/src/services/report/data/ns-access.ts @@ -1,3 +1,6 @@ +import { KeycloakUserService } from '../../keycloak'; +import { lookupUsersByUsernames } from '../../keystone'; +import { Keystone } from '@keystonejs/keystone'; import { PolicyQuery, UMAPolicyService } from '../../uma2'; import { EnvironmentContext } from '../../workflow/get-namespaces'; import { ReportOfNamespaces } from './namespaces'; @@ -5,12 +8,14 @@ import { ReportOfNamespaces } from './namespaces'; interface ReportOfNamespaceAccess { namespace: string; subject: string; + subjectName: string; scope: string; } /* */ export async function getNamespaceAccess( + context: Keystone, envCtx: EnvironmentContext, namespaces: ReportOfNamespaces[] ): Promise { @@ -33,6 +38,7 @@ export async function getNamespaceAccess( data.push({ namespace: ns.name, subject, + subjectName: '', scope, }); }); @@ -46,6 +52,16 @@ export async function getNamespaceAccess( policy.groups.forEach(doScopes); } }); + + const usernames = data.map((d) => d.subject); + const users = await lookupUsersByUsernames(context, usernames); + data.forEach( + (d) => + (d.subjectName = users + .filter((u) => u.username === d.subject) + .pop()?.name) + ); + return data; } ); diff --git a/src/services/report/output/structure.ts b/src/services/report/output/structure.ts index c1631e296..bc289503c 100644 --- a/src/services/report/output/structure.ts +++ b/src/services/report/output/structure.ts @@ -36,7 +36,7 @@ export const reportStructure: any = { { header: 'Org', key: 'org', - width: 25, + width: 40, }, { header: 'Org Unit', @@ -58,6 +58,11 @@ export const reportStructure: any = { key: 'subject', width: 40, }, + { + header: 'Subject Name', + key: 'subjectName', + width: 40, + }, { header: 'Scope', key: 'scope', diff --git a/src/services/report/workbook.service.ts b/src/services/report/workbook.service.ts index 5f4a4f6e7..c187cf09a 100644 --- a/src/services/report/workbook.service.ts +++ b/src/services/report/workbook.service.ts @@ -1,6 +1,9 @@ import { Keystone } from '@keystonejs/keystone'; import ExcelJS from 'exceljs'; -import { getGwaProductEnvironment } from '../workflow/get-namespaces'; +import { + getGwaProductEnvironment, + injectResSvrAccessTokenToContext, +} from '../workflow/get-namespaces'; import { generateExcelWorkbook } from './output/xls-generator'; import { getConsumerControls, @@ -25,10 +28,16 @@ export class WorkbookService { public async buildWorkbook(ids: string[] = []): Promise { const envCtx = await getGwaProductEnvironment(this.keystone, true); + await injectResSvrAccessTokenToContext(envCtx); + const namespaces = (await getNamespaces(envCtx)).filter( (ns) => ids.length === 0 || ids.includes(ns.resource_id) ); - const ns_access = await getNamespaceAccess(envCtx, namespaces); + const ns_access = await getNamespaceAccess( + this.keystone, + envCtx, + namespaces + ); const gateway_metrics = await getGatewayMetrics(this.keystone, namespaces); const serviceLookup: Map = gatewayToMap( gateway_metrics diff --git a/src/services/workflow/get-namespaces.ts b/src/services/workflow/get-namespaces.ts index c64689f35..cf337af32 100644 --- a/src/services/workflow/get-namespaces.ts +++ b/src/services/workflow/get-namespaces.ts @@ -106,9 +106,9 @@ export async function getEnvironmentContext( }; } -async function getNamespaceResourceSets(envCtx: EnvironmentContext) { - logger.debug('[getNamespaceResourceSets] for %s', envCtx.prodEnv.id); - +export async function injectResSvrAccessTokenToContext( + envCtx: EnvironmentContext +) { assert.strictEqual( isUserBasedResourceOwners(envCtx), false, @@ -116,15 +116,20 @@ async function getNamespaceResourceSets(envCtx: EnvironmentContext) { ); const issuerEnvConfig = envCtx.issuerEnvConfig; - //const resourceAccessScope = - // envCtx.prodEnv.credentialIssuer.resourceAccessScope; + const resSvrAccessToken = await new KeycloakTokenService( envCtx.openid.token_endpoint ).getKeycloakSession(issuerEnvConfig.clientId, issuerEnvConfig.clientSecret); + envCtx.accessToken = resSvrAccessToken; +} + +async function getNamespaceResourceSets(envCtx: EnvironmentContext) { + logger.debug('[getNamespaceResourceSets] for %s', envCtx.prodEnv.id); + const permApi = new UMAPermissionService( envCtx.uma2.permission_endpoint, - resSvrAccessToken + envCtx.accessToken ); const permTicket = await permApi.requestTicket([ { diff --git a/src/services/workflow/index.ts b/src/services/workflow/index.ts index 1f35c1aaf..3780a4ec6 100644 --- a/src/services/workflow/index.ts +++ b/src/services/workflow/index.ts @@ -38,6 +38,7 @@ export { LinkConsumerToNamespace } from './link-consumer-to-namespace'; export { getGwaProductEnvironment, getMyNamespaces, + injectResSvrAccessTokenToContext, getResourceServerContext, getEnvironmentContext, } from './get-namespaces'; From 042e0a3b4321188d9ce65408e9221cee668b9136 Mon Sep 17 00:00:00 2001 From: ikethecoder Date: Fri, 7 Oct 2022 17:11:40 -0700 Subject: [PATCH 17/48] upd export report with new user name rather than username --- src/services/keystone/access-request.ts | 1 + src/services/report/data/consumer-access.ts | 7 ++++--- src/services/report/data/consumer-requests.ts | 2 +- src/services/workflow/get-namespaces.ts | 4 ++++ 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/services/keystone/access-request.ts b/src/services/keystone/access-request.ts index 8bdb72d76..b298c504d 100644 --- a/src/services/keystone/access-request.ts +++ b/src/services/keystone/access-request.ts @@ -20,6 +20,7 @@ export async function getAccessRequestsByNamespace( isIssued isComplete requestor { + name username } application { diff --git a/src/services/report/data/consumer-access.ts b/src/services/report/data/consumer-access.ts index 53548acc8..9576c32a1 100644 --- a/src/services/report/data/consumer-access.ts +++ b/src/services/report/data/consumer-access.ts @@ -66,10 +66,10 @@ export async function getConsumerAccess( const accesses = await lookupDetailedServiceAccessesByNS(ksCtx, ns.name); const consumerLookup: any = {}; accesses.forEach((access: ServiceAccess) => { - if (access.consumer === null) { - logger.warn('Service Access with Missing Consumer! %j', access); - } else { + if (access.consumer) { consumerLookup[access.consumer.username] = access; + } else { + logger.warn('Service Access with Missing Consumer! %j', access); } }); @@ -143,6 +143,7 @@ export async function getConsumerAccess( await Promise.all(subPromises); accesses + .filter((access) => access.consumer) .filter((access) => !(access.consumer.username in repeatChecker)) .forEach((access) => { data.push({ diff --git a/src/services/report/data/consumer-requests.ts b/src/services/report/data/consumer-requests.ts index b43fa56b8..2a41ab345 100644 --- a/src/services/report/data/consumer-requests.ts +++ b/src/services/report/data/consumer-requests.ts @@ -42,7 +42,7 @@ export async function getConsumerRequests( prod_env_flow: req.productEnvironment?.flow, app_name: req.application.name, app_id: req.application.appId, - requestor: req.requestor.username, + requestor: req.requestor.name, req_created: req.createdAt, req_reviewer: '', req_result: req.isComplete diff --git a/src/services/workflow/get-namespaces.ts b/src/services/workflow/get-namespaces.ts index cf337af32..678ab356d 100644 --- a/src/services/workflow/get-namespaces.ts +++ b/src/services/workflow/get-namespaces.ts @@ -174,6 +174,10 @@ export async function getResourceServerContext( const usesUma2 = isAuthzUsingUma2(prodEnv); const openid = await getOpenidFromIssuer(issuerEnvConfig.issuerUrl); + if (openid == null) { + logger.error('[getResourceServerContext] Failed to reach IdP', prodEnv); + return null; + } const uma2 = usesUma2 ? await getUma2FromIssuer(issuerEnvConfig.issuerUrl) : null; From 4274b68be3149866fb590dae180d3c70be2957b4 Mon Sep 17 00:00:00 2001 From: ikethecoder Date: Fri, 7 Oct 2022 17:42:01 -0700 Subject: [PATCH 18/48] some integrated tests --- src/test/integrated/keycloak/users.ts | 55 ++++++++++++++ src/test/integrated/reports/consumerAccess.ts | 71 +++++++++++++++++++ .../integrated/reports/namespaceAccess.ts | 63 ++++++++++++++++ 3 files changed, 189 insertions(+) create mode 100644 src/test/integrated/keycloak/users.ts create mode 100644 src/test/integrated/reports/consumerAccess.ts create mode 100644 src/test/integrated/reports/namespaceAccess.ts diff --git a/src/test/integrated/keycloak/users.ts b/src/test/integrated/keycloak/users.ts new file mode 100644 index 000000000..179664641 --- /dev/null +++ b/src/test/integrated/keycloak/users.ts @@ -0,0 +1,55 @@ +/* + +Wire up directly with Keycloak and use the Services + +To run: + + +npm run ts-build +export CID="" +export CSC="" +export ISSUER="" +npm run ts-watch +node dist/test/integrated/keycloak/users.js + +*/ + +import { o } from '../util'; + +import { KeycloakUserService } from '../../../services/keycloak'; + +(async () => { + const kc = new KeycloakUserService(process.env.ISSUER); + + await kc.login(process.env.CID, process.env.CSC); + // const group = await kc.getGroup('ns', 'platform'); + // console.log(JSON.stringify(group, null, 4)); + + //const groups = await kc.search('orgcontrol'); + //o(groups); + + const user = await kc.lookupUserById('xf875dffa-6bcb-4a4d-a8da-4c0429bbb960'); + o(user); + + if (false) { + const users = await kc.lookupUsersByEmail('aidan.cope@gmail.com', false); + o(users); + const userId = users.pop().id; + o(userId); + } + + const permissions: any[] = [ + { + requester: 'f875dffa-6bcb-4a4d-a8da-4c0429bbb960', + }, + ]; + const userIds = ['f875dffa-6bcb-4a4d-a8da-4c0429bbb960']; + const users = await Promise.all(userIds.map((id) => kc.lookupUserById(id))); + + permissions.forEach((perm) => { + const user = users.filter((u) => u.id == perm.requester).pop(); + perm.requesterName = user.attributes.display_name || user.email; + }); + o(permissions); + // console.log(await kc.listMembers('660cadef-9233-4532-ba45-5393beaddea4')); +})(); diff --git a/src/test/integrated/reports/consumerAccess.ts b/src/test/integrated/reports/consumerAccess.ts new file mode 100644 index 000000000..35abdde80 --- /dev/null +++ b/src/test/integrated/reports/consumerAccess.ts @@ -0,0 +1,71 @@ +/* +Wire up directly with Keycloak and use the Services +export TOK="" +To run: +npm run ts-build +npm run ts-watch +node dist/test/integrated/reports/consumerAccess.js +*/ + +import InitKeystone from '../keystonejs/init'; +import { o } from '../util'; +import { Logger } from '../../../logger'; +import { + getConsumerAccess, + getNamespaceAccess, +} from '../../../services/report/data'; +import { + getGwaProductEnvironment, + injectResSvrAccessTokenToContext, +} from '../../../services/workflow'; +import { lookupProductEnvironmentServicesBySlug } from '../../../services/keystone'; + +const logger = Logger('test.reports'); + +(async () => { + const keystone = await InitKeystone(); + + const ns = 'refactortime'; + const skipAccessControl = true; + + const identity = { + id: null, + name: 'Sample User', + username: 'sample_username', + namespace: ns, + roles: JSON.stringify(['access-manager']), + scopes: [], + //userId: '60c9124f3518951bb519084d', + userId: '60c9124f3518951bb519084d', // acope@idir + } as any; + + const ctx = keystone.createContext({ + skipAccessControl, + authentication: { item: identity }, + }); + ctx.req = { + headers: { + 'x-forwarded-access-token': process.env.TOK, + }, + }; + + ctx.req.user = { sub: '15a3cbbe-95b5-49f0-84ee-434a9b92d04a' }; + + const envCtx = await getGwaProductEnvironment(ctx, true); + + await injectResSvrAccessTokenToContext(envCtx); + + const result = await getConsumerAccess( + envCtx, + ctx, + [ + { + resource_id: '49f95b75-6aa5-4bc0-a0bf-6a8037ca083d', + name: 'refactortime', + }, + ], + new Map() + ); + o(result); + await keystone.disconnect(); +})(); diff --git a/src/test/integrated/reports/namespaceAccess.ts b/src/test/integrated/reports/namespaceAccess.ts new file mode 100644 index 000000000..1d6d07f04 --- /dev/null +++ b/src/test/integrated/reports/namespaceAccess.ts @@ -0,0 +1,63 @@ +/* +Wire up directly with Keycloak and use the Services +export TOK="" +To run: +npm run ts-build +npm run ts-watch +node dist/test/integrated/reports/namespaceAccess.js +*/ + +import InitKeystone from '../keystonejs/init'; +import { o } from '../util'; +import { Logger } from '../../../logger'; +import { getNamespaceAccess } from '../../../services/report/data'; +import { + getGwaProductEnvironment, + injectResSvrAccessTokenToContext, +} from '../../../services/workflow'; +import { lookupProductEnvironmentServicesBySlug } from '../../../services/keystone'; + +const logger = Logger('test.reports'); + +(async () => { + const keystone = await InitKeystone(); + + const ns = 'refactortime'; + const skipAccessControl = true; + + const identity = { + id: null, + name: 'Sample User', + username: 'sample_username', + namespace: ns, + roles: JSON.stringify(['access-manager']), + scopes: [], + //userId: '60c9124f3518951bb519084d', + userId: '60c9124f3518951bb519084d', // acope@idir + } as any; + + const ctx = keystone.createContext({ + skipAccessControl, + authentication: { item: identity }, + }); + ctx.req = { + headers: { + 'x-forwarded-access-token': process.env.TOK, + }, + }; + + ctx.req.user = { sub: '15a3cbbe-95b5-49f0-84ee-434a9b92d04a' }; + + const envCtx = await getGwaProductEnvironment(ctx, true); + + await injectResSvrAccessTokenToContext(envCtx); + + const result = await getNamespaceAccess(ctx, envCtx, [ + { + resource_id: '49f95b75-6aa5-4bc0-a0bf-6a8037ca083d', + name: 'refactortime', + }, + ]); + o(result); + await keystone.disconnect(); +})(); From a496c8601f02b688f585bea4211db09cd576f199 Mon Sep 17 00:00:00 2001 From: ikethecoder Date: Tue, 11 Oct 2022 12:15:17 -0700 Subject: [PATCH 19/48] upd local realm with special users --- local/keycloak/master-realm.json | 6521 ++++++++++++++++-------------- 1 file changed, 3594 insertions(+), 2927 deletions(-) diff --git a/local/keycloak/master-realm.json b/local/keycloak/master-realm.json index 55260b275..80e2b6336 100644 --- a/local/keycloak/master-realm.json +++ b/local/keycloak/master-realm.json @@ -1,2994 +1,3661 @@ { - "id" : "master", - "realm" : "master", - "displayName" : "BCGov API Management Portal (DEV)", - "displayNameHtml" : "
Local Keycloak
", - "notBefore" : 0, - "revokeRefreshToken" : false, - "refreshTokenMaxReuse" : 0, - "accessTokenLifespan" : 300, - "accessTokenLifespanForImplicitFlow" : 900, - "ssoSessionIdleTimeout" : 1800, - "ssoSessionMaxLifespan" : 36000, - "ssoSessionIdleTimeoutRememberMe" : 0, - "ssoSessionMaxLifespanRememberMe" : 0, - "offlineSessionIdleTimeout" : 2592000, - "offlineSessionMaxLifespanEnabled" : false, - "offlineSessionMaxLifespan" : 5184000, - "clientSessionIdleTimeout" : 0, - "clientSessionMaxLifespan" : 0, - "clientOfflineSessionIdleTimeout" : 0, - "clientOfflineSessionMaxLifespan" : 0, - "accessCodeLifespan" : 60, - "accessCodeLifespanUserAction" : 43200, - "accessCodeLifespanLogin" : 864000000, - "actionTokenGeneratedByAdminLifespan" : 43200, - "actionTokenGeneratedByUserLifespan" : 43200, - "enabled" : true, - "sslRequired" : "external", - "registrationAllowed" : false, - "registrationEmailAsUsername" : false, - "rememberMe" : false, - "verifyEmail" : false, - "loginWithEmailAllowed" : true, - "duplicateEmailsAllowed" : false, - "resetPasswordAllowed" : false, - "editUsernameAllowed" : false, - "bruteForceProtected" : false, - "permanentLockout" : false, - "maxFailureWaitSeconds" : 900, - "minimumQuickLoginWaitSeconds" : 60, - "waitIncrementSeconds" : 60, - "quickLoginCheckMilliSeconds" : 1000, - "maxDeltaTimeSeconds" : 43200, - "failureFactor" : 30, - "roles" : { - "realm" : [ { - "id" : "2905dd1c-feb7-4b4c-a51a-924697adf78a", - "name" : "create-realm", - "description" : "${role_create-realm}", - "composite" : false, - "clientRole" : false, - "containerId" : "master", - "attributes" : { } - }, { - "id" : "006ba659-502a-4f51-aff5-3aa1cbb13d02", - "name" : "uma_authorization", - "description" : "${role_uma_authorization}", - "composite" : false, - "clientRole" : false, - "containerId" : "master", - "attributes" : { } - }, { - "id" : "ba7796d3-c1ba-4fb3-8c33-27226c979eba", - "name" : "aps-admin", - "composite" : false, - "clientRole" : false, - "containerId" : "master", - "attributes" : { } - }, { - "id" : "005aef84-ea6d-4edf-90b6-fc7bd64945ad", - "name" : "credential-admin", - "composite" : false, - "clientRole" : false, - "containerId" : "master", - "attributes" : { } - }, { - "id" : "65344728-04bb-4cb8-afe5-3d41cb4457ec", - "name" : "offline_access", - "description" : "${role_offline-access}", - "composite" : false, - "clientRole" : false, - "containerId" : "master", - "attributes" : { } - }, { - "id" : "75fad79d-71f1-46c2-b79b-001d25eae49f", - "name" : "api-manager", - "composite" : false, - "clientRole" : false, - "containerId" : "master", - "attributes" : { } - }, { - "id" : "0d22b102-52e1-4152-b119-2f6846e21b84", - "name" : "api-owner", - "composite" : false, - "clientRole" : false, - "containerId" : "master", - "attributes" : { } - }, { - "id" : "064ef17c-0617-4cbc-b632-77a2fa0919b7", - "name" : "admin", - "description" : "${role_admin}", - "composite" : true, - "composites" : { - "realm" : [ "create-realm" ], - "client" : { - "aps-v2-realm" : [ "query-realms", "create-client", "manage-realm", "manage-authorization", "manage-events", "impersonation", "view-authorization", "manage-identity-providers", "query-users", "manage-clients", "view-identity-providers", "query-groups", "view-events", "view-users", "manage-users", "view-clients", "query-clients", "view-realm" ], - "master-realm" : [ "query-realms", "manage-identity-providers", "manage-authorization", "manage-clients", "impersonation", "query-users", "manage-events", "manage-users", "view-identity-providers", "view-events", "view-users", "create-client", "query-clients", "query-groups", "view-realm", "view-clients", "manage-realm", "view-authorization" ] - } + "id": "master", + "realm": "master", + "displayName": "BCGov API Management Portal (DEV)", + "displayNameHtml": "
Local Keycloak
", + "notBefore": 0, + "revokeRefreshToken": false, + "refreshTokenMaxReuse": 0, + "accessTokenLifespan": 300, + "accessTokenLifespanForImplicitFlow": 900, + "ssoSessionIdleTimeout": 1800, + "ssoSessionMaxLifespan": 36000, + "ssoSessionIdleTimeoutRememberMe": 0, + "ssoSessionMaxLifespanRememberMe": 0, + "offlineSessionIdleTimeout": 2592000, + "offlineSessionMaxLifespanEnabled": false, + "offlineSessionMaxLifespan": 5184000, + "clientSessionIdleTimeout": 0, + "clientSessionMaxLifespan": 0, + "clientOfflineSessionIdleTimeout": 0, + "clientOfflineSessionMaxLifespan": 0, + "accessCodeLifespan": 60, + "accessCodeLifespanUserAction": 43200, + "accessCodeLifespanLogin": 864000000, + "actionTokenGeneratedByAdminLifespan": 43200, + "actionTokenGeneratedByUserLifespan": 43200, + "enabled": true, + "sslRequired": "external", + "registrationAllowed": false, + "registrationEmailAsUsername": false, + "rememberMe": false, + "verifyEmail": false, + "loginWithEmailAllowed": false, + "duplicateEmailsAllowed": true, + "resetPasswordAllowed": false, + "editUsernameAllowed": false, + "bruteForceProtected": false, + "permanentLockout": false, + "maxFailureWaitSeconds": 900, + "minimumQuickLoginWaitSeconds": 60, + "waitIncrementSeconds": 60, + "quickLoginCheckMilliSeconds": 1000, + "maxDeltaTimeSeconds": 43200, + "failureFactor": 30, + "roles": { + "realm": [ + { + "id": "2905dd1c-feb7-4b4c-a51a-924697adf78a", + "name": "create-realm", + "description": "${role_create-realm}", + "composite": false, + "clientRole": false, + "containerId": "master", + "attributes": {} + }, + { + "id": "006ba659-502a-4f51-aff5-3aa1cbb13d02", + "name": "uma_authorization", + "description": "${role_uma_authorization}", + "composite": false, + "clientRole": false, + "containerId": "master", + "attributes": {} + }, + { + "id": "ba7796d3-c1ba-4fb3-8c33-27226c979eba", + "name": "aps-admin", + "composite": false, + "clientRole": false, + "containerId": "master", + "attributes": {} + }, + { + "id": "005aef84-ea6d-4edf-90b6-fc7bd64945ad", + "name": "credential-admin", + "composite": false, + "clientRole": false, + "containerId": "master", + "attributes": {} + }, + { + "id": "65344728-04bb-4cb8-afe5-3d41cb4457ec", + "name": "offline_access", + "description": "${role_offline-access}", + "composite": false, + "clientRole": false, + "containerId": "master", + "attributes": {} + }, + { + "id": "75fad79d-71f1-46c2-b79b-001d25eae49f", + "name": "api-manager", + "composite": false, + "clientRole": false, + "containerId": "master", + "attributes": {} }, - "clientRole" : false, - "containerId" : "master", - "attributes" : { } - } ], - "client" : { - "aps-portal" : [ { - "id" : "b393d043-9ade-4c64-a6e1-5f70c9a416e3", - "name" : "api-owner", - "composite" : false, - "clientRole" : true, - "containerId" : "f333c5e5-fba2-48e8-aab7-7b6862881202", - "attributes" : { } - }, { - "id" : "e0c6f7a0-3a8b-4572-9dac-82dd4b676b30", - "name" : "credential-admin", - "composite" : false, - "clientRole" : true, - "containerId" : "f333c5e5-fba2-48e8-aab7-7b6862881202", - "attributes" : { } - }, { - "id" : "3c0fcf9e-e622-497d-8146-eddd0304f9c8", - "name" : "aps-admin", - "composite" : false, - "clientRole" : true, - "containerId" : "f333c5e5-fba2-48e8-aab7-7b6862881202", - "attributes" : { } - }, { - "id" : "9a357bd3-2c73-40ea-ac09-399a9f7cc9f8", - "name" : "api-manager", - "composite" : false, - "clientRole" : true, - "containerId" : "f333c5e5-fba2-48e8-aab7-7b6862881202", - "attributes" : { } - }, { - "id" : "2c0e0832-4a1e-411b-a8f9-8f86096c3968", - "name" : "developer", - "composite" : false, - "clientRole" : true, - "containerId" : "f333c5e5-fba2-48e8-aab7-7b6862881202", - "attributes" : { } - } ], - "gwa-api" : [ { - "id" : "a50b2fc6-ea49-46d8-9716-683f3a764f5d", - "name" : "developer", - "composite" : false, - "clientRole" : true, - "containerId" : "c002b2b1-0ca8-4fd6-896e-6d2e3395a345", - "attributes" : { } - }, { - "id" : "0c1c2230-24d4-4199-af35-bed6a1044c70", - "name" : "api-admin", - "composite" : false, - "clientRole" : true, - "containerId" : "c002b2b1-0ca8-4fd6-896e-6d2e3395a345", - "attributes" : { } - }, { - "id" : "409fcd4e-54ab-4e19-bdc5-ef8059721e22", - "name" : "uma_protection", - "composite" : false, - "clientRole" : true, - "containerId" : "c002b2b1-0ca8-4fd6-896e-6d2e3395a345", - "attributes" : { } - }, { - "id" : "8d387de9-3d53-4a69-9cb4-d5d285926029", - "name" : "api-owner", - "composite" : false, - "clientRole" : true, - "containerId" : "c002b2b1-0ca8-4fd6-896e-6d2e3395a345", - "attributes" : { } - } ], - "aps-v2-realm" : [ { - "id" : "a7ff1dc9-1214-4757-861b-453b204e460f", - "name" : "manage-events", - "description" : "${role_manage-events}", - "composite" : false, - "clientRole" : true, - "containerId" : "62f2227e-e1ac-4c74-b278-1eab7f7664ae", - "attributes" : { } - }, { - "id" : "faf54935-32bc-4e01-b0e6-8b9bb1cae6e8", - "name" : "query-realms", - "description" : "${role_query-realms}", - "composite" : false, - "clientRole" : true, - "containerId" : "62f2227e-e1ac-4c74-b278-1eab7f7664ae", - "attributes" : { } - }, { - "id" : "2272fc44-5c1d-465d-9608-6b4612e26755", - "name" : "impersonation", - "description" : "${role_impersonation}", - "composite" : false, - "clientRole" : true, - "containerId" : "62f2227e-e1ac-4c74-b278-1eab7f7664ae", - "attributes" : { } - }, { - "id" : "fecb856f-8db8-4432-9f11-6b3426372a9c", - "name" : "create-client", - "description" : "${role_create-client}", - "composite" : false, - "clientRole" : true, - "containerId" : "62f2227e-e1ac-4c74-b278-1eab7f7664ae", - "attributes" : { } - }, { - "id" : "dd8c065c-fcd9-4f58-8dad-ec6100cbcbdf", - "name" : "view-authorization", - "description" : "${role_view-authorization}", - "composite" : false, - "clientRole" : true, - "containerId" : "62f2227e-e1ac-4c74-b278-1eab7f7664ae", - "attributes" : { } - }, { - "id" : "ec6f0230-82ae-4713-8d21-fc97214042d9", - "name" : "manage-identity-providers", - "description" : "${role_manage-identity-providers}", - "composite" : false, - "clientRole" : true, - "containerId" : "62f2227e-e1ac-4c74-b278-1eab7f7664ae", - "attributes" : { } - }, { - "id" : "f33e3aa2-0b3e-4397-9968-82be07d68f40", - "name" : "manage-realm", - "description" : "${role_manage-realm}", - "composite" : false, - "clientRole" : true, - "containerId" : "62f2227e-e1ac-4c74-b278-1eab7f7664ae", - "attributes" : { } - }, { - "id" : "d08507c5-eb84-4d60-93f6-7c72f01536e7", - "name" : "query-users", - "description" : "${role_query-users}", - "composite" : false, - "clientRole" : true, - "containerId" : "62f2227e-e1ac-4c74-b278-1eab7f7664ae", - "attributes" : { } - }, { - "id" : "46d331cb-9fac-45af-b5ba-25bf003b9281", - "name" : "manage-clients", - "description" : "${role_manage-clients}", - "composite" : false, - "clientRole" : true, - "containerId" : "62f2227e-e1ac-4c74-b278-1eab7f7664ae", - "attributes" : { } - }, { - "id" : "77c0c84d-427b-4d73-a185-6bf3108ff9a2", - "name" : "view-identity-providers", - "description" : "${role_view-identity-providers}", - "composite" : false, - "clientRole" : true, - "containerId" : "62f2227e-e1ac-4c74-b278-1eab7f7664ae", - "attributes" : { } - }, { - "id" : "3a3f1c10-0d53-4a25-8bb8-46121f304af4", - "name" : "query-groups", - "description" : "${role_query-groups}", - "composite" : false, - "clientRole" : true, - "containerId" : "62f2227e-e1ac-4c74-b278-1eab7f7664ae", - "attributes" : { } - }, { - "id" : "12b4667f-1cb1-408d-bb8f-9905edea4fee", - "name" : "view-events", - "description" : "${role_view-events}", - "composite" : false, - "clientRole" : true, - "containerId" : "62f2227e-e1ac-4c74-b278-1eab7f7664ae", - "attributes" : { } - }, { - "id" : "99fcf818-a472-4ed1-8b23-d86a54156cf3", - "name" : "view-users", - "description" : "${role_view-users}", - "composite" : true, - "composites" : { - "client" : { - "aps-v2-realm" : [ "query-groups", "query-users" ] + { + "id": "0d22b102-52e1-4152-b119-2f6846e21b84", + "name": "api-owner", + "composite": false, + "clientRole": false, + "containerId": "master", + "attributes": {} + }, + { + "id": "064ef17c-0617-4cbc-b632-77a2fa0919b7", + "name": "admin", + "description": "${role_admin}", + "composite": true, + "composites": { + "realm": ["create-realm"], + "client": { + "aps-v2-realm": [ + "query-realms", + "create-client", + "manage-realm", + "manage-authorization", + "manage-events", + "impersonation", + "view-authorization", + "manage-identity-providers", + "query-users", + "manage-clients", + "view-identity-providers", + "query-groups", + "view-events", + "view-users", + "manage-users", + "view-clients", + "query-clients", + "view-realm" + ], + "master-realm": [ + "query-realms", + "manage-identity-providers", + "manage-authorization", + "manage-clients", + "impersonation", + "query-users", + "manage-events", + "manage-users", + "view-identity-providers", + "view-events", + "view-users", + "create-client", + "query-clients", + "query-groups", + "view-realm", + "view-clients", + "manage-realm", + "view-authorization" + ] } }, - "clientRole" : true, - "containerId" : "62f2227e-e1ac-4c74-b278-1eab7f7664ae", - "attributes" : { } - }, { - "id" : "e2bdd89b-1b4c-448e-b4a5-cc1196918e85", - "name" : "manage-users", - "description" : "${role_manage-users}", - "composite" : false, - "clientRole" : true, - "containerId" : "62f2227e-e1ac-4c74-b278-1eab7f7664ae", - "attributes" : { } - }, { - "id" : "8eecebf6-489f-4924-8afc-d40de58260a5", - "name" : "view-clients", - "description" : "${role_view-clients}", - "composite" : true, - "composites" : { - "client" : { - "aps-v2-realm" : [ "query-clients" ] - } + "clientRole": false, + "containerId": "master", + "attributes": {} + } + ], + "client": { + "aps-portal": [ + { + "id": "b393d043-9ade-4c64-a6e1-5f70c9a416e3", + "name": "api-owner", + "composite": false, + "clientRole": true, + "containerId": "f333c5e5-fba2-48e8-aab7-7b6862881202", + "attributes": {} }, - "clientRole" : true, - "containerId" : "62f2227e-e1ac-4c74-b278-1eab7f7664ae", - "attributes" : { } - }, { - "id" : "a93e05d2-ca5c-46e7-bd66-f98f915fdc30", - "name" : "query-clients", - "description" : "${role_query-clients}", - "composite" : false, - "clientRole" : true, - "containerId" : "62f2227e-e1ac-4c74-b278-1eab7f7664ae", - "attributes" : { } - }, { - "id" : "8016bdc5-4da8-4416-b6ef-fee7796cc8c2", - "name" : "manage-authorization", - "description" : "${role_manage-authorization}", - "composite" : false, - "clientRole" : true, - "containerId" : "62f2227e-e1ac-4c74-b278-1eab7f7664ae", - "attributes" : { } - }, { - "id" : "4c0f70bf-59c5-4878-a14a-eb658ea9ad4b", - "name" : "view-realm", - "description" : "${role_view-realm}", - "composite" : false, - "clientRole" : true, - "containerId" : "62f2227e-e1ac-4c74-b278-1eab7f7664ae", - "attributes" : { } - } ], - "sa-platform-e0000000-fa46551361b4" : [ ], - "security-admin-console" : [ ], - "sa-platform1-e0000000-5be82156d61f" : [ ], - "admin-cli" : [ ], - "account-console" : [ ], - "broker" : [ { - "id" : "8a00a2b3-fc3b-4b7d-aee1-1b3e46507b20", - "name" : "read-token", - "description" : "${role_read-token}", - "composite" : false, - "clientRole" : true, - "containerId" : "db7f58dc-c007-4e4c-ad7b-14f57a0521cd", - "attributes" : { } - } ], - "master-realm" : [ { - "id" : "a04656f4-d096-4cff-91f4-9b9f286c768d", - "name" : "query-realms", - "description" : "${role_query-realms}", - "composite" : false, - "clientRole" : true, - "containerId" : "4e6525e9-647c-4c80-85d6-9c13890b0ab2", - "attributes" : { } - }, { - "id" : "cccc1d8a-1a88-4a60-aff7-f7e5ec751f3f", - "name" : "view-identity-providers", - "description" : "${role_view-identity-providers}", - "composite" : false, - "clientRole" : true, - "containerId" : "4e6525e9-647c-4c80-85d6-9c13890b0ab2", - "attributes" : { } - }, { - "id" : "be5bcb8d-7466-402f-b289-6be26f961b0b", - "name" : "manage-identity-providers", - "description" : "${role_manage-identity-providers}", - "composite" : false, - "clientRole" : true, - "containerId" : "4e6525e9-647c-4c80-85d6-9c13890b0ab2", - "attributes" : { } - }, { - "id" : "e62d2ea1-fb57-41ae-ad8d-17ee8fb7356b", - "name" : "manage-authorization", - "description" : "${role_manage-authorization}", - "composite" : false, - "clientRole" : true, - "containerId" : "4e6525e9-647c-4c80-85d6-9c13890b0ab2", - "attributes" : { } - }, { - "id" : "f7247d9b-c35d-43dc-a10e-f1ce0cbc80fb", - "name" : "view-events", - "description" : "${role_view-events}", - "composite" : false, - "clientRole" : true, - "containerId" : "4e6525e9-647c-4c80-85d6-9c13890b0ab2", - "attributes" : { } - }, { - "id" : "be5fe2ea-0119-4eb4-a2c8-dae5eb3fd308", - "name" : "manage-clients", - "description" : "${role_manage-clients}", - "composite" : false, - "clientRole" : true, - "containerId" : "4e6525e9-647c-4c80-85d6-9c13890b0ab2", - "attributes" : { } - }, { - "id" : "3b1d6088-a992-4f81-b43b-5f71854ef3a4", - "name" : "view-users", - "description" : "${role_view-users}", - "composite" : true, - "composites" : { - "client" : { - "master-realm" : [ "query-users", "query-groups" ] - } + { + "id": "e0c6f7a0-3a8b-4572-9dac-82dd4b676b30", + "name": "credential-admin", + "composite": false, + "clientRole": true, + "containerId": "f333c5e5-fba2-48e8-aab7-7b6862881202", + "attributes": {} }, - "clientRole" : true, - "containerId" : "4e6525e9-647c-4c80-85d6-9c13890b0ab2", - "attributes" : { } - }, { - "id" : "d7cd3f01-b2e9-42b0-be8c-ef438932096c", - "name" : "impersonation", - "description" : "${role_impersonation}", - "composite" : false, - "clientRole" : true, - "containerId" : "4e6525e9-647c-4c80-85d6-9c13890b0ab2", - "attributes" : { } - }, { - "id" : "42fe78c7-3bb9-430d-a78d-013b95b31d0c", - "name" : "create-client", - "description" : "${role_create-client}", - "composite" : false, - "clientRole" : true, - "containerId" : "4e6525e9-647c-4c80-85d6-9c13890b0ab2", - "attributes" : { } - }, { - "id" : "c4c4b2b9-41a6-46c0-852e-5fb8ed755348", - "name" : "query-users", - "description" : "${role_query-users}", - "composite" : false, - "clientRole" : true, - "containerId" : "4e6525e9-647c-4c80-85d6-9c13890b0ab2", - "attributes" : { } - }, { - "id" : "c257a266-eba8-4469-8d9a-f171f489354c", - "name" : "query-clients", - "description" : "${role_query-clients}", - "composite" : false, - "clientRole" : true, - "containerId" : "4e6525e9-647c-4c80-85d6-9c13890b0ab2", - "attributes" : { } - }, { - "id" : "7e584743-ffe9-45e8-8f5b-722e07034141", - "name" : "query-groups", - "description" : "${role_query-groups}", - "composite" : false, - "clientRole" : true, - "containerId" : "4e6525e9-647c-4c80-85d6-9c13890b0ab2", - "attributes" : { } - }, { - "id" : "70aad632-dd34-46e8-813a-398914dd31c9", - "name" : "view-realm", - "description" : "${role_view-realm}", - "composite" : false, - "clientRole" : true, - "containerId" : "4e6525e9-647c-4c80-85d6-9c13890b0ab2", - "attributes" : { } - }, { - "id" : "6855b67a-f23d-40c9-a597-c98261e27ce4", - "name" : "view-clients", - "description" : "${role_view-clients}", - "composite" : true, - "composites" : { - "client" : { - "master-realm" : [ "query-clients" ] - } + { + "id": "3c0fcf9e-e622-497d-8146-eddd0304f9c8", + "name": "aps-admin", + "composite": false, + "clientRole": true, + "containerId": "f333c5e5-fba2-48e8-aab7-7b6862881202", + "attributes": {} }, - "clientRole" : true, - "containerId" : "4e6525e9-647c-4c80-85d6-9c13890b0ab2", - "attributes" : { } - }, { - "id" : "0725918a-6335-4556-aafa-ff6c3fb87989", - "name" : "manage-realm", - "description" : "${role_manage-realm}", - "composite" : false, - "clientRole" : true, - "containerId" : "4e6525e9-647c-4c80-85d6-9c13890b0ab2", - "attributes" : { } - }, { - "id" : "0d2640b7-461c-4c21-8270-064f5423ae74", - "name" : "manage-events", - "description" : "${role_manage-events}", - "composite" : false, - "clientRole" : true, - "containerId" : "4e6525e9-647c-4c80-85d6-9c13890b0ab2", - "attributes" : { } - }, { - "id" : "ba7e040b-9462-489a-9467-965f69ae1025", - "name" : "manage-users", - "description" : "${role_manage-users}", - "composite" : false, - "clientRole" : true, - "containerId" : "4e6525e9-647c-4c80-85d6-9c13890b0ab2", - "attributes" : { } - }, { - "id" : "b473aa2e-d49d-4ba5-b502-8d38db9dc81e", - "name" : "view-authorization", - "description" : "${role_view-authorization}", - "composite" : false, - "clientRole" : true, - "containerId" : "4e6525e9-647c-4c80-85d6-9c13890b0ab2", - "attributes" : { } - } ], - "account" : [ { - "id" : "dba0e0ba-f826-49df-a378-031e5fbcfd13", - "name" : "view-applications", - "description" : "${role_view-applications}", - "composite" : false, - "clientRole" : true, - "containerId" : "bc61d6b7-6876-4193-9881-1b994596a207", - "attributes" : { } - }, { - "id" : "5d9f0b2a-55bb-4cda-ab2d-67b77cf925f0", - "name" : "view-consent", - "description" : "${role_view-consent}", - "composite" : false, - "clientRole" : true, - "containerId" : "bc61d6b7-6876-4193-9881-1b994596a207", - "attributes" : { } - }, { - "id" : "f58a3fc3-9fbd-4308-8528-cee3d267fc74", - "name" : "manage-account", - "description" : "${role_manage-account}", - "composite" : true, - "composites" : { - "client" : { - "account" : [ "manage-account-links" ] - } + { + "id": "9a357bd3-2c73-40ea-ac09-399a9f7cc9f8", + "name": "api-manager", + "composite": false, + "clientRole": true, + "containerId": "f333c5e5-fba2-48e8-aab7-7b6862881202", + "attributes": {} }, - "clientRole" : true, - "containerId" : "bc61d6b7-6876-4193-9881-1b994596a207", - "attributes" : { } - }, { - "id" : "b84c29be-1b56-4b8e-be2c-1b5153d8b1aa", - "name" : "view-profile", - "description" : "${role_view-profile}", - "composite" : false, - "clientRole" : true, - "containerId" : "bc61d6b7-6876-4193-9881-1b994596a207", - "attributes" : { } - }, { - "id" : "baccbb7e-8777-4ff5-9d1a-491b61f6d87f", - "name" : "manage-consent", - "description" : "${role_manage-consent}", - "composite" : true, - "composites" : { - "client" : { - "account" : [ "view-consent" ] - } + { + "id": "2c0e0832-4a1e-411b-a8f9-8f86096c3968", + "name": "developer", + "composite": false, + "clientRole": true, + "containerId": "f333c5e5-fba2-48e8-aab7-7b6862881202", + "attributes": {} + } + ], + "gwa-api": [ + { + "id": "a50b2fc6-ea49-46d8-9716-683f3a764f5d", + "name": "developer", + "composite": false, + "clientRole": true, + "containerId": "c002b2b1-0ca8-4fd6-896e-6d2e3395a345", + "attributes": {} + }, + { + "id": "0c1c2230-24d4-4199-af35-bed6a1044c70", + "name": "api-admin", + "composite": false, + "clientRole": true, + "containerId": "c002b2b1-0ca8-4fd6-896e-6d2e3395a345", + "attributes": {} + }, + { + "id": "409fcd4e-54ab-4e19-bdc5-ef8059721e22", + "name": "uma_protection", + "composite": false, + "clientRole": true, + "containerId": "c002b2b1-0ca8-4fd6-896e-6d2e3395a345", + "attributes": {} + }, + { + "id": "8d387de9-3d53-4a69-9cb4-d5d285926029", + "name": "api-owner", + "composite": false, + "clientRole": true, + "containerId": "c002b2b1-0ca8-4fd6-896e-6d2e3395a345", + "attributes": {} + } + ], + "aps-v2-realm": [ + { + "id": "a7ff1dc9-1214-4757-861b-453b204e460f", + "name": "manage-events", + "description": "${role_manage-events}", + "composite": false, + "clientRole": true, + "containerId": "62f2227e-e1ac-4c74-b278-1eab7f7664ae", + "attributes": {} + }, + { + "id": "faf54935-32bc-4e01-b0e6-8b9bb1cae6e8", + "name": "query-realms", + "description": "${role_query-realms}", + "composite": false, + "clientRole": true, + "containerId": "62f2227e-e1ac-4c74-b278-1eab7f7664ae", + "attributes": {} + }, + { + "id": "2272fc44-5c1d-465d-9608-6b4612e26755", + "name": "impersonation", + "description": "${role_impersonation}", + "composite": false, + "clientRole": true, + "containerId": "62f2227e-e1ac-4c74-b278-1eab7f7664ae", + "attributes": {} + }, + { + "id": "fecb856f-8db8-4432-9f11-6b3426372a9c", + "name": "create-client", + "description": "${role_create-client}", + "composite": false, + "clientRole": true, + "containerId": "62f2227e-e1ac-4c74-b278-1eab7f7664ae", + "attributes": {} + }, + { + "id": "dd8c065c-fcd9-4f58-8dad-ec6100cbcbdf", + "name": "view-authorization", + "description": "${role_view-authorization}", + "composite": false, + "clientRole": true, + "containerId": "62f2227e-e1ac-4c74-b278-1eab7f7664ae", + "attributes": {} + }, + { + "id": "ec6f0230-82ae-4713-8d21-fc97214042d9", + "name": "manage-identity-providers", + "description": "${role_manage-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "62f2227e-e1ac-4c74-b278-1eab7f7664ae", + "attributes": {} + }, + { + "id": "f33e3aa2-0b3e-4397-9968-82be07d68f40", + "name": "manage-realm", + "description": "${role_manage-realm}", + "composite": false, + "clientRole": true, + "containerId": "62f2227e-e1ac-4c74-b278-1eab7f7664ae", + "attributes": {} + }, + { + "id": "d08507c5-eb84-4d60-93f6-7c72f01536e7", + "name": "query-users", + "description": "${role_query-users}", + "composite": false, + "clientRole": true, + "containerId": "62f2227e-e1ac-4c74-b278-1eab7f7664ae", + "attributes": {} + }, + { + "id": "46d331cb-9fac-45af-b5ba-25bf003b9281", + "name": "manage-clients", + "description": "${role_manage-clients}", + "composite": false, + "clientRole": true, + "containerId": "62f2227e-e1ac-4c74-b278-1eab7f7664ae", + "attributes": {} + }, + { + "id": "77c0c84d-427b-4d73-a185-6bf3108ff9a2", + "name": "view-identity-providers", + "description": "${role_view-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "62f2227e-e1ac-4c74-b278-1eab7f7664ae", + "attributes": {} + }, + { + "id": "3a3f1c10-0d53-4a25-8bb8-46121f304af4", + "name": "query-groups", + "description": "${role_query-groups}", + "composite": false, + "clientRole": true, + "containerId": "62f2227e-e1ac-4c74-b278-1eab7f7664ae", + "attributes": {} + }, + { + "id": "12b4667f-1cb1-408d-bb8f-9905edea4fee", + "name": "view-events", + "description": "${role_view-events}", + "composite": false, + "clientRole": true, + "containerId": "62f2227e-e1ac-4c74-b278-1eab7f7664ae", + "attributes": {} + }, + { + "id": "99fcf818-a472-4ed1-8b23-d86a54156cf3", + "name": "view-users", + "description": "${role_view-users}", + "composite": true, + "composites": { + "client": { + "aps-v2-realm": ["query-groups", "query-users"] + } + }, + "clientRole": true, + "containerId": "62f2227e-e1ac-4c74-b278-1eab7f7664ae", + "attributes": {} + }, + { + "id": "e2bdd89b-1b4c-448e-b4a5-cc1196918e85", + "name": "manage-users", + "description": "${role_manage-users}", + "composite": false, + "clientRole": true, + "containerId": "62f2227e-e1ac-4c74-b278-1eab7f7664ae", + "attributes": {} + }, + { + "id": "8eecebf6-489f-4924-8afc-d40de58260a5", + "name": "view-clients", + "description": "${role_view-clients}", + "composite": true, + "composites": { + "client": { + "aps-v2-realm": ["query-clients"] + } + }, + "clientRole": true, + "containerId": "62f2227e-e1ac-4c74-b278-1eab7f7664ae", + "attributes": {} + }, + { + "id": "a93e05d2-ca5c-46e7-bd66-f98f915fdc30", + "name": "query-clients", + "description": "${role_query-clients}", + "composite": false, + "clientRole": true, + "containerId": "62f2227e-e1ac-4c74-b278-1eab7f7664ae", + "attributes": {} + }, + { + "id": "8016bdc5-4da8-4416-b6ef-fee7796cc8c2", + "name": "manage-authorization", + "description": "${role_manage-authorization}", + "composite": false, + "clientRole": true, + "containerId": "62f2227e-e1ac-4c74-b278-1eab7f7664ae", + "attributes": {} + }, + { + "id": "4c0f70bf-59c5-4878-a14a-eb658ea9ad4b", + "name": "view-realm", + "description": "${role_view-realm}", + "composite": false, + "clientRole": true, + "containerId": "62f2227e-e1ac-4c74-b278-1eab7f7664ae", + "attributes": {} + } + ], + "sa-platform-e0000000-fa46551361b4": [], + "security-admin-console": [], + "sa-platform1-e0000000-5be82156d61f": [], + "admin-cli": [], + "account-console": [], + "broker": [ + { + "id": "8a00a2b3-fc3b-4b7d-aee1-1b3e46507b20", + "name": "read-token", + "description": "${role_read-token}", + "composite": false, + "clientRole": true, + "containerId": "db7f58dc-c007-4e4c-ad7b-14f57a0521cd", + "attributes": {} + } + ], + "master-realm": [ + { + "id": "a04656f4-d096-4cff-91f4-9b9f286c768d", + "name": "query-realms", + "description": "${role_query-realms}", + "composite": false, + "clientRole": true, + "containerId": "4e6525e9-647c-4c80-85d6-9c13890b0ab2", + "attributes": {} + }, + { + "id": "cccc1d8a-1a88-4a60-aff7-f7e5ec751f3f", + "name": "view-identity-providers", + "description": "${role_view-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "4e6525e9-647c-4c80-85d6-9c13890b0ab2", + "attributes": {} + }, + { + "id": "be5bcb8d-7466-402f-b289-6be26f961b0b", + "name": "manage-identity-providers", + "description": "${role_manage-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "4e6525e9-647c-4c80-85d6-9c13890b0ab2", + "attributes": {} + }, + { + "id": "e62d2ea1-fb57-41ae-ad8d-17ee8fb7356b", + "name": "manage-authorization", + "description": "${role_manage-authorization}", + "composite": false, + "clientRole": true, + "containerId": "4e6525e9-647c-4c80-85d6-9c13890b0ab2", + "attributes": {} + }, + { + "id": "f7247d9b-c35d-43dc-a10e-f1ce0cbc80fb", + "name": "view-events", + "description": "${role_view-events}", + "composite": false, + "clientRole": true, + "containerId": "4e6525e9-647c-4c80-85d6-9c13890b0ab2", + "attributes": {} + }, + { + "id": "be5fe2ea-0119-4eb4-a2c8-dae5eb3fd308", + "name": "manage-clients", + "description": "${role_manage-clients}", + "composite": false, + "clientRole": true, + "containerId": "4e6525e9-647c-4c80-85d6-9c13890b0ab2", + "attributes": {} }, - "clientRole" : true, - "containerId" : "bc61d6b7-6876-4193-9881-1b994596a207", - "attributes" : { } - }, { - "id" : "a1e4af9d-431f-4e0f-87c1-d6c24f0a61e0", - "name" : "manage-account-links", - "description" : "${role_manage-account-links}", - "composite" : false, - "clientRole" : true, - "containerId" : "bc61d6b7-6876-4193-9881-1b994596a207", - "attributes" : { } - } ], - "cypress-auth-profile" : [ { - "id" : "7e5fbfc1-4818-4736-9a47-21d35b3304c2", - "name" : "uma_protection", - "composite" : false, - "clientRole" : true, - "containerId" : "50c78923-95d9-4083-87ff-5233f2d6326e", - "attributes" : { } - } ] + { + "id": "3b1d6088-a992-4f81-b43b-5f71854ef3a4", + "name": "view-users", + "description": "${role_view-users}", + "composite": true, + "composites": { + "client": { + "master-realm": ["query-users", "query-groups"] + } + }, + "clientRole": true, + "containerId": "4e6525e9-647c-4c80-85d6-9c13890b0ab2", + "attributes": {} + }, + { + "id": "d7cd3f01-b2e9-42b0-be8c-ef438932096c", + "name": "impersonation", + "description": "${role_impersonation}", + "composite": false, + "clientRole": true, + "containerId": "4e6525e9-647c-4c80-85d6-9c13890b0ab2", + "attributes": {} + }, + { + "id": "42fe78c7-3bb9-430d-a78d-013b95b31d0c", + "name": "create-client", + "description": "${role_create-client}", + "composite": false, + "clientRole": true, + "containerId": "4e6525e9-647c-4c80-85d6-9c13890b0ab2", + "attributes": {} + }, + { + "id": "c4c4b2b9-41a6-46c0-852e-5fb8ed755348", + "name": "query-users", + "description": "${role_query-users}", + "composite": false, + "clientRole": true, + "containerId": "4e6525e9-647c-4c80-85d6-9c13890b0ab2", + "attributes": {} + }, + { + "id": "c257a266-eba8-4469-8d9a-f171f489354c", + "name": "query-clients", + "description": "${role_query-clients}", + "composite": false, + "clientRole": true, + "containerId": "4e6525e9-647c-4c80-85d6-9c13890b0ab2", + "attributes": {} + }, + { + "id": "7e584743-ffe9-45e8-8f5b-722e07034141", + "name": "query-groups", + "description": "${role_query-groups}", + "composite": false, + "clientRole": true, + "containerId": "4e6525e9-647c-4c80-85d6-9c13890b0ab2", + "attributes": {} + }, + { + "id": "70aad632-dd34-46e8-813a-398914dd31c9", + "name": "view-realm", + "description": "${role_view-realm}", + "composite": false, + "clientRole": true, + "containerId": "4e6525e9-647c-4c80-85d6-9c13890b0ab2", + "attributes": {} + }, + { + "id": "6855b67a-f23d-40c9-a597-c98261e27ce4", + "name": "view-clients", + "description": "${role_view-clients}", + "composite": true, + "composites": { + "client": { + "master-realm": ["query-clients"] + } + }, + "clientRole": true, + "containerId": "4e6525e9-647c-4c80-85d6-9c13890b0ab2", + "attributes": {} + }, + { + "id": "0725918a-6335-4556-aafa-ff6c3fb87989", + "name": "manage-realm", + "description": "${role_manage-realm}", + "composite": false, + "clientRole": true, + "containerId": "4e6525e9-647c-4c80-85d6-9c13890b0ab2", + "attributes": {} + }, + { + "id": "0d2640b7-461c-4c21-8270-064f5423ae74", + "name": "manage-events", + "description": "${role_manage-events}", + "composite": false, + "clientRole": true, + "containerId": "4e6525e9-647c-4c80-85d6-9c13890b0ab2", + "attributes": {} + }, + { + "id": "ba7e040b-9462-489a-9467-965f69ae1025", + "name": "manage-users", + "description": "${role_manage-users}", + "composite": false, + "clientRole": true, + "containerId": "4e6525e9-647c-4c80-85d6-9c13890b0ab2", + "attributes": {} + }, + { + "id": "b473aa2e-d49d-4ba5-b502-8d38db9dc81e", + "name": "view-authorization", + "description": "${role_view-authorization}", + "composite": false, + "clientRole": true, + "containerId": "4e6525e9-647c-4c80-85d6-9c13890b0ab2", + "attributes": {} + } + ], + "account": [ + { + "id": "dba0e0ba-f826-49df-a378-031e5fbcfd13", + "name": "view-applications", + "description": "${role_view-applications}", + "composite": false, + "clientRole": true, + "containerId": "bc61d6b7-6876-4193-9881-1b994596a207", + "attributes": {} + }, + { + "id": "5d9f0b2a-55bb-4cda-ab2d-67b77cf925f0", + "name": "view-consent", + "description": "${role_view-consent}", + "composite": false, + "clientRole": true, + "containerId": "bc61d6b7-6876-4193-9881-1b994596a207", + "attributes": {} + }, + { + "id": "f58a3fc3-9fbd-4308-8528-cee3d267fc74", + "name": "manage-account", + "description": "${role_manage-account}", + "composite": true, + "composites": { + "client": { + "account": ["manage-account-links"] + } + }, + "clientRole": true, + "containerId": "bc61d6b7-6876-4193-9881-1b994596a207", + "attributes": {} + }, + { + "id": "b84c29be-1b56-4b8e-be2c-1b5153d8b1aa", + "name": "view-profile", + "description": "${role_view-profile}", + "composite": false, + "clientRole": true, + "containerId": "bc61d6b7-6876-4193-9881-1b994596a207", + "attributes": {} + }, + { + "id": "baccbb7e-8777-4ff5-9d1a-491b61f6d87f", + "name": "manage-consent", + "description": "${role_manage-consent}", + "composite": true, + "composites": { + "client": { + "account": ["view-consent"] + } + }, + "clientRole": true, + "containerId": "bc61d6b7-6876-4193-9881-1b994596a207", + "attributes": {} + }, + { + "id": "a1e4af9d-431f-4e0f-87c1-d6c24f0a61e0", + "name": "manage-account-links", + "description": "${role_manage-account-links}", + "composite": false, + "clientRole": true, + "containerId": "bc61d6b7-6876-4193-9881-1b994596a207", + "attributes": {} + } + ], + "cypress-auth-profile": [ + { + "id": "7e5fbfc1-4818-4736-9a47-21d35b3304c2", + "name": "uma_protection", + "composite": false, + "clientRole": true, + "containerId": "50c78923-95d9-4083-87ff-5233f2d6326e", + "attributes": {} + } + ] } }, - "groups" : [ { - "id" : "b0944059-43fc-4dbc-9037-d25e01ae6c45", - "name" : "ns", - "path" : "/ns", - "attributes" : { }, - "realmRoles" : [ ], - "clientRoles" : { }, - "subGroups" : [ { - "id" : "5c875007-2e0e-4c01-8418-143e2a420722", - "name" : "platform", - "path" : "/ns/platform", - "attributes" : { - "org-unit" : [ "planning-and-innovation-division" ], - "org" : [ "ministry-of-health" ] + "groups": [ + { + "id": "b0944059-43fc-4dbc-9037-d25e01ae6c45", + "name": "ns", + "path": "/ns", + "attributes": {}, + "realmRoles": [], + "clientRoles": {}, + "subGroups": [ + { + "id": "5c875007-2e0e-4c01-8418-143e2a420722", + "name": "platform", + "path": "/ns/platform", + "attributes": { + "org-unit": ["planning-and-innovation-division"], + "org": ["ministry-of-health"] + }, + "realmRoles": [], + "clientRoles": {}, + "subGroups": [] + } + ] + }, + { + "id": "6a0b857d-3951-444d-823e-193bf9f12f67", + "name": "organization-admin", + "path": "/organization-admin", + "attributes": {}, + "realmRoles": [], + "clientRoles": {}, + "subGroups": [ + { + "id": "17434902-eda6-4d6a-a366-2dbfdbf3866c", + "name": "ca.bc.gov", + "path": "/organization-admin/ca.bc.gov", + "attributes": {}, + "realmRoles": [], + "clientRoles": {}, + "subGroups": [ + { + "id": "711b0078-fb8c-4ce9-aa50-06a690360508", + "name": "ministry-of-health", + "path": "/organization-admin/ca.bc.gov/ministry-of-health", + "attributes": {}, + "realmRoles": [], + "clientRoles": {}, + "subGroups": [ + { + "id": "614278c5-b60c-4101-9986-3d031720dec0", + "name": "planning-and-innovation-division", + "path": "/organization-admin/ca.bc.gov/ministry-of-health/planning-and-innovation-division", + "attributes": {}, + "realmRoles": [], + "clientRoles": {}, + "subGroups": [] + } + ] + } + ] + } + ] + } + ], + "defaultRoles": ["uma_authorization", "offline_access"], + "requiredCredentials": ["password"], + "otpPolicyType": "totp", + "otpPolicyAlgorithm": "HmacSHA1", + "otpPolicyInitialCounter": 0, + "otpPolicyDigits": 6, + "otpPolicyLookAheadWindow": 1, + "otpPolicyPeriod": 30, + "otpSupportedApplications": ["FreeOTP", "Google Authenticator"], + "webAuthnPolicyRpEntityName": "keycloak", + "webAuthnPolicySignatureAlgorithms": ["ES256"], + "webAuthnPolicyRpId": "", + "webAuthnPolicyAttestationConveyancePreference": "not specified", + "webAuthnPolicyAuthenticatorAttachment": "not specified", + "webAuthnPolicyRequireResidentKey": "not specified", + "webAuthnPolicyUserVerificationRequirement": "not specified", + "webAuthnPolicyCreateTimeout": 0, + "webAuthnPolicyAvoidSameAuthenticatorRegister": false, + "webAuthnPolicyAcceptableAaguids": [], + "webAuthnPolicyPasswordlessRpEntityName": "keycloak", + "webAuthnPolicyPasswordlessSignatureAlgorithms": ["ES256"], + "webAuthnPolicyPasswordlessRpId": "", + "webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified", + "webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified", + "webAuthnPolicyPasswordlessRequireResidentKey": "not specified", + "webAuthnPolicyPasswordlessUserVerificationRequirement": "not specified", + "webAuthnPolicyPasswordlessCreateTimeout": 0, + "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false, + "webAuthnPolicyPasswordlessAcceptableAaguids": [], + "users": [ + { + "id": "03ff1b38-197b-465f-854a-b64f56b13356", + "createdTimestamp": 1625085370528, + "username": "awsummer@idir", + "enabled": true, + "totp": false, + "emailVerified": false, + "firstName": "Awesome", + "lastName": "Summers", + "email": "awsummers@gmail.com", + "credentials": [ + { + "id": "fa2ee157-09ea-466e-b9f6-378fd6f4dcdc", + "type": "password", + "createdDate": 1625085504863, + "secretData": "{\"value\":\"Fg8F1kRC03xAi3dyLPoH7K0TDGGfN9FKkcG6gGobAkyZtqtfShgjhGB1DSBZdXXirK27lHHYv+ZTqpAf87uhuA==\",\"salt\":\"TD5LnQBeAReu7LfJ2bnWMQ==\"}", + "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\"}" + } + ], + "disableableCredentialTypes": [], + "requiredActions": [], + "realmRoles": ["uma_authorization", "offline_access", "api-owner"], + "clientRoles": { + "account": ["manage-account", "view-profile"] }, - "realmRoles" : [ ], - "clientRoles" : { }, - "subGroups" : [ ] - } ] - }, { - "id" : "6a0b857d-3951-444d-823e-193bf9f12f67", - "name" : "organization-admin", - "path" : "/organization-admin", - "attributes" : { }, - "realmRoles" : [ ], - "clientRoles" : { }, - "subGroups" : [ { - "id" : "17434902-eda6-4d6a-a366-2dbfdbf3866c", - "name" : "ca.bc.gov", - "path" : "/organization-admin/ca.bc.gov", - "attributes" : { }, - "realmRoles" : [ ], - "clientRoles" : { }, - "subGroups" : [ { - "id" : "711b0078-fb8c-4ce9-aa50-06a690360508", - "name" : "ministry-of-health", - "path" : "/organization-admin/ca.bc.gov/ministry-of-health", - "attributes" : { }, - "realmRoles" : [ ], - "clientRoles" : { }, - "subGroups" : [ { - "id" : "614278c5-b60c-4101-9986-3d031720dec0", - "name" : "planning-and-innovation-division", - "path" : "/organization-admin/ca.bc.gov/ministry-of-health/planning-and-innovation-division", - "attributes" : { }, - "realmRoles" : [ ], - "clientRoles" : { }, - "subGroups" : [ ] - } ] - } ] - } ] - } ], - "defaultRoles" : [ "uma_authorization", "offline_access" ], - "requiredCredentials" : [ "password" ], - "otpPolicyType" : "totp", - "otpPolicyAlgorithm" : "HmacSHA1", - "otpPolicyInitialCounter" : 0, - "otpPolicyDigits" : 6, - "otpPolicyLookAheadWindow" : 1, - "otpPolicyPeriod" : 30, - "otpSupportedApplications" : [ "FreeOTP", "Google Authenticator" ], - "webAuthnPolicyRpEntityName" : "keycloak", - "webAuthnPolicySignatureAlgorithms" : [ "ES256" ], - "webAuthnPolicyRpId" : "", - "webAuthnPolicyAttestationConveyancePreference" : "not specified", - "webAuthnPolicyAuthenticatorAttachment" : "not specified", - "webAuthnPolicyRequireResidentKey" : "not specified", - "webAuthnPolicyUserVerificationRequirement" : "not specified", - "webAuthnPolicyCreateTimeout" : 0, - "webAuthnPolicyAvoidSameAuthenticatorRegister" : false, - "webAuthnPolicyAcceptableAaguids" : [ ], - "webAuthnPolicyPasswordlessRpEntityName" : "keycloak", - "webAuthnPolicyPasswordlessSignatureAlgorithms" : [ "ES256" ], - "webAuthnPolicyPasswordlessRpId" : "", - "webAuthnPolicyPasswordlessAttestationConveyancePreference" : "not specified", - "webAuthnPolicyPasswordlessAuthenticatorAttachment" : "not specified", - "webAuthnPolicyPasswordlessRequireResidentKey" : "not specified", - "webAuthnPolicyPasswordlessUserVerificationRequirement" : "not specified", - "webAuthnPolicyPasswordlessCreateTimeout" : 0, - "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister" : false, - "webAuthnPolicyPasswordlessAcceptableAaguids" : [ ], - "users" : [ { - "id" : "03ff1b38-197b-465f-854a-b64f56b13356", - "createdTimestamp" : 1625085370528, - "username" : "awsummer@idir", - "enabled" : true, - "totp" : false, - "emailVerified" : false, - "firstName" : "Awesome", - "lastName" : "Summers", - "email" : "awsummers@gmail.com", - "credentials" : [ { - "id" : "fa2ee157-09ea-466e-b9f6-378fd6f4dcdc", - "type" : "password", - "createdDate" : 1625085504863, - "secretData" : "{\"value\":\"Fg8F1kRC03xAi3dyLPoH7K0TDGGfN9FKkcG6gGobAkyZtqtfShgjhGB1DSBZdXXirK27lHHYv+ZTqpAf87uhuA==\",\"salt\":\"TD5LnQBeAReu7LfJ2bnWMQ==\"}", - "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\"}" - } ], - "disableableCredentialTypes" : [ ], - "requiredActions" : [ ], - "realmRoles" : [ "uma_authorization", "offline_access", "api-owner" ], - "clientRoles" : { - "account" : [ "manage-account", "view-profile" ] + "notBefore": 0, + "groups": [] }, - "notBefore" : 0, - "groups" : [ ] - }, { - "id" : "f6296cb0-a7c4-45fc-88ff-c1da793ff981", - "createdTimestamp" : 1642463544967, - "username" : "harley", - "enabled" : true, - "totp" : false, - "emailVerified" : false, - "firstName" : "Harley", - "lastName" : "Jones", - "email" : "harley@test.com", - "credentials" : [ { - "id" : "0cc94c77-49c1-4e9c-b224-66dc661c06b5", - "type" : "password", - "createdDate" : 1642466431391, - "secretData" : "{\"value\":\"AxeI0+khXUu1TqFB+I89x9KSQCBo2KZLGPyYXvLSkQlu/lMSfw7QEp0S3+i364FuzHYRCwAC2GVCjrAiOiyHVg==\",\"salt\":\"GJZIGYazPq+sEMRAO2AtRA==\"}", - "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\"}" - } ], - "disableableCredentialTypes" : [ ], - "requiredActions" : [ ], - "realmRoles" : [ "uma_authorization", "offline_access" ], - "clientRoles" : { - "account" : [ "manage-account", "view-profile" ] + { + "id": "f6296cb0-a7c4-45fc-88ff-c1da793ff981", + "createdTimestamp": 1642463544967, + "username": "harley", + "enabled": true, + "totp": false, + "emailVerified": false, + "firstName": "Harley", + "lastName": "Jones", + "email": "harley@test.com", + "credentials": [ + { + "id": "0cc94c77-49c1-4e9c-b224-66dc661c06b5", + "type": "password", + "createdDate": 1642466431391, + "secretData": "{\"value\":\"AxeI0+khXUu1TqFB+I89x9KSQCBo2KZLGPyYXvLSkQlu/lMSfw7QEp0S3+i364FuzHYRCwAC2GVCjrAiOiyHVg==\",\"salt\":\"GJZIGYazPq+sEMRAO2AtRA==\"}", + "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\"}" + } + ], + "disableableCredentialTypes": [], + "requiredActions": [], + "realmRoles": ["uma_authorization", "offline_access"], + "clientRoles": { + "account": ["manage-account", "view-profile"] + }, + "notBefore": 0, + "groups": [] }, - "notBefore" : 0, - "groups" : [ ] - }, { - "id" : "bf498a7b-b6e0-49bb-9ea8-0241d7792fe2", - "createdTimestamp" : 1642463435902, - "username" : "janis@idir", - "enabled" : true, - "totp" : false, - "emailVerified" : false, - "firstName" : "Janis", - "lastName" : "Smith", - "email" : "janis@testmail.com", - "attributes" : { - "provider_user_guid" : [ "220469E037C84A7ABDFAB15204A607C5" ], - "identity_provider" : [ "idir" ], - "display_name" : [ "Janis@idir" ], - "provider_username" : [ "janis" ] + { + "id": "bf498a7b-b6e0-49bb-9ea8-0241d7792fe2", + "createdTimestamp": 1642463435902, + "username": "janis@idir", + "enabled": true, + "totp": false, + "emailVerified": false, + "firstName": "Janis", + "lastName": "Smith", + "email": "janis@testmail.com", + "attributes": { + "provider_user_guid": ["220469E037C84A7ABDFAB15204A607C5"], + "identity_provider": ["idir"], + "display_name": ["Janis@idir"], + "provider_username": ["janis"] + }, + "credentials": [ + { + "id": "6aa0a7ca-c2ad-43f5-9bdb-3f58693b28bc", + "type": "password", + "createdDate": 1642466403247, + "secretData": "{\"value\":\"ltS/DMUYOCSmZZRbf7rYFTpLa9cqQDewFO1jwRPczU99leiyGtOCsbdAPRmSvLVhOLnzqvcaua3B17ej2d6/7w==\",\"salt\":\"ZrR/QMSRwruFRU5FsPUgHQ==\"}", + "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\"}" + } + ], + "disableableCredentialTypes": [], + "requiredActions": [], + "realmRoles": [ + "uma_authorization", + "aps-admin", + "offline_access", + "api-owner" + ], + "clientRoles": { + "account": ["manage-account", "view-profile"] + }, + "notBefore": 0, + "groups": [] }, - "credentials" : [ { - "id" : "6aa0a7ca-c2ad-43f5-9bdb-3f58693b28bc", - "type" : "password", - "createdDate" : 1642466403247, - "secretData" : "{\"value\":\"ltS/DMUYOCSmZZRbf7rYFTpLa9cqQDewFO1jwRPczU99leiyGtOCsbdAPRmSvLVhOLnzqvcaua3B17ej2d6/7w==\",\"salt\":\"ZrR/QMSRwruFRU5FsPUgHQ==\"}", - "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\"}" - } ], - "disableableCredentialTypes" : [ ], - "requiredActions" : [ ], - "realmRoles" : [ "uma_authorization", "aps-admin", "offline_access", "api-owner" ], - "clientRoles" : { - "account" : [ "manage-account", "view-profile" ] + { + "id": "7f9dcdfc-6100-4ec8-ba3f-8bd26d184585", + "createdTimestamp": 1623537499547, + "username": "local", + "enabled": true, + "totp": false, + "emailVerified": false, + "firstName": "local F", + "lastName": "local L", + "email": "local@development.me", + "credentials": [ + { + "id": "4ea10252-fd5d-476c-9e75-896230209ba5", + "type": "password", + "createdDate": 1623537499592, + "secretData": "{\"value\":\"BuAJdiavdBRkL23vKkpx9Ua1jKeLagEd/AkExhMM5Npt5l9Q3HO3Z/Ksxen+TBGh0JZDMxpfHArCp7xaAaUThw==\",\"salt\":\"ASKUBGyIEAcGPJaCnkpk+A==\"}", + "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\"}" + } + ], + "disableableCredentialTypes": [], + "requiredActions": [], + "realmRoles": [ + "uma_authorization", + "offline_access", + "api-owner", + "admin" + ], + "clientRoles": { + "account": ["manage-account", "view-profile"] + }, + "notBefore": 0, + "groups": [] }, - "notBefore" : 0, - "groups" : [ ] - }, { - "id" : "7f9dcdfc-6100-4ec8-ba3f-8bd26d184585", - "createdTimestamp" : 1623537499547, - "username" : "local", - "enabled" : true, - "totp" : false, - "emailVerified" : false, - "firstName" : "local F", - "lastName" : "local L", - "email" : "local@development.me", - "credentials" : [ { - "id" : "4ea10252-fd5d-476c-9e75-896230209ba5", - "type" : "password", - "createdDate" : 1623537499592, - "secretData" : "{\"value\":\"BuAJdiavdBRkL23vKkpx9Ua1jKeLagEd/AkExhMM5Npt5l9Q3HO3Z/Ksxen+TBGh0JZDMxpfHArCp7xaAaUThw==\",\"salt\":\"ASKUBGyIEAcGPJaCnkpk+A==\"}", - "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\"}" - } ], - "disableableCredentialTypes" : [ ], - "requiredActions" : [ ], - "realmRoles" : [ "uma_authorization", "offline_access", "api-owner", "admin" ], - "clientRoles" : { - "account" : [ "manage-account", "view-profile" ] + { + "id": "0cb6367d-605d-44ef-a15a-a180e5773bc2", + "createdTimestamp": 1638573942042, + "username": "mark", + "enabled": true, + "totp": false, + "emailVerified": false, + "firstName": "Mark F", + "lastName": "Mark L", + "email": "mark@gmail.com", + "credentials": [ + { + "id": "51f9551c-700c-48a4-a8c9-741089fc8123", + "type": "password", + "createdDate": 1638573942161, + "secretData": "{\"value\":\"I1XjV+HZkoHcNhSOHbICpyAlzyGyeqp/kPuIMvjcRP8oCD5x1FimGeZ8PISATtgcAq+QaSz3jx/ntodr3LbxOw==\",\"salt\":\"1Exw3iFjhc8E6DprXFm26w==\"}", + "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\"}" + } + ], + "disableableCredentialTypes": [], + "requiredActions": [], + "realmRoles": [ + "uma_authorization", + "offline_access", + "api-manager", + "admin" + ], + "clientRoles": { + "account": ["manage-account", "view-profile"] + }, + "notBefore": 0, + "groups": [] }, - "notBefore" : 0, - "groups" : [ ] - }, { - "id" : "0cb6367d-605d-44ef-a15a-a180e5773bc2", - "createdTimestamp" : 1638573942042, - "username" : "mark", - "enabled" : true, - "totp" : false, - "emailVerified" : false, - "firstName" : "Mark F", - "lastName" : "Mark L", - "email" : "mark@gmail.com", - "credentials" : [ { - "id" : "51f9551c-700c-48a4-a8c9-741089fc8123", - "type" : "password", - "createdDate" : 1638573942161, - "secretData" : "{\"value\":\"I1XjV+HZkoHcNhSOHbICpyAlzyGyeqp/kPuIMvjcRP8oCD5x1FimGeZ8PISATtgcAq+QaSz3jx/ntodr3LbxOw==\",\"salt\":\"1Exw3iFjhc8E6DprXFm26w==\"}", - "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\"}" - } ], - "disableableCredentialTypes" : [ ], - "requiredActions" : [ ], - "realmRoles" : [ "uma_authorization", "offline_access", "api-manager", "admin" ], - "clientRoles" : { - "account" : [ "manage-account", "view-profile" ] + { + "id": "dcd4bf36-c332-4888-a768-ae67d1207ccb", + "createdTimestamp": 1623445150804, + "username": "service-account-aps-portal", + "enabled": true, + "totp": false, + "emailVerified": false, + "serviceAccountClientId": "aps-portal", + "credentials": [], + "disableableCredentialTypes": [], + "requiredActions": [], + "realmRoles": ["uma_authorization", "offline_access"], + "clientRoles": { + "account": ["manage-account", "view-profile"] + }, + "notBefore": 0, + "groups": [] }, - "notBefore" : 0, - "groups" : [ ] - }, { - "id" : "dcd4bf36-c332-4888-a768-ae67d1207ccb", - "createdTimestamp" : 1623445150804, - "username" : "service-account-aps-portal", - "enabled" : true, - "totp" : false, - "emailVerified" : false, - "serviceAccountClientId" : "aps-portal", - "credentials" : [ ], - "disableableCredentialTypes" : [ ], - "requiredActions" : [ ], - "realmRoles" : [ "uma_authorization", "offline_access" ], - "clientRoles" : { - "account" : [ "manage-account", "view-profile" ] + { + "id": "0b87eb7b-28cd-43ec-b1fc-9c6b7ba12c9c", + "createdTimestamp": 1640110055487, + "username": "service-account-cypress-auth-profile", + "enabled": true, + "totp": false, + "emailVerified": false, + "serviceAccountClientId": "cypress-auth-profile", + "credentials": [], + "disableableCredentialTypes": [], + "requiredActions": [], + "realmRoles": ["uma_authorization", "offline_access"], + "clientRoles": { + "master-realm": [ + "manage-clients", + "view-users", + "create-client", + "manage-users" + ], + "account": ["manage-account", "view-profile"], + "cypress-auth-profile": ["uma_protection"] + }, + "notBefore": 0, + "groups": [] }, - "notBefore" : 0, - "groups" : [ ] - }, { - "id" : "0b87eb7b-28cd-43ec-b1fc-9c6b7ba12c9c", - "createdTimestamp" : 1640110055487, - "username" : "service-account-cypress-auth-profile", - "enabled" : true, - "totp" : false, - "emailVerified" : false, - "serviceAccountClientId" : "cypress-auth-profile", - "credentials" : [ ], - "disableableCredentialTypes" : [ ], - "requiredActions" : [ ], - "realmRoles" : [ "uma_authorization", "offline_access" ], - "clientRoles" : { - "master-realm" : [ "manage-clients", "view-users", "create-client", "manage-users" ], - "account" : [ "manage-account", "view-profile" ], - "cypress-auth-profile" : [ "uma_protection" ] + { + "id": "08e76239-85ee-4d2b-ac51-1fe737496fe8", + "createdTimestamp": 1625089066378, + "username": "service-account-gwa-api", + "enabled": true, + "totp": false, + "emailVerified": false, + "serviceAccountClientId": "gwa-api", + "credentials": [], + "disableableCredentialTypes": [], + "requiredActions": [], + "realmRoles": ["uma_authorization", "offline_access"], + "clientRoles": { + "gwa-api": ["uma_protection"], + "master-realm": [ + "manage-clients", + "view-users", + "create-client", + "manage-users", + "manage-authorization" + ], + "account": ["manage-account", "view-profile"] + }, + "notBefore": 0, + "groups": [] }, - "notBefore" : 0, - "groups" : [ ] - }, { - "id" : "08e76239-85ee-4d2b-ac51-1fe737496fe8", - "createdTimestamp" : 1625089066378, - "username" : "service-account-gwa-api", - "enabled" : true, - "totp" : false, - "emailVerified" : false, - "serviceAccountClientId" : "gwa-api", - "credentials" : [ ], - "disableableCredentialTypes" : [ ], - "requiredActions" : [ ], - "realmRoles" : [ "uma_authorization", "offline_access" ], - "clientRoles" : { - "gwa-api" : [ "uma_protection" ], - "master-realm" : [ "manage-clients", "view-users", "create-client", "manage-users", "manage-authorization" ], - "account" : [ "manage-account", "view-profile" ] + { + "id": "c795236e-fb09-4b4e-93e0-8bffb7dda7b3", + "createdTimestamp": 1650644631111, + "username": "service-account-sa-platform1-e0000000-5be82156d61f", + "enabled": true, + "totp": false, + "emailVerified": false, + "serviceAccountClientId": "sa-platform1-e0000000-5be82156d61f", + "credentials": [], + "disableableCredentialTypes": [], + "requiredActions": [], + "realmRoles": ["uma_authorization", "offline_access"], + "clientRoles": { + "account": ["manage-account", "view-profile"] + }, + "notBefore": 0, + "groups": [] }, - "notBefore" : 0, - "groups" : [ ] - }, { - "id" : "c795236e-fb09-4b4e-93e0-8bffb7dda7b3", - "createdTimestamp" : 1650644631111, - "username" : "service-account-sa-platform1-e0000000-5be82156d61f", - "enabled" : true, - "totp" : false, - "emailVerified" : false, - "serviceAccountClientId" : "sa-platform1-e0000000-5be82156d61f", - "credentials" : [ ], - "disableableCredentialTypes" : [ ], - "requiredActions" : [ ], - "realmRoles" : [ "uma_authorization", "offline_access" ], - "clientRoles" : { - "account" : [ "manage-account", "view-profile" ] + { + "id": "54adc719-3687-4886-9a7c-18c719a31014", + "createdTimestamp": 1651510581479, + "username": "service-account-sa-platform-e0000000-fa46551361b4", + "enabled": true, + "totp": false, + "emailVerified": false, + "serviceAccountClientId": "sa-platform-e0000000-fa46551361b4", + "credentials": [], + "disableableCredentialTypes": [], + "requiredActions": [], + "realmRoles": ["uma_authorization", "offline_access"], + "clientRoles": { + "account": ["manage-account", "view-profile"] + }, + "notBefore": 0, + "groups": [] }, - "notBefore" : 0, - "groups" : [ ] - }, { - "id" : "54adc719-3687-4886-9a7c-18c719a31014", - "createdTimestamp" : 1651510581479, - "username" : "service-account-sa-platform-e0000000-fa46551361b4", - "enabled" : true, - "totp" : false, - "emailVerified" : false, - "serviceAccountClientId" : "sa-platform-e0000000-fa46551361b4", - "credentials" : [ ], - "disableableCredentialTypes" : [ ], - "requiredActions" : [ ], - "realmRoles" : [ "uma_authorization", "offline_access" ], - "clientRoles" : { - "account" : [ "manage-account", "view-profile" ] + { + "id": "106ae49e-2334-4147-9f59-cd1ef50dab3b", + "createdTimestamp": 1645047852963, + "username": "wendy", + "enabled": true, + "totp": false, + "emailVerified": false, + "firstName": "Wendy F", + "lastName": "Wendy L", + "email": "wendy@test.com", + "credentials": [ + { + "id": "879b81f9-8dc9-40b2-afb5-805afc4e7e4d", + "type": "password", + "createdDate": 1645047984782, + "secretData": "{\"value\":\"itMDSu6kUt6bNPEHYdg9zH7jc2avU6W3JYTa/gNen7kGXGkanthdm60CWJ3E3lVnkBqniON8ntmnrNqSnOJv2g==\",\"salt\":\"kB81qbXXeMnX7k3DSvBmvQ==\"}", + "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\"}" + } + ], + "disableableCredentialTypes": [], + "requiredActions": [], + "realmRoles": ["uma_authorization", "credential-admin", "offline_access"], + "clientRoles": { + "account": ["manage-account", "view-profile"] + }, + "notBefore": 0, + "groups": [] }, - "notBefore" : 0, - "groups" : [ ] - }, { - "id" : "106ae49e-2334-4147-9f59-cd1ef50dab3b", - "createdTimestamp" : 1645047852963, - "username" : "wendy", - "enabled" : true, - "totp" : false, - "emailVerified" : false, - "firstName" : "Wendy F", - "lastName" : "Wendy L", - "email" : "wendy@test.com", - "credentials" : [ { - "id" : "879b81f9-8dc9-40b2-afb5-805afc4e7e4d", - "type" : "password", - "createdDate" : 1645047984782, - "secretData" : "{\"value\":\"itMDSu6kUt6bNPEHYdg9zH7jc2avU6W3JYTa/gNen7kGXGkanthdm60CWJ3E3lVnkBqniON8ntmnrNqSnOJv2g==\",\"salt\":\"kB81qbXXeMnX7k3DSvBmvQ==\"}", - "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\"}" - } ], - "disableableCredentialTypes" : [ ], - "requiredActions" : [ ], - "realmRoles" : [ "uma_authorization", "credential-admin", "offline_access" ], - "clientRoles" : { - "account" : [ "manage-account", "view-profile" ] + { + "id": "bf498a7b-b6e0-49bb-9ea8-0241d7792f01", + "createdTimestamp": 1642463435902, + "username": "olduser@idir", + "enabled": true, + "totp": false, + "emailVerified": false, + "firstName": "oldF", + "lastName": "userL", + "email": "olduser@testmail.com", + "attributes": { + "provider_user_guid": ["220469E037C84A7ABDFAB15204A60701"], + "identity_provider": ["idir"], + "display_name": ["oldF userL"], + "provider_username": ["olduser@idir"] + }, + "credentials": [ + { + "id": "6aa0a7ca-c2ad-43f5-9bdb-3f58693b2801", + "type": "password", + "createdDate": 1642466403247, + "secretData": "{\"value\":\"ltS/DMUYOCSmZZRbf7rYFTpLa9cqQDewFO1jwRPczU99leiyGtOCsbdAPRmSvLVhOLnzqvcaua3B17ej2d6/7w==\",\"salt\":\"ZrR/QMSRwruFRU5FsPUgHQ==\"}", + "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\"}" + } + ], + "disableableCredentialTypes": [], + "requiredActions": [], + "realmRoles": [ + "uma_authorization", + "aps-admin", + "offline_access", + "api-owner" + ], + "clientRoles": { + "account": ["manage-account", "view-profile"] + }, + "notBefore": 0, + "groups": [] }, - "notBefore" : 0, - "groups" : [ ] - } ], - "scopeMappings" : [ { - "clientScope" : "offline_access", - "roles" : [ "offline_access" ] - } ], - "clientScopeMappings" : { - "account" : [ { - "client" : "account-console", - "roles" : [ "manage-account" ] - } ] + { + "id": "bf498a7b-b6e0-49bb-9ea8-0241d7792c01", + "createdTimestamp": 1642463435902, + "username": "220469E037C84A7ABDFAB15204A60701@olduser", + "enabled": true, + "totp": false, + "emailVerified": false, + "firstName": "oldF", + "lastName": "userL", + "email": "olduser@testmail.com", + "attributes": { + "provider_user_guid": ["220469E037C84A7ABDFAB15204A60701"], + "identity_provider": ["idir"], + "display_name": ["oldF userL"], + "provider_username": ["olduser"] + }, + "credentials": [ + { + "id": "6aa0a7ca-c2ad-43f5-9bdb-3f58693b2c01", + "type": "password", + "createdDate": 1642466403247, + "secretData": "{\"value\":\"ltS/DMUYOCSmZZRbf7rYFTpLa9cqQDewFO1jwRPczU99leiyGtOCsbdAPRmSvLVhOLnzqvcaua3B17ej2d6/7w==\",\"salt\":\"ZrR/QMSRwruFRU5FsPUgHQ==\"}", + "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\"}" + } + ], + "disableableCredentialTypes": [], + "requiredActions": [], + "realmRoles": [ + "uma_authorization", + "aps-admin", + "offline_access", + "api-owner" + ], + "clientRoles": { + "account": ["manage-account", "view-profile"] + }, + "notBefore": 0, + "groups": [] + } + ], + "scopeMappings": [ + { + "clientScope": "offline_access", + "roles": ["offline_access"] + } + ], + "clientScopeMappings": { + "account": [ + { + "client": "account-console", + "roles": ["manage-account"] + } + ] }, - "clients" : [ { - "id" : "bc61d6b7-6876-4193-9881-1b994596a207", - "clientId" : "account", - "name" : "${client_account}", - "rootUrl" : "${authBaseUrl}", - "baseUrl" : "/realms/master/account/", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "secret" : "**********", - "defaultRoles" : [ "manage-account", "view-profile" ], - "redirectUris" : [ "/realms/master/account/*" ], - "webOrigins" : [ ], - "notBefore" : 0, - "bearerOnly" : false, - "consentRequired" : false, - "standardFlowEnabled" : true, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : false, - "serviceAccountsEnabled" : false, - "publicClient" : false, - "frontchannelLogout" : false, - "protocol" : "openid-connect", - "attributes" : { }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : false, - "nodeReRegistrationTimeout" : 0, - "defaultClientScopes" : [ "web-origins", "role_list", "roles", "profile", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] - }, { - "id" : "0f7cdb03-8ae1-46a1-b97d-c7e8f8094517", - "clientId" : "account-console", - "name" : "${client_account-console}", - "rootUrl" : "${authBaseUrl}", - "baseUrl" : "/realms/master/account/", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "secret" : "**********", - "redirectUris" : [ "/realms/master/account/*" ], - "webOrigins" : [ ], - "notBefore" : 0, - "bearerOnly" : false, - "consentRequired" : false, - "standardFlowEnabled" : true, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : false, - "serviceAccountsEnabled" : false, - "publicClient" : true, - "frontchannelLogout" : false, - "protocol" : "openid-connect", - "attributes" : { - "pkce.code.challenge.method" : "S256" + "clients": [ + { + "id": "bc61d6b7-6876-4193-9881-1b994596a207", + "clientId": "account", + "name": "${client_account}", + "rootUrl": "${authBaseUrl}", + "baseUrl": "/realms/master/account/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "defaultRoles": ["manage-account", "view-profile"], + "redirectUris": ["/realms/master/account/*"], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : false, - "nodeReRegistrationTimeout" : 0, - "protocolMappers" : [ { - "id" : "7d9f3625-b978-4996-a063-12552470c586", - "name" : "audience resolve", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-audience-resolve-mapper", - "consentRequired" : false, - "config" : { } - } ], - "defaultClientScopes" : [ "web-origins", "role_list", "roles", "profile", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] - }, { - "id" : "4221af6b-3bc7-4685-8c69-e1ba30303101", - "clientId" : "admin-cli", - "name" : "${client_admin-cli}", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "secret" : "**********", - "redirectUris" : [ ], - "webOrigins" : [ ], - "notBefore" : 0, - "bearerOnly" : false, - "consentRequired" : false, - "standardFlowEnabled" : false, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : true, - "serviceAccountsEnabled" : false, - "publicClient" : true, - "frontchannelLogout" : false, - "protocol" : "openid-connect", - "attributes" : { }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : false, - "nodeReRegistrationTimeout" : 0, - "defaultClientScopes" : [ "web-origins", "role_list", "roles", "profile", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] - }, { - "id" : "f333c5e5-fba2-48e8-aab7-7b6862881202", - "clientId" : "aps-portal", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "secret" : "8e1a17ed-cb93-4806-ac32-e303d1c86018", - "redirectUris" : [ "http://*", "https://*" ], - "webOrigins" : [ "*" ], - "notBefore" : 0, - "bearerOnly" : false, - "consentRequired" : false, - "standardFlowEnabled" : true, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : true, - "serviceAccountsEnabled" : true, - "publicClient" : false, - "frontchannelLogout" : false, - "protocol" : "openid-connect", - "attributes" : { - "saml.assertion.signature" : "false", - "saml.force.post.binding" : "false", - "saml.multivalued.roles" : "false", - "saml.encrypt" : "false", - "saml.server.signature" : "false", - "saml.server.signature.keyinfo.ext" : "false", - "exclude.session.state.from.auth.response" : "false", - "saml_force_name_id_format" : "false", - "saml.client.signature" : "false", - "tls.client.certificate.bound.access.tokens" : "false", - "saml.authnstatement" : "false", - "display.on.consent.screen" : "false", - "saml.onetimeuse.condition" : "false" + { + "id": "0f7cdb03-8ae1-46a1-b97d-c7e8f8094517", + "clientId": "account-console", + "name": "${client_account-console}", + "rootUrl": "${authBaseUrl}", + "baseUrl": "/realms/master/account/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": ["/realms/master/account/*"], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "pkce.code.challenge.method": "S256" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "7d9f3625-b978-4996-a063-12552470c586", + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": false, + "config": {} + } + ], + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : false, - "nodeReRegistrationTimeout" : -1, - "protocolMappers" : [ { - "id" : "390fa558-2b62-4399-adfb-e2ec96784813", - "name" : "Client Host", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usersessionmodel-note-mapper", - "consentRequired" : false, - "config" : { - "user.session.note" : "clientHost", - "userinfo.token.claim" : "true", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "clientHost", - "jsonType.label" : "String" - } - }, { - "id" : "8df082aa-710d-4be7-b396-87323a710e84", - "name" : "identity_provider", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "user.attribute" : "identity_provider", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "identity_provider", - "userinfo.token.claim" : "true" - } - }, { - "id" : "d9196236-636f-4459-ac3b-2b0f9b87681d", - "name" : "Client ID", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usersessionmodel-note-mapper", - "consentRequired" : false, - "config" : { - "user.session.note" : "clientId", - "userinfo.token.claim" : "true", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "clientId", - "jsonType.label" : "String" + { + "id": "4221af6b-3bc7-4685-8c69-e1ba30303101", + "clientId": "admin-cli", + "name": "${client_admin-cli}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": false, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "f333c5e5-fba2-48e8-aab7-7b6862881202", + "clientId": "aps-portal", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "8e1a17ed-cb93-4806-ac32-e303d1c86018", + "redirectUris": ["http://*", "https://*"], + "webOrigins": ["*"], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": true, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "saml.assertion.signature": "false", + "saml.force.post.binding": "false", + "saml.multivalued.roles": "false", + "saml.encrypt": "false", + "saml.server.signature": "false", + "saml.server.signature.keyinfo.ext": "false", + "exclude.session.state.from.auth.response": "false", + "saml_force_name_id_format": "false", + "saml.client.signature": "false", + "tls.client.certificate.bound.access.tokens": "false", + "saml.authnstatement": "false", + "display.on.consent.screen": "false", + "saml.onetimeuse.condition": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": -1, + "protocolMappers": [ + { + "id": "390fa558-2b62-4399-adfb-e2ec96784813", + "name": "Client Host", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientHost", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientHost", + "jsonType.label": "String" + } + }, + { + "id": "8df082aa-710d-4be7-b396-87323a710e84", + "name": "identity_provider", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "user.attribute": "identity_provider", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "identity_provider", + "userinfo.token.claim": "true" + } + }, + { + "id": "d9196236-636f-4459-ac3b-2b0f9b87681d", + "name": "Client ID", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientId", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientId", + "jsonType.label": "String" + } + }, + { + "id": "f088eda3-2a14-45a4-8e91-1f669152a6e3", + "name": "Client IP Address", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientAddress", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientAddress", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "Namespace.Create", + "role_list", + "roles", + "Namespace.Admin", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "62f2227e-e1ac-4c74-b278-1eab7f7664ae", + "clientId": "aps-v2-realm", + "name": "aps-v2 Realm", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": true, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "db7f58dc-c007-4e4c-ad7b-14f57a0521cd", + "clientId": "broker", + "name": "${client_broker}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "50c78923-95d9-4083-87ff-5233f2d6326e", + "clientId": "cypress-auth-profile", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "43badfc1-c06f-4bec-bab6-ccdc764071ac", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": false, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": true, + "authorizationServicesEnabled": true, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "saml.assertion.signature": "false", + "saml.force.post.binding": "false", + "saml.multivalued.roles": "false", + "saml.encrypt": "false", + "saml.server.signature": "false", + "saml.server.signature.keyinfo.ext": "false", + "exclude.session.state.from.auth.response": "false", + "saml_force_name_id_format": "false", + "saml.client.signature": "false", + "tls.client.certificate.bound.access.tokens": "false", + "saml.authnstatement": "false", + "display.on.consent.screen": "false", + "saml.onetimeuse.condition": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "protocolMappers": [ + { + "id": "e5b7aae4-4667-40a4-bef5-34abb759e338", + "name": "Client Host", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientHost", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientHost", + "jsonType.label": "String" + } + }, + { + "id": "6d728625-6d5e-4363-90cc-e3b68baa756a", + "name": "Client ID", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientId", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientId", + "jsonType.label": "String" + } + }, + { + "id": "bbf72323-f9f4-44c1-8088-df564fe7b494", + "name": "Client IP Address", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientAddress", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientAddress", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "role_list", + "Namespace.Create", + "Namespace.Admin", + "roles", + "profile", + "System.Write", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ], + "authorizationSettings": { + "allowRemoteResourceManagement": true, + "policyEnforcementMode": "ENFORCING", + "resources": [ + { + "name": "Default Resource", + "type": "urn:cypress-auth-profile:resources:default", + "ownerManagedAccess": false, + "attributes": {}, + "_id": "8543a438-ee7e-44b7-aa28-aef951b65f2f", + "uris": ["/*"] + } + ], + "policies": [ + { + "id": "34e0a630-d6fa-499c-b7b7-bca8b6ef70f6", + "name": "Default Policy", + "description": "A policy that grants access only for users within this realm", + "type": "js", + "logic": "POSITIVE", + "decisionStrategy": "AFFIRMATIVE", + "config": { + "code": "// by default, grants any permission associated with this policy\n$evaluation.grant();\n" + } + }, + { + "id": "a1bbc96c-4248-4f32-8bec-59569165bcb8", + "name": "Default Permission", + "description": "A permission that applies to the default resource type", + "type": "resource", + "logic": "POSITIVE", + "decisionStrategy": "UNANIMOUS", + "config": { + "defaultResourceType": "urn:cypress-auth-profile:resources:default", + "applyPolicies": "[\"Default Policy\"]" + } + } + ], + "scopes": [], + "decisionStrategy": "UNANIMOUS" } - }, { - "id" : "f088eda3-2a14-45a4-8e91-1f669152a6e3", - "name" : "Client IP Address", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usersessionmodel-note-mapper", - "consentRequired" : false, - "config" : { - "user.session.note" : "clientAddress", - "userinfo.token.claim" : "true", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "clientAddress", - "jsonType.label" : "String" + }, + { + "id": "c002b2b1-0ca8-4fd6-896e-6d2e3395a345", + "clientId": "gwa-api", + "rootUrl": "https://gwa-api-gov-bc-ca.dev.api.gov.bc.ca", + "adminUrl": "https://gwa-api-gov-bc-ca.dev.api.gov.bc.ca", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "18900468-3db1-43f7-a8af-e75f079eb742", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": false, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": true, + "authorizationServicesEnabled": true, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "saml.assertion.signature": "false", + "saml.force.post.binding": "false", + "saml.multivalued.roles": "false", + "saml.encrypt": "false", + "saml.server.signature": "false", + "saml.server.signature.keyinfo.ext": "false", + "exclude.session.state.from.auth.response": "false", + "saml_force_name_id_format": "false", + "saml.client.signature": "false", + "tls.client.certificate.bound.access.tokens": "false", + "saml.authnstatement": "false", + "display.on.consent.screen": "false", + "saml.onetimeuse.condition": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "protocolMappers": [ + { + "id": "4f2fdd5d-7cd7-427b-bce3-60ac808570da", + "name": "Client IP Address", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientAddress", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientAddress", + "jsonType.label": "String" + } + }, + { + "id": "3ef8dcec-57b5-4217-9991-c3144ffafc19", + "name": "Client Host", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientHost", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientHost", + "jsonType.label": "String" + } + }, + { + "id": "9e857953-1628-4deb-a568-9a59af3c985f", + "name": "Client ID", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientId", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientId", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "Namespace.Create", + "role_list", + "roles", + "Namespace.Admin", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ], + "authorizationSettings": { + "allowRemoteResourceManagement": true, + "policyEnforcementMode": "ENFORCING", + "resources": [ + { + "name": "Default Resource", + "type": "urn:gwa-api:resources:default", + "ownerManagedAccess": false, + "attributes": {}, + "_id": "054b9d22-ce05-4b1c-86bf-424eb7f3ca13", + "uris": ["/*"] + }, + { + "name": "platform1", + "type": "namespace", + "ownerManagedAccess": true, + "attributes": {}, + "_id": "fa9f93b8-b1c1-45ab-ad65-672befbdaedc", + "uris": [], + "scopes": [ + { + "name": "GatewayConfig.Publish" + }, + { + "name": "Namespace.Manage" + }, + { + "name": "Access.Manage" + }, + { + "name": "Content.Publish" + }, + { + "name": "Namespace.View" + }, + { + "name": "CredentialIssuer.Admin" + } + ] + }, + { + "name": "platform2", + "type": "namespace", + "ownerManagedAccess": true, + "attributes": {}, + "_id": "c6ad734c-6d8f-4b90-bcf9-cb9c19eadc22", + "uris": [], + "scopes": [ + { + "name": "GatewayConfig.Publish" + }, + { + "name": "Namespace.Manage" + }, + { + "name": "Access.Manage" + }, + { + "name": "Content.Publish" + }, + { + "name": "Namespace.View" + }, + { + "name": "CredentialIssuer.Admin" + } + ] + }, + { + "name": "platform", + "type": "namespace", + "ownerManagedAccess": true, + "attributes": {}, + "_id": "501a70b7-546a-43f3-8992-a4c170f0bab7", + "uris": [], + "scopes": [ + { + "name": "GatewayConfig.Publish" + }, + { + "name": "Namespace.Manage" + }, + { + "name": "Access.Manage" + }, + { + "name": "Content.Publish" + }, + { + "name": "Namespace.View" + }, + { + "name": "CredentialIssuer.Admin" + } + ] + }, + { + "name": "org/ca.bc.gov", + "type": "organization", + "ownerManagedAccess": true, + "displayName": "org/ca.bc.gov", + "attributes": {}, + "_id": "228c26be-3ef4-43d6-92ec-8441ebf5887c", + "uris": [], + "scopes": [ + { + "name": "GroupAccess.Manage" + } + ] + }, + { + "name": "org/ministry-of-health", + "type": "organization", + "ownerManagedAccess": true, + "attributes": {}, + "_id": "2367ab08-6c6e-42e4-b1db-3a86de3a028d", + "uris": [], + "scopes": [ + { + "name": "GroupAccess.Manage" + }, + { + "name": "Dataset.Manage" + }, + { + "name": "Namespace.Assign" + } + ] + }, + { + "name": "org/planning-and-innovation-division", + "type": "organization", + "ownerManagedAccess": true, + "attributes": {}, + "_id": "032644b7-a3a0-489e-bda3-193bd14d861a", + "uris": [], + "scopes": [ + { + "name": "GroupAccess.Manage" + }, + { + "name": "Dataset.Manage" + }, + { + "name": "Namespace.Assign" + } + ] + } + ], + "policies": [ + { + "id": "35dcd837-d215-4036-84fe-452605b0a065", + "name": "Default Policy", + "description": "A policy that grants access only for users within this realm", + "type": "js", + "logic": "POSITIVE", + "decisionStrategy": "AFFIRMATIVE", + "config": { + "code": "// by default, grants any permission associated with this policy\n$evaluation.grant();\n" + } + }, + { + "id": "ca06ef6c-d7f8-42c9-b0d6-0c9be85c1cc1", + "name": "janis", + "type": "user", + "logic": "POSITIVE", + "decisionStrategy": "UNANIMOUS", + "config": { + "users": "[\"janis@idir\"]" + } + }, + { + "id": "c3848ff4-76b0-4f2d-afe9-7dfd77467fcb", + "name": "group-organization-admin-ca.bc.gov-policy", + "description": "Group '/organization-admin' / 'ca.bc.gov' Policy", + "type": "group", + "logic": "POSITIVE", + "decisionStrategy": "UNANIMOUS", + "config": { + "groups": "[{\"path\":\"/organization-admin\",\"extendChildren\":false},{\"path\":\"/organization-admin/ca.bc.gov\",\"extendChildren\":false}]" + } + }, + { + "id": "6f49c571-fbbb-4f86-a72a-c1591a446bb3", + "name": "group-organization-admin-ca.bc.gov-ministry-of-health-policy", + "description": "Group '/organization-admin/ca.bc.gov' / 'ministry-of-health' Policy", + "type": "group", + "logic": "POSITIVE", + "decisionStrategy": "UNANIMOUS", + "config": { + "groups": "[{\"path\":\"/organization-admin/ca.bc.gov/ministry-of-health\",\"extendChildren\":false},{\"path\":\"/organization-admin\",\"extendChildren\":false},{\"path\":\"/organization-admin/ca.bc.gov\",\"extendChildren\":false}]" + } + }, + { + "id": "99fdf1a9-d5ec-48c7-a2cd-1ddeb130b058", + "name": "group-organization-admin-ca.bc.gov-ministry-of-health-planning-and-innovation-division-policy", + "description": "Group '/organization-admin/ca.bc.gov/ministry-of-health' / 'planning-and-innovation-division' Policy", + "type": "group", + "logic": "POSITIVE", + "decisionStrategy": "UNANIMOUS", + "config": { + "groups": "[{\"path\":\"/organization-admin/ca.bc.gov\",\"extendChildren\":false},{\"path\":\"/organization-admin/ca.bc.gov/ministry-of-health/planning-and-innovation-division\",\"extendChildren\":false},{\"path\":\"/organization-admin/ca.bc.gov/ministry-of-health\",\"extendChildren\":false},{\"path\":\"/organization-admin\",\"extendChildren\":false}]" + } + }, + { + "id": "31be7436-e9d8-42a3-b42e-69a1869a7eea", + "name": "Default Permission", + "description": "A permission that applies to the default resource type", + "type": "resource", + "logic": "POSITIVE", + "decisionStrategy": "UNANIMOUS", + "config": { + "defaultResourceType": "urn:gwa-api:resources:default", + "applyPolicies": "[\"Default Policy\"]" + } + }, + { + "id": "65f0c0a4-e2ac-4364-800d-ebd4e11ce393", + "name": "janis full access", + "type": "scope", + "logic": "POSITIVE", + "decisionStrategy": "UNANIMOUS", + "config": { + "scopes": "[\"GroupAccess.Manage\",\"Namespace.Assign\"]", + "applyPolicies": "[\"janis\"]" + } + }, + { + "id": "854f0dfe-952d-48f8-9d53-d49b0b4ed122", + "name": "Access to 'org/ca.bc.gov' services for role organization-admin", + "type": "scope", + "logic": "POSITIVE", + "decisionStrategy": "UNANIMOUS", + "config": { + "resources": "[\"org/ca.bc.gov\"]", + "scopes": "[\"GroupAccess.Manage\"]", + "applyPolicies": "[\"group-organization-admin-ca.bc.gov-policy\"]" + } + }, + { + "id": "3f934d3f-d231-48fc-9f5a-924da7808989", + "name": "Access to 'org/ministry-of-health' services for role organization-admin", + "type": "scope", + "logic": "POSITIVE", + "decisionStrategy": "UNANIMOUS", + "config": { + "resources": "[\"org/ministry-of-health\"]", + "scopes": "[\"Dataset.Manage\",\"GroupAccess.Manage\",\"Namespace.Assign\"]", + "applyPolicies": "[\"group-organization-admin-ca.bc.gov-ministry-of-health-policy\"]" + } + }, + { + "id": "56a4857d-a0be-472c-85d0-2dca93a1fdac", + "name": "Access to 'org/planning-and-innovation-division' services for role organization-admin", + "type": "scope", + "logic": "POSITIVE", + "decisionStrategy": "UNANIMOUS", + "config": { + "resources": "[\"org/planning-and-innovation-division\"]", + "scopes": "[\"Dataset.Manage\",\"GroupAccess.Manage\",\"Namespace.Assign\"]", + "applyPolicies": "[\"group-organization-admin-ca.bc.gov-ministry-of-health-planning-and-innovation-division-policy\"]" + } + }, + { + "id": "f2e764aa-c355-4e81-a5e6-e76ffb86041f", + "name": "Access to 'platform' services for role organization-admin", + "type": "scope", + "logic": "POSITIVE", + "decisionStrategy": "UNANIMOUS", + "config": { + "resources": "[\"platform\"]", + "scopes": "[\"Namespace.View\"]", + "applyPolicies": "[\"group-organization-admin-ca.bc.gov-ministry-of-health-planning-and-innovation-division-policy\"]" + } + } + ], + "scopes": [ + { + "id": "6871ce8b-5d5f-455b-86ff-7cf5940930eb", + "name": "Namespace.Manage" + }, + { + "id": "0006d34f-1416-4ffb-ad1f-39ebf63f9556", + "name": "Namespace.View" + }, + { + "id": "a4d424c9-7331-4715-96a9-ecfd1dd0cf2c", + "name": "GatewayConfig.Publish" + }, + { + "id": "fd403d7f-1dfb-4673-8ab3-5e1ff7797b35", + "name": "Access.Manage" + }, + { + "id": "0f98e35d-c2c3-4781-bf85-478bf06cfa24", + "name": "Content.Publish" + }, + { + "id": "dfc132ca-aa87-40b5-bc33-3e972a88f638", + "name": "CredentialIssuer.Admin" + }, + { + "id": "95893c25-6b83-4e59-9518-a25568d95542", + "name": "GroupAccess.Manage", + "iconUri": "", + "displayName": "GroupAccess.Manage" + }, + { + "id": "b0b007b1-1ecb-4b3f-9f0c-41b3fa34754c", + "name": "Dataset.Manage" + }, + { + "id": "f3bf8d43-54a4-4594-aeea-f61b99411f92", + "name": "Namespace.Assign" + } + ], + "decisionStrategy": "AFFIRMATIVE" } - } ], - "defaultClientScopes" : [ "web-origins", "Namespace.Create", "role_list", "roles", "Namespace.Admin", "profile", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] - }, { - "id" : "62f2227e-e1ac-4c74-b278-1eab7f7664ae", - "clientId" : "aps-v2-realm", - "name" : "aps-v2 Realm", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "secret" : "**********", - "redirectUris" : [ ], - "webOrigins" : [ ], - "notBefore" : 0, - "bearerOnly" : true, - "consentRequired" : false, - "standardFlowEnabled" : true, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : false, - "serviceAccountsEnabled" : false, - "publicClient" : false, - "frontchannelLogout" : false, - "protocol" : "openid-connect", - "attributes" : { }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : true, - "nodeReRegistrationTimeout" : 0, - "defaultClientScopes" : [ "web-origins", "role_list", "roles", "profile", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] - }, { - "id" : "db7f58dc-c007-4e4c-ad7b-14f57a0521cd", - "clientId" : "broker", - "name" : "${client_broker}", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "secret" : "**********", - "redirectUris" : [ ], - "webOrigins" : [ ], - "notBefore" : 0, - "bearerOnly" : false, - "consentRequired" : false, - "standardFlowEnabled" : true, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : false, - "serviceAccountsEnabled" : false, - "publicClient" : false, - "frontchannelLogout" : false, - "protocol" : "openid-connect", - "attributes" : { }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : false, - "nodeReRegistrationTimeout" : 0, - "defaultClientScopes" : [ "web-origins", "role_list", "roles", "profile", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] - }, { - "id" : "50c78923-95d9-4083-87ff-5233f2d6326e", - "clientId" : "cypress-auth-profile", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "secret" : "43badfc1-c06f-4bec-bab6-ccdc764071ac", - "redirectUris" : [ ], - "webOrigins" : [ ], - "notBefore" : 0, - "bearerOnly" : false, - "consentRequired" : false, - "standardFlowEnabled" : false, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : false, - "serviceAccountsEnabled" : true, - "authorizationServicesEnabled" : true, - "publicClient" : false, - "frontchannelLogout" : false, - "protocol" : "openid-connect", - "attributes" : { - "saml.assertion.signature" : "false", - "saml.force.post.binding" : "false", - "saml.multivalued.roles" : "false", - "saml.encrypt" : "false", - "saml.server.signature" : "false", - "saml.server.signature.keyinfo.ext" : "false", - "exclude.session.state.from.auth.response" : "false", - "saml_force_name_id_format" : "false", - "saml.client.signature" : "false", - "tls.client.certificate.bound.access.tokens" : "false", - "saml.authnstatement" : "false", - "display.on.consent.screen" : "false", - "saml.onetimeuse.condition" : "false" }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : true, - "nodeReRegistrationTimeout" : -1, - "protocolMappers" : [ { - "id" : "e5b7aae4-4667-40a4-bef5-34abb759e338", - "name" : "Client Host", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usersessionmodel-note-mapper", - "consentRequired" : false, - "config" : { - "user.session.note" : "clientHost", - "userinfo.token.claim" : "true", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "clientHost", - "jsonType.label" : "String" + { + "id": "4e6525e9-647c-4c80-85d6-9c13890b0ab2", + "clientId": "master-realm", + "name": "master Realm", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": true, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "4bbc355d-7a87-4476-9593-7f9359dc8859", + "clientId": "sa-platform1-e0000000-5be82156d61f", + "name": "", + "description": "", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "c01a7839-2679-4cdd-96c4-173223b49ee6", + "redirectUris": ["https://*"], + "webOrigins": ["*"], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": false, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": true, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "saml.assertion.signature": "false", + "saml.multivalued.roles": "false", + "saml.force.post.binding": "false", + "saml.encrypt": "false", + "saml.server.signature": "false", + "saml.server.signature.keyinfo.ext": "false", + "exclude.session.state.from.auth.response": "false", + "client_credentials.use_refresh_token": "false", + "saml_force_name_id_format": "false", + "saml.client.signature": "false", + "tls.client.certificate.bound.access.tokens": "false", + "saml.authnstatement": "false", + "display.on.consent.screen": "false", + "saml.onetimeuse.condition": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": -1, + "protocolMappers": [ + { + "id": "d5b56ac0-01af-4241-991e-1cd25edeb739", + "name": "Client ID", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientId", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientId", + "jsonType.label": "String" + } + }, + { + "id": "8c119e4b-b308-41aa-be7b-91e1d299e499", + "name": "Client Host", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientHost", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientHost", + "jsonType.label": "String" + } + }, + { + "id": "3ba852b4-71b8-4942-950b-80968346b0e2", + "name": "Client IP Address", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientAddress", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientAddress", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": [], + "optionalClientScopes": [] + }, + { + "id": "25ee1923-6323-4c4c-ae70-178615ace3b2", + "clientId": "sa-platform-e0000000-fa46551361b4", + "name": "", + "description": "", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "dc96e3d3-23cc-4345-aa5e-6f89b5d20c91", + "redirectUris": ["https://*"], + "webOrigins": ["*"], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": false, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": true, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "saml.assertion.signature": "false", + "saml.multivalued.roles": "false", + "saml.force.post.binding": "false", + "saml.encrypt": "false", + "saml.server.signature": "false", + "saml.server.signature.keyinfo.ext": "false", + "exclude.session.state.from.auth.response": "false", + "client_credentials.use_refresh_token": "false", + "saml_force_name_id_format": "false", + "saml.client.signature": "false", + "tls.client.certificate.bound.access.tokens": "false", + "saml.authnstatement": "false", + "display.on.consent.screen": "false", + "saml.onetimeuse.condition": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": -1, + "protocolMappers": [ + { + "id": "270af568-11bf-4208-bccd-58583e44f09c", + "name": "Client IP Address", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientAddress", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientAddress", + "jsonType.label": "String" + } + }, + { + "id": "9dda9072-1e47-43fd-a482-6830b252ca5b", + "name": "Client Host", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientHost", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientHost", + "jsonType.label": "String" + } + }, + { + "id": "a35858ac-39ad-46bc-9227-e40698049c62", + "name": "Client ID", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientId", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientId", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": [], + "optionalClientScopes": [] + }, + { + "id": "5c797848-2f03-4085-a03a-e4f7c22d0050", + "clientId": "security-admin-console", + "name": "${client_security-admin-console}", + "rootUrl": "${authAdminUrl}", + "baseUrl": "/admin/master/console/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": ["/admin/master/console/*"], + "webOrigins": ["+"], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "pkce.code.challenge.method": "S256" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "c5b453d6-73e5-40f2-bc65-375b571f7d6c", + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + } + ], + "clientScopes": [ + { + "id": "f5d4d8e2-6e57-477a-83b0-88047af5285d", + "name": "Content.Publish", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true" } - }, { - "id" : "6d728625-6d5e-4363-90cc-e3b68baa756a", - "name" : "Client ID", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usersessionmodel-note-mapper", - "consentRequired" : false, - "config" : { - "user.session.note" : "clientId", - "userinfo.token.claim" : "true", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "clientId", - "jsonType.label" : "String" + }, + { + "id": "4f7a31ce-a48b-4816-baff-4dbc378d4a10", + "name": "Namespace.Admin", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true" } - }, { - "id" : "bbf72323-f9f4-44c1-8088-df564fe7b494", - "name" : "Client IP Address", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usersessionmodel-note-mapper", - "consentRequired" : false, - "config" : { - "user.session.note" : "clientAddress", - "userinfo.token.claim" : "true", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "clientAddress", - "jsonType.label" : "String" + }, + { + "id": "5c280525-34b7-4436-a567-ad5a75f0b093", + "name": "Namespace.Create", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true" } - } ], - "defaultClientScopes" : [ "web-origins", "role_list", "Namespace.Create", "Namespace.Admin", "roles", "profile", "System.Write", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ], - "authorizationSettings" : { - "allowRemoteResourceManagement" : true, - "policyEnforcementMode" : "ENFORCING", - "resources" : [ { - "name" : "Default Resource", - "type" : "urn:cypress-auth-profile:resources:default", - "ownerManagedAccess" : false, - "attributes" : { }, - "_id" : "8543a438-ee7e-44b7-aa28-aef951b65f2f", - "uris" : [ "/*" ] - } ], - "policies" : [ { - "id" : "34e0a630-d6fa-499c-b7b7-bca8b6ef70f6", - "name" : "Default Policy", - "description" : "A policy that grants access only for users within this realm", - "type" : "js", - "logic" : "POSITIVE", - "decisionStrategy" : "AFFIRMATIVE", - "config" : { - "code" : "// by default, grants any permission associated with this policy\n$evaluation.grant();\n" + }, + { + "id": "e78e5fd1-5ee2-4215-a5c3-a8581a19c716", + "name": "address", + "description": "OpenID Connect built-in scope: address", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${addressScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "b2a36609-2408-44fd-88ac-ef41fa62f5f4", + "name": "address", + "protocol": "openid-connect", + "protocolMapper": "oidc-address-mapper", + "consentRequired": false, + "config": { + "user.attribute.formatted": "formatted", + "user.attribute.country": "country", + "user.attribute.postal_code": "postal_code", + "userinfo.token.claim": "true", + "user.attribute.street": "street", + "id.token.claim": "true", + "user.attribute.region": "region", + "access.token.claim": "true", + "user.attribute.locality": "locality" + } + } + ] + }, + { + "id": "89e870cc-7056-4bc0-8cf2-9c961ff4a62d", + "name": "email", + "description": "OpenID Connect built-in scope: email", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${emailScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "7fb89890-a73f-4162-9ca3-e1539905ccb6", + "name": "email verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "emailVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email_verified", + "jsonType.label": "boolean" + } + }, + { + "id": "9ec60f35-65c9-4ea2-ab0e-2fc2c462d892", + "name": "email", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "email", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email", + "jsonType.label": "String" + } } - }, { - "id" : "a1bbc96c-4248-4f32-8bec-59569165bcb8", - "name" : "Default Permission", - "description" : "A permission that applies to the default resource type", - "type" : "resource", - "logic" : "POSITIVE", - "decisionStrategy" : "UNANIMOUS", - "config" : { - "defaultResourceType" : "urn:cypress-auth-profile:resources:default", - "applyPolicies" : "[\"Default Policy\"]" + ] + }, + { + "id": "920764e0-6019-462b-bc25-f17a54562752", + "name": "microprofile-jwt", + "description": "Microprofile - JWT built-in scope", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "cd9090fd-faf4-450a-9144-3a9e04260095", + "name": "groups", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "multivalued": "true", + "userinfo.token.claim": "true", + "user.attribute": "foo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "groups", + "jsonType.label": "String" + } + }, + { + "id": "9ca3b431-06e3-43f0-9277-a6dec6ec1172", + "name": "upn", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "upn", + "jsonType.label": "String" + } } - } ], - "scopes" : [ ], - "decisionStrategy" : "UNANIMOUS" - } - }, { - "id" : "c002b2b1-0ca8-4fd6-896e-6d2e3395a345", - "clientId" : "gwa-api", - "rootUrl" : "https://gwa-api-gov-bc-ca.dev.api.gov.bc.ca", - "adminUrl" : "https://gwa-api-gov-bc-ca.dev.api.gov.bc.ca", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "secret" : "18900468-3db1-43f7-a8af-e75f079eb742", - "redirectUris" : [ ], - "webOrigins" : [ ], - "notBefore" : 0, - "bearerOnly" : false, - "consentRequired" : false, - "standardFlowEnabled" : false, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : false, - "serviceAccountsEnabled" : true, - "authorizationServicesEnabled" : true, - "publicClient" : false, - "frontchannelLogout" : false, - "protocol" : "openid-connect", - "attributes" : { - "saml.assertion.signature" : "false", - "saml.force.post.binding" : "false", - "saml.multivalued.roles" : "false", - "saml.encrypt" : "false", - "saml.server.signature" : "false", - "saml.server.signature.keyinfo.ext" : "false", - "exclude.session.state.from.auth.response" : "false", - "saml_force_name_id_format" : "false", - "saml.client.signature" : "false", - "tls.client.certificate.bound.access.tokens" : "false", - "saml.authnstatement" : "false", - "display.on.consent.screen" : "false", - "saml.onetimeuse.condition" : "false" + ] }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : true, - "nodeReRegistrationTimeout" : -1, - "protocolMappers" : [ { - "id" : "4f2fdd5d-7cd7-427b-bce3-60ac808570da", - "name" : "Client IP Address", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usersessionmodel-note-mapper", - "consentRequired" : false, - "config" : { - "user.session.note" : "clientAddress", - "userinfo.token.claim" : "true", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "clientAddress", - "jsonType.label" : "String" + { + "id": "bb473906-0c39-4af1-aad9-d8788dc7559f", + "name": "offline_access", + "description": "OpenID Connect built-in scope: offline_access", + "protocol": "openid-connect", + "attributes": { + "consent.screen.text": "${offlineAccessScopeConsentText}", + "display.on.consent.screen": "true" } - }, { - "id" : "3ef8dcec-57b5-4217-9991-c3144ffafc19", - "name" : "Client Host", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usersessionmodel-note-mapper", - "consentRequired" : false, - "config" : { - "user.session.note" : "clientHost", - "userinfo.token.claim" : "true", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "clientHost", - "jsonType.label" : "String" + }, + { + "id": "e5e16f12-1b4c-47e7-9599-99ff395f359c", + "name": "phone", + "description": "OpenID Connect built-in scope: phone", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${phoneScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "8d83aa08-43a9-49f5-b1dd-caa144e2cad5", + "name": "phone number", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "phoneNumber", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number", + "jsonType.label": "String" + } + }, + { + "id": "3886e58f-d64f-4851-80f3-ae7cc5c6ab13", + "name": "phone number verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "phoneNumberVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number_verified", + "jsonType.label": "boolean" + } + } + ] + }, + { + "id": "f33d0489-2a52-4066-9c38-e130c02665ee", + "name": "profile", + "description": "OpenID Connect built-in scope: profile", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${profileScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "1826e2b1-380a-4c65-a73e-3bb79f519550", + "name": "website", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "website", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "website", + "jsonType.label": "String" + } + }, + { + "id": "6ea0a08a-ab42-4b45-acfc-a05f5b452cb0", + "name": "nickname", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "nickname", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "nickname", + "jsonType.label": "String" + } + }, + { + "id": "78d97855-5557-4f10-9d20-74d8ea6bdfef", + "name": "full name", + "protocol": "openid-connect", + "protocolMapper": "oidc-full-name-mapper", + "consentRequired": false, + "config": { + "id.token.claim": "true", + "access.token.claim": "true", + "userinfo.token.claim": "true" + } + }, + { + "id": "22e60a23-914f-40bf-960d-e7a96655581d", + "name": "picture", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "picture", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "picture", + "jsonType.label": "String" + } + }, + { + "id": "e595c828-c815-4dff-bd8f-39b1eee5a3b3", + "name": "birthdate", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "birthdate", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "birthdate", + "jsonType.label": "String" + } + }, + { + "id": "cd91c70b-0856-4f5d-aeb6-9b5c3b48a966", + "name": "zoneinfo", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "zoneinfo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "zoneinfo", + "jsonType.label": "String" + } + }, + { + "id": "4ce90553-d828-4146-92e0-ee1775c9ba28", + "name": "updated at", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "updatedAt", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "updated_at", + "jsonType.label": "String" + } + }, + { + "id": "43710808-227e-4171-a106-7576f933a32b", + "name": "family name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "lastName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "family_name", + "jsonType.label": "String" + } + }, + { + "id": "a814d5c0-bdcd-4f33-8cfd-228005f2ba94", + "name": "gender", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "gender", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "gender", + "jsonType.label": "String" + } + }, + { + "id": "df9e1465-617d-4a7b-a208-7354c6cbaada", + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + }, + { + "id": "fc508e60-a978-41f1-bea2-311673b4b0a8", + "name": "given name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "firstName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "given_name", + "jsonType.label": "String" + } + }, + { + "id": "8e4641a3-87d3-4958-8113-dcfa82f0ef54", + "name": "middle name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "middleName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "middle_name", + "jsonType.label": "String" + } + }, + { + "id": "ffc38939-9e10-4cf3-b4fc-65203e079a92", + "name": "username", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "preferred_username", + "jsonType.label": "String" + } + }, + { + "id": "9364fe99-268a-4a74-88aa-a120a6897e78", + "name": "profile", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "profile", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "profile", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "b5a38584-219b-4618-a3a5-70814bed867e", + "name": "role_list", + "description": "SAML role list", + "protocol": "saml", + "attributes": { + "consent.screen.text": "${samlRoleListScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "id": "1a0a5251-1b3f-47b1-8cc1-07a285d6479f", + "name": "role list", + "protocol": "saml", + "protocolMapper": "saml-role-list-mapper", + "consentRequired": false, + "config": { + "single": "false", + "attribute.nameformat": "Basic", + "attribute.name": "Role" + } + } + ] + }, + { + "id": "33bd4c0f-225f-43cb-8b6c-0bd4db702525", + "name": "roles", + "description": "OpenID Connect scope for add user roles to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "true", + "consent.screen.text": "${rolesScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "e276a79b-99cc-4f10-8d26-0e10ce245fdb", + "name": "client roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-client-role-mapper", + "consentRequired": false, + "config": { + "user.attribute": "foo", + "access.token.claim": "true", + "claim.name": "resource_access.${client_id}.roles", + "jsonType.label": "String", + "multivalued": "true" + } + }, + { + "id": "b64cc3a2-8ed8-4dee-a13a-fef5588a5949", + "name": "realm roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "user.attribute": "foo", + "access.token.claim": "true", + "claim.name": "realm_access.roles", + "jsonType.label": "String", + "multivalued": "true" + } + }, + { + "id": "c9828318-6d78-4aba-94ea-405f12fce589", + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": false, + "config": {} + } + ] + }, + { + "id": "0bfddcf3-017d-44b6-8447-297c565d5d2d", + "name": "web-origins", + "description": "OpenID Connect scope for add allowed web origins to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "false", + "consent.screen.text": "" + }, + "protocolMappers": [ + { + "id": "28867dcd-803d-47a5-be90-51be8a331527", + "name": "allowed web origins", + "protocol": "openid-connect", + "protocolMapper": "oidc-allowed-origins-mapper", + "consentRequired": false, + "config": {} + } + ] + }, + { + "id": "e28fac82-4db1-4900-8096-74706a71f7f3", + "name": "System.Write", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true" } - }, { - "id" : "9e857953-1628-4deb-a568-9a59af3c985f", - "name" : "Client ID", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usersessionmodel-note-mapper", - "consentRequired" : false, - "config" : { - "user.session.note" : "clientId", - "userinfo.token.claim" : "true", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "clientId", - "jsonType.label" : "String" + } + ], + "defaultDefaultClientScopes": [ + "web-origins", + "roles", + "Namespace.Admin", + "Namespace.Create", + "email", + "role_list", + "profile" + ], + "defaultOptionalClientScopes": [ + "microprofile-jwt", + "offline_access", + "phone", + "address" + ], + "browserSecurityHeaders": { + "contentSecurityPolicyReportOnly": "", + "xContentTypeOptions": "nosniff", + "xRobotsTag": "none", + "xFrameOptions": "SAMEORIGIN", + "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "xXSSProtection": "1; mode=block", + "strictTransportSecurity": "max-age=31536000; includeSubDomains" + }, + "smtpServer": {}, + "eventsEnabled": false, + "eventsListeners": ["jboss-logging"], + "enabledEventTypes": [], + "adminEventsEnabled": false, + "adminEventsDetailsEnabled": false, + "components": { + "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [ + { + "id": "d7699c96-1cc0-46fe-b0fe-c72c7f7d1804", + "name": "Consent Required", + "providerId": "consent-required", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "522f0c4c-8dfe-4421-b573-0e5723319dac", + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allow-default-scopes": ["true"] + } + }, + { + "id": "2502109c-1319-4bcd-bf94-a5225239c42b", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "oidc-full-name-mapper", + "saml-user-property-mapper", + "oidc-sha256-pairwise-sub-mapper", + "saml-user-attribute-mapper", + "oidc-usermodel-attribute-mapper", + "oidc-address-mapper", + "saml-role-list-mapper", + "oidc-usermodel-property-mapper" + ] + } + }, + { + "id": "013bd2ad-80e7-40fe-ba41-b90642d536cd", + "name": "Trusted Hosts", + "providerId": "trusted-hosts", + "subType": "anonymous", + "subComponents": {}, + "config": { + "host-sending-registration-request-must-match": ["true"], + "client-uris-must-match": ["true"] + } + }, + { + "id": "c0bcf5a2-ef5f-4f03-95c7-ea15f27c8cd7", + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allow-default-scopes": ["true"] + } + }, + { + "id": "1157f7fe-a055-4ec3-8af8-3f809fd2fec0", + "name": "Full Scope Disabled", + "providerId": "scope", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "650e6c8f-8a93-4096-9d37-1aecfe000e49", + "name": "Max Clients Limit", + "providerId": "max-clients", + "subType": "anonymous", + "subComponents": {}, + "config": { + "max-clients": ["200"] + } + }, + { + "id": "93e21f15-c390-475a-865a-3f8125b1ccc9", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "oidc-usermodel-property-mapper", + "oidc-sha256-pairwise-sub-mapper", + "oidc-address-mapper", + "saml-role-list-mapper", + "saml-user-property-mapper", + "oidc-full-name-mapper", + "saml-user-attribute-mapper", + "oidc-usermodel-attribute-mapper" + ] + } } - } ], - "defaultClientScopes" : [ "web-origins", "Namespace.Create", "role_list", "roles", "Namespace.Admin", "profile", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ], - "authorizationSettings" : { - "allowRemoteResourceManagement" : true, - "policyEnforcementMode" : "ENFORCING", - "resources" : [ { - "name" : "Default Resource", - "type" : "urn:gwa-api:resources:default", - "ownerManagedAccess" : false, - "attributes" : { }, - "_id" : "054b9d22-ce05-4b1c-86bf-424eb7f3ca13", - "uris" : [ "/*" ] - }, { - "name" : "platform1", - "type" : "namespace", - "ownerManagedAccess" : true, - "attributes" : { }, - "_id" : "fa9f93b8-b1c1-45ab-ad65-672befbdaedc", - "uris" : [ ], - "scopes" : [ { - "name" : "GatewayConfig.Publish" - }, { - "name" : "Namespace.Manage" - }, { - "name" : "Access.Manage" - }, { - "name" : "Content.Publish" - }, { - "name" : "Namespace.View" - }, { - "name" : "CredentialIssuer.Admin" - } ] - }, { - "name" : "platform2", - "type" : "namespace", - "ownerManagedAccess" : true, - "attributes" : { }, - "_id" : "c6ad734c-6d8f-4b90-bcf9-cb9c19eadc22", - "uris" : [ ], - "scopes" : [ { - "name" : "GatewayConfig.Publish" - }, { - "name" : "Namespace.Manage" - }, { - "name" : "Access.Manage" - }, { - "name" : "Content.Publish" - }, { - "name" : "Namespace.View" - }, { - "name" : "CredentialIssuer.Admin" - } ] - }, { - "name" : "platform", - "type" : "namespace", - "ownerManagedAccess" : true, - "attributes" : { }, - "_id" : "501a70b7-546a-43f3-8992-a4c170f0bab7", - "uris" : [ ], - "scopes" : [ { - "name" : "GatewayConfig.Publish" - }, { - "name" : "Namespace.Manage" - }, { - "name" : "Access.Manage" - }, { - "name" : "Content.Publish" - }, { - "name" : "Namespace.View" - }, { - "name" : "CredentialIssuer.Admin" - } ] - }, { - "name" : "org/ca.bc.gov", - "type" : "organization", - "ownerManagedAccess" : true, - "displayName" : "org/ca.bc.gov", - "attributes" : { }, - "_id" : "228c26be-3ef4-43d6-92ec-8441ebf5887c", - "uris" : [ ], - "scopes" : [ { - "name" : "GroupAccess.Manage" - } ] - }, { - "name" : "org/ministry-of-health", - "type" : "organization", - "ownerManagedAccess" : true, - "attributes" : { }, - "_id" : "2367ab08-6c6e-42e4-b1db-3a86de3a028d", - "uris" : [ ], - "scopes" : [ { - "name" : "GroupAccess.Manage" - }, { - "name" : "Dataset.Manage" - }, { - "name" : "Namespace.Assign" - } ] - }, { - "name" : "org/planning-and-innovation-division", - "type" : "organization", - "ownerManagedAccess" : true, - "attributes" : { }, - "_id" : "032644b7-a3a0-489e-bda3-193bd14d861a", - "uris" : [ ], - "scopes" : [ { - "name" : "GroupAccess.Manage" - }, { - "name" : "Dataset.Manage" - }, { - "name" : "Namespace.Assign" - } ] - } ], - "policies" : [ { - "id" : "35dcd837-d215-4036-84fe-452605b0a065", - "name" : "Default Policy", - "description" : "A policy that grants access only for users within this realm", - "type" : "js", - "logic" : "POSITIVE", - "decisionStrategy" : "AFFIRMATIVE", - "config" : { - "code" : "// by default, grants any permission associated with this policy\n$evaluation.grant();\n" + ], + "org.keycloak.keys.KeyProvider": [ + { + "id": "2b0c7bcb-c441-4694-8639-7175a1956655", + "name": "hmac-generated", + "providerId": "hmac-generated", + "subComponents": {}, + "config": { + "kid": ["1b23b32b-bb69-4a9a-b20d-770d009ffb67"], + "active": ["true"], + "secretSize": ["64"], + "secret": [ + "FqB7weAN-07obv1h7cltkFANraOPiK3BN-x1fBR7BY3yF_tOVVy0faPtS24pbPB5VJMXrvZBVy4MvQbhPGOn-A" + ], + "priority": ["100"], + "enabled": ["true"], + "algorithm": ["HS256"] } - }, { - "id" : "ca06ef6c-d7f8-42c9-b0d6-0c9be85c1cc1", - "name" : "janis", - "type" : "user", - "logic" : "POSITIVE", - "decisionStrategy" : "UNANIMOUS", - "config" : { - "users" : "[\"janis@idir\"]" + }, + { + "id": "82953e3c-d927-4f6f-8b57-3b5c7b8903d6", + "name": "rsa-generated", + "providerId": "rsa-generated", + "subComponents": {}, + "config": { + "privateKey": [ + "MIIEpAIBAAKCAQEAtE+K9HXgyAM2I3gmzReAKg3ukb0LgHI00kBz79cTLX+aXjAMl5n3cajJZuVBPj+Cyy4fm4vB7tHMTcY5StOMcQv95DZvmonQkweU87quqfETLTp6607tUfUdRib5W/euaKqVbCi09xwSftBeHHCcvotFTz/IjnZ6Ul/qZcDzXgoLEiaZrKz3iSFsnuJEWiozFP+hPZNESfRz/jqd7PcD++SO1iLtMjB5BPvlB7cFWDaWww+nUPbnsqsLZzwdAzhAjYe17x2AafffkZUUp1rf5VXEz8bzAoMpRZDswhG+v1jUPg638b3LFakV6PhRTvLnoKRpPvdzLmRguXtxufrQDwIDAQABAoIBAG0CLcrPPR8OuftFl4ekbop+M74OIVb9NKvr5WuZhnGaVHQe7m302mDvnxtC/Geqs+MsNlWub4d3dOGMNnTjYmOx0UPYGS6/pMZO7iFPumrpYSOV2FxMMjO7UYBo7ZZJLjr+7ikejxFZ+mCKjmr5NfoIbtWThSeDvz3v2OC9fyRZPE/AAqsy9Gkhukxnsi4nJOBK89nLeZS1nbGPzJxu9jiNm2snWI56N7orrVW5KBR/ynaFMN5CepYqgzK5uXv9dkzjBgiQbPlXk9c+LIWrrjXFxjftJTiop6C938B1MlfamkUsoQLwG1Uh8SQNgBExFUOeegouOJthbjhhVdPe/QkCgYEA/7Y5B2Sm0S+DXfoWyHS26ZQ2fDu9WweLbnGL9KrKd4T7u5Ubu9+qTu1aU2m7RxRya9yHzzVXSiTEKPoTPCjC9CIGA3YtQxze2zf7un+RfdN0Ty9pBZiKbAavsX5+KyIliC6FQy0O48eWR7LMsVSFJGGIeYPTjgY3U34uLsN55RUCgYEAtIOQxc1AFw/wcQIsJYEZWmwUIEd49s6x6iCBXez1sfZLJVHL5mE7NNxT0vuSKwxMK4gddSoRjBDqWGgge93HlIz+N+Ln656zCdLlOlDGe5a3jvtxIRKak/mp+nmk8G+FGGlAatPIRmZQbk0hIzh0m88k8hJ7NqRXTDeDDmzmcZMCgYEAgpvOcSpF0l7UWHHepTCIJLIhSj8xLoeh/h1dAPEjTPzNnzg/3CwXzwyIsEY2881LzC/t5jY2iZZR4yQoIvgm649dRvNblwXuBkaH+vAhngUdSTzMBaGuQhMANkaHpvxf8zjftDoVet58sc5voruq7bQrgvWEXuxp4el3KUeKwSkCgYAmOa4QlPQ7bf6mj6U1k+8AfN6OL1RoP0DhqVx7vVASDWvATV/2OyTEftupU+iSARqoJTzHsM7icDqP2gz27fHzfR/gScZ+2K5lKCmufahqR3I7bvd3326oYzgheFz7JUJz9uXTOWGxtrzVfrPDt5LJ48WZFVzOJ2LtGtw/08PAzQKBgQDy/mQxGSxIImcBcjdHDP7kb5T3M69PWN/VER1AMvkU+60uQTfZ7sXsJhWQn6XgzHF9ZhpTJeeliNn9dcTFOt9sWEoLspxZNz/RoKeW2P6p1krjrz74XDOgce63AaXufAFIGUDrJhCcIbyvalEvVQyDnnWe/dHl4us/DX+/+GWjVQ==" + ], + "keySize": ["2048"], + "certificate": [ + "MIICmzCCAYMCBgF6AmA7pTANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZtYXN0ZXIwHhcNMjEwNjEyMjIzNjM5WhcNMzEwNjEyMjIzODE5WjARMQ8wDQYDVQQDDAZtYXN0ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC0T4r0deDIAzYjeCbNF4AqDe6RvQuAcjTSQHPv1xMtf5peMAyXmfdxqMlm5UE+P4LLLh+bi8Hu0cxNxjlK04xxC/3kNm+aidCTB5Tzuq6p8RMtOnrrTu1R9R1GJvlb965oqpVsKLT3HBJ+0F4ccJy+i0VPP8iOdnpSX+plwPNeCgsSJpmsrPeJIWye4kRaKjMU/6E9k0RJ9HP+Op3s9wP75I7WIu0yMHkE++UHtwVYNpbDD6dQ9ueyqwtnPB0DOECNh7XvHYBp99+RlRSnWt/lVcTPxvMCgylFkOzCEb6/WNQ+DrfxvcsVqRXo+FFO8uegpGk+93MuZGC5e3G5+tAPAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAD25ZjxPFys+OAoSmgRuk4KwpTG4cLm3vEwUjD60+gvYJk3bFUgxErNv+Ax69PN4OZwMh9fdnVHRx0haVno0ULUBintRP/P0ond1mw7HB1v/i9EMpRiVoMEL8y3wV363XVw6mDrYI8Pp0OihJBKo5I1EWgaLAl+lu9YS6f3VXaASgqx1AaV6qZiXM95FOeYkjpx30cbIR6uhRAfBHz10PO//RhTCnBrjasU921qFSMH3EuvRZET0jB68FLF7uRFK+goSVrw9O+TcK6Cbh4I4GZX66ZBRW6MTTIzYNsSuSMUlGFujGcVi5+1JmJgJg76coIo7NIR68KPKyh+47Mvy9bI=" + ], + "active": ["true"], + "priority": ["100"], + "enabled": ["true"], + "algorithm": ["RS256"] } - }, { - "id" : "c3848ff4-76b0-4f2d-afe9-7dfd77467fcb", - "name" : "group-organization-admin-ca.bc.gov-policy", - "description" : "Group '/organization-admin' / 'ca.bc.gov' Policy", - "type" : "group", - "logic" : "POSITIVE", - "decisionStrategy" : "UNANIMOUS", - "config" : { - "groups" : "[{\"path\":\"/organization-admin\",\"extendChildren\":false},{\"path\":\"/organization-admin/ca.bc.gov\",\"extendChildren\":false}]" + }, + { + "id": "4ac9540a-c5b7-48b0-b3e1-1a7887ed5414", + "name": "aes-generated", + "providerId": "aes-generated", + "subComponents": {}, + "config": { + "kid": ["8fc9ebb4-d633-4fbc-a940-43414dbb6841"], + "active": ["true"], + "secretSize": ["16"], + "secret": ["mwpmhvHuQq_qLZAKhngrjg"], + "priority": ["100"], + "enabled": ["true"] } - }, { - "id" : "6f49c571-fbbb-4f86-a72a-c1591a446bb3", - "name" : "group-organization-admin-ca.bc.gov-ministry-of-health-policy", - "description" : "Group '/organization-admin/ca.bc.gov' / 'ministry-of-health' Policy", - "type" : "group", - "logic" : "POSITIVE", - "decisionStrategy" : "UNANIMOUS", - "config" : { - "groups" : "[{\"path\":\"/organization-admin/ca.bc.gov/ministry-of-health\",\"extendChildren\":false},{\"path\":\"/organization-admin\",\"extendChildren\":false},{\"path\":\"/organization-admin/ca.bc.gov\",\"extendChildren\":false}]" + } + ] + }, + "internationalizationEnabled": false, + "supportedLocales": [], + "authenticationFlows": [ + { + "id": "fad0619f-460c-48b9-a877-f75157be2498", + "alias": "Account verification options", + "description": "Method with which to verity the existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-email-verification", + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "ALTERNATIVE", + "priority": 20, + "flowAlias": "Verify Existing Account by Re-authentication", + "userSetupAllowed": false, + "autheticatorFlow": true } - }, { - "id" : "99fdf1a9-d5ec-48c7-a2cd-1ddeb130b058", - "name" : "group-organization-admin-ca.bc.gov-ministry-of-health-planning-and-innovation-division-policy", - "description" : "Group '/organization-admin/ca.bc.gov/ministry-of-health' / 'planning-and-innovation-division' Policy", - "type" : "group", - "logic" : "POSITIVE", - "decisionStrategy" : "UNANIMOUS", - "config" : { - "groups" : "[{\"path\":\"/organization-admin/ca.bc.gov\",\"extendChildren\":false},{\"path\":\"/organization-admin/ca.bc.gov/ministry-of-health/planning-and-innovation-division\",\"extendChildren\":false},{\"path\":\"/organization-admin/ca.bc.gov/ministry-of-health\",\"extendChildren\":false},{\"path\":\"/organization-admin\",\"extendChildren\":false}]" + ] + }, + { + "id": "33504bb1-b977-4948-a6ff-3c68adf583e4", + "alias": "Authentication Options", + "description": "Authentication options.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "basic-auth", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "basic-auth-otp", + "requirement": "DISABLED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-spnego", + "requirement": "DISABLED", + "priority": 30, + "userSetupAllowed": false, + "autheticatorFlow": false } - }, { - "id" : "31be7436-e9d8-42a3-b42e-69a1869a7eea", - "name" : "Default Permission", - "description" : "A permission that applies to the default resource type", - "type" : "resource", - "logic" : "POSITIVE", - "decisionStrategy" : "UNANIMOUS", - "config" : { - "defaultResourceType" : "urn:gwa-api:resources:default", - "applyPolicies" : "[\"Default Policy\"]" + ] + }, + { + "id": "bfe57f7a-b041-4a15-be88-44894c673f24", + "alias": "Browser - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-otp-form", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false } - }, { - "id" : "65f0c0a4-e2ac-4364-800d-ebd4e11ce393", - "name" : "janis full access", - "type" : "scope", - "logic" : "POSITIVE", - "decisionStrategy" : "UNANIMOUS", - "config" : { - "scopes" : "[\"GroupAccess.Manage\",\"Namespace.Assign\"]", - "applyPolicies" : "[\"janis\"]" + ] + }, + { + "id": "377ac00d-87d0-4752-8aa0-90459e334175", + "alias": "Direct Grant - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "direct-grant-validate-otp", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false } - }, { - "id" : "854f0dfe-952d-48f8-9d53-d49b0b4ed122", - "name" : "Access to 'org/ca.bc.gov' services for role organization-admin", - "type" : "scope", - "logic" : "POSITIVE", - "decisionStrategy" : "UNANIMOUS", - "config" : { - "resources" : "[\"org/ca.bc.gov\"]", - "scopes" : "[\"GroupAccess.Manage\"]", - "applyPolicies" : "[\"group-organization-admin-ca.bc.gov-policy\"]" + ] + }, + { + "id": "23859306-7ccf-4313-9a8e-0dc39ca6749e", + "alias": "First broker login - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-otp-form", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false } - }, { - "id" : "3f934d3f-d231-48fc-9f5a-924da7808989", - "name" : "Access to 'org/ministry-of-health' services for role organization-admin", - "type" : "scope", - "logic" : "POSITIVE", - "decisionStrategy" : "UNANIMOUS", - "config" : { - "resources" : "[\"org/ministry-of-health\"]", - "scopes" : "[\"Dataset.Manage\",\"GroupAccess.Manage\",\"Namespace.Assign\"]", - "applyPolicies" : "[\"group-organization-admin-ca.bc.gov-ministry-of-health-policy\"]" + ] + }, + { + "id": "60b03eac-baf5-47e9-8e69-89c4292487fd", + "alias": "Handle Existing Account", + "description": "Handle what to do if there is existing account with same email/username like authenticated identity provider", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-confirm-link", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "REQUIRED", + "priority": 20, + "flowAlias": "Account verification options", + "userSetupAllowed": false, + "autheticatorFlow": true } - }, { - "id" : "56a4857d-a0be-472c-85d0-2dca93a1fdac", - "name" : "Access to 'org/planning-and-innovation-division' services for role organization-admin", - "type" : "scope", - "logic" : "POSITIVE", - "decisionStrategy" : "UNANIMOUS", - "config" : { - "resources" : "[\"org/planning-and-innovation-division\"]", - "scopes" : "[\"Dataset.Manage\",\"GroupAccess.Manage\",\"Namespace.Assign\"]", - "applyPolicies" : "[\"group-organization-admin-ca.bc.gov-ministry-of-health-planning-and-innovation-division-policy\"]" + ] + }, + { + "id": "2a42f367-4220-478d-bbbc-36def807b298", + "alias": "Reset - Conditional OTP", + "description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "reset-otp", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false } - }, { - "id" : "f2e764aa-c355-4e81-a5e6-e76ffb86041f", - "name" : "Access to 'platform' services for role organization-admin", - "type" : "scope", - "logic" : "POSITIVE", - "decisionStrategy" : "UNANIMOUS", - "config" : { - "resources" : "[\"platform\"]", - "scopes" : "[\"Namespace.View\"]", - "applyPolicies" : "[\"group-organization-admin-ca.bc.gov-ministry-of-health-planning-and-innovation-division-policy\"]" + ] + }, + { + "id": "6f87a5c3-1a77-456e-b649-b0adfb5c5d47", + "alias": "User creation or linking", + "description": "Flow for the existing/non-existing user alternatives", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "create unique user config", + "authenticator": "idp-create-user-if-unique", + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "ALTERNATIVE", + "priority": 20, + "flowAlias": "Handle Existing Account", + "userSetupAllowed": false, + "autheticatorFlow": true } - } ], - "scopes" : [ { - "id" : "6871ce8b-5d5f-455b-86ff-7cf5940930eb", - "name" : "Namespace.Manage" - }, { - "id" : "0006d34f-1416-4ffb-ad1f-39ebf63f9556", - "name" : "Namespace.View" - }, { - "id" : "a4d424c9-7331-4715-96a9-ecfd1dd0cf2c", - "name" : "GatewayConfig.Publish" - }, { - "id" : "fd403d7f-1dfb-4673-8ab3-5e1ff7797b35", - "name" : "Access.Manage" - }, { - "id" : "0f98e35d-c2c3-4781-bf85-478bf06cfa24", - "name" : "Content.Publish" - }, { - "id" : "dfc132ca-aa87-40b5-bc33-3e972a88f638", - "name" : "CredentialIssuer.Admin" - }, { - "id" : "95893c25-6b83-4e59-9518-a25568d95542", - "name" : "GroupAccess.Manage", - "iconUri" : "", - "displayName" : "GroupAccess.Manage" - }, { - "id" : "b0b007b1-1ecb-4b3f-9f0c-41b3fa34754c", - "name" : "Dataset.Manage" - }, { - "id" : "f3bf8d43-54a4-4594-aeea-f61b99411f92", - "name" : "Namespace.Assign" - } ], - "decisionStrategy" : "AFFIRMATIVE" - } - }, { - "id" : "4e6525e9-647c-4c80-85d6-9c13890b0ab2", - "clientId" : "master-realm", - "name" : "master Realm", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "secret" : "**********", - "redirectUris" : [ ], - "webOrigins" : [ ], - "notBefore" : 0, - "bearerOnly" : true, - "consentRequired" : false, - "standardFlowEnabled" : true, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : false, - "serviceAccountsEnabled" : false, - "publicClient" : false, - "frontchannelLogout" : false, - "protocol" : "openid-connect", - "attributes" : { }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : true, - "nodeReRegistrationTimeout" : 0, - "defaultClientScopes" : [ "web-origins", "role_list", "roles", "profile", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] - }, { - "id" : "4bbc355d-7a87-4476-9593-7f9359dc8859", - "clientId" : "sa-platform1-e0000000-5be82156d61f", - "name" : "", - "description" : "", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "secret" : "c01a7839-2679-4cdd-96c4-173223b49ee6", - "redirectUris" : [ "https://*" ], - "webOrigins" : [ "*" ], - "notBefore" : 0, - "bearerOnly" : false, - "consentRequired" : false, - "standardFlowEnabled" : false, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : false, - "serviceAccountsEnabled" : true, - "publicClient" : false, - "frontchannelLogout" : false, - "protocol" : "openid-connect", - "attributes" : { - "saml.assertion.signature" : "false", - "saml.multivalued.roles" : "false", - "saml.force.post.binding" : "false", - "saml.encrypt" : "false", - "saml.server.signature" : "false", - "saml.server.signature.keyinfo.ext" : "false", - "exclude.session.state.from.auth.response" : "false", - "client_credentials.use_refresh_token" : "false", - "saml_force_name_id_format" : "false", - "saml.client.signature" : "false", - "tls.client.certificate.bound.access.tokens" : "false", - "saml.authnstatement" : "false", - "display.on.consent.screen" : "false", - "saml.onetimeuse.condition" : "false" + ] }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : false, - "nodeReRegistrationTimeout" : -1, - "protocolMappers" : [ { - "id" : "d5b56ac0-01af-4241-991e-1cd25edeb739", - "name" : "Client ID", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usersessionmodel-note-mapper", - "consentRequired" : false, - "config" : { - "user.session.note" : "clientId", - "userinfo.token.claim" : "true", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "clientId", - "jsonType.label" : "String" - } - }, { - "id" : "8c119e4b-b308-41aa-be7b-91e1d299e499", - "name" : "Client Host", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usersessionmodel-note-mapper", - "consentRequired" : false, - "config" : { - "user.session.note" : "clientHost", - "userinfo.token.claim" : "true", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "clientHost", - "jsonType.label" : "String" - } - }, { - "id" : "3ba852b4-71b8-4942-950b-80968346b0e2", - "name" : "Client IP Address", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usersessionmodel-note-mapper", - "consentRequired" : false, - "config" : { - "user.session.note" : "clientAddress", - "userinfo.token.claim" : "true", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "clientAddress", - "jsonType.label" : "String" - } - } ], - "defaultClientScopes" : [ ], - "optionalClientScopes" : [ ] - }, { - "id" : "25ee1923-6323-4c4c-ae70-178615ace3b2", - "clientId" : "sa-platform-e0000000-fa46551361b4", - "name" : "", - "description" : "", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "secret" : "dc96e3d3-23cc-4345-aa5e-6f89b5d20c91", - "redirectUris" : [ "https://*" ], - "webOrigins" : [ "*" ], - "notBefore" : 0, - "bearerOnly" : false, - "consentRequired" : false, - "standardFlowEnabled" : false, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : false, - "serviceAccountsEnabled" : true, - "publicClient" : false, - "frontchannelLogout" : false, - "protocol" : "openid-connect", - "attributes" : { - "saml.assertion.signature" : "false", - "saml.multivalued.roles" : "false", - "saml.force.post.binding" : "false", - "saml.encrypt" : "false", - "saml.server.signature" : "false", - "saml.server.signature.keyinfo.ext" : "false", - "exclude.session.state.from.auth.response" : "false", - "client_credentials.use_refresh_token" : "false", - "saml_force_name_id_format" : "false", - "saml.client.signature" : "false", - "tls.client.certificate.bound.access.tokens" : "false", - "saml.authnstatement" : "false", - "display.on.consent.screen" : "false", - "saml.onetimeuse.condition" : "false" + { + "id": "2262356b-b4ab-4d1c-beb4-267198ce85ef", + "alias": "Verify Existing Account by Re-authentication", + "description": "Reauthentication of existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-username-password-form", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "CONDITIONAL", + "priority": 20, + "flowAlias": "First broker login - Conditional OTP", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : false, - "nodeReRegistrationTimeout" : -1, - "protocolMappers" : [ { - "id" : "270af568-11bf-4208-bccd-58583e44f09c", - "name" : "Client IP Address", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usersessionmodel-note-mapper", - "consentRequired" : false, - "config" : { - "user.session.note" : "clientAddress", - "userinfo.token.claim" : "true", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "clientAddress", - "jsonType.label" : "String" - } - }, { - "id" : "9dda9072-1e47-43fd-a482-6830b252ca5b", - "name" : "Client Host", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usersessionmodel-note-mapper", - "consentRequired" : false, - "config" : { - "user.session.note" : "clientHost", - "userinfo.token.claim" : "true", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "clientHost", - "jsonType.label" : "String" - } - }, { - "id" : "a35858ac-39ad-46bc-9227-e40698049c62", - "name" : "Client ID", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usersessionmodel-note-mapper", - "consentRequired" : false, - "config" : { - "user.session.note" : "clientId", - "userinfo.token.claim" : "true", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "clientId", - "jsonType.label" : "String" - } - } ], - "defaultClientScopes" : [ ], - "optionalClientScopes" : [ ] - }, { - "id" : "5c797848-2f03-4085-a03a-e4f7c22d0050", - "clientId" : "security-admin-console", - "name" : "${client_security-admin-console}", - "rootUrl" : "${authAdminUrl}", - "baseUrl" : "/admin/master/console/", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "secret" : "**********", - "redirectUris" : [ "/admin/master/console/*" ], - "webOrigins" : [ "+" ], - "notBefore" : 0, - "bearerOnly" : false, - "consentRequired" : false, - "standardFlowEnabled" : true, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : false, - "serviceAccountsEnabled" : false, - "publicClient" : true, - "frontchannelLogout" : false, - "protocol" : "openid-connect", - "attributes" : { - "pkce.code.challenge.method" : "S256" + { + "id": "9a82a84c-49be-427c-8d4e-e193a4d7a353", + "alias": "browser", + "description": "browser based authentication", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-cookie", + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-spnego", + "requirement": "DISABLED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "identity-provider-redirector", + "requirement": "ALTERNATIVE", + "priority": 25, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "ALTERNATIVE", + "priority": 30, + "flowAlias": "forms", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : false, - "nodeReRegistrationTimeout" : 0, - "protocolMappers" : [ { - "id" : "c5b453d6-73e5-40f2-bc65-375b571f7d6c", - "name" : "locale", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "locale", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "locale", - "jsonType.label" : "String" - } - } ], - "defaultClientScopes" : [ "web-origins", "role_list", "roles", "profile", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] - } ], - "clientScopes" : [ { - "id" : "f5d4d8e2-6e57-477a-83b0-88047af5285d", - "name" : "Content.Publish", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "true", - "display.on.consent.screen" : "true" - } - }, { - "id" : "4f7a31ce-a48b-4816-baff-4dbc378d4a10", - "name" : "Namespace.Admin", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "true", - "display.on.consent.screen" : "true" - } - }, { - "id" : "5c280525-34b7-4436-a567-ad5a75f0b093", - "name" : "Namespace.Create", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "true", - "display.on.consent.screen" : "true" - } - }, { - "id" : "e78e5fd1-5ee2-4215-a5c3-a8581a19c716", - "name" : "address", - "description" : "OpenID Connect built-in scope: address", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "true", - "display.on.consent.screen" : "true", - "consent.screen.text" : "${addressScopeConsentText}" + { + "id": "de2f29cf-ac12-4c88-b2e3-bb1e061dd013", + "alias": "clients", + "description": "Base authentication for clients", + "providerId": "client-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "client-secret", + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "client-jwt", + "requirement": "ALTERNATIVE", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "client-secret-jwt", + "requirement": "ALTERNATIVE", + "priority": 30, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "client-x509", + "requirement": "ALTERNATIVE", + "priority": 40, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] }, - "protocolMappers" : [ { - "id" : "b2a36609-2408-44fd-88ac-ef41fa62f5f4", - "name" : "address", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-address-mapper", - "consentRequired" : false, - "config" : { - "user.attribute.formatted" : "formatted", - "user.attribute.country" : "country", - "user.attribute.postal_code" : "postal_code", - "userinfo.token.claim" : "true", - "user.attribute.street" : "street", - "id.token.claim" : "true", - "user.attribute.region" : "region", - "access.token.claim" : "true", - "user.attribute.locality" : "locality" - } - } ] - }, { - "id" : "89e870cc-7056-4bc0-8cf2-9c961ff4a62d", - "name" : "email", - "description" : "OpenID Connect built-in scope: email", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "true", - "display.on.consent.screen" : "true", - "consent.screen.text" : "${emailScopeConsentText}" + { + "id": "79023955-88dd-4230-9185-9aee45846718", + "alias": "direct grant", + "description": "OpenID Connect Resource Owner Grant", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "direct-grant-validate-username", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "direct-grant-validate-password", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "CONDITIONAL", + "priority": 30, + "flowAlias": "Direct Grant - Conditional OTP", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] }, - "protocolMappers" : [ { - "id" : "7fb89890-a73f-4162-9ca3-e1539905ccb6", - "name" : "email verified", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-property-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "emailVerified", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "email_verified", - "jsonType.label" : "boolean" - } - }, { - "id" : "9ec60f35-65c9-4ea2-ab0e-2fc2c462d892", - "name" : "email", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-property-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "email", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "email", - "jsonType.label" : "String" - } - } ] - }, { - "id" : "920764e0-6019-462b-bc25-f17a54562752", - "name" : "microprofile-jwt", - "description" : "Microprofile - JWT built-in scope", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "true", - "display.on.consent.screen" : "false" + { + "id": "bcb59a24-d9e3-449a-95a8-cb8e39dbda09", + "alias": "docker auth", + "description": "Used by Docker clients to authenticate against the IDP", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "docker-http-basic-authenticator", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] }, - "protocolMappers" : [ { - "id" : "cd9090fd-faf4-450a-9144-3a9e04260095", - "name" : "groups", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-realm-role-mapper", - "consentRequired" : false, - "config" : { - "multivalued" : "true", - "userinfo.token.claim" : "true", - "user.attribute" : "foo", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "groups", - "jsonType.label" : "String" - } - }, { - "id" : "9ca3b431-06e3-43f0-9277-a6dec6ec1172", - "name" : "upn", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-property-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "username", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "upn", - "jsonType.label" : "String" - } - } ] - }, { - "id" : "bb473906-0c39-4af1-aad9-d8788dc7559f", - "name" : "offline_access", - "description" : "OpenID Connect built-in scope: offline_access", - "protocol" : "openid-connect", - "attributes" : { - "consent.screen.text" : "${offlineAccessScopeConsentText}", - "display.on.consent.screen" : "true" - } - }, { - "id" : "e5e16f12-1b4c-47e7-9599-99ff395f359c", - "name" : "phone", - "description" : "OpenID Connect built-in scope: phone", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "true", - "display.on.consent.screen" : "true", - "consent.screen.text" : "${phoneScopeConsentText}" + { + "id": "4891506e-c7be-495b-b3c6-be1024e56f03", + "alias": "first broker login", + "description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "review profile config", + "authenticator": "idp-review-profile", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "REQUIRED", + "priority": 20, + "flowAlias": "User creation or linking", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] }, - "protocolMappers" : [ { - "id" : "8d83aa08-43a9-49f5-b1dd-caa144e2cad5", - "name" : "phone number", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "phoneNumber", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "phone_number", - "jsonType.label" : "String" - } - }, { - "id" : "3886e58f-d64f-4851-80f3-ae7cc5c6ab13", - "name" : "phone number verified", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "phoneNumberVerified", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "phone_number_verified", - "jsonType.label" : "boolean" - } - } ] - }, { - "id" : "f33d0489-2a52-4066-9c38-e130c02665ee", - "name" : "profile", - "description" : "OpenID Connect built-in scope: profile", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "true", - "display.on.consent.screen" : "true", - "consent.screen.text" : "${profileScopeConsentText}" + { + "id": "f166a866-5a3c-493b-8c86-e3c7147c57ae", + "alias": "forms", + "description": "Username, password, otp and other auth forms.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-username-password-form", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "CONDITIONAL", + "priority": 20, + "flowAlias": "Browser - Conditional OTP", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] }, - "protocolMappers" : [ { - "id" : "1826e2b1-380a-4c65-a73e-3bb79f519550", - "name" : "website", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "website", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "website", - "jsonType.label" : "String" - } - }, { - "id" : "6ea0a08a-ab42-4b45-acfc-a05f5b452cb0", - "name" : "nickname", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "nickname", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "nickname", - "jsonType.label" : "String" - } - }, { - "id" : "78d97855-5557-4f10-9d20-74d8ea6bdfef", - "name" : "full name", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-full-name-mapper", - "consentRequired" : false, - "config" : { - "id.token.claim" : "true", - "access.token.claim" : "true", - "userinfo.token.claim" : "true" - } - }, { - "id" : "22e60a23-914f-40bf-960d-e7a96655581d", - "name" : "picture", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "picture", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "picture", - "jsonType.label" : "String" - } - }, { - "id" : "e595c828-c815-4dff-bd8f-39b1eee5a3b3", - "name" : "birthdate", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "birthdate", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "birthdate", - "jsonType.label" : "String" - } - }, { - "id" : "cd91c70b-0856-4f5d-aeb6-9b5c3b48a966", - "name" : "zoneinfo", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "zoneinfo", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "zoneinfo", - "jsonType.label" : "String" - } - }, { - "id" : "4ce90553-d828-4146-92e0-ee1775c9ba28", - "name" : "updated at", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "updatedAt", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "updated_at", - "jsonType.label" : "String" - } - }, { - "id" : "43710808-227e-4171-a106-7576f933a32b", - "name" : "family name", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-property-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "lastName", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "family_name", - "jsonType.label" : "String" - } - }, { - "id" : "a814d5c0-bdcd-4f33-8cfd-228005f2ba94", - "name" : "gender", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "gender", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "gender", - "jsonType.label" : "String" - } - }, { - "id" : "df9e1465-617d-4a7b-a208-7354c6cbaada", - "name" : "locale", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "locale", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "locale", - "jsonType.label" : "String" - } - }, { - "id" : "fc508e60-a978-41f1-bea2-311673b4b0a8", - "name" : "given name", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-property-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "firstName", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "given_name", - "jsonType.label" : "String" - } - }, { - "id" : "8e4641a3-87d3-4958-8113-dcfa82f0ef54", - "name" : "middle name", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "middleName", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "middle_name", - "jsonType.label" : "String" - } - }, { - "id" : "ffc38939-9e10-4cf3-b4fc-65203e079a92", - "name" : "username", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-property-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "username", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "preferred_username", - "jsonType.label" : "String" - } - }, { - "id" : "9364fe99-268a-4a74-88aa-a120a6897e78", - "name" : "profile", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "profile", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "profile", - "jsonType.label" : "String" - } - } ] - }, { - "id" : "b5a38584-219b-4618-a3a5-70814bed867e", - "name" : "role_list", - "description" : "SAML role list", - "protocol" : "saml", - "attributes" : { - "consent.screen.text" : "${samlRoleListScopeConsentText}", - "display.on.consent.screen" : "true" + { + "id": "a8c90847-b4e1-41ad-85dd-fc189700c205", + "alias": "http challenge", + "description": "An authentication flow based on challenge-response HTTP Authentication Schemes", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "no-cookie-redirect", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "REQUIRED", + "priority": 20, + "flowAlias": "Authentication Options", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] }, - "protocolMappers" : [ { - "id" : "1a0a5251-1b3f-47b1-8cc1-07a285d6479f", - "name" : "role list", - "protocol" : "saml", - "protocolMapper" : "saml-role-list-mapper", - "consentRequired" : false, - "config" : { - "single" : "false", - "attribute.nameformat" : "Basic", - "attribute.name" : "Role" - } - } ] - }, { - "id" : "33bd4c0f-225f-43cb-8b6c-0bd4db702525", - "name" : "roles", - "description" : "OpenID Connect scope for add user roles to the access token", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "false", - "display.on.consent.screen" : "true", - "consent.screen.text" : "${rolesScopeConsentText}" + { + "id": "b19038dd-3c7c-4352-8789-2086c56287bc", + "alias": "registration", + "description": "registration flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-page-form", + "requirement": "REQUIRED", + "priority": 10, + "flowAlias": "registration form", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] }, - "protocolMappers" : [ { - "id" : "e276a79b-99cc-4f10-8d26-0e10ce245fdb", - "name" : "client roles", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-client-role-mapper", - "consentRequired" : false, - "config" : { - "user.attribute" : "foo", - "access.token.claim" : "true", - "claim.name" : "resource_access.${client_id}.roles", - "jsonType.label" : "String", - "multivalued" : "true" - } - }, { - "id" : "b64cc3a2-8ed8-4dee-a13a-fef5588a5949", - "name" : "realm roles", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-realm-role-mapper", - "consentRequired" : false, - "config" : { - "user.attribute" : "foo", - "access.token.claim" : "true", - "claim.name" : "realm_access.roles", - "jsonType.label" : "String", - "multivalued" : "true" - } - }, { - "id" : "c9828318-6d78-4aba-94ea-405f12fce589", - "name" : "audience resolve", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-audience-resolve-mapper", - "consentRequired" : false, - "config" : { } - } ] - }, { - "id" : "0bfddcf3-017d-44b6-8447-297c565d5d2d", - "name" : "web-origins", - "description" : "OpenID Connect scope for add allowed web origins to the access token", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "false", - "display.on.consent.screen" : "false", - "consent.screen.text" : "" + { + "id": "017a3853-ce82-42d5-916f-69af01d60b75", + "alias": "registration form", + "description": "registration form", + "providerId": "form-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-user-creation", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-profile-action", + "requirement": "REQUIRED", + "priority": 40, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-password-action", + "requirement": "REQUIRED", + "priority": 50, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-recaptcha-action", + "requirement": "DISABLED", + "priority": 60, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] }, - "protocolMappers" : [ { - "id" : "28867dcd-803d-47a5-be90-51be8a331527", - "name" : "allowed web origins", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-allowed-origins-mapper", - "consentRequired" : false, - "config" : { } - } ] - }, { - "id" : "e28fac82-4db1-4900-8096-74706a71f7f3", - "name" : "System.Write", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "true", - "display.on.consent.screen" : "true" + { + "id": "7e37f103-3f7a-4105-9804-194d8758038e", + "alias": "reset credentials", + "description": "Reset credentials for a user if they forgot their password or something", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "reset-credentials-choose-user", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "reset-credential-email", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "reset-password", + "requirement": "REQUIRED", + "priority": 30, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "CONDITIONAL", + "priority": 40, + "flowAlias": "Reset - Conditional OTP", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "c4a172b7-12f7-4472-8cd7-032376527d0f", + "alias": "saml ecp", + "description": "SAML ECP Profile Authentication Flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "http-basic-authenticator", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] } - } ], - "defaultDefaultClientScopes" : [ "web-origins", "roles", "Namespace.Admin", "Namespace.Create", "email", "role_list", "profile" ], - "defaultOptionalClientScopes" : [ "microprofile-jwt", "offline_access", "phone", "address" ], - "browserSecurityHeaders" : { - "contentSecurityPolicyReportOnly" : "", - "xContentTypeOptions" : "nosniff", - "xRobotsTag" : "none", - "xFrameOptions" : "SAMEORIGIN", - "contentSecurityPolicy" : "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", - "xXSSProtection" : "1; mode=block", - "strictTransportSecurity" : "max-age=31536000; includeSubDomains" - }, - "smtpServer" : { }, - "eventsEnabled" : false, - "eventsListeners" : [ "jboss-logging" ], - "enabledEventTypes" : [ ], - "adminEventsEnabled" : false, - "adminEventsDetailsEnabled" : false, - "components" : { - "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy" : [ { - "id" : "d7699c96-1cc0-46fe-b0fe-c72c7f7d1804", - "name" : "Consent Required", - "providerId" : "consent-required", - "subType" : "anonymous", - "subComponents" : { }, - "config" : { } - }, { - "id" : "522f0c4c-8dfe-4421-b573-0e5723319dac", - "name" : "Allowed Client Scopes", - "providerId" : "allowed-client-templates", - "subType" : "authenticated", - "subComponents" : { }, - "config" : { - "allow-default-scopes" : [ "true" ] - } - }, { - "id" : "2502109c-1319-4bcd-bf94-a5225239c42b", - "name" : "Allowed Protocol Mapper Types", - "providerId" : "allowed-protocol-mappers", - "subType" : "anonymous", - "subComponents" : { }, - "config" : { - "allowed-protocol-mapper-types" : [ "oidc-full-name-mapper", "saml-user-property-mapper", "oidc-sha256-pairwise-sub-mapper", "saml-user-attribute-mapper", "oidc-usermodel-attribute-mapper", "oidc-address-mapper", "saml-role-list-mapper", "oidc-usermodel-property-mapper" ] - } - }, { - "id" : "013bd2ad-80e7-40fe-ba41-b90642d536cd", - "name" : "Trusted Hosts", - "providerId" : "trusted-hosts", - "subType" : "anonymous", - "subComponents" : { }, - "config" : { - "host-sending-registration-request-must-match" : [ "true" ], - "client-uris-must-match" : [ "true" ] - } - }, { - "id" : "c0bcf5a2-ef5f-4f03-95c7-ea15f27c8cd7", - "name" : "Allowed Client Scopes", - "providerId" : "allowed-client-templates", - "subType" : "anonymous", - "subComponents" : { }, - "config" : { - "allow-default-scopes" : [ "true" ] - } - }, { - "id" : "1157f7fe-a055-4ec3-8af8-3f809fd2fec0", - "name" : "Full Scope Disabled", - "providerId" : "scope", - "subType" : "anonymous", - "subComponents" : { }, - "config" : { } - }, { - "id" : "650e6c8f-8a93-4096-9d37-1aecfe000e49", - "name" : "Max Clients Limit", - "providerId" : "max-clients", - "subType" : "anonymous", - "subComponents" : { }, - "config" : { - "max-clients" : [ "200" ] + ], + "authenticatorConfig": [ + { + "id": "b6a50f4b-4bec-4036-b796-d5a0ac12f0e7", + "alias": "create unique user config", + "config": { + "require.password.update.after.registration": "false" } - }, { - "id" : "93e21f15-c390-475a-865a-3f8125b1ccc9", - "name" : "Allowed Protocol Mapper Types", - "providerId" : "allowed-protocol-mappers", - "subType" : "authenticated", - "subComponents" : { }, - "config" : { - "allowed-protocol-mapper-types" : [ "oidc-usermodel-property-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-address-mapper", "saml-role-list-mapper", "saml-user-property-mapper", "oidc-full-name-mapper", "saml-user-attribute-mapper", "oidc-usermodel-attribute-mapper" ] - } - } ], - "org.keycloak.keys.KeyProvider" : [ { - "id" : "2b0c7bcb-c441-4694-8639-7175a1956655", - "name" : "hmac-generated", - "providerId" : "hmac-generated", - "subComponents" : { }, - "config" : { - "kid" : [ "1b23b32b-bb69-4a9a-b20d-770d009ffb67" ], - "active" : [ "true" ], - "secretSize" : [ "64" ], - "secret" : [ "FqB7weAN-07obv1h7cltkFANraOPiK3BN-x1fBR7BY3yF_tOVVy0faPtS24pbPB5VJMXrvZBVy4MvQbhPGOn-A" ], - "priority" : [ "100" ], - "enabled" : [ "true" ], - "algorithm" : [ "HS256" ] - } - }, { - "id" : "82953e3c-d927-4f6f-8b57-3b5c7b8903d6", - "name" : "rsa-generated", - "providerId" : "rsa-generated", - "subComponents" : { }, - "config" : { - "privateKey" : [ "MIIEpAIBAAKCAQEAtE+K9HXgyAM2I3gmzReAKg3ukb0LgHI00kBz79cTLX+aXjAMl5n3cajJZuVBPj+Cyy4fm4vB7tHMTcY5StOMcQv95DZvmonQkweU87quqfETLTp6607tUfUdRib5W/euaKqVbCi09xwSftBeHHCcvotFTz/IjnZ6Ul/qZcDzXgoLEiaZrKz3iSFsnuJEWiozFP+hPZNESfRz/jqd7PcD++SO1iLtMjB5BPvlB7cFWDaWww+nUPbnsqsLZzwdAzhAjYe17x2AafffkZUUp1rf5VXEz8bzAoMpRZDswhG+v1jUPg638b3LFakV6PhRTvLnoKRpPvdzLmRguXtxufrQDwIDAQABAoIBAG0CLcrPPR8OuftFl4ekbop+M74OIVb9NKvr5WuZhnGaVHQe7m302mDvnxtC/Geqs+MsNlWub4d3dOGMNnTjYmOx0UPYGS6/pMZO7iFPumrpYSOV2FxMMjO7UYBo7ZZJLjr+7ikejxFZ+mCKjmr5NfoIbtWThSeDvz3v2OC9fyRZPE/AAqsy9Gkhukxnsi4nJOBK89nLeZS1nbGPzJxu9jiNm2snWI56N7orrVW5KBR/ynaFMN5CepYqgzK5uXv9dkzjBgiQbPlXk9c+LIWrrjXFxjftJTiop6C938B1MlfamkUsoQLwG1Uh8SQNgBExFUOeegouOJthbjhhVdPe/QkCgYEA/7Y5B2Sm0S+DXfoWyHS26ZQ2fDu9WweLbnGL9KrKd4T7u5Ubu9+qTu1aU2m7RxRya9yHzzVXSiTEKPoTPCjC9CIGA3YtQxze2zf7un+RfdN0Ty9pBZiKbAavsX5+KyIliC6FQy0O48eWR7LMsVSFJGGIeYPTjgY3U34uLsN55RUCgYEAtIOQxc1AFw/wcQIsJYEZWmwUIEd49s6x6iCBXez1sfZLJVHL5mE7NNxT0vuSKwxMK4gddSoRjBDqWGgge93HlIz+N+Ln656zCdLlOlDGe5a3jvtxIRKak/mp+nmk8G+FGGlAatPIRmZQbk0hIzh0m88k8hJ7NqRXTDeDDmzmcZMCgYEAgpvOcSpF0l7UWHHepTCIJLIhSj8xLoeh/h1dAPEjTPzNnzg/3CwXzwyIsEY2881LzC/t5jY2iZZR4yQoIvgm649dRvNblwXuBkaH+vAhngUdSTzMBaGuQhMANkaHpvxf8zjftDoVet58sc5voruq7bQrgvWEXuxp4el3KUeKwSkCgYAmOa4QlPQ7bf6mj6U1k+8AfN6OL1RoP0DhqVx7vVASDWvATV/2OyTEftupU+iSARqoJTzHsM7icDqP2gz27fHzfR/gScZ+2K5lKCmufahqR3I7bvd3326oYzgheFz7JUJz9uXTOWGxtrzVfrPDt5LJ48WZFVzOJ2LtGtw/08PAzQKBgQDy/mQxGSxIImcBcjdHDP7kb5T3M69PWN/VER1AMvkU+60uQTfZ7sXsJhWQn6XgzHF9ZhpTJeeliNn9dcTFOt9sWEoLspxZNz/RoKeW2P6p1krjrz74XDOgce63AaXufAFIGUDrJhCcIbyvalEvVQyDnnWe/dHl4us/DX+/+GWjVQ==" ], - "keySize" : [ "2048" ], - "certificate" : [ "MIICmzCCAYMCBgF6AmA7pTANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZtYXN0ZXIwHhcNMjEwNjEyMjIzNjM5WhcNMzEwNjEyMjIzODE5WjARMQ8wDQYDVQQDDAZtYXN0ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC0T4r0deDIAzYjeCbNF4AqDe6RvQuAcjTSQHPv1xMtf5peMAyXmfdxqMlm5UE+P4LLLh+bi8Hu0cxNxjlK04xxC/3kNm+aidCTB5Tzuq6p8RMtOnrrTu1R9R1GJvlb965oqpVsKLT3HBJ+0F4ccJy+i0VPP8iOdnpSX+plwPNeCgsSJpmsrPeJIWye4kRaKjMU/6E9k0RJ9HP+Op3s9wP75I7WIu0yMHkE++UHtwVYNpbDD6dQ9ueyqwtnPB0DOECNh7XvHYBp99+RlRSnWt/lVcTPxvMCgylFkOzCEb6/WNQ+DrfxvcsVqRXo+FFO8uegpGk+93MuZGC5e3G5+tAPAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAD25ZjxPFys+OAoSmgRuk4KwpTG4cLm3vEwUjD60+gvYJk3bFUgxErNv+Ax69PN4OZwMh9fdnVHRx0haVno0ULUBintRP/P0ond1mw7HB1v/i9EMpRiVoMEL8y3wV363XVw6mDrYI8Pp0OihJBKo5I1EWgaLAl+lu9YS6f3VXaASgqx1AaV6qZiXM95FOeYkjpx30cbIR6uhRAfBHz10PO//RhTCnBrjasU921qFSMH3EuvRZET0jB68FLF7uRFK+goSVrw9O+TcK6Cbh4I4GZX66ZBRW6MTTIzYNsSuSMUlGFujGcVi5+1JmJgJg76coIo7NIR68KPKyh+47Mvy9bI=" ], - "active" : [ "true" ], - "priority" : [ "100" ], - "enabled" : [ "true" ], - "algorithm" : [ "RS256" ] - } - }, { - "id" : "4ac9540a-c5b7-48b0-b3e1-1a7887ed5414", - "name" : "aes-generated", - "providerId" : "aes-generated", - "subComponents" : { }, - "config" : { - "kid" : [ "8fc9ebb4-d633-4fbc-a940-43414dbb6841" ], - "active" : [ "true" ], - "secretSize" : [ "16" ], - "secret" : [ "mwpmhvHuQq_qLZAKhngrjg" ], - "priority" : [ "100" ], - "enabled" : [ "true" ] + }, + { + "id": "1df3203a-ba48-4a72-b851-bb5bc25f33cf", + "alias": "review profile config", + "config": { + "update.profile.on.first.login": "missing" } - } ] - }, - "internationalizationEnabled" : false, - "supportedLocales" : [ ], - "authenticationFlows" : [ { - "id" : "fad0619f-460c-48b9-a877-f75157be2498", - "alias" : "Account verification options", - "description" : "Method with which to verity the existing account", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "idp-email-verification", - "requirement" : "ALTERNATIVE", - "priority" : 10, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "requirement" : "ALTERNATIVE", - "priority" : 20, - "flowAlias" : "Verify Existing Account by Re-authentication", - "userSetupAllowed" : false, - "autheticatorFlow" : true - } ] - }, { - "id" : "33504bb1-b977-4948-a6ff-3c68adf583e4", - "alias" : "Authentication Options", - "description" : "Authentication options.", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "basic-auth", - "requirement" : "REQUIRED", - "priority" : 10, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "authenticator" : "basic-auth-otp", - "requirement" : "DISABLED", - "priority" : 20, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "authenticator" : "auth-spnego", - "requirement" : "DISABLED", - "priority" : 30, - "userSetupAllowed" : false, - "autheticatorFlow" : false - } ] - }, { - "id" : "bfe57f7a-b041-4a15-be88-44894c673f24", - "alias" : "Browser - Conditional OTP", - "description" : "Flow to determine if the OTP is required for the authentication", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "conditional-user-configured", - "requirement" : "REQUIRED", - "priority" : 10, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "authenticator" : "auth-otp-form", - "requirement" : "REQUIRED", - "priority" : 20, - "userSetupAllowed" : false, - "autheticatorFlow" : false - } ] - }, { - "id" : "377ac00d-87d0-4752-8aa0-90459e334175", - "alias" : "Direct Grant - Conditional OTP", - "description" : "Flow to determine if the OTP is required for the authentication", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "conditional-user-configured", - "requirement" : "REQUIRED", - "priority" : 10, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "authenticator" : "direct-grant-validate-otp", - "requirement" : "REQUIRED", - "priority" : 20, - "userSetupAllowed" : false, - "autheticatorFlow" : false - } ] - }, { - "id" : "23859306-7ccf-4313-9a8e-0dc39ca6749e", - "alias" : "First broker login - Conditional OTP", - "description" : "Flow to determine if the OTP is required for the authentication", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "conditional-user-configured", - "requirement" : "REQUIRED", - "priority" : 10, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "authenticator" : "auth-otp-form", - "requirement" : "REQUIRED", - "priority" : 20, - "userSetupAllowed" : false, - "autheticatorFlow" : false - } ] - }, { - "id" : "60b03eac-baf5-47e9-8e69-89c4292487fd", - "alias" : "Handle Existing Account", - "description" : "Handle what to do if there is existing account with same email/username like authenticated identity provider", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "idp-confirm-link", - "requirement" : "REQUIRED", - "priority" : 10, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "requirement" : "REQUIRED", - "priority" : 20, - "flowAlias" : "Account verification options", - "userSetupAllowed" : false, - "autheticatorFlow" : true - } ] - }, { - "id" : "2a42f367-4220-478d-bbbc-36def807b298", - "alias" : "Reset - Conditional OTP", - "description" : "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "conditional-user-configured", - "requirement" : "REQUIRED", - "priority" : 10, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "authenticator" : "reset-otp", - "requirement" : "REQUIRED", - "priority" : 20, - "userSetupAllowed" : false, - "autheticatorFlow" : false - } ] - }, { - "id" : "6f87a5c3-1a77-456e-b649-b0adfb5c5d47", - "alias" : "User creation or linking", - "description" : "Flow for the existing/non-existing user alternatives", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticatorConfig" : "create unique user config", - "authenticator" : "idp-create-user-if-unique", - "requirement" : "ALTERNATIVE", - "priority" : 10, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "requirement" : "ALTERNATIVE", - "priority" : 20, - "flowAlias" : "Handle Existing Account", - "userSetupAllowed" : false, - "autheticatorFlow" : true - } ] - }, { - "id" : "2262356b-b4ab-4d1c-beb4-267198ce85ef", - "alias" : "Verify Existing Account by Re-authentication", - "description" : "Reauthentication of existing account", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "idp-username-password-form", - "requirement" : "REQUIRED", - "priority" : 10, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "requirement" : "CONDITIONAL", - "priority" : 20, - "flowAlias" : "First broker login - Conditional OTP", - "userSetupAllowed" : false, - "autheticatorFlow" : true - } ] - }, { - "id" : "9a82a84c-49be-427c-8d4e-e193a4d7a353", - "alias" : "browser", - "description" : "browser based authentication", - "providerId" : "basic-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "auth-cookie", - "requirement" : "ALTERNATIVE", - "priority" : 10, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "authenticator" : "auth-spnego", - "requirement" : "DISABLED", - "priority" : 20, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "authenticator" : "identity-provider-redirector", - "requirement" : "ALTERNATIVE", - "priority" : 25, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "requirement" : "ALTERNATIVE", - "priority" : 30, - "flowAlias" : "forms", - "userSetupAllowed" : false, - "autheticatorFlow" : true - } ] - }, { - "id" : "de2f29cf-ac12-4c88-b2e3-bb1e061dd013", - "alias" : "clients", - "description" : "Base authentication for clients", - "providerId" : "client-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "client-secret", - "requirement" : "ALTERNATIVE", - "priority" : 10, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "authenticator" : "client-jwt", - "requirement" : "ALTERNATIVE", - "priority" : 20, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "authenticator" : "client-secret-jwt", - "requirement" : "ALTERNATIVE", - "priority" : 30, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "authenticator" : "client-x509", - "requirement" : "ALTERNATIVE", - "priority" : 40, - "userSetupAllowed" : false, - "autheticatorFlow" : false - } ] - }, { - "id" : "79023955-88dd-4230-9185-9aee45846718", - "alias" : "direct grant", - "description" : "OpenID Connect Resource Owner Grant", - "providerId" : "basic-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "direct-grant-validate-username", - "requirement" : "REQUIRED", - "priority" : 10, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "authenticator" : "direct-grant-validate-password", - "requirement" : "REQUIRED", - "priority" : 20, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "requirement" : "CONDITIONAL", - "priority" : 30, - "flowAlias" : "Direct Grant - Conditional OTP", - "userSetupAllowed" : false, - "autheticatorFlow" : true - } ] - }, { - "id" : "bcb59a24-d9e3-449a-95a8-cb8e39dbda09", - "alias" : "docker auth", - "description" : "Used by Docker clients to authenticate against the IDP", - "providerId" : "basic-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "docker-http-basic-authenticator", - "requirement" : "REQUIRED", - "priority" : 10, - "userSetupAllowed" : false, - "autheticatorFlow" : false - } ] - }, { - "id" : "4891506e-c7be-495b-b3c6-be1024e56f03", - "alias" : "first broker login", - "description" : "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", - "providerId" : "basic-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticatorConfig" : "review profile config", - "authenticator" : "idp-review-profile", - "requirement" : "REQUIRED", - "priority" : 10, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "requirement" : "REQUIRED", - "priority" : 20, - "flowAlias" : "User creation or linking", - "userSetupAllowed" : false, - "autheticatorFlow" : true - } ] - }, { - "id" : "f166a866-5a3c-493b-8c86-e3c7147c57ae", - "alias" : "forms", - "description" : "Username, password, otp and other auth forms.", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "auth-username-password-form", - "requirement" : "REQUIRED", - "priority" : 10, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "requirement" : "CONDITIONAL", - "priority" : 20, - "flowAlias" : "Browser - Conditional OTP", - "userSetupAllowed" : false, - "autheticatorFlow" : true - } ] - }, { - "id" : "a8c90847-b4e1-41ad-85dd-fc189700c205", - "alias" : "http challenge", - "description" : "An authentication flow based on challenge-response HTTP Authentication Schemes", - "providerId" : "basic-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "no-cookie-redirect", - "requirement" : "REQUIRED", - "priority" : 10, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "requirement" : "REQUIRED", - "priority" : 20, - "flowAlias" : "Authentication Options", - "userSetupAllowed" : false, - "autheticatorFlow" : true - } ] - }, { - "id" : "b19038dd-3c7c-4352-8789-2086c56287bc", - "alias" : "registration", - "description" : "registration flow", - "providerId" : "basic-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "registration-page-form", - "requirement" : "REQUIRED", - "priority" : 10, - "flowAlias" : "registration form", - "userSetupAllowed" : false, - "autheticatorFlow" : true - } ] - }, { - "id" : "017a3853-ce82-42d5-916f-69af01d60b75", - "alias" : "registration form", - "description" : "registration form", - "providerId" : "form-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "registration-user-creation", - "requirement" : "REQUIRED", - "priority" : 20, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "authenticator" : "registration-profile-action", - "requirement" : "REQUIRED", - "priority" : 40, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "authenticator" : "registration-password-action", - "requirement" : "REQUIRED", - "priority" : 50, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "authenticator" : "registration-recaptcha-action", - "requirement" : "DISABLED", - "priority" : 60, - "userSetupAllowed" : false, - "autheticatorFlow" : false - } ] - }, { - "id" : "7e37f103-3f7a-4105-9804-194d8758038e", - "alias" : "reset credentials", - "description" : "Reset credentials for a user if they forgot their password or something", - "providerId" : "basic-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "reset-credentials-choose-user", - "requirement" : "REQUIRED", - "priority" : 10, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "authenticator" : "reset-credential-email", - "requirement" : "REQUIRED", - "priority" : 20, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "authenticator" : "reset-password", - "requirement" : "REQUIRED", - "priority" : 30, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "requirement" : "CONDITIONAL", - "priority" : 40, - "flowAlias" : "Reset - Conditional OTP", - "userSetupAllowed" : false, - "autheticatorFlow" : true - } ] - }, { - "id" : "c4a172b7-12f7-4472-8cd7-032376527d0f", - "alias" : "saml ecp", - "description" : "SAML ECP Profile Authentication Flow", - "providerId" : "basic-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "http-basic-authenticator", - "requirement" : "REQUIRED", - "priority" : 10, - "userSetupAllowed" : false, - "autheticatorFlow" : false - } ] - } ], - "authenticatorConfig" : [ { - "id" : "b6a50f4b-4bec-4036-b796-d5a0ac12f0e7", - "alias" : "create unique user config", - "config" : { - "require.password.update.after.registration" : "false" } - }, { - "id" : "1df3203a-ba48-4a72-b851-bb5bc25f33cf", - "alias" : "review profile config", - "config" : { - "update.profile.on.first.login" : "missing" + ], + "requiredActions": [ + { + "alias": "CONFIGURE_TOTP", + "name": "Configure OTP", + "providerId": "CONFIGURE_TOTP", + "enabled": true, + "defaultAction": false, + "priority": 10, + "config": {} + }, + { + "alias": "terms_and_conditions", + "name": "Terms and Conditions", + "providerId": "terms_and_conditions", + "enabled": false, + "defaultAction": false, + "priority": 20, + "config": {} + }, + { + "alias": "UPDATE_PASSWORD", + "name": "Update Password", + "providerId": "UPDATE_PASSWORD", + "enabled": true, + "defaultAction": false, + "priority": 30, + "config": {} + }, + { + "alias": "UPDATE_PROFILE", + "name": "Update Profile", + "providerId": "UPDATE_PROFILE", + "enabled": true, + "defaultAction": false, + "priority": 40, + "config": {} + }, + { + "alias": "VERIFY_EMAIL", + "name": "Verify Email", + "providerId": "VERIFY_EMAIL", + "enabled": true, + "defaultAction": false, + "priority": 50, + "config": {} + }, + { + "alias": "update_user_locale", + "name": "Update User Locale", + "providerId": "update_user_locale", + "enabled": true, + "defaultAction": false, + "priority": 1000, + "config": {} } - } ], - "requiredActions" : [ { - "alias" : "CONFIGURE_TOTP", - "name" : "Configure OTP", - "providerId" : "CONFIGURE_TOTP", - "enabled" : true, - "defaultAction" : false, - "priority" : 10, - "config" : { } - }, { - "alias" : "terms_and_conditions", - "name" : "Terms and Conditions", - "providerId" : "terms_and_conditions", - "enabled" : false, - "defaultAction" : false, - "priority" : 20, - "config" : { } - }, { - "alias" : "UPDATE_PASSWORD", - "name" : "Update Password", - "providerId" : "UPDATE_PASSWORD", - "enabled" : true, - "defaultAction" : false, - "priority" : 30, - "config" : { } - }, { - "alias" : "UPDATE_PROFILE", - "name" : "Update Profile", - "providerId" : "UPDATE_PROFILE", - "enabled" : true, - "defaultAction" : false, - "priority" : 40, - "config" : { } - }, { - "alias" : "VERIFY_EMAIL", - "name" : "Verify Email", - "providerId" : "VERIFY_EMAIL", - "enabled" : true, - "defaultAction" : false, - "priority" : 50, - "config" : { } - }, { - "alias" : "update_user_locale", - "name" : "Update User Locale", - "providerId" : "update_user_locale", - "enabled" : true, - "defaultAction" : false, - "priority" : 1000, - "config" : { } - } ], - "browserFlow" : "browser", - "registrationFlow" : "registration", - "directGrantFlow" : "direct grant", - "resetCredentialsFlow" : "reset credentials", - "clientAuthenticationFlow" : "clients", - "dockerAuthenticationFlow" : "docker auth", - "attributes" : { - "clientOfflineSessionMaxLifespan" : "0", - "clientSessionIdleTimeout" : "0", - "clientSessionMaxLifespan" : "0", - "clientOfflineSessionIdleTimeout" : "0" + ], + "browserFlow": "browser", + "registrationFlow": "registration", + "directGrantFlow": "direct grant", + "resetCredentialsFlow": "reset credentials", + "clientAuthenticationFlow": "clients", + "dockerAuthenticationFlow": "docker auth", + "attributes": { + "clientOfflineSessionMaxLifespan": "0", + "clientSessionIdleTimeout": "0", + "clientSessionMaxLifespan": "0", + "clientOfflineSessionIdleTimeout": "0" }, - "keycloakVersion" : "11.0.3", - "userManagedAccessAllowed" : true -} \ No newline at end of file + "keycloakVersion": "11.0.3", + "userManagedAccessAllowed": true +} From 1ee17cc1a256617684faf3ea2974a1bc7f3d476f Mon Sep 17 00:00:00 2001 From: ikethecoder Date: Tue, 11 Oct 2022 14:17:07 -0700 Subject: [PATCH 20/48] fix unit tests to pass sonarscan --- src/services/org-groups/org-group-service.ts | 2 +- src/test/services/batch/batch-utils.test.js | 4 ++-- src/test/services/org-groups/resource.test.ts | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/services/org-groups/org-group-service.ts b/src/services/org-groups/org-group-service.ts index ee001dd91..29239364b 100644 --- a/src/services/org-groups/org-group-service.ts +++ b/src/services/org-groups/org-group-service.ts @@ -166,7 +166,7 @@ export class OrgGroupService { owner: cid, description: policy.description, scopes: permission.scopes.map((s) => s.name), - users: members.map((u) => u.username), + users: members.map((u) => u.email), groups: groups.sort(), }; diff --git a/src/test/services/batch/batch-utils.test.js b/src/test/services/batch/batch-utils.test.js index 392453bba..907c6c7d1 100644 --- a/src/test/services/batch/batch-utils.test.js +++ b/src/test/services/batch/batch-utils.test.js @@ -34,7 +34,7 @@ describe('Batch Utilities', function () { }; const output = { name: 'sample name', - blob: ['tag1', 'tag2'], + blob: [['tag1', 'tag2']], }; const result = parseBlobString(input, ['blob']); @@ -52,7 +52,7 @@ describe('Batch Utilities', function () { }; const output = { name: 'sample name', - blob: ['tag1', 'tag2'], + blob: [['tag1', 'tag2']], }; const result = parseBlobString(input); diff --git a/src/test/services/org-groups/resource.test.ts b/src/test/services/org-groups/resource.test.ts index 55d77361c..dd69ccf44 100644 --- a/src/test/services/org-groups/resource.test.ts +++ b/src/test/services/org-groups/resource.test.ts @@ -37,9 +37,9 @@ describe('Org Group Resource Service', function () { scopes: - Namespace.View users: - - user1 - - user2 - - user3 + - user1@local + - user2@local + - user3@local groups: - /organization-admin - /organization-admin/ministry-citizens-services From 466d7e93033abd2eca4940df0ad60f52680f0d9c Mon Sep 17 00:00:00 2001 From: ike thecoder Date: Wed, 12 Oct 2022 13:31:21 -0700 Subject: [PATCH 21/48] Feature/keycloak migration (#580) --- .github/workflows/ci-build-deploy.yaml | 4 + local/keycloak/master-realm.json | 6521 +++++++++-------- src/auth/auth-oauth2-proxy.js | 35 + src/controllers/v2/OrganizationController.ts | 2 +- src/controllers/v2/openapi.yaml | 4 - src/controllers/v2/routes.ts | 1 - src/lists/extensions/UMAPermissionTicket.ts | 48 +- .../namespace-access-dialog.tsx | 6 +- .../service-accounts-access.tsx | 4 +- .../namespace-access/users-access.tsx | 9 +- src/nextapp/shared/types/query.types.ts | 2 +- src/services/checkKeystoneStatus.ts | 13 + src/services/keycloak/group-service.ts | 6 +- .../keycloak/permission-ticket-service.ts | 1 + src/services/keycloak/user-service.ts | 68 +- src/services/keystone/access-request.ts | 1 + src/services/keystone/types.ts | 2 +- src/services/keystone/user.ts | 23 + src/services/org-groups/group-access.ts | 14 +- src/services/org-groups/org-group-service.ts | 23 +- src/services/org-groups/types.ts | 1 - src/services/report/data/consumer-access.ts | 7 +- src/services/report/data/consumer-requests.ts | 2 +- src/services/report/data/ns-access.ts | 16 + src/services/report/output/structure.ts | 7 +- src/services/report/workbook.service.ts | 13 +- src/services/workflow/get-namespaces.ts | 21 +- src/services/workflow/index.ts | 3 + src/services/workflow/migrate-user.ts | 127 + src/test/integrated/keycloak/users.ts | 55 + .../integrated/keystonejs/batch-product.ts | 5 +- .../integrated/org-groups/group-access.ts | 26 +- .../integrated/org-groups/sync-members.ts | 14 +- src/test/integrated/reports/consumerAccess.ts | 71 + .../integrated/reports/namespaceAccess.ts | 63 + src/test/integrated/workflow/migrate-user.ts | 42 + src/test/services/batch/batch-utils.test.js | 4 +- src/test/services/org-groups/resource.test.ts | 6 +- 38 files changed, 4265 insertions(+), 3005 deletions(-) create mode 100644 src/services/checkKeystoneStatus.ts create mode 100644 src/services/workflow/migrate-user.ts create mode 100644 src/test/integrated/keycloak/users.ts create mode 100644 src/test/integrated/reports/consumerAccess.ts create mode 100644 src/test/integrated/reports/namespaceAccess.ts create mode 100644 src/test/integrated/workflow/migrate-user.ts diff --git a/.github/workflows/ci-build-deploy.yaml b/.github/workflows/ci-build-deploy.yaml index a2e12c183..2740b40af 100644 --- a/.github/workflows/ci-build-deploy.yaml +++ b/.github/workflows/ci-build-deploy.yaml @@ -271,6 +271,10 @@ jobs: value: '${{ secrets.KEYCLOAK_REALM }}' COOKIE_SECURE: value: 'true' + LOG_LEVEL: + value: 'debug' + DISABLE_LOGGING: + value: 'true' EMAIL_ENABLED: value: 'true' EMAIL_FROM: diff --git a/local/keycloak/master-realm.json b/local/keycloak/master-realm.json index 55260b275..80e2b6336 100644 --- a/local/keycloak/master-realm.json +++ b/local/keycloak/master-realm.json @@ -1,2994 +1,3661 @@ { - "id" : "master", - "realm" : "master", - "displayName" : "BCGov API Management Portal (DEV)", - "displayNameHtml" : "
Local Keycloak
", - "notBefore" : 0, - "revokeRefreshToken" : false, - "refreshTokenMaxReuse" : 0, - "accessTokenLifespan" : 300, - "accessTokenLifespanForImplicitFlow" : 900, - "ssoSessionIdleTimeout" : 1800, - "ssoSessionMaxLifespan" : 36000, - "ssoSessionIdleTimeoutRememberMe" : 0, - "ssoSessionMaxLifespanRememberMe" : 0, - "offlineSessionIdleTimeout" : 2592000, - "offlineSessionMaxLifespanEnabled" : false, - "offlineSessionMaxLifespan" : 5184000, - "clientSessionIdleTimeout" : 0, - "clientSessionMaxLifespan" : 0, - "clientOfflineSessionIdleTimeout" : 0, - "clientOfflineSessionMaxLifespan" : 0, - "accessCodeLifespan" : 60, - "accessCodeLifespanUserAction" : 43200, - "accessCodeLifespanLogin" : 864000000, - "actionTokenGeneratedByAdminLifespan" : 43200, - "actionTokenGeneratedByUserLifespan" : 43200, - "enabled" : true, - "sslRequired" : "external", - "registrationAllowed" : false, - "registrationEmailAsUsername" : false, - "rememberMe" : false, - "verifyEmail" : false, - "loginWithEmailAllowed" : true, - "duplicateEmailsAllowed" : false, - "resetPasswordAllowed" : false, - "editUsernameAllowed" : false, - "bruteForceProtected" : false, - "permanentLockout" : false, - "maxFailureWaitSeconds" : 900, - "minimumQuickLoginWaitSeconds" : 60, - "waitIncrementSeconds" : 60, - "quickLoginCheckMilliSeconds" : 1000, - "maxDeltaTimeSeconds" : 43200, - "failureFactor" : 30, - "roles" : { - "realm" : [ { - "id" : "2905dd1c-feb7-4b4c-a51a-924697adf78a", - "name" : "create-realm", - "description" : "${role_create-realm}", - "composite" : false, - "clientRole" : false, - "containerId" : "master", - "attributes" : { } - }, { - "id" : "006ba659-502a-4f51-aff5-3aa1cbb13d02", - "name" : "uma_authorization", - "description" : "${role_uma_authorization}", - "composite" : false, - "clientRole" : false, - "containerId" : "master", - "attributes" : { } - }, { - "id" : "ba7796d3-c1ba-4fb3-8c33-27226c979eba", - "name" : "aps-admin", - "composite" : false, - "clientRole" : false, - "containerId" : "master", - "attributes" : { } - }, { - "id" : "005aef84-ea6d-4edf-90b6-fc7bd64945ad", - "name" : "credential-admin", - "composite" : false, - "clientRole" : false, - "containerId" : "master", - "attributes" : { } - }, { - "id" : "65344728-04bb-4cb8-afe5-3d41cb4457ec", - "name" : "offline_access", - "description" : "${role_offline-access}", - "composite" : false, - "clientRole" : false, - "containerId" : "master", - "attributes" : { } - }, { - "id" : "75fad79d-71f1-46c2-b79b-001d25eae49f", - "name" : "api-manager", - "composite" : false, - "clientRole" : false, - "containerId" : "master", - "attributes" : { } - }, { - "id" : "0d22b102-52e1-4152-b119-2f6846e21b84", - "name" : "api-owner", - "composite" : false, - "clientRole" : false, - "containerId" : "master", - "attributes" : { } - }, { - "id" : "064ef17c-0617-4cbc-b632-77a2fa0919b7", - "name" : "admin", - "description" : "${role_admin}", - "composite" : true, - "composites" : { - "realm" : [ "create-realm" ], - "client" : { - "aps-v2-realm" : [ "query-realms", "create-client", "manage-realm", "manage-authorization", "manage-events", "impersonation", "view-authorization", "manage-identity-providers", "query-users", "manage-clients", "view-identity-providers", "query-groups", "view-events", "view-users", "manage-users", "view-clients", "query-clients", "view-realm" ], - "master-realm" : [ "query-realms", "manage-identity-providers", "manage-authorization", "manage-clients", "impersonation", "query-users", "manage-events", "manage-users", "view-identity-providers", "view-events", "view-users", "create-client", "query-clients", "query-groups", "view-realm", "view-clients", "manage-realm", "view-authorization" ] - } + "id": "master", + "realm": "master", + "displayName": "BCGov API Management Portal (DEV)", + "displayNameHtml": "
Local Keycloak
", + "notBefore": 0, + "revokeRefreshToken": false, + "refreshTokenMaxReuse": 0, + "accessTokenLifespan": 300, + "accessTokenLifespanForImplicitFlow": 900, + "ssoSessionIdleTimeout": 1800, + "ssoSessionMaxLifespan": 36000, + "ssoSessionIdleTimeoutRememberMe": 0, + "ssoSessionMaxLifespanRememberMe": 0, + "offlineSessionIdleTimeout": 2592000, + "offlineSessionMaxLifespanEnabled": false, + "offlineSessionMaxLifespan": 5184000, + "clientSessionIdleTimeout": 0, + "clientSessionMaxLifespan": 0, + "clientOfflineSessionIdleTimeout": 0, + "clientOfflineSessionMaxLifespan": 0, + "accessCodeLifespan": 60, + "accessCodeLifespanUserAction": 43200, + "accessCodeLifespanLogin": 864000000, + "actionTokenGeneratedByAdminLifespan": 43200, + "actionTokenGeneratedByUserLifespan": 43200, + "enabled": true, + "sslRequired": "external", + "registrationAllowed": false, + "registrationEmailAsUsername": false, + "rememberMe": false, + "verifyEmail": false, + "loginWithEmailAllowed": false, + "duplicateEmailsAllowed": true, + "resetPasswordAllowed": false, + "editUsernameAllowed": false, + "bruteForceProtected": false, + "permanentLockout": false, + "maxFailureWaitSeconds": 900, + "minimumQuickLoginWaitSeconds": 60, + "waitIncrementSeconds": 60, + "quickLoginCheckMilliSeconds": 1000, + "maxDeltaTimeSeconds": 43200, + "failureFactor": 30, + "roles": { + "realm": [ + { + "id": "2905dd1c-feb7-4b4c-a51a-924697adf78a", + "name": "create-realm", + "description": "${role_create-realm}", + "composite": false, + "clientRole": false, + "containerId": "master", + "attributes": {} + }, + { + "id": "006ba659-502a-4f51-aff5-3aa1cbb13d02", + "name": "uma_authorization", + "description": "${role_uma_authorization}", + "composite": false, + "clientRole": false, + "containerId": "master", + "attributes": {} + }, + { + "id": "ba7796d3-c1ba-4fb3-8c33-27226c979eba", + "name": "aps-admin", + "composite": false, + "clientRole": false, + "containerId": "master", + "attributes": {} + }, + { + "id": "005aef84-ea6d-4edf-90b6-fc7bd64945ad", + "name": "credential-admin", + "composite": false, + "clientRole": false, + "containerId": "master", + "attributes": {} + }, + { + "id": "65344728-04bb-4cb8-afe5-3d41cb4457ec", + "name": "offline_access", + "description": "${role_offline-access}", + "composite": false, + "clientRole": false, + "containerId": "master", + "attributes": {} + }, + { + "id": "75fad79d-71f1-46c2-b79b-001d25eae49f", + "name": "api-manager", + "composite": false, + "clientRole": false, + "containerId": "master", + "attributes": {} }, - "clientRole" : false, - "containerId" : "master", - "attributes" : { } - } ], - "client" : { - "aps-portal" : [ { - "id" : "b393d043-9ade-4c64-a6e1-5f70c9a416e3", - "name" : "api-owner", - "composite" : false, - "clientRole" : true, - "containerId" : "f333c5e5-fba2-48e8-aab7-7b6862881202", - "attributes" : { } - }, { - "id" : "e0c6f7a0-3a8b-4572-9dac-82dd4b676b30", - "name" : "credential-admin", - "composite" : false, - "clientRole" : true, - "containerId" : "f333c5e5-fba2-48e8-aab7-7b6862881202", - "attributes" : { } - }, { - "id" : "3c0fcf9e-e622-497d-8146-eddd0304f9c8", - "name" : "aps-admin", - "composite" : false, - "clientRole" : true, - "containerId" : "f333c5e5-fba2-48e8-aab7-7b6862881202", - "attributes" : { } - }, { - "id" : "9a357bd3-2c73-40ea-ac09-399a9f7cc9f8", - "name" : "api-manager", - "composite" : false, - "clientRole" : true, - "containerId" : "f333c5e5-fba2-48e8-aab7-7b6862881202", - "attributes" : { } - }, { - "id" : "2c0e0832-4a1e-411b-a8f9-8f86096c3968", - "name" : "developer", - "composite" : false, - "clientRole" : true, - "containerId" : "f333c5e5-fba2-48e8-aab7-7b6862881202", - "attributes" : { } - } ], - "gwa-api" : [ { - "id" : "a50b2fc6-ea49-46d8-9716-683f3a764f5d", - "name" : "developer", - "composite" : false, - "clientRole" : true, - "containerId" : "c002b2b1-0ca8-4fd6-896e-6d2e3395a345", - "attributes" : { } - }, { - "id" : "0c1c2230-24d4-4199-af35-bed6a1044c70", - "name" : "api-admin", - "composite" : false, - "clientRole" : true, - "containerId" : "c002b2b1-0ca8-4fd6-896e-6d2e3395a345", - "attributes" : { } - }, { - "id" : "409fcd4e-54ab-4e19-bdc5-ef8059721e22", - "name" : "uma_protection", - "composite" : false, - "clientRole" : true, - "containerId" : "c002b2b1-0ca8-4fd6-896e-6d2e3395a345", - "attributes" : { } - }, { - "id" : "8d387de9-3d53-4a69-9cb4-d5d285926029", - "name" : "api-owner", - "composite" : false, - "clientRole" : true, - "containerId" : "c002b2b1-0ca8-4fd6-896e-6d2e3395a345", - "attributes" : { } - } ], - "aps-v2-realm" : [ { - "id" : "a7ff1dc9-1214-4757-861b-453b204e460f", - "name" : "manage-events", - "description" : "${role_manage-events}", - "composite" : false, - "clientRole" : true, - "containerId" : "62f2227e-e1ac-4c74-b278-1eab7f7664ae", - "attributes" : { } - }, { - "id" : "faf54935-32bc-4e01-b0e6-8b9bb1cae6e8", - "name" : "query-realms", - "description" : "${role_query-realms}", - "composite" : false, - "clientRole" : true, - "containerId" : "62f2227e-e1ac-4c74-b278-1eab7f7664ae", - "attributes" : { } - }, { - "id" : "2272fc44-5c1d-465d-9608-6b4612e26755", - "name" : "impersonation", - "description" : "${role_impersonation}", - "composite" : false, - "clientRole" : true, - "containerId" : "62f2227e-e1ac-4c74-b278-1eab7f7664ae", - "attributes" : { } - }, { - "id" : "fecb856f-8db8-4432-9f11-6b3426372a9c", - "name" : "create-client", - "description" : "${role_create-client}", - "composite" : false, - "clientRole" : true, - "containerId" : "62f2227e-e1ac-4c74-b278-1eab7f7664ae", - "attributes" : { } - }, { - "id" : "dd8c065c-fcd9-4f58-8dad-ec6100cbcbdf", - "name" : "view-authorization", - "description" : "${role_view-authorization}", - "composite" : false, - "clientRole" : true, - "containerId" : "62f2227e-e1ac-4c74-b278-1eab7f7664ae", - "attributes" : { } - }, { - "id" : "ec6f0230-82ae-4713-8d21-fc97214042d9", - "name" : "manage-identity-providers", - "description" : "${role_manage-identity-providers}", - "composite" : false, - "clientRole" : true, - "containerId" : "62f2227e-e1ac-4c74-b278-1eab7f7664ae", - "attributes" : { } - }, { - "id" : "f33e3aa2-0b3e-4397-9968-82be07d68f40", - "name" : "manage-realm", - "description" : "${role_manage-realm}", - "composite" : false, - "clientRole" : true, - "containerId" : "62f2227e-e1ac-4c74-b278-1eab7f7664ae", - "attributes" : { } - }, { - "id" : "d08507c5-eb84-4d60-93f6-7c72f01536e7", - "name" : "query-users", - "description" : "${role_query-users}", - "composite" : false, - "clientRole" : true, - "containerId" : "62f2227e-e1ac-4c74-b278-1eab7f7664ae", - "attributes" : { } - }, { - "id" : "46d331cb-9fac-45af-b5ba-25bf003b9281", - "name" : "manage-clients", - "description" : "${role_manage-clients}", - "composite" : false, - "clientRole" : true, - "containerId" : "62f2227e-e1ac-4c74-b278-1eab7f7664ae", - "attributes" : { } - }, { - "id" : "77c0c84d-427b-4d73-a185-6bf3108ff9a2", - "name" : "view-identity-providers", - "description" : "${role_view-identity-providers}", - "composite" : false, - "clientRole" : true, - "containerId" : "62f2227e-e1ac-4c74-b278-1eab7f7664ae", - "attributes" : { } - }, { - "id" : "3a3f1c10-0d53-4a25-8bb8-46121f304af4", - "name" : "query-groups", - "description" : "${role_query-groups}", - "composite" : false, - "clientRole" : true, - "containerId" : "62f2227e-e1ac-4c74-b278-1eab7f7664ae", - "attributes" : { } - }, { - "id" : "12b4667f-1cb1-408d-bb8f-9905edea4fee", - "name" : "view-events", - "description" : "${role_view-events}", - "composite" : false, - "clientRole" : true, - "containerId" : "62f2227e-e1ac-4c74-b278-1eab7f7664ae", - "attributes" : { } - }, { - "id" : "99fcf818-a472-4ed1-8b23-d86a54156cf3", - "name" : "view-users", - "description" : "${role_view-users}", - "composite" : true, - "composites" : { - "client" : { - "aps-v2-realm" : [ "query-groups", "query-users" ] + { + "id": "0d22b102-52e1-4152-b119-2f6846e21b84", + "name": "api-owner", + "composite": false, + "clientRole": false, + "containerId": "master", + "attributes": {} + }, + { + "id": "064ef17c-0617-4cbc-b632-77a2fa0919b7", + "name": "admin", + "description": "${role_admin}", + "composite": true, + "composites": { + "realm": ["create-realm"], + "client": { + "aps-v2-realm": [ + "query-realms", + "create-client", + "manage-realm", + "manage-authorization", + "manage-events", + "impersonation", + "view-authorization", + "manage-identity-providers", + "query-users", + "manage-clients", + "view-identity-providers", + "query-groups", + "view-events", + "view-users", + "manage-users", + "view-clients", + "query-clients", + "view-realm" + ], + "master-realm": [ + "query-realms", + "manage-identity-providers", + "manage-authorization", + "manage-clients", + "impersonation", + "query-users", + "manage-events", + "manage-users", + "view-identity-providers", + "view-events", + "view-users", + "create-client", + "query-clients", + "query-groups", + "view-realm", + "view-clients", + "manage-realm", + "view-authorization" + ] } }, - "clientRole" : true, - "containerId" : "62f2227e-e1ac-4c74-b278-1eab7f7664ae", - "attributes" : { } - }, { - "id" : "e2bdd89b-1b4c-448e-b4a5-cc1196918e85", - "name" : "manage-users", - "description" : "${role_manage-users}", - "composite" : false, - "clientRole" : true, - "containerId" : "62f2227e-e1ac-4c74-b278-1eab7f7664ae", - "attributes" : { } - }, { - "id" : "8eecebf6-489f-4924-8afc-d40de58260a5", - "name" : "view-clients", - "description" : "${role_view-clients}", - "composite" : true, - "composites" : { - "client" : { - "aps-v2-realm" : [ "query-clients" ] - } + "clientRole": false, + "containerId": "master", + "attributes": {} + } + ], + "client": { + "aps-portal": [ + { + "id": "b393d043-9ade-4c64-a6e1-5f70c9a416e3", + "name": "api-owner", + "composite": false, + "clientRole": true, + "containerId": "f333c5e5-fba2-48e8-aab7-7b6862881202", + "attributes": {} }, - "clientRole" : true, - "containerId" : "62f2227e-e1ac-4c74-b278-1eab7f7664ae", - "attributes" : { } - }, { - "id" : "a93e05d2-ca5c-46e7-bd66-f98f915fdc30", - "name" : "query-clients", - "description" : "${role_query-clients}", - "composite" : false, - "clientRole" : true, - "containerId" : "62f2227e-e1ac-4c74-b278-1eab7f7664ae", - "attributes" : { } - }, { - "id" : "8016bdc5-4da8-4416-b6ef-fee7796cc8c2", - "name" : "manage-authorization", - "description" : "${role_manage-authorization}", - "composite" : false, - "clientRole" : true, - "containerId" : "62f2227e-e1ac-4c74-b278-1eab7f7664ae", - "attributes" : { } - }, { - "id" : "4c0f70bf-59c5-4878-a14a-eb658ea9ad4b", - "name" : "view-realm", - "description" : "${role_view-realm}", - "composite" : false, - "clientRole" : true, - "containerId" : "62f2227e-e1ac-4c74-b278-1eab7f7664ae", - "attributes" : { } - } ], - "sa-platform-e0000000-fa46551361b4" : [ ], - "security-admin-console" : [ ], - "sa-platform1-e0000000-5be82156d61f" : [ ], - "admin-cli" : [ ], - "account-console" : [ ], - "broker" : [ { - "id" : "8a00a2b3-fc3b-4b7d-aee1-1b3e46507b20", - "name" : "read-token", - "description" : "${role_read-token}", - "composite" : false, - "clientRole" : true, - "containerId" : "db7f58dc-c007-4e4c-ad7b-14f57a0521cd", - "attributes" : { } - } ], - "master-realm" : [ { - "id" : "a04656f4-d096-4cff-91f4-9b9f286c768d", - "name" : "query-realms", - "description" : "${role_query-realms}", - "composite" : false, - "clientRole" : true, - "containerId" : "4e6525e9-647c-4c80-85d6-9c13890b0ab2", - "attributes" : { } - }, { - "id" : "cccc1d8a-1a88-4a60-aff7-f7e5ec751f3f", - "name" : "view-identity-providers", - "description" : "${role_view-identity-providers}", - "composite" : false, - "clientRole" : true, - "containerId" : "4e6525e9-647c-4c80-85d6-9c13890b0ab2", - "attributes" : { } - }, { - "id" : "be5bcb8d-7466-402f-b289-6be26f961b0b", - "name" : "manage-identity-providers", - "description" : "${role_manage-identity-providers}", - "composite" : false, - "clientRole" : true, - "containerId" : "4e6525e9-647c-4c80-85d6-9c13890b0ab2", - "attributes" : { } - }, { - "id" : "e62d2ea1-fb57-41ae-ad8d-17ee8fb7356b", - "name" : "manage-authorization", - "description" : "${role_manage-authorization}", - "composite" : false, - "clientRole" : true, - "containerId" : "4e6525e9-647c-4c80-85d6-9c13890b0ab2", - "attributes" : { } - }, { - "id" : "f7247d9b-c35d-43dc-a10e-f1ce0cbc80fb", - "name" : "view-events", - "description" : "${role_view-events}", - "composite" : false, - "clientRole" : true, - "containerId" : "4e6525e9-647c-4c80-85d6-9c13890b0ab2", - "attributes" : { } - }, { - "id" : "be5fe2ea-0119-4eb4-a2c8-dae5eb3fd308", - "name" : "manage-clients", - "description" : "${role_manage-clients}", - "composite" : false, - "clientRole" : true, - "containerId" : "4e6525e9-647c-4c80-85d6-9c13890b0ab2", - "attributes" : { } - }, { - "id" : "3b1d6088-a992-4f81-b43b-5f71854ef3a4", - "name" : "view-users", - "description" : "${role_view-users}", - "composite" : true, - "composites" : { - "client" : { - "master-realm" : [ "query-users", "query-groups" ] - } + { + "id": "e0c6f7a0-3a8b-4572-9dac-82dd4b676b30", + "name": "credential-admin", + "composite": false, + "clientRole": true, + "containerId": "f333c5e5-fba2-48e8-aab7-7b6862881202", + "attributes": {} }, - "clientRole" : true, - "containerId" : "4e6525e9-647c-4c80-85d6-9c13890b0ab2", - "attributes" : { } - }, { - "id" : "d7cd3f01-b2e9-42b0-be8c-ef438932096c", - "name" : "impersonation", - "description" : "${role_impersonation}", - "composite" : false, - "clientRole" : true, - "containerId" : "4e6525e9-647c-4c80-85d6-9c13890b0ab2", - "attributes" : { } - }, { - "id" : "42fe78c7-3bb9-430d-a78d-013b95b31d0c", - "name" : "create-client", - "description" : "${role_create-client}", - "composite" : false, - "clientRole" : true, - "containerId" : "4e6525e9-647c-4c80-85d6-9c13890b0ab2", - "attributes" : { } - }, { - "id" : "c4c4b2b9-41a6-46c0-852e-5fb8ed755348", - "name" : "query-users", - "description" : "${role_query-users}", - "composite" : false, - "clientRole" : true, - "containerId" : "4e6525e9-647c-4c80-85d6-9c13890b0ab2", - "attributes" : { } - }, { - "id" : "c257a266-eba8-4469-8d9a-f171f489354c", - "name" : "query-clients", - "description" : "${role_query-clients}", - "composite" : false, - "clientRole" : true, - "containerId" : "4e6525e9-647c-4c80-85d6-9c13890b0ab2", - "attributes" : { } - }, { - "id" : "7e584743-ffe9-45e8-8f5b-722e07034141", - "name" : "query-groups", - "description" : "${role_query-groups}", - "composite" : false, - "clientRole" : true, - "containerId" : "4e6525e9-647c-4c80-85d6-9c13890b0ab2", - "attributes" : { } - }, { - "id" : "70aad632-dd34-46e8-813a-398914dd31c9", - "name" : "view-realm", - "description" : "${role_view-realm}", - "composite" : false, - "clientRole" : true, - "containerId" : "4e6525e9-647c-4c80-85d6-9c13890b0ab2", - "attributes" : { } - }, { - "id" : "6855b67a-f23d-40c9-a597-c98261e27ce4", - "name" : "view-clients", - "description" : "${role_view-clients}", - "composite" : true, - "composites" : { - "client" : { - "master-realm" : [ "query-clients" ] - } + { + "id": "3c0fcf9e-e622-497d-8146-eddd0304f9c8", + "name": "aps-admin", + "composite": false, + "clientRole": true, + "containerId": "f333c5e5-fba2-48e8-aab7-7b6862881202", + "attributes": {} }, - "clientRole" : true, - "containerId" : "4e6525e9-647c-4c80-85d6-9c13890b0ab2", - "attributes" : { } - }, { - "id" : "0725918a-6335-4556-aafa-ff6c3fb87989", - "name" : "manage-realm", - "description" : "${role_manage-realm}", - "composite" : false, - "clientRole" : true, - "containerId" : "4e6525e9-647c-4c80-85d6-9c13890b0ab2", - "attributes" : { } - }, { - "id" : "0d2640b7-461c-4c21-8270-064f5423ae74", - "name" : "manage-events", - "description" : "${role_manage-events}", - "composite" : false, - "clientRole" : true, - "containerId" : "4e6525e9-647c-4c80-85d6-9c13890b0ab2", - "attributes" : { } - }, { - "id" : "ba7e040b-9462-489a-9467-965f69ae1025", - "name" : "manage-users", - "description" : "${role_manage-users}", - "composite" : false, - "clientRole" : true, - "containerId" : "4e6525e9-647c-4c80-85d6-9c13890b0ab2", - "attributes" : { } - }, { - "id" : "b473aa2e-d49d-4ba5-b502-8d38db9dc81e", - "name" : "view-authorization", - "description" : "${role_view-authorization}", - "composite" : false, - "clientRole" : true, - "containerId" : "4e6525e9-647c-4c80-85d6-9c13890b0ab2", - "attributes" : { } - } ], - "account" : [ { - "id" : "dba0e0ba-f826-49df-a378-031e5fbcfd13", - "name" : "view-applications", - "description" : "${role_view-applications}", - "composite" : false, - "clientRole" : true, - "containerId" : "bc61d6b7-6876-4193-9881-1b994596a207", - "attributes" : { } - }, { - "id" : "5d9f0b2a-55bb-4cda-ab2d-67b77cf925f0", - "name" : "view-consent", - "description" : "${role_view-consent}", - "composite" : false, - "clientRole" : true, - "containerId" : "bc61d6b7-6876-4193-9881-1b994596a207", - "attributes" : { } - }, { - "id" : "f58a3fc3-9fbd-4308-8528-cee3d267fc74", - "name" : "manage-account", - "description" : "${role_manage-account}", - "composite" : true, - "composites" : { - "client" : { - "account" : [ "manage-account-links" ] - } + { + "id": "9a357bd3-2c73-40ea-ac09-399a9f7cc9f8", + "name": "api-manager", + "composite": false, + "clientRole": true, + "containerId": "f333c5e5-fba2-48e8-aab7-7b6862881202", + "attributes": {} }, - "clientRole" : true, - "containerId" : "bc61d6b7-6876-4193-9881-1b994596a207", - "attributes" : { } - }, { - "id" : "b84c29be-1b56-4b8e-be2c-1b5153d8b1aa", - "name" : "view-profile", - "description" : "${role_view-profile}", - "composite" : false, - "clientRole" : true, - "containerId" : "bc61d6b7-6876-4193-9881-1b994596a207", - "attributes" : { } - }, { - "id" : "baccbb7e-8777-4ff5-9d1a-491b61f6d87f", - "name" : "manage-consent", - "description" : "${role_manage-consent}", - "composite" : true, - "composites" : { - "client" : { - "account" : [ "view-consent" ] - } + { + "id": "2c0e0832-4a1e-411b-a8f9-8f86096c3968", + "name": "developer", + "composite": false, + "clientRole": true, + "containerId": "f333c5e5-fba2-48e8-aab7-7b6862881202", + "attributes": {} + } + ], + "gwa-api": [ + { + "id": "a50b2fc6-ea49-46d8-9716-683f3a764f5d", + "name": "developer", + "composite": false, + "clientRole": true, + "containerId": "c002b2b1-0ca8-4fd6-896e-6d2e3395a345", + "attributes": {} + }, + { + "id": "0c1c2230-24d4-4199-af35-bed6a1044c70", + "name": "api-admin", + "composite": false, + "clientRole": true, + "containerId": "c002b2b1-0ca8-4fd6-896e-6d2e3395a345", + "attributes": {} + }, + { + "id": "409fcd4e-54ab-4e19-bdc5-ef8059721e22", + "name": "uma_protection", + "composite": false, + "clientRole": true, + "containerId": "c002b2b1-0ca8-4fd6-896e-6d2e3395a345", + "attributes": {} + }, + { + "id": "8d387de9-3d53-4a69-9cb4-d5d285926029", + "name": "api-owner", + "composite": false, + "clientRole": true, + "containerId": "c002b2b1-0ca8-4fd6-896e-6d2e3395a345", + "attributes": {} + } + ], + "aps-v2-realm": [ + { + "id": "a7ff1dc9-1214-4757-861b-453b204e460f", + "name": "manage-events", + "description": "${role_manage-events}", + "composite": false, + "clientRole": true, + "containerId": "62f2227e-e1ac-4c74-b278-1eab7f7664ae", + "attributes": {} + }, + { + "id": "faf54935-32bc-4e01-b0e6-8b9bb1cae6e8", + "name": "query-realms", + "description": "${role_query-realms}", + "composite": false, + "clientRole": true, + "containerId": "62f2227e-e1ac-4c74-b278-1eab7f7664ae", + "attributes": {} + }, + { + "id": "2272fc44-5c1d-465d-9608-6b4612e26755", + "name": "impersonation", + "description": "${role_impersonation}", + "composite": false, + "clientRole": true, + "containerId": "62f2227e-e1ac-4c74-b278-1eab7f7664ae", + "attributes": {} + }, + { + "id": "fecb856f-8db8-4432-9f11-6b3426372a9c", + "name": "create-client", + "description": "${role_create-client}", + "composite": false, + "clientRole": true, + "containerId": "62f2227e-e1ac-4c74-b278-1eab7f7664ae", + "attributes": {} + }, + { + "id": "dd8c065c-fcd9-4f58-8dad-ec6100cbcbdf", + "name": "view-authorization", + "description": "${role_view-authorization}", + "composite": false, + "clientRole": true, + "containerId": "62f2227e-e1ac-4c74-b278-1eab7f7664ae", + "attributes": {} + }, + { + "id": "ec6f0230-82ae-4713-8d21-fc97214042d9", + "name": "manage-identity-providers", + "description": "${role_manage-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "62f2227e-e1ac-4c74-b278-1eab7f7664ae", + "attributes": {} + }, + { + "id": "f33e3aa2-0b3e-4397-9968-82be07d68f40", + "name": "manage-realm", + "description": "${role_manage-realm}", + "composite": false, + "clientRole": true, + "containerId": "62f2227e-e1ac-4c74-b278-1eab7f7664ae", + "attributes": {} + }, + { + "id": "d08507c5-eb84-4d60-93f6-7c72f01536e7", + "name": "query-users", + "description": "${role_query-users}", + "composite": false, + "clientRole": true, + "containerId": "62f2227e-e1ac-4c74-b278-1eab7f7664ae", + "attributes": {} + }, + { + "id": "46d331cb-9fac-45af-b5ba-25bf003b9281", + "name": "manage-clients", + "description": "${role_manage-clients}", + "composite": false, + "clientRole": true, + "containerId": "62f2227e-e1ac-4c74-b278-1eab7f7664ae", + "attributes": {} + }, + { + "id": "77c0c84d-427b-4d73-a185-6bf3108ff9a2", + "name": "view-identity-providers", + "description": "${role_view-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "62f2227e-e1ac-4c74-b278-1eab7f7664ae", + "attributes": {} + }, + { + "id": "3a3f1c10-0d53-4a25-8bb8-46121f304af4", + "name": "query-groups", + "description": "${role_query-groups}", + "composite": false, + "clientRole": true, + "containerId": "62f2227e-e1ac-4c74-b278-1eab7f7664ae", + "attributes": {} + }, + { + "id": "12b4667f-1cb1-408d-bb8f-9905edea4fee", + "name": "view-events", + "description": "${role_view-events}", + "composite": false, + "clientRole": true, + "containerId": "62f2227e-e1ac-4c74-b278-1eab7f7664ae", + "attributes": {} + }, + { + "id": "99fcf818-a472-4ed1-8b23-d86a54156cf3", + "name": "view-users", + "description": "${role_view-users}", + "composite": true, + "composites": { + "client": { + "aps-v2-realm": ["query-groups", "query-users"] + } + }, + "clientRole": true, + "containerId": "62f2227e-e1ac-4c74-b278-1eab7f7664ae", + "attributes": {} + }, + { + "id": "e2bdd89b-1b4c-448e-b4a5-cc1196918e85", + "name": "manage-users", + "description": "${role_manage-users}", + "composite": false, + "clientRole": true, + "containerId": "62f2227e-e1ac-4c74-b278-1eab7f7664ae", + "attributes": {} + }, + { + "id": "8eecebf6-489f-4924-8afc-d40de58260a5", + "name": "view-clients", + "description": "${role_view-clients}", + "composite": true, + "composites": { + "client": { + "aps-v2-realm": ["query-clients"] + } + }, + "clientRole": true, + "containerId": "62f2227e-e1ac-4c74-b278-1eab7f7664ae", + "attributes": {} + }, + { + "id": "a93e05d2-ca5c-46e7-bd66-f98f915fdc30", + "name": "query-clients", + "description": "${role_query-clients}", + "composite": false, + "clientRole": true, + "containerId": "62f2227e-e1ac-4c74-b278-1eab7f7664ae", + "attributes": {} + }, + { + "id": "8016bdc5-4da8-4416-b6ef-fee7796cc8c2", + "name": "manage-authorization", + "description": "${role_manage-authorization}", + "composite": false, + "clientRole": true, + "containerId": "62f2227e-e1ac-4c74-b278-1eab7f7664ae", + "attributes": {} + }, + { + "id": "4c0f70bf-59c5-4878-a14a-eb658ea9ad4b", + "name": "view-realm", + "description": "${role_view-realm}", + "composite": false, + "clientRole": true, + "containerId": "62f2227e-e1ac-4c74-b278-1eab7f7664ae", + "attributes": {} + } + ], + "sa-platform-e0000000-fa46551361b4": [], + "security-admin-console": [], + "sa-platform1-e0000000-5be82156d61f": [], + "admin-cli": [], + "account-console": [], + "broker": [ + { + "id": "8a00a2b3-fc3b-4b7d-aee1-1b3e46507b20", + "name": "read-token", + "description": "${role_read-token}", + "composite": false, + "clientRole": true, + "containerId": "db7f58dc-c007-4e4c-ad7b-14f57a0521cd", + "attributes": {} + } + ], + "master-realm": [ + { + "id": "a04656f4-d096-4cff-91f4-9b9f286c768d", + "name": "query-realms", + "description": "${role_query-realms}", + "composite": false, + "clientRole": true, + "containerId": "4e6525e9-647c-4c80-85d6-9c13890b0ab2", + "attributes": {} + }, + { + "id": "cccc1d8a-1a88-4a60-aff7-f7e5ec751f3f", + "name": "view-identity-providers", + "description": "${role_view-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "4e6525e9-647c-4c80-85d6-9c13890b0ab2", + "attributes": {} + }, + { + "id": "be5bcb8d-7466-402f-b289-6be26f961b0b", + "name": "manage-identity-providers", + "description": "${role_manage-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "4e6525e9-647c-4c80-85d6-9c13890b0ab2", + "attributes": {} + }, + { + "id": "e62d2ea1-fb57-41ae-ad8d-17ee8fb7356b", + "name": "manage-authorization", + "description": "${role_manage-authorization}", + "composite": false, + "clientRole": true, + "containerId": "4e6525e9-647c-4c80-85d6-9c13890b0ab2", + "attributes": {} + }, + { + "id": "f7247d9b-c35d-43dc-a10e-f1ce0cbc80fb", + "name": "view-events", + "description": "${role_view-events}", + "composite": false, + "clientRole": true, + "containerId": "4e6525e9-647c-4c80-85d6-9c13890b0ab2", + "attributes": {} + }, + { + "id": "be5fe2ea-0119-4eb4-a2c8-dae5eb3fd308", + "name": "manage-clients", + "description": "${role_manage-clients}", + "composite": false, + "clientRole": true, + "containerId": "4e6525e9-647c-4c80-85d6-9c13890b0ab2", + "attributes": {} }, - "clientRole" : true, - "containerId" : "bc61d6b7-6876-4193-9881-1b994596a207", - "attributes" : { } - }, { - "id" : "a1e4af9d-431f-4e0f-87c1-d6c24f0a61e0", - "name" : "manage-account-links", - "description" : "${role_manage-account-links}", - "composite" : false, - "clientRole" : true, - "containerId" : "bc61d6b7-6876-4193-9881-1b994596a207", - "attributes" : { } - } ], - "cypress-auth-profile" : [ { - "id" : "7e5fbfc1-4818-4736-9a47-21d35b3304c2", - "name" : "uma_protection", - "composite" : false, - "clientRole" : true, - "containerId" : "50c78923-95d9-4083-87ff-5233f2d6326e", - "attributes" : { } - } ] + { + "id": "3b1d6088-a992-4f81-b43b-5f71854ef3a4", + "name": "view-users", + "description": "${role_view-users}", + "composite": true, + "composites": { + "client": { + "master-realm": ["query-users", "query-groups"] + } + }, + "clientRole": true, + "containerId": "4e6525e9-647c-4c80-85d6-9c13890b0ab2", + "attributes": {} + }, + { + "id": "d7cd3f01-b2e9-42b0-be8c-ef438932096c", + "name": "impersonation", + "description": "${role_impersonation}", + "composite": false, + "clientRole": true, + "containerId": "4e6525e9-647c-4c80-85d6-9c13890b0ab2", + "attributes": {} + }, + { + "id": "42fe78c7-3bb9-430d-a78d-013b95b31d0c", + "name": "create-client", + "description": "${role_create-client}", + "composite": false, + "clientRole": true, + "containerId": "4e6525e9-647c-4c80-85d6-9c13890b0ab2", + "attributes": {} + }, + { + "id": "c4c4b2b9-41a6-46c0-852e-5fb8ed755348", + "name": "query-users", + "description": "${role_query-users}", + "composite": false, + "clientRole": true, + "containerId": "4e6525e9-647c-4c80-85d6-9c13890b0ab2", + "attributes": {} + }, + { + "id": "c257a266-eba8-4469-8d9a-f171f489354c", + "name": "query-clients", + "description": "${role_query-clients}", + "composite": false, + "clientRole": true, + "containerId": "4e6525e9-647c-4c80-85d6-9c13890b0ab2", + "attributes": {} + }, + { + "id": "7e584743-ffe9-45e8-8f5b-722e07034141", + "name": "query-groups", + "description": "${role_query-groups}", + "composite": false, + "clientRole": true, + "containerId": "4e6525e9-647c-4c80-85d6-9c13890b0ab2", + "attributes": {} + }, + { + "id": "70aad632-dd34-46e8-813a-398914dd31c9", + "name": "view-realm", + "description": "${role_view-realm}", + "composite": false, + "clientRole": true, + "containerId": "4e6525e9-647c-4c80-85d6-9c13890b0ab2", + "attributes": {} + }, + { + "id": "6855b67a-f23d-40c9-a597-c98261e27ce4", + "name": "view-clients", + "description": "${role_view-clients}", + "composite": true, + "composites": { + "client": { + "master-realm": ["query-clients"] + } + }, + "clientRole": true, + "containerId": "4e6525e9-647c-4c80-85d6-9c13890b0ab2", + "attributes": {} + }, + { + "id": "0725918a-6335-4556-aafa-ff6c3fb87989", + "name": "manage-realm", + "description": "${role_manage-realm}", + "composite": false, + "clientRole": true, + "containerId": "4e6525e9-647c-4c80-85d6-9c13890b0ab2", + "attributes": {} + }, + { + "id": "0d2640b7-461c-4c21-8270-064f5423ae74", + "name": "manage-events", + "description": "${role_manage-events}", + "composite": false, + "clientRole": true, + "containerId": "4e6525e9-647c-4c80-85d6-9c13890b0ab2", + "attributes": {} + }, + { + "id": "ba7e040b-9462-489a-9467-965f69ae1025", + "name": "manage-users", + "description": "${role_manage-users}", + "composite": false, + "clientRole": true, + "containerId": "4e6525e9-647c-4c80-85d6-9c13890b0ab2", + "attributes": {} + }, + { + "id": "b473aa2e-d49d-4ba5-b502-8d38db9dc81e", + "name": "view-authorization", + "description": "${role_view-authorization}", + "composite": false, + "clientRole": true, + "containerId": "4e6525e9-647c-4c80-85d6-9c13890b0ab2", + "attributes": {} + } + ], + "account": [ + { + "id": "dba0e0ba-f826-49df-a378-031e5fbcfd13", + "name": "view-applications", + "description": "${role_view-applications}", + "composite": false, + "clientRole": true, + "containerId": "bc61d6b7-6876-4193-9881-1b994596a207", + "attributes": {} + }, + { + "id": "5d9f0b2a-55bb-4cda-ab2d-67b77cf925f0", + "name": "view-consent", + "description": "${role_view-consent}", + "composite": false, + "clientRole": true, + "containerId": "bc61d6b7-6876-4193-9881-1b994596a207", + "attributes": {} + }, + { + "id": "f58a3fc3-9fbd-4308-8528-cee3d267fc74", + "name": "manage-account", + "description": "${role_manage-account}", + "composite": true, + "composites": { + "client": { + "account": ["manage-account-links"] + } + }, + "clientRole": true, + "containerId": "bc61d6b7-6876-4193-9881-1b994596a207", + "attributes": {} + }, + { + "id": "b84c29be-1b56-4b8e-be2c-1b5153d8b1aa", + "name": "view-profile", + "description": "${role_view-profile}", + "composite": false, + "clientRole": true, + "containerId": "bc61d6b7-6876-4193-9881-1b994596a207", + "attributes": {} + }, + { + "id": "baccbb7e-8777-4ff5-9d1a-491b61f6d87f", + "name": "manage-consent", + "description": "${role_manage-consent}", + "composite": true, + "composites": { + "client": { + "account": ["view-consent"] + } + }, + "clientRole": true, + "containerId": "bc61d6b7-6876-4193-9881-1b994596a207", + "attributes": {} + }, + { + "id": "a1e4af9d-431f-4e0f-87c1-d6c24f0a61e0", + "name": "manage-account-links", + "description": "${role_manage-account-links}", + "composite": false, + "clientRole": true, + "containerId": "bc61d6b7-6876-4193-9881-1b994596a207", + "attributes": {} + } + ], + "cypress-auth-profile": [ + { + "id": "7e5fbfc1-4818-4736-9a47-21d35b3304c2", + "name": "uma_protection", + "composite": false, + "clientRole": true, + "containerId": "50c78923-95d9-4083-87ff-5233f2d6326e", + "attributes": {} + } + ] } }, - "groups" : [ { - "id" : "b0944059-43fc-4dbc-9037-d25e01ae6c45", - "name" : "ns", - "path" : "/ns", - "attributes" : { }, - "realmRoles" : [ ], - "clientRoles" : { }, - "subGroups" : [ { - "id" : "5c875007-2e0e-4c01-8418-143e2a420722", - "name" : "platform", - "path" : "/ns/platform", - "attributes" : { - "org-unit" : [ "planning-and-innovation-division" ], - "org" : [ "ministry-of-health" ] + "groups": [ + { + "id": "b0944059-43fc-4dbc-9037-d25e01ae6c45", + "name": "ns", + "path": "/ns", + "attributes": {}, + "realmRoles": [], + "clientRoles": {}, + "subGroups": [ + { + "id": "5c875007-2e0e-4c01-8418-143e2a420722", + "name": "platform", + "path": "/ns/platform", + "attributes": { + "org-unit": ["planning-and-innovation-division"], + "org": ["ministry-of-health"] + }, + "realmRoles": [], + "clientRoles": {}, + "subGroups": [] + } + ] + }, + { + "id": "6a0b857d-3951-444d-823e-193bf9f12f67", + "name": "organization-admin", + "path": "/organization-admin", + "attributes": {}, + "realmRoles": [], + "clientRoles": {}, + "subGroups": [ + { + "id": "17434902-eda6-4d6a-a366-2dbfdbf3866c", + "name": "ca.bc.gov", + "path": "/organization-admin/ca.bc.gov", + "attributes": {}, + "realmRoles": [], + "clientRoles": {}, + "subGroups": [ + { + "id": "711b0078-fb8c-4ce9-aa50-06a690360508", + "name": "ministry-of-health", + "path": "/organization-admin/ca.bc.gov/ministry-of-health", + "attributes": {}, + "realmRoles": [], + "clientRoles": {}, + "subGroups": [ + { + "id": "614278c5-b60c-4101-9986-3d031720dec0", + "name": "planning-and-innovation-division", + "path": "/organization-admin/ca.bc.gov/ministry-of-health/planning-and-innovation-division", + "attributes": {}, + "realmRoles": [], + "clientRoles": {}, + "subGroups": [] + } + ] + } + ] + } + ] + } + ], + "defaultRoles": ["uma_authorization", "offline_access"], + "requiredCredentials": ["password"], + "otpPolicyType": "totp", + "otpPolicyAlgorithm": "HmacSHA1", + "otpPolicyInitialCounter": 0, + "otpPolicyDigits": 6, + "otpPolicyLookAheadWindow": 1, + "otpPolicyPeriod": 30, + "otpSupportedApplications": ["FreeOTP", "Google Authenticator"], + "webAuthnPolicyRpEntityName": "keycloak", + "webAuthnPolicySignatureAlgorithms": ["ES256"], + "webAuthnPolicyRpId": "", + "webAuthnPolicyAttestationConveyancePreference": "not specified", + "webAuthnPolicyAuthenticatorAttachment": "not specified", + "webAuthnPolicyRequireResidentKey": "not specified", + "webAuthnPolicyUserVerificationRequirement": "not specified", + "webAuthnPolicyCreateTimeout": 0, + "webAuthnPolicyAvoidSameAuthenticatorRegister": false, + "webAuthnPolicyAcceptableAaguids": [], + "webAuthnPolicyPasswordlessRpEntityName": "keycloak", + "webAuthnPolicyPasswordlessSignatureAlgorithms": ["ES256"], + "webAuthnPolicyPasswordlessRpId": "", + "webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified", + "webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified", + "webAuthnPolicyPasswordlessRequireResidentKey": "not specified", + "webAuthnPolicyPasswordlessUserVerificationRequirement": "not specified", + "webAuthnPolicyPasswordlessCreateTimeout": 0, + "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false, + "webAuthnPolicyPasswordlessAcceptableAaguids": [], + "users": [ + { + "id": "03ff1b38-197b-465f-854a-b64f56b13356", + "createdTimestamp": 1625085370528, + "username": "awsummer@idir", + "enabled": true, + "totp": false, + "emailVerified": false, + "firstName": "Awesome", + "lastName": "Summers", + "email": "awsummers@gmail.com", + "credentials": [ + { + "id": "fa2ee157-09ea-466e-b9f6-378fd6f4dcdc", + "type": "password", + "createdDate": 1625085504863, + "secretData": "{\"value\":\"Fg8F1kRC03xAi3dyLPoH7K0TDGGfN9FKkcG6gGobAkyZtqtfShgjhGB1DSBZdXXirK27lHHYv+ZTqpAf87uhuA==\",\"salt\":\"TD5LnQBeAReu7LfJ2bnWMQ==\"}", + "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\"}" + } + ], + "disableableCredentialTypes": [], + "requiredActions": [], + "realmRoles": ["uma_authorization", "offline_access", "api-owner"], + "clientRoles": { + "account": ["manage-account", "view-profile"] }, - "realmRoles" : [ ], - "clientRoles" : { }, - "subGroups" : [ ] - } ] - }, { - "id" : "6a0b857d-3951-444d-823e-193bf9f12f67", - "name" : "organization-admin", - "path" : "/organization-admin", - "attributes" : { }, - "realmRoles" : [ ], - "clientRoles" : { }, - "subGroups" : [ { - "id" : "17434902-eda6-4d6a-a366-2dbfdbf3866c", - "name" : "ca.bc.gov", - "path" : "/organization-admin/ca.bc.gov", - "attributes" : { }, - "realmRoles" : [ ], - "clientRoles" : { }, - "subGroups" : [ { - "id" : "711b0078-fb8c-4ce9-aa50-06a690360508", - "name" : "ministry-of-health", - "path" : "/organization-admin/ca.bc.gov/ministry-of-health", - "attributes" : { }, - "realmRoles" : [ ], - "clientRoles" : { }, - "subGroups" : [ { - "id" : "614278c5-b60c-4101-9986-3d031720dec0", - "name" : "planning-and-innovation-division", - "path" : "/organization-admin/ca.bc.gov/ministry-of-health/planning-and-innovation-division", - "attributes" : { }, - "realmRoles" : [ ], - "clientRoles" : { }, - "subGroups" : [ ] - } ] - } ] - } ] - } ], - "defaultRoles" : [ "uma_authorization", "offline_access" ], - "requiredCredentials" : [ "password" ], - "otpPolicyType" : "totp", - "otpPolicyAlgorithm" : "HmacSHA1", - "otpPolicyInitialCounter" : 0, - "otpPolicyDigits" : 6, - "otpPolicyLookAheadWindow" : 1, - "otpPolicyPeriod" : 30, - "otpSupportedApplications" : [ "FreeOTP", "Google Authenticator" ], - "webAuthnPolicyRpEntityName" : "keycloak", - "webAuthnPolicySignatureAlgorithms" : [ "ES256" ], - "webAuthnPolicyRpId" : "", - "webAuthnPolicyAttestationConveyancePreference" : "not specified", - "webAuthnPolicyAuthenticatorAttachment" : "not specified", - "webAuthnPolicyRequireResidentKey" : "not specified", - "webAuthnPolicyUserVerificationRequirement" : "not specified", - "webAuthnPolicyCreateTimeout" : 0, - "webAuthnPolicyAvoidSameAuthenticatorRegister" : false, - "webAuthnPolicyAcceptableAaguids" : [ ], - "webAuthnPolicyPasswordlessRpEntityName" : "keycloak", - "webAuthnPolicyPasswordlessSignatureAlgorithms" : [ "ES256" ], - "webAuthnPolicyPasswordlessRpId" : "", - "webAuthnPolicyPasswordlessAttestationConveyancePreference" : "not specified", - "webAuthnPolicyPasswordlessAuthenticatorAttachment" : "not specified", - "webAuthnPolicyPasswordlessRequireResidentKey" : "not specified", - "webAuthnPolicyPasswordlessUserVerificationRequirement" : "not specified", - "webAuthnPolicyPasswordlessCreateTimeout" : 0, - "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister" : false, - "webAuthnPolicyPasswordlessAcceptableAaguids" : [ ], - "users" : [ { - "id" : "03ff1b38-197b-465f-854a-b64f56b13356", - "createdTimestamp" : 1625085370528, - "username" : "awsummer@idir", - "enabled" : true, - "totp" : false, - "emailVerified" : false, - "firstName" : "Awesome", - "lastName" : "Summers", - "email" : "awsummers@gmail.com", - "credentials" : [ { - "id" : "fa2ee157-09ea-466e-b9f6-378fd6f4dcdc", - "type" : "password", - "createdDate" : 1625085504863, - "secretData" : "{\"value\":\"Fg8F1kRC03xAi3dyLPoH7K0TDGGfN9FKkcG6gGobAkyZtqtfShgjhGB1DSBZdXXirK27lHHYv+ZTqpAf87uhuA==\",\"salt\":\"TD5LnQBeAReu7LfJ2bnWMQ==\"}", - "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\"}" - } ], - "disableableCredentialTypes" : [ ], - "requiredActions" : [ ], - "realmRoles" : [ "uma_authorization", "offline_access", "api-owner" ], - "clientRoles" : { - "account" : [ "manage-account", "view-profile" ] + "notBefore": 0, + "groups": [] }, - "notBefore" : 0, - "groups" : [ ] - }, { - "id" : "f6296cb0-a7c4-45fc-88ff-c1da793ff981", - "createdTimestamp" : 1642463544967, - "username" : "harley", - "enabled" : true, - "totp" : false, - "emailVerified" : false, - "firstName" : "Harley", - "lastName" : "Jones", - "email" : "harley@test.com", - "credentials" : [ { - "id" : "0cc94c77-49c1-4e9c-b224-66dc661c06b5", - "type" : "password", - "createdDate" : 1642466431391, - "secretData" : "{\"value\":\"AxeI0+khXUu1TqFB+I89x9KSQCBo2KZLGPyYXvLSkQlu/lMSfw7QEp0S3+i364FuzHYRCwAC2GVCjrAiOiyHVg==\",\"salt\":\"GJZIGYazPq+sEMRAO2AtRA==\"}", - "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\"}" - } ], - "disableableCredentialTypes" : [ ], - "requiredActions" : [ ], - "realmRoles" : [ "uma_authorization", "offline_access" ], - "clientRoles" : { - "account" : [ "manage-account", "view-profile" ] + { + "id": "f6296cb0-a7c4-45fc-88ff-c1da793ff981", + "createdTimestamp": 1642463544967, + "username": "harley", + "enabled": true, + "totp": false, + "emailVerified": false, + "firstName": "Harley", + "lastName": "Jones", + "email": "harley@test.com", + "credentials": [ + { + "id": "0cc94c77-49c1-4e9c-b224-66dc661c06b5", + "type": "password", + "createdDate": 1642466431391, + "secretData": "{\"value\":\"AxeI0+khXUu1TqFB+I89x9KSQCBo2KZLGPyYXvLSkQlu/lMSfw7QEp0S3+i364FuzHYRCwAC2GVCjrAiOiyHVg==\",\"salt\":\"GJZIGYazPq+sEMRAO2AtRA==\"}", + "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\"}" + } + ], + "disableableCredentialTypes": [], + "requiredActions": [], + "realmRoles": ["uma_authorization", "offline_access"], + "clientRoles": { + "account": ["manage-account", "view-profile"] + }, + "notBefore": 0, + "groups": [] }, - "notBefore" : 0, - "groups" : [ ] - }, { - "id" : "bf498a7b-b6e0-49bb-9ea8-0241d7792fe2", - "createdTimestamp" : 1642463435902, - "username" : "janis@idir", - "enabled" : true, - "totp" : false, - "emailVerified" : false, - "firstName" : "Janis", - "lastName" : "Smith", - "email" : "janis@testmail.com", - "attributes" : { - "provider_user_guid" : [ "220469E037C84A7ABDFAB15204A607C5" ], - "identity_provider" : [ "idir" ], - "display_name" : [ "Janis@idir" ], - "provider_username" : [ "janis" ] + { + "id": "bf498a7b-b6e0-49bb-9ea8-0241d7792fe2", + "createdTimestamp": 1642463435902, + "username": "janis@idir", + "enabled": true, + "totp": false, + "emailVerified": false, + "firstName": "Janis", + "lastName": "Smith", + "email": "janis@testmail.com", + "attributes": { + "provider_user_guid": ["220469E037C84A7ABDFAB15204A607C5"], + "identity_provider": ["idir"], + "display_name": ["Janis@idir"], + "provider_username": ["janis"] + }, + "credentials": [ + { + "id": "6aa0a7ca-c2ad-43f5-9bdb-3f58693b28bc", + "type": "password", + "createdDate": 1642466403247, + "secretData": "{\"value\":\"ltS/DMUYOCSmZZRbf7rYFTpLa9cqQDewFO1jwRPczU99leiyGtOCsbdAPRmSvLVhOLnzqvcaua3B17ej2d6/7w==\",\"salt\":\"ZrR/QMSRwruFRU5FsPUgHQ==\"}", + "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\"}" + } + ], + "disableableCredentialTypes": [], + "requiredActions": [], + "realmRoles": [ + "uma_authorization", + "aps-admin", + "offline_access", + "api-owner" + ], + "clientRoles": { + "account": ["manage-account", "view-profile"] + }, + "notBefore": 0, + "groups": [] }, - "credentials" : [ { - "id" : "6aa0a7ca-c2ad-43f5-9bdb-3f58693b28bc", - "type" : "password", - "createdDate" : 1642466403247, - "secretData" : "{\"value\":\"ltS/DMUYOCSmZZRbf7rYFTpLa9cqQDewFO1jwRPczU99leiyGtOCsbdAPRmSvLVhOLnzqvcaua3B17ej2d6/7w==\",\"salt\":\"ZrR/QMSRwruFRU5FsPUgHQ==\"}", - "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\"}" - } ], - "disableableCredentialTypes" : [ ], - "requiredActions" : [ ], - "realmRoles" : [ "uma_authorization", "aps-admin", "offline_access", "api-owner" ], - "clientRoles" : { - "account" : [ "manage-account", "view-profile" ] + { + "id": "7f9dcdfc-6100-4ec8-ba3f-8bd26d184585", + "createdTimestamp": 1623537499547, + "username": "local", + "enabled": true, + "totp": false, + "emailVerified": false, + "firstName": "local F", + "lastName": "local L", + "email": "local@development.me", + "credentials": [ + { + "id": "4ea10252-fd5d-476c-9e75-896230209ba5", + "type": "password", + "createdDate": 1623537499592, + "secretData": "{\"value\":\"BuAJdiavdBRkL23vKkpx9Ua1jKeLagEd/AkExhMM5Npt5l9Q3HO3Z/Ksxen+TBGh0JZDMxpfHArCp7xaAaUThw==\",\"salt\":\"ASKUBGyIEAcGPJaCnkpk+A==\"}", + "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\"}" + } + ], + "disableableCredentialTypes": [], + "requiredActions": [], + "realmRoles": [ + "uma_authorization", + "offline_access", + "api-owner", + "admin" + ], + "clientRoles": { + "account": ["manage-account", "view-profile"] + }, + "notBefore": 0, + "groups": [] }, - "notBefore" : 0, - "groups" : [ ] - }, { - "id" : "7f9dcdfc-6100-4ec8-ba3f-8bd26d184585", - "createdTimestamp" : 1623537499547, - "username" : "local", - "enabled" : true, - "totp" : false, - "emailVerified" : false, - "firstName" : "local F", - "lastName" : "local L", - "email" : "local@development.me", - "credentials" : [ { - "id" : "4ea10252-fd5d-476c-9e75-896230209ba5", - "type" : "password", - "createdDate" : 1623537499592, - "secretData" : "{\"value\":\"BuAJdiavdBRkL23vKkpx9Ua1jKeLagEd/AkExhMM5Npt5l9Q3HO3Z/Ksxen+TBGh0JZDMxpfHArCp7xaAaUThw==\",\"salt\":\"ASKUBGyIEAcGPJaCnkpk+A==\"}", - "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\"}" - } ], - "disableableCredentialTypes" : [ ], - "requiredActions" : [ ], - "realmRoles" : [ "uma_authorization", "offline_access", "api-owner", "admin" ], - "clientRoles" : { - "account" : [ "manage-account", "view-profile" ] + { + "id": "0cb6367d-605d-44ef-a15a-a180e5773bc2", + "createdTimestamp": 1638573942042, + "username": "mark", + "enabled": true, + "totp": false, + "emailVerified": false, + "firstName": "Mark F", + "lastName": "Mark L", + "email": "mark@gmail.com", + "credentials": [ + { + "id": "51f9551c-700c-48a4-a8c9-741089fc8123", + "type": "password", + "createdDate": 1638573942161, + "secretData": "{\"value\":\"I1XjV+HZkoHcNhSOHbICpyAlzyGyeqp/kPuIMvjcRP8oCD5x1FimGeZ8PISATtgcAq+QaSz3jx/ntodr3LbxOw==\",\"salt\":\"1Exw3iFjhc8E6DprXFm26w==\"}", + "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\"}" + } + ], + "disableableCredentialTypes": [], + "requiredActions": [], + "realmRoles": [ + "uma_authorization", + "offline_access", + "api-manager", + "admin" + ], + "clientRoles": { + "account": ["manage-account", "view-profile"] + }, + "notBefore": 0, + "groups": [] }, - "notBefore" : 0, - "groups" : [ ] - }, { - "id" : "0cb6367d-605d-44ef-a15a-a180e5773bc2", - "createdTimestamp" : 1638573942042, - "username" : "mark", - "enabled" : true, - "totp" : false, - "emailVerified" : false, - "firstName" : "Mark F", - "lastName" : "Mark L", - "email" : "mark@gmail.com", - "credentials" : [ { - "id" : "51f9551c-700c-48a4-a8c9-741089fc8123", - "type" : "password", - "createdDate" : 1638573942161, - "secretData" : "{\"value\":\"I1XjV+HZkoHcNhSOHbICpyAlzyGyeqp/kPuIMvjcRP8oCD5x1FimGeZ8PISATtgcAq+QaSz3jx/ntodr3LbxOw==\",\"salt\":\"1Exw3iFjhc8E6DprXFm26w==\"}", - "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\"}" - } ], - "disableableCredentialTypes" : [ ], - "requiredActions" : [ ], - "realmRoles" : [ "uma_authorization", "offline_access", "api-manager", "admin" ], - "clientRoles" : { - "account" : [ "manage-account", "view-profile" ] + { + "id": "dcd4bf36-c332-4888-a768-ae67d1207ccb", + "createdTimestamp": 1623445150804, + "username": "service-account-aps-portal", + "enabled": true, + "totp": false, + "emailVerified": false, + "serviceAccountClientId": "aps-portal", + "credentials": [], + "disableableCredentialTypes": [], + "requiredActions": [], + "realmRoles": ["uma_authorization", "offline_access"], + "clientRoles": { + "account": ["manage-account", "view-profile"] + }, + "notBefore": 0, + "groups": [] }, - "notBefore" : 0, - "groups" : [ ] - }, { - "id" : "dcd4bf36-c332-4888-a768-ae67d1207ccb", - "createdTimestamp" : 1623445150804, - "username" : "service-account-aps-portal", - "enabled" : true, - "totp" : false, - "emailVerified" : false, - "serviceAccountClientId" : "aps-portal", - "credentials" : [ ], - "disableableCredentialTypes" : [ ], - "requiredActions" : [ ], - "realmRoles" : [ "uma_authorization", "offline_access" ], - "clientRoles" : { - "account" : [ "manage-account", "view-profile" ] + { + "id": "0b87eb7b-28cd-43ec-b1fc-9c6b7ba12c9c", + "createdTimestamp": 1640110055487, + "username": "service-account-cypress-auth-profile", + "enabled": true, + "totp": false, + "emailVerified": false, + "serviceAccountClientId": "cypress-auth-profile", + "credentials": [], + "disableableCredentialTypes": [], + "requiredActions": [], + "realmRoles": ["uma_authorization", "offline_access"], + "clientRoles": { + "master-realm": [ + "manage-clients", + "view-users", + "create-client", + "manage-users" + ], + "account": ["manage-account", "view-profile"], + "cypress-auth-profile": ["uma_protection"] + }, + "notBefore": 0, + "groups": [] }, - "notBefore" : 0, - "groups" : [ ] - }, { - "id" : "0b87eb7b-28cd-43ec-b1fc-9c6b7ba12c9c", - "createdTimestamp" : 1640110055487, - "username" : "service-account-cypress-auth-profile", - "enabled" : true, - "totp" : false, - "emailVerified" : false, - "serviceAccountClientId" : "cypress-auth-profile", - "credentials" : [ ], - "disableableCredentialTypes" : [ ], - "requiredActions" : [ ], - "realmRoles" : [ "uma_authorization", "offline_access" ], - "clientRoles" : { - "master-realm" : [ "manage-clients", "view-users", "create-client", "manage-users" ], - "account" : [ "manage-account", "view-profile" ], - "cypress-auth-profile" : [ "uma_protection" ] + { + "id": "08e76239-85ee-4d2b-ac51-1fe737496fe8", + "createdTimestamp": 1625089066378, + "username": "service-account-gwa-api", + "enabled": true, + "totp": false, + "emailVerified": false, + "serviceAccountClientId": "gwa-api", + "credentials": [], + "disableableCredentialTypes": [], + "requiredActions": [], + "realmRoles": ["uma_authorization", "offline_access"], + "clientRoles": { + "gwa-api": ["uma_protection"], + "master-realm": [ + "manage-clients", + "view-users", + "create-client", + "manage-users", + "manage-authorization" + ], + "account": ["manage-account", "view-profile"] + }, + "notBefore": 0, + "groups": [] }, - "notBefore" : 0, - "groups" : [ ] - }, { - "id" : "08e76239-85ee-4d2b-ac51-1fe737496fe8", - "createdTimestamp" : 1625089066378, - "username" : "service-account-gwa-api", - "enabled" : true, - "totp" : false, - "emailVerified" : false, - "serviceAccountClientId" : "gwa-api", - "credentials" : [ ], - "disableableCredentialTypes" : [ ], - "requiredActions" : [ ], - "realmRoles" : [ "uma_authorization", "offline_access" ], - "clientRoles" : { - "gwa-api" : [ "uma_protection" ], - "master-realm" : [ "manage-clients", "view-users", "create-client", "manage-users", "manage-authorization" ], - "account" : [ "manage-account", "view-profile" ] + { + "id": "c795236e-fb09-4b4e-93e0-8bffb7dda7b3", + "createdTimestamp": 1650644631111, + "username": "service-account-sa-platform1-e0000000-5be82156d61f", + "enabled": true, + "totp": false, + "emailVerified": false, + "serviceAccountClientId": "sa-platform1-e0000000-5be82156d61f", + "credentials": [], + "disableableCredentialTypes": [], + "requiredActions": [], + "realmRoles": ["uma_authorization", "offline_access"], + "clientRoles": { + "account": ["manage-account", "view-profile"] + }, + "notBefore": 0, + "groups": [] }, - "notBefore" : 0, - "groups" : [ ] - }, { - "id" : "c795236e-fb09-4b4e-93e0-8bffb7dda7b3", - "createdTimestamp" : 1650644631111, - "username" : "service-account-sa-platform1-e0000000-5be82156d61f", - "enabled" : true, - "totp" : false, - "emailVerified" : false, - "serviceAccountClientId" : "sa-platform1-e0000000-5be82156d61f", - "credentials" : [ ], - "disableableCredentialTypes" : [ ], - "requiredActions" : [ ], - "realmRoles" : [ "uma_authorization", "offline_access" ], - "clientRoles" : { - "account" : [ "manage-account", "view-profile" ] + { + "id": "54adc719-3687-4886-9a7c-18c719a31014", + "createdTimestamp": 1651510581479, + "username": "service-account-sa-platform-e0000000-fa46551361b4", + "enabled": true, + "totp": false, + "emailVerified": false, + "serviceAccountClientId": "sa-platform-e0000000-fa46551361b4", + "credentials": [], + "disableableCredentialTypes": [], + "requiredActions": [], + "realmRoles": ["uma_authorization", "offline_access"], + "clientRoles": { + "account": ["manage-account", "view-profile"] + }, + "notBefore": 0, + "groups": [] }, - "notBefore" : 0, - "groups" : [ ] - }, { - "id" : "54adc719-3687-4886-9a7c-18c719a31014", - "createdTimestamp" : 1651510581479, - "username" : "service-account-sa-platform-e0000000-fa46551361b4", - "enabled" : true, - "totp" : false, - "emailVerified" : false, - "serviceAccountClientId" : "sa-platform-e0000000-fa46551361b4", - "credentials" : [ ], - "disableableCredentialTypes" : [ ], - "requiredActions" : [ ], - "realmRoles" : [ "uma_authorization", "offline_access" ], - "clientRoles" : { - "account" : [ "manage-account", "view-profile" ] + { + "id": "106ae49e-2334-4147-9f59-cd1ef50dab3b", + "createdTimestamp": 1645047852963, + "username": "wendy", + "enabled": true, + "totp": false, + "emailVerified": false, + "firstName": "Wendy F", + "lastName": "Wendy L", + "email": "wendy@test.com", + "credentials": [ + { + "id": "879b81f9-8dc9-40b2-afb5-805afc4e7e4d", + "type": "password", + "createdDate": 1645047984782, + "secretData": "{\"value\":\"itMDSu6kUt6bNPEHYdg9zH7jc2avU6W3JYTa/gNen7kGXGkanthdm60CWJ3E3lVnkBqniON8ntmnrNqSnOJv2g==\",\"salt\":\"kB81qbXXeMnX7k3DSvBmvQ==\"}", + "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\"}" + } + ], + "disableableCredentialTypes": [], + "requiredActions": [], + "realmRoles": ["uma_authorization", "credential-admin", "offline_access"], + "clientRoles": { + "account": ["manage-account", "view-profile"] + }, + "notBefore": 0, + "groups": [] }, - "notBefore" : 0, - "groups" : [ ] - }, { - "id" : "106ae49e-2334-4147-9f59-cd1ef50dab3b", - "createdTimestamp" : 1645047852963, - "username" : "wendy", - "enabled" : true, - "totp" : false, - "emailVerified" : false, - "firstName" : "Wendy F", - "lastName" : "Wendy L", - "email" : "wendy@test.com", - "credentials" : [ { - "id" : "879b81f9-8dc9-40b2-afb5-805afc4e7e4d", - "type" : "password", - "createdDate" : 1645047984782, - "secretData" : "{\"value\":\"itMDSu6kUt6bNPEHYdg9zH7jc2avU6W3JYTa/gNen7kGXGkanthdm60CWJ3E3lVnkBqniON8ntmnrNqSnOJv2g==\",\"salt\":\"kB81qbXXeMnX7k3DSvBmvQ==\"}", - "credentialData" : "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\"}" - } ], - "disableableCredentialTypes" : [ ], - "requiredActions" : [ ], - "realmRoles" : [ "uma_authorization", "credential-admin", "offline_access" ], - "clientRoles" : { - "account" : [ "manage-account", "view-profile" ] + { + "id": "bf498a7b-b6e0-49bb-9ea8-0241d7792f01", + "createdTimestamp": 1642463435902, + "username": "olduser@idir", + "enabled": true, + "totp": false, + "emailVerified": false, + "firstName": "oldF", + "lastName": "userL", + "email": "olduser@testmail.com", + "attributes": { + "provider_user_guid": ["220469E037C84A7ABDFAB15204A60701"], + "identity_provider": ["idir"], + "display_name": ["oldF userL"], + "provider_username": ["olduser@idir"] + }, + "credentials": [ + { + "id": "6aa0a7ca-c2ad-43f5-9bdb-3f58693b2801", + "type": "password", + "createdDate": 1642466403247, + "secretData": "{\"value\":\"ltS/DMUYOCSmZZRbf7rYFTpLa9cqQDewFO1jwRPczU99leiyGtOCsbdAPRmSvLVhOLnzqvcaua3B17ej2d6/7w==\",\"salt\":\"ZrR/QMSRwruFRU5FsPUgHQ==\"}", + "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\"}" + } + ], + "disableableCredentialTypes": [], + "requiredActions": [], + "realmRoles": [ + "uma_authorization", + "aps-admin", + "offline_access", + "api-owner" + ], + "clientRoles": { + "account": ["manage-account", "view-profile"] + }, + "notBefore": 0, + "groups": [] }, - "notBefore" : 0, - "groups" : [ ] - } ], - "scopeMappings" : [ { - "clientScope" : "offline_access", - "roles" : [ "offline_access" ] - } ], - "clientScopeMappings" : { - "account" : [ { - "client" : "account-console", - "roles" : [ "manage-account" ] - } ] + { + "id": "bf498a7b-b6e0-49bb-9ea8-0241d7792c01", + "createdTimestamp": 1642463435902, + "username": "220469E037C84A7ABDFAB15204A60701@olduser", + "enabled": true, + "totp": false, + "emailVerified": false, + "firstName": "oldF", + "lastName": "userL", + "email": "olduser@testmail.com", + "attributes": { + "provider_user_guid": ["220469E037C84A7ABDFAB15204A60701"], + "identity_provider": ["idir"], + "display_name": ["oldF userL"], + "provider_username": ["olduser"] + }, + "credentials": [ + { + "id": "6aa0a7ca-c2ad-43f5-9bdb-3f58693b2c01", + "type": "password", + "createdDate": 1642466403247, + "secretData": "{\"value\":\"ltS/DMUYOCSmZZRbf7rYFTpLa9cqQDewFO1jwRPczU99leiyGtOCsbdAPRmSvLVhOLnzqvcaua3B17ej2d6/7w==\",\"salt\":\"ZrR/QMSRwruFRU5FsPUgHQ==\"}", + "credentialData": "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\"}" + } + ], + "disableableCredentialTypes": [], + "requiredActions": [], + "realmRoles": [ + "uma_authorization", + "aps-admin", + "offline_access", + "api-owner" + ], + "clientRoles": { + "account": ["manage-account", "view-profile"] + }, + "notBefore": 0, + "groups": [] + } + ], + "scopeMappings": [ + { + "clientScope": "offline_access", + "roles": ["offline_access"] + } + ], + "clientScopeMappings": { + "account": [ + { + "client": "account-console", + "roles": ["manage-account"] + } + ] }, - "clients" : [ { - "id" : "bc61d6b7-6876-4193-9881-1b994596a207", - "clientId" : "account", - "name" : "${client_account}", - "rootUrl" : "${authBaseUrl}", - "baseUrl" : "/realms/master/account/", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "secret" : "**********", - "defaultRoles" : [ "manage-account", "view-profile" ], - "redirectUris" : [ "/realms/master/account/*" ], - "webOrigins" : [ ], - "notBefore" : 0, - "bearerOnly" : false, - "consentRequired" : false, - "standardFlowEnabled" : true, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : false, - "serviceAccountsEnabled" : false, - "publicClient" : false, - "frontchannelLogout" : false, - "protocol" : "openid-connect", - "attributes" : { }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : false, - "nodeReRegistrationTimeout" : 0, - "defaultClientScopes" : [ "web-origins", "role_list", "roles", "profile", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] - }, { - "id" : "0f7cdb03-8ae1-46a1-b97d-c7e8f8094517", - "clientId" : "account-console", - "name" : "${client_account-console}", - "rootUrl" : "${authBaseUrl}", - "baseUrl" : "/realms/master/account/", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "secret" : "**********", - "redirectUris" : [ "/realms/master/account/*" ], - "webOrigins" : [ ], - "notBefore" : 0, - "bearerOnly" : false, - "consentRequired" : false, - "standardFlowEnabled" : true, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : false, - "serviceAccountsEnabled" : false, - "publicClient" : true, - "frontchannelLogout" : false, - "protocol" : "openid-connect", - "attributes" : { - "pkce.code.challenge.method" : "S256" + "clients": [ + { + "id": "bc61d6b7-6876-4193-9881-1b994596a207", + "clientId": "account", + "name": "${client_account}", + "rootUrl": "${authBaseUrl}", + "baseUrl": "/realms/master/account/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "defaultRoles": ["manage-account", "view-profile"], + "redirectUris": ["/realms/master/account/*"], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : false, - "nodeReRegistrationTimeout" : 0, - "protocolMappers" : [ { - "id" : "7d9f3625-b978-4996-a063-12552470c586", - "name" : "audience resolve", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-audience-resolve-mapper", - "consentRequired" : false, - "config" : { } - } ], - "defaultClientScopes" : [ "web-origins", "role_list", "roles", "profile", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] - }, { - "id" : "4221af6b-3bc7-4685-8c69-e1ba30303101", - "clientId" : "admin-cli", - "name" : "${client_admin-cli}", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "secret" : "**********", - "redirectUris" : [ ], - "webOrigins" : [ ], - "notBefore" : 0, - "bearerOnly" : false, - "consentRequired" : false, - "standardFlowEnabled" : false, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : true, - "serviceAccountsEnabled" : false, - "publicClient" : true, - "frontchannelLogout" : false, - "protocol" : "openid-connect", - "attributes" : { }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : false, - "nodeReRegistrationTimeout" : 0, - "defaultClientScopes" : [ "web-origins", "role_list", "roles", "profile", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] - }, { - "id" : "f333c5e5-fba2-48e8-aab7-7b6862881202", - "clientId" : "aps-portal", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "secret" : "8e1a17ed-cb93-4806-ac32-e303d1c86018", - "redirectUris" : [ "http://*", "https://*" ], - "webOrigins" : [ "*" ], - "notBefore" : 0, - "bearerOnly" : false, - "consentRequired" : false, - "standardFlowEnabled" : true, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : true, - "serviceAccountsEnabled" : true, - "publicClient" : false, - "frontchannelLogout" : false, - "protocol" : "openid-connect", - "attributes" : { - "saml.assertion.signature" : "false", - "saml.force.post.binding" : "false", - "saml.multivalued.roles" : "false", - "saml.encrypt" : "false", - "saml.server.signature" : "false", - "saml.server.signature.keyinfo.ext" : "false", - "exclude.session.state.from.auth.response" : "false", - "saml_force_name_id_format" : "false", - "saml.client.signature" : "false", - "tls.client.certificate.bound.access.tokens" : "false", - "saml.authnstatement" : "false", - "display.on.consent.screen" : "false", - "saml.onetimeuse.condition" : "false" + { + "id": "0f7cdb03-8ae1-46a1-b97d-c7e8f8094517", + "clientId": "account-console", + "name": "${client_account-console}", + "rootUrl": "${authBaseUrl}", + "baseUrl": "/realms/master/account/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": ["/realms/master/account/*"], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "pkce.code.challenge.method": "S256" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "7d9f3625-b978-4996-a063-12552470c586", + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": false, + "config": {} + } + ], + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : false, - "nodeReRegistrationTimeout" : -1, - "protocolMappers" : [ { - "id" : "390fa558-2b62-4399-adfb-e2ec96784813", - "name" : "Client Host", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usersessionmodel-note-mapper", - "consentRequired" : false, - "config" : { - "user.session.note" : "clientHost", - "userinfo.token.claim" : "true", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "clientHost", - "jsonType.label" : "String" - } - }, { - "id" : "8df082aa-710d-4be7-b396-87323a710e84", - "name" : "identity_provider", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "user.attribute" : "identity_provider", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "identity_provider", - "userinfo.token.claim" : "true" - } - }, { - "id" : "d9196236-636f-4459-ac3b-2b0f9b87681d", - "name" : "Client ID", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usersessionmodel-note-mapper", - "consentRequired" : false, - "config" : { - "user.session.note" : "clientId", - "userinfo.token.claim" : "true", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "clientId", - "jsonType.label" : "String" + { + "id": "4221af6b-3bc7-4685-8c69-e1ba30303101", + "clientId": "admin-cli", + "name": "${client_admin-cli}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": false, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "f333c5e5-fba2-48e8-aab7-7b6862881202", + "clientId": "aps-portal", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "8e1a17ed-cb93-4806-ac32-e303d1c86018", + "redirectUris": ["http://*", "https://*"], + "webOrigins": ["*"], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": true, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "saml.assertion.signature": "false", + "saml.force.post.binding": "false", + "saml.multivalued.roles": "false", + "saml.encrypt": "false", + "saml.server.signature": "false", + "saml.server.signature.keyinfo.ext": "false", + "exclude.session.state.from.auth.response": "false", + "saml_force_name_id_format": "false", + "saml.client.signature": "false", + "tls.client.certificate.bound.access.tokens": "false", + "saml.authnstatement": "false", + "display.on.consent.screen": "false", + "saml.onetimeuse.condition": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": -1, + "protocolMappers": [ + { + "id": "390fa558-2b62-4399-adfb-e2ec96784813", + "name": "Client Host", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientHost", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientHost", + "jsonType.label": "String" + } + }, + { + "id": "8df082aa-710d-4be7-b396-87323a710e84", + "name": "identity_provider", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "user.attribute": "identity_provider", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "identity_provider", + "userinfo.token.claim": "true" + } + }, + { + "id": "d9196236-636f-4459-ac3b-2b0f9b87681d", + "name": "Client ID", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientId", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientId", + "jsonType.label": "String" + } + }, + { + "id": "f088eda3-2a14-45a4-8e91-1f669152a6e3", + "name": "Client IP Address", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientAddress", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientAddress", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "Namespace.Create", + "role_list", + "roles", + "Namespace.Admin", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "62f2227e-e1ac-4c74-b278-1eab7f7664ae", + "clientId": "aps-v2-realm", + "name": "aps-v2 Realm", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": true, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "db7f58dc-c007-4e4c-ad7b-14f57a0521cd", + "clientId": "broker", + "name": "${client_broker}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "50c78923-95d9-4083-87ff-5233f2d6326e", + "clientId": "cypress-auth-profile", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "43badfc1-c06f-4bec-bab6-ccdc764071ac", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": false, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": true, + "authorizationServicesEnabled": true, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "saml.assertion.signature": "false", + "saml.force.post.binding": "false", + "saml.multivalued.roles": "false", + "saml.encrypt": "false", + "saml.server.signature": "false", + "saml.server.signature.keyinfo.ext": "false", + "exclude.session.state.from.auth.response": "false", + "saml_force_name_id_format": "false", + "saml.client.signature": "false", + "tls.client.certificate.bound.access.tokens": "false", + "saml.authnstatement": "false", + "display.on.consent.screen": "false", + "saml.onetimeuse.condition": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "protocolMappers": [ + { + "id": "e5b7aae4-4667-40a4-bef5-34abb759e338", + "name": "Client Host", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientHost", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientHost", + "jsonType.label": "String" + } + }, + { + "id": "6d728625-6d5e-4363-90cc-e3b68baa756a", + "name": "Client ID", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientId", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientId", + "jsonType.label": "String" + } + }, + { + "id": "bbf72323-f9f4-44c1-8088-df564fe7b494", + "name": "Client IP Address", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientAddress", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientAddress", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "role_list", + "Namespace.Create", + "Namespace.Admin", + "roles", + "profile", + "System.Write", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ], + "authorizationSettings": { + "allowRemoteResourceManagement": true, + "policyEnforcementMode": "ENFORCING", + "resources": [ + { + "name": "Default Resource", + "type": "urn:cypress-auth-profile:resources:default", + "ownerManagedAccess": false, + "attributes": {}, + "_id": "8543a438-ee7e-44b7-aa28-aef951b65f2f", + "uris": ["/*"] + } + ], + "policies": [ + { + "id": "34e0a630-d6fa-499c-b7b7-bca8b6ef70f6", + "name": "Default Policy", + "description": "A policy that grants access only for users within this realm", + "type": "js", + "logic": "POSITIVE", + "decisionStrategy": "AFFIRMATIVE", + "config": { + "code": "// by default, grants any permission associated with this policy\n$evaluation.grant();\n" + } + }, + { + "id": "a1bbc96c-4248-4f32-8bec-59569165bcb8", + "name": "Default Permission", + "description": "A permission that applies to the default resource type", + "type": "resource", + "logic": "POSITIVE", + "decisionStrategy": "UNANIMOUS", + "config": { + "defaultResourceType": "urn:cypress-auth-profile:resources:default", + "applyPolicies": "[\"Default Policy\"]" + } + } + ], + "scopes": [], + "decisionStrategy": "UNANIMOUS" } - }, { - "id" : "f088eda3-2a14-45a4-8e91-1f669152a6e3", - "name" : "Client IP Address", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usersessionmodel-note-mapper", - "consentRequired" : false, - "config" : { - "user.session.note" : "clientAddress", - "userinfo.token.claim" : "true", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "clientAddress", - "jsonType.label" : "String" + }, + { + "id": "c002b2b1-0ca8-4fd6-896e-6d2e3395a345", + "clientId": "gwa-api", + "rootUrl": "https://gwa-api-gov-bc-ca.dev.api.gov.bc.ca", + "adminUrl": "https://gwa-api-gov-bc-ca.dev.api.gov.bc.ca", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "18900468-3db1-43f7-a8af-e75f079eb742", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": false, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": true, + "authorizationServicesEnabled": true, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "saml.assertion.signature": "false", + "saml.force.post.binding": "false", + "saml.multivalued.roles": "false", + "saml.encrypt": "false", + "saml.server.signature": "false", + "saml.server.signature.keyinfo.ext": "false", + "exclude.session.state.from.auth.response": "false", + "saml_force_name_id_format": "false", + "saml.client.signature": "false", + "tls.client.certificate.bound.access.tokens": "false", + "saml.authnstatement": "false", + "display.on.consent.screen": "false", + "saml.onetimeuse.condition": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "protocolMappers": [ + { + "id": "4f2fdd5d-7cd7-427b-bce3-60ac808570da", + "name": "Client IP Address", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientAddress", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientAddress", + "jsonType.label": "String" + } + }, + { + "id": "3ef8dcec-57b5-4217-9991-c3144ffafc19", + "name": "Client Host", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientHost", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientHost", + "jsonType.label": "String" + } + }, + { + "id": "9e857953-1628-4deb-a568-9a59af3c985f", + "name": "Client ID", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientId", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientId", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "Namespace.Create", + "role_list", + "roles", + "Namespace.Admin", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ], + "authorizationSettings": { + "allowRemoteResourceManagement": true, + "policyEnforcementMode": "ENFORCING", + "resources": [ + { + "name": "Default Resource", + "type": "urn:gwa-api:resources:default", + "ownerManagedAccess": false, + "attributes": {}, + "_id": "054b9d22-ce05-4b1c-86bf-424eb7f3ca13", + "uris": ["/*"] + }, + { + "name": "platform1", + "type": "namespace", + "ownerManagedAccess": true, + "attributes": {}, + "_id": "fa9f93b8-b1c1-45ab-ad65-672befbdaedc", + "uris": [], + "scopes": [ + { + "name": "GatewayConfig.Publish" + }, + { + "name": "Namespace.Manage" + }, + { + "name": "Access.Manage" + }, + { + "name": "Content.Publish" + }, + { + "name": "Namespace.View" + }, + { + "name": "CredentialIssuer.Admin" + } + ] + }, + { + "name": "platform2", + "type": "namespace", + "ownerManagedAccess": true, + "attributes": {}, + "_id": "c6ad734c-6d8f-4b90-bcf9-cb9c19eadc22", + "uris": [], + "scopes": [ + { + "name": "GatewayConfig.Publish" + }, + { + "name": "Namespace.Manage" + }, + { + "name": "Access.Manage" + }, + { + "name": "Content.Publish" + }, + { + "name": "Namespace.View" + }, + { + "name": "CredentialIssuer.Admin" + } + ] + }, + { + "name": "platform", + "type": "namespace", + "ownerManagedAccess": true, + "attributes": {}, + "_id": "501a70b7-546a-43f3-8992-a4c170f0bab7", + "uris": [], + "scopes": [ + { + "name": "GatewayConfig.Publish" + }, + { + "name": "Namespace.Manage" + }, + { + "name": "Access.Manage" + }, + { + "name": "Content.Publish" + }, + { + "name": "Namespace.View" + }, + { + "name": "CredentialIssuer.Admin" + } + ] + }, + { + "name": "org/ca.bc.gov", + "type": "organization", + "ownerManagedAccess": true, + "displayName": "org/ca.bc.gov", + "attributes": {}, + "_id": "228c26be-3ef4-43d6-92ec-8441ebf5887c", + "uris": [], + "scopes": [ + { + "name": "GroupAccess.Manage" + } + ] + }, + { + "name": "org/ministry-of-health", + "type": "organization", + "ownerManagedAccess": true, + "attributes": {}, + "_id": "2367ab08-6c6e-42e4-b1db-3a86de3a028d", + "uris": [], + "scopes": [ + { + "name": "GroupAccess.Manage" + }, + { + "name": "Dataset.Manage" + }, + { + "name": "Namespace.Assign" + } + ] + }, + { + "name": "org/planning-and-innovation-division", + "type": "organization", + "ownerManagedAccess": true, + "attributes": {}, + "_id": "032644b7-a3a0-489e-bda3-193bd14d861a", + "uris": [], + "scopes": [ + { + "name": "GroupAccess.Manage" + }, + { + "name": "Dataset.Manage" + }, + { + "name": "Namespace.Assign" + } + ] + } + ], + "policies": [ + { + "id": "35dcd837-d215-4036-84fe-452605b0a065", + "name": "Default Policy", + "description": "A policy that grants access only for users within this realm", + "type": "js", + "logic": "POSITIVE", + "decisionStrategy": "AFFIRMATIVE", + "config": { + "code": "// by default, grants any permission associated with this policy\n$evaluation.grant();\n" + } + }, + { + "id": "ca06ef6c-d7f8-42c9-b0d6-0c9be85c1cc1", + "name": "janis", + "type": "user", + "logic": "POSITIVE", + "decisionStrategy": "UNANIMOUS", + "config": { + "users": "[\"janis@idir\"]" + } + }, + { + "id": "c3848ff4-76b0-4f2d-afe9-7dfd77467fcb", + "name": "group-organization-admin-ca.bc.gov-policy", + "description": "Group '/organization-admin' / 'ca.bc.gov' Policy", + "type": "group", + "logic": "POSITIVE", + "decisionStrategy": "UNANIMOUS", + "config": { + "groups": "[{\"path\":\"/organization-admin\",\"extendChildren\":false},{\"path\":\"/organization-admin/ca.bc.gov\",\"extendChildren\":false}]" + } + }, + { + "id": "6f49c571-fbbb-4f86-a72a-c1591a446bb3", + "name": "group-organization-admin-ca.bc.gov-ministry-of-health-policy", + "description": "Group '/organization-admin/ca.bc.gov' / 'ministry-of-health' Policy", + "type": "group", + "logic": "POSITIVE", + "decisionStrategy": "UNANIMOUS", + "config": { + "groups": "[{\"path\":\"/organization-admin/ca.bc.gov/ministry-of-health\",\"extendChildren\":false},{\"path\":\"/organization-admin\",\"extendChildren\":false},{\"path\":\"/organization-admin/ca.bc.gov\",\"extendChildren\":false}]" + } + }, + { + "id": "99fdf1a9-d5ec-48c7-a2cd-1ddeb130b058", + "name": "group-organization-admin-ca.bc.gov-ministry-of-health-planning-and-innovation-division-policy", + "description": "Group '/organization-admin/ca.bc.gov/ministry-of-health' / 'planning-and-innovation-division' Policy", + "type": "group", + "logic": "POSITIVE", + "decisionStrategy": "UNANIMOUS", + "config": { + "groups": "[{\"path\":\"/organization-admin/ca.bc.gov\",\"extendChildren\":false},{\"path\":\"/organization-admin/ca.bc.gov/ministry-of-health/planning-and-innovation-division\",\"extendChildren\":false},{\"path\":\"/organization-admin/ca.bc.gov/ministry-of-health\",\"extendChildren\":false},{\"path\":\"/organization-admin\",\"extendChildren\":false}]" + } + }, + { + "id": "31be7436-e9d8-42a3-b42e-69a1869a7eea", + "name": "Default Permission", + "description": "A permission that applies to the default resource type", + "type": "resource", + "logic": "POSITIVE", + "decisionStrategy": "UNANIMOUS", + "config": { + "defaultResourceType": "urn:gwa-api:resources:default", + "applyPolicies": "[\"Default Policy\"]" + } + }, + { + "id": "65f0c0a4-e2ac-4364-800d-ebd4e11ce393", + "name": "janis full access", + "type": "scope", + "logic": "POSITIVE", + "decisionStrategy": "UNANIMOUS", + "config": { + "scopes": "[\"GroupAccess.Manage\",\"Namespace.Assign\"]", + "applyPolicies": "[\"janis\"]" + } + }, + { + "id": "854f0dfe-952d-48f8-9d53-d49b0b4ed122", + "name": "Access to 'org/ca.bc.gov' services for role organization-admin", + "type": "scope", + "logic": "POSITIVE", + "decisionStrategy": "UNANIMOUS", + "config": { + "resources": "[\"org/ca.bc.gov\"]", + "scopes": "[\"GroupAccess.Manage\"]", + "applyPolicies": "[\"group-organization-admin-ca.bc.gov-policy\"]" + } + }, + { + "id": "3f934d3f-d231-48fc-9f5a-924da7808989", + "name": "Access to 'org/ministry-of-health' services for role organization-admin", + "type": "scope", + "logic": "POSITIVE", + "decisionStrategy": "UNANIMOUS", + "config": { + "resources": "[\"org/ministry-of-health\"]", + "scopes": "[\"Dataset.Manage\",\"GroupAccess.Manage\",\"Namespace.Assign\"]", + "applyPolicies": "[\"group-organization-admin-ca.bc.gov-ministry-of-health-policy\"]" + } + }, + { + "id": "56a4857d-a0be-472c-85d0-2dca93a1fdac", + "name": "Access to 'org/planning-and-innovation-division' services for role organization-admin", + "type": "scope", + "logic": "POSITIVE", + "decisionStrategy": "UNANIMOUS", + "config": { + "resources": "[\"org/planning-and-innovation-division\"]", + "scopes": "[\"Dataset.Manage\",\"GroupAccess.Manage\",\"Namespace.Assign\"]", + "applyPolicies": "[\"group-organization-admin-ca.bc.gov-ministry-of-health-planning-and-innovation-division-policy\"]" + } + }, + { + "id": "f2e764aa-c355-4e81-a5e6-e76ffb86041f", + "name": "Access to 'platform' services for role organization-admin", + "type": "scope", + "logic": "POSITIVE", + "decisionStrategy": "UNANIMOUS", + "config": { + "resources": "[\"platform\"]", + "scopes": "[\"Namespace.View\"]", + "applyPolicies": "[\"group-organization-admin-ca.bc.gov-ministry-of-health-planning-and-innovation-division-policy\"]" + } + } + ], + "scopes": [ + { + "id": "6871ce8b-5d5f-455b-86ff-7cf5940930eb", + "name": "Namespace.Manage" + }, + { + "id": "0006d34f-1416-4ffb-ad1f-39ebf63f9556", + "name": "Namespace.View" + }, + { + "id": "a4d424c9-7331-4715-96a9-ecfd1dd0cf2c", + "name": "GatewayConfig.Publish" + }, + { + "id": "fd403d7f-1dfb-4673-8ab3-5e1ff7797b35", + "name": "Access.Manage" + }, + { + "id": "0f98e35d-c2c3-4781-bf85-478bf06cfa24", + "name": "Content.Publish" + }, + { + "id": "dfc132ca-aa87-40b5-bc33-3e972a88f638", + "name": "CredentialIssuer.Admin" + }, + { + "id": "95893c25-6b83-4e59-9518-a25568d95542", + "name": "GroupAccess.Manage", + "iconUri": "", + "displayName": "GroupAccess.Manage" + }, + { + "id": "b0b007b1-1ecb-4b3f-9f0c-41b3fa34754c", + "name": "Dataset.Manage" + }, + { + "id": "f3bf8d43-54a4-4594-aeea-f61b99411f92", + "name": "Namespace.Assign" + } + ], + "decisionStrategy": "AFFIRMATIVE" } - } ], - "defaultClientScopes" : [ "web-origins", "Namespace.Create", "role_list", "roles", "Namespace.Admin", "profile", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] - }, { - "id" : "62f2227e-e1ac-4c74-b278-1eab7f7664ae", - "clientId" : "aps-v2-realm", - "name" : "aps-v2 Realm", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "secret" : "**********", - "redirectUris" : [ ], - "webOrigins" : [ ], - "notBefore" : 0, - "bearerOnly" : true, - "consentRequired" : false, - "standardFlowEnabled" : true, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : false, - "serviceAccountsEnabled" : false, - "publicClient" : false, - "frontchannelLogout" : false, - "protocol" : "openid-connect", - "attributes" : { }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : true, - "nodeReRegistrationTimeout" : 0, - "defaultClientScopes" : [ "web-origins", "role_list", "roles", "profile", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] - }, { - "id" : "db7f58dc-c007-4e4c-ad7b-14f57a0521cd", - "clientId" : "broker", - "name" : "${client_broker}", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "secret" : "**********", - "redirectUris" : [ ], - "webOrigins" : [ ], - "notBefore" : 0, - "bearerOnly" : false, - "consentRequired" : false, - "standardFlowEnabled" : true, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : false, - "serviceAccountsEnabled" : false, - "publicClient" : false, - "frontchannelLogout" : false, - "protocol" : "openid-connect", - "attributes" : { }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : false, - "nodeReRegistrationTimeout" : 0, - "defaultClientScopes" : [ "web-origins", "role_list", "roles", "profile", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] - }, { - "id" : "50c78923-95d9-4083-87ff-5233f2d6326e", - "clientId" : "cypress-auth-profile", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "secret" : "43badfc1-c06f-4bec-bab6-ccdc764071ac", - "redirectUris" : [ ], - "webOrigins" : [ ], - "notBefore" : 0, - "bearerOnly" : false, - "consentRequired" : false, - "standardFlowEnabled" : false, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : false, - "serviceAccountsEnabled" : true, - "authorizationServicesEnabled" : true, - "publicClient" : false, - "frontchannelLogout" : false, - "protocol" : "openid-connect", - "attributes" : { - "saml.assertion.signature" : "false", - "saml.force.post.binding" : "false", - "saml.multivalued.roles" : "false", - "saml.encrypt" : "false", - "saml.server.signature" : "false", - "saml.server.signature.keyinfo.ext" : "false", - "exclude.session.state.from.auth.response" : "false", - "saml_force_name_id_format" : "false", - "saml.client.signature" : "false", - "tls.client.certificate.bound.access.tokens" : "false", - "saml.authnstatement" : "false", - "display.on.consent.screen" : "false", - "saml.onetimeuse.condition" : "false" }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : true, - "nodeReRegistrationTimeout" : -1, - "protocolMappers" : [ { - "id" : "e5b7aae4-4667-40a4-bef5-34abb759e338", - "name" : "Client Host", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usersessionmodel-note-mapper", - "consentRequired" : false, - "config" : { - "user.session.note" : "clientHost", - "userinfo.token.claim" : "true", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "clientHost", - "jsonType.label" : "String" + { + "id": "4e6525e9-647c-4c80-85d6-9c13890b0ab2", + "clientId": "master-realm", + "name": "master Realm", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": true, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "4bbc355d-7a87-4476-9593-7f9359dc8859", + "clientId": "sa-platform1-e0000000-5be82156d61f", + "name": "", + "description": "", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "c01a7839-2679-4cdd-96c4-173223b49ee6", + "redirectUris": ["https://*"], + "webOrigins": ["*"], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": false, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": true, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "saml.assertion.signature": "false", + "saml.multivalued.roles": "false", + "saml.force.post.binding": "false", + "saml.encrypt": "false", + "saml.server.signature": "false", + "saml.server.signature.keyinfo.ext": "false", + "exclude.session.state.from.auth.response": "false", + "client_credentials.use_refresh_token": "false", + "saml_force_name_id_format": "false", + "saml.client.signature": "false", + "tls.client.certificate.bound.access.tokens": "false", + "saml.authnstatement": "false", + "display.on.consent.screen": "false", + "saml.onetimeuse.condition": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": -1, + "protocolMappers": [ + { + "id": "d5b56ac0-01af-4241-991e-1cd25edeb739", + "name": "Client ID", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientId", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientId", + "jsonType.label": "String" + } + }, + { + "id": "8c119e4b-b308-41aa-be7b-91e1d299e499", + "name": "Client Host", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientHost", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientHost", + "jsonType.label": "String" + } + }, + { + "id": "3ba852b4-71b8-4942-950b-80968346b0e2", + "name": "Client IP Address", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientAddress", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientAddress", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": [], + "optionalClientScopes": [] + }, + { + "id": "25ee1923-6323-4c4c-ae70-178615ace3b2", + "clientId": "sa-platform-e0000000-fa46551361b4", + "name": "", + "description": "", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "dc96e3d3-23cc-4345-aa5e-6f89b5d20c91", + "redirectUris": ["https://*"], + "webOrigins": ["*"], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": false, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": true, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "saml.assertion.signature": "false", + "saml.multivalued.roles": "false", + "saml.force.post.binding": "false", + "saml.encrypt": "false", + "saml.server.signature": "false", + "saml.server.signature.keyinfo.ext": "false", + "exclude.session.state.from.auth.response": "false", + "client_credentials.use_refresh_token": "false", + "saml_force_name_id_format": "false", + "saml.client.signature": "false", + "tls.client.certificate.bound.access.tokens": "false", + "saml.authnstatement": "false", + "display.on.consent.screen": "false", + "saml.onetimeuse.condition": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": -1, + "protocolMappers": [ + { + "id": "270af568-11bf-4208-bccd-58583e44f09c", + "name": "Client IP Address", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientAddress", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientAddress", + "jsonType.label": "String" + } + }, + { + "id": "9dda9072-1e47-43fd-a482-6830b252ca5b", + "name": "Client Host", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientHost", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientHost", + "jsonType.label": "String" + } + }, + { + "id": "a35858ac-39ad-46bc-9227-e40698049c62", + "name": "Client ID", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientId", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientId", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": [], + "optionalClientScopes": [] + }, + { + "id": "5c797848-2f03-4085-a03a-e4f7c22d0050", + "clientId": "security-admin-console", + "name": "${client_security-admin-console}", + "rootUrl": "${authAdminUrl}", + "baseUrl": "/admin/master/console/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": ["/admin/master/console/*"], + "webOrigins": ["+"], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "pkce.code.challenge.method": "S256" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "c5b453d6-73e5-40f2-bc65-375b571f7d6c", + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "role_list", + "roles", + "profile", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + } + ], + "clientScopes": [ + { + "id": "f5d4d8e2-6e57-477a-83b0-88047af5285d", + "name": "Content.Publish", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true" } - }, { - "id" : "6d728625-6d5e-4363-90cc-e3b68baa756a", - "name" : "Client ID", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usersessionmodel-note-mapper", - "consentRequired" : false, - "config" : { - "user.session.note" : "clientId", - "userinfo.token.claim" : "true", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "clientId", - "jsonType.label" : "String" + }, + { + "id": "4f7a31ce-a48b-4816-baff-4dbc378d4a10", + "name": "Namespace.Admin", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true" } - }, { - "id" : "bbf72323-f9f4-44c1-8088-df564fe7b494", - "name" : "Client IP Address", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usersessionmodel-note-mapper", - "consentRequired" : false, - "config" : { - "user.session.note" : "clientAddress", - "userinfo.token.claim" : "true", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "clientAddress", - "jsonType.label" : "String" + }, + { + "id": "5c280525-34b7-4436-a567-ad5a75f0b093", + "name": "Namespace.Create", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true" } - } ], - "defaultClientScopes" : [ "web-origins", "role_list", "Namespace.Create", "Namespace.Admin", "roles", "profile", "System.Write", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ], - "authorizationSettings" : { - "allowRemoteResourceManagement" : true, - "policyEnforcementMode" : "ENFORCING", - "resources" : [ { - "name" : "Default Resource", - "type" : "urn:cypress-auth-profile:resources:default", - "ownerManagedAccess" : false, - "attributes" : { }, - "_id" : "8543a438-ee7e-44b7-aa28-aef951b65f2f", - "uris" : [ "/*" ] - } ], - "policies" : [ { - "id" : "34e0a630-d6fa-499c-b7b7-bca8b6ef70f6", - "name" : "Default Policy", - "description" : "A policy that grants access only for users within this realm", - "type" : "js", - "logic" : "POSITIVE", - "decisionStrategy" : "AFFIRMATIVE", - "config" : { - "code" : "// by default, grants any permission associated with this policy\n$evaluation.grant();\n" + }, + { + "id": "e78e5fd1-5ee2-4215-a5c3-a8581a19c716", + "name": "address", + "description": "OpenID Connect built-in scope: address", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${addressScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "b2a36609-2408-44fd-88ac-ef41fa62f5f4", + "name": "address", + "protocol": "openid-connect", + "protocolMapper": "oidc-address-mapper", + "consentRequired": false, + "config": { + "user.attribute.formatted": "formatted", + "user.attribute.country": "country", + "user.attribute.postal_code": "postal_code", + "userinfo.token.claim": "true", + "user.attribute.street": "street", + "id.token.claim": "true", + "user.attribute.region": "region", + "access.token.claim": "true", + "user.attribute.locality": "locality" + } + } + ] + }, + { + "id": "89e870cc-7056-4bc0-8cf2-9c961ff4a62d", + "name": "email", + "description": "OpenID Connect built-in scope: email", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${emailScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "7fb89890-a73f-4162-9ca3-e1539905ccb6", + "name": "email verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "emailVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email_verified", + "jsonType.label": "boolean" + } + }, + { + "id": "9ec60f35-65c9-4ea2-ab0e-2fc2c462d892", + "name": "email", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "email", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email", + "jsonType.label": "String" + } } - }, { - "id" : "a1bbc96c-4248-4f32-8bec-59569165bcb8", - "name" : "Default Permission", - "description" : "A permission that applies to the default resource type", - "type" : "resource", - "logic" : "POSITIVE", - "decisionStrategy" : "UNANIMOUS", - "config" : { - "defaultResourceType" : "urn:cypress-auth-profile:resources:default", - "applyPolicies" : "[\"Default Policy\"]" + ] + }, + { + "id": "920764e0-6019-462b-bc25-f17a54562752", + "name": "microprofile-jwt", + "description": "Microprofile - JWT built-in scope", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "cd9090fd-faf4-450a-9144-3a9e04260095", + "name": "groups", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "multivalued": "true", + "userinfo.token.claim": "true", + "user.attribute": "foo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "groups", + "jsonType.label": "String" + } + }, + { + "id": "9ca3b431-06e3-43f0-9277-a6dec6ec1172", + "name": "upn", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "upn", + "jsonType.label": "String" + } } - } ], - "scopes" : [ ], - "decisionStrategy" : "UNANIMOUS" - } - }, { - "id" : "c002b2b1-0ca8-4fd6-896e-6d2e3395a345", - "clientId" : "gwa-api", - "rootUrl" : "https://gwa-api-gov-bc-ca.dev.api.gov.bc.ca", - "adminUrl" : "https://gwa-api-gov-bc-ca.dev.api.gov.bc.ca", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "secret" : "18900468-3db1-43f7-a8af-e75f079eb742", - "redirectUris" : [ ], - "webOrigins" : [ ], - "notBefore" : 0, - "bearerOnly" : false, - "consentRequired" : false, - "standardFlowEnabled" : false, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : false, - "serviceAccountsEnabled" : true, - "authorizationServicesEnabled" : true, - "publicClient" : false, - "frontchannelLogout" : false, - "protocol" : "openid-connect", - "attributes" : { - "saml.assertion.signature" : "false", - "saml.force.post.binding" : "false", - "saml.multivalued.roles" : "false", - "saml.encrypt" : "false", - "saml.server.signature" : "false", - "saml.server.signature.keyinfo.ext" : "false", - "exclude.session.state.from.auth.response" : "false", - "saml_force_name_id_format" : "false", - "saml.client.signature" : "false", - "tls.client.certificate.bound.access.tokens" : "false", - "saml.authnstatement" : "false", - "display.on.consent.screen" : "false", - "saml.onetimeuse.condition" : "false" + ] }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : true, - "nodeReRegistrationTimeout" : -1, - "protocolMappers" : [ { - "id" : "4f2fdd5d-7cd7-427b-bce3-60ac808570da", - "name" : "Client IP Address", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usersessionmodel-note-mapper", - "consentRequired" : false, - "config" : { - "user.session.note" : "clientAddress", - "userinfo.token.claim" : "true", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "clientAddress", - "jsonType.label" : "String" + { + "id": "bb473906-0c39-4af1-aad9-d8788dc7559f", + "name": "offline_access", + "description": "OpenID Connect built-in scope: offline_access", + "protocol": "openid-connect", + "attributes": { + "consent.screen.text": "${offlineAccessScopeConsentText}", + "display.on.consent.screen": "true" } - }, { - "id" : "3ef8dcec-57b5-4217-9991-c3144ffafc19", - "name" : "Client Host", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usersessionmodel-note-mapper", - "consentRequired" : false, - "config" : { - "user.session.note" : "clientHost", - "userinfo.token.claim" : "true", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "clientHost", - "jsonType.label" : "String" + }, + { + "id": "e5e16f12-1b4c-47e7-9599-99ff395f359c", + "name": "phone", + "description": "OpenID Connect built-in scope: phone", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${phoneScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "8d83aa08-43a9-49f5-b1dd-caa144e2cad5", + "name": "phone number", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "phoneNumber", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number", + "jsonType.label": "String" + } + }, + { + "id": "3886e58f-d64f-4851-80f3-ae7cc5c6ab13", + "name": "phone number verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "phoneNumberVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number_verified", + "jsonType.label": "boolean" + } + } + ] + }, + { + "id": "f33d0489-2a52-4066-9c38-e130c02665ee", + "name": "profile", + "description": "OpenID Connect built-in scope: profile", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${profileScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "1826e2b1-380a-4c65-a73e-3bb79f519550", + "name": "website", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "website", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "website", + "jsonType.label": "String" + } + }, + { + "id": "6ea0a08a-ab42-4b45-acfc-a05f5b452cb0", + "name": "nickname", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "nickname", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "nickname", + "jsonType.label": "String" + } + }, + { + "id": "78d97855-5557-4f10-9d20-74d8ea6bdfef", + "name": "full name", + "protocol": "openid-connect", + "protocolMapper": "oidc-full-name-mapper", + "consentRequired": false, + "config": { + "id.token.claim": "true", + "access.token.claim": "true", + "userinfo.token.claim": "true" + } + }, + { + "id": "22e60a23-914f-40bf-960d-e7a96655581d", + "name": "picture", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "picture", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "picture", + "jsonType.label": "String" + } + }, + { + "id": "e595c828-c815-4dff-bd8f-39b1eee5a3b3", + "name": "birthdate", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "birthdate", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "birthdate", + "jsonType.label": "String" + } + }, + { + "id": "cd91c70b-0856-4f5d-aeb6-9b5c3b48a966", + "name": "zoneinfo", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "zoneinfo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "zoneinfo", + "jsonType.label": "String" + } + }, + { + "id": "4ce90553-d828-4146-92e0-ee1775c9ba28", + "name": "updated at", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "updatedAt", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "updated_at", + "jsonType.label": "String" + } + }, + { + "id": "43710808-227e-4171-a106-7576f933a32b", + "name": "family name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "lastName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "family_name", + "jsonType.label": "String" + } + }, + { + "id": "a814d5c0-bdcd-4f33-8cfd-228005f2ba94", + "name": "gender", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "gender", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "gender", + "jsonType.label": "String" + } + }, + { + "id": "df9e1465-617d-4a7b-a208-7354c6cbaada", + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + }, + { + "id": "fc508e60-a978-41f1-bea2-311673b4b0a8", + "name": "given name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "firstName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "given_name", + "jsonType.label": "String" + } + }, + { + "id": "8e4641a3-87d3-4958-8113-dcfa82f0ef54", + "name": "middle name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "middleName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "middle_name", + "jsonType.label": "String" + } + }, + { + "id": "ffc38939-9e10-4cf3-b4fc-65203e079a92", + "name": "username", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "preferred_username", + "jsonType.label": "String" + } + }, + { + "id": "9364fe99-268a-4a74-88aa-a120a6897e78", + "name": "profile", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "profile", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "profile", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "b5a38584-219b-4618-a3a5-70814bed867e", + "name": "role_list", + "description": "SAML role list", + "protocol": "saml", + "attributes": { + "consent.screen.text": "${samlRoleListScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "id": "1a0a5251-1b3f-47b1-8cc1-07a285d6479f", + "name": "role list", + "protocol": "saml", + "protocolMapper": "saml-role-list-mapper", + "consentRequired": false, + "config": { + "single": "false", + "attribute.nameformat": "Basic", + "attribute.name": "Role" + } + } + ] + }, + { + "id": "33bd4c0f-225f-43cb-8b6c-0bd4db702525", + "name": "roles", + "description": "OpenID Connect scope for add user roles to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "true", + "consent.screen.text": "${rolesScopeConsentText}" + }, + "protocolMappers": [ + { + "id": "e276a79b-99cc-4f10-8d26-0e10ce245fdb", + "name": "client roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-client-role-mapper", + "consentRequired": false, + "config": { + "user.attribute": "foo", + "access.token.claim": "true", + "claim.name": "resource_access.${client_id}.roles", + "jsonType.label": "String", + "multivalued": "true" + } + }, + { + "id": "b64cc3a2-8ed8-4dee-a13a-fef5588a5949", + "name": "realm roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "user.attribute": "foo", + "access.token.claim": "true", + "claim.name": "realm_access.roles", + "jsonType.label": "String", + "multivalued": "true" + } + }, + { + "id": "c9828318-6d78-4aba-94ea-405f12fce589", + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": false, + "config": {} + } + ] + }, + { + "id": "0bfddcf3-017d-44b6-8447-297c565d5d2d", + "name": "web-origins", + "description": "OpenID Connect scope for add allowed web origins to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "false", + "consent.screen.text": "" + }, + "protocolMappers": [ + { + "id": "28867dcd-803d-47a5-be90-51be8a331527", + "name": "allowed web origins", + "protocol": "openid-connect", + "protocolMapper": "oidc-allowed-origins-mapper", + "consentRequired": false, + "config": {} + } + ] + }, + { + "id": "e28fac82-4db1-4900-8096-74706a71f7f3", + "name": "System.Write", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true" } - }, { - "id" : "9e857953-1628-4deb-a568-9a59af3c985f", - "name" : "Client ID", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usersessionmodel-note-mapper", - "consentRequired" : false, - "config" : { - "user.session.note" : "clientId", - "userinfo.token.claim" : "true", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "clientId", - "jsonType.label" : "String" + } + ], + "defaultDefaultClientScopes": [ + "web-origins", + "roles", + "Namespace.Admin", + "Namespace.Create", + "email", + "role_list", + "profile" + ], + "defaultOptionalClientScopes": [ + "microprofile-jwt", + "offline_access", + "phone", + "address" + ], + "browserSecurityHeaders": { + "contentSecurityPolicyReportOnly": "", + "xContentTypeOptions": "nosniff", + "xRobotsTag": "none", + "xFrameOptions": "SAMEORIGIN", + "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "xXSSProtection": "1; mode=block", + "strictTransportSecurity": "max-age=31536000; includeSubDomains" + }, + "smtpServer": {}, + "eventsEnabled": false, + "eventsListeners": ["jboss-logging"], + "enabledEventTypes": [], + "adminEventsEnabled": false, + "adminEventsDetailsEnabled": false, + "components": { + "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [ + { + "id": "d7699c96-1cc0-46fe-b0fe-c72c7f7d1804", + "name": "Consent Required", + "providerId": "consent-required", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "522f0c4c-8dfe-4421-b573-0e5723319dac", + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allow-default-scopes": ["true"] + } + }, + { + "id": "2502109c-1319-4bcd-bf94-a5225239c42b", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "oidc-full-name-mapper", + "saml-user-property-mapper", + "oidc-sha256-pairwise-sub-mapper", + "saml-user-attribute-mapper", + "oidc-usermodel-attribute-mapper", + "oidc-address-mapper", + "saml-role-list-mapper", + "oidc-usermodel-property-mapper" + ] + } + }, + { + "id": "013bd2ad-80e7-40fe-ba41-b90642d536cd", + "name": "Trusted Hosts", + "providerId": "trusted-hosts", + "subType": "anonymous", + "subComponents": {}, + "config": { + "host-sending-registration-request-must-match": ["true"], + "client-uris-must-match": ["true"] + } + }, + { + "id": "c0bcf5a2-ef5f-4f03-95c7-ea15f27c8cd7", + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allow-default-scopes": ["true"] + } + }, + { + "id": "1157f7fe-a055-4ec3-8af8-3f809fd2fec0", + "name": "Full Scope Disabled", + "providerId": "scope", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "650e6c8f-8a93-4096-9d37-1aecfe000e49", + "name": "Max Clients Limit", + "providerId": "max-clients", + "subType": "anonymous", + "subComponents": {}, + "config": { + "max-clients": ["200"] + } + }, + { + "id": "93e21f15-c390-475a-865a-3f8125b1ccc9", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "oidc-usermodel-property-mapper", + "oidc-sha256-pairwise-sub-mapper", + "oidc-address-mapper", + "saml-role-list-mapper", + "saml-user-property-mapper", + "oidc-full-name-mapper", + "saml-user-attribute-mapper", + "oidc-usermodel-attribute-mapper" + ] + } } - } ], - "defaultClientScopes" : [ "web-origins", "Namespace.Create", "role_list", "roles", "Namespace.Admin", "profile", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ], - "authorizationSettings" : { - "allowRemoteResourceManagement" : true, - "policyEnforcementMode" : "ENFORCING", - "resources" : [ { - "name" : "Default Resource", - "type" : "urn:gwa-api:resources:default", - "ownerManagedAccess" : false, - "attributes" : { }, - "_id" : "054b9d22-ce05-4b1c-86bf-424eb7f3ca13", - "uris" : [ "/*" ] - }, { - "name" : "platform1", - "type" : "namespace", - "ownerManagedAccess" : true, - "attributes" : { }, - "_id" : "fa9f93b8-b1c1-45ab-ad65-672befbdaedc", - "uris" : [ ], - "scopes" : [ { - "name" : "GatewayConfig.Publish" - }, { - "name" : "Namespace.Manage" - }, { - "name" : "Access.Manage" - }, { - "name" : "Content.Publish" - }, { - "name" : "Namespace.View" - }, { - "name" : "CredentialIssuer.Admin" - } ] - }, { - "name" : "platform2", - "type" : "namespace", - "ownerManagedAccess" : true, - "attributes" : { }, - "_id" : "c6ad734c-6d8f-4b90-bcf9-cb9c19eadc22", - "uris" : [ ], - "scopes" : [ { - "name" : "GatewayConfig.Publish" - }, { - "name" : "Namespace.Manage" - }, { - "name" : "Access.Manage" - }, { - "name" : "Content.Publish" - }, { - "name" : "Namespace.View" - }, { - "name" : "CredentialIssuer.Admin" - } ] - }, { - "name" : "platform", - "type" : "namespace", - "ownerManagedAccess" : true, - "attributes" : { }, - "_id" : "501a70b7-546a-43f3-8992-a4c170f0bab7", - "uris" : [ ], - "scopes" : [ { - "name" : "GatewayConfig.Publish" - }, { - "name" : "Namespace.Manage" - }, { - "name" : "Access.Manage" - }, { - "name" : "Content.Publish" - }, { - "name" : "Namespace.View" - }, { - "name" : "CredentialIssuer.Admin" - } ] - }, { - "name" : "org/ca.bc.gov", - "type" : "organization", - "ownerManagedAccess" : true, - "displayName" : "org/ca.bc.gov", - "attributes" : { }, - "_id" : "228c26be-3ef4-43d6-92ec-8441ebf5887c", - "uris" : [ ], - "scopes" : [ { - "name" : "GroupAccess.Manage" - } ] - }, { - "name" : "org/ministry-of-health", - "type" : "organization", - "ownerManagedAccess" : true, - "attributes" : { }, - "_id" : "2367ab08-6c6e-42e4-b1db-3a86de3a028d", - "uris" : [ ], - "scopes" : [ { - "name" : "GroupAccess.Manage" - }, { - "name" : "Dataset.Manage" - }, { - "name" : "Namespace.Assign" - } ] - }, { - "name" : "org/planning-and-innovation-division", - "type" : "organization", - "ownerManagedAccess" : true, - "attributes" : { }, - "_id" : "032644b7-a3a0-489e-bda3-193bd14d861a", - "uris" : [ ], - "scopes" : [ { - "name" : "GroupAccess.Manage" - }, { - "name" : "Dataset.Manage" - }, { - "name" : "Namespace.Assign" - } ] - } ], - "policies" : [ { - "id" : "35dcd837-d215-4036-84fe-452605b0a065", - "name" : "Default Policy", - "description" : "A policy that grants access only for users within this realm", - "type" : "js", - "logic" : "POSITIVE", - "decisionStrategy" : "AFFIRMATIVE", - "config" : { - "code" : "// by default, grants any permission associated with this policy\n$evaluation.grant();\n" + ], + "org.keycloak.keys.KeyProvider": [ + { + "id": "2b0c7bcb-c441-4694-8639-7175a1956655", + "name": "hmac-generated", + "providerId": "hmac-generated", + "subComponents": {}, + "config": { + "kid": ["1b23b32b-bb69-4a9a-b20d-770d009ffb67"], + "active": ["true"], + "secretSize": ["64"], + "secret": [ + "FqB7weAN-07obv1h7cltkFANraOPiK3BN-x1fBR7BY3yF_tOVVy0faPtS24pbPB5VJMXrvZBVy4MvQbhPGOn-A" + ], + "priority": ["100"], + "enabled": ["true"], + "algorithm": ["HS256"] } - }, { - "id" : "ca06ef6c-d7f8-42c9-b0d6-0c9be85c1cc1", - "name" : "janis", - "type" : "user", - "logic" : "POSITIVE", - "decisionStrategy" : "UNANIMOUS", - "config" : { - "users" : "[\"janis@idir\"]" + }, + { + "id": "82953e3c-d927-4f6f-8b57-3b5c7b8903d6", + "name": "rsa-generated", + "providerId": "rsa-generated", + "subComponents": {}, + "config": { + "privateKey": [ + "MIIEpAIBAAKCAQEAtE+K9HXgyAM2I3gmzReAKg3ukb0LgHI00kBz79cTLX+aXjAMl5n3cajJZuVBPj+Cyy4fm4vB7tHMTcY5StOMcQv95DZvmonQkweU87quqfETLTp6607tUfUdRib5W/euaKqVbCi09xwSftBeHHCcvotFTz/IjnZ6Ul/qZcDzXgoLEiaZrKz3iSFsnuJEWiozFP+hPZNESfRz/jqd7PcD++SO1iLtMjB5BPvlB7cFWDaWww+nUPbnsqsLZzwdAzhAjYe17x2AafffkZUUp1rf5VXEz8bzAoMpRZDswhG+v1jUPg638b3LFakV6PhRTvLnoKRpPvdzLmRguXtxufrQDwIDAQABAoIBAG0CLcrPPR8OuftFl4ekbop+M74OIVb9NKvr5WuZhnGaVHQe7m302mDvnxtC/Geqs+MsNlWub4d3dOGMNnTjYmOx0UPYGS6/pMZO7iFPumrpYSOV2FxMMjO7UYBo7ZZJLjr+7ikejxFZ+mCKjmr5NfoIbtWThSeDvz3v2OC9fyRZPE/AAqsy9Gkhukxnsi4nJOBK89nLeZS1nbGPzJxu9jiNm2snWI56N7orrVW5KBR/ynaFMN5CepYqgzK5uXv9dkzjBgiQbPlXk9c+LIWrrjXFxjftJTiop6C938B1MlfamkUsoQLwG1Uh8SQNgBExFUOeegouOJthbjhhVdPe/QkCgYEA/7Y5B2Sm0S+DXfoWyHS26ZQ2fDu9WweLbnGL9KrKd4T7u5Ubu9+qTu1aU2m7RxRya9yHzzVXSiTEKPoTPCjC9CIGA3YtQxze2zf7un+RfdN0Ty9pBZiKbAavsX5+KyIliC6FQy0O48eWR7LMsVSFJGGIeYPTjgY3U34uLsN55RUCgYEAtIOQxc1AFw/wcQIsJYEZWmwUIEd49s6x6iCBXez1sfZLJVHL5mE7NNxT0vuSKwxMK4gddSoRjBDqWGgge93HlIz+N+Ln656zCdLlOlDGe5a3jvtxIRKak/mp+nmk8G+FGGlAatPIRmZQbk0hIzh0m88k8hJ7NqRXTDeDDmzmcZMCgYEAgpvOcSpF0l7UWHHepTCIJLIhSj8xLoeh/h1dAPEjTPzNnzg/3CwXzwyIsEY2881LzC/t5jY2iZZR4yQoIvgm649dRvNblwXuBkaH+vAhngUdSTzMBaGuQhMANkaHpvxf8zjftDoVet58sc5voruq7bQrgvWEXuxp4el3KUeKwSkCgYAmOa4QlPQ7bf6mj6U1k+8AfN6OL1RoP0DhqVx7vVASDWvATV/2OyTEftupU+iSARqoJTzHsM7icDqP2gz27fHzfR/gScZ+2K5lKCmufahqR3I7bvd3326oYzgheFz7JUJz9uXTOWGxtrzVfrPDt5LJ48WZFVzOJ2LtGtw/08PAzQKBgQDy/mQxGSxIImcBcjdHDP7kb5T3M69PWN/VER1AMvkU+60uQTfZ7sXsJhWQn6XgzHF9ZhpTJeeliNn9dcTFOt9sWEoLspxZNz/RoKeW2P6p1krjrz74XDOgce63AaXufAFIGUDrJhCcIbyvalEvVQyDnnWe/dHl4us/DX+/+GWjVQ==" + ], + "keySize": ["2048"], + "certificate": [ + "MIICmzCCAYMCBgF6AmA7pTANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZtYXN0ZXIwHhcNMjEwNjEyMjIzNjM5WhcNMzEwNjEyMjIzODE5WjARMQ8wDQYDVQQDDAZtYXN0ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC0T4r0deDIAzYjeCbNF4AqDe6RvQuAcjTSQHPv1xMtf5peMAyXmfdxqMlm5UE+P4LLLh+bi8Hu0cxNxjlK04xxC/3kNm+aidCTB5Tzuq6p8RMtOnrrTu1R9R1GJvlb965oqpVsKLT3HBJ+0F4ccJy+i0VPP8iOdnpSX+plwPNeCgsSJpmsrPeJIWye4kRaKjMU/6E9k0RJ9HP+Op3s9wP75I7WIu0yMHkE++UHtwVYNpbDD6dQ9ueyqwtnPB0DOECNh7XvHYBp99+RlRSnWt/lVcTPxvMCgylFkOzCEb6/WNQ+DrfxvcsVqRXo+FFO8uegpGk+93MuZGC5e3G5+tAPAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAD25ZjxPFys+OAoSmgRuk4KwpTG4cLm3vEwUjD60+gvYJk3bFUgxErNv+Ax69PN4OZwMh9fdnVHRx0haVno0ULUBintRP/P0ond1mw7HB1v/i9EMpRiVoMEL8y3wV363XVw6mDrYI8Pp0OihJBKo5I1EWgaLAl+lu9YS6f3VXaASgqx1AaV6qZiXM95FOeYkjpx30cbIR6uhRAfBHz10PO//RhTCnBrjasU921qFSMH3EuvRZET0jB68FLF7uRFK+goSVrw9O+TcK6Cbh4I4GZX66ZBRW6MTTIzYNsSuSMUlGFujGcVi5+1JmJgJg76coIo7NIR68KPKyh+47Mvy9bI=" + ], + "active": ["true"], + "priority": ["100"], + "enabled": ["true"], + "algorithm": ["RS256"] } - }, { - "id" : "c3848ff4-76b0-4f2d-afe9-7dfd77467fcb", - "name" : "group-organization-admin-ca.bc.gov-policy", - "description" : "Group '/organization-admin' / 'ca.bc.gov' Policy", - "type" : "group", - "logic" : "POSITIVE", - "decisionStrategy" : "UNANIMOUS", - "config" : { - "groups" : "[{\"path\":\"/organization-admin\",\"extendChildren\":false},{\"path\":\"/organization-admin/ca.bc.gov\",\"extendChildren\":false}]" + }, + { + "id": "4ac9540a-c5b7-48b0-b3e1-1a7887ed5414", + "name": "aes-generated", + "providerId": "aes-generated", + "subComponents": {}, + "config": { + "kid": ["8fc9ebb4-d633-4fbc-a940-43414dbb6841"], + "active": ["true"], + "secretSize": ["16"], + "secret": ["mwpmhvHuQq_qLZAKhngrjg"], + "priority": ["100"], + "enabled": ["true"] } - }, { - "id" : "6f49c571-fbbb-4f86-a72a-c1591a446bb3", - "name" : "group-organization-admin-ca.bc.gov-ministry-of-health-policy", - "description" : "Group '/organization-admin/ca.bc.gov' / 'ministry-of-health' Policy", - "type" : "group", - "logic" : "POSITIVE", - "decisionStrategy" : "UNANIMOUS", - "config" : { - "groups" : "[{\"path\":\"/organization-admin/ca.bc.gov/ministry-of-health\",\"extendChildren\":false},{\"path\":\"/organization-admin\",\"extendChildren\":false},{\"path\":\"/organization-admin/ca.bc.gov\",\"extendChildren\":false}]" + } + ] + }, + "internationalizationEnabled": false, + "supportedLocales": [], + "authenticationFlows": [ + { + "id": "fad0619f-460c-48b9-a877-f75157be2498", + "alias": "Account verification options", + "description": "Method with which to verity the existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-email-verification", + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "ALTERNATIVE", + "priority": 20, + "flowAlias": "Verify Existing Account by Re-authentication", + "userSetupAllowed": false, + "autheticatorFlow": true } - }, { - "id" : "99fdf1a9-d5ec-48c7-a2cd-1ddeb130b058", - "name" : "group-organization-admin-ca.bc.gov-ministry-of-health-planning-and-innovation-division-policy", - "description" : "Group '/organization-admin/ca.bc.gov/ministry-of-health' / 'planning-and-innovation-division' Policy", - "type" : "group", - "logic" : "POSITIVE", - "decisionStrategy" : "UNANIMOUS", - "config" : { - "groups" : "[{\"path\":\"/organization-admin/ca.bc.gov\",\"extendChildren\":false},{\"path\":\"/organization-admin/ca.bc.gov/ministry-of-health/planning-and-innovation-division\",\"extendChildren\":false},{\"path\":\"/organization-admin/ca.bc.gov/ministry-of-health\",\"extendChildren\":false},{\"path\":\"/organization-admin\",\"extendChildren\":false}]" + ] + }, + { + "id": "33504bb1-b977-4948-a6ff-3c68adf583e4", + "alias": "Authentication Options", + "description": "Authentication options.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "basic-auth", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "basic-auth-otp", + "requirement": "DISABLED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-spnego", + "requirement": "DISABLED", + "priority": 30, + "userSetupAllowed": false, + "autheticatorFlow": false } - }, { - "id" : "31be7436-e9d8-42a3-b42e-69a1869a7eea", - "name" : "Default Permission", - "description" : "A permission that applies to the default resource type", - "type" : "resource", - "logic" : "POSITIVE", - "decisionStrategy" : "UNANIMOUS", - "config" : { - "defaultResourceType" : "urn:gwa-api:resources:default", - "applyPolicies" : "[\"Default Policy\"]" + ] + }, + { + "id": "bfe57f7a-b041-4a15-be88-44894c673f24", + "alias": "Browser - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-otp-form", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false } - }, { - "id" : "65f0c0a4-e2ac-4364-800d-ebd4e11ce393", - "name" : "janis full access", - "type" : "scope", - "logic" : "POSITIVE", - "decisionStrategy" : "UNANIMOUS", - "config" : { - "scopes" : "[\"GroupAccess.Manage\",\"Namespace.Assign\"]", - "applyPolicies" : "[\"janis\"]" + ] + }, + { + "id": "377ac00d-87d0-4752-8aa0-90459e334175", + "alias": "Direct Grant - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "direct-grant-validate-otp", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false } - }, { - "id" : "854f0dfe-952d-48f8-9d53-d49b0b4ed122", - "name" : "Access to 'org/ca.bc.gov' services for role organization-admin", - "type" : "scope", - "logic" : "POSITIVE", - "decisionStrategy" : "UNANIMOUS", - "config" : { - "resources" : "[\"org/ca.bc.gov\"]", - "scopes" : "[\"GroupAccess.Manage\"]", - "applyPolicies" : "[\"group-organization-admin-ca.bc.gov-policy\"]" + ] + }, + { + "id": "23859306-7ccf-4313-9a8e-0dc39ca6749e", + "alias": "First broker login - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-otp-form", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false } - }, { - "id" : "3f934d3f-d231-48fc-9f5a-924da7808989", - "name" : "Access to 'org/ministry-of-health' services for role organization-admin", - "type" : "scope", - "logic" : "POSITIVE", - "decisionStrategy" : "UNANIMOUS", - "config" : { - "resources" : "[\"org/ministry-of-health\"]", - "scopes" : "[\"Dataset.Manage\",\"GroupAccess.Manage\",\"Namespace.Assign\"]", - "applyPolicies" : "[\"group-organization-admin-ca.bc.gov-ministry-of-health-policy\"]" + ] + }, + { + "id": "60b03eac-baf5-47e9-8e69-89c4292487fd", + "alias": "Handle Existing Account", + "description": "Handle what to do if there is existing account with same email/username like authenticated identity provider", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-confirm-link", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "REQUIRED", + "priority": 20, + "flowAlias": "Account verification options", + "userSetupAllowed": false, + "autheticatorFlow": true } - }, { - "id" : "56a4857d-a0be-472c-85d0-2dca93a1fdac", - "name" : "Access to 'org/planning-and-innovation-division' services for role organization-admin", - "type" : "scope", - "logic" : "POSITIVE", - "decisionStrategy" : "UNANIMOUS", - "config" : { - "resources" : "[\"org/planning-and-innovation-division\"]", - "scopes" : "[\"Dataset.Manage\",\"GroupAccess.Manage\",\"Namespace.Assign\"]", - "applyPolicies" : "[\"group-organization-admin-ca.bc.gov-ministry-of-health-planning-and-innovation-division-policy\"]" + ] + }, + { + "id": "2a42f367-4220-478d-bbbc-36def807b298", + "alias": "Reset - Conditional OTP", + "description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "reset-otp", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false } - }, { - "id" : "f2e764aa-c355-4e81-a5e6-e76ffb86041f", - "name" : "Access to 'platform' services for role organization-admin", - "type" : "scope", - "logic" : "POSITIVE", - "decisionStrategy" : "UNANIMOUS", - "config" : { - "resources" : "[\"platform\"]", - "scopes" : "[\"Namespace.View\"]", - "applyPolicies" : "[\"group-organization-admin-ca.bc.gov-ministry-of-health-planning-and-innovation-division-policy\"]" + ] + }, + { + "id": "6f87a5c3-1a77-456e-b649-b0adfb5c5d47", + "alias": "User creation or linking", + "description": "Flow for the existing/non-existing user alternatives", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "create unique user config", + "authenticator": "idp-create-user-if-unique", + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "ALTERNATIVE", + "priority": 20, + "flowAlias": "Handle Existing Account", + "userSetupAllowed": false, + "autheticatorFlow": true } - } ], - "scopes" : [ { - "id" : "6871ce8b-5d5f-455b-86ff-7cf5940930eb", - "name" : "Namespace.Manage" - }, { - "id" : "0006d34f-1416-4ffb-ad1f-39ebf63f9556", - "name" : "Namespace.View" - }, { - "id" : "a4d424c9-7331-4715-96a9-ecfd1dd0cf2c", - "name" : "GatewayConfig.Publish" - }, { - "id" : "fd403d7f-1dfb-4673-8ab3-5e1ff7797b35", - "name" : "Access.Manage" - }, { - "id" : "0f98e35d-c2c3-4781-bf85-478bf06cfa24", - "name" : "Content.Publish" - }, { - "id" : "dfc132ca-aa87-40b5-bc33-3e972a88f638", - "name" : "CredentialIssuer.Admin" - }, { - "id" : "95893c25-6b83-4e59-9518-a25568d95542", - "name" : "GroupAccess.Manage", - "iconUri" : "", - "displayName" : "GroupAccess.Manage" - }, { - "id" : "b0b007b1-1ecb-4b3f-9f0c-41b3fa34754c", - "name" : "Dataset.Manage" - }, { - "id" : "f3bf8d43-54a4-4594-aeea-f61b99411f92", - "name" : "Namespace.Assign" - } ], - "decisionStrategy" : "AFFIRMATIVE" - } - }, { - "id" : "4e6525e9-647c-4c80-85d6-9c13890b0ab2", - "clientId" : "master-realm", - "name" : "master Realm", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "secret" : "**********", - "redirectUris" : [ ], - "webOrigins" : [ ], - "notBefore" : 0, - "bearerOnly" : true, - "consentRequired" : false, - "standardFlowEnabled" : true, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : false, - "serviceAccountsEnabled" : false, - "publicClient" : false, - "frontchannelLogout" : false, - "protocol" : "openid-connect", - "attributes" : { }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : true, - "nodeReRegistrationTimeout" : 0, - "defaultClientScopes" : [ "web-origins", "role_list", "roles", "profile", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] - }, { - "id" : "4bbc355d-7a87-4476-9593-7f9359dc8859", - "clientId" : "sa-platform1-e0000000-5be82156d61f", - "name" : "", - "description" : "", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "secret" : "c01a7839-2679-4cdd-96c4-173223b49ee6", - "redirectUris" : [ "https://*" ], - "webOrigins" : [ "*" ], - "notBefore" : 0, - "bearerOnly" : false, - "consentRequired" : false, - "standardFlowEnabled" : false, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : false, - "serviceAccountsEnabled" : true, - "publicClient" : false, - "frontchannelLogout" : false, - "protocol" : "openid-connect", - "attributes" : { - "saml.assertion.signature" : "false", - "saml.multivalued.roles" : "false", - "saml.force.post.binding" : "false", - "saml.encrypt" : "false", - "saml.server.signature" : "false", - "saml.server.signature.keyinfo.ext" : "false", - "exclude.session.state.from.auth.response" : "false", - "client_credentials.use_refresh_token" : "false", - "saml_force_name_id_format" : "false", - "saml.client.signature" : "false", - "tls.client.certificate.bound.access.tokens" : "false", - "saml.authnstatement" : "false", - "display.on.consent.screen" : "false", - "saml.onetimeuse.condition" : "false" + ] }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : false, - "nodeReRegistrationTimeout" : -1, - "protocolMappers" : [ { - "id" : "d5b56ac0-01af-4241-991e-1cd25edeb739", - "name" : "Client ID", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usersessionmodel-note-mapper", - "consentRequired" : false, - "config" : { - "user.session.note" : "clientId", - "userinfo.token.claim" : "true", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "clientId", - "jsonType.label" : "String" - } - }, { - "id" : "8c119e4b-b308-41aa-be7b-91e1d299e499", - "name" : "Client Host", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usersessionmodel-note-mapper", - "consentRequired" : false, - "config" : { - "user.session.note" : "clientHost", - "userinfo.token.claim" : "true", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "clientHost", - "jsonType.label" : "String" - } - }, { - "id" : "3ba852b4-71b8-4942-950b-80968346b0e2", - "name" : "Client IP Address", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usersessionmodel-note-mapper", - "consentRequired" : false, - "config" : { - "user.session.note" : "clientAddress", - "userinfo.token.claim" : "true", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "clientAddress", - "jsonType.label" : "String" - } - } ], - "defaultClientScopes" : [ ], - "optionalClientScopes" : [ ] - }, { - "id" : "25ee1923-6323-4c4c-ae70-178615ace3b2", - "clientId" : "sa-platform-e0000000-fa46551361b4", - "name" : "", - "description" : "", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "secret" : "dc96e3d3-23cc-4345-aa5e-6f89b5d20c91", - "redirectUris" : [ "https://*" ], - "webOrigins" : [ "*" ], - "notBefore" : 0, - "bearerOnly" : false, - "consentRequired" : false, - "standardFlowEnabled" : false, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : false, - "serviceAccountsEnabled" : true, - "publicClient" : false, - "frontchannelLogout" : false, - "protocol" : "openid-connect", - "attributes" : { - "saml.assertion.signature" : "false", - "saml.multivalued.roles" : "false", - "saml.force.post.binding" : "false", - "saml.encrypt" : "false", - "saml.server.signature" : "false", - "saml.server.signature.keyinfo.ext" : "false", - "exclude.session.state.from.auth.response" : "false", - "client_credentials.use_refresh_token" : "false", - "saml_force_name_id_format" : "false", - "saml.client.signature" : "false", - "tls.client.certificate.bound.access.tokens" : "false", - "saml.authnstatement" : "false", - "display.on.consent.screen" : "false", - "saml.onetimeuse.condition" : "false" + { + "id": "2262356b-b4ab-4d1c-beb4-267198ce85ef", + "alias": "Verify Existing Account by Re-authentication", + "description": "Reauthentication of existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-username-password-form", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "CONDITIONAL", + "priority": 20, + "flowAlias": "First broker login - Conditional OTP", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : false, - "nodeReRegistrationTimeout" : -1, - "protocolMappers" : [ { - "id" : "270af568-11bf-4208-bccd-58583e44f09c", - "name" : "Client IP Address", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usersessionmodel-note-mapper", - "consentRequired" : false, - "config" : { - "user.session.note" : "clientAddress", - "userinfo.token.claim" : "true", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "clientAddress", - "jsonType.label" : "String" - } - }, { - "id" : "9dda9072-1e47-43fd-a482-6830b252ca5b", - "name" : "Client Host", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usersessionmodel-note-mapper", - "consentRequired" : false, - "config" : { - "user.session.note" : "clientHost", - "userinfo.token.claim" : "true", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "clientHost", - "jsonType.label" : "String" - } - }, { - "id" : "a35858ac-39ad-46bc-9227-e40698049c62", - "name" : "Client ID", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usersessionmodel-note-mapper", - "consentRequired" : false, - "config" : { - "user.session.note" : "clientId", - "userinfo.token.claim" : "true", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "clientId", - "jsonType.label" : "String" - } - } ], - "defaultClientScopes" : [ ], - "optionalClientScopes" : [ ] - }, { - "id" : "5c797848-2f03-4085-a03a-e4f7c22d0050", - "clientId" : "security-admin-console", - "name" : "${client_security-admin-console}", - "rootUrl" : "${authAdminUrl}", - "baseUrl" : "/admin/master/console/", - "surrogateAuthRequired" : false, - "enabled" : true, - "alwaysDisplayInConsole" : false, - "clientAuthenticatorType" : "client-secret", - "secret" : "**********", - "redirectUris" : [ "/admin/master/console/*" ], - "webOrigins" : [ "+" ], - "notBefore" : 0, - "bearerOnly" : false, - "consentRequired" : false, - "standardFlowEnabled" : true, - "implicitFlowEnabled" : false, - "directAccessGrantsEnabled" : false, - "serviceAccountsEnabled" : false, - "publicClient" : true, - "frontchannelLogout" : false, - "protocol" : "openid-connect", - "attributes" : { - "pkce.code.challenge.method" : "S256" + { + "id": "9a82a84c-49be-427c-8d4e-e193a4d7a353", + "alias": "browser", + "description": "browser based authentication", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-cookie", + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-spnego", + "requirement": "DISABLED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "identity-provider-redirector", + "requirement": "ALTERNATIVE", + "priority": 25, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "ALTERNATIVE", + "priority": 30, + "flowAlias": "forms", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] }, - "authenticationFlowBindingOverrides" : { }, - "fullScopeAllowed" : false, - "nodeReRegistrationTimeout" : 0, - "protocolMappers" : [ { - "id" : "c5b453d6-73e5-40f2-bc65-375b571f7d6c", - "name" : "locale", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "locale", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "locale", - "jsonType.label" : "String" - } - } ], - "defaultClientScopes" : [ "web-origins", "role_list", "roles", "profile", "email" ], - "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] - } ], - "clientScopes" : [ { - "id" : "f5d4d8e2-6e57-477a-83b0-88047af5285d", - "name" : "Content.Publish", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "true", - "display.on.consent.screen" : "true" - } - }, { - "id" : "4f7a31ce-a48b-4816-baff-4dbc378d4a10", - "name" : "Namespace.Admin", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "true", - "display.on.consent.screen" : "true" - } - }, { - "id" : "5c280525-34b7-4436-a567-ad5a75f0b093", - "name" : "Namespace.Create", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "true", - "display.on.consent.screen" : "true" - } - }, { - "id" : "e78e5fd1-5ee2-4215-a5c3-a8581a19c716", - "name" : "address", - "description" : "OpenID Connect built-in scope: address", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "true", - "display.on.consent.screen" : "true", - "consent.screen.text" : "${addressScopeConsentText}" + { + "id": "de2f29cf-ac12-4c88-b2e3-bb1e061dd013", + "alias": "clients", + "description": "Base authentication for clients", + "providerId": "client-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "client-secret", + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "client-jwt", + "requirement": "ALTERNATIVE", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "client-secret-jwt", + "requirement": "ALTERNATIVE", + "priority": 30, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "client-x509", + "requirement": "ALTERNATIVE", + "priority": 40, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] }, - "protocolMappers" : [ { - "id" : "b2a36609-2408-44fd-88ac-ef41fa62f5f4", - "name" : "address", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-address-mapper", - "consentRequired" : false, - "config" : { - "user.attribute.formatted" : "formatted", - "user.attribute.country" : "country", - "user.attribute.postal_code" : "postal_code", - "userinfo.token.claim" : "true", - "user.attribute.street" : "street", - "id.token.claim" : "true", - "user.attribute.region" : "region", - "access.token.claim" : "true", - "user.attribute.locality" : "locality" - } - } ] - }, { - "id" : "89e870cc-7056-4bc0-8cf2-9c961ff4a62d", - "name" : "email", - "description" : "OpenID Connect built-in scope: email", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "true", - "display.on.consent.screen" : "true", - "consent.screen.text" : "${emailScopeConsentText}" + { + "id": "79023955-88dd-4230-9185-9aee45846718", + "alias": "direct grant", + "description": "OpenID Connect Resource Owner Grant", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "direct-grant-validate-username", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "direct-grant-validate-password", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "CONDITIONAL", + "priority": 30, + "flowAlias": "Direct Grant - Conditional OTP", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] }, - "protocolMappers" : [ { - "id" : "7fb89890-a73f-4162-9ca3-e1539905ccb6", - "name" : "email verified", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-property-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "emailVerified", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "email_verified", - "jsonType.label" : "boolean" - } - }, { - "id" : "9ec60f35-65c9-4ea2-ab0e-2fc2c462d892", - "name" : "email", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-property-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "email", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "email", - "jsonType.label" : "String" - } - } ] - }, { - "id" : "920764e0-6019-462b-bc25-f17a54562752", - "name" : "microprofile-jwt", - "description" : "Microprofile - JWT built-in scope", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "true", - "display.on.consent.screen" : "false" + { + "id": "bcb59a24-d9e3-449a-95a8-cb8e39dbda09", + "alias": "docker auth", + "description": "Used by Docker clients to authenticate against the IDP", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "docker-http-basic-authenticator", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] }, - "protocolMappers" : [ { - "id" : "cd9090fd-faf4-450a-9144-3a9e04260095", - "name" : "groups", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-realm-role-mapper", - "consentRequired" : false, - "config" : { - "multivalued" : "true", - "userinfo.token.claim" : "true", - "user.attribute" : "foo", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "groups", - "jsonType.label" : "String" - } - }, { - "id" : "9ca3b431-06e3-43f0-9277-a6dec6ec1172", - "name" : "upn", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-property-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "username", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "upn", - "jsonType.label" : "String" - } - } ] - }, { - "id" : "bb473906-0c39-4af1-aad9-d8788dc7559f", - "name" : "offline_access", - "description" : "OpenID Connect built-in scope: offline_access", - "protocol" : "openid-connect", - "attributes" : { - "consent.screen.text" : "${offlineAccessScopeConsentText}", - "display.on.consent.screen" : "true" - } - }, { - "id" : "e5e16f12-1b4c-47e7-9599-99ff395f359c", - "name" : "phone", - "description" : "OpenID Connect built-in scope: phone", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "true", - "display.on.consent.screen" : "true", - "consent.screen.text" : "${phoneScopeConsentText}" + { + "id": "4891506e-c7be-495b-b3c6-be1024e56f03", + "alias": "first broker login", + "description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "review profile config", + "authenticator": "idp-review-profile", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "REQUIRED", + "priority": 20, + "flowAlias": "User creation or linking", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] }, - "protocolMappers" : [ { - "id" : "8d83aa08-43a9-49f5-b1dd-caa144e2cad5", - "name" : "phone number", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "phoneNumber", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "phone_number", - "jsonType.label" : "String" - } - }, { - "id" : "3886e58f-d64f-4851-80f3-ae7cc5c6ab13", - "name" : "phone number verified", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "phoneNumberVerified", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "phone_number_verified", - "jsonType.label" : "boolean" - } - } ] - }, { - "id" : "f33d0489-2a52-4066-9c38-e130c02665ee", - "name" : "profile", - "description" : "OpenID Connect built-in scope: profile", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "true", - "display.on.consent.screen" : "true", - "consent.screen.text" : "${profileScopeConsentText}" + { + "id": "f166a866-5a3c-493b-8c86-e3c7147c57ae", + "alias": "forms", + "description": "Username, password, otp and other auth forms.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-username-password-form", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "CONDITIONAL", + "priority": 20, + "flowAlias": "Browser - Conditional OTP", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] }, - "protocolMappers" : [ { - "id" : "1826e2b1-380a-4c65-a73e-3bb79f519550", - "name" : "website", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "website", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "website", - "jsonType.label" : "String" - } - }, { - "id" : "6ea0a08a-ab42-4b45-acfc-a05f5b452cb0", - "name" : "nickname", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "nickname", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "nickname", - "jsonType.label" : "String" - } - }, { - "id" : "78d97855-5557-4f10-9d20-74d8ea6bdfef", - "name" : "full name", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-full-name-mapper", - "consentRequired" : false, - "config" : { - "id.token.claim" : "true", - "access.token.claim" : "true", - "userinfo.token.claim" : "true" - } - }, { - "id" : "22e60a23-914f-40bf-960d-e7a96655581d", - "name" : "picture", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "picture", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "picture", - "jsonType.label" : "String" - } - }, { - "id" : "e595c828-c815-4dff-bd8f-39b1eee5a3b3", - "name" : "birthdate", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "birthdate", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "birthdate", - "jsonType.label" : "String" - } - }, { - "id" : "cd91c70b-0856-4f5d-aeb6-9b5c3b48a966", - "name" : "zoneinfo", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "zoneinfo", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "zoneinfo", - "jsonType.label" : "String" - } - }, { - "id" : "4ce90553-d828-4146-92e0-ee1775c9ba28", - "name" : "updated at", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "updatedAt", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "updated_at", - "jsonType.label" : "String" - } - }, { - "id" : "43710808-227e-4171-a106-7576f933a32b", - "name" : "family name", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-property-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "lastName", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "family_name", - "jsonType.label" : "String" - } - }, { - "id" : "a814d5c0-bdcd-4f33-8cfd-228005f2ba94", - "name" : "gender", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "gender", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "gender", - "jsonType.label" : "String" - } - }, { - "id" : "df9e1465-617d-4a7b-a208-7354c6cbaada", - "name" : "locale", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "locale", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "locale", - "jsonType.label" : "String" - } - }, { - "id" : "fc508e60-a978-41f1-bea2-311673b4b0a8", - "name" : "given name", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-property-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "firstName", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "given_name", - "jsonType.label" : "String" - } - }, { - "id" : "8e4641a3-87d3-4958-8113-dcfa82f0ef54", - "name" : "middle name", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "middleName", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "middle_name", - "jsonType.label" : "String" - } - }, { - "id" : "ffc38939-9e10-4cf3-b4fc-65203e079a92", - "name" : "username", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-property-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "username", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "preferred_username", - "jsonType.label" : "String" - } - }, { - "id" : "9364fe99-268a-4a74-88aa-a120a6897e78", - "name" : "profile", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-attribute-mapper", - "consentRequired" : false, - "config" : { - "userinfo.token.claim" : "true", - "user.attribute" : "profile", - "id.token.claim" : "true", - "access.token.claim" : "true", - "claim.name" : "profile", - "jsonType.label" : "String" - } - } ] - }, { - "id" : "b5a38584-219b-4618-a3a5-70814bed867e", - "name" : "role_list", - "description" : "SAML role list", - "protocol" : "saml", - "attributes" : { - "consent.screen.text" : "${samlRoleListScopeConsentText}", - "display.on.consent.screen" : "true" + { + "id": "a8c90847-b4e1-41ad-85dd-fc189700c205", + "alias": "http challenge", + "description": "An authentication flow based on challenge-response HTTP Authentication Schemes", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "no-cookie-redirect", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "REQUIRED", + "priority": 20, + "flowAlias": "Authentication Options", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] }, - "protocolMappers" : [ { - "id" : "1a0a5251-1b3f-47b1-8cc1-07a285d6479f", - "name" : "role list", - "protocol" : "saml", - "protocolMapper" : "saml-role-list-mapper", - "consentRequired" : false, - "config" : { - "single" : "false", - "attribute.nameformat" : "Basic", - "attribute.name" : "Role" - } - } ] - }, { - "id" : "33bd4c0f-225f-43cb-8b6c-0bd4db702525", - "name" : "roles", - "description" : "OpenID Connect scope for add user roles to the access token", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "false", - "display.on.consent.screen" : "true", - "consent.screen.text" : "${rolesScopeConsentText}" + { + "id": "b19038dd-3c7c-4352-8789-2086c56287bc", + "alias": "registration", + "description": "registration flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-page-form", + "requirement": "REQUIRED", + "priority": 10, + "flowAlias": "registration form", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] }, - "protocolMappers" : [ { - "id" : "e276a79b-99cc-4f10-8d26-0e10ce245fdb", - "name" : "client roles", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-client-role-mapper", - "consentRequired" : false, - "config" : { - "user.attribute" : "foo", - "access.token.claim" : "true", - "claim.name" : "resource_access.${client_id}.roles", - "jsonType.label" : "String", - "multivalued" : "true" - } - }, { - "id" : "b64cc3a2-8ed8-4dee-a13a-fef5588a5949", - "name" : "realm roles", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-usermodel-realm-role-mapper", - "consentRequired" : false, - "config" : { - "user.attribute" : "foo", - "access.token.claim" : "true", - "claim.name" : "realm_access.roles", - "jsonType.label" : "String", - "multivalued" : "true" - } - }, { - "id" : "c9828318-6d78-4aba-94ea-405f12fce589", - "name" : "audience resolve", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-audience-resolve-mapper", - "consentRequired" : false, - "config" : { } - } ] - }, { - "id" : "0bfddcf3-017d-44b6-8447-297c565d5d2d", - "name" : "web-origins", - "description" : "OpenID Connect scope for add allowed web origins to the access token", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "false", - "display.on.consent.screen" : "false", - "consent.screen.text" : "" + { + "id": "017a3853-ce82-42d5-916f-69af01d60b75", + "alias": "registration form", + "description": "registration form", + "providerId": "form-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-user-creation", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-profile-action", + "requirement": "REQUIRED", + "priority": 40, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-password-action", + "requirement": "REQUIRED", + "priority": 50, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-recaptcha-action", + "requirement": "DISABLED", + "priority": 60, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] }, - "protocolMappers" : [ { - "id" : "28867dcd-803d-47a5-be90-51be8a331527", - "name" : "allowed web origins", - "protocol" : "openid-connect", - "protocolMapper" : "oidc-allowed-origins-mapper", - "consentRequired" : false, - "config" : { } - } ] - }, { - "id" : "e28fac82-4db1-4900-8096-74706a71f7f3", - "name" : "System.Write", - "protocol" : "openid-connect", - "attributes" : { - "include.in.token.scope" : "true", - "display.on.consent.screen" : "true" + { + "id": "7e37f103-3f7a-4105-9804-194d8758038e", + "alias": "reset credentials", + "description": "Reset credentials for a user if they forgot their password or something", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "reset-credentials-choose-user", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "reset-credential-email", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "reset-password", + "requirement": "REQUIRED", + "priority": 30, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "CONDITIONAL", + "priority": 40, + "flowAlias": "Reset - Conditional OTP", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "c4a172b7-12f7-4472-8cd7-032376527d0f", + "alias": "saml ecp", + "description": "SAML ECP Profile Authentication Flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "http-basic-authenticator", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] } - } ], - "defaultDefaultClientScopes" : [ "web-origins", "roles", "Namespace.Admin", "Namespace.Create", "email", "role_list", "profile" ], - "defaultOptionalClientScopes" : [ "microprofile-jwt", "offline_access", "phone", "address" ], - "browserSecurityHeaders" : { - "contentSecurityPolicyReportOnly" : "", - "xContentTypeOptions" : "nosniff", - "xRobotsTag" : "none", - "xFrameOptions" : "SAMEORIGIN", - "contentSecurityPolicy" : "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", - "xXSSProtection" : "1; mode=block", - "strictTransportSecurity" : "max-age=31536000; includeSubDomains" - }, - "smtpServer" : { }, - "eventsEnabled" : false, - "eventsListeners" : [ "jboss-logging" ], - "enabledEventTypes" : [ ], - "adminEventsEnabled" : false, - "adminEventsDetailsEnabled" : false, - "components" : { - "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy" : [ { - "id" : "d7699c96-1cc0-46fe-b0fe-c72c7f7d1804", - "name" : "Consent Required", - "providerId" : "consent-required", - "subType" : "anonymous", - "subComponents" : { }, - "config" : { } - }, { - "id" : "522f0c4c-8dfe-4421-b573-0e5723319dac", - "name" : "Allowed Client Scopes", - "providerId" : "allowed-client-templates", - "subType" : "authenticated", - "subComponents" : { }, - "config" : { - "allow-default-scopes" : [ "true" ] - } - }, { - "id" : "2502109c-1319-4bcd-bf94-a5225239c42b", - "name" : "Allowed Protocol Mapper Types", - "providerId" : "allowed-protocol-mappers", - "subType" : "anonymous", - "subComponents" : { }, - "config" : { - "allowed-protocol-mapper-types" : [ "oidc-full-name-mapper", "saml-user-property-mapper", "oidc-sha256-pairwise-sub-mapper", "saml-user-attribute-mapper", "oidc-usermodel-attribute-mapper", "oidc-address-mapper", "saml-role-list-mapper", "oidc-usermodel-property-mapper" ] - } - }, { - "id" : "013bd2ad-80e7-40fe-ba41-b90642d536cd", - "name" : "Trusted Hosts", - "providerId" : "trusted-hosts", - "subType" : "anonymous", - "subComponents" : { }, - "config" : { - "host-sending-registration-request-must-match" : [ "true" ], - "client-uris-must-match" : [ "true" ] - } - }, { - "id" : "c0bcf5a2-ef5f-4f03-95c7-ea15f27c8cd7", - "name" : "Allowed Client Scopes", - "providerId" : "allowed-client-templates", - "subType" : "anonymous", - "subComponents" : { }, - "config" : { - "allow-default-scopes" : [ "true" ] - } - }, { - "id" : "1157f7fe-a055-4ec3-8af8-3f809fd2fec0", - "name" : "Full Scope Disabled", - "providerId" : "scope", - "subType" : "anonymous", - "subComponents" : { }, - "config" : { } - }, { - "id" : "650e6c8f-8a93-4096-9d37-1aecfe000e49", - "name" : "Max Clients Limit", - "providerId" : "max-clients", - "subType" : "anonymous", - "subComponents" : { }, - "config" : { - "max-clients" : [ "200" ] + ], + "authenticatorConfig": [ + { + "id": "b6a50f4b-4bec-4036-b796-d5a0ac12f0e7", + "alias": "create unique user config", + "config": { + "require.password.update.after.registration": "false" } - }, { - "id" : "93e21f15-c390-475a-865a-3f8125b1ccc9", - "name" : "Allowed Protocol Mapper Types", - "providerId" : "allowed-protocol-mappers", - "subType" : "authenticated", - "subComponents" : { }, - "config" : { - "allowed-protocol-mapper-types" : [ "oidc-usermodel-property-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-address-mapper", "saml-role-list-mapper", "saml-user-property-mapper", "oidc-full-name-mapper", "saml-user-attribute-mapper", "oidc-usermodel-attribute-mapper" ] - } - } ], - "org.keycloak.keys.KeyProvider" : [ { - "id" : "2b0c7bcb-c441-4694-8639-7175a1956655", - "name" : "hmac-generated", - "providerId" : "hmac-generated", - "subComponents" : { }, - "config" : { - "kid" : [ "1b23b32b-bb69-4a9a-b20d-770d009ffb67" ], - "active" : [ "true" ], - "secretSize" : [ "64" ], - "secret" : [ "FqB7weAN-07obv1h7cltkFANraOPiK3BN-x1fBR7BY3yF_tOVVy0faPtS24pbPB5VJMXrvZBVy4MvQbhPGOn-A" ], - "priority" : [ "100" ], - "enabled" : [ "true" ], - "algorithm" : [ "HS256" ] - } - }, { - "id" : "82953e3c-d927-4f6f-8b57-3b5c7b8903d6", - "name" : "rsa-generated", - "providerId" : "rsa-generated", - "subComponents" : { }, - "config" : { - "privateKey" : [ "MIIEpAIBAAKCAQEAtE+K9HXgyAM2I3gmzReAKg3ukb0LgHI00kBz79cTLX+aXjAMl5n3cajJZuVBPj+Cyy4fm4vB7tHMTcY5StOMcQv95DZvmonQkweU87quqfETLTp6607tUfUdRib5W/euaKqVbCi09xwSftBeHHCcvotFTz/IjnZ6Ul/qZcDzXgoLEiaZrKz3iSFsnuJEWiozFP+hPZNESfRz/jqd7PcD++SO1iLtMjB5BPvlB7cFWDaWww+nUPbnsqsLZzwdAzhAjYe17x2AafffkZUUp1rf5VXEz8bzAoMpRZDswhG+v1jUPg638b3LFakV6PhRTvLnoKRpPvdzLmRguXtxufrQDwIDAQABAoIBAG0CLcrPPR8OuftFl4ekbop+M74OIVb9NKvr5WuZhnGaVHQe7m302mDvnxtC/Geqs+MsNlWub4d3dOGMNnTjYmOx0UPYGS6/pMZO7iFPumrpYSOV2FxMMjO7UYBo7ZZJLjr+7ikejxFZ+mCKjmr5NfoIbtWThSeDvz3v2OC9fyRZPE/AAqsy9Gkhukxnsi4nJOBK89nLeZS1nbGPzJxu9jiNm2snWI56N7orrVW5KBR/ynaFMN5CepYqgzK5uXv9dkzjBgiQbPlXk9c+LIWrrjXFxjftJTiop6C938B1MlfamkUsoQLwG1Uh8SQNgBExFUOeegouOJthbjhhVdPe/QkCgYEA/7Y5B2Sm0S+DXfoWyHS26ZQ2fDu9WweLbnGL9KrKd4T7u5Ubu9+qTu1aU2m7RxRya9yHzzVXSiTEKPoTPCjC9CIGA3YtQxze2zf7un+RfdN0Ty9pBZiKbAavsX5+KyIliC6FQy0O48eWR7LMsVSFJGGIeYPTjgY3U34uLsN55RUCgYEAtIOQxc1AFw/wcQIsJYEZWmwUIEd49s6x6iCBXez1sfZLJVHL5mE7NNxT0vuSKwxMK4gddSoRjBDqWGgge93HlIz+N+Ln656zCdLlOlDGe5a3jvtxIRKak/mp+nmk8G+FGGlAatPIRmZQbk0hIzh0m88k8hJ7NqRXTDeDDmzmcZMCgYEAgpvOcSpF0l7UWHHepTCIJLIhSj8xLoeh/h1dAPEjTPzNnzg/3CwXzwyIsEY2881LzC/t5jY2iZZR4yQoIvgm649dRvNblwXuBkaH+vAhngUdSTzMBaGuQhMANkaHpvxf8zjftDoVet58sc5voruq7bQrgvWEXuxp4el3KUeKwSkCgYAmOa4QlPQ7bf6mj6U1k+8AfN6OL1RoP0DhqVx7vVASDWvATV/2OyTEftupU+iSARqoJTzHsM7icDqP2gz27fHzfR/gScZ+2K5lKCmufahqR3I7bvd3326oYzgheFz7JUJz9uXTOWGxtrzVfrPDt5LJ48WZFVzOJ2LtGtw/08PAzQKBgQDy/mQxGSxIImcBcjdHDP7kb5T3M69PWN/VER1AMvkU+60uQTfZ7sXsJhWQn6XgzHF9ZhpTJeeliNn9dcTFOt9sWEoLspxZNz/RoKeW2P6p1krjrz74XDOgce63AaXufAFIGUDrJhCcIbyvalEvVQyDnnWe/dHl4us/DX+/+GWjVQ==" ], - "keySize" : [ "2048" ], - "certificate" : [ "MIICmzCCAYMCBgF6AmA7pTANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZtYXN0ZXIwHhcNMjEwNjEyMjIzNjM5WhcNMzEwNjEyMjIzODE5WjARMQ8wDQYDVQQDDAZtYXN0ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC0T4r0deDIAzYjeCbNF4AqDe6RvQuAcjTSQHPv1xMtf5peMAyXmfdxqMlm5UE+P4LLLh+bi8Hu0cxNxjlK04xxC/3kNm+aidCTB5Tzuq6p8RMtOnrrTu1R9R1GJvlb965oqpVsKLT3HBJ+0F4ccJy+i0VPP8iOdnpSX+plwPNeCgsSJpmsrPeJIWye4kRaKjMU/6E9k0RJ9HP+Op3s9wP75I7WIu0yMHkE++UHtwVYNpbDD6dQ9ueyqwtnPB0DOECNh7XvHYBp99+RlRSnWt/lVcTPxvMCgylFkOzCEb6/WNQ+DrfxvcsVqRXo+FFO8uegpGk+93MuZGC5e3G5+tAPAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAD25ZjxPFys+OAoSmgRuk4KwpTG4cLm3vEwUjD60+gvYJk3bFUgxErNv+Ax69PN4OZwMh9fdnVHRx0haVno0ULUBintRP/P0ond1mw7HB1v/i9EMpRiVoMEL8y3wV363XVw6mDrYI8Pp0OihJBKo5I1EWgaLAl+lu9YS6f3VXaASgqx1AaV6qZiXM95FOeYkjpx30cbIR6uhRAfBHz10PO//RhTCnBrjasU921qFSMH3EuvRZET0jB68FLF7uRFK+goSVrw9O+TcK6Cbh4I4GZX66ZBRW6MTTIzYNsSuSMUlGFujGcVi5+1JmJgJg76coIo7NIR68KPKyh+47Mvy9bI=" ], - "active" : [ "true" ], - "priority" : [ "100" ], - "enabled" : [ "true" ], - "algorithm" : [ "RS256" ] - } - }, { - "id" : "4ac9540a-c5b7-48b0-b3e1-1a7887ed5414", - "name" : "aes-generated", - "providerId" : "aes-generated", - "subComponents" : { }, - "config" : { - "kid" : [ "8fc9ebb4-d633-4fbc-a940-43414dbb6841" ], - "active" : [ "true" ], - "secretSize" : [ "16" ], - "secret" : [ "mwpmhvHuQq_qLZAKhngrjg" ], - "priority" : [ "100" ], - "enabled" : [ "true" ] + }, + { + "id": "1df3203a-ba48-4a72-b851-bb5bc25f33cf", + "alias": "review profile config", + "config": { + "update.profile.on.first.login": "missing" } - } ] - }, - "internationalizationEnabled" : false, - "supportedLocales" : [ ], - "authenticationFlows" : [ { - "id" : "fad0619f-460c-48b9-a877-f75157be2498", - "alias" : "Account verification options", - "description" : "Method with which to verity the existing account", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "idp-email-verification", - "requirement" : "ALTERNATIVE", - "priority" : 10, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "requirement" : "ALTERNATIVE", - "priority" : 20, - "flowAlias" : "Verify Existing Account by Re-authentication", - "userSetupAllowed" : false, - "autheticatorFlow" : true - } ] - }, { - "id" : "33504bb1-b977-4948-a6ff-3c68adf583e4", - "alias" : "Authentication Options", - "description" : "Authentication options.", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "basic-auth", - "requirement" : "REQUIRED", - "priority" : 10, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "authenticator" : "basic-auth-otp", - "requirement" : "DISABLED", - "priority" : 20, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "authenticator" : "auth-spnego", - "requirement" : "DISABLED", - "priority" : 30, - "userSetupAllowed" : false, - "autheticatorFlow" : false - } ] - }, { - "id" : "bfe57f7a-b041-4a15-be88-44894c673f24", - "alias" : "Browser - Conditional OTP", - "description" : "Flow to determine if the OTP is required for the authentication", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "conditional-user-configured", - "requirement" : "REQUIRED", - "priority" : 10, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "authenticator" : "auth-otp-form", - "requirement" : "REQUIRED", - "priority" : 20, - "userSetupAllowed" : false, - "autheticatorFlow" : false - } ] - }, { - "id" : "377ac00d-87d0-4752-8aa0-90459e334175", - "alias" : "Direct Grant - Conditional OTP", - "description" : "Flow to determine if the OTP is required for the authentication", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "conditional-user-configured", - "requirement" : "REQUIRED", - "priority" : 10, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "authenticator" : "direct-grant-validate-otp", - "requirement" : "REQUIRED", - "priority" : 20, - "userSetupAllowed" : false, - "autheticatorFlow" : false - } ] - }, { - "id" : "23859306-7ccf-4313-9a8e-0dc39ca6749e", - "alias" : "First broker login - Conditional OTP", - "description" : "Flow to determine if the OTP is required for the authentication", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "conditional-user-configured", - "requirement" : "REQUIRED", - "priority" : 10, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "authenticator" : "auth-otp-form", - "requirement" : "REQUIRED", - "priority" : 20, - "userSetupAllowed" : false, - "autheticatorFlow" : false - } ] - }, { - "id" : "60b03eac-baf5-47e9-8e69-89c4292487fd", - "alias" : "Handle Existing Account", - "description" : "Handle what to do if there is existing account with same email/username like authenticated identity provider", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "idp-confirm-link", - "requirement" : "REQUIRED", - "priority" : 10, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "requirement" : "REQUIRED", - "priority" : 20, - "flowAlias" : "Account verification options", - "userSetupAllowed" : false, - "autheticatorFlow" : true - } ] - }, { - "id" : "2a42f367-4220-478d-bbbc-36def807b298", - "alias" : "Reset - Conditional OTP", - "description" : "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "conditional-user-configured", - "requirement" : "REQUIRED", - "priority" : 10, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "authenticator" : "reset-otp", - "requirement" : "REQUIRED", - "priority" : 20, - "userSetupAllowed" : false, - "autheticatorFlow" : false - } ] - }, { - "id" : "6f87a5c3-1a77-456e-b649-b0adfb5c5d47", - "alias" : "User creation or linking", - "description" : "Flow for the existing/non-existing user alternatives", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticatorConfig" : "create unique user config", - "authenticator" : "idp-create-user-if-unique", - "requirement" : "ALTERNATIVE", - "priority" : 10, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "requirement" : "ALTERNATIVE", - "priority" : 20, - "flowAlias" : "Handle Existing Account", - "userSetupAllowed" : false, - "autheticatorFlow" : true - } ] - }, { - "id" : "2262356b-b4ab-4d1c-beb4-267198ce85ef", - "alias" : "Verify Existing Account by Re-authentication", - "description" : "Reauthentication of existing account", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "idp-username-password-form", - "requirement" : "REQUIRED", - "priority" : 10, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "requirement" : "CONDITIONAL", - "priority" : 20, - "flowAlias" : "First broker login - Conditional OTP", - "userSetupAllowed" : false, - "autheticatorFlow" : true - } ] - }, { - "id" : "9a82a84c-49be-427c-8d4e-e193a4d7a353", - "alias" : "browser", - "description" : "browser based authentication", - "providerId" : "basic-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "auth-cookie", - "requirement" : "ALTERNATIVE", - "priority" : 10, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "authenticator" : "auth-spnego", - "requirement" : "DISABLED", - "priority" : 20, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "authenticator" : "identity-provider-redirector", - "requirement" : "ALTERNATIVE", - "priority" : 25, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "requirement" : "ALTERNATIVE", - "priority" : 30, - "flowAlias" : "forms", - "userSetupAllowed" : false, - "autheticatorFlow" : true - } ] - }, { - "id" : "de2f29cf-ac12-4c88-b2e3-bb1e061dd013", - "alias" : "clients", - "description" : "Base authentication for clients", - "providerId" : "client-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "client-secret", - "requirement" : "ALTERNATIVE", - "priority" : 10, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "authenticator" : "client-jwt", - "requirement" : "ALTERNATIVE", - "priority" : 20, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "authenticator" : "client-secret-jwt", - "requirement" : "ALTERNATIVE", - "priority" : 30, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "authenticator" : "client-x509", - "requirement" : "ALTERNATIVE", - "priority" : 40, - "userSetupAllowed" : false, - "autheticatorFlow" : false - } ] - }, { - "id" : "79023955-88dd-4230-9185-9aee45846718", - "alias" : "direct grant", - "description" : "OpenID Connect Resource Owner Grant", - "providerId" : "basic-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "direct-grant-validate-username", - "requirement" : "REQUIRED", - "priority" : 10, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "authenticator" : "direct-grant-validate-password", - "requirement" : "REQUIRED", - "priority" : 20, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "requirement" : "CONDITIONAL", - "priority" : 30, - "flowAlias" : "Direct Grant - Conditional OTP", - "userSetupAllowed" : false, - "autheticatorFlow" : true - } ] - }, { - "id" : "bcb59a24-d9e3-449a-95a8-cb8e39dbda09", - "alias" : "docker auth", - "description" : "Used by Docker clients to authenticate against the IDP", - "providerId" : "basic-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "docker-http-basic-authenticator", - "requirement" : "REQUIRED", - "priority" : 10, - "userSetupAllowed" : false, - "autheticatorFlow" : false - } ] - }, { - "id" : "4891506e-c7be-495b-b3c6-be1024e56f03", - "alias" : "first broker login", - "description" : "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", - "providerId" : "basic-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticatorConfig" : "review profile config", - "authenticator" : "idp-review-profile", - "requirement" : "REQUIRED", - "priority" : 10, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "requirement" : "REQUIRED", - "priority" : 20, - "flowAlias" : "User creation or linking", - "userSetupAllowed" : false, - "autheticatorFlow" : true - } ] - }, { - "id" : "f166a866-5a3c-493b-8c86-e3c7147c57ae", - "alias" : "forms", - "description" : "Username, password, otp and other auth forms.", - "providerId" : "basic-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "auth-username-password-form", - "requirement" : "REQUIRED", - "priority" : 10, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "requirement" : "CONDITIONAL", - "priority" : 20, - "flowAlias" : "Browser - Conditional OTP", - "userSetupAllowed" : false, - "autheticatorFlow" : true - } ] - }, { - "id" : "a8c90847-b4e1-41ad-85dd-fc189700c205", - "alias" : "http challenge", - "description" : "An authentication flow based on challenge-response HTTP Authentication Schemes", - "providerId" : "basic-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "no-cookie-redirect", - "requirement" : "REQUIRED", - "priority" : 10, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "requirement" : "REQUIRED", - "priority" : 20, - "flowAlias" : "Authentication Options", - "userSetupAllowed" : false, - "autheticatorFlow" : true - } ] - }, { - "id" : "b19038dd-3c7c-4352-8789-2086c56287bc", - "alias" : "registration", - "description" : "registration flow", - "providerId" : "basic-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "registration-page-form", - "requirement" : "REQUIRED", - "priority" : 10, - "flowAlias" : "registration form", - "userSetupAllowed" : false, - "autheticatorFlow" : true - } ] - }, { - "id" : "017a3853-ce82-42d5-916f-69af01d60b75", - "alias" : "registration form", - "description" : "registration form", - "providerId" : "form-flow", - "topLevel" : false, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "registration-user-creation", - "requirement" : "REQUIRED", - "priority" : 20, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "authenticator" : "registration-profile-action", - "requirement" : "REQUIRED", - "priority" : 40, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "authenticator" : "registration-password-action", - "requirement" : "REQUIRED", - "priority" : 50, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "authenticator" : "registration-recaptcha-action", - "requirement" : "DISABLED", - "priority" : 60, - "userSetupAllowed" : false, - "autheticatorFlow" : false - } ] - }, { - "id" : "7e37f103-3f7a-4105-9804-194d8758038e", - "alias" : "reset credentials", - "description" : "Reset credentials for a user if they forgot their password or something", - "providerId" : "basic-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "reset-credentials-choose-user", - "requirement" : "REQUIRED", - "priority" : 10, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "authenticator" : "reset-credential-email", - "requirement" : "REQUIRED", - "priority" : 20, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "authenticator" : "reset-password", - "requirement" : "REQUIRED", - "priority" : 30, - "userSetupAllowed" : false, - "autheticatorFlow" : false - }, { - "requirement" : "CONDITIONAL", - "priority" : 40, - "flowAlias" : "Reset - Conditional OTP", - "userSetupAllowed" : false, - "autheticatorFlow" : true - } ] - }, { - "id" : "c4a172b7-12f7-4472-8cd7-032376527d0f", - "alias" : "saml ecp", - "description" : "SAML ECP Profile Authentication Flow", - "providerId" : "basic-flow", - "topLevel" : true, - "builtIn" : true, - "authenticationExecutions" : [ { - "authenticator" : "http-basic-authenticator", - "requirement" : "REQUIRED", - "priority" : 10, - "userSetupAllowed" : false, - "autheticatorFlow" : false - } ] - } ], - "authenticatorConfig" : [ { - "id" : "b6a50f4b-4bec-4036-b796-d5a0ac12f0e7", - "alias" : "create unique user config", - "config" : { - "require.password.update.after.registration" : "false" } - }, { - "id" : "1df3203a-ba48-4a72-b851-bb5bc25f33cf", - "alias" : "review profile config", - "config" : { - "update.profile.on.first.login" : "missing" + ], + "requiredActions": [ + { + "alias": "CONFIGURE_TOTP", + "name": "Configure OTP", + "providerId": "CONFIGURE_TOTP", + "enabled": true, + "defaultAction": false, + "priority": 10, + "config": {} + }, + { + "alias": "terms_and_conditions", + "name": "Terms and Conditions", + "providerId": "terms_and_conditions", + "enabled": false, + "defaultAction": false, + "priority": 20, + "config": {} + }, + { + "alias": "UPDATE_PASSWORD", + "name": "Update Password", + "providerId": "UPDATE_PASSWORD", + "enabled": true, + "defaultAction": false, + "priority": 30, + "config": {} + }, + { + "alias": "UPDATE_PROFILE", + "name": "Update Profile", + "providerId": "UPDATE_PROFILE", + "enabled": true, + "defaultAction": false, + "priority": 40, + "config": {} + }, + { + "alias": "VERIFY_EMAIL", + "name": "Verify Email", + "providerId": "VERIFY_EMAIL", + "enabled": true, + "defaultAction": false, + "priority": 50, + "config": {} + }, + { + "alias": "update_user_locale", + "name": "Update User Locale", + "providerId": "update_user_locale", + "enabled": true, + "defaultAction": false, + "priority": 1000, + "config": {} } - } ], - "requiredActions" : [ { - "alias" : "CONFIGURE_TOTP", - "name" : "Configure OTP", - "providerId" : "CONFIGURE_TOTP", - "enabled" : true, - "defaultAction" : false, - "priority" : 10, - "config" : { } - }, { - "alias" : "terms_and_conditions", - "name" : "Terms and Conditions", - "providerId" : "terms_and_conditions", - "enabled" : false, - "defaultAction" : false, - "priority" : 20, - "config" : { } - }, { - "alias" : "UPDATE_PASSWORD", - "name" : "Update Password", - "providerId" : "UPDATE_PASSWORD", - "enabled" : true, - "defaultAction" : false, - "priority" : 30, - "config" : { } - }, { - "alias" : "UPDATE_PROFILE", - "name" : "Update Profile", - "providerId" : "UPDATE_PROFILE", - "enabled" : true, - "defaultAction" : false, - "priority" : 40, - "config" : { } - }, { - "alias" : "VERIFY_EMAIL", - "name" : "Verify Email", - "providerId" : "VERIFY_EMAIL", - "enabled" : true, - "defaultAction" : false, - "priority" : 50, - "config" : { } - }, { - "alias" : "update_user_locale", - "name" : "Update User Locale", - "providerId" : "update_user_locale", - "enabled" : true, - "defaultAction" : false, - "priority" : 1000, - "config" : { } - } ], - "browserFlow" : "browser", - "registrationFlow" : "registration", - "directGrantFlow" : "direct grant", - "resetCredentialsFlow" : "reset credentials", - "clientAuthenticationFlow" : "clients", - "dockerAuthenticationFlow" : "docker auth", - "attributes" : { - "clientOfflineSessionMaxLifespan" : "0", - "clientSessionIdleTimeout" : "0", - "clientSessionMaxLifespan" : "0", - "clientOfflineSessionIdleTimeout" : "0" + ], + "browserFlow": "browser", + "registrationFlow": "registration", + "directGrantFlow": "direct grant", + "resetCredentialsFlow": "reset credentials", + "clientAuthenticationFlow": "clients", + "dockerAuthenticationFlow": "docker auth", + "attributes": { + "clientOfflineSessionMaxLifespan": "0", + "clientSessionIdleTimeout": "0", + "clientSessionMaxLifespan": "0", + "clientOfflineSessionIdleTimeout": "0" }, - "keycloakVersion" : "11.0.3", - "userManagedAccessAllowed" : true -} \ No newline at end of file + "keycloakVersion": "11.0.3", + "userManagedAccessAllowed": true +} diff --git a/src/auth/auth-oauth2-proxy.js b/src/auth/auth-oauth2-proxy.js index 8f5e02aeb..1948f73dd 100644 --- a/src/auth/auth-oauth2-proxy.js +++ b/src/auth/auth-oauth2-proxy.js @@ -25,6 +25,7 @@ const { Logger } = require('../logger'); const { UMA2TokenService } = require('../services/uma2'); const { getUma2FromIssuer, Uma2WellKnown } = require('../services/keycloak'); +const { MigrateAuthzUser, MigratePortalUser } = require('../services/workflow'); const toJson = (val) => (val ? JSON.parse(val) : null); @@ -354,6 +355,40 @@ class Oauth2ProxyAuthStrategy { let _results = await _users.adapter.find({ username: username }); + if ( + _results.length == 0 && + username != `${providerUsername}@${identityProvider}` + ) { + logger.info( + '[migration] %s not found. Migrate %s@%s access to %s', + username, + providerUsername, + identityProvider, + username + ); + try { + _results = await _users.adapter.find({ + username: `${providerUsername}@${identityProvider}`, + }); + if (_results.length == 1) { + const oldUser = _results[0]; + const suctx = this.keystone.createContext({ + skipAccessControl: true, + }); + // check to see if we need to migrate + await MigrateAuthzUser(suctx, oldUser.username, username, true); + await MigratePortalUser(suctx, oldUser.username, username); + } + } catch (err) { + logger.error( + '[migration] Error during migration (%s) %s', + username, + err + ); + throw new Error('User migration error'); + } + } + let userId = _results.length == 0 ? null : _results[0].id; if (_results.length == 0) { diff --git a/src/controllers/v2/OrganizationController.ts b/src/controllers/v2/OrganizationController.ts index f06593b8c..eb6a6112b 100644 --- a/src/controllers/v2/OrganizationController.ts +++ b/src/controllers/v2/OrganizationController.ts @@ -140,7 +140,7 @@ export class OrganizationController extends Controller { const groupAccessService = new GroupAccessService(prodEnv.uma2); await groupAccessService.login(envConfig.clientId, envConfig.clientSecret); - await groupAccessService.createOrUpdateGroupAccess(body); + await groupAccessService.createOrUpdateGroupAccess(body, ['idir']); } /** diff --git a/src/controllers/v2/openapi.yaml b/src/controllers/v2/openapi.yaml index d1752fc1f..018379ebd 100644 --- a/src/controllers/v2/openapi.yaml +++ b/src/controllers/v2/openapi.yaml @@ -464,12 +464,8 @@ components: properties: id: type: string - username: - type: string email: type: string - required: - - username type: object additionalProperties: false GroupMember: diff --git a/src/controllers/v2/routes.ts b/src/controllers/v2/routes.ts index e3af9986b..470142a58 100644 --- a/src/controllers/v2/routes.ts +++ b/src/controllers/v2/routes.ts @@ -283,7 +283,6 @@ const models: TsoaRoute.Models = { "dataType": "refObject", "properties": { "id": {"dataType":"string"}, - "username": {"dataType":"string","required":true}, "email": {"dataType":"string"}, }, "additionalProperties": false, diff --git a/src/lists/extensions/UMAPermissionTicket.ts b/src/lists/extensions/UMAPermissionTicket.ts index 5a6c32295..70adb4a99 100644 --- a/src/lists/extensions/UMAPermissionTicket.ts +++ b/src/lists/extensions/UMAPermissionTicket.ts @@ -9,6 +9,7 @@ import { getResourceSets, getEnvironmentContext } from './Common'; import { strict as assert } from 'assert'; import { Logger } from '../../logger'; import { StructuredActivityService } from '../../services/workflow'; +import { lookupUsersByUsernames } from '../../services/keystone'; const logger = Logger('lists.umaticket'); @@ -29,7 +30,7 @@ type UMAPermissionTicket { const typeUMAPermissionTicketInput = ` input UMAPermissionTicketInput { resourceId: String!, - username: String!, + email: String!, granted: Boolean, scopes: [String]! } @@ -109,7 +110,24 @@ module.exports = { resourceId: args.resourceId, returnNames: true, }; - return await permissionApi.listPermissions(params); + const permissions = await permissionApi.listPermissions(params); + + const usernameList: string[] = permissions.map( + (p) => p.requesterName + ); + + const users = await lookupUsersByUsernames( + context.sudo(), + usernameList + ); + + permissions.forEach((perm) => { + const user = users + .filter((u) => u.username == perm.requesterName) + .pop(); + perm.requesterName = user?.name || perm.requesterName; + }); + return permissions; }, access: EnforcementPoint, }, @@ -145,9 +163,13 @@ module.exports = { envCtx.issuerEnvConfig.clientId, envCtx.issuerEnvConfig.clientSecret ); - const userId = await userApi.lookupUserByUsername( - args.data.username + const users = await userApi.lookupUsersByEmail( + args.data.email, + false ); + assert.strictEqual(users.length, 1, 'Unable to match email'); + const user = users.pop(); + const displayName = user.attributes.display_name || user.email; const result = []; const granted = @@ -159,7 +181,7 @@ module.exports = { for (const scope of scopes) { const permission = await permissionApi.createOrUpdatePermission( args.data.resourceId, - userId, + user.id, granted, scope ); @@ -174,7 +196,7 @@ module.exports = { 'granted', 'namespace access', 'user', - args.data.username, + displayName, scopes ); @@ -215,16 +237,24 @@ module.exports = { returnNames: true, }); - const requesterName = []; + const requesterIds = []; const deletedScopes = []; for (const permId of args.ids) { const foundPerms = perms.filter((perm) => perm.id === permId); assert.strictEqual(foundPerms.length, 1, 'Invalid Permission'); deletedScopes.push(foundPerms[0].scopeName); - requesterName.push(foundPerms[0].requesterName); + requesterIds.push(foundPerms[0].requester); await permissionApi.deletePermission(permId); } + const userApi = new KeycloakUserService(envCtx.openid.issuer); + await userApi.login( + envCtx.issuerEnvConfig.clientId, + envCtx.issuerEnvConfig.clientSecret + ); + const user = await userApi.lookupUserById(requesterIds.pop()); + const displayName = user.attributes.display_name || user.email; + await new StructuredActivityService( context.sudo(), context.authedItem['namespace'] @@ -233,7 +263,7 @@ module.exports = { 'revoked', 'namespace access', 'user', - requesterName.pop(), + displayName, deletedScopes ); diff --git a/src/nextapp/components/namespace-access/namespace-access-dialog.tsx b/src/nextapp/components/namespace-access/namespace-access-dialog.tsx index 1e8124aef..05cdd5db4 100644 --- a/src/nextapp/components/namespace-access/namespace-access-dialog.tsx +++ b/src/nextapp/components/namespace-access/namespace-access-dialog.tsx @@ -77,12 +77,12 @@ const NamespaceAccessDialog: React.FC = ({ - {variant === 'user' ? 'Username' : 'Service Account'} + {variant === 'user' ? 'Email' : 'Service Account'} diff --git a/src/nextapp/components/namespace-access/service-accounts-access.tsx b/src/nextapp/components/namespace-access/service-accounts-access.tsx index 2bccabea9..f32c9edd0 100644 --- a/src/nextapp/components/namespace-access/service-accounts-access.tsx +++ b/src/nextapp/components/namespace-access/service-accounts-access.tsx @@ -64,7 +64,9 @@ const ServiceAccountsAccess: React.FC = ({ const requests = React.useMemo(() => { if (isSuccess) { - const result = data?.getUmaPoliciesForResource; + const result = data?.getUmaPoliciesForResource.filter((policy) => + Boolean(policy.clients) + ); if (search) { return result.filter((d) => d.name.search(search) >= 0); } diff --git a/src/nextapp/components/namespace-access/users-access.tsx b/src/nextapp/components/namespace-access/users-access.tsx index 650af04a5..bd64a2146 100644 --- a/src/nextapp/components/namespace-access/users-access.tsx +++ b/src/nextapp/components/namespace-access/users-access.tsx @@ -73,11 +73,12 @@ const UsersAccess: React.FC = ({ if (isSuccess) { const groupedByRequester = groupBy( data?.getPermissionTicketsForResource, - 'requesterName' + (a) => a.requester + '|' + a.requesterName ); const result = Object.keys(groupedByRequester).map((r) => { + const requesterName = r.split('|')[1]; return { - requesterName: r, + requesterName, scopes: groupedByRequester[r].map((d) => ({ id: d.scope, name: d.scopeName, @@ -94,7 +95,7 @@ const UsersAccess: React.FC = ({ }, [data, isSuccess, search]); const handleGrantAccess = async (form: FormData) => { - const username = form.get('username') as string; + const email = form.get('email') as string; const scopes = form.getAll('scopes') as string[]; try { @@ -102,7 +103,7 @@ const UsersAccess: React.FC = ({ prodEnvId, data: { resourceId, - username, + email, scopes, }, }); diff --git a/src/nextapp/shared/types/query.types.ts b/src/nextapp/shared/types/query.types.ts index ab7845e28..e4e142651 100644 --- a/src/nextapp/shared/types/query.types.ts +++ b/src/nextapp/shared/types/query.types.ts @@ -8268,7 +8268,7 @@ export type UmaPermissionTicket = { export type UmaPermissionTicketInput = { resourceId: Scalars['String']; - username: Scalars['String']; + email: Scalars['String']; granted?: Maybe; scopes: Array>; }; diff --git a/src/services/checkKeystoneStatus.ts b/src/services/checkKeystoneStatus.ts new file mode 100644 index 000000000..018b31931 --- /dev/null +++ b/src/services/checkKeystoneStatus.ts @@ -0,0 +1,13 @@ +import { logger } from '../logger'; +import { strict as assert } from 'assert'; + +export function checkKeystoneStatus( + ref: string, + errorMessage: string, + result: any +): void { + if ('errors' in result) { + logger.error('[%s] %j', ref, result['errors']); + assert.strictEqual(result['errors'].length, 0, errorMessage); + } +} diff --git a/src/services/keycloak/group-service.ts b/src/services/keycloak/group-service.ts index cbbc8c17c..5b5f58438 100644 --- a/src/services/keycloak/group-service.ts +++ b/src/services/keycloak/group-service.ts @@ -197,13 +197,13 @@ export class KeycloakGroupService { return this.kcAdminClient.users.delFromGroup({ id, groupId }); } - public async lookupMemberByUsername(username: string): Promise { + public async lookupMemberByEmail(email: string): Promise { const foundUsers = await this.kcAdminClient.users.find({ - username, + email, exact: true, }); if (foundUsers.length == 0) { - logger.warn('[lookupMemberByUsername] User not found %s', username); + logger.warn('[lookupMemberByEmail] User not found %s', email); } return foundUsers.length == 0 ? null : foundUsers[0].id; } diff --git a/src/services/keycloak/permission-ticket-service.ts b/src/services/keycloak/permission-ticket-service.ts index d1ba2daa8..af3e9af97 100644 --- a/src/services/keycloak/permission-ticket-service.ts +++ b/src/services/keycloak/permission-ticket-service.ts @@ -143,6 +143,7 @@ export class KeycloakPermissionTicketService { method: 'delete', headers: headers(this.accessToken) as any, }).then(checkStatus); + logger.debug('[deletePermission] DELETED %s', id); } public async getPermission(id: string): Promise { diff --git a/src/services/keycloak/user-service.ts b/src/services/keycloak/user-service.ts index 9f662c0a5..ade8e5cf4 100644 --- a/src/services/keycloak/user-service.ts +++ b/src/services/keycloak/user-service.ts @@ -5,6 +5,8 @@ import KeycloakAdminClient, { default as KcAdminClient, } from '@keycloak/keycloak-admin-client'; import { RoleMappingPayload } from '@keycloak/keycloak-admin-client/lib/defs/roleRepresentation'; +import { checkKeystoneStatus } from '../checkKeystoneStatus'; +import UserRepresentation from '@keycloak/keycloak-admin-client/lib/defs/userRepresentation'; const logger = Logger('kc.user'); @@ -18,6 +20,10 @@ export class KeycloakUserService { this.kcAdminClient = new KcAdminClient({ baseUrl, realmName }); } + public useAdminClient(client: KcAdminClient) { + this.kcAdminClient = client; + } + // public async findOne(id: string) { // logger.debug('[findOne] %s', id); // const user = await this.kcAdminClient.users.findOne({ @@ -31,13 +37,63 @@ export class KeycloakUserService { logger.debug('[lookupUserByUsername] %s', username); const users = await this.kcAdminClient.users.find({ exact: true, - username: username, + username, }); logger.debug('[lookupUserByUsername] : %j', users); assert.strictEqual(users.length, 1, 'User not found ' + username); return users[0].id; } + public async lookupUserById(id: string): Promise { + logger.debug('[lookupUserById] %s', id); + const user = await this.kcAdminClient.users.findOne({ + id, + }); + logger.debug('[lookupUserById] : %j', user); + return user; + } + + public async lookupUserIdByEmail( + email: string, + verified: boolean, + identityProviders: string[] + ): Promise { + const user = (await this.lookupUsersByEmail(email, verified)) + .filter(async (user) => { + const userWithAttributes = await this.lookupUserById(user.id); + return identityProviders.includes( + userWithAttributes.attributes.identity_provider + ); + }) + .pop(); + assert.strictEqual(Boolean(user), true, `No suitable match for ${email}`); + return user.id; + } + + public async lookupUsersByEmail( + email: string, + verified: boolean + ): Promise { + logger.debug('[lookupUserByEmail] %s', email); + const users = ( + await this.kcAdminClient.users.find({ + exact: true, + email, + }) + ) + .filter((user: UserRepresentation) => user.enabled) + .filter( + (user: UserRepresentation) => verified == false || user.emailVerified + ); + logger.debug('[lookupUserByEmail] : %j', users); + assert.strictEqual( + users.length > 0, + true, + 'No suitable match for ' + email + ); + return users; + } + public async login( clientId: string, clientSecret: string @@ -96,4 +152,14 @@ export class KeycloakUserService { } logger.debug('[syncUserClientRoles] %s OK', id); } + + public async disableUser(id: string): Promise { + logger.debug('[disableUser] %s', id); + await this.kcAdminClient.users.update( + { id }, + { + enabled: false, + } + ); + } } diff --git a/src/services/keystone/access-request.ts b/src/services/keystone/access-request.ts index 8bdb72d76..b298c504d 100644 --- a/src/services/keystone/access-request.ts +++ b/src/services/keystone/access-request.ts @@ -20,6 +20,7 @@ export async function getAccessRequestsByNamespace( isIssued isComplete requestor { + name username } application { diff --git a/src/services/keystone/types.ts b/src/services/keystone/types.ts index ab7845e28..e4e142651 100644 --- a/src/services/keystone/types.ts +++ b/src/services/keystone/types.ts @@ -8268,7 +8268,7 @@ export type UmaPermissionTicket = { export type UmaPermissionTicketInput = { resourceId: Scalars['String']; - username: Scalars['String']; + email: Scalars['String']; granted?: Maybe; scopes: Array>; }; diff --git a/src/services/keystone/user.ts b/src/services/keystone/user.ts index f49d53b52..840c206f5 100644 --- a/src/services/keystone/user.ts +++ b/src/services/keystone/user.ts @@ -1,4 +1,5 @@ import { Logger } from '../../logger'; +import { checkKeystoneStatus } from '../checkKeystoneStatus'; import { User } from './types'; const assert = require('assert').strict; @@ -145,3 +146,25 @@ export async function lookupUsersByNamespace( logger.debug('Query [lookupUsersByNamespace] result %j', result); return result.data.usersByNamespace; } + +export async function changeUsername( + context: any, + userId: string, + newUsername: string +): Promise { + const result = await context.executeGraphQL({ + query: `mutation ChangeUsername($userId: ID!, $newUsername: String!) { + updateUser(id: $userId, data: { username: $newUsername } ) { + id + username + } + }`, + variables: { userId, newUsername }, + }); + if ('errors' in result) { + logger.error('[changeUsername] %s : %s', newUsername, userId); + throw new Error('Failed to change username'); + } + + logger.info('[changeUsername] RESULT %j', result); +} diff --git a/src/services/org-groups/group-access.ts b/src/services/org-groups/group-access.ts index 232798565..d22bbed80 100644 --- a/src/services/org-groups/group-access.ts +++ b/src/services/org-groups/group-access.ts @@ -44,7 +44,8 @@ export class GroupAccessService { } async createOrUpdateGroupAccess( - groupMembership: GroupMembership + groupMembership: GroupMembership, + validIdentityProviders: string[] ): Promise { const access = buildGroupAccess( groupMembership.name, @@ -88,7 +89,8 @@ export class GroupAccessService { await this.orgGroupService.syncMembers( orgGroup, - buildUserReference(groupRole.name, groupMembership.members) + buildUserReference(groupRole.name, groupMembership.members), + validIdentityProviders ); // TODO: Delete any Permissions that are no longer specified for the Policy @@ -235,7 +237,7 @@ export class GroupAccessService { members: [], }; - const members: { [username: string]: GroupMember } = {}; + const members: { [email: string]: GroupMember } = {}; for (const groupPath of fullGroupPaths) { logger.debug('[getGroupAccess] Evaluate %s', groupPath); @@ -254,10 +256,10 @@ export class GroupAccessService { ); roleMembers.forEach((userRef) => { - if (userRef.username in members) { - members[userRef.username].roles.push(root(fullGroupPaths[0])); + if (userRef.email in members) { + members[userRef.email].roles.push(root(fullGroupPaths[0])); } else { - members[userRef.username] = { + members[userRef.email] = { member: userRef, roles: [root(fullGroupPaths[0])], }; diff --git a/src/services/org-groups/org-group-service.ts b/src/services/org-groups/org-group-service.ts index 6089776e0..29239364b 100644 --- a/src/services/org-groups/org-group-service.ts +++ b/src/services/org-groups/org-group-service.ts @@ -7,6 +7,7 @@ import { KeycloakClientPolicyService, KeycloakClientService, KeycloakGroupService, + KeycloakUserService, } from '../keycloak'; import GroupRepresentation from '@keycloak/keycloak-admin-client/lib/defs/groupRepresentation'; import ClientScopeRepresentation from '@keycloak/keycloak-admin-client/lib/defs/clientScopeRepresentation'; @@ -61,11 +62,17 @@ function throwError(msg: string) { export class OrgGroupService { private clientId: string; private keycloakService; + private userKeycloakService; private groups: GroupRepresentation[]; constructor(issuerUrl: string) { logger.debug('[OrgGroupService] %s', issuerUrl); this.keycloakService = new KeycloakGroupService(issuerUrl); + + this.userKeycloakService = new KeycloakUserService(issuerUrl); + this.userKeycloakService.useAdminClient( + this.keycloakService.getAdminClient() + ); } public async login( @@ -159,7 +166,7 @@ export class OrgGroupService { owner: cid, description: policy.description, scopes: permission.scopes.map((s) => s.name), - users: members.map((u) => u.username), + users: members.map((u) => u.email), groups: groups.sort(), }; @@ -534,7 +541,6 @@ export class OrgGroupService { } return allGroupMembers.map((user) => ({ id: user.id, - username: user.username, email: user.email, })); } @@ -554,7 +560,8 @@ export class OrgGroupService { public async syncMembers( orgGroup: OrganizationGroup, - memberUsernames: UserReference[] + memberEmails: UserReference[], + validIdentityProviders: string[] ) { const groupIds = this.getGroupBranchToLeaf(orgGroup); const group = groupIds[groupIds.length - 1]; @@ -563,7 +570,7 @@ export class OrgGroupService { '[syncMembers] %s (%s) %j', orgGroup.name, group.id, - memberUsernames + memberEmails ); const currentMembers = (await this.listMembersForLeafOnly(orgGroup)).map( @@ -571,8 +578,12 @@ export class OrgGroupService { ); const desiredMembers = ( await Promise.all( - memberUsernames.map((u) => - this.keycloakService.lookupMemberByUsername(u.username) + memberEmails.map((u) => + this.userKeycloakService.lookupUserIdByEmail( + u.email, + false, + validIdentityProviders + ) ) ) ).filter((s) => s); diff --git a/src/services/org-groups/types.ts b/src/services/org-groups/types.ts index 440e8f160..a1c5fc364 100644 --- a/src/services/org-groups/types.ts +++ b/src/services/org-groups/types.ts @@ -26,7 +26,6 @@ export interface GroupPermission { export interface UserReference { id?: string; - username: string; email?: string; } diff --git a/src/services/report/data/consumer-access.ts b/src/services/report/data/consumer-access.ts index 53548acc8..9576c32a1 100644 --- a/src/services/report/data/consumer-access.ts +++ b/src/services/report/data/consumer-access.ts @@ -66,10 +66,10 @@ export async function getConsumerAccess( const accesses = await lookupDetailedServiceAccessesByNS(ksCtx, ns.name); const consumerLookup: any = {}; accesses.forEach((access: ServiceAccess) => { - if (access.consumer === null) { - logger.warn('Service Access with Missing Consumer! %j', access); - } else { + if (access.consumer) { consumerLookup[access.consumer.username] = access; + } else { + logger.warn('Service Access with Missing Consumer! %j', access); } }); @@ -143,6 +143,7 @@ export async function getConsumerAccess( await Promise.all(subPromises); accesses + .filter((access) => access.consumer) .filter((access) => !(access.consumer.username in repeatChecker)) .forEach((access) => { data.push({ diff --git a/src/services/report/data/consumer-requests.ts b/src/services/report/data/consumer-requests.ts index b43fa56b8..2a41ab345 100644 --- a/src/services/report/data/consumer-requests.ts +++ b/src/services/report/data/consumer-requests.ts @@ -42,7 +42,7 @@ export async function getConsumerRequests( prod_env_flow: req.productEnvironment?.flow, app_name: req.application.name, app_id: req.application.appId, - requestor: req.requestor.username, + requestor: req.requestor.name, req_created: req.createdAt, req_reviewer: '', req_result: req.isComplete diff --git a/src/services/report/data/ns-access.ts b/src/services/report/data/ns-access.ts index f4e8a87c1..8c41fc233 100644 --- a/src/services/report/data/ns-access.ts +++ b/src/services/report/data/ns-access.ts @@ -1,3 +1,6 @@ +import { KeycloakUserService } from '../../keycloak'; +import { lookupUsersByUsernames } from '../../keystone'; +import { Keystone } from '@keystonejs/keystone'; import { PolicyQuery, UMAPolicyService } from '../../uma2'; import { EnvironmentContext } from '../../workflow/get-namespaces'; import { ReportOfNamespaces } from './namespaces'; @@ -5,12 +8,14 @@ import { ReportOfNamespaces } from './namespaces'; interface ReportOfNamespaceAccess { namespace: string; subject: string; + subjectName: string; scope: string; } /* */ export async function getNamespaceAccess( + context: Keystone, envCtx: EnvironmentContext, namespaces: ReportOfNamespaces[] ): Promise { @@ -33,6 +38,7 @@ export async function getNamespaceAccess( data.push({ namespace: ns.name, subject, + subjectName: '', scope, }); }); @@ -46,6 +52,16 @@ export async function getNamespaceAccess( policy.groups.forEach(doScopes); } }); + + const usernames = data.map((d) => d.subject); + const users = await lookupUsersByUsernames(context, usernames); + data.forEach( + (d) => + (d.subjectName = users + .filter((u) => u.username === d.subject) + .pop()?.name) + ); + return data; } ); diff --git a/src/services/report/output/structure.ts b/src/services/report/output/structure.ts index c1631e296..bc289503c 100644 --- a/src/services/report/output/structure.ts +++ b/src/services/report/output/structure.ts @@ -36,7 +36,7 @@ export const reportStructure: any = { { header: 'Org', key: 'org', - width: 25, + width: 40, }, { header: 'Org Unit', @@ -58,6 +58,11 @@ export const reportStructure: any = { key: 'subject', width: 40, }, + { + header: 'Subject Name', + key: 'subjectName', + width: 40, + }, { header: 'Scope', key: 'scope', diff --git a/src/services/report/workbook.service.ts b/src/services/report/workbook.service.ts index 5f4a4f6e7..c187cf09a 100644 --- a/src/services/report/workbook.service.ts +++ b/src/services/report/workbook.service.ts @@ -1,6 +1,9 @@ import { Keystone } from '@keystonejs/keystone'; import ExcelJS from 'exceljs'; -import { getGwaProductEnvironment } from '../workflow/get-namespaces'; +import { + getGwaProductEnvironment, + injectResSvrAccessTokenToContext, +} from '../workflow/get-namespaces'; import { generateExcelWorkbook } from './output/xls-generator'; import { getConsumerControls, @@ -25,10 +28,16 @@ export class WorkbookService { public async buildWorkbook(ids: string[] = []): Promise { const envCtx = await getGwaProductEnvironment(this.keystone, true); + await injectResSvrAccessTokenToContext(envCtx); + const namespaces = (await getNamespaces(envCtx)).filter( (ns) => ids.length === 0 || ids.includes(ns.resource_id) ); - const ns_access = await getNamespaceAccess(envCtx, namespaces); + const ns_access = await getNamespaceAccess( + this.keystone, + envCtx, + namespaces + ); const gateway_metrics = await getGatewayMetrics(this.keystone, namespaces); const serviceLookup: Map = gatewayToMap( gateway_metrics diff --git a/src/services/workflow/get-namespaces.ts b/src/services/workflow/get-namespaces.ts index c64689f35..678ab356d 100644 --- a/src/services/workflow/get-namespaces.ts +++ b/src/services/workflow/get-namespaces.ts @@ -106,9 +106,9 @@ export async function getEnvironmentContext( }; } -async function getNamespaceResourceSets(envCtx: EnvironmentContext) { - logger.debug('[getNamespaceResourceSets] for %s', envCtx.prodEnv.id); - +export async function injectResSvrAccessTokenToContext( + envCtx: EnvironmentContext +) { assert.strictEqual( isUserBasedResourceOwners(envCtx), false, @@ -116,15 +116,20 @@ async function getNamespaceResourceSets(envCtx: EnvironmentContext) { ); const issuerEnvConfig = envCtx.issuerEnvConfig; - //const resourceAccessScope = - // envCtx.prodEnv.credentialIssuer.resourceAccessScope; + const resSvrAccessToken = await new KeycloakTokenService( envCtx.openid.token_endpoint ).getKeycloakSession(issuerEnvConfig.clientId, issuerEnvConfig.clientSecret); + envCtx.accessToken = resSvrAccessToken; +} + +async function getNamespaceResourceSets(envCtx: EnvironmentContext) { + logger.debug('[getNamespaceResourceSets] for %s', envCtx.prodEnv.id); + const permApi = new UMAPermissionService( envCtx.uma2.permission_endpoint, - resSvrAccessToken + envCtx.accessToken ); const permTicket = await permApi.requestTicket([ { @@ -169,6 +174,10 @@ export async function getResourceServerContext( const usesUma2 = isAuthzUsingUma2(prodEnv); const openid = await getOpenidFromIssuer(issuerEnvConfig.issuerUrl); + if (openid == null) { + logger.error('[getResourceServerContext] Failed to reach IdP', prodEnv); + return null; + } const uma2 = usesUma2 ? await getUma2FromIssuer(issuerEnvConfig.issuerUrl) : null; diff --git a/src/services/workflow/index.ts b/src/services/workflow/index.ts index 255bbcb12..3780a4ec6 100644 --- a/src/services/workflow/index.ts +++ b/src/services/workflow/index.ts @@ -38,6 +38,7 @@ export { LinkConsumerToNamespace } from './link-consumer-to-namespace'; export { getGwaProductEnvironment, getMyNamespaces, + injectResSvrAccessTokenToContext, getResourceServerContext, getEnvironmentContext, } from './get-namespaces'; @@ -49,3 +50,5 @@ export { transformActivity, StructuredActivityService, } from './namespace-activity'; + +export { MigrateAuthzUser, MigratePortalUser } from './migrate-user'; diff --git a/src/services/workflow/migrate-user.ts b/src/services/workflow/migrate-user.ts new file mode 100644 index 000000000..bd59772b9 --- /dev/null +++ b/src/services/workflow/migrate-user.ts @@ -0,0 +1,127 @@ +import { Logger } from '../../logger'; +import { + KeycloakPermissionTicketService, + KeycloakTokenService, + KeycloakUserService, + PermissionTicket, +} from '../keycloak'; +import { lookupProductEnvironmentServicesBySlug } from '../keystone'; +import { changeUsername, lookupUserByUsername } from '../keystone/user'; +import { getEnvironmentContext } from './get-namespaces'; + +const logger = Logger('wf.MigrateUser'); + +export const MigrateAuthzUser = async ( + context: any, + oldUser: string, + newUser: string, + deleteOldPermissions: boolean +): Promise => { + logger.info( + 'MigrateAuthzUser %s to %s (delete old? %s)', + oldUser, + newUser, + deleteOldPermissions + ); + + const productEnvironmentSlug = process.env.GWA_PROD_ENV_SLUG; + const productEnvironment = await lookupProductEnvironmentServicesBySlug( + context, + productEnvironmentSlug + ); + + const envCtx = await getEnvironmentContext( + context, + productEnvironment.id, + {}, + false + ); + + const tok = new KeycloakTokenService(envCtx.openid.token_endpoint); + const token = await tok.getKeycloakSession( + envCtx.issuerEnvConfig.clientId, + envCtx.issuerEnvConfig.clientSecret + ); + + const permissionApi = new KeycloakPermissionTicketService( + envCtx.openid.issuer, + token + ); + + const userApi = new KeycloakUserService(envCtx.openid.issuer); + await userApi.login( + envCtx.issuerEnvConfig.clientId, + envCtx.issuerEnvConfig.clientSecret + ); + + const oldUserId = await userApi.lookupUserByUsername(oldUser); + const newUserId = await userApi.lookupUserByUsername(newUser); + + const resPermsOld = await permissionApi.listPermissions({ + requester: oldUserId, + returnNames: true, + }); + + const resPermsNew = await permissionApi.listPermissions({ + requester: newUserId, + returnNames: true, + }); + + const createPermission = async (perm: PermissionTicket) => { + await permissionApi.createPermission( + perm.resource, + newUserId, + true, + perm.scopeName + ); + }; + + function filterOutAlreadyExisting(p: PermissionTicket): boolean { + return ( + resPermsNew.filter( + (newp) => p.resource === newp.resource && p.scope === newp.scope + ).length == 0 + ); + } + const updates = await Promise.all( + resPermsOld.filter(filterOutAlreadyExisting).map(createPermission) + ); + logger.info( + 'MigrateAuthzUser %s to %s : Copied %d Permissions', + oldUser, + newUser, + updates.length + ); + + if (deleteOldPermissions) { + const deletePermission = async (perm: PermissionTicket) => { + await permissionApi.deletePermission(perm.id); + }; + const deletes = await Promise.all(resPermsOld.map(deletePermission)); + logger.info( + 'MigrateAuthzUser %s to %s : Deleted %d Permissions', + oldUser, + newUser, + deletes.length + ); + + // disable oldUser in authz + userApi.disableUser(oldUserId); + } +}; + +export const MigratePortalUser = async ( + context: any, + oldUsername: string, + newUsername: string +) => { + logger.info('MigratePortalUser %s to %s', oldUsername, newUsername); + + // update the `username` for the user from oldUser and newUsername + const oldUser = (await lookupUserByUsername(context, oldUsername))[0]; + + // change username + await changeUsername(context, oldUser.id, newUsername); + + logger.info('MigratePortalUser %s to %s DONE', oldUsername, newUsername); +}; diff --git a/src/test/integrated/keycloak/users.ts b/src/test/integrated/keycloak/users.ts new file mode 100644 index 000000000..179664641 --- /dev/null +++ b/src/test/integrated/keycloak/users.ts @@ -0,0 +1,55 @@ +/* + +Wire up directly with Keycloak and use the Services + +To run: + + +npm run ts-build +export CID="" +export CSC="" +export ISSUER="" +npm run ts-watch +node dist/test/integrated/keycloak/users.js + +*/ + +import { o } from '../util'; + +import { KeycloakUserService } from '../../../services/keycloak'; + +(async () => { + const kc = new KeycloakUserService(process.env.ISSUER); + + await kc.login(process.env.CID, process.env.CSC); + // const group = await kc.getGroup('ns', 'platform'); + // console.log(JSON.stringify(group, null, 4)); + + //const groups = await kc.search('orgcontrol'); + //o(groups); + + const user = await kc.lookupUserById('xf875dffa-6bcb-4a4d-a8da-4c0429bbb960'); + o(user); + + if (false) { + const users = await kc.lookupUsersByEmail('aidan.cope@gmail.com', false); + o(users); + const userId = users.pop().id; + o(userId); + } + + const permissions: any[] = [ + { + requester: 'f875dffa-6bcb-4a4d-a8da-4c0429bbb960', + }, + ]; + const userIds = ['f875dffa-6bcb-4a4d-a8da-4c0429bbb960']; + const users = await Promise.all(userIds.map((id) => kc.lookupUserById(id))); + + permissions.forEach((perm) => { + const user = users.filter((u) => u.id == perm.requester).pop(); + perm.requesterName = user.attributes.display_name || user.email; + }); + o(permissions); + // console.log(await kc.listMembers('660cadef-9233-4532-ba45-5393beaddea4')); +})(); diff --git a/src/test/integrated/keystonejs/batch-product.ts b/src/test/integrated/keystonejs/batch-product.ts index 634f95fad..45b0970c2 100644 --- a/src/test/integrated/keystonejs/batch-product.ts +++ b/src/test/integrated/keystonejs/batch-product.ts @@ -73,9 +73,10 @@ import { lookupServiceAccessesByEnvironment } from '../../../services/keystone'; appId: '122000000002', environments: [ { + active: false, name: 'dev', - approval: false, - flow: 'public', + approval: true, + flow: 'client-credentials', appId: '12200000', }, ], diff --git a/src/test/integrated/org-groups/group-access.ts b/src/test/integrated/org-groups/group-access.ts index 66b0879be..c1574464c 100644 --- a/src/test/integrated/org-groups/group-access.ts +++ b/src/test/integrated/org-groups/group-access.ts @@ -46,13 +46,17 @@ import { GroupMembership } from '@/services/org-groups/types'; parent: '/ca.bc.gov/ministry-of-citizens-services', members: [ { - member: { username: 'acope@idir' }, - roles: ['data-custodian'], + member: { email: 'aidan.cope@gmail.com' }, + roles: ['organization-admin'], + }, + { + member: { email: 'apsowner@nowhere' }, + roles: ['organization-admin'], }, ], }; - await kc.createOrUpdateGroupAccess(access); + await kc.createOrUpdateGroupAccess(access, ['idir']); } if (false) { @@ -79,7 +83,7 @@ import { GroupMembership } from '@/services/org-groups/types'; ], }; - await kc.createOrUpdateGroupAccess(access); + await kc.createOrUpdateGroupAccess(access, ['idir']); } if (false) { @@ -114,15 +118,15 @@ import { GroupMembership } from '@/services/org-groups/types'; 'namespace', 'erx-demo' ); - await kc.createOrUpdateGroupAccess(access); + await kc.createOrUpdateGroupAccess(access, ['idir']); } - if (false) { + if (true) { o(await kc.getGroupMembership('databc')); - await kc.assignNamespace( - 'ministry-of-citizens-services', - 'databc', - 'erx-demo' - ); + // await kc.assignNamespace( + // 'ministry-of-citizens-services', + // 'databc', + // 'erx-demo' + // ); } if (false) { diff --git a/src/test/integrated/org-groups/sync-members.ts b/src/test/integrated/org-groups/sync-members.ts index d58732295..e102ad84e 100644 --- a/src/test/integrated/org-groups/sync-members.ts +++ b/src/test/integrated/org-groups/sync-members.ts @@ -27,11 +27,15 @@ import { KeycloakGroupService } from '../../../services/keycloak'; parent: '/data-custodian/ca.bc.gov/ministry-of-citizens-services', }; - await kc.syncMembers(org, [ - { username: 'acope@idir' }, - { username: 'someone_doesnt_exist' }, - { username: 'platform' }, - ]); + await kc.syncMembers( + org, + [ + { email: 'acope@idir' }, + { email: 'someone_doesnt_exist' }, + { email: 'platform' }, + ], + ['idir'] + ); // await kc.syncMembers(org, [{ username: 'acope@idir' }]); diff --git a/src/test/integrated/reports/consumerAccess.ts b/src/test/integrated/reports/consumerAccess.ts new file mode 100644 index 000000000..35abdde80 --- /dev/null +++ b/src/test/integrated/reports/consumerAccess.ts @@ -0,0 +1,71 @@ +/* +Wire up directly with Keycloak and use the Services +export TOK="" +To run: +npm run ts-build +npm run ts-watch +node dist/test/integrated/reports/consumerAccess.js +*/ + +import InitKeystone from '../keystonejs/init'; +import { o } from '../util'; +import { Logger } from '../../../logger'; +import { + getConsumerAccess, + getNamespaceAccess, +} from '../../../services/report/data'; +import { + getGwaProductEnvironment, + injectResSvrAccessTokenToContext, +} from '../../../services/workflow'; +import { lookupProductEnvironmentServicesBySlug } from '../../../services/keystone'; + +const logger = Logger('test.reports'); + +(async () => { + const keystone = await InitKeystone(); + + const ns = 'refactortime'; + const skipAccessControl = true; + + const identity = { + id: null, + name: 'Sample User', + username: 'sample_username', + namespace: ns, + roles: JSON.stringify(['access-manager']), + scopes: [], + //userId: '60c9124f3518951bb519084d', + userId: '60c9124f3518951bb519084d', // acope@idir + } as any; + + const ctx = keystone.createContext({ + skipAccessControl, + authentication: { item: identity }, + }); + ctx.req = { + headers: { + 'x-forwarded-access-token': process.env.TOK, + }, + }; + + ctx.req.user = { sub: '15a3cbbe-95b5-49f0-84ee-434a9b92d04a' }; + + const envCtx = await getGwaProductEnvironment(ctx, true); + + await injectResSvrAccessTokenToContext(envCtx); + + const result = await getConsumerAccess( + envCtx, + ctx, + [ + { + resource_id: '49f95b75-6aa5-4bc0-a0bf-6a8037ca083d', + name: 'refactortime', + }, + ], + new Map() + ); + o(result); + await keystone.disconnect(); +})(); diff --git a/src/test/integrated/reports/namespaceAccess.ts b/src/test/integrated/reports/namespaceAccess.ts new file mode 100644 index 000000000..1d6d07f04 --- /dev/null +++ b/src/test/integrated/reports/namespaceAccess.ts @@ -0,0 +1,63 @@ +/* +Wire up directly with Keycloak and use the Services +export TOK="" +To run: +npm run ts-build +npm run ts-watch +node dist/test/integrated/reports/namespaceAccess.js +*/ + +import InitKeystone from '../keystonejs/init'; +import { o } from '../util'; +import { Logger } from '../../../logger'; +import { getNamespaceAccess } from '../../../services/report/data'; +import { + getGwaProductEnvironment, + injectResSvrAccessTokenToContext, +} from '../../../services/workflow'; +import { lookupProductEnvironmentServicesBySlug } from '../../../services/keystone'; + +const logger = Logger('test.reports'); + +(async () => { + const keystone = await InitKeystone(); + + const ns = 'refactortime'; + const skipAccessControl = true; + + const identity = { + id: null, + name: 'Sample User', + username: 'sample_username', + namespace: ns, + roles: JSON.stringify(['access-manager']), + scopes: [], + //userId: '60c9124f3518951bb519084d', + userId: '60c9124f3518951bb519084d', // acope@idir + } as any; + + const ctx = keystone.createContext({ + skipAccessControl, + authentication: { item: identity }, + }); + ctx.req = { + headers: { + 'x-forwarded-access-token': process.env.TOK, + }, + }; + + ctx.req.user = { sub: '15a3cbbe-95b5-49f0-84ee-434a9b92d04a' }; + + const envCtx = await getGwaProductEnvironment(ctx, true); + + await injectResSvrAccessTokenToContext(envCtx); + + const result = await getNamespaceAccess(ctx, envCtx, [ + { + resource_id: '49f95b75-6aa5-4bc0-a0bf-6a8037ca083d', + name: 'refactortime', + }, + ]); + o(result); + await keystone.disconnect(); +})(); diff --git a/src/test/integrated/workflow/migrate-user.ts b/src/test/integrated/workflow/migrate-user.ts new file mode 100644 index 000000000..cc7b8f081 --- /dev/null +++ b/src/test/integrated/workflow/migrate-user.ts @@ -0,0 +1,42 @@ +/* +Wire up directly with Keycloak and use the Services +To run: +npm run ts-build +npm run ts-watch +node dist/test/integrated/workflow/migrate-user.js +*/ + +import InitKeystone from '../keystonejs/init'; +import { + MigrateAuthzUser, + MigratePortalUser, +} from '../../../services/workflow'; + +(async () => { + const keystone = await InitKeystone(); + + const ns = 'refactortime'; + const skipAccessControl = true; + + const identity = { + id: null, + name: 'Sample User', + username: 'sample_username', + //namespace: ns, + roles: JSON.stringify(['api-owner']), + scopes: [], + userId: '60c9124f3518951bb519084d', + } as any; + + const ctx = keystone.createContext({ + skipAccessControl, + authentication: { item: identity }, + }); + + if (true) { + //await MigrateAuthzUser(ctx, 'acope@idir', 'acope2@idir', false); + await MigratePortalUser(ctx, 'acopex@idir', 'acope2@idir'); + } + + await keystone.disconnect(); +})(); diff --git a/src/test/services/batch/batch-utils.test.js b/src/test/services/batch/batch-utils.test.js index 392453bba..907c6c7d1 100644 --- a/src/test/services/batch/batch-utils.test.js +++ b/src/test/services/batch/batch-utils.test.js @@ -34,7 +34,7 @@ describe('Batch Utilities', function () { }; const output = { name: 'sample name', - blob: ['tag1', 'tag2'], + blob: [['tag1', 'tag2']], }; const result = parseBlobString(input, ['blob']); @@ -52,7 +52,7 @@ describe('Batch Utilities', function () { }; const output = { name: 'sample name', - blob: ['tag1', 'tag2'], + blob: [['tag1', 'tag2']], }; const result = parseBlobString(input); diff --git a/src/test/services/org-groups/resource.test.ts b/src/test/services/org-groups/resource.test.ts index 55d77361c..dd69ccf44 100644 --- a/src/test/services/org-groups/resource.test.ts +++ b/src/test/services/org-groups/resource.test.ts @@ -37,9 +37,9 @@ describe('Org Group Resource Service', function () { scopes: - Namespace.View users: - - user1 - - user2 - - user3 + - user1@local + - user2@local + - user3@local groups: - /organization-admin - /organization-admin/ministry-citizens-services From 63c5e67d079f0df8bbae300d2a33b92edc42f88e Mon Sep 17 00:00:00 2001 From: Joshua Jones Date: Wed, 12 Oct 2022 13:38:16 -0700 Subject: [PATCH 22/48] Feature/sprint 56 UI fixes (#596) * Add fixes for deleting application optimistically and preventing saves in controls dialog * Tighten up applications mocks, errors --- ...alhost4180devportalapplications-7fc130.gql | 2 +- ...estsnew610c1e2329ee4c2072b16fa8-312522.gql | 2 +- src/mocks/handlers.js | 9 ++ src/mocks/resolvers/applications.js | 98 +++++++++++++++++++ .../access-request-dialog.tsx | 10 +- .../application-select.tsx | 2 +- .../components/access-request/edit-dialog.tsx | 22 ++++- .../new-application-dialog.tsx | 5 +- .../pages/devportal/applications/index.tsx | 74 ++++++++------ 9 files changed, 183 insertions(+), 41 deletions(-) create mode 100644 src/mocks/resolvers/applications.js diff --git a/src/authz/graphql-whitelist/httplocalhost4180devportalapplications-7fc130.gql b/src/authz/graphql-whitelist/httplocalhost4180devportalapplications-7fc130.gql index b8ab34974..9a1989902 100644 --- a/src/authz/graphql-whitelist/httplocalhost4180devportalapplications-7fc130.gql +++ b/src/authz/graphql-whitelist/httplocalhost4180devportalapplications-7fc130.gql @@ -1,5 +1,5 @@ - mutation Remove($id: ID!) { + mutation RemoveApplication($id: ID!) { deleteApplication(id: $id) { name id diff --git a/src/authz/graphql-whitelist/httplocalhost4180devportalrequestsnew610c1e2329ee4c2072b16fa8-312522.gql b/src/authz/graphql-whitelist/httplocalhost4180devportalrequestsnew610c1e2329ee4c2072b16fa8-312522.gql index 1d2a0294c..e6ece6fe4 100644 --- a/src/authz/graphql-whitelist/httplocalhost4180devportalrequestsnew610c1e2329ee4c2072b16fa8-312522.gql +++ b/src/authz/graphql-whitelist/httplocalhost4180devportalrequestsnew610c1e2329ee4c2072b16fa8-312522.gql @@ -1,5 +1,5 @@ - mutation Add($name: String!, $description: String) { + mutation AddApplication($name: String!, $description: String) { createApplication(data: { name: $name, description: $description }) { id appId diff --git a/src/mocks/handlers.js b/src/mocks/handlers.js index d82348bf2..be8f66966 100644 --- a/src/mocks/handlers.js +++ b/src/mocks/handlers.js @@ -1,6 +1,11 @@ import { graphql, rest } from 'msw'; import { harley, mark } from './resolvers/personas'; +import { + allApplicationsHandler, + createApplicationHandler, + removeApplicationHandler, +} from './resolvers/applications'; import { allProductsByNamespaceHandler, accessRequestAuthHandler, @@ -116,6 +121,10 @@ export const handlers = [ 'GetConsumerProductsAndEnvironments', allProductsByNamespaceHandler ), + // Applications + keystone.query('MyApplications', allApplicationsHandler), + keystone.mutation('AddApplication', createApplicationHandler), + keystone.mutation('RemoveApplication', removeApplicationHandler), // Service accounts keystone.query('GetAllServiceAccounts', getAllServiceAccountsHandler), keystone.mutation('CreateServiceAccount', createServiceAccountHandler), diff --git a/src/mocks/resolvers/applications.js b/src/mocks/resolvers/applications.js new file mode 100644 index 000000000..07f048226 --- /dev/null +++ b/src/mocks/resolvers/applications.js @@ -0,0 +1,98 @@ +import casual from 'casual-browserify'; + +const applications = new Map([ + [ + 'app1', + { + id: 'app1', + appId: 'ABC123', + description: '', + name: 'Demo App', + owner: { + name: 'Mark Smith', + }, + }, + ], + [ + 'app2', + { + id: 'app2', + appId: 'ABC123', + description: '', + name: 'Shoppers Drug Mart 112', + owner: { + name: 'Mark Smith', + }, + }, + ], + [ + 'app3error', + { + id: 'app3error', + appId: 'ABC123', + description: '', + name: 'Easy Mart Store 123', + owner: { + name: 'Carter Schleifer', + }, + }, + ], +]); + +export const allApplicationsHandler = (req, res, ctx) => { + return res( + ctx.data({ + myApplications: Array.from(applications.values()), + allTemporaryIdentities: [ + { + id: 'u1', + userId: '1', + }, + ], + }) + ); +}; + +export const createApplicationHandler = (req, res, ctx) => { + if (req.variables.name === 'error') { + return res( + ctx.data({ + errors: [{ message: 'You do not have permission' }], + }) + ); + } + + const record = { + id: `app1${applications.size + 1}`, + appId: casual.uuid, + ...req.variables, + }; + applications.set(record.id, record); + return res( + ctx.data({ + createApplication: record, + }) + ); +}; + +export const removeApplicationHandler = (req, res, ctx) => { + const { id } = req.variables; + + if (id === 'app3error') { + return res( + ctx.data({ + errors: [ + { message: 'You do not have permission to delete this application' }, + ], + }) + ); + } + + const application = applications.get(id); + applications.delete(id); + return res( + ctx.data({ + deleteApplication: application, + }) + ); +}; diff --git a/src/nextapp/components/access-request-form/access-request-dialog.tsx b/src/nextapp/components/access-request-form/access-request-dialog.tsx index 362441f83..6fc8430da 100644 --- a/src/nextapp/components/access-request-form/access-request-dialog.tsx +++ b/src/nextapp/components/access-request-form/access-request-dialog.tsx @@ -71,11 +71,11 @@ const AccessRequestDialog: React.FC = ({ const buttonProps = !isInline ? {} : { - fontWeight: 'normal', - fontSize: 'inherit', - color: 'bc-link', - textDecor: 'underline', - }; + fontWeight: 'normal', + fontSize: 'inherit', + color: 'bc-link', + textDecor: 'underline', + }; // Events const handleAccessSubmit = React.useCallback( diff --git a/src/nextapp/components/access-request-form/application-select.tsx b/src/nextapp/components/access-request-form/application-select.tsx index eba1db464..fe761f070 100644 --- a/src/nextapp/components/access-request-form/application-select.tsx +++ b/src/nextapp/components/access-request-form/application-select.tsx @@ -213,7 +213,7 @@ const query = gql` `; const mutation = gql` - mutation Add($name: String!, $description: String) { + mutation AddApplication($name: String!, $description: String) { createApplication(data: { name: $name, description: $description }) { id appId diff --git a/src/nextapp/components/access-request/edit-dialog.tsx b/src/nextapp/components/access-request/edit-dialog.tsx index fe2774b03..d4fbd9a1b 100644 --- a/src/nextapp/components/access-request/edit-dialog.tsx +++ b/src/nextapp/components/access-request/edit-dialog.tsx @@ -19,11 +19,12 @@ import { Grid, useToast, Flex, + Alert, + AlertDescription, + AlertIcon, } from '@chakra-ui/react'; import { ConsumerPlugin, - GatewayPlugin, - GatewayPluginCreateInput, } from '@/shared/types/query.types'; import EnvironmentTag from '@/components/environment-tag'; import format from 'date-fns/format'; @@ -56,6 +57,7 @@ const ConsumerEditDialog: React.FC = ({ { suspense: false, enabled: isOpen } ); const [tabIndex, setTabIndex] = React.useState(0); + const [hasUnsavedChanges, setHasUnsavedChanges] = React.useState(false); const restrictions = React.useState(() => { return ( data?.getConsumerProdEnvAccess.plugins @@ -93,6 +95,7 @@ const ConsumerEditDialog: React.FC = ({ const handleClose = () => { const [, setRestrictions] = restrictions; const [, setRateLimits] = rateLimits; + setHasUnsavedChanges(false); setRestrictions( data?.getConsumerProdEnvAccess.plugins .filter((p) => p.name === 'ip-restriction') @@ -124,10 +127,16 @@ const ConsumerEditDialog: React.FC = ({ const data = { plugins: [...restrictsionsData, ...rateLimitsData], }; - const authorizationForm = ref?.current.querySelector( 'form[name="authorizationForm"]' ); + const ipRestrictionForm = new FormData(ref?.current.querySelector('form[name="ipRestrictionsForm"]')); + + if (ipRestrictionForm.get('allow') !== '[]') { + setHasUnsavedChanges(true); + return false; + } + if (authorizationForm) { const authorizationFormData = new FormData(authorizationForm); const defaultClientScopes = authorizationFormData.getAll( @@ -153,6 +162,7 @@ const ConsumerEditDialog: React.FC = ({ client.invalidateQueries(['consumerEdit', prodEnvId, consumerId]); onClose(); setTabIndex(0); + setHasUnsavedChanges(false); } catch (err) { toast({ title: 'Request save failed', @@ -249,6 +259,12 @@ const ConsumerEditDialog: React.FC = ({ {isSuccess && ( + {hasUnsavedChanges && ( + + + You have an unapplied IP Restrictions control. + + )} diff --git a/src/nextapp/components/new-product/new-product-dialog.tsx b/src/nextapp/components/new-product/new-product-dialog.tsx index d1af93864..6bdef37ae 100644 --- a/src/nextapp/components/new-product/new-product-dialog.tsx +++ b/src/nextapp/components/new-product/new-product-dialog.tsx @@ -17,69 +17,66 @@ import { Stack, useToast, } from '@chakra-ui/react'; -import { useQueryClient } from 'react-query'; -import { - ADD_ENVIRONMENT, - ADD_PRODUCT, -} from '@/shared/queries/products-queries'; +import { QueryKey, useQueryClient } from 'react-query'; import { useApiMutation } from '@/shared/services/api'; import type { Mutation } from '@/types/query.types'; +import { gql } from 'graphql-request'; interface NewProductDialogProps { open: boolean; onClose: () => void; + queryKey: QueryKey; } const NewProductDialog: React.FC = ({ open, onClose, + queryKey, }) => { const toast = useToast(); const queryClient = useQueryClient(); - const productMutation = useApiMutation<{ name: string }>(ADD_PRODUCT); + const productMutation = useApiMutation<{ name: string }>(addProductMutation); const environmentMutation = useApiMutation<{ product: string; name: string; - }>(ADD_ENVIRONMENT); + }>(addEnvironmentMutation); const form = React.useRef(); - const onSubmit = (event: React.FormEvent) => { + const handleSubmit = async (event: React.FormEvent) => { event.preventDefault(); - createProduct(); - }; - const createProduct = async () => { - if (form.current) { - const data = new FormData(form.current); + const data = new FormData(form.current); - if (form.current.checkValidity()) { - try { - const productName = data.get('name') as string; - const environment = data.get('environment') as string; - const res: Mutation = await productMutation.mutateAsync({ - name: productName, - }); - await environmentMutation.mutateAsync({ - product: res.createProduct.id, - name: environment, - }); + if (form.current.checkValidity()) { + try { + const productName = data.get('name') as string; + const environment = data.get('environment') as string; + const res: Mutation = await productMutation.mutateAsync({ + name: productName, + }); + await environmentMutation.mutateAsync({ + product: res.createProduct.id, + name: environment, + }); - queryClient.invalidateQueries('products'); - toast({ - title: `Product ${productName} created!`, - description: 'You can now add more environments', - status: 'success', - isClosable: true, - }); - onClose(); - } catch { - toast({ - title: 'Create failed', - status: 'error', - isClosable: true, - }); - } + queryClient.invalidateQueries(queryKey); + toast({ + title: `Product ${productName} created!`, + description: 'You can now add more environments', + status: 'success', + isClosable: true, + }); + onClose(); + } catch { + toast({ + title: 'Create failed', + status: 'error', + isClosable: true, + }); } } }; + const handleCreateClick = () => { + form.current?.requestSubmit(); + }; return ( @@ -87,7 +84,7 @@ const NewProductDialog: React.FC = ({ Create Product -
+ = ({ Environment + + Select the first environment for this product + = ({ - - Select the first environment for this product -
@@ -159,7 +156,7 @@ const NewProductDialog: React.FC = ({ - + ); }; diff --git a/src/nextapp/components/products-list/add-environment.tsx b/src/nextapp/components/products-list/add-environment.tsx index fb9d2b773..7c7670193 100644 --- a/src/nextapp/components/products-list/add-environment.tsx +++ b/src/nextapp/components/products-list/add-environment.tsx @@ -7,10 +7,10 @@ import { MenuItem, useToast, } from '@chakra-ui/react'; -import { useQueryClient } from 'react-query'; -import { ADD_ENVIRONMENT } from '@/shared/queries/products-queries'; +import { QueryKey, useQueryClient } from 'react-query'; import { useApiMutation } from '@/shared/services/api'; import kebabCase from 'lodash/kebabCase'; +import { gql } from 'graphql-request'; const options: { name: string; value: string }[] = [ { name: 'Development', value: 'dev' }, @@ -25,6 +25,7 @@ interface AddEnvironmentProps { environments: string[]; productId: string; productName: string; + productQueryKey: QueryKey; } const AddEnvironment: React.FC = ({ @@ -32,16 +33,19 @@ const AddEnvironment: React.FC = ({ environments, productId, productName, + productQueryKey, }) => { const toast = useToast(); const client = useQueryClient(); - const mutation = useApiMutation<{ product: string; name: string }>( - ADD_ENVIRONMENT + const mutate = useApiMutation<{ product: string; name: string }>(mutation); + const availableOptions = options.filter( + (e) => !environments.includes(e.value) ); + const onSelect = (value: string) => async () => { try { - await mutation.mutateAsync({ product: productId, name: value }); - client.invalidateQueries('products'); + await mutate.mutateAsync({ product: productId, name: value }); + client.invalidateQueries(productQueryKey); toast({ title: 'Environment added', description: 'You may now configure it. By default it is not enabled.', @@ -62,27 +66,42 @@ const AddEnvironment: React.FC = ({ {children} - {options - .filter((e) => !environments.includes(e.value)) - .map((e) => ( - - {e.name} - - ))} + {availableOptions.map((e) => ( + + {e.name} + + ))} ); }; export default AddEnvironment; + +const mutation = gql` + mutation AddEnvironment($name: String!, $product: ID!) { + createEnvironment( + data: { name: $name, product: { connect: { id: $product } } } + ) { + id + name + } + } +`; diff --git a/src/nextapp/components/products-list/dataset-input.tsx b/src/nextapp/components/products-list/dataset-input.tsx index a47701b09..e666ee8da 100644 --- a/src/nextapp/components/products-list/dataset-input.tsx +++ b/src/nextapp/components/products-list/dataset-input.tsx @@ -10,9 +10,9 @@ import { } from '@chakra-ui/react'; import Downshift, { StateChangeOptions } from 'downshift'; -import { SEARCH_DATASETS } from '@/shared/queries/dataset-queries'; import { useApi } from '@/shared/services/api'; import { Dataset } from '@/shared/types/query.types'; +import { gql } from 'graphql-request'; interface DatasetInputProps { dataset?: Dataset; @@ -22,10 +22,10 @@ const DatasetInput: React.FC = ({ dataset }) => { const theme = useTheme(); const [search, setSearch] = React.useState(''); const [selected, setSelected] = React.useState(dataset); - const { data, isLoading, isSuccess } = useApi( + const { data, isSuccess } = useApi( ['dataset-search', search], { - query: SEARCH_DATASETS, + query, variables: { search, first: 25 }, }, { @@ -76,6 +76,11 @@ const DatasetInput: React.FC = ({ dataset }) => { Link to BC Data Catalogue + + This value is the slug value of a corresponding BC Data + Catalogue entry: https://catalogue.data.gov.bc.ca/dataset/ + {selected ? selected.name : ''} + = ({ dataset }) => { )} - - - https://catalogue.data.gov.bc.ca/dataset/ - {selected ? selected.name : ''} - - - - This value is the slug value of a corresponding BC Data Catalogue - entry -
); }; export default DatasetInput; + +const query = gql` + query GetAllDatasets($search: String!, $first: Int) { + allDatasets(search: $search, first: $first) { + id + name + title + } + } +`; diff --git a/src/nextapp/components/products-list/delete-environment.tsx b/src/nextapp/components/products-list/delete-environment.tsx new file mode 100644 index 000000000..23adcf912 --- /dev/null +++ b/src/nextapp/components/products-list/delete-environment.tsx @@ -0,0 +1,100 @@ +import * as React from 'react'; +import { + AlertDialog, + AlertDialogBody, + AlertDialogContent, + AlertDialogFooter, + AlertDialogHeader, + AlertDialogOverlay, + Button, + Icon, + IconButton, + MenuItem, + useDisclosure, + useToast, +} from '@chakra-ui/react'; +import { gql } from 'graphql-request'; +import { useApiMutation } from '@/shared/services/api'; +import { Environment } from '@/shared/types/query.types'; + +import ActionsMenu from '../actions-menu'; +import { QueryKey, useQueryClient } from 'react-query'; + +interface DeleteEnvironmentProps { + data: Environment; + queryKey: QueryKey +} + +const DeleteEnvironment: React.FC = ({ data, queryKey }) => { + const { isOpen, onClose, onOpen } = useDisclosure(); + const client = useQueryClient(); + const deleteEnvironment = useApiMutation(deleteMutation); + const toast = useToast(); + const cancelRef = React.useRef(); + + const handleDeleteEnvironment = async () => { + try { + await deleteEnvironment.mutateAsync({ id: data.id, force: false }); + client.invalidateQueries(queryKey); + toast({ + status: 'success', + title: `${data.name} environment deleted`, + isClosable: true, + }); + } catch (err) { + toast({ + status: 'error', + title: 'Environment deletion failed', + description: err, + isClosable: true, + }); + } + }; + + return ( + <> + + + Delete Environment... + + + + + + + Delete Environment + + + + Are you sure? You can't undo this action afterwards. + + + + + + + + + + + ) +} + +export default DeleteEnvironment; + +const deleteMutation = gql` + mutation DeleteEnvironment($id: ID!, $force: Boolean!) { + forceDeleteEnvironment(id: $id, force: $force) + } +`; diff --git a/src/nextapp/components/products-list/delete-product.tsx b/src/nextapp/components/products-list/delete-product.tsx index 2a731dfbd..4252f791b 100644 --- a/src/nextapp/components/products-list/delete-product.tsx +++ b/src/nextapp/components/products-list/delete-product.tsx @@ -9,36 +9,39 @@ import { AlertDialogFooter, useToast, } from '@chakra-ui/react'; -import { DELETE_PRODUCT } from '@/shared/queries/products-queries'; -import { useQueryClient } from 'react-query'; +import { QueryKey, useQueryClient } from 'react-query'; import { useApiMutation } from '@/shared/services/api'; +import { gql } from 'graphql-request'; interface DeleteProductProps { id: string; + isOpen: boolean; + onClose: () => void; onDeleted: () => void; + queryKey: QueryKey; } -const DeleteProduct: React.FC = ({ id, onDeleted }) => { +const DeleteProduct: React.FC = ({ + id, + isOpen, + onClose, + onDeleted, + queryKey, +}) => { const toast = useToast(); const client = useQueryClient(); - const [isOpen, setIsOpen] = React.useState(false); - const onClose = () => setIsOpen(false); const cancelRef = React.useRef(); - const onOpen = () => { - setIsOpen(true); - }; - const mutation = useApiMutation<{ id: string }>(DELETE_PRODUCT); + const mutate = useApiMutation<{ id: string }>(mutation); const onDelete = async () => { try { - await mutation.mutateAsync({ id }); + await mutate.mutateAsync({ id }); toast({ title: 'Product deleted', status: 'success', isClosable: true, }); onDeleted(); - setIsOpen(false); - client.invalidateQueries('products'); + client.invalidateQueries(queryKey); } catch { toast({ title: 'Product delete failed', @@ -49,47 +52,45 @@ const DeleteProduct: React.FC = ({ id, onDeleted }) => { }; return ( - <> - - - - - - Delete Product - - - - Are you sure? You can not undo this action afterwards. - + + + + + Delete Product + + + Are you sure? You can not undo this action afterwards. + - - - - - - - - + + + + + + + ); }; export default DeleteProduct; + +const mutation = gql` + mutation RemoveProduct($id: ID!) { + deleteProduct(id: $id) { + id + } + } +`; diff --git a/src/nextapp/components/products-list/edit-product.tsx b/src/nextapp/components/products-list/edit-product.tsx index b347d6a54..ba3739de7 100644 --- a/src/nextapp/components/products-list/edit-product.tsx +++ b/src/nextapp/components/products-list/edit-product.tsx @@ -1,11 +1,9 @@ import * as React from 'react'; import { - Box, Button, FormControl, FormLabel, FormHelperText, - Icon, Input, Modal, ModalOverlay, @@ -16,28 +14,30 @@ import { useDisclosure, useToast, VStack, + MenuItem, } from '@chakra-ui/react'; -import { FaPenSquare } from 'react-icons/fa'; -import { useQueryClient } from 'react-query'; +import { QueryKey, useQueryClient } from 'react-query'; import { useApiMutation } from '@/shared/services/api'; -import { UPDATE_PRODUCT } from '@/shared/queries/products-queries'; import type { Product, ProductUpdateInput } from '@/shared/types/query.types'; import kebabCase from 'lodash/kebabCase'; import DatasetInput from './dataset-input'; import DeleteProduct from './delete-product'; -import OrganizationSelect from './organization-select'; +import ActionsMenu from '../actions-menu'; +import { gql } from 'graphql-request'; interface EditProductProps { data: Product; + queryKey: QueryKey; } -const EditProduct: React.FC = ({ data }) => { +const EditProduct: React.FC = ({ data, queryKey }) => { const client = useQueryClient(); const formRef = React.useRef(null); const toast = useToast(); const { isOpen, onOpen, onClose } = useDisclosure(); - const mutation = useApiMutation(UPDATE_PRODUCT); - const updateProduct = React.useCallback(async () => { + const deleteDisclosure = useDisclosure(); + const mutate = useApiMutation(mutation); + const updateProduct = async () => { try { const formData = new FormData(formRef.current); const payload: ProductUpdateInput = { @@ -60,8 +60,8 @@ const EditProduct: React.FC = ({ data }) => { } } - await mutation.mutateAsync({ id: data.id, data: payload }); - client.invalidateQueries(['products']); + await mutate.mutateAsync({ id: data.id, data: payload }); + await client.invalidateQueries(queryKey); onClose(); toast({ title: `${data.name} updated`, @@ -69,46 +69,54 @@ const EditProduct: React.FC = ({ data }) => { isClosable: true, }); } catch (err) { - console.error(err.message); toast({ title: 'Update product failed', status: 'error', + description: err, isClosable: true, }); } - }, [client, data, mutation, onClose, toast]); - const onUpdate = React.useCallback(() => { - if (formRef.current.checkValidity()) { - updateProduct(); - } - }, [updateProduct]); - const onSubmit = React.useCallback( - (event) => { - event.preventDefault(); - updateProduct; - }, - [updateProduct] - ); + }; + const handleSaveClick = () => { + formRef.current?.requestSubmit(); + }; + const handleSubmit = (event: React.FormEvent) => { + event.preventDefault(); + updateProduct(); + }; + const dataTestIdName = kebabCase(data.name); return ( <> - + + + Edit Product + + + Delete Product... + + + {`Edit ${data.name}`} -
+ Product Name + Must be unique = ({ data }) => { variant="bc-input" data-testid="prd-edit-name-input" /> - Must be unique @@ -124,16 +131,19 @@ const EditProduct: React.FC = ({ data }) => { - - - + + + + + + + Authorization + + + + + + Issuer + + + + + + Instructions for Requester (Optional) + + + + + + Terms of Use + + + + + + + Require Approval + + + Enable Environment + + + + + + + + + ); +}; + +export default AuthorizationFlow; + +const flowTypes: { value: string; label: string }[] = [ + { value: 'public', label: 'Public' }, + { value: 'authorization-code', label: 'Oauth2 Authorization Code Flow' }, + { value: 'client-credentials', label: 'Oauth2 Client Credentials Flow' }, + { value: 'kong-acl-only', label: 'Kong ACL Only' }, + { value: 'kong-api-key-only', label: 'Kong API Key Only' }, + { value: 'kong-api-key-acl', label: 'Kong API Key with ACL Flow' }, +]; diff --git a/src/nextapp/components/environment-edit/configure-environment.tsx b/src/nextapp/components/environment-edit/configure-environment.tsx new file mode 100644 index 000000000..81daa1aa2 --- /dev/null +++ b/src/nextapp/components/environment-edit/configure-environment.tsx @@ -0,0 +1,214 @@ +import * as React from 'react'; +import { + Box, + Center, + Flex, + Heading, + Select, + Tag, + TagCloseButton, + TagLabel, + TagRightIcon, + Text, + Wrap, + WrapItem, +} from '@chakra-ui/react'; +import { FaGripVertical } from 'react-icons/fa'; +import { Environment, GatewayService } from '@/shared/types/query.types'; +import SearchInput from '../search-input'; +import EmptyPane from '../empty-pane'; + +const dataTransferType = 'application/service'; + +interface ConfigureEnvironmentProps { + data: GatewayService[]; + environment: Environment; + hasError?: boolean; +} + +const ConfigureEnvironment: React.FC = ({ + data, + environment, + hasError, +}) => { + const dragRef = React.useRef(null); + const [hasDragTarget, setDragTarget] = React.useState(false); + const [activeServices, setActiveServices] = React.useState(() => { + try { + return environment.services; + } catch { + return []; + } + }); + const [search, setSearch] = React.useState(''); + const [sort, setSort] = React.useState('name'); + const value = React.useMemo(() => { + const result = activeServices.map((s) => s.id); + return JSON.stringify(result); + }, [activeServices]); + const availableServices = React.useMemo(() => { + return data + .filter((s) => !activeServices.map((a) => a.id).includes(s.id)) + .filter((s) => { + if (s.name.search(search) >= 0) { + return true; + } + return false; + }) + .sort((a, b) => { + if (sort === 'name') { + return a.name > b.name ? 1 : -1; + } + if (sort === 'date') { + return a.updatedAt > b.updatedAt ? 1 : -1; + } + }); + }, [activeServices, data, search, sort]); + + // Events + const handleServiceSelect = (service: GatewayService) => () => { + setActiveServices((state) => [...state, service]); + }; + const handleDragStart = (d: GatewayService) => ( + event: React.DragEvent + ) => { + const data = JSON.stringify(d); + dragRef.current = data; + event.dataTransfer.setData(dataTransferType, data); + event.dataTransfer.effectAllowed = 'move'; + }; + const handleDrop = () => { + setActiveServices((state) => [...state, JSON.parse(dragRef.current)]); + setDragTarget(true); + }; + const handleDragOver = (event: React.DragEvent) => { + event.preventDefault(); + event.dataTransfer.dropEffect = 'move'; + setDragTarget(true); + }; + const handleDragExit = (event: React.DragEvent) => { + event.preventDefault(); + setDragTarget(false); + }; + const handleRemoveService = (id: string) => () => { + setActiveServices((state) => state.filter((s) => s.id !== id)); + }; + const handleSearchChange = (value: string) => { + setSearch(value); + }; + const handleSortChange = (event: React.ChangeEvent) => { + setSort(event.target.value); + }; + + return ( +
+ + {`Active Services (${activeServices.length ?? 0})`} + + + {activeServices.length <= 0 && ( +
+ + Drag and Drop + available services here to activate them + +
+ )} + + {activeServices.length > 0 && ( + + {activeServices.map((s) => ( + + + {s.name} + + + + ))} + + )} +
+ + + {`Available Services (${availableServices.length ?? 0})`} + + + + + + + + {availableServices.length === 0 && ( + div': { + py: 2, + }, + }} + title={ + search ? `No services match ${search}` : 'No available services' + } + message={ + search + ? 'Try changing your search term' + : 'All services assigned to Environments' + } + /> + )} + + {availableServices.map((s) => ( + + + + {s.name} + + + + + ))} + + +
+ ); +}; + +export default ConfigureEnvironment; diff --git a/src/nextapp/components/environment-edit/environment-edit-dialog.tsx b/src/nextapp/components/environment-edit/environment-edit-dialog.tsx new file mode 100644 index 000000000..986bc538f --- /dev/null +++ b/src/nextapp/components/environment-edit/environment-edit-dialog.tsx @@ -0,0 +1,347 @@ +import * as React from 'react'; +import { + Alert, + AlertDescription, + AlertIcon, + Box, + Button, + ButtonGroup, + Flex, + Modal, + ModalBody, + ModalContent, + ModalFooter, + ModalHeader, + ModalOverlay, + Tab, + TabList, + Tabs, + Tag, + Tooltip, + useToast, +} from '@chakra-ui/react'; +import { Environment, Product } from '@/shared/types/query.types'; +import { ExpandableCards, ExpandableCard } from '@/components/card'; +import { gql } from 'graphql-request'; +import { useApi, useApiMutation } from '@/shared/services/api'; +import { FaLock } from 'react-icons/fa'; +import { QueryKey, useQueryClient } from 'react-query'; +import { useAuth } from '@/shared/services/auth'; + +import AuthorizationFlow from './authorization-flow'; +import ConfigureEnvironment from './configure-environment'; +import { difference } from 'lodash'; + +interface EnvironmentEditDialogProps { + environment: Environment; + open: boolean; + onClose: () => void; + product: Product; + productQueryKey: QueryKey; +} +const EnvironmentEditDialog: React.FC = ({ + environment, + open, + onClose, + product, + productQueryKey, +}) => { + const [tab, setTab] = React.useState(0); + const [flow, setFlow] = React.useState(environment.flow ?? 'public'); + const auth = useAuth(); + const formRef = React.useRef(null); + const client = useQueryClient(); + const toast = useToast(); + const queryKey = ['environment', environment.id]; + const { data, isLoading, isError, isSuccess } = useApi( + queryKey, + { query, variables: { id: environment.id } }, + { + enabled: open, + suspense: false, + } + ); + const servicesRequest = useApi( + ['allGatewayServices'], + { + query: servicesQuery, + variables: { ns: auth.user.namespace }, + }, + { suspense: false, enabled: Boolean(auth?.user.namespace) } + ); + const mutate = useApiMutation(mutation); + const isConfigureServicesTabEnabled = React.useMemo(() => { + if (isSuccess && data.OwnedEnvironment?.services.length > 0) { + return true; + } + if (servicesRequest.isSuccess) { + return servicesRequest.data?.allGatewayServices?.length > 0; + } + return false; + }, [data, isSuccess, servicesRequest.data, servicesRequest.isSuccess]); + // Events + const handleSetNextTab = () => { + if (formRef.current?.checkValidity()) { + setTab(1); + } else { + formRef.current?.reportValidity(); + } + }; + const handleClose = () => { + mutate.reset(); + setTab(0); + onClose(); + }; + const handleSubmit = async (event: React.FormEvent) => { + event.preventDefault(); + try { + const formData = new FormData(formRef.current); + const entries = Object.fromEntries(formData); + const activeValue = formData.get('active'); + const approvalValue = formData.get('approval'); + const credentialIssuerValue = formData.get('credentialIssuer'); + const credentialIssuer = credentialIssuerValue + ? { + connect: { + id: credentialIssuerValue, + }, + } + : { + disconnectAll: true, + }; + const legalValue = formData.get('legal'); + const legal = legalValue + ? { + connect: { + id: legalValue, + }, + } + : { + disconnectAll: true, + }; + const servicesValue = formData.get('services'); + const selectedServices: string[] = + JSON.parse(servicesValue as string) ?? []; + const disconnectServices: string[] = difference( + data.OwnedEnvironment.services.map((s) => s.id), + selectedServices + ); + const services = { + connect: selectedServices.map((id) => ({ id })), + disconnect: disconnectServices.map((id) => ({ id })), + }; + const payload = { + ...entries, + active: Boolean(activeValue), + approval: Boolean(approvalValue), + legal, + services, + credentialIssuer, + }; + await mutate.mutateAsync({ id: environment.id, data: payload }); + await client.invalidateQueries(queryKey); + await client.invalidateQueries(productQueryKey); + toast({ + title: 'Success', + description: `Your ${environment.name} environment for ${product.name} has been updated successfully`, + status: 'success', + isClosable: true, + }); + handleClose(); + } catch (err) { + toast({ + title: 'Services update failed', + description: err, + status: 'error', + isClosable: true, + }); + } + }; + const handleSave = () => { + if (formRef.current?.checkValidity()) { + formRef.current?.requestSubmit(); + } + }; + + return ( + + + + + + {product.name} + + {environment.name} + + + + + setTab(0)} + data-testid="edit-env-configure-env-tab" + > + Configure Environment + + + + Configure Environment Services + + + + + + + {(isError || mutate.isError) && ( + + + + {isError && 'Unable to load environment details'} + {mutate.isError && mutate.error} + + + )} + {isLoading && 'Loading...'} + {isSuccess && ( + + + + + )} + + + + + {tab === 0 && isConfigureServicesTabEnabled && ( + + )} + {(tab === 1 || !isConfigureServicesTabEnabled) && ( + + )} + + + + + ); +}; + +export default EnvironmentEditDialog; + +const query = gql` + query GetOwnedEnvironment($id: ID!) { + OwnedEnvironment(where: { id: $id }) { + id + name + active + flow + appId + legal { + id + title + reference + } + credentialIssuer { + id + } + approval + additionalDetailsToRequest + product { + name + namespace + organization { + name + } + environments { + name + id + } + } + services { + name + id + updatedAt + } + } + } +`; +const servicesQuery = gql` + query GetAllGatewayServices($ns: String!) { + allGatewayServices(where: { namespace: $ns }) { + id + name + environment { + id + } + } + } +`; + +const mutation = gql` + mutation UpdateEnvironment($id: ID!, $data: EnvironmentUpdateInput) { + updateEnvironment(id: $id, data: $data) { + name + id + } + } +`; diff --git a/src/nextapp/components/environment-edit/environment-edit.tsx b/src/nextapp/components/environment-edit/environment-edit.tsx new file mode 100644 index 000000000..50934d12d --- /dev/null +++ b/src/nextapp/components/environment-edit/environment-edit.tsx @@ -0,0 +1,47 @@ +import * as React from 'react'; +import { Button, Icon, useDisclosure } from '@chakra-ui/react'; +import kebabCase from 'lodash/kebabCase'; + +import { FaPen } from 'react-icons/fa'; +import EnvironmentEditDialog from './environment-edit-dialog'; +import { Environment, Product } from '@/shared/types/query.types'; +import { QueryKey } from 'react-query'; + +interface EnvironmentEditProps { + data: Environment; + product: Product; + productQueryKey: QueryKey; +} + +const EnvironmentEdit: React.FC = ({ + data, + product, + productQueryKey, +}) => { + const { isOpen, onOpen, onClose } = useDisclosure(); + + return ( + <> + + + + ); +}; + +export default EnvironmentEdit; diff --git a/src/nextapp/components/environment-edit/index.ts b/src/nextapp/components/environment-edit/index.ts new file mode 100644 index 000000000..a991e5585 --- /dev/null +++ b/src/nextapp/components/environment-edit/index.ts @@ -0,0 +1 @@ +export { default } from './environment-edit'; diff --git a/src/nextapp/components/environment-plugins/environment-plugins.tsx b/src/nextapp/components/environment-plugins/environment-plugins.tsx index f58179564..f265a51ab 100644 --- a/src/nextapp/components/environment-plugins/environment-plugins.tsx +++ b/src/nextapp/components/environment-plugins/environment-plugins.tsx @@ -1,6 +1,14 @@ import * as React from 'react'; -import { Box, Heading, Text, Icon, Flex, Divider } from '@chakra-ui/react'; -import { FaCircle, FaCode } from 'react-icons/fa'; +import { + Box, + Text, + Center, + CircularProgress, + Alert, + AlertIcon, + AlertDescription, + Tag, +} from '@chakra-ui/react'; import { Environment } from '@/shared/types/query.types'; import YamlViewer from '../yaml-viewer'; import JwtKeycloak from './templates/jwt-keycloak'; @@ -11,71 +19,97 @@ import { gql } from 'graphql-request'; import { useApi } from '@/shared/services/api'; interface EnvironmentPluginsProps { - data: Environment; + environment: Environment; + flow: string; } -const query = gql` - query GET($id: ID!) { - allCredentialIssuersByNamespace(where: { id: $id }) { - environmentDetails - } - } -`; - -const EnvironmentPlugins: React.FC = ({ data }) => { - const flow = data.flow; - - const issuerDetails = { issuer: null }; - - if (data?.credentialIssuer?.id) { - const variables = { id: data?.credentialIssuer?.id }; - const { data: _data, isLoading, isSuccess } = useApi( - ['environment-credential', data?.credentialIssuer?.id], - { - query, - variables, - }, - { - suspense: false, - } - ); - - if (isLoading) { - return <>; +const EnvironmentPlugins: React.FC = ({ + environment, + flow, +}) => { + const id = environment?.credentialIssuer?.id; + const { data, isLoading, isSuccess } = useApi( + ['environment-credential', environment?.credentialIssuer?.id], + { + query, + variables: { id }, + }, + { + enabled: Boolean(id), + suspense: false, } - issuerDetails.issuer = _data.allCredentialIssuersByNamespace[0]; - } - + ); + const issuer = data?.allCredentialIssuersByNamespace[0]; const pluginConfigs = { - 'kong-api-key-acl': KongApiKeyAcl(data.product.namespace, data.appId), - 'kong-api-key-only': KongApiKeyOnly(data.product.namespace, data.appId), - 'kong-acl-only': KongAclOnly(data.product.namespace, data.appId), + 'kong-api-key-acl': KongApiKeyAcl( + environment?.product.namespace, + environment?.appId + ), + 'kong-api-key-only': KongApiKeyOnly(environment?.product.namespace), + 'kong-acl-only': KongAclOnly( + environment?.product.namespace, + environment?.appId + ), 'client-credentials': JwtKeycloak( - data.product.namespace, - data.name, - issuerDetails.issuer + environment?.product.namespace, + environment?.name, + issuer ), }; + const doc = pluginConfigs[flow]; + return ( - flow in pluginConfigs && ( - - - - Plugin Template - - - - - Ensure that services associated with this environment have the - following plugins configured: - - - - - + <> + + + Ensure that services associated with this environment have the + following plugins configured: + + + + {isLoading && ( +
+ +
+ )} + {flow === 'client-credentials' && !id && ( + + + + Credential Issuer missing setup for{' '} + {environment.name} environment + + + )} + {doc && }{' '} + {(!doc || data?.allCredentialIssuersByNamespace.length === 0) && ( + + + + Authorization Profile missing setup for{' '} + {environment.name} environment + + + )}
- ) + ); }; export default EnvironmentPlugins; + +const query = gql` + query GetAllCredentialIssuersByNamespace($id: ID!) { + allCredentialIssuersByNamespace(where: { id: $id }) { + environmentDetails + } + } +`; diff --git a/src/nextapp/components/environment-plugins/templates/jwt-keycloak.ts b/src/nextapp/components/environment-plugins/templates/jwt-keycloak.ts index 91f34e3d1..9d31d5fb7 100644 --- a/src/nextapp/components/environment-plugins/templates/jwt-keycloak.ts +++ b/src/nextapp/components/environment-plugins/templates/jwt-keycloak.ts @@ -1,12 +1,22 @@ -export default function JwtKeycloak(namespace, envName, issuer) { - if (issuer == null || issuer.environmentDetails == null) { +import { CredentialIssuer } from '@/shared/types/query.types'; + +export default function JwtKeycloak( + namespace: string, + envName: string, + issuer: CredentialIssuer +): string { + if (!issuer || !issuer.environmentDetails) { return ''; } - const envDetails = JSON.parse(issuer.environmentDetails); - const env = envDetails.filter((e) => e.environment === envName); - if (env.length == 0) { + const envDetails: { environment: string; issuerUrl: string }[] = JSON.parse( + issuer.environmentDetails + ); + const env = envDetails.find((e) => e.environment === envName); + + if (!env) { return ''; } + return ` plugins: - name: jwt-keycloak @@ -14,9 +24,9 @@ export default function JwtKeycloak(namespace, envName, issuer) { enabled: true config: algorithm: RS256 - well_known_template: ${env[0].issuerUrl}/.well-known/openid-configuration + well_known_template: ${env.issuerUrl}/.well-known/openid-configuration allowed_iss: - - ${env[0].issuerUrl} + - ${env.issuerUrl} run_on_preflight: true iss_key_grace_period: 10 maximum_expiration: 0 diff --git a/src/nextapp/components/environment-plugins/templates/kong-acl-only.ts b/src/nextapp/components/environment-plugins/templates/kong-acl-only.ts index a078aec3c..fe621d1e6 100644 --- a/src/nextapp/components/environment-plugins/templates/kong-acl-only.ts +++ b/src/nextapp/components/environment-plugins/templates/kong-acl-only.ts @@ -1,4 +1,4 @@ -export default function KongAclOnly(namespace, appId) { +export default function KongAclOnly(namespace: string, appId: string): string { return ` plugins: - name: acl diff --git a/src/nextapp/components/environment-plugins/templates/kong-api-key-acl.ts b/src/nextapp/components/environment-plugins/templates/kong-api-key-acl.ts index ab5b894d3..7834f37d9 100644 --- a/src/nextapp/components/environment-plugins/templates/kong-api-key-acl.ts +++ b/src/nextapp/components/environment-plugins/templates/kong-api-key-acl.ts @@ -1,4 +1,7 @@ -export default function KongApiKeyAcl(namespace, appId) { +export default function KongApiKeyAcl( + namespace: string, + appId: string +): string { return ` plugins: - name: key-auth diff --git a/src/nextapp/components/environment-plugins/templates/kong-api-key-only.ts b/src/nextapp/components/environment-plugins/templates/kong-api-key-only.ts index d2b80e3fd..b3ec6ee72 100644 --- a/src/nextapp/components/environment-plugins/templates/kong-api-key-only.ts +++ b/src/nextapp/components/environment-plugins/templates/kong-api-key-only.ts @@ -1,4 +1,4 @@ -export default function KongApiKeyAcl(namespace, appId) { +export default function KongApiKeyAcl(namespace: string): string { return ` plugins: - name: key-auth diff --git a/src/nextapp/components/environments-list/edit-environment.tsx b/src/nextapp/components/environments-list/edit-environment.tsx index c8225c689..5f57ea927 100644 --- a/src/nextapp/components/environments-list/edit-environment.tsx +++ b/src/nextapp/components/environments-list/edit-environment.tsx @@ -1,11 +1,8 @@ import * as React from 'react'; import { Button, - Checkbox, FormControl, FormLabel, - FormErrorMessage, - FormHelperText, Icon, Modal, ModalOverlay, @@ -14,7 +11,6 @@ import { ModalFooter, ModalBody, useDisclosure, - Input, IconButton, Select, VStack, @@ -81,7 +77,7 @@ const EditEnvironment: React.FC = ({ data }) => { Auth Method diff --git a/src/nextapp/components/new-product/new-product-dialog.tsx b/src/nextapp/components/new-product/new-product-dialog.tsx index d1af93864..6bdef37ae 100644 --- a/src/nextapp/components/new-product/new-product-dialog.tsx +++ b/src/nextapp/components/new-product/new-product-dialog.tsx @@ -17,69 +17,66 @@ import { Stack, useToast, } from '@chakra-ui/react'; -import { useQueryClient } from 'react-query'; -import { - ADD_ENVIRONMENT, - ADD_PRODUCT, -} from '@/shared/queries/products-queries'; +import { QueryKey, useQueryClient } from 'react-query'; import { useApiMutation } from '@/shared/services/api'; import type { Mutation } from '@/types/query.types'; +import { gql } from 'graphql-request'; interface NewProductDialogProps { open: boolean; onClose: () => void; + queryKey: QueryKey; } const NewProductDialog: React.FC = ({ open, onClose, + queryKey, }) => { const toast = useToast(); const queryClient = useQueryClient(); - const productMutation = useApiMutation<{ name: string }>(ADD_PRODUCT); + const productMutation = useApiMutation<{ name: string }>(addProductMutation); const environmentMutation = useApiMutation<{ product: string; name: string; - }>(ADD_ENVIRONMENT); + }>(addEnvironmentMutation); const form = React.useRef(); - const onSubmit = (event: React.FormEvent) => { + const handleSubmit = async (event: React.FormEvent) => { event.preventDefault(); - createProduct(); - }; - const createProduct = async () => { - if (form.current) { - const data = new FormData(form.current); + const data = new FormData(form.current); - if (form.current.checkValidity()) { - try { - const productName = data.get('name') as string; - const environment = data.get('environment') as string; - const res: Mutation = await productMutation.mutateAsync({ - name: productName, - }); - await environmentMutation.mutateAsync({ - product: res.createProduct.id, - name: environment, - }); + if (form.current.checkValidity()) { + try { + const productName = data.get('name') as string; + const environment = data.get('environment') as string; + const res: Mutation = await productMutation.mutateAsync({ + name: productName, + }); + await environmentMutation.mutateAsync({ + product: res.createProduct.id, + name: environment, + }); - queryClient.invalidateQueries('products'); - toast({ - title: `Product ${productName} created!`, - description: 'You can now add more environments', - status: 'success', - isClosable: true, - }); - onClose(); - } catch { - toast({ - title: 'Create failed', - status: 'error', - isClosable: true, - }); - } + queryClient.invalidateQueries(queryKey); + toast({ + title: `Product ${productName} created!`, + description: 'You can now add more environments', + status: 'success', + isClosable: true, + }); + onClose(); + } catch { + toast({ + title: 'Create failed', + status: 'error', + isClosable: true, + }); } } }; + const handleCreateClick = () => { + form.current?.requestSubmit(); + }; return ( @@ -87,7 +84,7 @@ const NewProductDialog: React.FC = ({ Create Product -
+ = ({ Environment + + Select the first environment for this product + = ({ - - Select the first environment for this product -
@@ -159,7 +156,7 @@ const NewProductDialog: React.FC = ({ - + ); }; diff --git a/src/nextapp/components/products-list/add-environment.tsx b/src/nextapp/components/products-list/add-environment.tsx index fb9d2b773..7c7670193 100644 --- a/src/nextapp/components/products-list/add-environment.tsx +++ b/src/nextapp/components/products-list/add-environment.tsx @@ -7,10 +7,10 @@ import { MenuItem, useToast, } from '@chakra-ui/react'; -import { useQueryClient } from 'react-query'; -import { ADD_ENVIRONMENT } from '@/shared/queries/products-queries'; +import { QueryKey, useQueryClient } from 'react-query'; import { useApiMutation } from '@/shared/services/api'; import kebabCase from 'lodash/kebabCase'; +import { gql } from 'graphql-request'; const options: { name: string; value: string }[] = [ { name: 'Development', value: 'dev' }, @@ -25,6 +25,7 @@ interface AddEnvironmentProps { environments: string[]; productId: string; productName: string; + productQueryKey: QueryKey; } const AddEnvironment: React.FC = ({ @@ -32,16 +33,19 @@ const AddEnvironment: React.FC = ({ environments, productId, productName, + productQueryKey, }) => { const toast = useToast(); const client = useQueryClient(); - const mutation = useApiMutation<{ product: string; name: string }>( - ADD_ENVIRONMENT + const mutate = useApiMutation<{ product: string; name: string }>(mutation); + const availableOptions = options.filter( + (e) => !environments.includes(e.value) ); + const onSelect = (value: string) => async () => { try { - await mutation.mutateAsync({ product: productId, name: value }); - client.invalidateQueries('products'); + await mutate.mutateAsync({ product: productId, name: value }); + client.invalidateQueries(productQueryKey); toast({ title: 'Environment added', description: 'You may now configure it. By default it is not enabled.', @@ -62,27 +66,42 @@ const AddEnvironment: React.FC = ({ {children} - {options - .filter((e) => !environments.includes(e.value)) - .map((e) => ( - - {e.name} - - ))} + {availableOptions.map((e) => ( + + {e.name} + + ))} ); }; export default AddEnvironment; + +const mutation = gql` + mutation AddEnvironment($name: String!, $product: ID!) { + createEnvironment( + data: { name: $name, product: { connect: { id: $product } } } + ) { + id + name + } + } +`; diff --git a/src/nextapp/components/products-list/dataset-input.tsx b/src/nextapp/components/products-list/dataset-input.tsx index a47701b09..e666ee8da 100644 --- a/src/nextapp/components/products-list/dataset-input.tsx +++ b/src/nextapp/components/products-list/dataset-input.tsx @@ -10,9 +10,9 @@ import { } from '@chakra-ui/react'; import Downshift, { StateChangeOptions } from 'downshift'; -import { SEARCH_DATASETS } from '@/shared/queries/dataset-queries'; import { useApi } from '@/shared/services/api'; import { Dataset } from '@/shared/types/query.types'; +import { gql } from 'graphql-request'; interface DatasetInputProps { dataset?: Dataset; @@ -22,10 +22,10 @@ const DatasetInput: React.FC = ({ dataset }) => { const theme = useTheme(); const [search, setSearch] = React.useState(''); const [selected, setSelected] = React.useState(dataset); - const { data, isLoading, isSuccess } = useApi( + const { data, isSuccess } = useApi( ['dataset-search', search], { - query: SEARCH_DATASETS, + query, variables: { search, first: 25 }, }, { @@ -76,6 +76,11 @@ const DatasetInput: React.FC = ({ dataset }) => { Link to BC Data Catalogue + + This value is the slug value of a corresponding BC Data + Catalogue entry: https://catalogue.data.gov.bc.ca/dataset/ + {selected ? selected.name : ''} + = ({ dataset }) => { )} - - - https://catalogue.data.gov.bc.ca/dataset/ - {selected ? selected.name : ''} - - - - This value is the slug value of a corresponding BC Data Catalogue - entry - ); }; export default DatasetInput; + +const query = gql` + query GetAllDatasets($search: String!, $first: Int) { + allDatasets(search: $search, first: $first) { + id + name + title + } + } +`; diff --git a/src/nextapp/components/products-list/delete-environment.tsx b/src/nextapp/components/products-list/delete-environment.tsx new file mode 100644 index 000000000..23adcf912 --- /dev/null +++ b/src/nextapp/components/products-list/delete-environment.tsx @@ -0,0 +1,100 @@ +import * as React from 'react'; +import { + AlertDialog, + AlertDialogBody, + AlertDialogContent, + AlertDialogFooter, + AlertDialogHeader, + AlertDialogOverlay, + Button, + Icon, + IconButton, + MenuItem, + useDisclosure, + useToast, +} from '@chakra-ui/react'; +import { gql } from 'graphql-request'; +import { useApiMutation } from '@/shared/services/api'; +import { Environment } from '@/shared/types/query.types'; + +import ActionsMenu from '../actions-menu'; +import { QueryKey, useQueryClient } from 'react-query'; + +interface DeleteEnvironmentProps { + data: Environment; + queryKey: QueryKey +} + +const DeleteEnvironment: React.FC = ({ data, queryKey }) => { + const { isOpen, onClose, onOpen } = useDisclosure(); + const client = useQueryClient(); + const deleteEnvironment = useApiMutation(deleteMutation); + const toast = useToast(); + const cancelRef = React.useRef(); + + const handleDeleteEnvironment = async () => { + try { + await deleteEnvironment.mutateAsync({ id: data.id, force: false }); + client.invalidateQueries(queryKey); + toast({ + status: 'success', + title: `${data.name} environment deleted`, + isClosable: true, + }); + } catch (err) { + toast({ + status: 'error', + title: 'Environment deletion failed', + description: err, + isClosable: true, + }); + } + }; + + return ( + <> + + + Delete Environment... + + + + + + + Delete Environment + + + + Are you sure? You can't undo this action afterwards. + + + + + + + + + + + ) +} + +export default DeleteEnvironment; + +const deleteMutation = gql` + mutation DeleteEnvironment($id: ID!, $force: Boolean!) { + forceDeleteEnvironment(id: $id, force: $force) + } +`; diff --git a/src/nextapp/components/products-list/delete-product.tsx b/src/nextapp/components/products-list/delete-product.tsx index 2a731dfbd..4252f791b 100644 --- a/src/nextapp/components/products-list/delete-product.tsx +++ b/src/nextapp/components/products-list/delete-product.tsx @@ -9,36 +9,39 @@ import { AlertDialogFooter, useToast, } from '@chakra-ui/react'; -import { DELETE_PRODUCT } from '@/shared/queries/products-queries'; -import { useQueryClient } from 'react-query'; +import { QueryKey, useQueryClient } from 'react-query'; import { useApiMutation } from '@/shared/services/api'; +import { gql } from 'graphql-request'; interface DeleteProductProps { id: string; + isOpen: boolean; + onClose: () => void; onDeleted: () => void; + queryKey: QueryKey; } -const DeleteProduct: React.FC = ({ id, onDeleted }) => { +const DeleteProduct: React.FC = ({ + id, + isOpen, + onClose, + onDeleted, + queryKey, +}) => { const toast = useToast(); const client = useQueryClient(); - const [isOpen, setIsOpen] = React.useState(false); - const onClose = () => setIsOpen(false); const cancelRef = React.useRef(); - const onOpen = () => { - setIsOpen(true); - }; - const mutation = useApiMutation<{ id: string }>(DELETE_PRODUCT); + const mutate = useApiMutation<{ id: string }>(mutation); const onDelete = async () => { try { - await mutation.mutateAsync({ id }); + await mutate.mutateAsync({ id }); toast({ title: 'Product deleted', status: 'success', isClosable: true, }); onDeleted(); - setIsOpen(false); - client.invalidateQueries('products'); + client.invalidateQueries(queryKey); } catch { toast({ title: 'Product delete failed', @@ -49,47 +52,45 @@ const DeleteProduct: React.FC = ({ id, onDeleted }) => { }; return ( - <> - - - - - - Delete Product - - - - Are you sure? You can not undo this action afterwards. - + + + + + Delete Product + + + Are you sure? You can not undo this action afterwards. + - - - - - - - - + + + + + + + ); }; export default DeleteProduct; + +const mutation = gql` + mutation RemoveProduct($id: ID!) { + deleteProduct(id: $id) { + id + } + } +`; diff --git a/src/nextapp/components/products-list/edit-product.tsx b/src/nextapp/components/products-list/edit-product.tsx index b347d6a54..ba3739de7 100644 --- a/src/nextapp/components/products-list/edit-product.tsx +++ b/src/nextapp/components/products-list/edit-product.tsx @@ -1,11 +1,9 @@ import * as React from 'react'; import { - Box, Button, FormControl, FormLabel, FormHelperText, - Icon, Input, Modal, ModalOverlay, @@ -16,28 +14,30 @@ import { useDisclosure, useToast, VStack, + MenuItem, } from '@chakra-ui/react'; -import { FaPenSquare } from 'react-icons/fa'; -import { useQueryClient } from 'react-query'; +import { QueryKey, useQueryClient } from 'react-query'; import { useApiMutation } from '@/shared/services/api'; -import { UPDATE_PRODUCT } from '@/shared/queries/products-queries'; import type { Product, ProductUpdateInput } from '@/shared/types/query.types'; import kebabCase from 'lodash/kebabCase'; import DatasetInput from './dataset-input'; import DeleteProduct from './delete-product'; -import OrganizationSelect from './organization-select'; +import ActionsMenu from '../actions-menu'; +import { gql } from 'graphql-request'; interface EditProductProps { data: Product; + queryKey: QueryKey; } -const EditProduct: React.FC = ({ data }) => { +const EditProduct: React.FC = ({ data, queryKey }) => { const client = useQueryClient(); const formRef = React.useRef(null); const toast = useToast(); const { isOpen, onOpen, onClose } = useDisclosure(); - const mutation = useApiMutation(UPDATE_PRODUCT); - const updateProduct = React.useCallback(async () => { + const deleteDisclosure = useDisclosure(); + const mutate = useApiMutation(mutation); + const updateProduct = async () => { try { const formData = new FormData(formRef.current); const payload: ProductUpdateInput = { @@ -60,8 +60,8 @@ const EditProduct: React.FC = ({ data }) => { } } - await mutation.mutateAsync({ id: data.id, data: payload }); - client.invalidateQueries(['products']); + await mutate.mutateAsync({ id: data.id, data: payload }); + await client.invalidateQueries(queryKey); onClose(); toast({ title: `${data.name} updated`, @@ -69,46 +69,54 @@ const EditProduct: React.FC = ({ data }) => { isClosable: true, }); } catch (err) { - console.error(err.message); toast({ title: 'Update product failed', status: 'error', + description: err, isClosable: true, }); } - }, [client, data, mutation, onClose, toast]); - const onUpdate = React.useCallback(() => { - if (formRef.current.checkValidity()) { - updateProduct(); - } - }, [updateProduct]); - const onSubmit = React.useCallback( - (event) => { - event.preventDefault(); - updateProduct; - }, - [updateProduct] - ); + }; + const handleSaveClick = () => { + formRef.current?.requestSubmit(); + }; + const handleSubmit = (event: React.FormEvent) => { + event.preventDefault(); + updateProduct(); + }; + const dataTestIdName = kebabCase(data.name); return ( <> - + + + Edit Product + + + Delete Product... + + + {`Edit ${data.name}`} -
+ Product Name + Must be unique = ({ data }) => { variant="bc-input" data-testid="prd-edit-name-input" /> - Must be unique @@ -124,16 +131,19 @@ const EditProduct: React.FC = ({ data }) => { - - - - - - - - - - ) -} + + + + + + ); +}; export default DeleteEnvironment; From 6c4b836aba1b51aecc6b99c4abadb9efb21425f5 Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Mon, 24 Oct 2022 14:16:41 -0700 Subject: [PATCH 45/48] Uncommented migrate user scenarios --- .../01-migrate-user-access.spec.ts | 150 +++++++++--------- 1 file changed, 75 insertions(+), 75 deletions(-) diff --git a/e2e/cypress/tests/05-migrate-user/01-migrate-user-access.spec.ts b/e2e/cypress/tests/05-migrate-user/01-migrate-user-access.spec.ts index 09b658c49..d8b566044 100644 --- a/e2e/cypress/tests/05-migrate-user/01-migrate-user-access.spec.ts +++ b/e2e/cypress/tests/05-migrate-user/01-migrate-user-access.spec.ts @@ -3,81 +3,81 @@ import LoginPage from '../../pageObjects/login' import NamespaceAccessPage from '../../pageObjects/namespaceAccess' const { _, $ } = Cypress -// describe('Assign Access to existing user Spec', () => { -// const login = new LoginPage() -// const home = new HomePage() -// const na = new NamespaceAccessPage() - -// before(() => { -// cy.visit('/') -// cy.deleteAllCookies() -// cy.reload() -// }) - -// beforeEach(() => { -// cy.preserveCookies() -// cy.fixture('apiowner').as('apiowner') -// // cy.visit(login.path) -// }) - -// it('authenticates Janis (api owner)', () => { -// cy.get('@apiowner').then(({ user, namespace }: any) => { -// cy.login(user.credentials.username, user.credentials.password) -// cy.log('Logged in!') -// home.useNamespace(namespace) -// }) -// }) - -// it('Navigate to Namespace Access Page', () => { -// cy.visit(na.path) -// cy.wait(2000) -// }) - -// it('Grant namespace access to Old User', () => { -// cy.get('@apiowner').then(({ grantPermission }: any) => { -// na.clickGrantUserAccessButton() -// na.grantPermission(grantPermission.OldUser) -// }) -// }) - -// after(() => { -// cy.logout() -// cy.clearLocalStorage({ log: true }) -// cy.deleteAllCookies() -// }) -// }) - -// describe('Authernticate with old user to initiate migration', () => { -// const login = new LoginPage() -// const home = new HomePage() -// const na = new NamespaceAccessPage() - -// before(() => { -// cy.visit('/') -// cy.deleteAllCookies() -// cy.reload() -// }) - -// beforeEach(() => { -// cy.preserveCookies() -// cy.fixture('usermigration').as('usermigration') -// // cy.visit(login.path) -// }) - -// it('authenticates with old user', () => { -// cy.get('@usermigration').then(({ oldUser, namespace }: any) => { -// cy.login(oldUser.credentials.username, oldUser.credentials.password) -// cy.log('Logged in!') -// home.useNamespace(namespace) -// }) -// }) - -// after(() => { -// cy.logout() -// cy.clearLocalStorage({ log: true }) -// cy.deleteAllCookies() -// }) -// }) +describe('Assign Access to existing user Spec', () => { + const login = new LoginPage() + const home = new HomePage() + const na = new NamespaceAccessPage() + + before(() => { + cy.visit('/') + cy.deleteAllCookies() + cy.reload() + }) + + beforeEach(() => { + cy.preserveCookies() + cy.fixture('apiowner').as('apiowner') + // cy.visit(login.path) + }) + + it('authenticates Janis (api owner)', () => { + cy.get('@apiowner').then(({ user, namespace }: any) => { + cy.login(user.credentials.username, user.credentials.password) + cy.log('Logged in!') + home.useNamespace(namespace) + }) + }) + + it('Navigate to Namespace Access Page', () => { + cy.visit(na.path) + cy.wait(2000) + }) + + it('Grant namespace access to Old User', () => { + cy.get('@apiowner').then(({ grantPermission }: any) => { + na.clickGrantUserAccessButton() + na.grantPermission(grantPermission.OldUser) + }) + }) + + after(() => { + cy.logout() + cy.clearLocalStorage({ log: true }) + cy.deleteAllCookies() + }) +}) + +describe('Authernticate with old user to initiate migration', () => { + const login = new LoginPage() + const home = new HomePage() + const na = new NamespaceAccessPage() + + before(() => { + cy.visit('/') + cy.deleteAllCookies() + cy.reload() + }) + + beforeEach(() => { + cy.preserveCookies() + cy.fixture('usermigration').as('usermigration') + // cy.visit(login.path) + }) + + it('authenticates with old user', () => { + cy.get('@usermigration').then(({ oldUser, namespace }: any) => { + cy.login(oldUser.credentials.username, oldUser.credentials.password) + cy.log('Logged in!') + home.useNamespace(namespace) + }) + }) + + after(() => { + cy.logout() + cy.clearLocalStorage({ log: true }) + cy.deleteAllCookies() + }) +}) describe('Verify that permission of old user is migrated to new user', () => { const login = new LoginPage() From df6927eb592d7e96eed0948573fe99354b38e638 Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Mon, 24 Oct 2022 15:27:00 -0700 Subject: [PATCH 46/48] Reset 3 files in src to it's previous state --- src/auth/auth-oauth2-proxy.js | 90 ++++++--------------- src/lists/extensions/UMAPermissionTicket.ts | 42 +++++++--- src/services/keycloak/user-service.ts | 55 ++++++++----- 3 files changed, 91 insertions(+), 96 deletions(-) diff --git a/src/auth/auth-oauth2-proxy.js b/src/auth/auth-oauth2-proxy.js index de2ec79f5..f51517a26 100644 --- a/src/auth/auth-oauth2-proxy.js +++ b/src/auth/auth-oauth2-proxy.js @@ -12,7 +12,6 @@ const { maintenance } = require('../services/maintenance'); const jwt = require('express-jwt'); const jwksRsa = require('jwks-rsa'); -const jwtDecoder = require('jwt-decode'); const { deriveRoleFromIdP, scopesToRoles } = require('./scope-role-utils'); const proxy = process.env.EXTERNAL_URL; @@ -25,6 +24,12 @@ const { Logger } = require('../logger'); const { UMA2TokenService } = require('../services/uma2'); const { getUma2FromIssuer, Uma2WellKnown } = require('../services/keycloak'); +const { + clearNamespace, + assignNamespace, + switchTo, +} = require('../services/keystone'); + const { MigrateAuthzUser, MigratePortalUser } = require('../services/workflow'); const toJson = (val) => (val ? JSON.parse(val) : null); @@ -194,11 +199,14 @@ class Oauth2ProxyAuthStrategy { jti, req.user.jti === jti ? 'SAME TOKEN' : 'REFRESHED TOKEN!' ); - await this.assign_namespace(req.user.jti, jti, identityProvider, { - rsname: null, - scopes: [], - }); - res.json({ switch: true }); + const switched = await clearNamespace( + this.keystone, + req.user.jti, + jti, + identityProvider + ); + + res.json({ switch: switched }); } catch (err) { logger.error('Error clearing namespace %s', err); res.status(400).json({ switch: false, error: 'ns_cleared_fail' }); @@ -212,40 +220,23 @@ class Oauth2ProxyAuthStrategy { async (req, res, next) => { // Switch namespace // - Get a Requestor Party Token for the particular Resource - const subjectToken = req.headers['x-forwarded-access-token']; - const uma2 = await getUma2FromIssuer(process.env.OIDC_ISSUER); - const accessToken = await new UMA2TokenService(uma2.token_endpoint) - .getRequestingPartyToken( - process.env.GWA_RES_SVR_CLIENT_ID, - process.env.GWA_RES_SVR_CLIENT_SECRET, - subjectToken, - req.params['ns'] - ) - .catch((err) => { - logger.error('Error getting new RPT %s', err); - res.status(400).json({ switch: false, error: 'rpt_fail' }); - return; - }); try { - const rpt = jwtDecoder(accessToken); const jti = req['oauth_user']['jti']; // JWT ID - Unique Identifier for the token const identityProvider = req['oauth_user']['identity_provider']; // Identity Provider included in token - // The oauth2_proxy is handling the refresh token; so there can be a new jti - logger.info( - '[ns-switch] %s -> %s : %s', - req.user.jti, - jti, - req.user.jti === jti ? 'SAME TOKEN' : 'REFRESHED TOKEN!' - ); - await this.assign_namespace( + + const subjectToken = req.headers['x-forwarded-access-token']; + + const result = await switchTo( + this.keystone, + req.params['ns'], + subjectToken, req.user.jti, jti, - identityProvider, - rpt['authorization']['permissions'][0] + identityProvider ); - res.json({ switch: true }); + res.status(200).json({ switch: result }); } catch (err) { - logger.error('Error evaluating new access token %s', err); + logger.error(err); res.status(400).json({ switch: false, error: 'ns_assign_fail' }); } } @@ -253,37 +244,6 @@ class Oauth2ProxyAuthStrategy { return app; } - async assign_namespace(jti, newJti, identityProvider, umaAuthDetails) { - const namespace = umaAuthDetails['rsname']; - const scopes = umaAuthDetails['scopes']; - const _roles = scopesToRoles(identityProvider, scopes); - - const roles = JSON.stringify(_roles); - - // should be TemporaryIdentity - const idList = this.keystone.getListByKey(this.listKey); - let results = await idList.adapter.find({ jti: jti }); - let tempId = results[0]['id']; - - const { errors } = await this.keystone.executeGraphQL({ - context: this.keystone.createContext({ skipAccessControl: true }), - query: `mutation ($tempId: ID!, $newJti: String, $namespace: String, $roles: String, $scopes: String) { - updateTemporaryIdentity(id: $tempId, data: {jti: $newJti, namespace: $namespace, roles: $roles, scopes: $scopes }) { - id - } }`, - variables: { - tempId, - newJti, - namespace, - roles, - scopes: JSON.stringify(scopes), - }, - }); - if (errors) { - logger.error('assign_namespace - NO! Something went wrong %j', errors); - } - } - async register_user(req, res, next) { const _users = this.keystone.getListByKey('User'); const users = this.keystone.getListByKey(this.listKey); @@ -600,4 +560,4 @@ Oauth2ProxyAuthStrategy.authType = 'password'; module.exports = { Oauth2ProxyAuthStrategy, -}; +}; \ No newline at end of file diff --git a/src/lists/extensions/UMAPermissionTicket.ts b/src/lists/extensions/UMAPermissionTicket.ts index 70adb4a99..3197125cf 100644 --- a/src/lists/extensions/UMAPermissionTicket.ts +++ b/src/lists/extensions/UMAPermissionTicket.ts @@ -9,7 +9,7 @@ import { getResourceSets, getEnvironmentContext } from './Common'; import { strict as assert } from 'assert'; import { Logger } from '../../logger'; import { StructuredActivityService } from '../../services/workflow'; -import { lookupUsersByUsernames } from '../../services/keystone'; +import { lookupUsersByUsernames, switchTo } from '../../services/keystone'; const logger = Logger('lists.umaticket'); @@ -143,7 +143,7 @@ module.exports = { info: any, { query, access }: any ) => { - const scopes = args.data.scopes; + const { email, scopes, resourceId } = args.data; const envCtx = await getEnvironmentContext( context, args.prodEnvId, @@ -152,8 +152,7 @@ module.exports = { const resourceIds = await getResourceSets(envCtx); assert.strictEqual( - resourceIds.filter((rid) => rid === args.data.resourceId) - .length, + resourceIds.filter((rid) => rid === resourceId).length, 1, 'Invalid Resource' ); @@ -163,13 +162,14 @@ module.exports = { envCtx.issuerEnvConfig.clientId, envCtx.issuerEnvConfig.clientSecret ); - const users = await userApi.lookupUsersByEmail( + const user = await userApi.lookupUserByEmail( args.data.email, - false + false, + ['idir'] ); - assert.strictEqual(users.length, 1, 'Unable to match email'); - const user = users.pop(); - const displayName = user.attributes.display_name || user.email; + const displayName = + userApi.getOneAttributeValue(user, 'display_name') || + user.email; const result = []; const granted = @@ -180,7 +180,7 @@ module.exports = { ); for (const scope of scopes) { const permission = await permissionApi.createOrUpdatePermission( - args.data.resourceId, + resourceId, user.id, granted, scope @@ -200,6 +200,28 @@ module.exports = { scopes ); + // refresh the permissions for this user in TemporaryIdentity + try { + logger.info( + 'User matching %s with %j', + user.id, + context.req.user + ); + if (user.id === context.req.user.sub) { + const subjectToken = + context.req.headers['x-forwarded-access-token']; + + await switchTo( + context, + context.authedItem['namespace'], + subjectToken, + context.req.user.jti, + context.req.user.sub, + context.req.user.provider + ); + } + } catch (err) {} + return result; }, access: EnforcementPoint, diff --git a/src/services/keycloak/user-service.ts b/src/services/keycloak/user-service.ts index ade8e5cf4..603103d6f 100644 --- a/src/services/keycloak/user-service.ts +++ b/src/services/keycloak/user-service.ts @@ -22,16 +22,16 @@ export class KeycloakUserService { public useAdminClient(client: KcAdminClient) { this.kcAdminClient = client; + return this; } - // public async findOne(id: string) { - // logger.debug('[findOne] %s', id); - // const user = await this.kcAdminClient.users.findOne({ - // id, - // }); - // logger.debug('[findOne] : %j', user); - // return user; - // } + public getOneAttributeValue(user: UserRepresentation, name: string): string { + return user.attributes && + name in user.attributes && + user.attributes[name].length > 0 + ? user.attributes[name][0] + : undefined; + } public async lookupUserByUsername(username: string) { logger.debug('[lookupUserByUsername] %s', username); @@ -58,23 +58,36 @@ export class KeycloakUserService { verified: boolean, identityProviders: string[] ): Promise { - const user = (await this.lookupUsersByEmail(email, verified)) - .filter(async (user) => { - const userWithAttributes = await this.lookupUserById(user.id); - return identityProviders.includes( - userWithAttributes.attributes.identity_provider - ); - }) + return (await this.lookupUserByEmail(email, verified, identityProviders)) + .id; + } + + public async lookupUserByEmail( + email: string, + verified: boolean, + identityProviders: string[] + ): Promise { + const matchingUsers = await this.lookupActiveUsersByEmail(email, verified); + const user = matchingUsers + .filter((user) => + identityProviders.includes( + this.getOneAttributeValue(user, 'identity_provider') + ) + ) .pop(); - assert.strictEqual(Boolean(user), true, `No suitable match for ${email}`); - return user.id; + assert.strictEqual( + Boolean(user), + true, + `No suitable match for ${identityProviders.join(',')} : ${email}` + ); + return user; } - public async lookupUsersByEmail( + public async lookupActiveUsersByEmail( email: string, verified: boolean ): Promise { - logger.debug('[lookupUserByEmail] %s', email); + logger.debug('[lookupActiveUsersByEmail] %s', email); const users = ( await this.kcAdminClient.users.find({ exact: true, @@ -85,7 +98,7 @@ export class KeycloakUserService { .filter( (user: UserRepresentation) => verified == false || user.emailVerified ); - logger.debug('[lookupUserByEmail] : %j', users); + logger.debug('[lookupActiveUsersByEmail] : %j', users); assert.strictEqual( users.length > 0, true, @@ -162,4 +175,4 @@ export class KeycloakUserService { } ); } -} +} \ No newline at end of file From eae729dac07c1670f63d3736bf068a71b72e4b83 Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Mon, 24 Oct 2022 22:32:49 -0700 Subject: [PATCH 47/48] Update for clear product scenarios --- e2e/cypress/pageObjects/products.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/e2e/cypress/pageObjects/products.ts b/e2e/cypress/pageObjects/products.ts index 8442ba3ff..79edb89d7 100644 --- a/e2e/cypress/pageObjects/products.ts +++ b/e2e/cypress/pageObjects/products.ts @@ -156,14 +156,16 @@ class Products { deleteProductEnvironment(productName: string, envName: string) { const pname: string = productName.toLowerCase().replaceAll(' ', '-') let env = this.getTestIdEnvName(envName); - cy.get(`[data-testid=${pname}-${env}-edit-btn]`).siblings(this.deleteProductEnvBtn).click() + cy.get(`[data-testid=${pname}-${env}-more-options-btn]`).click() + cy.get(`[data-testid=${pname}-${env}-delete-btn]`).click() cy.get(this.deleteConfirmationBtn).click() } deleteProduct(productName: string) { // this.editProduct(productName) - cy.get(`[data-testid=${productName}-more-options-btn]`).first().click() - cy.get(this.deleteProductBtn).click() + const pname: string = productName.toLowerCase().replaceAll(' ', '-') + cy.get(`[data-testid=${pname}-edit-btn]`).first().click({force: true}) + cy.get(`[data-testid=${pname}-delete-btn]`).first().click({force: true}) cy.get(this.deleteProductConfirmationBtn).click() } From c193ea9e6056dd1b755e07709ed54ff814b2034d Mon Sep 17 00:00:00 2001 From: Niraj Patel Date: Tue, 25 Oct 2022 10:31:52 -0700 Subject: [PATCH 48/48] Removed debugger statements --- e2e/cypress/pageObjects/activity.ts | 2 -- e2e/cypress/pageObjects/apiDirectory.ts | 2 -- e2e/cypress/pageObjects/applications.ts | 1 - e2e/cypress/pageObjects/consumers.ts | 6 ------ e2e/cypress/pageObjects/namespaceAccess.ts | 1 - e2e/cypress/pageObjects/products.ts | 2 -- e2e/cypress/support/auth-commands.ts | 4 ---- .../04-review-request-without-collecting-credentials.ts | 1 - .../03-client-cred-create-api-prod-auth-pro.ts | 3 --- e2e/cypress/tests/06-refresh-credential/01-api-key.ts | 1 - e2e/cypress/tests/08-activity-feed/01-activity-feed.ts | 4 ---- .../tests/08-activity-feed/02-activity-feed-failure.ts | 2 -- e2e/cypress/tests/12-aps-api/03-documentation.ts | 1 - e2e/cypress/tests/12-aps-api/06-api-directory.ts | 3 --- 14 files changed, 33 deletions(-) diff --git a/e2e/cypress/pageObjects/activity.ts b/e2e/cypress/pageObjects/activity.ts index 8b4c6a4d3..2d1f17774 100644 --- a/e2e/cypress/pageObjects/activity.ts +++ b/e2e/cypress/pageObjects/activity.ts @@ -11,7 +11,6 @@ class ActivityPage { this.setFilterCondition(filterCondition, value) var filteredResponse: any let result: any - debugger if (value == "") { filteredResponse = response } @@ -28,7 +27,6 @@ class ActivityPage { cy.wrap($e1).find('p').invoke('text').then((text) => { activityText = text filteredResponse.forEach((record: any) => { - debugger responseText = record.message responseText = responseText.replaceAll("{", "${filteredResponse[index].params.") const regexp = /\${([^{]+)}/g; diff --git a/e2e/cypress/pageObjects/apiDirectory.ts b/e2e/cypress/pageObjects/apiDirectory.ts index 42e0abadc..90e6f2122 100644 --- a/e2e/cypress/pageObjects/apiDirectory.ts +++ b/e2e/cypress/pageObjects/apiDirectory.ts @@ -45,10 +45,8 @@ class ApiDirectoryPage { isProductDisplay(productName: string): Boolean { var flag = false; cy.get('body', {timeout: 6000}).then(($body) => { - debugger const pname: string = productName.toLowerCase().replaceAll(' ', '-') var ele : string = `[data-testid=api-${pname}]` - debugger cy.log('Body -> '+ $body) if ($body.find(ele).length > 0) { flag = true diff --git a/e2e/cypress/pageObjects/applications.ts b/e2e/cypress/pageObjects/applications.ts index 4b9bf63a0..29558e57f 100644 --- a/e2e/cypress/pageObjects/applications.ts +++ b/e2e/cypress/pageObjects/applications.ts @@ -27,7 +27,6 @@ class ApplicationPage { checkDeletedApplication(appName: any) { cy.get(this.applicationTbl).find('tr').each(($e1, index, $list) => { let applicationName = $e1.find('td:nth-child(1)').text() - debugger if (applicationName.toLowerCase() === appName.toLowerCase() ) { assert.fail("Application is not deleted") } diff --git a/e2e/cypress/pageObjects/consumers.ts b/e2e/cypress/pageObjects/consumers.ts index 8a53799e8..c8dd210d7 100644 --- a/e2e/cypress/pageObjects/consumers.ts +++ b/e2e/cypress/pageObjects/consumers.ts @@ -86,7 +86,6 @@ export default class ConsumersPage { // cy.wait(500) cy.get(this.consumerDialogSaveBtn).click() cy.get(this.consumerDialogSaveBtn, { timeout: 2000 }).should('not.exist') - debugger cy.wait(3000) } @@ -180,7 +179,6 @@ export default class ConsumersPage { }); cy.get(this.filterType).select(type).invoke('val') cy.get(this.filterValue).select(value).invoke('val') - debugger if (type == 'Labels') { cy.get(this.labelValueInput).type(labelValue) } @@ -205,7 +203,6 @@ export default class ConsumersPage { expect($e1.next().text().trim()).to.eq('Dev') } if ($e1.text() === 'Application') { - debugger expect($e1.next().text().trim()).to.eq(applicationDetails.name) } if ($e1.text() === 'Instructions from the API Provider') { @@ -219,7 +216,6 @@ export default class ConsumersPage { addGroupLabels(groupLabels: any) { Object.entries(groupLabels.labels).forEach((entry, index) => { - debugger cy.get(this.labelsGroupSelection).select('[+] Add New Label Group...').invoke('val') cy.get(this.labelName).type(entry[0]) cy.contains('Add').click() @@ -287,9 +283,7 @@ export default class ConsumersPage { addManageLabels() { cy.wait(2000) - debugger cy.get(this.manageLabelsBtn).parents('ul').find('li').then(($ele) => { - debugger const index = $ele.length - 1 this.openManageLabelsWindow() cy.get(this.labelsGroupSelection).select('[+] Add New Label Group...').invoke('val') diff --git a/e2e/cypress/pageObjects/namespaceAccess.ts b/e2e/cypress/pageObjects/namespaceAccess.ts index e6550ad76..14a3146d5 100644 --- a/e2e/cypress/pageObjects/namespaceAccess.ts +++ b/e2e/cypress/pageObjects/namespaceAccess.ts @@ -5,7 +5,6 @@ class NamespaceAccessPage { grantPermission(accessRqst: any) { cy.get(this.userNameInput,{ timeout: 2000 }).should('be.visible'); - debugger cy.get(this.userNameInput).type(accessRqst.email); let accessRole: Array = accessRqst.accessRole accessRole.forEach(function (accessName) { diff --git a/e2e/cypress/pageObjects/products.ts b/e2e/cypress/pageObjects/products.ts index 79edb89d7..cbbe6766a 100644 --- a/e2e/cypress/pageObjects/products.ts +++ b/e2e/cypress/pageObjects/products.ts @@ -31,7 +31,6 @@ class Products { config: string | undefined getTestIdEnvName(env: string): string { - debugger switch (env) { case "Development": return "dev" @@ -72,7 +71,6 @@ class Products { editProductEnvironment(productName: string, envName: string) { const pname: string = productName.toLowerCase().replaceAll(' ', '-') - debugger let env = this.getTestIdEnvName(envName); cy.get(`[data-testid=${pname}-${env}-edit-btn]`).click() } diff --git a/e2e/cypress/support/auth-commands.ts b/e2e/cypress/support/auth-commands.ts index 27af9347f..319615f3c 100644 --- a/e2e/cypress/support/auth-commands.ts +++ b/e2e/cypress/support/auth-commands.ts @@ -118,7 +118,6 @@ Cypress.Commands.add('getUserSessionTokenValue', (namespace: string) => { }) Cypress.Commands.add('getUserSessionResponse', () => { - debugger cy.getUserSession().then(() => { cy.get('@login').then(function (xhr: any) { return xhr @@ -264,7 +263,6 @@ Cypress.Commands.add('makeKongRequest', (serviceName: string, methodType: string cy.fixture('state/regen').then((creds: any) => { cy.wait(2000) let token = key || creds.apikey - debugger const service = serviceName cy.log("Token->" + token) return cy.request({ @@ -365,7 +363,6 @@ Cypress.Commands.add('verifyToastMessage', (msg: string) => { }) Cypress.Commands.add('compareJSONObjects', (actualResponse: any, expectedResponse: any, indexFlag = false) => { - debugger let response = actualResponse if (indexFlag) { const index = actualResponse.findIndex((x: { name: string }) => x.name === expectedResponse.name); @@ -387,7 +384,6 @@ Cypress.Commands.add('compareJSONObjects', (actualResponse: any, expectedRespons response[p] = response[p]['name'] } if ((response[p] !== expectedResponse[p]) && !(['clientSecret', 'appId', 'isInCatalog', 'isDraft', 'consumer', 'id'].includes(p))) { - debugger cy.log("Different Value ->" + expectedResponse[p]) assert.fail("JSON value mismatch for " + p) } diff --git a/e2e/cypress/tests/01-api-key/04-review-request-without-collecting-credentials.ts b/e2e/cypress/tests/01-api-key/04-review-request-without-collecting-credentials.ts index 0a5a71cd3..23c60a7da 100644 --- a/e2e/cypress/tests/01-api-key/04-review-request-without-collecting-credentials.ts +++ b/e2e/cypress/tests/01-api-key/04-review-request-without-collecting-credentials.ts @@ -36,7 +36,6 @@ describe('Approve Pending Request without collecting credentials Spec', () => { }) it('verify that pending request is not displayed', () => { - debugger const flag = consumers.reviewThePendingRequest() assert.isFalse(flag, 'Review request popup is displayed') }) diff --git a/e2e/cypress/tests/04-client-credential-flow/03-client-cred-create-api-prod-auth-pro.ts b/e2e/cypress/tests/04-client-credential-flow/03-client-cred-create-api-prod-auth-pro.ts index d99665b28..1b16fa29c 100644 --- a/e2e/cypress/tests/04-client-credential-flow/03-client-cred-create-api-prod-auth-pro.ts +++ b/e2e/cypress/tests/04-client-credential-flow/03-client-cred-create-api-prod-auth-pro.ts @@ -93,15 +93,12 @@ describe('Create API, Product, and Authorization Profiles; Apply Auth Profiles t it('Adds environment with Client ID/Secret authenticator to product', () => { cy.visit(pd.path) cy.get('@apiowner').then(({ clientCredentials }: any) => { - debugger let product = clientCredentials.clientIdSecret.product let authProfile = clientCredentials.clientIdSecret.authProfile - debugger pd.editProductEnvironment(product.name, product.environment.name) product.environment.config.authIssuer = authProfile.name product.environment.config.authIssuerEnv = authProfile.environmentConfig.environment pd.editProductEnvironmentConfig(product.environment.config) - debugger pd.generateKongPluginConfig(product.name, product.environment.name,'cc-service.yml') }) // pd.generateKongPluginConfig('cc-service.yml') diff --git a/e2e/cypress/tests/06-refresh-credential/01-api-key.ts b/e2e/cypress/tests/06-refresh-credential/01-api-key.ts index 1f5fb31c7..95364a290 100644 --- a/e2e/cypress/tests/06-refresh-credential/01-api-key.ts +++ b/e2e/cypress/tests/06-refresh-credential/01-api-key.ts @@ -85,7 +85,6 @@ describe('Regenerate Credential for API Key', () => { it('Verify that API is not accessible with the old API Key', () => { cy.get('@apiowner').then(({ product }: any) => { cy.makeKongRequest(product.environment.config.serviceName, 'GET', existingAPIKey).then((response) => { - debugger expect(response.status).to.be.equal(500) }) }) diff --git a/e2e/cypress/tests/08-activity-feed/01-activity-feed.ts b/e2e/cypress/tests/08-activity-feed/01-activity-feed.ts index 127078901..83c376ebb 100644 --- a/e2e/cypress/tests/08-activity-feed/01-activity-feed.ts +++ b/e2e/cypress/tests/08-activity-feed/01-activity-feed.ts @@ -51,10 +51,8 @@ describe('API Tests for Activity report', () => { }) it('Get the resource and verify the success code in the response', () => { - debugger cy.get('@api').then(({ namespaces }: any) => { cy.makeAPIRequest(namespaces.endPoint + "/" + nameSpace + "/activity?first=100", 'GET').then((res) => { - debugger expect(res.status).to.be.equal(200) response = res.body }) @@ -80,10 +78,8 @@ describe('Generate activity response from APS V2 API', () => { }) it('Get the resource and verify the success code in the response', () => { - debugger cy.get('@api').then(({ namespaces }: any) => { cy.makeAPIRequest(namespaces.endPoint + "/" + nameSpace + "/activity?first=100", 'GET').then((res) => { - debugger expect(res.status).to.be.equal(200) response = res.body }) diff --git a/e2e/cypress/tests/08-activity-feed/02-activity-feed-failure.ts b/e2e/cypress/tests/08-activity-feed/02-activity-feed-failure.ts index 745f8f08e..f0369c17c 100644 --- a/e2e/cypress/tests/08-activity-feed/02-activity-feed-failure.ts +++ b/e2e/cypress/tests/08-activity-feed/02-activity-feed-failure.ts @@ -100,10 +100,8 @@ describe('Create API, Product, and Authorization Profiles; Apply Auth Profiles t }) it('Get the resource and verify the success code in the response', () => { - debugger cy.get('@api').then(({ namespaces }: any) => { cy.makeAPIRequest(namespaces.endPoint + "/" + nameSpace + "/activity?first=100", 'GET').then((res) => { - debugger expect(res.status).to.be.equal(200) response = res.body }) diff --git a/e2e/cypress/tests/12-aps-api/03-documentation.ts b/e2e/cypress/tests/12-aps-api/03-documentation.ts index 429fb7b0c..28bee039f 100644 --- a/e2e/cypress/tests/12-aps-api/03-documentation.ts +++ b/e2e/cypress/tests/12-aps-api/03-documentation.ts @@ -119,7 +119,6 @@ describe('API Tests for Deleting documentation', () => { }) it('Delete the documentation', () => { - debugger cy.get('@api').then(({ documentation }: any) => { cy.makeAPIRequest(documentation.endPoint + '/' + slugValue, 'DELETE').then((response) => { expect(response.status).to.be.equal(200) diff --git a/e2e/cypress/tests/12-aps-api/06-api-directory.ts b/e2e/cypress/tests/12-aps-api/06-api-directory.ts index 5cba52ca6..34cac8593 100644 --- a/e2e/cypress/tests/12-aps-api/06-api-directory.ts +++ b/e2e/cypress/tests/12-aps-api/06-api-directory.ts @@ -138,9 +138,7 @@ describe('API Tests for Updating dataset', () => { it('Get the directory details (/directory) and verify the success code in the response', () => { cy.get('@api').then(({ apiDirectory }: any) => { - debugger cy.makeAPIRequest(apiDirectory.directoryEndPoint, 'GET').then((res) => { - debugger expect(res.status).to.be.equal(200) response = res.body directoryID = res.body[0].id @@ -151,7 +149,6 @@ describe('API Tests for Updating dataset', () => { it('Verify the expected directory details are display in the response', () => { cy.get('@api').then(({ apiDirectory }: any) => { - debugger // cy.compareJSONObjects(response, apiDirectory.directory, true) }) })