From e72472f28cee16b706849b1d97d4c2893a761023 Mon Sep 17 00:00:00 2001 From: Sergey Beryozkin Date: Mon, 16 Dec 2024 13:33:23 +0000 Subject: [PATCH] Update OIDC bearer doc with a section about response filters --- ...rity-oidc-bearer-token-authentication.adoc | 43 +++++++++++++++++++ ...ecurity-oidc-code-flow-authentication.adoc | 8 ++-- 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/docs/src/main/asciidoc/security-oidc-bearer-token-authentication.adoc b/docs/src/main/asciidoc/security-oidc-bearer-token-authentication.adoc index a91d02726b3a3..bc2a4fcecd343 100644 --- a/docs/src/main/asciidoc/security-oidc-bearer-token-authentication.adoc +++ b/docs/src/main/asciidoc/security-oidc-bearer-token-authentication.adoc @@ -1346,6 +1346,49 @@ Authentication that requires a dynamic tenant will fail. You can filter OIDC requests made by Quarkus to the OIDC provider by registering one or more `OidcRequestFilter` implementations, which can update or add new request headers, and log requests. For more information, see xref:security-oidc-code-flow-authentication#code-flow-oidc-request-filters[OIDC request filters]. +[[bearer-token-oidc-response-filters]] +=== OIDC response filters + +You can filter responses from the OIDC providers by registering one or more `OidcResponseFilter` implementations, which can check the response status, headers and body in order to log them or perform other actions. + +You can have a single filter intercepting all the OIDC responses, or use an `@OidcEndpoint` annotation to apply this filter to the specific endpoint responses only. For example: + +[source,java] +---- +package io.quarkus.it.keycloak; + +import jakarta.enterprise.context.ApplicationScoped; + +import io.quarkus.arc.Unremovable; +import io.quarkus.logging.Log; +import io.quarkus.oidc.common.OidcEndpoint; +import io.quarkus.oidc.common.OidcEndpoint.Type; +import io.quarkus.oidc.common.OidcResponseFilter; +import io.quarkus.oidc.common.runtime.OidcConstants; +import io.quarkus.oidc.runtime.OidcUtils; + +@ApplicationScoped +@Unremovable +@OidcEndpoint(value = Type.DISCOVERY) <1> +public class DiscoveryEndpointResponseFilter implements OidcResponseFilter { + + @Override + public void filter(OidcResponseContext rc) { + String contentType = rc.responseHeaders().get("Content-Type"); <2> + if (contentType.equals("application/json") { + String tenantId = rc.requestProperties().get(OidcUtils.TENANT_ID_ATTRIBUTE); <3> + String metadata = rc.responseBody().toString(); <4> + Log.debugf("Tenant %s OIDC metadata: %s", tenantId, metadata); + } + } +} + +---- +<1> Restrict this filter to requests targeting the OIDC discovery endpoint only. +<2> Check the response `Content-Type` header. +<3> Use `OidcRequestContextProperties` request properties to get the tenant id. +<4> Get the response data as String. + == References * xref:security-oidc-configuration-properties-reference.adoc[OIDC configuration properties] diff --git a/docs/src/main/asciidoc/security-oidc-code-flow-authentication.adoc b/docs/src/main/asciidoc/security-oidc-code-flow-authentication.adoc index b20907196ff14..dc57ffe76c4af 100644 --- a/docs/src/main/asciidoc/security-oidc-code-flow-authentication.adoc +++ b/docs/src/main/asciidoc/security-oidc-code-flow-authentication.adoc @@ -392,9 +392,8 @@ package io.quarkus.it.keycloak; import jakarta.enterprise.context.ApplicationScoped; -import org.jboss.logging.Logger; - import io.quarkus.arc.Unremovable; +import io.quarkus.logging.Log; import io.quarkus.oidc.common.OidcEndpoint; import io.quarkus.oidc.common.OidcEndpoint.Type; import io.quarkus.oidc.common.OidcResponseFilter; @@ -405,8 +404,7 @@ import io.quarkus.oidc.runtime.OidcUtils; @Unremovable @OidcEndpoint(value = Type.TOKEN) <1> public class TokenEndpointResponseFilter implements OidcResponseFilter { - private static final Logger LOG = Logger.getLogger(TokenResponseFilter.class); - + @Override public void filter(OidcResponseContext rc) { String contentType = rc.responseHeaders().get("Content-Type"); <2> @@ -414,7 +412,7 @@ public class TokenEndpointResponseFilter implements OidcResponseFilter { && OidcConstants.AUTHORIZATION_CODE.equals(rc.requestProperties().get(OidcConstants.GRANT_TYPE)) <3> && "code-flow-user-info-cached-in-idtoken".equals(rc.requestProperties().get(OidcUtils.TENANT_ID_ATTRIBUTE)) <3> && rc.responseBody().toJsonObject().containsKey("id_token")) { <4> - LOG.debug("Authorization code completed for tenant 'code-flow-user-info-cached-in-idtoken'"); + Log.debug("Authorization code completed for tenant 'code-flow-user-info-cached-in-idtoken'"); } } }