Skip to content

Commit

Permalink
Add OIDC Client SPI
Browse files Browse the repository at this point in the history
  • Loading branch information
sberyozkin committed Aug 29, 2024
1 parent 844a541 commit 719695d
Show file tree
Hide file tree
Showing 10 changed files with 159 additions and 1 deletion.
5 changes: 5 additions & 0 deletions bom/application/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -918,6 +918,11 @@
<artifactId>quarkus-oidc-client-deployment</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-oidc-client-spi</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-client-oidc-filter</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -934,6 +934,42 @@ quarkus.oidc-client.tls.trust-store-password=${trust-store-password}
#quarkus.oidc-client.tls.trust-store-alias=certAlias
----

=== OIDC Client SPI

When your custom extension must acquire OIDC tokens using one of the OIDC token grants supported by OIDC client, this extension can depend on the OIDC Client SPI only and let OIDC client itself acquire and refresh access tokens as necessary.

Check warning on line 939 in docs/src/main/asciidoc/security-openid-connect-client-reference.adoc

View workflow job for this annotation

GitHub Actions / Linting with Vale

[vale] reported by reviewdog 🐶 [Quarkus.SentenceLength] Try to keep sentences to an average of 32 words or fewer. Raw Output: {"message": "[Quarkus.SentenceLength] Try to keep sentences to an average of 32 words or fewer.", "location": {"path": "docs/src/main/asciidoc/security-openid-connect-client-reference.adoc", "range": {"start": {"line": 939, "column": 1}}}, "severity": "INFO"}

Check warning on line 939 in docs/src/main/asciidoc/security-openid-connect-client-reference.adoc

View workflow job for this annotation

GitHub Actions / Linting with Vale

[vale] reported by reviewdog 🐶 [Quarkus.TermsSuggestions] Depending on the context, consider using 'by using' or 'that uses' rather than 'using'. Raw Output: {"message": "[Quarkus.TermsSuggestions] Depending on the context, consider using 'by using' or 'that uses' rather than 'using'.", "location": {"path": "docs/src/main/asciidoc/security-openid-connect-client-reference.adoc", "range": {"start": {"line": 939, "column": 52}}}, "severity": "INFO"}

Check warning on line 939 in docs/src/main/asciidoc/security-openid-connect-client-reference.adoc

View workflow job for this annotation

GitHub Actions / Linting with Vale

[vale] reported by reviewdog 🐶 [Quarkus.Headings] Use sentence-style capitalization in 'OIDC Client SPI'. Raw Output: {"message": "[Quarkus.Headings] Use sentence-style capitalization in 'OIDC Client SPI'.", "location": {"path": "docs/src/main/asciidoc/security-openid-connect-client-reference.adoc", "range": {"start": {"line": 939, "column": 147}}}, "severity": "INFO"}

Check warning on line 939 in docs/src/main/asciidoc/security-openid-connect-client-reference.adoc

View workflow job for this annotation

GitHub Actions / Linting with Vale

[vale] reported by reviewdog 🐶 [Quarkus.TermsSuggestions] Depending on the context, consider using 'because' or 'while' rather than 'as'. Raw Output: {"message": "[Quarkus.TermsSuggestions] Depending on the context, consider using 'because' or 'while' rather than 'as'.", "location": {"path": "docs/src/main/asciidoc/security-openid-connect-client-reference.adoc", "range": {"start": {"line": 939, "column": 229}}}, "severity": "INFO"}

Add the following dependency:

[source,xml]
----
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-oidc-client-spi</artifactId>
</dependency>
----

Next update your extension to use `io.quarkus.oidc.client.spi.TokenProvider` CDI bean as required, for example:

[source,java]
----
package org.acme.extension;
import jakarta.inject.Inject;
import io.quarkus.oidc.client.spi.TokenProvider;
public class ExtensionOAuth2Support {
@Inject
TokenProvider tokenProvider;
public Uni<String> getAccessToken() {
return tokenProvider.getAccessToken();
}
}
----

Currently, `io.quarkus.oidc.client.spi.TokenProvider` is only available for default OIDC clients, since custom extensions are unlikely to be aware of multiple named OIDC clients.

