Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
135 commits
Select commit Hold shift + click to select a range
49ddbc7
feat: Add keycloak-ydb-extension module. Implement storing keycloak r…
inoorinoor Feb 1, 2026
5b6b8e7
chore: Make migrations name in format year-month-day-date-{name-of-mi…
inoorinoor Feb 1, 2026
d5d735e
feat: Implement JpaConnectionProviderFactory to not implement own Ydb…
inoorinoor Feb 4, 2026
5bbcd34
feat: Use keycloak like code to create connection with YDB. Use YdbDa…
inoorinoor Feb 10, 2026
2f65afd
feat: Add migrations to keycloak started successfully with ydb. Forma…
inoorinoor Feb 10, 2026
566145f
feat: Rewrite some functions, because ydb does not support FOR UPDATE
inoorinoor Feb 10, 2026
f89c356
feat: Add YdbClientProviderFactory to use YdbRealmProvider in creatio…
inoorinoor Feb 10, 2026
b333061
feat: Use hibernate-v7 dialect
inoorinoor Feb 15, 2026
802f95a
refactor: Make code more kotlin style
inoorinoor Feb 15, 2026
b88220c
feat: Create ClientScopeProviderFactory implementation to return YdbR…
inoorinoor Feb 15, 2026
cff1d97
feat: Implement removeClientScope without PESSIMISTIC_WRITE because y…
inoorinoor Feb 15, 2026
e19c0ac
chore: Add more migrations to support realm removing
inoorinoor Feb 15, 2026
ff31ec7
feat: remove features-disabled from docker-compose.yml
inoorinoor Feb 16, 2026
25d92f8
refactor: Write keycloak correctly. Make error in run-keycloack-with-…
inoorinoor Feb 16, 2026
66bfcc7
refactor: Remove redundant IS_YDB_PROFILE_ENABLED
inoorinoor Feb 25, 2026
6b383b0
refactor: Deleted redundant files
inoorinoor Feb 25, 2026
d7daf7f
refactor: Make PROVIDER_PRIORITY bigger to show that only YDB factori…
inoorinoor Feb 25, 2026
e1ff4e7
refactor: Use keycloak.conf file to pass all configs
inoorinoor Feb 25, 2026
7dda6c0
refactor: Set "ydb" id in all providers
inoorinoor Feb 25, 2026
e1889ee
chore: Move files from the root to core module
inoorinoor Feb 25, 2026
accd2ed
test: Implement RealmModelTest
inoorinoor Feb 26, 2026
a483476
test: Add TimeOffsetTest
inoorinoor Mar 5, 2026
63e4461
test: Add ClientModelTest
inoorinoor Mar 5, 2026
ff14620
test: Add GroupModelTest
inoorinoor Mar 5, 2026
de44952
test: Add ClientScopeModelTest
inoorinoor Mar 5, 2026
0b7c1d0
test: Add RoleModelTest
inoorinoor Mar 5, 2026
2aebd51
test: Add ClientScopeStorageTest
inoorinoor Mar 5, 2026
2a2f849
test: Add AdminEventQueryTest
inoorinoor Mar 5, 2026
f932c78
test: Add EventQueryTest
inoorinoor Mar 5, 2026
539922a
feat: Use junit 4 as it is in keycloak
inoorinoor Mar 7, 2026
ed6ec46
test: Add StorageTransactionTest
inoorinoor Mar 14, 2026
e9e5ad7
test: Add SingleUseObjectModelTest.java
inoorinoor Mar 15, 2026
e3d07ac
fix: Use new bootstrap-admin in conf to fix admin login
inoorinoor Mar 19, 2026
1a4971d
feat: Handle parallel liquibase migrations, add DBLockTest
inoorinoor Mar 11, 2026
2c90198
fix: Use insert statements instead of update because UPDATE does not …
inoorinoor Apr 4, 2026
895e373
feat: Add YdbRetryableException handling to respond with 503 error co…
inoorinoor Mar 22, 2026
dce1716
feat: Add hikari connection pool because default hibernate pool it no…
inoorinoor Mar 22, 2026
fa6a83b
feat: Add retry proxy for keycloak
inoorinoor Mar 22, 2026
69824a8
feat: Use Forwarded header instead of X-Forwarded
inoorinoor Mar 22, 2026
4107b6e
feat: Add load testing setup for ydb
inoorinoor Mar 22, 2026
e11b631
refactor: make different names to services to easily differ them
inoorinoor Mar 22, 2026
544499a
fix: Make keycloak port not exposable outward
inoorinoor Mar 22, 2026
3c8b2e3
fix: Add keycloak postgres example for load testing
inoorinoor Mar 22, 2026
0d257a8
fix: Add remote ydb infrastructure
inoorinoor Mar 23, 2026
0dc9ecf
docs: Update load testing readme
inoorinoor Mar 23, 2026
3577a09
refactor: Optimize imports, add new line at file ends
inoorinoor Mar 23, 2026
d37b551
refactor: Delete postgres mention and add link to example in keycloak…
inoorinoor Apr 4, 2026
fc49347
refactor: Remove run.sh and provide examples how to run scenarios.
inoorinoor Apr 4, 2026
90e54f3
refactor: Remove retry-proxy implementation and leave only load tests…
inoorinoor Apr 9, 2026
e020e55
Revert "refactor: Remove retry-proxy implementation and leave only lo…
inoorinoor Apr 9, 2026
6ca1dd8
feat: Add keycloak-ydb-extension module. Implement storing keycloak r…
inoorinoor Feb 1, 2026
fd744fe
chore: Make migrations name in format year-month-day-date-{name-of-mi…
inoorinoor Feb 1, 2026
2b71ba4
feat: Implement JpaConnectionProviderFactory to not implement own Ydb…
inoorinoor Feb 4, 2026
b239225
feat: Use keycloak like code to create connection with YDB. Use YdbDa…
inoorinoor Feb 10, 2026
5d7dd1b
feat: Add migrations to keycloak started successfully with ydb. Forma…
inoorinoor Feb 10, 2026
9144b91
feat: Rewrite some functions, because ydb does not support FOR UPDATE
inoorinoor Feb 10, 2026
3300c85
feat: Add YdbClientProviderFactory to use YdbRealmProvider in creatio…
inoorinoor Feb 10, 2026
4735ca1
feat: Use hibernate-v7 dialect
inoorinoor Feb 15, 2026
a348c3e
refactor: Make code more kotlin style
inoorinoor Feb 15, 2026
3203a2a
feat: Create ClientScopeProviderFactory implementation to return YdbR…
inoorinoor Feb 15, 2026
826d946
feat: Implement removeClientScope without PESSIMISTIC_WRITE because y…
inoorinoor Feb 15, 2026
55c3e9b
chore: Add more migrations to support realm removing
inoorinoor Feb 15, 2026
5a31c99
feat: remove features-disabled from docker-compose.yml
inoorinoor Feb 16, 2026
3fc1e80
refactor: Write keycloak correctly. Make error in run-keycloack-with-…
inoorinoor Feb 16, 2026
3f089cd
refactor: Remove redundant IS_YDB_PROFILE_ENABLED
inoorinoor Feb 25, 2026
d61f6b3
refactor: Deleted redundant files
inoorinoor Feb 25, 2026
4182df3
refactor: Make PROVIDER_PRIORITY bigger to show that only YDB factori…
inoorinoor Feb 25, 2026
fb27f4a
refactor: Use keycloak.conf file to pass all configs
inoorinoor Feb 25, 2026
1dd62da
refactor: Set "ydb" id in all providers
inoorinoor Feb 25, 2026
c11fc31
chore: Move files from the root to core module
inoorinoor Feb 25, 2026
139643f
test: Implement RealmModelTest
inoorinoor Feb 26, 2026
7adfaa4
test: Add TimeOffsetTest
inoorinoor Mar 5, 2026
73c9db7
test: Add ClientModelTest
inoorinoor Mar 5, 2026
3dff759
test: Add GroupModelTest
inoorinoor Mar 5, 2026
44305c7
test: Add ClientScopeModelTest
inoorinoor Mar 5, 2026
edd0190
test: Add RoleModelTest
inoorinoor Mar 5, 2026
9c4bb37
test: Add ClientScopeStorageTest
inoorinoor Mar 5, 2026
eecc4d8
test: Add AdminEventQueryTest
inoorinoor Mar 5, 2026
c7d036c
test: Add EventQueryTest
inoorinoor Mar 5, 2026
d8755af
feat: Use junit 4 as it is in keycloak
inoorinoor Mar 7, 2026
fafd678
test: Add StorageTransactionTest
inoorinoor Mar 14, 2026
64fad3d
test: Add SingleUseObjectModelTest.java
inoorinoor Mar 15, 2026
d519d0d
fix: Use new bootstrap-admin in conf to fix admin login
inoorinoor Mar 19, 2026
f75cda6
feat: Handle ydb specific queries by queries-ydb.properties file
inoorinoor Mar 20, 2026
d4c9478
test: Add MigrationModelTest
inoorinoor Apr 11, 2026
2d713a2
Merge remote-tracking branch 'refs/remotes/origin/add-keycloak-ydb-ex…
inoorinoor Apr 11, 2026
150536a
Merge pull request #6 from inoorinoor/add-dblock-test
inoorinoor Apr 11, 2026
63251b7
feat: Add YdbRetryableException handling to respond with 503 error co…
inoorinoor Mar 22, 2026
6e28a11
feat: Add hikari connection pool because default hibernate pool it no…
inoorinoor Mar 22, 2026
73da475
feat: Add retry proxy for keycloak
inoorinoor Mar 22, 2026
fcf6bb6
feat: Use Forwarded header instead of X-Forwarded
inoorinoor Mar 22, 2026
5bc524a
feat: Add load testing setup for ydb
inoorinoor Mar 22, 2026
4a4bebe
refactor: make different names to services to easily differ them
inoorinoor Mar 22, 2026
fc1ae64
fix: Make keycloak port not exposable outward
inoorinoor Mar 22, 2026
48d3105
fix: Add keycloak postgres example for load testing
inoorinoor Mar 22, 2026
0bca866
fix: Add remote ydb infrastructure
inoorinoor Mar 23, 2026
022c57c
docs: Update load testing readme
inoorinoor Mar 23, 2026
810cb30
refactor: Optimize imports, add new line at file ends
inoorinoor Mar 23, 2026
1518869
refactor: Delete postgres mention and add link to example in keycloak…
inoorinoor Apr 4, 2026
45e9539
refactor: Remove run.sh and provide examples how to run scenarios.
inoorinoor Apr 4, 2026
cb94f45
refactor: Remove retry-proxy implementation and leave only load tests…
inoorinoor Apr 9, 2026
83affd0
Merge remote-tracking branch 'origin/add-keycloak-ydb-extension-modul…
inoorinoor Apr 11, 2026
a8280ef
Merge pull request #1 from inoorinoor/add-keycloak-ydb-extension-module
KirillKurdyukov Apr 11, 2026
57ba512
Merge branch 'ydb-platform:main' into main
inoorinoor May 18, 2026
396d8c6
Merge remote-tracking branch 'origin/main' into load-testing-implemen…
inoorinoor May 18, 2026
bbee239
chore: Format file
inoorinoor May 18, 2026
8831fc0
Merge branch 'load-testing-implementation' into retry-proxy-implement…
inoorinoor May 18, 2026
0328a1c
test: Add unit test of YdbEntityManagerProxy
inoorinoor May 19, 2026
46cb384
fix: Use jdbcUrl from config
inoorinoor May 19, 2026
ff8bd92
Merge pull request #11 from inoorinoor/retry-proxy-implementation
inoorinoor May 19, 2026
c781adb
fix: Add async index to USER_ENTITY
inoorinoor May 19, 2026
6ca891b
Add another ydb retryable exception handling
inoorinoor May 19, 2026
eba4e83
Merge pull request #10 from inoorinoor/load-testing-implementation
inoorinoor May 20, 2026
f10ac44
chore: Add indexes as it is in PG. Remove redundant indexes. Add miss…
inoorinoor May 20, 2026
20f45ea
chore: Remove redundant indexes
inoorinoor May 20, 2026
495b1d1
chore: Add comments with foreign keys for info
inoorinoor May 20, 2026
f16a868
Merge remote-tracking branch 'refs/remotes/origin/main' into migratio…
inoorinoor May 20, 2026
5306e80
Merge branch 'ydb-platform:main' into main
inoorinoor May 20, 2026
c40cf23
chore: Update hibernate v7 dialect version. Use FOR UPDATE ignore hint
inoorinoor May 20, 2026
8d56325
Merge pull request #13 from inoorinoor/use-new-hibernate-dialect
inoorinoor May 20, 2026
32bc3d5
Merge branch 'main' into migration-model-test
inoorinoor May 20, 2026
9d694b8
chore: Remove ignored tests after update of hibernate dialect version
inoorinoor May 20, 2026
0c3f66d
Merge pull request #12 from inoorinoor/migration-model-test
inoorinoor May 20, 2026
25a4da3
test: Add tests for sessions and user
inoorinoor May 20, 2026
88406f6
Revert "test: Add ClientScopeStorageTest" because it does not use YDB
inoorinoor May 20, 2026
17901fd
chore: Remove ignored tests after update of hibernate dialect version
inoorinoor May 20, 2026
e443c47
Merge pull request #14 from inoorinoor/add-integration-tests
inoorinoor May 20, 2026
58068d5
fix: Update YDB healthcheck, use service_healthy in depends_on
inoorinoor May 20, 2026
4a60ae8
chore: Update comment in keycloak-remote-ydb.conf
inoorinoor May 20, 2026
6ec1f48
fix: Remove redundant dependency
inoorinoor May 20, 2026
064f83c
fix: Correct log message
inoorinoor May 20, 2026
998ede9
fix: Use `origin.scheme` instead of hardcoded http
inoorinoor May 21, 2026
13b307f
refactor: Move retryable exception detecting to another file
inoorinoor May 21, 2026
b589f57
ci: add keycloak-ydb-extensions GitHub Actions workflow
inoorinoor May 21, 2026
6858974
fix: Update to ASYNC index in CLIENT
inoorinoor May 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions .github/workflows/ci-keycloak-ydb-extension.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Keycloak YDB Extension CI with Maven

on:
push:
branches:
- main
paths:
- 'keycloak-ydb-extension/**'
- '.github/workflows/ci-keycloak-ydb-extension.yaml'
pull_request:
paths:
- 'keycloak-ydb-extension/**'
- '.github/workflows/ci-keycloak-ydb-extension.yaml'

env:
MAVEN_ARGS: --batch-mode --update-snapshots -Dstyle.color=always

jobs:
build:
name: Keycloak YDB Extension
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
cache: maven

- name: Download dependencies
working-directory: ./keycloak-ydb-extension
run: mvn $MAVEN_ARGS dependency:go-offline

- name: Build & test (unit + Keycloak model tests with YDB)
working-directory: ./keycloak-ydb-extension
run: mvn $MAVEN_ARGS verify
4 changes: 4 additions & 0 deletions keycloak-ydb-extension/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
dependency-reduced-pom.xml

# jar files of keycloak-ydb-extension
docker/providers
51 changes: 51 additions & 0 deletions keycloak-ydb-extension/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Keycloak YDB extension

## Overview

Keycloak extension to use [YDB](https://ydb.tech/) as the main database. Keycloak does not support YDB as a built-in database (see [Configuring the database](https://www.keycloak.org/server/db)); this extension provides the JDBC driver and Hibernate dialect.

## Configuration

When using YDB you must avoid giving the YDB URL to Keycloak’s default datasource (it would fail with “Driver does not support the provided URL”). Use:

| Variable | Value | Purpose |
|----------|--------|---------|
| `KC_DB` | `dev-file` | Built-in datasource uses dev-file; it never sees the YDB URL. |
| `KC_SPI_CONNECTIONS_JPA_DEFAULT_YDB_JDBC_URL` | `jdbc:ydb:grpc://host:2136/database` | JDBC URL used by this extension (required). |
| `KC_SPI_CONNECTIONS_JPA_QUARKUS_ENABLED` | `false` | Disables the default Quarkus JPA provider so H2 is not used. |
| `KC_SPI_CONNECTIONS_LIQUIBASE_QUARKUS_ENABLED` | `false` | Disables the default Quarkus Liquibase provider (migrations are run by this extension). |

The extension is enabled when its JAR is in the `providers` directory and the YDB JDBC URL is configured. No separate “enable” flag is required.

### Connection Pool (HikariCP)

| Variable | Default | Description |
|----------|---------|-------------|
| `KC_SPI_CONNECTIONS_JPA_YDB_POOL_SIZE` | `50` | Maximum pool size |
| `KC_SPI_CONNECTIONS_JPA_YDB_MIN_IDLE` | `10` | Minimum idle connections |
| `KC_SPI_CONNECTIONS_JPA_YDB_CONNECTION_TIMEOUT` | `30000` | Connection timeout (ms) |
| `KC_SPI_CONNECTIONS_JPA_YDB_IDLE_TIMEOUT` | `600000` | Idle connection timeout (ms) |
| `KC_SPI_CONNECTIONS_JPA_YDB_MAX_LIFETIME` | `1800000` | Max connection lifetime (ms) |

Or in `keycloak.conf`:

```properties
spi-connections-jpa-ydb-pool-size=50
spi-connections-jpa-ydb-min-idle=10
```

## Getting started

1. Build and package the extension, then put the JAR in Keycloak’s `providers` directory (or use the Docker setup below).
2. Set the environment variables above and start Keycloak.

### Local development with Docker

From the project root:

```bash
./run-keycloak-with-ydb.sh
```

This builds the extension, copies the JAR to `docker/providers/`, and starts Keycloak + YDB via `docker/docker-compose.yml`.
All Keycloak options (YDB URL, admin user, etc.) are set in `docker/conf/keycloak.conf`; override with environment variables if needed.
212 changes: 212 additions & 0 deletions keycloak-ydb-extension/core/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>tech.ydb</groupId>
<artifactId>keycloak-ydb-extension-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

<packaging>jar</packaging>
<name>keycloak-ydb-extension (core)</name>
<artifactId>keycloak-ydb-extension</artifactId>
<version>1.0-SNAPSHOT</version>

<build>
<sourceDirectory>src/main/kotlin</sourceDirectory>
<testSourceDirectory>src/test/kotlin</testSourceDirectory>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<configuration>
<source>21</source>
<target>21</target>
</configuration>
<executions>
<execution>
<id>default-compile</id>
<phase>none</phase>
</execution>
<execution>
<id>default-testCompile</id>
<phase>none</phase>
</execution>
<execution>
<id>java-compile</id>
<goals>
<goal>compile</goal>
</goals>
<phase>compile</phase>
</execution>
<execution>
<id>java-test-compile</id>
<goals>
<goal>testCompile</goal>
</goals>
<phase>test-compile</phase>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<sourceDirs>
<sourceDir>${project.basedir}/src/main/kotlin</sourceDir>
<sourceDir>${project.basedir}/src/main/java</sourceDir>
</sourceDirs>
</configuration>
</execution>
<execution>
<id>test-compile</id>
<goals>
<goal>test-compile</goal>
</goals>
<configuration>
<sourceDirs>
<sourceDir>${project.basedir}/src/test/kotlin</sourceDir>
<sourceDir>${project.basedir}/src/test/java</sourceDir>
</sourceDirs>
</configuration>
</execution>
</executions>
</plugin>
<plugin>

<artifactId>maven-shade-plugin</artifactId>
<version>3.5.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<artifactSet>
<includes>
<include>org.jetbrains.kotlin:kotlin-stdlib</include>
<include>org.jetbrains.kotlin:kotlin-reflect</include>
<include>org.jetbrains.kotlin:*</include>

<include>tech.ydb.jdbc:*</include>
<include>tech.ydb:*</include>
<include>tech.ydb.dialects:*</include>
<include>com.zaxxer:HikariCP</include>
<include>io.r2dbc:*</include>
</includes>
</artifactSet>

<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-parent</artifactId>
<version>${keycloak.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

Comment thread
inoorinoor marked this conversation as resolved.
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-reflect</artifactId>
<version>${kotlin.version}</version>
</dependency>

<!-- keycloak -->
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-server-spi</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-server-spi-private</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-jpa</artifactId>
<scope>provided</scope>
</dependency>

<!-- YDB -->
<dependency>
<groupId>tech.ydb.jdbc</groupId>
<artifactId>ydb-jdbc-driver</artifactId>
<version>${ydb-jdbc-driver.version}</version>
</dependency>

<dependency>
<groupId>tech.ydb.dialects</groupId>
<artifactId>liquibase-ydb-dialect</artifactId>
<version>1.1.1</version>
</dependency>

<dependency>
<groupId>tech.ydb.dialects</groupId>
<artifactId>hibernate-ydb-dialect-v7</artifactId>
<version>${hibernate-v7.ydb.dialect.version}</version>
</dependency>

<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>${hikaricp.version}</version>
</dependency>

<!-- tests -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>tech.ydb.test</groupId>
<artifactId>ydb-junit5-support</artifactId>
<version>2.3.27</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito.kotlin</groupId>
<artifactId>mockito-kotlin</artifactId>
<version>6.1.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package tech.ydb.keycloak.client

import org.keycloak.Config
import org.keycloak.authorization.fgap.AdminPermissionsSchema
import org.keycloak.common.Profile
import org.keycloak.connections.jpa.JpaConnectionProvider
import org.keycloak.models.ClientProvider
import org.keycloak.models.KeycloakSession
import org.keycloak.models.KeycloakSessionFactory
import org.keycloak.models.RealmModel.RealmAttributeUpdateEvent
import org.keycloak.models.jpa.JpaClientProviderFactory
import org.keycloak.models.jpa.entities.RealmAttributes
import org.keycloak.protocol.saml.SamlConfigAttributes
import org.keycloak.provider.ProviderEvent
import tech.ydb.keycloak.config.ProviderConfig.PROVIDER_ID
import tech.ydb.keycloak.config.ProviderConfig.PROVIDER_PRIORITY
import tech.ydb.keycloak.realm.YdbRealmProvider

class YdbClientProviderFactory : JpaClientProviderFactory() {

private lateinit var clientSearchableAttributes: Set<String>

override fun init(config: Config.Scope) {
var searchableAttrsArr = config.getArray("searchableAttributes")?.toList()
if (searchableAttrsArr == null) {
val s = System.getProperty("keycloak.client.searchableAttributes")
searchableAttrsArr = s?.split("\\s*,\\s*".toRegex())
}
val s = HashSet(REQUIRED_SEARCHABLE_ATTRIBUTES)
if (searchableAttrsArr != null) {
s.addAll(searchableAttrsArr)
}
clientSearchableAttributes = s.toSet()
}

override fun postInit(factory: KeycloakSessionFactory) {
if (Profile.isFeatureEnabled(Profile.Feature.ADMIN_FINE_GRAINED_AUTHZ_V2)) {
factory.register { event: ProviderEvent? ->
if (event is RealmAttributeUpdateEvent) {
if (event.attributeName == RealmAttributes.ADMIN_PERMISSIONS_ENABLED && event.attributeValue.toBoolean()) {
val keycloakSession = event.keycloakSession
val realm = event.realm
AdminPermissionsSchema.SCHEMA.init(keycloakSession, realm)
}
}
}
}
}

override fun create(session: KeycloakSession): ClientProvider {
val em = session.getProvider(JpaConnectionProvider::class.java).entityManager
return YdbRealmProvider(session, em, clientSearchableAttributes, null)
}

override fun close() {
// no operations
}

override fun order(): Int = PROVIDER_PRIORITY

override fun getId(): String = PROVIDER_ID

private companion object{
private val REQUIRED_SEARCHABLE_ATTRIBUTES = listOf(
"saml_idp_initiated_sso_url_name",
SamlConfigAttributes.SAML_ARTIFACT_BINDING_IDENTIFIER,
"jwt.credential.issuer",
"jwt.credential.sub"
)
}
}
Loading
Loading