Skip to content

Commit d1a5e75

Browse files
authored
Merge pull request #48914 from sberyozkin/improve_oidc_client_exchange_grant
Simplify OIDC client exchange grant configuration
2 parents ec5d2bc + 4bb8fbc commit d1a5e75

File tree

8 files changed

+50
-3
lines changed

8 files changed

+50
-3
lines changed

extensions/oidc-client/runtime/src/main/java/io/quarkus/oidc/client/runtime/OidcClientRecorder.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,11 @@ public OidcClient apply(OidcConfigurationMetadata metadata, Throwable t) {
178178
tokenGrantParams.addAll(grantOptions);
179179
}
180180
}
181+
if (oidcConfig.grant().type() == Grant.Type.EXCHANGE
182+
&& !tokenGrantParams.contains(OidcConstants.EXCHANGE_GRANT_SUBJECT_TOKEN_TYPE)) {
183+
tokenGrantParams.add(OidcConstants.EXCHANGE_GRANT_SUBJECT_TOKEN_TYPE,
184+
OidcConstants.EXCHANGE_GRANT_SUBJECT_ACCESS_TOKEN_TYPE);
185+
}
181186
}
182187
}
183188

extensions/oidc-common/runtime/src/main/java/io/quarkus/oidc/common/runtime/OidcConstants.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ public final class OidcConstants {
99
public static final String JWT_BEARER_CLIENT_ASSERTION_TYPE = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer";
1010
public static final String JWT_BEARER_GRANT_TYPE = "urn:ietf:params:oauth:grant-type:jwt-bearer";
1111
public static final String JWT_BEARER_GRANT_ASSERTION = "assertion";
12+
public static final String EXCHANGE_GRANT_SUBJECT_TOKEN = "subject_token";
13+
public static final String EXCHANGE_GRANT_SUBJECT_TOKEN_TYPE = "subject_token_type";
14+
public static final String EXCHANGE_GRANT_SUBJECT_ACCESS_TOKEN_TYPE = "urn:ietf:params:oauth:token-type:access_token";
1215

1316
public static final String CLIENT_CREDENTIALS_GRANT = "client_credentials";
1417
public static final String PASSWORD_GRANT = "password";

extensions/oidc-token-propagation-reactive/runtime/src/main/java/io/quarkus/oidc/token/propagation/reactive/AccessTokenRequestReactiveFilter.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import io.quarkus.oidc.client.OidcClients;
2525
import io.quarkus.oidc.client.runtime.DisabledOidcClientException;
2626
import io.quarkus.oidc.client.runtime.OidcClientConfig.Grant;
27+
import io.quarkus.oidc.common.runtime.OidcConstants;
2728
import io.quarkus.runtime.configuration.ConfigurationException;
2829
import io.quarkus.security.credential.TokenCredential;
2930
import io.quarkus.vertx.core.runtime.context.VertxContextSafetyToggle;
@@ -59,9 +60,9 @@ public void initExchangeTokenClient() {
5960
+ "grant.type",
6061
Grant.Type.class);
6162
if (exchangeTokenGrantType == Grant.Type.EXCHANGE) {
62-
exchangeTokenProperty = "subject_token";
63+
exchangeTokenProperty = OidcConstants.EXCHANGE_GRANT_SUBJECT_TOKEN;
6364
} else if (exchangeTokenGrantType == Grant.Type.JWT) {
64-
exchangeTokenProperty = "assertion";
65+
exchangeTokenProperty = OidcConstants.JWT_BEARER_GRANT_ASSERTION;
6566
} else {
6667
throw new ConfigurationException("Token exchange is required but OIDC client is configured "
6768
+ "to use the " + exchangeTokenGrantType.getGrantType() + " grantType");

extensions/oidc-token-propagation/runtime/src/main/java/io/quarkus/oidc/token/propagation/AccessTokenRequestFilter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public void initExchangeTokenClient() {
5353
+ "grant.type",
5454
Grant.Type.class);
5555
if (exchangeTokenGrantType == Grant.Type.EXCHANGE) {
56-
exchangeTokenProperty = "subject_token";
56+
exchangeTokenProperty = OidcConstants.EXCHANGE_GRANT_SUBJECT_TOKEN;
5757
} else if (exchangeTokenGrantType == Grant.Type.JWT) {
5858
exchangeTokenProperty = OidcConstants.JWT_BEARER_GRANT_ASSERTION;
5959
} else {

integration-tests/oidc-client-wiremock/src/main/java/io/quarkus/it/keycloak/FrontendResource.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import io.quarkus.oidc.client.OidcClientException;
1818
import io.quarkus.oidc.client.OidcClients;
1919
import io.quarkus.oidc.client.Tokens;
20+
import io.quarkus.oidc.common.runtime.OidcConstants;
2021
import io.smallrye.mutiny.Uni;
2122

2223
@Path("/frontend")
@@ -57,6 +58,10 @@ public class FrontendResource {
5758
@NamedOidcClient("jwtbearer-grant")
5859
OidcClient jwtBearerGrantClient;
5960

61+
@Inject
62+
@NamedOidcClient("exchange-grant")
63+
OidcClient exchangeGrantClient;
64+
6065
@Inject
6166
@RestClient
6267
ProtectedResourceServiceRefreshIntervalTestClient tokenRefreshIntervalTestClient;
@@ -70,6 +75,13 @@ public String echoToken() {
7075
return protectedResourceServiceOidcClient.echoToken();
7176
}
7277

78+
@GET
79+
@Path("echoTokenExchangeGrant")
80+
public String echoTokenExchangeGrant() {
81+
return exchangeGrantClient.getTokens(Map.of(OidcConstants.EXCHANGE_GRANT_SUBJECT_TOKEN, "token_to_be_exchanged"))
82+
.await().indefinitely().getAccessToken();
83+
}
84+
7385
@GET
7486
@Path("crashTest")
7587
public String crashTest() {

integration-tests/oidc-client-wiremock/src/main/resources/application.properties

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,14 @@ quarkus.oidc-client.password-grant-public-client.grant.type=password
4747
quarkus.oidc-client.password-grant-public-client.grant-options.password.username=alice
4848
quarkus.oidc-client.password-grant-public-client.grant-options.password.password=alice
4949

50+
quarkus.oidc-client.exchange-grant.auth-server-url=${keycloak.url}
51+
quarkus.oidc-client.exchange-grant.discovery-enabled=false
52+
quarkus.oidc-client.exchange-grant.token-path=/tokens-exchange
53+
quarkus.oidc-client.exchange-grant.grant.type=exchange
54+
quarkus.oidc-client.exchange-grant.client-id=quarkus-app
55+
quarkus.oidc-client.exchange-grant.credentials.secret=secret
56+
57+
5058
quarkus.oidc-client.non-standard-response.token-path=${keycloak.url}/non-standard-tokens
5159
quarkus.oidc-client.non-standard-response.client-id=quarkus-app
5260
quarkus.oidc-client.non-standard-response.credentials.secret=secret

integration-tests/oidc-client-wiremock/src/test/java/io/quarkus/it/keycloak/KeycloakRealmResourceManager.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,15 @@ public Map<String, String> start() {
4242
.withHeader("Content-Type", MediaType.APPLICATION_JSON)
4343
.withBody(
4444
"{\"access_token\":\"access_token_1\", \"expires_in\":4, \"refresh_token\":\"refresh_token_1\"}")));
45+
server.stubFor(WireMock.post("/tokens-exchange")
46+
.withRequestBody(containing("grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Atoken-exchange"))
47+
.withRequestBody(containing("subject_token=token_to_be_exchanged"))
48+
.withRequestBody(containing("subject_token_type=urn%3Aietf%3Aparams%3Aoauth%3Atoken-type%3Aaccess_token"))
49+
.willReturn(WireMock
50+
.aResponse()
51+
.withHeader("Content-Type", MediaType.APPLICATION_JSON)
52+
.withBody(
53+
"{\"access_token\":\"access_token_exchanged\", \"expires_in\":4}")));
4554
server.stubFor(WireMock.post("/tokens-jwtbearer")
4655
.withRequestBody(matching("grant_type=client_credentials&"
4756
+ "client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&"

integration-tests/oidc-client-wiremock/src/test/java/io/quarkus/it/keycloak/OidcClientTest.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,15 @@ public void testEchoWithRefreshInterval() {
318318
}
319319
}
320320

321+
@Order(15)
322+
@Test
323+
public void testEchoTokensExchangeGrant() {
324+
RestAssured.when().get("/frontend/echoTokenExchangeGrant")
325+
.then()
326+
.statusCode(200)
327+
.body(equalTo("access_token_exchanged"));
328+
}
329+
321330
private void checkLog() {
322331
final Path logDirectory = Paths.get(".", "target");
323332
given().await().pollInterval(100, TimeUnit.MILLISECONDS)

0 commit comments

Comments
 (0)