diff --git a/docs/src/main/asciidoc/security-openid-connect-client.adoc b/docs/src/main/asciidoc/security-openid-connect-client.adoc index c83c738171186..f0714df598d15 100644 --- a/docs/src/main/asciidoc/security-openid-connect-client.adoc +++ b/docs/src/main/asciidoc/security-openid-connect-client.adoc @@ -596,15 +596,17 @@ quarkus.oidc-client.token-path=/protocol/openid-connect/tokens [[token-propagation]] == Token Propagation in MicroProfile RestClient client filter -`quarkus-oidc-token-propagation` extension provide `io.quarkus.oidc.token.propagation.AccessTokenRequestFilter` and `io.quarkus.oidc.token.propagation.JsonWebTokenRequestFilter` JAX-RS ClientRequestFilters which propagates the current link:security-openid-connect[Bearer] or link:security-openid-connect-web-authentication[Authorization Code Flow] access token as an HTTP `Authorization` `Bearer` scheme value. +The `quarkus-oidc-token-propagation` extension provides two JAX-RS `javax.ws.rs.client.ClientRequestFilter` class implementations that simplify the propagation of authentication information. +`io.quarkus.oidc.token.propagation.AccessTokenRequestFilter` propagates the link:security-openid-connect[Bearer] token present in the current active request or the token acquired from the link:security-openid-connect-web-authentication[Authorization Code Flow], as the HTTP `Authorization` header's `Bearer` scheme value. +The `io.quarkus.oidc.token.propagation.JsonWebTokenRequestFilter` provides the same functionality, but in addition provides support for JWT tokens. When you need to propagate the current Authorization Code Flow access token then the immediate token propagation will work well - as the code flow access tokens (as opposed to ID tokens) are meant to be propagated for the current Quarkus endpoint to access the remote services on behalf of the currently authenticated user. However, the direct end to end Bearer token propagation should be avoided if possible. For example, `Client -> Service A -> Service B` where `Service B` receives a token sent by `Client` to `Service A`. In such cases `Service B` will not be able to distinguish if the token came from `Service A` or from `Client` directly. For `Service B` to verify the token came from `Service A` it should be able to assert a new issuer and audience claims. -Additionally, a complex application may need to exchange or update the tokens before propagating them. For example, the access context might be different when Service A is accessing Service B. In this case, Service A might be granted a narrow or a completely different set of scopes to access Service B. +Additionally, a complex application may need to exchange or update the tokens before propagating them. For example, the access context might be different when `Service A` is accessing `Service B`. In this case, `Service A` might be granted a narrow or a completely different set of scopes to access `Service B`. -Please see below how both `AccessTokenRequestFilter` and `JsonWebTokenRequestFilter` can help. +The following sections show how `AccessTokenRequestFilter` and `JsonWebTokenRequestFilter` can help. === AccessTokenRequestFilter diff --git a/extensions/oidc-token-propagation/runtime/src/main/java/io/quarkus/oidc/token/propagation/AccessToken.java b/extensions/oidc-token-propagation/runtime/src/main/java/io/quarkus/oidc/token/propagation/AccessToken.java index a3075712a3bfe..2debaf34ecd77 100644 --- a/extensions/oidc-token-propagation/runtime/src/main/java/io/quarkus/oidc/token/propagation/AccessToken.java +++ b/extensions/oidc-token-propagation/runtime/src/main/java/io/quarkus/oidc/token/propagation/AccessToken.java @@ -6,6 +6,13 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +/** + * When this annotation is added to a MicroProfile REST Client interface, the {@link AccessTokenRequestFilter} will be added to + * the request pipeline. + * The end result is that the request propagates the Bearer token present in the current active request or the token acquired + * from the Authorization Code Flow, + * as the HTTP {@code Authorization} header's {@code Bearer} scheme value. + */ @Target({ ElementType.TYPE }) @Retention(RetentionPolicy.RUNTIME) @Documented diff --git a/extensions/oidc-token-propagation/runtime/src/main/java/io/quarkus/oidc/token/propagation/AccessTokenRequestFilter.java b/extensions/oidc-token-propagation/runtime/src/main/java/io/quarkus/oidc/token/propagation/AccessTokenRequestFilter.java index 0a5df9d7a98e1..0ec0b0877ae9b 100644 --- a/extensions/oidc-token-propagation/runtime/src/main/java/io/quarkus/oidc/token/propagation/AccessTokenRequestFilter.java +++ b/extensions/oidc-token-propagation/runtime/src/main/java/io/quarkus/oidc/token/propagation/AccessTokenRequestFilter.java @@ -20,6 +20,9 @@ public class AccessTokenRequestFilter extends AbstractTokenRequestFilter { private static final String EXCHANGE_SUBJECT_TOKEN = "subject_token"; + // note: We can't use constructor injection for these fields because they are registered by RESTEasy + // which doesn't know about CDI at the point of registration + @Inject Instance accessToken; diff --git a/extensions/oidc-token-propagation/runtime/src/main/java/io/quarkus/oidc/token/propagation/JsonWebToken.java b/extensions/oidc-token-propagation/runtime/src/main/java/io/quarkus/oidc/token/propagation/JsonWebToken.java index e7b8601602bd6..81649761f76cf 100644 --- a/extensions/oidc-token-propagation/runtime/src/main/java/io/quarkus/oidc/token/propagation/JsonWebToken.java +++ b/extensions/oidc-token-propagation/runtime/src/main/java/io/quarkus/oidc/token/propagation/JsonWebToken.java @@ -6,6 +6,13 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +/** + * When this annotation is added to a MicroProfile REST Client interface, the {@link JsonWebTokenRequestFilter} will be added to + * the request pipeline. + * The end result is that the request propagates the JWT token present in the current active request or the token acquired from + * the Authorization Code Flow, + * as the HTTP {@code Authorization} header's {@code Bearer} scheme value. + */ @Target({ ElementType.TYPE }) @Retention(RetentionPolicy.RUNTIME) @Documented diff --git a/extensions/oidc-token-propagation/runtime/src/main/java/io/quarkus/oidc/token/propagation/JsonWebTokenRequestFilter.java b/extensions/oidc-token-propagation/runtime/src/main/java/io/quarkus/oidc/token/propagation/JsonWebTokenRequestFilter.java index 4151e696ac946..1be3a3795359c 100644 --- a/extensions/oidc-token-propagation/runtime/src/main/java/io/quarkus/oidc/token/propagation/JsonWebTokenRequestFilter.java +++ b/extensions/oidc-token-propagation/runtime/src/main/java/io/quarkus/oidc/token/propagation/JsonWebTokenRequestFilter.java @@ -12,6 +12,10 @@ import io.smallrye.jwt.build.Jwt; public class JsonWebTokenRequestFilter extends AbstractTokenRequestFilter { + + // note: We can't use constructor injection for these fields because they are registered by RESTEasy + // which doesn't know about CDI at the point of registration + @Inject Instance jwtAccessToken;