This article will cover the basics of securing an NestJS API with keycloak, I’ll also cover how you can integrate the frontend(React) with this ecosystem and show you some other tricks as well.
Optimizing KeyCloak Setup for Effective Nest.js Integration
Development → For local development, we are going to use docker for running keycloak and connecting it to a postgres container as well.
volumes:
postgres_data:
driver: local
services:
postgres_keycloak: # Service name
image: postgres:11
volumes:
- postgres_data:/var/lib/postgresql/data
environment:
POSTGRES_DB: keycloak
POSTGRES_USER: keycloak
POSTGRES_PASSWORD: password
ports:
- "127.0.0.1:5433:5432"
keycloak:
image: quay.io/keycloak/keycloak:18.0.2
environment:
DB_VENDOR: POSTGRES
DB_ADDR: postgres_keycloak # <<< This is the address, change it to your external db ip/domain
DB_DATABASE: keycloak
DB_USER: keycloak
DB_SCHEMA: public
DB_PASSWORD: password
KEYCLOAK_ADMIN: admin
KEYCLOAK_ADMIN_PASSWORD: password
JAVA_OPTS: -Dkeycloak.profile=preview
KEYCLOAK_LOGLEVEL: DEBUG
ROOT_LOGLEVEL: DEBUG
command:
- start-dev
ports:
- 8080:8080
- 8443:8443
depends_on:
- postgres_keycloak
- We are opening ports 8080, 8443 for docker and also making sure that you can access the postgres instance through 5433 port.
- As you can see this is using the latest version of keycloak so you might find some differences when running up a jboss based image which is now deprecated.
- JAVA_OPTS: -Dkeycloak.profile=preview flag passed inside the docker-compose file is used for starting keycloak with preview features on. This will cause to enable authorization, new admin UI and much more features.
- Make an educated decision if you want to use preview features in production as they might lack support.
Running this -
docker-compose -f docker-compose.yml up -d # Up
docker-compose -f docker-compose.yml down # Down
Common Error when starting keycloak
Keycloak: User with username 'admin' already added.
Resolution
1. stop all containers
2. comment out the two relevant lines
version: "3"
services:
keycloak:
image: quay.io/keycloak/keycloak:latest
environment:
# KEYCLOAK_USER: admin
# KEYCLOAK_PASSWORD: pass
...
3. start all containers
4. wait until keycloak container has successfully starteds
5. stop all containers, again
6. comment back in the two lines from above
version: "3"
services:
keycloak:
image: quay.io/keycloak/keycloak:latest
environment:
KEYCLOAK_USER: admin
KEYCLOAK_PASSWORD: pass
...
7. start all containers
This time (and subsequent times) it worked. Keycloak was running and the admin user was registered and working as expected.
Keycloak Configuration
1. Set up Keycloak server
There are multiple ways to setup Keycloak instance. Follow the instructions in the link . Once the setup completed you should login to the Keycloak server using provided admin account credentials.
For reference, this was the docker-compose we used

2. Create a Realm
A realm secures and manages security meta data for a set of users, applications, and registered OAuth clients. Users can be created confined to a specific realm within the Administration console. Roles can be defined at the realm level. You can also set up user role mappings to assign these permissions to specific users. Create a realm by clicking the add realm button on the Select realm drop down. Give a name with your preference and click the Create button.

Add realm
After that you will be redirected to the realm setting page.

Note: You can change access token and refresh token lifespan by moving to token tab.

Make sure Demo-Realm is selected for the below configurations. Avoid using the master realm. You don’t have to create the realm every time. It’s a one time process.
3. Create Clients
Clients are entities that can request Keycloak to authenticate a user. Most often, clients are applications and services that want to use Keycloak to secure themselves and provide a single sign-on solution. Clients can also be entities that just want to request identity information or an access token so that they can securely invoke other services on the network that are secured by Keycloak.
Clients tab allows you to manage your application clients.

Here we have to register out NestJs application as a Keycloak client in Keycoak server.
Client :nest-app

For the created client set theAccess Type as bearer-only

Access Types explained,
- Bearer-only— this is for services that rely solely on the bearer token included in the request and never initiate login on their own. It’s typically used for securing the back-end.
- Confidential— clients of this type need to provide a secret in order to initiate the login process. Mostly used in OAuth client credential flow.
- Public — since we have no real way of hiding the secret in a JS-based browser app, this is what we need to stick with.
- Note — You won’t see the same access types when running the preview version of the app, but you will see the flows when setting up clients. The standered flow should work for backend and frontend both but you can try playing around to confirm your best flow.
4. Create Roles
Roles identify a type or category of user. Admin, user, manager and employee are all typical roles that may exist in an organization. Applications often assign access and permissions to specific roles rather than individual users as dealing with users can be too fine grained and hard to manage. For example, the Admin Console has specific roles which give permission to users to access parts of the Admin Console UI and perform certain actions. There is a global namespace for roles and each client also has its own dedicated namespace where roles can be defined. Realm Roles: Realm-level roles are a global namespace to define your roles. You can see the list of built-in and created roles by clicking the Roles left menu item.Client Roles: Client roles are basically a namespace dedicated to a client. Each client gets its own namespace. Client roles are managed under the Roles tab under each individual client. You interact with this UI the same way you do for realm-level roles.
1. Create client roles admin and user for nest-app client

Client admin role

Client user role

2. Create realm roles app-admin and app-user for nest-app client

Realm admin role

Realm user role
Composite Roles: Any realm or client level role can be turned into a composite role. A composite role is a role that has one or more additional roles associated with it. When a composite role is mapped to the user, the user also gains the roles associated with that composite. This inheritance is recursive so any composite of composites also gets inherited.
3. After saving the realm roles enable Composite Roles and search for client react-web-app in Client Roles field. Select admin role and click Add selected . This configuration will assign nest-app, admin client role to the app-admin realm role. If you have multiple clients with multiple roles, pick and choose the required roles from each client to create realm roles based on the need.

4.Similarly add user client role to app-user realm role.

5. Create Users
Users are entities that are able to log into your system. They can have attributes associated with themselves like email, username, address and phone number. They can be assigned to groups and have specific roles assigned to them.
1. Create three users and assign them following realm roles,
- User1 with app-user
- User2 with app-admin
- User3 with app-user, app-admin
Go toUsers in left side menu to create users

2. Go to Credentials tab to set user credentials.

3. From the Role Mappings tab assign required roles to the Users.

2. Create realm roles app-admin and app-user for nest-app client

