Skip to content

Commit b11cdaf

Browse files
authored
Merge pull request quarkusio#47570 from ayagmar/issues/47562_improve_oidc_tenant_resolver
OIDC : Improve DefaultStaticTenantResolver URL handling
2 parents 6315150 + c209bad commit b11cdaf

File tree

4 files changed

+62
-9
lines changed

4 files changed

+62
-9
lines changed

extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/StaticTenantResolver.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ Uni<String> resolve(RoutingContext context) {
8484
}
8585

8686
private static final class DefaultStaticTenantResolver implements TenantResolver {
87-
87+
private static final String PATH_SEPARATOR = "/";
8888
private final TenantConfigBean tenantConfigBean;
8989

9090
private DefaultStaticTenantResolver(TenantConfigBean tenantConfigBean) {
@@ -93,13 +93,12 @@ private DefaultStaticTenantResolver(TenantConfigBean tenantConfigBean) {
9393

9494
@Override
9595
public String resolve(RoutingContext context) {
96-
String[] pathSegments = context.request().path().split("/");
97-
if (pathSegments.length > 0) {
98-
String lastPathSegment = pathSegments[pathSegments.length - 1];
99-
if (tenantConfigBean.getStaticTenant(lastPathSegment) != null) {
96+
String[] pathSegments = context.request().path().split(PATH_SEPARATOR);
97+
for (String segment : pathSegments) {
98+
if (tenantConfigBean.getStaticTenant(segment) != null) {
10099
LOG.debugf(
101-
"Tenant id '%s' is selected on the '%s' request path", lastPathSegment, context.normalizedPath());
102-
return lastPathSegment;
100+
"Tenant id '%s' is selected on the '%s' request path", segment, context.normalizedPath());
101+
return segment;
103102
}
104103
}
105104
return null;

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

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
package io.quarkus.it.keycloak;
22

3+
import static io.quarkus.oidc.runtime.OidcUtils.TENANT_ID_ATTRIBUTE;
4+
35
import jakarta.annotation.security.RolesAllowed;
46
import jakarta.inject.Inject;
57
import jakarta.ws.rs.GET;
68
import jakarta.ws.rs.Path;
79
import jakarta.ws.rs.Produces;
10+
import jakarta.ws.rs.QueryParam;
811
import jakarta.ws.rs.core.MediaType;
912

1013
import org.eclipse.microprofile.jwt.JsonWebToken;
1114

1215
import io.quarkus.it.keycloak.model.User;
1316
import io.quarkus.security.identity.SecurityIdentity;
17+
import io.vertx.ext.web.RoutingContext;
1418

1519
/**
1620
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
@@ -20,6 +24,8 @@ public class UsersResource {
2024

2125
@Inject
2226
SecurityIdentity identity;
27+
@Inject
28+
private RoutingContext context;
2329

2430
@GET
2531
@Path("/me/bearer")
@@ -41,8 +47,23 @@ public User principalNameId() {
4147
@Path("/preferredUserName/bearer")
4248
@RolesAllowed("user")
4349
@Produces(MediaType.APPLICATION_JSON)
44-
public User preferredUserName() {
45-
return new User(((JsonWebToken) identity.getPrincipal()).getClaim("preferred_username"));
50+
public User preferredUserName(@QueryParam("includeTenantId") boolean includeTenantId) {
51+
String preferredUsername = ((JsonWebToken) identity.getPrincipal()).getClaim("preferred_username");
52+
if (includeTenantId) {
53+
String tenantId = context.get(TENANT_ID_ATTRIBUTE);
54+
return new User(preferredUsername, tenantId);
55+
}
56+
return new User(preferredUsername);
57+
}
58+
59+
@GET
60+
@Path("/preferredUserName/bearer/token")
61+
@RolesAllowed("user")
62+
@Produces(MediaType.APPLICATION_JSON)
63+
public User preferredUserNameWithExtendedPath() {
64+
String preferredUsername = ((JsonWebToken) identity.getPrincipal()).getClaim("preferred_username");
65+
String tenantId = context.get(TENANT_ID_ATTRIBUTE);
66+
return new User(preferredUsername, tenantId);
4667
}
4768

4869
@GET

integration-tests/oidc-wiremock/src/main/java/io/quarkus/it/keycloak/model/User.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,23 @@
33
public class User {
44

55
private final String userName;
6+
private final String tenantId;
67

78
public User(String name) {
89
this.userName = name;
10+
this.tenantId = null;
11+
}
12+
13+
public User(String userName, String tenantId) {
14+
this.userName = userName;
15+
this.tenantId = tenantId;
916
}
1017

1118
public String getUserName() {
1219
return userName;
1320
}
21+
22+
public String getTenantId() {
23+
return tenantId;
24+
}
1425
}

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,28 @@ public void testSecureAccessSuccessPreferredUsername() {
5858
}
5959
}
6060

61+
@Test
62+
public void testTenantIdFromRoutingContextDefaultTenantResolver() {
63+
String username = "alice";
64+
String tenantId = "bearer";
65+
String accessToken = getAccessToken(username, Set.of("user"));
66+
67+
RestAssured.given().auth().oauth2(accessToken)
68+
.queryParam("includeTenantId", Boolean.TRUE)
69+
.when().get("/api/users/preferredUserName/bearer")
70+
.then()
71+
.statusCode(200)
72+
.body("userName", equalTo(username))
73+
.body("tenantId", equalTo(tenantId));
74+
75+
RestAssured.given().auth().oauth2(getAccessToken(username, Set.of("user", "admin")))
76+
.when().get("/api/users/preferredUserName/bearer/token")
77+
.then()
78+
.statusCode(200)
79+
.body("userName", equalTo(username))
80+
.body("tenantId", equalTo(tenantId));
81+
}
82+
6183
@Test
6284
public void testAccessResourceAzure() throws Exception {
6385
String azureToken = readFile("token.txt");

0 commit comments

Comments
 (0)