Skip to content

Commit 75bf854

Browse files
sberyozkingsmet
authored andcommitted
Support for a custom OIDC resource metadata's authorization server URL
(cherry picked from commit 9db0d2c)
1 parent 7f3f799 commit 75bf854

File tree

8 files changed

+45
-9
lines changed

8 files changed

+45
-9
lines changed

docs/src/main/asciidoc/security-oidc-expanded-configuration.adoc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1295,6 +1295,7 @@ In turn, a client that requested the protected resource metadata can use its pro
12951295

12961296
|quarkus.oidc.resource-metadata.enabled |false|Enable resource metadata properties
12971297
|quarkus.oidc.resource-metadata.resource ||Resource identifier
1298+
|quarkus.oidc.resource-metadata.authorization-server ||Authorization server URL
12981299
|quarkus.oidc.resource-metadata.force-https-scheme |true|Force that a resource identifier URL has an HTTPS scheme
12991300
|====
13001301

@@ -1307,7 +1308,9 @@ According to the https://datatracker.ietf.org/doc/rfc9728/[OAuth2 Protected Reso
13071308

13081309
If it is configured as a relative path then it is added to the current request URL's host and port to build a resource identifier URL. If it is not configured at all then, unless it is a default tenant id, the tenand id is added to the current request URL's host and port to build a resource identifier URL.
13091310

1310-
In such cases, the `quarkus.oidc.resource-metadata.force-https-scheme` property can be used to set a correct URL scheme, which is set to HTTPS by default.
1311+
The resource identifier URL scheme is set to `HTTPS` by default. You can enable an `HTTP` URL scheme with `quarkus.oidc.resource-metadata.force-https-scheme=false`, it can be particularly useful in simple demos and tests.
1312+
1313+
`quarkus.oidc.resource-metadata.authorization-server` allows to customize an authorization server URL that will be included in the resource metadata. The `quarkus.oidc.auth-server-url` URL is included by default, however, for some cases where an OIDC proxy interposes over the actual OIDC provider, returning the OIDC proxy's URL is required instead.
13111314

13121315
See also the <<oidc-metadata-properties>> for details about the OIDC provider metadata that Quarkus OIDC uses for its work.
13131316

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2751,6 +2751,7 @@ public static class ResourceMetadata implements io.quarkus.oidc.runtime.OidcTena
27512751

27522752
public boolean enabled;
27532753
public Optional<String> resource = Optional.empty();
2754+
public Optional<String> authorizationServer = Optional.empty();
27542755
public boolean forceHttpsScheme = true;
27552756

27562757
@Override
@@ -2763,6 +2764,11 @@ public Optional<String> resource() {
27632764
return resource;
27642765
}
27652766

