diff --git a/docs/src/main/asciidoc/security-openid-connect-web-authentication.adoc b/docs/src/main/asciidoc/security-openid-connect-web-authentication.adoc index fac0fe4a7031a..20e7b53d50e7d 100644 --- a/docs/src/main/asciidoc/security-openid-connect-web-authentication.adoc +++ b/docs/src/main/asciidoc/security-openid-connect-web-authentication.adoc @@ -273,15 +273,13 @@ If `quarkus.oidc.authentication.redirect-path` is set but the original request U The OIDC adapter uses cookies to keep the session, code flow and post logout state. -If you access the protected resources with overlapping or different roots, for example: +`quarkus.oidc.authentication.cookie-path` property is used to ensure the cookies are visible especially when you access the protected resources with overlapping or different roots, for example: * `/index.html` and `/web-app/service` * `/web-app/service1` and `/web-app/service2` * `/web-app1/service` and `/web-app2/service` -then most likely you also need to set a `quarkus.oidc.authentication.cookie-path` property to a path value that is common to all of them, such as `/` or `/web-app`, etc. - -Otherwise the browser cache manager may keep request path specific cookies which in turn may lead to some difficult to diagnoze errors. For example, an authorization code flow may fail due to a missing state cookie if a user has initially accessed `/index.html` but configured a callback URI to `/web-app/callback`. +`quarkus.oidc.authentication.cookie-path` is set to `/` by default but can be narrowed to the more specific root path such as `/web-app`. You can also set a `quarkus.oidc.authentication.cookie-path-header` property if the cookie path needs to be set dynamically. For example, setting `quarkus.oidc.authentication.cookie-path-header=X-Forwarded-Prefix` means that the value of HTTP `X-Forwarded-Prefix` header will be used to set a cookie path. diff --git a/extensions/oidc-client/runtime/src/main/java/io/quarkus/oidc/client/runtime/OidcClientRecorder.java b/extensions/oidc-client/runtime/src/main/java/io/quarkus/oidc/client/runtime/OidcClientRecorder.java index 9c28f7741aeb5..7ea0df89b5fcf 100644 --- a/extensions/oidc-client/runtime/src/main/java/io/quarkus/oidc/client/runtime/OidcClientRecorder.java +++ b/extensions/oidc-client/runtime/src/main/java/io/quarkus/oidc/client/runtime/OidcClientRecorder.java @@ -97,7 +97,7 @@ protected static Uni createOidcClientUni(OidcClientConfig oidcConfig oidcConfig.setId(oidcClientId); } - OidcCommonUtils.verifyCommonConfiguration(oidcConfig); + OidcCommonUtils.verifyCommonConfiguration(oidcConfig, false); String authServerUriString = OidcCommonUtils.getAuthServerUrl(oidcConfig); diff --git a/extensions/oidc-common/runtime/src/main/java/io/quarkus/oidc/common/runtime/OidcCommonUtils.java b/extensions/oidc-common/runtime/src/main/java/io/quarkus/oidc/common/runtime/OidcCommonUtils.java index a560416d6e387..a694ad270cca7 100644 --- a/extensions/oidc-common/runtime/src/main/java/io/quarkus/oidc/common/runtime/OidcCommonUtils.java +++ b/extensions/oidc-common/runtime/src/main/java/io/quarkus/oidc/common/runtime/OidcCommonUtils.java @@ -28,19 +28,24 @@ private OidcCommonUtils() { } - public static void verifyCommonConfiguration(OidcCommonConfig oidcConfig) { + public static void verifyCommonConfiguration(OidcCommonConfig oidcConfig, boolean isServerConfig) { + final String configPrefix = isServerConfig ? "quarkus.oidc." : "quarkus.oidc-client."; if (!oidcConfig.getAuthServerUrl().isPresent() || !oidcConfig.getClientId().isPresent()) { - throw new ConfigurationException("Both 'auth-server-url' and 'client-id' properties must be configured"); + throw new ConfigurationException( + String.format("Both '%sauth-server-url' and '%sclient-id' properties must be configured", configPrefix)); } Credentials creds = oidcConfig.getCredentials(); if (creds.secret.isPresent() && creds.clientSecret.value.isPresent()) { throw new ConfigurationException( - "'credentials.secret' and 'credentials.client-secret' properties are mutually exclusive"); + String.format("'%scredentials.secret' and '%scredentials.client-secret' properties are mutually exclusive", + configPrefix)); } if ((creds.secret.isPresent() || creds.clientSecret.value.isPresent()) && creds.jwt.secret.isPresent()) { throw new ConfigurationException( - "Use only 'credentials.secret' or 'credentials.client-secret' or 'credentials.jwt.secret' property"); + String.format( + "Use only '%scredentials.secret' or '%scredentials.client-secret' or '%scredentials.jwt.secret' property", + configPrefix)); } } diff --git a/extensions/oidc/deployment/src/main/java/io/quarkus/oidc/deployment/OidcBuildStep.java b/extensions/oidc/deployment/src/main/java/io/quarkus/oidc/deployment/OidcBuildStep.java index 7ca3a549667d9..780907c2d5b43 100644 --- a/extensions/oidc/deployment/src/main/java/io/quarkus/oidc/deployment/OidcBuildStep.java +++ b/extensions/oidc/deployment/src/main/java/io/quarkus/oidc/deployment/OidcBuildStep.java @@ -30,6 +30,7 @@ import io.quarkus.oidc.runtime.OidcAuthenticationMechanism; import io.quarkus.oidc.runtime.OidcBuildTimeConfig; import io.quarkus.oidc.runtime.OidcConfig; +import io.quarkus.oidc.runtime.OidcConfigurationMetadataProducer; import io.quarkus.oidc.runtime.OidcIdentityProvider; import io.quarkus.oidc.runtime.OidcJsonWebTokenProducer; import io.quarkus.oidc.runtime.OidcRecorder; @@ -72,6 +73,7 @@ public void additionalBeans(BuildProducer additionalBea builder.addBeanClass(OidcAuthenticationMechanism.class) .addBeanClass(OidcJsonWebTokenProducer.class) .addBeanClass(OidcTokenCredentialProducer.class) + .addBeanClass(OidcConfigurationMetadataProducer.class) .addBeanClass(OidcIdentityProvider.class) .addBeanClass(DefaultTenantConfigResolver.class) .addBeanClass(DefaultTokenStateManager.class); diff --git a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/OidcConfigurationMetadata.java b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/OidcConfigurationMetadata.java index 00c6aa56c1817..b458566d91b47 100644 --- a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/OidcConfigurationMetadata.java +++ b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/OidcConfigurationMetadata.java @@ -1,5 +1,8 @@ package io.quarkus.oidc; +import java.util.Collections; +import java.util.Set; + import io.vertx.core.json.JsonObject; public class OidcConfigurationMetadata { @@ -18,6 +21,7 @@ public class OidcConfigurationMetadata { private final String userInfoUri; private final String endSessionUri; private final String issuer; + private JsonObject json; public OidcConfigurationMetadata(String tokenUri, String introspectionUri, @@ -43,6 +47,7 @@ public OidcConfigurationMetadata(JsonObject wellKnownConfig) { this.userInfoUri = wellKnownConfig.getString(USERINFO_ENDPOINT); this.endSessionUri = wellKnownConfig.getString(END_SESSION_ENDPOINT); this.issuer = wellKnownConfig.getString(ISSUER); + this.json = wellKnownConfig; } public String getTokenUri() { @@ -72,4 +77,16 @@ public String getEndSessionUri() { public String getIssuer() { return issuer; } + + public String get(String propertyName) { + return json != null ? null : json.getString(propertyName); + } + + public boolean contains(String propertyName) { + return json.containsKey(propertyName); + } + + public Set getPropertyNames() { + return Collections.unmodifiableSet(json.fieldNames()); + } } diff --git a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/OidcTenantConfig.java b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/OidcTenantConfig.java index 2dff9fbce3b9d..392c7470dfad1 100644 --- a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/OidcTenantConfig.java +++ b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/OidcTenantConfig.java @@ -390,7 +390,8 @@ public static class Authentication { * For example, if the current request URI is 'https://localhost:8080/service' then a 'redirect_uri' parameter * will be set to 'https://localhost:8080/' if this property is set to '/' and be the same as the request URI * if this property has not been configured. - * Note the original request URI will be restored after the user has authenticated. + * Note the original request URI will be restored after the user has authenticated if 'restorePathAfterRedirect' is set + * to 'true'. */ @ConfigItem public Optional redirectPath = Optional.empty(); @@ -398,9 +399,12 @@ public static class Authentication { /** * If this property is set to 'true' then the original request URI which was used before * the authentication will be restored after the user has been redirected back to the application. + * + * Note if `redirectPath` property is not set the the original request URI will be restored even if this property is + * disabled. */ - @ConfigItem(defaultValue = "true") - public boolean restorePathAfterRedirect = true; + @ConfigItem(defaultValue = "false") + public boolean restorePathAfterRedirect; /** * Remove the query parameters such as 'code' and 'state' set by the OIDC server on the redirect URI @@ -457,8 +461,8 @@ public static class Authentication { * logout cookies. * The `cookie-path-header` property, if set, will be checked first. */ - @ConfigItem - public Optional cookiePath = Optional.empty(); + @ConfigItem(defaultValue = "/") + public String cookiePath = "/"; /** * Cookie path header parameter value which, if set, identifies the incoming HTTP header @@ -559,12 +563,12 @@ public void setCookieForceSecure(boolean cookieForceSecure) { this.cookieForceSecure = cookieForceSecure; } - public Optional getCookiePath() { + public String getCookiePath() { return cookiePath; } public void setCookiePath(String cookiePath) { - this.cookiePath = Optional.of(cookiePath); + this.cookiePath = cookiePath; } public Optional getCookieDomain() { diff --git a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/CodeAuthenticationMechanism.java b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/CodeAuthenticationMechanism.java index 4aadb47296f8e..fa5aeba7b3e38 100644 --- a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/CodeAuthenticationMechanism.java +++ b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/CodeAuthenticationMechanism.java @@ -394,7 +394,8 @@ private String generateCodeFlowState(RoutingContext context, TenantConfigContext String cookieValue = uuid; Authentication auth = configContext.oidcConfig.getAuthentication(); - if (auth.isRestorePathAfterRedirect()) { + boolean restorePath = auth.isRestorePathAfterRedirect() || !auth.redirectPath.isPresent(); + if (restorePath) { String requestQuery = context.request().query(); String requestPath = !redirectPath.equals(context.request().path()) || requestQuery != null ? context.request().path() @@ -436,8 +437,8 @@ static ServerCookie createCookie(RoutingContext context, OidcTenantConfig oidcCo static void setCookiePath(RoutingContext context, Authentication auth, ServerCookie cookie) { if (auth.cookiePathHeader.isPresent() && context.request().headers().contains(auth.cookiePathHeader.get())) { cookie.setPath(context.request().getHeader(auth.cookiePathHeader.get())); - } else if (auth.cookiePath.isPresent()) { - cookie.setPath(auth.getCookiePath().get()); + } else { + cookie.setPath(auth.getCookiePath()); } } diff --git a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcConfigurationMetadataProducer.java b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcConfigurationMetadataProducer.java new file mode 100644 index 0000000000000..5a0b8675b36eb --- /dev/null +++ b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcConfigurationMetadataProducer.java @@ -0,0 +1,26 @@ +package io.quarkus.oidc.runtime; + +import javax.enterprise.context.RequestScoped; +import javax.enterprise.inject.Produces; +import javax.inject.Inject; + +import io.quarkus.oidc.OIDCException; +import io.quarkus.oidc.OidcConfigurationMetadata; +import io.quarkus.security.identity.SecurityIdentity; + +@RequestScoped +public class OidcConfigurationMetadataProducer { + @Inject + SecurityIdentity identity; + + @Produces + @RequestScoped + OidcConfigurationMetadata produce() { + OidcConfigurationMetadata configMetadata = (OidcConfigurationMetadata) identity + .getAttribute(OidcUtils.CONFIG_METADATA_ATTRIBUTE); + if (configMetadata == null) { + throw new OIDCException("OidcConfigurationMetadata can not be injected"); + } + return configMetadata; + } +} diff --git a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcIdentityProvider.java b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcIdentityProvider.java index 38992f6d3e7d2..c81332c40a3f2 100644 --- a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcIdentityProvider.java +++ b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcIdentityProvider.java @@ -149,8 +149,7 @@ public Uni apply(TokenVerificationResult result, Throwable t) JsonObject rolesJson = getRolesJson(vertxContext, resolvedContext, tokenCred, tokenJson, userInfo); SecurityIdentity securityIdentity = validateAndCreateIdentity(vertxContext, tokenCred, - resolvedContext.oidcConfig, - tokenJson, rolesJson, userInfo); + resolvedContext, tokenJson, rolesJson, userInfo); if (tokenAutoRefreshPrepared(tokenJson, vertxContext, resolvedContext.oidcConfig)) { return Uni.createFrom().failure(new TokenAutoRefreshException(securityIdentity)); } else { @@ -169,9 +168,7 @@ public Uni apply(TokenVerificationResult result, Throwable t) QuarkusSecurityIdentity.Builder builder = QuarkusSecurityIdentity.builder(); builder.addCredential(tokenCred); OidcUtils.setSecurityIdentityUserInfo(builder, userInfo); - - // getRolesJson: make sure the introspection is picked up correctly - // OidcRuntimeClient.verifyCodeToken - set the introspection there - which may be ambiguous + OidcUtils.setSecurityIdentityConfigMetadata(builder, resolvedContext); if (result.introspectionResult.containsKey(OidcConstants.INTROSPECTION_TOKEN_USERNAME)) { final String userName = result.introspectionResult .getString(OidcConstants.INTROSPECTION_TOKEN_USERNAME); @@ -289,7 +286,7 @@ private static Uni validateTokenWithoutOidcServer(TokenAuthent try { TokenVerificationResult result = resolvedContext.provider.verifyJwtToken(request.getToken().getToken()); return Uni.createFrom() - .item(validateAndCreateIdentity(null, request.getToken(), resolvedContext.oidcConfig, + .item(validateAndCreateIdentity(null, request.getToken(), resolvedContext, result.localVerificationResult, result.localVerificationResult, null)); } catch (Throwable t) { return Uni.createFrom().failure(new AuthenticationFailedException(t)); diff --git a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcProvider.java b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcProvider.java index 0474a35fb3f2e..dbf64bacd7c9f 100644 --- a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcProvider.java +++ b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcProvider.java @@ -34,9 +34,9 @@ public class OidcProvider { private static final Logger LOG = Logger.getLogger(OidcProvider.class); - private final OidcProviderClient client; - private final RefreshableVerificationKeyResolver keyResolver; - private final OidcTenantConfig oidcConfig; + final OidcProviderClient client; + final RefreshableVerificationKeyResolver keyResolver; + final OidcTenantConfig oidcConfig; public OidcProvider(OidcProviderClient client, OidcTenantConfig oidcConfig, JsonWebKeyCache jwks) { this.client = client; diff --git a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcRecorder.java b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcRecorder.java index e6bb891ba3295..870965b1d1843 100644 --- a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcRecorder.java +++ b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcRecorder.java @@ -114,7 +114,7 @@ private Uni createTenantContext(Vertx vertx, OidcTenantConf return Uni.createFrom().item(createTenantContextFromPublicKey(oidcConfig)); } - OidcCommonUtils.verifyCommonConfiguration(oidcConfig); + OidcCommonUtils.verifyCommonConfiguration(oidcConfig, true); if (!oidcConfig.discoveryEnabled) { if (oidcConfig.applicationType != ApplicationType.SERVICE) { @@ -213,8 +213,6 @@ public OidcProvider apply(JsonWebKeyCache jwks) { protected static Uni createOidcClientUni(OidcTenantConfig oidcConfig, TlsConfig tlsConfig, Vertx vertx) { - OidcCommonUtils.verifyCommonConfiguration(oidcConfig); - String authServerUriString = OidcCommonUtils.getAuthServerUrl(oidcConfig); WebClientOptions options = new WebClientOptions(); diff --git a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcTokenCredentialProducer.java b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcTokenCredentialProducer.java index 55d946ac6fff2..07b76d1c0df0b 100644 --- a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcTokenCredentialProducer.java +++ b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcTokenCredentialProducer.java @@ -65,7 +65,7 @@ RefreshToken currentRefreshToken() { @Produces @RequestScoped UserInfo currentUserInfo() { - UserInfo userInfo = (UserInfo) identity.getAttribute("userinfo"); + UserInfo userInfo = (UserInfo) identity.getAttribute(OidcUtils.USER_INFO_ATTRIBUTE); if (userInfo == null) { throw new OIDCException("UserInfo can not be injected"); } diff --git a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcUtils.java b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcUtils.java index 84f8feaf43ca7..8d7add91f246d 100644 --- a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcUtils.java +++ b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcUtils.java @@ -28,6 +28,9 @@ import io.vertx.ext.web.RoutingContext; public final class OidcUtils { + static final String CONFIG_METADATA_ATTRIBUTE = "configuration-metadata"; + static final String USER_INFO_ATTRIBUTE = "userinfo"; + static final String TENANT_ID_ATTRIBUTE = "tenant-id"; /** * This pattern uses a positive lookahead to split an expression around the forward slashes * ignoring those which are located inside a pair of the double quotes. @@ -133,8 +136,9 @@ private static List convertJsonArrayToList(JsonArray claimValue) { static QuarkusSecurityIdentity validateAndCreateIdentity( RoutingContext vertxContext, TokenCredential credential, - OidcTenantConfig config, JsonObject tokenJson, JsonObject rolesJson, JsonObject userInfo) { + TenantConfigContext resolvedContext, JsonObject tokenJson, JsonObject rolesJson, JsonObject userInfo) { + OidcTenantConfig config = resolvedContext.oidcConfig; QuarkusSecurityIdentity.Builder builder = QuarkusSecurityIdentity.builder(); builder.addCredential(credential); @@ -150,6 +154,7 @@ static QuarkusSecurityIdentity validateAndCreateIdentity( builder.setPrincipal(jwtPrincipal); setSecurityIdentityRoles(builder, config, rolesJson); setSecurityIdentityUserInfo(builder, userInfo); + setSecurityIdentityConfigMetadata(builder, resolvedContext); setBlockinApiAttribute(builder, vertxContext); setTenantIdAttribute(builder, config); return builder.build(); @@ -175,12 +180,19 @@ public static void setBlockinApiAttribute(QuarkusSecurityIdentity.Builder builde } public static void setTenantIdAttribute(QuarkusSecurityIdentity.Builder builder, OidcTenantConfig config) { - builder.addAttribute("tenant-id", config.tenantId.orElse("Default")); + builder.addAttribute(TENANT_ID_ATTRIBUTE, config.tenantId.orElse("Default")); } public static void setSecurityIdentityUserInfo(QuarkusSecurityIdentity.Builder builder, JsonObject userInfo) { if (userInfo != null) { - builder.addAttribute("userinfo", new UserInfo(userInfo.encode())); + builder.addAttribute(USER_INFO_ATTRIBUTE, new UserInfo(userInfo.encode())); + } + } + + public static void setSecurityIdentityConfigMetadata(QuarkusSecurityIdentity.Builder builder, + TenantConfigContext resolvedContext) { + if (resolvedContext.provider.client != null) { + builder.addAttribute(CONFIG_METADATA_ATTRIBUTE, resolvedContext.provider.client.getMetadata()); } } diff --git a/integration-tests/oidc-code-flow/src/main/java/io/quarkus/it/keycloak/ProtectedResource.java b/integration-tests/oidc-code-flow/src/main/java/io/quarkus/it/keycloak/ProtectedResource.java index 6317279cec474..a4207bea1dbee 100644 --- a/integration-tests/oidc-code-flow/src/main/java/io/quarkus/it/keycloak/ProtectedResource.java +++ b/integration-tests/oidc-code-flow/src/main/java/io/quarkus/it/keycloak/ProtectedResource.java @@ -14,6 +14,7 @@ import io.quarkus.oidc.IdToken; import io.quarkus.oidc.IdTokenCredential; import io.quarkus.oidc.OIDCException; +import io.quarkus.oidc.OidcConfigurationMetadata; import io.quarkus.oidc.RefreshToken; import io.quarkus.security.Authenticated; import io.quarkus.security.identity.SecurityIdentity; @@ -26,6 +27,9 @@ public class ProtectedResource { @Inject SecurityIdentity identity; + @Inject + OidcConfigurationMetadata configMetadata; + @Inject @IdToken JsonWebToken idToken; @@ -51,6 +55,12 @@ public String hello() { return securityContext.getUserPrincipal().getName(); } + @GET + @Path("configMetadataIssuer") + public String configMetadataIssuer() { + return configMetadata.getIssuer(); + } + @GET public String getName() { if (!idTokenCredential.getToken().equals(idToken.getRawToken())) { diff --git a/integration-tests/oidc-code-flow/src/main/resources/application.properties b/integration-tests/oidc-code-flow/src/main/resources/application.properties index d2be71801c786..13c04a9328fbd 100644 --- a/integration-tests/oidc-code-flow/src/main/resources/application.properties +++ b/integration-tests/oidc-code-flow/src/main/resources/application.properties @@ -4,10 +4,7 @@ quarkus.oidc.client-id=quarkus-app quarkus.oidc.credentials.secret=secret quarkus.oidc.authentication.scopes=profile,email,phone quarkus.oidc.authentication.redirect-path=/web-app -# Several tests here start from /index.html (state cookie is available) -# and next they try /web-app/* (when a state cookie might not be available) -# Adding 'cookie-path=/' may prevent the intermittent CI failures to do with the missing state cookie -quarkus.oidc.authentication.cookie-path=/ +quarkus.oidc.authentication.restore-path-after-redirect=true quarkus.oidc.authentication.cookie-path-header=some-header quarkus.oidc.authentication.cookie-domain=localhost quarkus.oidc.authentication.extra-params.max-age=60 @@ -17,7 +14,6 @@ quarkus.oidc.application-type=web-app quarkus.oidc.tenant-listener.auth-server-url=${keycloak.url}/realms/quarkus quarkus.oidc.tenant-listener.client-id=quarkus-app quarkus.oidc.tenant-listener.credentials.secret=secret -quarkus.oidc.tenant-listener.authentication.cookie-path=/ # Redirect parameters are dropped by redirecting the authenticated user but this final redirect loses the login event message # on Vertx context; so disabling it for the test endpoint to confirm the login event has been accepted quarkus.oidc.tenant-listener.authentication.remove-redirect-parameters=false @@ -37,7 +33,6 @@ quarkus.oidc.tenant-1.credentials.client-secret.value=secret quarkus.oidc.tenant-1.credentials.client-secret.method=post quarkus.oidc.tenant-1.token.issuer=${keycloak.url}/realms/quarkus quarkus.oidc.tenant-1.authentication.redirect-path=/web-app/callback-after-redirect -quarkus.oidc.tenant-1.authentication.restore-path-after-redirect=false quarkus.oidc.tenant-1.application-type=web-app # Tenant with client which needs to use client_secret_jwt method @@ -46,7 +41,6 @@ quarkus.oidc.tenant-jwt.client-id=quarkus-app-jwt quarkus.oidc.tenant-jwt.credentials.jwt.secret=AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow quarkus.oidc.tenant-jwt.token.issuer=${keycloak.url}/realms/quarkus quarkus.oidc.tenant-jwt.authentication.redirect-path=/web-app/callback-jwt-after-redirect -quarkus.oidc.tenant-jwt.authentication.restore-path-after-redirect=false quarkus.oidc.tenant-jwt.application-type=web-app # Tenant with client which needs to use client_secret_jwt but uses client_secret_post @@ -56,7 +50,6 @@ quarkus.oidc.tenant-jwt-not-used.credentials.client-secret.value=AyM1SysPpbyDfgZ quarkus.oidc.tenant-jwt-not-used.credentials.client-secret.method=post quarkus.oidc.tenant-jwt-not-used.token.issuer=${keycloak.url}/realms/quarkus quarkus.oidc.tenant-jwt-not-used.authentication.redirect-path=/web-app/callback-jwt-not-used-after-redirect -quarkus.oidc.tenant-jwt-not-used.authentication.restore-path-after-redirect=false quarkus.oidc.tenant-jwt-not-used.application-type=web-app # Tenant which does not need to restore a request path after redirect with a different redirect path root @@ -65,7 +58,6 @@ quarkus.oidc.tenant-2.client-id=quarkus-app quarkus.oidc.tenant-2.credentials.client-secret.value=secret quarkus.oidc.tenant-2.token.issuer=${keycloak.url}/realms/quarkus quarkus.oidc.tenant-2.authentication.redirect-path=/web-app2/name -quarkus.oidc.tenant-2.authentication.restore-path-after-redirect=false quarkus.oidc.tenant-2.authentication.cookie-path=/web-app2 quarkus.oidc.tenant-2.application-type=web-app @@ -75,7 +67,6 @@ quarkus.oidc.tenant-3.client-id=quarkus-app quarkus.oidc.tenant-3.credentials.secret=secret quarkus.oidc.tenant-3.token.issuer=${keycloak.url}/realms/quarkus quarkus.oidc.tenant-3.authentication.redirect-path=/web-app3 -quarkus.oidc.tenant-3.authentication.restore-path-after-redirect=false quarkus.oidc.tenant-3.application-type=web-app quarkus.oidc.tenant-logout.auth-server-url=${keycloak.url}/realms/logout-realm @@ -101,7 +92,6 @@ quarkus.oidc.tenant-https.auth-server-url=${keycloak.url}/realms/quarkus quarkus.oidc.tenant-https.client-id=quarkus-app quarkus.oidc.tenant-https.credentials.secret=secret quarkus.oidc.tenant-https.authentication.scopes=profile,email,phone -quarkus.oidc.tenant-https.authentication.cookie-path=/ quarkus.oidc.tenant-https.authentication.extra-params.max-age=60 quarkus.oidc.tenant-https.application-type=web-app quarkus.oidc.tenant-https.authentication.force-redirect-https-scheme=true diff --git a/integration-tests/oidc-code-flow/src/test/java/io/quarkus/it/keycloak/CodeFlowTest.java b/integration-tests/oidc-code-flow/src/test/java/io/quarkus/it/keycloak/CodeFlowTest.java index ffc915f226737..e279cad783488 100644 --- a/integration-tests/oidc-code-flow/src/test/java/io/quarkus/it/keycloak/CodeFlowTest.java +++ b/integration-tests/oidc-code-flow/src/test/java/io/quarkus/it/keycloak/CodeFlowTest.java @@ -66,6 +66,13 @@ public void testCodeFlowNoConsent() throws IOException { assertEquals("Welcome to Test App", page.getTitleText(), "A second request should not redirect and just re-authenticate the user"); + + page = webClient.getPage("http://localhost:8081/web-app/configMetadataIssuer"); + + assertEquals( + KeycloakRealmResourceManager.KEYCLOAK_SERVER_URL + "/realms/" + KeycloakRealmResourceManager.KEYCLOAK_REALM, + page.asText()); + webClient.getCookieManager().clearCookies(); } } diff --git a/integration-tests/oidc-code-flow/src/test/java/io/quarkus/it/keycloak/KeycloakRealmResourceManager.java b/integration-tests/oidc-code-flow/src/test/java/io/quarkus/it/keycloak/KeycloakRealmResourceManager.java index bc49802bf10e1..6d5321ce0a42f 100644 --- a/integration-tests/oidc-code-flow/src/test/java/io/quarkus/it/keycloak/KeycloakRealmResourceManager.java +++ b/integration-tests/oidc-code-flow/src/test/java/io/quarkus/it/keycloak/KeycloakRealmResourceManager.java @@ -21,8 +21,8 @@ public class KeycloakRealmResourceManager implements QuarkusTestResourceLifecycleManager { - private static final String KEYCLOAK_SERVER_URL = System.getProperty("keycloak.url", "http://localhost:8180/auth"); - private static final String KEYCLOAK_REALM = "quarkus"; + public static final String KEYCLOAK_SERVER_URL = System.getProperty("keycloak.url", "http://localhost:8180/auth"); + public static final String KEYCLOAK_REALM = "quarkus"; private List realms = new ArrayList<>(); @Override