Like above assign app-user role to User2 and app-user, app-admin roles to User3
What we want with keycloak ?
- User trying to login to the front-end application (React.js).
- User will be redirected to the Keycloak server for authentication.
- If authentication successful, Authenticated user will be redirected to the application. Meantime user will get a JWT (JSON Web Token).
- Unauthenticated user will be redirected to back to the keycloak login page.
- With the valid JWT, front-end can access back-end rest api (Node.js/NestJS) by sending the JWT along with the service request.
- Back-end will communicate with the Keycloak server to validate the token.
- If the token is valid, back-end will server the request accordingly.
- If the token is invalid, back-end will respond with error code 401 (Unauthorized).
Securing Nest API with KeyCloak
Application Configuration (NestJs)
I am assuming that you have basic knowledge on how to create a NestJs application with basic setup. We are using nest-keycloak-connect adapter to communicate with Keycloak server.
Keycloak Client Adapers : Keycloak client adapters are libraries that make it very easy to secure applications and services with Keycloak. We call these ‘adapters’ rather than libraries as they provide a tight integration to the underlying platform and framework. This makes adapters easy to use and require less boilerplate code than what is typically required by a library.
Implementation
Add nest Keycloak library to our code base
npm install nest-keycloak-connect --save
Now we need to add Keycloak configuration to NestJs. Here we are adding configuration to the app.module.ts. But if you want you can create a separate module for Keycloak configuration and import that module in app.module.ts.
Here below is my actual setup
1.KeyCloak Service keycloak.service.ts
import { Injectable } from '@nestjs/common';
import { KeycloakConnectOptions, KeycloakConnectOptionsFactory, PolicyEnforcementMode, TokenValidation } from 'nest-keycloak-connect';
@Injectable()
export class KeycloakConfigService implements KeycloakConnectOptionsFactory {
createKeycloakConnectOptions(): KeycloakConnectOptions | Promise {
return {
authServerUrl: process.env.KEYCLOAK_AUTH_SERVER_URL,
realm: process.env.KEYCLOAK_REALM,
clientId: process.env.KEYCLOAK_CLIENT_ID,
secret: process.env.KEYCLOAK_CLIENT_SECRET,
policyEnforcement: PolicyEnforcementMode.PERMISSIVE,
tokenValidation: TokenValidation.ONLINE,
};
}
}
2. KeyCloak Module keycloak.module.ts
import { Global, Module } from '@nestjs/common';
import { KeycloakConfigService } from './keycloak.service';
@Global()
@Module({
providers: [KeycloakConfigService],
exports: [KeycloakConfigService], // 👈 export PrismaService for DI
})
export class KeyCloakConfigModule {}
3. Types types.d.ts
interface RealmAccess {
[name: string]: ?string[];
}
interface ResourceAccess {
[name: string]: ?{
[name: string]: ?string[];
}; // Any represent
}
export interface KeyCloakUserType {
exp: number;
iat: number;
auth_time: number;
jti: string;
iss: string;
aud: string[];
sub: string;
typ: string;
azp: string;
session_state: string;
acr: string;
realm_access: RealmAccess;
resource_access: ResourceAccess;
scope: string;
sid: string;
email_verified: boolean;
name?: string;
preferred_username?: string;
given_name?: string;
family_name?: string;
email: string;
// Extra Meta Data in Case needed
[otherOptions: string]: unknown;
}
4. Auth Guards (NestJS)
import { APP_GUARD } from '@nestjs/core';
import { AuthGuard, ResourceGuard, RoleGuard } from 'nest-keycloak-connect';
export const GlobalKeyCloakGuard = [
// This adds a global level authentication guard,
// you can also have it scoped
// if you like.
//
// Will return a 401 unauthorized when it is unable to
// verify the JWT token or Bearer header is missing.
{
provide: APP_GUARD,
useClass: AuthGuard,
},
// This adds a global level resource guard, which is permissive.
// Only controllers annotated with @Resource and
// methods with @Scopes
// are handled by this guard.
{
provide: APP_GUARD,
useClass: ResourceGuard,
},
// New in 1.1.0
// This adds a global level role guard, which is permissive.
// Used by `@Roles` decorator with the
// optional `@AllowAnyRole` decorator for allowing any
// specified role passed.
{
provide: APP_GUARD,
useClass: RoleGuard,
},
];
Here we are using nest-keycloak-connect’s AuthGuard, ResourceGuard, RoleGuard to protect our endpoints.
Now we add following endpoints to our controller and start the application using npm start.
@Controller()
export class UserController {
constructor(private readonly userService: UserService) {}@Get()
getpublic(): string {
return `${this.userService.getHello()} from public`;
}
@Get('/user')
getUser(): string {
return `${this.userService.getHello()} from user`;
}
@Get('/admin')
getAdmin(): string {
return `${this.userService.getHello()} from admin`;
}
@Get('/all')
getAll(): string {
return `${this.userService.getHello()} from all`;
}
}
You can try to access those endpoints from postman or a browser. You can see you are getting {“statusCode”:401,”message”:”Unauthorized”} from those endpoints.
To give access those endpoints we can use following annotations..
@Controller()
export class UserController {
constructor(private readonly userService: UserService) {}@Get('/public')
@Unprotected()
getpublic(): string {
return `${this.userService.getHello()} from public`;
}
@Get('/user')
@Roles({ roles: ['admin', 'other'] })
getUser(): string {
return `${this.userService.getHello()} from user`;
}
@Get('/admin')
@Roles({ roles: ['admin', 'realm:sysadmin'], mode: RoleMatchingMode.ALL })
getAdmin(): string {
return `${this.userService.getHello()} from admin`;
}
@Get('/all')
@Roles({ roles: [], mode: RoleMatchingMode.ALL })
getAll(): string {
return `${this.userService.getHello()} from all`;
}
}
This is the extracted JWT received from frontend application from User1 we created when configuring Keycloak. In the resource access section you can see this that user has user client role and in the realm access section user has app-user realm role. We can also use realm role in the @Roles annotation. e.g : @Roles(‘realm:app-user’). In above example we used client role.

Now we can access the /user endpoint with postman with JWT attached in the Authorization header.

But if we try to access /admin endpoint we are getting 403 because User1 doesn’t have admin role.

We can access access the /all endpoint since it’s allowed for any roles.