[[integration-testing-oidc-client]]
=== Testing

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
import io.quarkus.oidc.client.runtime.OidcClientBuildTimeConfig;
import io.quarkus.oidc.client.runtime.OidcClientRecorder;
import io.quarkus.oidc.client.runtime.OidcClientsConfig;
import io.quarkus.oidc.client.runtime.TokenProviderProducer;
import io.quarkus.oidc.client.runtime.TokensHelper;
import io.quarkus.oidc.client.runtime.TokensProducer;
import io.quarkus.oidc.token.propagation.AccessToken;
Expand All @@ -66,7 +67,10 @@ ExtensionSslNativeSupportBuildItem enableSslInNative() {

@BuildStep
void registerProvider(BuildProducer<AdditionalBeanBuildItem> additionalBeans) {
additionalBeans.produce(AdditionalBeanBuildItem.unremovableOf(TokensProducer.class));
AdditionalBeanBuildItem.Builder builder = AdditionalBeanBuildItem.builder().setUnremovable();
builder.addBeanClass(TokensProducer.class);
builder.addBeanClass(TokenProviderProducer.class);
additionalBeans.produce(builder.build());
}

@BuildStep
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import jakarta.ws.rs.Path;
import jakarta.ws.rs.QueryParam;

import io.quarkus.oidc.client.spi.TokenProvider;
import io.smallrye.mutiny.Uni;

@Path("/client")
Expand All @@ -14,6 +15,9 @@ public class OidcClientResource {
@Inject
OidcClient client;

@Inject
TokenProvider tokenProvider;

@Inject
@NamedOidcClient("key")
OidcClient keyClient;
Expand All @@ -30,6 +34,12 @@ public Uni<String> tokenUni() {
return client.getTokens().flatMap(tokens -> Uni.createFrom().item(tokens.getAccessToken()));
}

@GET
@Path("tokenprovider")
public Uni<String> tokenProvider() {
return tokenProvider.getAccessToken();
}

@GET
@Path("tokens")
public Uni<String> grantTokensUni() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,17 @@ public void testPasswordGrantToken() {

}

@Test
public void testPasswordGrantTokenProvider() {
String token = RestAssured.when().get("/client/tokenprovider").body().asString();
RestAssured.given().auth().oauth2(token)
.when().get("/protected")
.then()
.statusCode(200)
.body(equalTo("alice"));

}

@Test
public void testPublicClientPasswordGrantToken() {
String token = RestAssured.when().get("/public-client/token").body().asString();
Expand Down
1 change: 1 addition & 0 deletions extensions/oidc-client/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@
<modules>
<module>deployment</module>
<module>runtime</module>
<module>spi</module>
</modules>
</project>
4 changes: 4 additions & 0 deletions extensions/oidc-client/runtime/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@
<groupId>io.quarkus</groupId>
<artifactId>quarkus-oidc-common</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-oidc-client-spi</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5-internal</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package io.quarkus.oidc.client.runtime;

import jakarta.enterprise.context.RequestScoped;
import jakarta.enterprise.inject.Produces;
import jakarta.inject.Singleton;

import io.quarkus.oidc.client.spi.TokenProvider;
import io.smallrye.mutiny.Uni;

@Singleton
public class TokenProviderProducer extends AbstractTokensProducer {

@Produces
@RequestScoped
public TokenProvider produceTokenProvider() {
return new TokenProviderImpl();
}

class TokenProviderImpl implements TokenProvider {

@Override
public Uni<String> getAccessToken() {
return TokenProviderProducer.super.getTokens().onItem().transform(t -> t.getAccessToken());
}

};
}
47 changes: 47 additions & 0 deletions extensions/oidc-client/spi/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?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-client-parent</artifactId>
<groupId>io.quarkus</groupId>
<version>999-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>quarkus-oidc-client-spi</artifactId>
<name>Quarkus - OIDC Client - SPI</name>

<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-core</artifactId>
</dependency>
<dependency>
<groupId>io.smallrye.reactive</groupId>
<artifactId>mutiny</artifactId>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<id>default-compile</id>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-extension-processor</artifactId>
<version>${project.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package io.quarkus.oidc.client.spi;

import io.smallrye.mutiny.Uni;

public interface TokenProvider {

/**
* Get a valid, if necessary refreshed, access token.
*
* @return the access token
*/
Uni<String> getAccessToken();
}

0 comments on commit 719695d

Please sign in to comment.