2767+
@Override
2768+
public Optional<String> authorizationServer() {
2769+
return authorizationServer;
2770+
}
2771+
27662772
@Override
27672773
public boolean forceHttpsScheme() {
27682774
return forceHttpsScheme;
@@ -2771,6 +2777,7 @@ public boolean forceHttpsScheme() {
27712777
private void addConfigMappingValues(io.quarkus.oidc.runtime.OidcTenantConfig.ResourceMetadata mapping) {
27722778
enabled = mapping.enabled();
27732779
resource = mapping.resource();
2780+
authorizationServer = mapping.authorizationServer();
27742781
forceHttpsScheme = mapping.forceHttpsScheme();
27752782
}
27762783
}

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

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -863,12 +863,13 @@ public CertificateChain build() {
863863
public static final class ResourceMetadataBuilder {
864864

865865
private record ResourceMetadataImpl(boolean enabled, Optional<String> resource,
866-
boolean forceHttpsScheme) implements ResourceMetadata {
866+
Optional<String> authorizationServer, boolean forceHttpsScheme) implements ResourceMetadata {
867867
}
868868

869869
private final OidcTenantConfigBuilder builder;
870870
private boolean enabled;
871871
private Optional<String> resource;
872+
private Optional<String> authorizationServer;
872873
private boolean forceHttpsScheme;
873874

874875
public ResourceMetadataBuilder() {
@@ -879,6 +880,7 @@ public ResourceMetadataBuilder(OidcTenantConfigBuilder builder) {
879880
this.builder = Objects.requireNonNull(builder);
880881
this.enabled = builder.resourceMetadata.enabled();
881882
this.resource = builder.resourceMetadata.resource();
883+
this.authorizationServer = builder.resourceMetadata.authorizationServer();
882884
this.forceHttpsScheme = builder.resourceMetadata.forceHttpsScheme();
883885
}
884886

@@ -909,6 +911,15 @@ public ResourceMetadataBuilder resource(String resource) {
909911
return this;
910912
}
911913

914+
/**
915+
* @param resource {@link ResourceMetadata#authorizationServer()}
916+
* @return this builder
917+
*/
918+
public ResourceMetadataBuilder authorizationServer(String authorizationServer) {
919+
this.authorizationServer = Optional.ofNullable(authorizationServer);
920+
return this;
921+
}
922+
912923
/**
913924
* forceHttpsScheme {@link ResourceMetadata#forceHttpsScheme()}
914925
*
@@ -938,7 +949,7 @@ public OidcTenantConfigBuilder end() {
938949
* @return built ResourceMetadata
939950
*/
940951
public ResourceMetadata build() {
941-
return new ResourceMetadataImpl(enabled, resource, forceHttpsScheme);
952+
return new ResourceMetadataImpl(enabled, resource, authorizationServer, forceHttpsScheme);
942953
}
943954
}
944955

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,12 @@ interface ResourceMetadata {
162162
*/
163163
Optional<String> resource();
164164

165+
/**
166+
* Authorization server URL.
167+
* 'quarkus.oidc.auth-server-url' property value is reported by default.
168+
*/
169+
Optional<String> authorizationServer();
170+
165171
/**
166172
* Force a protected resource identifier HTTPS scheme.
167173
* This property is ignored if {@link #resource() is an absolute URL}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,8 @@ private String prepareMetadata(RoutingContext context) {
147147
metadata.put(OidcConstants.RESOURCE_METADATA_RESOURCE, resourceIdentifier);
148148

149149
JsonArray authorizationServers = new JsonArray();
150-
authorizationServers.add(0, oidcConfig.authServerUrl().get());
150+
authorizationServers.add(0, oidcConfig.resourceMetadata().authorizationServer()
151+
.orElse(oidcConfig.authServerUrl().get()));
151152
metadata.put(OidcConstants.RESOURCE_METADATA_AUTHORIZATION_SERVERS, authorizationServers);
152153
return metadata.toString();
153154
}

extensions/oidc/runtime/src/test/java/io/quarkus/oidc/runtime/OidcTenantConfigImpl.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ enum ConfigMappingMethods {
161161
CERTIFICATION_CHAIN_TRUST_STORE_FILE_TYPE,
162162
RESOURCE_METADATA_ENABLED,
163163
RESOURCE_METADATA_RESOURCE,
164+
RESOURCE_METADATA_AUTHORIZATION_SERVER,
164165
RESOURCE_METADATA_FORCE_HTTPS_SCHEME,
165166
LOGOUT_PATH,
166167
LOGOUT_POST_LOGOUT_PATH,
@@ -620,6 +621,12 @@ public Optional<String> resource() {
620621
return Optional.empty();
621622
}
622623

624+
@Override
625+
public Optional<String> authorizationServer() {
626+
invocationsRecorder.put(ConfigMappingMethods.RESOURCE_METADATA_AUTHORIZATION_SERVER, true);
627+
return Optional.empty();
628+
}
629+
623630
@Override
624631
public boolean forceHttpsScheme() {
625632
invocationsRecorder.put(ConfigMappingMethods.RESOURCE_METADATA_FORCE_HTTPS_SCHEME, true);

integration-tests/oidc-code-flow/src/main/resources/application.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ quarkus.oidc.tenant-nonce.token-state-manager.encryption-required=false
138138
quarkus.oidc.tenant-nonce.token.allow-jwt-introspection=false
139139
quarkus.oidc.tenant-nonce.resource-metadata.enabled=true
140140
quarkus.oidc.tenant-nonce.resource-metadata.resource=/metadata
141+
quarkus.oidc.tenant-nonce.resource-metadata.authorization-server=http://localhost:8080/q/oidc
141142

142143
quarkus.oidc.tenant-javascript.auth-server-url=${quarkus.oidc.auth-server-url}
143144
quarkus.oidc.tenant-javascript.client-id=quarkus-app

integration-tests/oidc-code-flow/src/test/java/io/quarkus/it/keycloak/CodeFlowTest.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ public void testCodeFlowNoConsent() throws IOException {
150150
checkHealth();
151151

152152
// Static default tenant
153-
checkResourceMetadata(null, "quarkus");
153+
checkResourceMetadata(null, "/realms/quarkus");
154154
}
155155
}
156156

@@ -465,7 +465,7 @@ public void testCodeFlowNonce() throws Exception {
465465
assertEquals("Unexpected 401", ex.getMessage());
466466
}
467467
// Static `tenant-nonce` tenant with custom resource path
468-
checkResourceMetadata("metadata", "quarkus");
468+
checkResourceMetadata("metadata", ":8080/q/oidc");
469469
}
470470

471471
private void doTestCodeFlowNonce(boolean wrongRedirect) throws Exception {
@@ -869,7 +869,7 @@ public Boolean call() throws Exception {
869869
webClient.getCookieManager().clearCookies();
870870

871871
// Static `tenant-refresh` tenant
872-
checkResourceMetadata("tenant-refresh", "logout-realm");
872+
checkResourceMetadata("tenant-refresh", "/realms/logout-realm");
873873
}
874874
}
875875

@@ -1762,7 +1762,7 @@ private String getIdToken(Cookie sessionCookie) {
17621762
return sessionCookie.getValue().split("\\|")[0];
17631763
}
17641764

1765-
private static void checkResourceMetadata(String resource, String realm) {
1765+
private static void checkResourceMetadata(String resource, String authorizationServerSuffix) {
17661766
Response metadataResponse = RestAssured.when()
17671767
.get("http://localhost:8081" + OidcConstants.RESOURCE_METADATA_WELL_KNOWN_PATH
17681768
+ (resource == null ? "" : "/" + resource));
@@ -1774,6 +1774,6 @@ private static void checkResourceMetadata(String resource, String realm) {
17741774

17751775
String authorizationServer = jsonAuthorizarionServers.getString(0);
17761776
assertTrue(authorizationServer.startsWith("http://localhost:"));
1777-
assertTrue(authorizationServer.endsWith("/realms/" + realm));
1777+
assertTrue(authorizationServer.endsWith(authorizationServerSuffix));
17781778
}
17791779
}

0 commit comments

Comments
 (0)