-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1e3a64b
commit 2b4e25d
Showing
40 changed files
with
1,483 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<parent> | ||
<artifactId>quarkus-oidc-db-token-state-manager-parent</artifactId> | ||
<groupId>io.quarkus</groupId> | ||
<version>999-SNAPSHOT</version> | ||
<relativePath>../</relativePath> | ||
</parent> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<artifactId>quarkus-oidc-db-token-state-manager-deployment</artifactId> | ||
<name>Quarkus - OpenID Connect Database Token State Manager - Deployment</name> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>io.quarkus</groupId> | ||
<artifactId>quarkus-oidc-db-token-state-manager</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>io.quarkus</groupId> | ||
<artifactId>quarkus-oidc-deployment</artifactId> | ||
</dependency> | ||
<!-- Test dependencies --> | ||
<dependency> | ||
<groupId>io.quarkus</groupId> | ||
<artifactId>quarkus-resteasy-reactive-deployment</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>io.quarkus</groupId> | ||
<artifactId>quarkus-hibernate-orm-deployment</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>io.quarkus</groupId> | ||
<artifactId>quarkus-junit5-internal</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>io.rest-assured</groupId> | ||
<artifactId>rest-assured</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>net.sourceforge.htmlunit</groupId> | ||
<artifactId>htmlunit</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
</dependencies> | ||
|
||
<build> | ||
<plugins> | ||
<plugin> | ||
<artifactId>maven-compiler-plugin</artifactId> | ||
<configuration> | ||
<annotationProcessorPaths> | ||
<path> | ||
<groupId>io.quarkus</groupId> | ||
<artifactId>quarkus-extension-processor</artifactId> | ||
<version>${project.version}</version> | ||
</path> | ||
</annotationProcessorPaths> | ||
</configuration> | ||
</plugin> | ||
<plugin> | ||
<artifactId>maven-surefire-plugin</artifactId> | ||
<configuration> | ||
<skip>true</skip> | ||
</configuration> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
<profiles> | ||
<profile> | ||
<id>test-keycloak</id> | ||
<activation> | ||
<property> | ||
<name>test-containers</name> | ||
</property> | ||
</activation> | ||
<build> | ||
<plugins> | ||
<plugin> | ||
<artifactId>maven-surefire-plugin</artifactId> | ||
<configuration> | ||
<skip>false</skip> | ||
<systemPropertyVariables> | ||
<mssql.image>${mssql.image}</mssql.image> | ||
<db2.image>${db2.image}</db2.image> | ||
</systemPropertyVariables> | ||
</configuration> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
</profile> | ||
</profiles> | ||
</project> |
17 changes: 17 additions & 0 deletions
17
...n/java/io/quarkus/oidc/db/token/state/manager/OidcDbTokenStateManagerBuildTimeConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package io.quarkus.oidc.db.token.state.manager; | ||
|
||
import io.quarkus.runtime.annotations.ConfigRoot; | ||
import io.smallrye.config.ConfigMapping; | ||
import io.smallrye.config.WithDefault; | ||
|
||
@ConfigMapping(prefix = "quarkus.oidc-db-token-state-manager") | ||
@ConfigRoot | ||
public interface OidcDbTokenStateManagerBuildTimeConfig { | ||
|
||
/** | ||
* Whether token state should be stored in the database. | ||
*/ | ||
@WithDefault("true") | ||
boolean enabled(); | ||
|
||
} |
213 changes: 213 additions & 0 deletions
213
...rc/main/java/io/quarkus/oidc/db/token/state/manager/OidcDbTokenStateManagerProcessor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,213 @@ | ||
package io.quarkus.oidc.db.token.state.manager; | ||
|
||
import static io.quarkus.deployment.Capability.REACTIVE_DB2_CLIENT; | ||
import static io.quarkus.deployment.Capability.REACTIVE_MSSQL_CLIENT; | ||
import static io.quarkus.deployment.Capability.REACTIVE_MYSQL_CLIENT; | ||
import static io.quarkus.deployment.Capability.REACTIVE_ORACLE_CLIENT; | ||
import static io.quarkus.deployment.Capability.REACTIVE_PG_CLIENT; | ||
import static io.quarkus.deployment.annotations.ExecutionTime.RUNTIME_INIT; | ||
import static io.quarkus.deployment.annotations.ExecutionTime.STATIC_INIT; | ||
|
||
import java.util.function.BooleanSupplier; | ||
|
||
import jakarta.enterprise.context.Dependent; | ||
import jakarta.inject.Singleton; | ||
|
||
import io.quarkus.arc.deployment.AdditionalBeanBuildItem; | ||
import io.quarkus.arc.deployment.BeanContainerBuildItem; | ||
import io.quarkus.arc.deployment.SyntheticBeanBuildItem; | ||
import io.quarkus.arc.deployment.SyntheticBeansRuntimeInitBuildItem; | ||
import io.quarkus.arc.deployment.ValidationPhaseBuildItem; | ||
import io.quarkus.builder.item.SimpleBuildItem; | ||
import io.quarkus.deployment.Capabilities; | ||
import io.quarkus.deployment.annotations.BuildProducer; | ||
import io.quarkus.deployment.annotations.BuildStep; | ||
import io.quarkus.deployment.annotations.BuildSteps; | ||
import io.quarkus.deployment.annotations.Consume; | ||
import io.quarkus.deployment.annotations.Record; | ||
import io.quarkus.deployment.builditem.RuntimeConfigSetupCompleteBuildItem; | ||
import io.quarkus.oidc.TokenStateManager; | ||
import io.quarkus.oidc.db.token.state.manager.runtime.OidcDbTokenStateManager; | ||
import io.quarkus.oidc.db.token.state.manager.runtime.OidcDbTokenStateManagerInitializer; | ||
import io.quarkus.oidc.db.token.state.manager.runtime.OidcDbTokenStateManagerInitializer.OidcDbTokenStateManagerInitializerProperties; | ||
import io.quarkus.oidc.db.token.state.manager.runtime.OidcDbTokenStateManagerRecorder; | ||
import io.quarkus.runtime.configuration.ConfigurationException; | ||
|
||
@BuildSteps(onlyIf = OidcDbTokenStateManagerProcessor.OidcDbTokenStateManagerEnabled.class) | ||
public class OidcDbTokenStateManagerProcessor { | ||
|
||
private static final String[] SUPPORTED_REACTIVE_CLIENTS = new String[] { REACTIVE_PG_CLIENT, REACTIVE_MYSQL_CLIENT, | ||
REACTIVE_MSSQL_CLIENT, REACTIVE_DB2_CLIENT, REACTIVE_ORACLE_CLIENT }; | ||
|
||
@Record(STATIC_INIT) | ||
@BuildStep | ||
SyntheticBeanBuildItem produceDbTokenStateManagerBean(OidcDbTokenStateManagerRecorder recorder, | ||
ReactiveSqlClientBuildItem sqlClientBuildItem) { | ||
boolean isMySQL = false; | ||
final String insertStatement; | ||
switch (sqlClientBuildItem.reactiveClient) { | ||
case REACTIVE_PG_CLIENT: | ||
insertStatement = "INSERT INTO oidc_db_token_state_manager (id_token, access_token, refresh_token, expires_in) VALUES ($1, $2, $3, $4) RETURNING id"; | ||
break; | ||
case REACTIVE_MYSQL_CLIENT: | ||
isMySQL = true; | ||
insertStatement = "INSERT INTO oidc_db_token_state_manager (id_token, access_token, refresh_token, expires_in) VALUES (?, ?, ?, ?)"; | ||
break; | ||
case REACTIVE_MSSQL_CLIENT: | ||
insertStatement = "INSERT INTO oidc_db_token_state_manager (id_token, access_token, refresh_token, expires_in) OUTPUT INSERTED.id VALUES (@p1, @p2, @p3, @p4)"; | ||
break; | ||
case REACTIVE_DB2_CLIENT: | ||
insertStatement = "SELECT id FROM FINAL TABLE (INSERT INTO oidc_db_token_state_manager (id_token, access_token, refresh_token, expires_in) VALUES (?, ?, ?, ?))"; | ||
break; | ||
case REACTIVE_ORACLE_CLIENT: | ||
// FIXME: make this optimal with io.vertx.oracleclient.OraclePrepareOptions.setAutoGeneratedKeysIndexes | ||
// once on Oracle 24.x driver (as 23.4.0.0 will probably not be available for community) | ||
// see https://github.com/eclipse-vertx/vertx-sql-client/issues/1343 for more info | ||
insertStatement = "SELECT INSERT_TOKENS(?, ?, ?, ?) FROM DUAL"; | ||
break; | ||
default: | ||
throw new RuntimeException("Unknown Reactive Sql Client " + sqlClientBuildItem.reactiveClient); | ||
} | ||
return SyntheticBeanBuildItem | ||
.configure(OidcDbTokenStateManager.class) | ||
.alternative(true) | ||
.priority(1) | ||
.addType(TokenStateManager.class) | ||
.unremovable() | ||
.scope(Singleton.class) | ||
.supplier(recorder.createTokenStateManager(insertStatement, isMySQL)) | ||
.done(); | ||
} | ||
|
||
@BuildStep | ||
ReactiveSqlClientBuildItem validateReactiveSqlClient( | ||
BuildProducer<ValidationPhaseBuildItem.ValidationErrorBuildItem> validationErrors, | ||
Capabilities capabilities) { | ||
ReactiveSqlClientBuildItem sqlClientDbTable = null; | ||
for (String reactiveClient : SUPPORTED_REACTIVE_CLIENTS) { | ||
if (capabilities.isPresent(reactiveClient)) { | ||
if (sqlClientDbTable == null) { | ||
sqlClientDbTable = new ReactiveSqlClientBuildItem(reactiveClient); | ||
} else { | ||
validationErrors.produce(new ValidationPhaseBuildItem.ValidationErrorBuildItem( | ||
new ConfigurationException("The OpenID Connect Database Token State Manager extension is " | ||
+ "only supported when exactly one Reactive SQL Client extension is present."))); | ||
return null; | ||
} | ||
} | ||
} | ||
if (sqlClientDbTable == null) { | ||
validationErrors.produce(new ValidationPhaseBuildItem.ValidationErrorBuildItem(new ConfigurationException( | ||
"The OpenID Connect Database Token State Manager extension requires Reactive SQL Client extension. " | ||
+ "Please refer to the https://quarkus.io/guides/reactive-sql-clients for more information."))); | ||
} | ||
return sqlClientDbTable; | ||
} | ||
|
||
@BuildStep | ||
AdditionalBeanBuildItem makeDbTokenStateManagerInitializerBean() { | ||
return new AdditionalBeanBuildItem(OidcDbTokenStateManagerInitializer.class); | ||
} | ||
|
||
@BuildStep | ||
@Record(STATIC_INIT) | ||
SyntheticBeanBuildItem createDbTokenStateInitializerProps(ReactiveSqlClientBuildItem sqlClientBuildItem, | ||
OidcDbTokenStateManagerRecorder recorder) { | ||
final String createTableDdl; | ||
final boolean supportsIfTableNotExists; | ||
boolean isOracleClient = false; | ||
switch (sqlClientBuildItem.reactiveClient) { | ||
case REACTIVE_PG_CLIENT: | ||
createTableDdl = "CREATE TABLE IF NOT EXISTS oidc_db_token_state_manager (" + | ||
"id BIGSERIAL PRIMARY KEY, " + | ||
"id_token VARCHAR, " + | ||
"access_token VARCHAR, " + | ||
"expires_in BIGINT NOT NULL, " + | ||
"refresh_token VARCHAR)"; | ||
supportsIfTableNotExists = true; | ||
break; | ||
case REACTIVE_MYSQL_CLIENT: | ||
createTableDdl = "CREATE TABLE IF NOT EXISTS oidc_db_token_state_manager (" | ||
+ "id BIGINT NOT NULL AUTO_INCREMENT, " | ||
+ "id_token VARCHAR(5000) NULL, " | ||
+ "access_token VARCHAR(5000) NULL, " | ||
+ "refresh_token VARCHAR(5000) NULL, " | ||
+ "expires_in BIGINT NOT NULL, " | ||
+ "PRIMARY KEY (id))"; | ||
supportsIfTableNotExists = true; | ||
break; | ||
case REACTIVE_MSSQL_CLIENT: | ||
createTableDdl = "CREATE TABLE oidc_db_token_state_manager (" | ||
+ "id BIGINT IDENTITY(1,1) PRIMARY KEY, " | ||
+ "id_token NVARCHAR(MAX), " | ||
+ "access_token NVARCHAR(MAX), " | ||
+ "refresh_token NVARCHAR(MAX), " | ||
+ "expires_in BIGINT NOT NULL)"; | ||
supportsIfTableNotExists = false; | ||
break; | ||
case REACTIVE_DB2_CLIENT: | ||
createTableDdl = "CREATE TABLE oidc_db_token_state_manager (" | ||
+ "id BIGINT NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1), " | ||
+ "id_token VARCHAR(4000), " | ||
+ "access_token VARCHAR(4000), " | ||
+ "refresh_token VARCHAR(4000), " | ||
+ "expires_in BIGINT NOT NULL, " | ||
+ "PRIMARY KEY (id))"; | ||
supportsIfTableNotExists = false; | ||
break; | ||
case REACTIVE_ORACLE_CLIENT: | ||
createTableDdl = "CREATE TABLE IF NOT EXISTS oidc_db_token_state_manager (" | ||
+ "id NUMBER GENERATED ALWAYS AS IDENTITY PRIMARY KEY, " | ||
+ "id_token VARCHAR2(4000), " | ||
+ "access_token VARCHAR2(4000), " | ||
+ "refresh_token VARCHAR2(4000), " | ||
+ "expires_in NUMBER NOT NULL)"; | ||
supportsIfTableNotExists = true; | ||
isOracleClient = true; | ||
break; | ||
default: | ||
throw new ConfigurationException("Unknown Reactive Sql Client " + sqlClientBuildItem.reactiveClient); | ||
} | ||
return SyntheticBeanBuildItem | ||
.configure(OidcDbTokenStateManagerInitializerProperties.class) | ||
.supplier(recorder.createDbTokenStateInitializerProps(createTableDdl, supportsIfTableNotExists, | ||
isOracleClient)) | ||
.unremovable() | ||
.scope(Dependent.class) | ||
.done(); | ||
} | ||
|
||
@Consume(RuntimeConfigSetupCompleteBuildItem.class) | ||
@Record(RUNTIME_INIT) | ||
@BuildStep | ||
void validateTenantConfig(OidcDbTokenStateManagerRecorder recorder) { | ||
recorder.validateOidcTenantConfig(); | ||
} | ||
|
||
@Consume(SyntheticBeansRuntimeInitBuildItem.class) | ||
@Record(RUNTIME_INIT) | ||
@BuildStep | ||
void setSqlClientPool(OidcDbTokenStateManagerRecorder recorder, BeanContainerBuildItem beanContainer) { | ||
recorder.setSqlClientPool(beanContainer.getValue()); | ||
} | ||
|
||
static final class OidcDbTokenStateManagerEnabled implements BooleanSupplier { | ||
|
||
OidcDbTokenStateManagerBuildTimeConfig config; | ||
|
||
@Override | ||
public boolean getAsBoolean() { | ||
return config.enabled(); | ||
} | ||
} | ||
|
||
static final class ReactiveSqlClientBuildItem extends SimpleBuildItem { | ||
|
||
private final String reactiveClient; | ||
|
||
private ReactiveSqlClientBuildItem(String reactiveClient) { | ||
this.reactiveClient = reactiveClient; | ||
} | ||
} | ||
|
||
} |
Oops, something went wrong.