Volla, we have successfully secured our NestJs REST API using Keycloak.
Managing Keycloak Data
- As keycloak handles all the db related magic, we are sorted on that end but if you want to use that DB to fetch data. That’s another case.
- If it’s simple data fetching, we can use the nodejs-admin-keycloak for this task but if you are want to integrate more complex logic with keycloak-db then you will have to use a second database with your ORM for the task.
- We are using Prisma ORM and ended up with this schema file for the second db aka keycloak connection
Show schema.prisma
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("KEYCLOAK_DATABASE_URL")
}
model admin_event_entity {
id String @id(map: "constraint_admin_event_entity") @db.VarChar(36)
admin_event_time BigInt?
realm_id String? @db.VarChar(255)
operation_type String? @db.VarChar(255)
auth_realm_id String? @db.VarChar(255)
auth_client_id String? @db.VarChar(255)
auth_user_id String? @db.VarChar(255)
ip_address String? @db.VarChar(255)
resource_path String? @db.VarChar(2550)
representation String?
error String? @db.VarChar(255)
resource_type String? @db.VarChar(64)
}
model associated_policy {
policy_id String @db.VarChar(36)
associated_policy_id String @db.VarChar(36)
resource_server_policy_associated_policy_associated_policy_idToresource_server_policy resource_server_policy @relation("associated_policy_associated_policy_idToresource_server_policy", fields: [associated_policy_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_frsr5s213xcx4wnkog82ssrfy")
resource_server_policy_associated_policy_policy_idToresource_server_policy resource_server_policy @relation("associated_policy_policy_idToresource_server_policy", fields: [policy_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_frsrpas14xcx4wnkog82ssrfy")
@@id([policy_id, associated_policy_id], map: "constraint_farsrpap")
@@index([associated_policy_id], map: "idx_assoc_pol_assoc_pol_id")
}
model authentication_execution {
id String @id(map: "constraint_auth_exec_pk") @db.VarChar(36)
alias String? @db.VarChar(255)
authenticator String? @db.VarChar(36)
realm_id String? @db.VarChar(36)
flow_id String? @db.VarChar(36)
requirement Int?
priority Int?
authenticator_flow Boolean @default(false)
auth_flow_id String? @db.VarChar(36)
auth_config String? @db.VarChar(36)
authentication_flow authentication_flow? @relation(fields: [flow_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_auth_exec_flow")
realm realm? @relation(fields: [realm_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_auth_exec_realm")
@@index([flow_id], map: "idx_auth_exec_flow")
@@index([realm_id, flow_id], map: "idx_auth_exec_realm_flow")
}
model authentication_flow {
id String @id(map: "constraint_auth_flow_pk") @db.VarChar(36)
alias String? @db.VarChar(255)
description String? @db.VarChar(255)
realm_id String? @db.VarChar(36)
provider_id String @default("basic-flow") @db.VarChar(36)
top_level Boolean @default(false)
built_in Boolean @default(false)
realm realm? @relation(fields: [realm_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_auth_flow_realm")
authentication_execution authentication_execution[]
@@index([realm_id], map: "idx_auth_flow_realm")
}
model authenticator_config {
id String @id(map: "constraint_auth_pk") @db.VarChar(36)
alias String? @db.VarChar(255)
realm_id String? @db.VarChar(36)
realm realm? @relation(fields: [realm_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_auth_realm")
@@index([realm_id], map: "idx_auth_config_realm")
}
model authenticator_config_entry {
authenticator_id String @db.VarChar(36)
value String?
name String @db.VarChar(255)
@@id([authenticator_id, name], map: "constraint_auth_cfg_pk")
}
model broker_link {
identity_provider String @db.VarChar(255)
storage_provider_id String? @db.VarChar(255)
realm_id String @db.VarChar(36)
broker_user_id String? @db.VarChar(255)
broker_username String? @db.VarChar(255)
token String?
user_id String @db.VarChar(255)
@@id([identity_provider, user_id], map: "constr_broker_link_pk")
}
model client {
id String @id(map: "constraint_7") @db.VarChar(36)
enabled Boolean @default(false)
full_scope_allowed Boolean @default(false)
client_id String? @db.VarChar(255)
not_before Int?
public_client Boolean @default(false)
secret String? @db.VarChar(255)
base_url String? @db.VarChar(255)
bearer_only Boolean @default(false)
management_url String? @db.VarChar(255)
surrogate_auth_required Boolean @default(false)
realm_id String? @db.VarChar(36)
protocol String? @db.VarChar(255)
node_rereg_timeout Int? @default(0)
frontchannel_logout Boolean @default(false)
consent_required Boolean @default(false)
name String? @db.VarChar(255)
service_accounts_enabled Boolean @default(false)
client_authenticator_type String? @db.VarChar(255)
root_url String? @db.VarChar(255)
description String? @db.VarChar(255)
registration_token String? @db.VarChar(255)
standard_flow_enabled Boolean @default(true)
implicit_flow_enabled Boolean @default(false)
direct_access_grants_enabled Boolean @default(false)
always_display_in_console Boolean @default(false)
client_attributes client_attributes[]
client_node_registrations client_node_registrations[]
protocol_mapper protocol_mapper[]
redirect_uris redirect_uris[]
scope_mapping scope_mapping[]
web_origins web_origins[]
@@unique([realm_id, client_id], map: "uk_b71cjlbenv945rb6gcon438at")
@@index([client_id], map: "idx_client_id")
}
model client_attributes {
client_id String @db.VarChar(36)
value String? @db.VarChar(4000)
name String @db.VarChar(255)
client client @relation(fields: [client_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk3c47c64beacca966")
@@id([client_id, name], map: "constraint_3c")
@@index([name], map: "idx_client_att_by_name_value")
}
model client_auth_flow_bindings {
client_id String @db.VarChar(36)
flow_id String? @db.VarChar(36)
binding_name String @db.VarChar(255)
@@id([client_id, binding_name], map: "c_cli_flow_bind")
}
model client_initial_access {
id String @id(map: "cnstr_client_init_acc_pk") @db.VarChar(36)
realm_id String @db.VarChar(36)
timestamp Int?
expiration Int?
count Int?
remaining_count Int?
realm realm @relation(fields: [realm_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_client_init_acc_realm")
@@index([realm_id], map: "idx_client_init_acc_realm")
}
model client_node_registrations {
client_id String @db.VarChar(36)
value Int?
name String @db.VarChar(255)
client client @relation(fields: [client_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk4129723ba992f594")
@@id([client_id, name], map: "constraint_84")
}
model client_scope {
id String @id(map: "pk_cli_template") @db.VarChar(36)
name String? @db.VarChar(255)
realm_id String? @db.VarChar(36)
description String? @db.VarChar(255)
protocol String? @db.VarChar(255)
client_scope_attributes client_scope_attributes[]
client_scope_role_mapping client_scope_role_mapping[]
protocol_mapper protocol_mapper[]
@@unique([realm_id, name], map: "uk_cli_scope")
@@index([realm_id], map: "idx_realm_clscope")
}
model client_scope_attributes {
scope_id String @db.VarChar(36)
value String? @db.VarChar(2048)
name String @db.VarChar(255)
client_scope client_scope @relation(fields: [scope_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_cl_scope_attr_scope")
@@id([scope_id, name], map: "pk_cl_tmpl_attr")
@@index([scope_id], map: "idx_clscope_attrs")
}
model client_scope_client {
client_id String @db.VarChar(255)
scope_id String @db.VarChar(255)
default_scope Boolean @default(false)
@@id([client_id, scope_id], map: "c_cli_scope_bind")
@@index([scope_id], map: "idx_cl_clscope")
@@index([client_id], map: "idx_clscope_cl")
}
model client_scope_role_mapping {
scope_id String @db.VarChar(36)
role_id String @db.VarChar(36)
client_scope client_scope @relation(fields: [scope_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_cl_scope_rm_scope")
@@id([scope_id, role_id], map: "pk_template_scope")
@@index([scope_id], map: "idx_clscope_role")
@@index([role_id], map: "idx_role_clscope")
}
model client_session {
id String @id(map: "constraint_8") @db.VarChar(36)
client_id String? @db.VarChar(36)
redirect_uri String? @db.VarChar(255)
state String? @db.VarChar(255)
timestamp Int?
session_id String? @db.VarChar(36)
auth_method String? @db.VarChar(255)
realm_id String? @db.VarChar(255)
auth_user_id String? @db.VarChar(36)
current_action String? @db.VarChar(36)
user_session user_session? @relation(fields: [session_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_b4ao2vcvat6ukau74wbwtfqo1")
client_session_auth_status client_session_auth_status[]
client_session_note client_session_note[]
client_session_prot_mapper client_session_prot_mapper[]
client_session_role client_session_role[]
client_user_session_note client_user_session_note[]
@@index([session_id], map: "idx_client_session_session")
}
model client_session_auth_status {
authenticator String @db.VarChar(36)
status Int?
client_session String @db.VarChar(36)
client_session_client_sessionToclient_session_auth_status client_session @relation(fields: [client_session], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "auth_status_constraint")
@@id([client_session, authenticator], map: "constraint_auth_status_pk")
}
model client_session_note {
name String @db.VarChar(255)
value String? @db.VarChar(255)
client_session String @db.VarChar(36)
client_session_client_sessionToclient_session_note client_session @relation(fields: [client_session], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk5edfb00ff51c2736")
@@id([client_session, name], map: "constraint_5e")
}
model client_session_prot_mapper {
protocol_mapper_id String @db.VarChar(36)
client_session String @db.VarChar(36)
client_session_client_sessionToclient_session_prot_mapper client_session @relation(fields: [client_session], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_33a8sgqw18i532811v7o2dk89")
@@id([client_session, protocol_mapper_id], map: "constraint_cs_pmp_pk")
}
model client_session_role {
role_id String @db.VarChar(255)
client_session String @db.VarChar(36)
client_session_client_sessionToclient_session_role client_session @relation(fields: [client_session], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_11b7sgqw18i532811v7o2dv76")
@@id([client_session, role_id], map: "constraint_5")
}
model client_user_session_note {
name String @db.VarChar(255)
value String? @db.VarChar(2048)
client_session String @db.VarChar(36)
client_session_client_sessionToclient_user_session_note client_session @relation(fields: [client_session], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_cl_usr_ses_note")
@@id([client_session, name], map: "constr_cl_usr_ses_note")
}
model component {
id String @id(map: "constr_component_pk") @db.VarChar(36)
name String? @db.VarChar(255)
parent_id String? @db.VarChar(36)
provider_id String? @db.VarChar(36)
provider_type String? @db.VarChar(255)
realm_id String? @db.VarChar(36)
sub_type String? @db.VarChar(255)
realm realm? @relation(fields: [realm_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_component_realm")
component_config component_config[]
@@index([provider_type], map: "idx_component_provider_type")
@@index([realm_id], map: "idx_component_realm")
}
model component_config {
id String @id(map: "constr_component_config_pk") @db.VarChar(36)
component_id String @db.VarChar(36)
name String @db.VarChar(255)
value String? @db.VarChar(4000)
component component @relation(fields: [component_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_component_config")
@@index([component_id], map: "idx_compo_config_compo")
}
model composite_role {
composite String @db.VarChar(36)
child_role String @db.VarChar(36)
keycloak_role_composite_role_child_roleTokeycloak_role keycloak_role @relation("composite_role_child_roleTokeycloak_role", fields: [child_role], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_gr7thllb9lu8q4vqa4524jjy8")
keycloak_role_composite_role_compositeTokeycloak_role keycloak_role @relation("composite_role_compositeTokeycloak_role", fields: [composite], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_a63wvekftu8jo1pnj81e7mce2")
@@id([composite, child_role], map: "constraint_composite_role")
@@index([composite], map: "idx_composite")
@@index([child_role], map: "idx_composite_child")
}
model credential {
id String @id(map: "constraint_f") @db.VarChar(36)
salt Bytes?
type String? @db.VarChar(255)
user_id String? @db.VarChar(36)
created_date BigInt?
user_label String? @db.VarChar(255)
secret_data String?
credential_data String?
priority Int?
user_entity user_entity? @relation(fields: [user_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_pfyr0glasqyl0dei3kl69r6v0")
@@index([user_id], map: "idx_user_credential")
}
/// The underlying table does not contain a valid unique identifier and can therefore currently not be handled by the Prisma Client.
model databasechangelog {
id String @db.VarChar(255)
author String @db.VarChar(255)
filename String @db.VarChar(255)
dateexecuted DateTime @db.Timestamp(6)
orderexecuted Int
exectype String @db.VarChar(10)
md5sum String? @db.VarChar(35)
description String? @db.VarChar(255)
comments String? @db.VarChar(255)
tag String? @db.VarChar(255)
liquibase String? @db.VarChar(20)
contexts String? @db.VarChar(255)
labels String? @db.VarChar(255)
deployment_id String? @db.VarChar(10)
@@ignore
}
model databasechangeloglock {
id Int @id(map: "pk_databasechangeloglock")
locked Boolean
lockgranted DateTime? @db.Timestamp(6)
lockedby String? @db.VarChar(255)
}
model default_client_scope {
realm_id String @db.VarChar(36)
scope_id String @db.VarChar(36)
default_scope Boolean @default(false)
realm realm @relation(fields: [realm_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_r_def_cli_scope_realm")
@@id([realm_id, scope_id], map: "r_def_cli_scope_bind")
@@index([realm_id], map: "idx_defcls_realm")
@@index([scope_id], map: "idx_defcls_scope")
}
model event_entity {
id String @id(map: "constraint_4") @db.VarChar(36)
client_id String? @db.VarChar(255)
details_json String? @db.VarChar(2550)
error String? @db.VarChar(255)
ip_address String? @db.VarChar(255)
realm_id String? @db.VarChar(255)
session_id String? @db.VarChar(255)
event_time BigInt?
type String? @db.VarChar(255)
user_id String? @db.VarChar(255)
@@index([realm_id, event_time], map: "idx_event_time")
}
model federated_identity {
identity_provider String @db.VarChar(255)
realm_id String? @db.VarChar(36)
federated_user_id String? @db.VarChar(255)
federated_username String? @db.VarChar(255)
token String?
user_id String @db.VarChar(36)
user_entity user_entity @relation(fields: [user_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk404288b92ef007a6")
@@id([identity_provider, user_id], map: "constraint_40")
@@index([federated_user_id], map: "idx_fedidentity_feduser")
@@index([user_id], map: "idx_fedidentity_user")
}
model federated_user {
id String @id(map: "constr_federated_user") @db.VarChar(255)
storage_provider_id String? @db.VarChar(255)
realm_id String @db.VarChar(36)
}
model fed_user_attribute {
id String @id(map: "constr_fed_user_attr_pk") @db.VarChar(36)
name String @db.VarChar(255)
user_id String @db.VarChar(255)
realm_id String @db.VarChar(36)
storage_provider_id String? @db.VarChar(36)
value String? @db.VarChar(2024)
@@index([user_id, realm_id, name], map: "idx_fu_attribute")
}
model fed_user_consent {
id String @id(map: "constr_fed_user_consent_pk") @db.VarChar(36)
client_id String? @db.VarChar(255)
user_id String @db.VarChar(255)
realm_id String @db.VarChar(36)
storage_provider_id String? @db.VarChar(36)
created_date BigInt?
last_updated_date BigInt?
client_storage_provider String? @db.VarChar(36)
external_client_id String? @db.VarChar(255)
@@index([user_id, client_storage_provider, external_client_id], map: "idx_fu_cnsnt_ext")
@@index([user_id, client_id], map: "idx_fu_consent")
@@index([realm_id, user_id], map: "idx_fu_consent_ru")
}
model fed_user_consent_cl_scope {
user_consent_id String @db.VarChar(36)
scope_id String @db.VarChar(36)
@@id([user_consent_id, scope_id], map: "constraint_fgrntcsnt_clsc_pm")
}
model fed_user_credential {
id String @id(map: "constr_fed_user_cred_pk") @db.VarChar(36)
salt Bytes?
type String? @db.VarChar(255)
created_date BigInt?
user_id String @db.VarChar(255)
realm_id String @db.VarChar(36)
storage_provider_id String? @db.VarChar(36)
user_label String? @db.VarChar(255)
secret_data String?
credential_data String?
priority Int?
@@index([user_id, type], map: "idx_fu_credential")
@@index([realm_id, user_id], map: "idx_fu_credential_ru")
}
model fed_user_group_membership {
group_id String @db.VarChar(36)
user_id String @db.VarChar(255)
realm_id String @db.VarChar(36)
storage_provider_id String? @db.VarChar(36)
@@id([group_id, user_id], map: "constr_fed_user_group")
@@index([user_id, group_id], map: "idx_fu_group_membership")
@@index([realm_id, user_id], map: "idx_fu_group_membership_ru")
}
model fed_user_required_action {
required_action String @default(" ") @db.VarChar(255)
user_id String @db.VarChar(255)
realm_id String @db.VarChar(36)
storage_provider_id String? @db.VarChar(36)
@@id([required_action, user_id], map: "constr_fed_required_action")
@@index([user_id, required_action], map: "idx_fu_required_action")
@@index([realm_id, user_id], map: "idx_fu_required_action_ru")
}
model fed_user_role_mapping {
role_id String @db.VarChar(36)
user_id String @db.VarChar(255)
realm_id String @db.VarChar(36)
storage_provider_id String? @db.VarChar(36)
@@id([role_id, user_id], map: "constr_fed_user_role")
@@index([user_id, role_id], map: "idx_fu_role_mapping")
@@index([realm_id, user_id], map: "idx_fu_role_mapping_ru")
}
model group_attribute {
id String @id(map: "constraint_group_attribute_pk") @default("sybase-needs-something-here") @db.VarChar(36)
name String @db.VarChar(255)
value String? @db.VarChar(255)
group_id String @db.VarChar(36)
keycloak_group keycloak_group @relation(fields: [group_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_group_attribute_group")
@@index([group_id], map: "idx_group_attr_group")
}
model group_role_mapping {
role_id String @db.VarChar(36)
group_id String @db.VarChar(36)
keycloak_group keycloak_group @relation(fields: [group_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_group_role_group")
@@id([role_id, group_id], map: "constraint_group_role")
@@index([group_id], map: "idx_group_role_mapp_group")
}
model identity_provider {
internal_id String @id(map: "constraint_2b") @db.VarChar(36)
enabled Boolean @default(false)
provider_alias String? @db.VarChar(255)
provider_id String? @db.VarChar(255)
store_token Boolean @default(false)
authenticate_by_default Boolean @default(false)
realm_id String? @db.VarChar(36)
add_token_role Boolean @default(true)
trust_email Boolean @default(false)
first_broker_login_flow_id String? @db.VarChar(36)
post_broker_login_flow_id String? @db.VarChar(36)
provider_display_name String? @db.VarChar(255)
link_only Boolean @default(false)
realm realm? @relation(fields: [realm_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk2b4ebc52ae5c3b34")
identity_provider_config identity_provider_config[]
@@unique([provider_alias, realm_id], map: "uk_2daelwnibji49avxsrtuf6xj33")
@@index([realm_id], map: "idx_ident_prov_realm")
}
model identity_provider_config {
identity_provider_id String @db.VarChar(36)
value String?
name String @db.VarChar(255)
identity_provider identity_provider @relation(fields: [identity_provider_id], references: [internal_id], onDelete: NoAction, onUpdate: NoAction, map: "fkdc4897cf864c4e43")
@@id([identity_provider_id, name], map: "constraint_d")
}
model identity_provider_mapper {
id String @id(map: "constraint_idpm") @db.VarChar(36)
name String @db.VarChar(255)
idp_alias String @db.VarChar(255)
idp_mapper_name String @db.VarChar(255)
realm_id String @db.VarChar(36)
realm realm @relation(fields: [realm_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_idpm_realm")
idp_mapper_config idp_mapper_config[]
@@index([realm_id], map: "idx_id_prov_mapp_realm")
}
model idp_mapper_config {
idp_mapper_id String @db.VarChar(36)
value String?
name String @db.VarChar(255)
identity_provider_mapper identity_provider_mapper @relation(fields: [idp_mapper_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_idpmconfig")
@@id([idp_mapper_id, name], map: "constraint_idpmconfig")
}
model keycloak_group {
id String @id(map: "constraint_group") @db.VarChar(36)
name String? @db.VarChar(255)
parent_group String @db.VarChar(36)
realm_id String? @db.VarChar(36)
group_attribute group_attribute[]
group_role_mapping group_role_mapping[]
@@unique([realm_id, parent_group, name], map: "sibling_names")
}
model keycloak_role {
id String @id(map: "constraint_a") @db.VarChar(36)
client_realm_constraint String? @db.VarChar(255)
client_role Boolean @default(false)
description String? @db.VarChar(255)
name String? @db.VarChar(255)
realm_id String? @db.VarChar(255)
client String? @db.VarChar(36)
realm String? @db.VarChar(36)
realm_keycloak_roleTorealm realm? @relation(fields: [realm], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_6vyqfe4cn4wlq8r6kt5vdsj5c")
composite_role_composite_role_child_roleTokeycloak_role composite_role[] @relation("composite_role_child_roleTokeycloak_role")
composite_role_composite_role_compositeTokeycloak_role composite_role[] @relation("composite_role_compositeTokeycloak_role")
role_attribute role_attribute[]
@@unique([name, client_realm_constraint], map: "UK_J3RWUVD56ONTGSUHOGM184WW2-2")
@@index([client], map: "idx_keycloak_role_client")
@@index([realm], map: "idx_keycloak_role_realm")
}
model migration_model {
id String @id(map: "constraint_migmod") @db.VarChar(36)
version String? @db.VarChar(36)
update_time BigInt @default(0)
@@index([update_time], map: "idx_update_time")
}
model offline_client_session {
user_session_id String @db.VarChar(36)
client_id String @db.VarChar(255)
offline_flag String @db.VarChar(4)
timestamp Int?
data String?
client_storage_provider String @default("local") @db.VarChar(36)
external_client_id String @default("local") @db.VarChar(255)
@@id([user_session_id, client_id, client_storage_provider, external_client_id, offline_flag], map: "constraint_offl_cl_ses_pk3")
@@index([client_id, offline_flag], map: "idx_offline_css_preload")
@@index([user_session_id], map: "idx_us_sess_id_on_cl_sess")
}
model offline_user_session {
user_session_id String @db.VarChar(36)
user_id String @db.VarChar(255)
realm_id String @db.VarChar(36)
created_on Int
offline_flag String @db.VarChar(4)
data String?
last_session_refresh Int @default(0)
@@id([user_session_id, offline_flag], map: "constraint_offl_us_ses_pk2")
@@index([user_id, realm_id, offline_flag], map: "idx_offline_uss_by_user")
@@index([realm_id, offline_flag, user_session_id], map: "idx_offline_uss_by_usersess")
@@index([created_on], map: "idx_offline_uss_createdon")
@@index([offline_flag, created_on, user_session_id], map: "idx_offline_uss_preload")
}
model policy_config {
policy_id String @db.VarChar(36)
name String @db.VarChar(255)
value String?
resource_server_policy resource_server_policy @relation(fields: [policy_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fkdc34197cf864c4e43")
@@id([policy_id, name], map: "constraint_dpc")
}
model protocol_mapper {
id String @id(map: "constraint_pcm") @db.VarChar(36)
name String @db.VarChar(255)
protocol String @db.VarChar(255)
protocol_mapper_name String @db.VarChar(255)
client_id String? @db.VarChar(36)
client_scope_id String? @db.VarChar(36)
client client? @relation(fields: [client_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_pcm_realm")
client_scope client_scope? @relation(fields: [client_scope_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_cli_scope_mapper")
protocol_mapper_config protocol_mapper_config[]
@@index([client_scope_id], map: "idx_clscope_protmap")
@@index([client_id], map: "idx_protocol_mapper_client")
}
model protocol_mapper_config {
protocol_mapper_id String @db.VarChar(36)
value String?
name String @db.VarChar(255)
protocol_mapper protocol_mapper @relation(fields: [protocol_mapper_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_pmconfig")
@@id([protocol_mapper_id, name], map: "constraint_pmconfig")
}
model realm {
id String @id(map: "constraint_4a") @db.VarChar(36)
access_code_lifespan Int?
user_action_lifespan Int?
access_token_lifespan Int?
account_theme String? @db.VarChar(255)
admin_theme String? @db.VarChar(255)
email_theme String? @db.VarChar(255)
enabled Boolean @default(false)
events_enabled Boolean @default(false)
events_expiration BigInt?
login_theme String? @db.VarChar(255)
name String? @unique(map: "uk_orvsdmla56612eaefiq6wl5oi") @db.VarChar(255)
not_before Int?
password_policy String? @db.VarChar(2550)
registration_allowed Boolean @default(false)
remember_me Boolean @default(false)
reset_password_allowed Boolean @default(false)
social Boolean @default(false)
ssl_required String? @db.VarChar(255)
sso_idle_timeout Int?
sso_max_lifespan Int?
update_profile_on_soc_login Boolean @default(false)
verify_email Boolean @default(false)
master_admin_client String? @db.VarChar(36)
login_lifespan Int?
internationalization_enabled Boolean @default(false)
default_locale String? @db.VarChar(255)
reg_email_as_username Boolean @default(false)
admin_events_enabled Boolean @default(false)
admin_events_details_enabled Boolean @default(false)
edit_username_allowed Boolean @default(false)
otp_policy_counter Int? @default(0)
otp_policy_window Int? @default(1)
otp_policy_period Int? @default(30)
otp_policy_digits Int? @default(6)
otp_policy_alg String? @default("HmacSHA1") @db.VarChar(36)
otp_policy_type String? @default("totp") @db.VarChar(36)
browser_flow String? @db.VarChar(36)
registration_flow String? @db.VarChar(36)
direct_grant_flow String? @db.VarChar(36)
reset_credentials_flow String? @db.VarChar(36)
client_auth_flow String? @db.VarChar(36)
offline_session_idle_timeout Int? @default(0)
revoke_refresh_token Boolean @default(false)
access_token_life_implicit Int? @default(0)
login_with_email_allowed Boolean @default(true)
duplicate_emails_allowed Boolean @default(false)
docker_auth_flow String? @db.VarChar(36)
refresh_token_max_reuse Int? @default(0)
allow_user_managed_access Boolean @default(false)
sso_max_lifespan_remember_me Int @default(0)
sso_idle_timeout_remember_me Int @default(0)
default_role String? @db.VarChar(255)
authentication_execution authentication_execution[]
authentication_flow authentication_flow[]
authenticator_config authenticator_config[]
client_initial_access client_initial_access[]
component component[]
default_client_scope default_client_scope[]
identity_provider identity_provider[]
identity_provider_mapper identity_provider_mapper[]
keycloak_role keycloak_role[]
realm_attribute realm_attribute[]
realm_default_groups realm_default_groups[]
realm_enabled_event_types realm_enabled_event_types[]
realm_events_listeners realm_events_listeners[]
realm_required_credential realm_required_credential[]
realm_smtp_config realm_smtp_config[]
realm_supported_locales realm_supported_locales[]
required_action_provider required_action_provider[]
user_federation_mapper user_federation_mapper[]
user_federation_provider user_federation_provider[]
@@index([master_admin_client], map: "idx_realm_master_adm_cli")
}
model realm_attribute {
name String @db.VarChar(255)
realm_id String @db.VarChar(36)
value String?
realm realm @relation(fields: [realm_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_8shxd6l3e9atqukacxgpffptw")
@@id([name, realm_id], map: "constraint_9")
@@index([realm_id], map: "idx_realm_attr_realm")
}
model realm_default_groups {
realm_id String @db.VarChar(36)
group_id String @unique(map: "con_group_id_def_groups") @db.VarChar(36)
realm realm @relation(fields: [realm_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_def_groups_realm")
@@id([realm_id, group_id], map: "constr_realm_default_groups")
@@index([realm_id], map: "idx_realm_def_grp_realm")
}
model realm_enabled_event_types {
realm_id String @db.VarChar(36)
value String @db.VarChar(255)
realm realm @relation(fields: [realm_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_h846o4h0w8epx5nwedrf5y69j")
@@id([realm_id, value], map: "constr_realm_enabl_event_types")
@@index([realm_id], map: "idx_realm_evt_types_realm")
}
model realm_events_listeners {
realm_id String @db.VarChar(36)
value String @db.VarChar(255)
realm realm @relation(fields: [realm_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_h846o4h0w8epx5nxev9f5y69j")
@@id([realm_id, value], map: "constr_realm_events_listeners")
@@index([realm_id], map: "idx_realm_evt_list_realm")
}
model realm_localizations {
realm_id String @db.VarChar(255)
locale String @db.VarChar(255)
texts String
@@id([realm_id, locale])
}
model realm_required_credential {
type String @db.VarChar(255)
form_label String? @db.VarChar(255)
input Boolean @default(false)
secret Boolean @default(false)
realm_id String @db.VarChar(36)
realm realm @relation(fields: [realm_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_5hg65lybevavkqfki3kponh9v")
@@id([realm_id, type], map: "constraint_92")
}
model realm_smtp_config {
realm_id String @db.VarChar(36)
value String? @db.VarChar(255)
name String @db.VarChar(255)
realm realm @relation(fields: [realm_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_70ej8xdxgxd0b9hh6180irr0o")
@@id([realm_id, name], map: "constraint_e")
}
model realm_supported_locales {
realm_id String @db.VarChar(36)
value String @db.VarChar(255)
realm realm @relation(fields: [realm_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_supported_locales_realm")
@@id([realm_id, value], map: "constr_realm_supported_locales")
@@index([realm_id], map: "idx_realm_supp_local_realm")
}
model redirect_uris {
client_id String @db.VarChar(36)
value String @db.VarChar(255)
client client @relation(fields: [client_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_1burs8pb4ouj97h5wuppahv9f")
@@id([client_id, value], map: "constraint_redirect_uris")
@@index([client_id], map: "idx_redir_uri_client")
}
model required_action_config {
required_action_id String @db.VarChar(36)
value String?
name String @db.VarChar(255)
@@id([required_action_id, name], map: "constraint_req_act_cfg_pk")
}
model required_action_provider {
id String @id(map: "constraint_req_act_prv_pk") @db.VarChar(36)
alias String? @db.VarChar(255)
name String? @db.VarChar(255)
realm_id String? @db.VarChar(36)
enabled Boolean @default(false)
default_action Boolean @default(false)
provider_id String? @db.VarChar(255)
priority Int?
realm realm? @relation(fields: [realm_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_req_act_realm")
@@index([realm_id], map: "idx_req_act_prov_realm")
}
model resource_attribute {
id String @id(map: "res_attr_pk") @default("sybase-needs-something-here") @db.VarChar(36)
name String @db.VarChar(255)
value String? @db.VarChar(255)
resource_id String @db.VarChar(36)
resource_server_resource resource_server_resource @relation(fields: [resource_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_5hrm2vlf9ql5fu022kqepovbr")
}
model resource_policy {
resource_id String @db.VarChar(36)
policy_id String @db.VarChar(36)
resource_server_policy resource_server_policy @relation(fields: [policy_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_frsrpp213xcx4wnkog82ssrfy")
resource_server_resource resource_server_resource @relation(fields: [resource_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_frsrpos53xcx4wnkog82ssrfy")
@@id([resource_id, policy_id], map: "constraint_farsrpp")
@@index([policy_id], map: "idx_res_policy_policy")
}
model resource_scope {
resource_id String @db.VarChar(36)
scope_id String @db.VarChar(36)
resource_server_resource resource_server_resource @relation(fields: [resource_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_frsrpos13xcx4wnkog82ssrfy")
resource_server_scope resource_server_scope @relation(fields: [scope_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_frsrps213xcx4wnkog82ssrfy")
@@id([resource_id, scope_id], map: "constraint_farsrsp")
@@index([scope_id], map: "idx_res_scope_scope")
}
model resource_server {
id String @id(map: "pk_resource_server") @db.VarChar(36)
allow_rs_remote_mgmt Boolean @default(false)
policy_enforce_mode String @db.VarChar(15)
decision_strategy Int @default(1) @db.SmallInt
resource_server_perm_ticket resource_server_perm_ticket[]
resource_server_policy resource_server_policy[]
resource_server_resource resource_server_resource[]
resource_server_scope resource_server_scope[]
}
model resource_server_perm_ticket {
id String @id(map: "constraint_fapmt") @db.VarChar(36)
owner String @db.VarChar(255)
requester String @db.VarChar(255)
created_timestamp BigInt
granted_timestamp BigInt?
resource_id String @db.VarChar(36)
scope_id String? @db.VarChar(36)
resource_server_id String @db.VarChar(36)
policy_id String? @db.VarChar(36)
resource_server_policy resource_server_policy? @relation(fields: [policy_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_frsrpo2128cx4wnkog82ssrfy")
resource_server_resource resource_server_resource @relation(fields: [resource_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_frsrho213xcx4wnkog83sspmt")
resource_server resource_server @relation(fields: [resource_server_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_frsrho213xcx4wnkog82sspmt")
resource_server_scope resource_server_scope? @relation(fields: [scope_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_frsrho213xcx4wnkog84sspmt")
@@unique([owner, requester, resource_server_id, resource_id, scope_id], map: "uk_frsr6t700s9v50bu18ws5pmt")
}
model resource_server_policy {
id String @id(map: "constraint_farsrp") @db.VarChar(36)
name String @db.VarChar(255)
description String? @db.VarChar(255)
type String @db.VarChar(255)
decision_strategy String? @db.VarChar(20)
logic String? @db.VarChar(20)
resource_server_id String @db.VarChar(36)
owner String? @db.VarChar(255)
resource_server resource_server @relation(fields: [resource_server_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_frsrpo213xcx4wnkog82ssrfy")
associated_policy_associated_policy_associated_policy_idToresource_server_policy associated_policy[] @relation("associated_policy_associated_policy_idToresource_server_policy")
associated_policy_associated_policy_policy_idToresource_server_policy associated_policy[] @relation("associated_policy_policy_idToresource_server_policy")
policy_config policy_config[]
resource_policy resource_policy[]
resource_server_perm_ticket resource_server_perm_ticket[]
scope_policy scope_policy[]
@@unique([name, resource_server_id], map: "uk_frsrpt700s9v50bu18ws5ha6")
@@index([resource_server_id], map: "idx_res_serv_pol_res_serv")
}
model resource_server_resource {
id String @id(map: "constraint_farsr") @db.VarChar(36)
name String @db.VarChar(255)
type String? @db.VarChar(255)
icon_uri String? @db.VarChar(255)
owner String @db.VarChar(255)
resource_server_id String @db.VarChar(36)
owner_managed_access Boolean @default(false)
display_name String? @db.VarChar(255)
resource_server resource_server @relation(fields: [resource_server_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_frsrho213xcx4wnkog82ssrfy")
resource_attribute resource_attribute[]
resource_policy resource_policy[]
resource_scope resource_scope[]
resource_server_perm_ticket resource_server_perm_ticket[]
resource_uris resource_uris[]
@@unique([name, owner, resource_server_id], map: "uk_frsr6t700s9v50bu18ws5ha6")
@@index([resource_server_id], map: "idx_res_srv_res_res_srv")
}
model resource_server_scope {
id String @id(map: "constraint_farsrs") @db.VarChar(36)
name String @db.VarChar(255)
icon_uri String? @db.VarChar(255)
resource_server_id String @db.VarChar(36)
display_name String? @db.VarChar(255)
resource_server resource_server @relation(fields: [resource_server_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_frsrso213xcx4wnkog82ssrfy")
resource_scope resource_scope[]
resource_server_perm_ticket resource_server_perm_ticket[]
scope_policy scope_policy[]
@@unique([name, resource_server_id], map: "uk_frsrst700s9v50bu18ws5ha6")
@@index([resource_server_id], map: "idx_res_srv_scope_res_srv")
}
model resource_uris {
resource_id String @db.VarChar(36)
value String @db.VarChar(255)
resource_server_resource resource_server_resource @relation(fields: [resource_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_resource_server_uris")
@@id([resource_id, value], map: "constraint_resour_uris_pk")
}
model role_attribute {
id String @id(map: "constraint_role_attribute_pk") @db.VarChar(36)
role_id String @db.VarChar(36)
name String @db.VarChar(255)
value String? @db.VarChar(255)
keycloak_role keycloak_role @relation(fields: [role_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_role_attribute_id")
@@index([role_id], map: "idx_role_attribute")
}
model scope_mapping {
client_id String @db.VarChar(36)
role_id String @db.VarChar(36)
client client @relation(fields: [client_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_ouse064plmlr732lxjcn1q5f1")
@@id([client_id, role_id], map: "constraint_81")
@@index([role_id], map: "idx_scope_mapping_role")
}
model scope_policy {
scope_id String @db.VarChar(36)
policy_id String @db.VarChar(36)
resource_server_policy resource_server_policy @relation(fields: [policy_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_frsrasp13xcx4wnkog82ssrfy")
resource_server_scope resource_server_scope @relation(fields: [scope_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_frsrpass3xcx4wnkog82ssrfy")
@@id([scope_id, policy_id], map: "constraint_farsrsps")
@@index([policy_id], map: "idx_scope_policy_policy")
}
model user_attribute {
name String @db.VarChar(255)
value String? @db.VarChar(255)
user_id String @db.VarChar(36)
id String @id(map: "constraint_user_attribute_pk") @default("sybase-needs-something-here") @db.VarChar(36)
user_entity user_entity @relation(fields: [user_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_5hrm2vlf9ql5fu043kqepovbr")
@@index([user_id], map: "idx_user_attribute")
@@index([name, value], map: "idx_user_attribute_name")
}
model user_consent {
id String @id(map: "constraint_grntcsnt_pm") @db.VarChar(36)
client_id String? @db.VarChar(255)
user_id String @db.VarChar(36)
created_date BigInt?
last_updated_date BigInt?
client_storage_provider String? @db.VarChar(36)
external_client_id String? @db.VarChar(255)
user_entity user_entity @relation(fields: [user_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_grntcsnt_user")
user_consent_client_scope user_consent_client_scope[]
@@unique([client_id, client_storage_provider, external_client_id, user_id], map: "uk_jkuwuvd56ontgsuhogm8uewrt")
@@index([user_id], map: "idx_user_consent")
}
model user_consent_client_scope {
user_consent_id String @db.VarChar(36)
scope_id String @db.VarChar(36)
user_consent user_consent @relation(fields: [user_consent_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_grntcsnt_clsc_usc")
@@id([user_consent_id, scope_id], map: "constraint_grntcsnt_clsc_pm")
@@index([user_consent_id], map: "idx_usconsent_clscope")
}
model user_entity {
id String @id(map: "constraint_fb") @db.VarChar(36)
email String? @db.VarChar(255)
email_constraint String? @db.VarChar(255)
email_verified Boolean @default(false)
enabled Boolean @default(false)
federation_link String? @db.VarChar(255)
first_name String? @db.VarChar(255)
last_name String? @db.VarChar(255)
realm_id String? @db.VarChar(255)
username String? @db.VarChar(255)
created_timestamp BigInt?
service_account_client_link String? @db.VarChar(255)
not_before Int @default(0)
credential credential[]
federated_identity federated_identity[]
user_attribute user_attribute[]
user_consent user_consent[]
user_group_membership user_group_membership[]
user_required_action user_required_action[]
user_role_mapping user_role_mapping[]
@@unique([realm_id, email_constraint], map: "uk_dykn684sl8up1crfei6eckhd7")
@@unique([realm_id, username], map: "uk_ru8tt6t700s9v50bu18ws5ha6")
@@index([email], map: "idx_user_email")
}
model user_federation_config {
user_federation_provider_id String @db.VarChar(36)
value String? @db.VarChar(255)
name String @db.VarChar(255)
user_federation_provider user_federation_provider @relation(fields: [user_federation_provider_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_t13hpu1j94r2ebpekr39x5eu5")
@@id([user_federation_provider_id, name], map: "constraint_f9")
}
model user_federation_mapper {
id String @id(map: "constraint_fedmapperpm") @db.VarChar(36)
name String @db.VarChar(255)
federation_provider_id String @db.VarChar(36)
federation_mapper_type String @db.VarChar(255)
realm_id String @db.VarChar(36)
user_federation_provider user_federation_provider @relation(fields: [federation_provider_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_fedmapperpm_fedprv")
realm realm @relation(fields: [realm_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_fedmapperpm_realm")
user_federation_mapper_config user_federation_mapper_config[]
@@index([federation_provider_id], map: "idx_usr_fed_map_fed_prv")
@@index([realm_id], map: "idx_usr_fed_map_realm")
}
model user_federation_mapper_config {
user_federation_mapper_id String @db.VarChar(36)
value String? @db.VarChar(255)
name String @db.VarChar(255)
user_federation_mapper user_federation_mapper @relation(fields: [user_federation_mapper_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_fedmapper_cfg")
@@id([user_federation_mapper_id, name], map: "constraint_fedmapper_cfg_pm")
}
model user_federation_provider {
id String @id(map: "constraint_5c") @db.VarChar(36)
changed_sync_period Int?
display_name String? @db.VarChar(255)
full_sync_period Int?
last_sync Int?
priority Int?
provider_name String? @db.VarChar(255)
realm_id String? @db.VarChar(36)
realm realm? @relation(fields: [realm_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_1fj32f6ptolw2qy60cd8n01e8")
user_federation_config user_federation_config[]
user_federation_mapper user_federation_mapper[]
@@index([realm_id], map: "idx_usr_fed_prv_realm")
}
model user_group_membership {
group_id String @db.VarChar(36)
user_id String @db.VarChar(36)
user_entity user_entity @relation(fields: [user_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_user_group_user")
@@id([group_id, user_id], map: "constraint_user_group")
@@index([user_id], map: "idx_user_group_mapping")
}
model username_login_failure {
realm_id String @db.VarChar(36)
username String @db.VarChar(255)
failed_login_not_before Int?
last_failure BigInt?
last_ip_failure String? @db.VarChar(255)
num_failures Int?
@@id([realm_id, username], map: "CONSTRAINT_17-2")
}
model user_required_action {
user_id String @db.VarChar(36)
required_action String @default(" ") @db.VarChar(255)
user_entity user_entity @relation(fields: [user_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_6qj3w1jw9cvafhe19bwsiuvmd")
@@id([required_action, user_id], map: "constraint_required_action")
@@index([user_id], map: "idx_user_reqactions")
}
model user_role_mapping {
role_id String @db.VarChar(255)
user_id String @db.VarChar(36)
user_entity user_entity @relation(fields: [user_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_c4fqv34p1mbylloxang7b1q3l")
@@id([role_id, user_id], map: "constraint_c")
@@index([user_id], map: "idx_user_role_mapping")
}
model user_session {
id String @id(map: "constraint_57") @db.VarChar(36)
auth_method String? @db.VarChar(255)
ip_address String? @db.VarChar(255)
last_session_refresh Int?
login_username String? @db.VarChar(255)
realm_id String? @db.VarChar(255)
remember_me Boolean @default(false)
started Int?
user_id String? @db.VarChar(255)
user_session_state Int?
broker_session_id String? @db.VarChar(255)
broker_user_id String? @db.VarChar(255)
client_session client_session[]
user_session_note user_session_note[]
}
model user_session_note {
user_session String @db.VarChar(36)
name String @db.VarChar(255)
value String? @db.VarChar(2048)
user_session_user_sessionTouser_session_note user_session @relation(fields: [user_session], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk5edfb00ff51d3472")
@@id([user_session, name], map: "constraint_usn_pk")
}
model web_origins {
client_id String @db.VarChar(36)
value String @db.VarChar(255)
client client @relation(fields: [client_id], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "fk_lojpho213xcx4wnkog82ssrfy")
@@id([client_id, value], map: "constraint_web_origins")
@@index([client_id], map: "idx_web_orig_client")
}
Setting up Keycloak with React
- 1. Similar to NestJS keycloak setup, create a new client called react -web-app
- 2. For the front-end client (react-web-app) we set Access Type to public and Redirect URL to application url.
- 3. Make similar roles as NestJS client and also connect users with the same roles.
Front-end Application Configuration (React.js)
Keycloak Client Adapers : Keycloak client adapters are libraries that make it very easy to secure applications and services with Keycloak. We call these ‘adapters’ rather than libraries as they provide a tight integration to the underlying platform and framework. This makes adapters easy to use and require less boilerplate code than what is typically required by a library.
1. Install keycloak-js dependency to the react app.npm install keycloak-js
2. We can implement our authentication logic using the standard Keycloak APIs init method call which returns a promise containing authentication details.

login-required is one of two possible values to be passed as an onLoad parameter. This will authenticate the client if the user has already logged into Keycloak, or redirect the browser to the login page if he hasn’t. The other option is check-sso : this will only authenticate the client if the user has already logged in, otherwise the client will remain unauthenticated without automatic redirection.
Here we need to store the access token received from authenticated Keycolak object to call back-end Rest APIs. We can put it into either global variable or local storage. We are proceeding with the global variable scenario.

4. After user authenticated to the react-web-app , For each Back-end API call we have to send the access token in the header. Let’s add it to an interceptor.

add the token stored in the global variable
3. Get the client related info JSON from the Keycloak server and put it into the public/keycloak.json .


That’s it for the front-end application configuration.
Keycloakify
- Keycloak does not allow the user to have their custom login pages for any of the authentication flow. This might be the only con for working with keycloak.
- Although keycloak does enable you to work with themes, the themes and ftl based themes which require a lot of HTML, CSS and JS work for them to show a proper UI.
- Keycloakify is package that helps in making those login pages with utilising react.
- Docs - https://docs.keycloakify.dev/
- After generating login files, you will have to attach a docker volume based on existing theme location and docker theme location. Check the above tutorial for clarification
Setup KeyCloak on EC2
- Use the same docker-compose file as you are using for development.
- You will an https required error as ec2 does not allow unsecured connection, follow this post to fix - https://stackoverflow.com/questions/49859066/keycloak-docker-https-required
- Only use this setup on development between frontend and backend teams.
- Keycloak docs have the proper deployment guide, follow that that final deployment
Read more blogs here