1.5. RESTEasy Classic 的令牌传播
quarkus-resteasy-client-oidc-token-propagation
扩展提供了两个 Jakarta REST jakarta.ws.rs.client.ClientRequestFilter
类实现,以简化身份验证信息的传播。io.quarkus.oidc.token.propagation.AccessTokenRequestFilter
传播在当前活动请求中的 Bearer 令牌,或从 Authorization 代码流机制获取的令牌,作为 HTTP Authorization
标头的 Bearer
方案值。io.quarkus.oidc.token.propagation.JsonWebTokenRequestFilter
提供相同的功能,但也提供对 JWT 令牌的支持。
当您需要传播当前的授权代码流访问令牌时,直接令牌传播将正常工作,因为代码流访问令牌(而不是 ID 令牌)旨在为当前的 Quarkus 端点传播,以代表当前经过身份验证的用户访问远程服务。
但是,应避免直接端到端的 Bearer 令牌传播。例如,Client
,其中 Service B
接收由 Client
发送到 Service A
的令牌。在这种情况下,Service B
无法区分令牌是否来自 Service A
或直接与 客户端
。对于 Service B
验证令牌来自 Service A
,它应该能够断言新的签发者和受众声明。
此外,复杂的应用可能需要在传播令牌之前交换或更新令牌。例如,当 Service A
访问 Service B
时,访问上下文可能会有所不同。在这种情况下,服务 A
可能会被授予一个范围范围,或者完全不同的范围来访问服务 B
。
以下小节演示了 AccessTokenRequestFilter
和 JsonWebTokenRequestFilter
可以如何提供帮助。
1.5.1. RESTClient AccessTokenRequestFilter
AccessTokenRequestFilter
将所有令牌视为 Strings,因此它可以使用 JWT 和 opaque 令牌。
您可以使用 io.quarkus.oidc.token.propagation.common.AccessToken
或 org.eclipse.microprofile.rest.client.annotation.RegisterProvider
来选择性地注册 AccessTokenRequestFilter
,例如:
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import io.quarkus.oidc.token.propagation.common.AccessToken;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
@RegisterRestClient
@AccessToken
@Path("/")
public interface ProtectedResourceService {
@GET
String getUserName();
}
Copy to clipboardCopied或者
import org.eclipse.microprofile.rest.client.annotation.RegisterProvider;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import io.quarkus.oidc.token.propagation.AccessTokenRequestFilter;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
@RegisterRestClient
@RegisterProvider(AccessTokenRequestFilter.class)
@Path("/")
public interface ProtectedResourceService {
@GET
String getUserName();
}
Copy to clipboardCopied
另外,如果 quarkus.resteasy-client-oidc-token-propagation.register-filter
属性设置为 true
,并且 quarkus.resteasy-client-oidc-token-propagation.json-web-token
属性设置为 false
,则 AccessTokenRequestFilter
属性会自动注册到所有 MP Rest 或 Jakarta REST 客户端。
1.5.1.1. 在传播前交换令牌
如果需要在传播前交换当前的访问令牌,并使用 Keycloak 或其他支持 Token Exchange 令牌授权的 OpenID Connect 供应商,您可以配置 AccessTokenRequestFilter
,如下所示:
quarkus.oidc-client.auth-server-url=http://localhost:8180/auth/realms/quarkus
quarkus.oidc-client.client-id=quarkus-app
quarkus.oidc-client.credentials.secret=secret
quarkus.oidc-client.grant.type=exchange
quarkus.oidc-client.grant-options.exchange.audience=quarkus-app-exchange
quarkus.resteasy-client-oidc-token-propagation.exchange-token=true
Copy to clipboardCopied
如果您使用需要使用 JWT bearer 令牌 授权的 Azure
等提供程序来交换当前令牌,您可以配置 AccessTokenRequestFilter
以交换令牌,如下所示:
quarkus.oidc-client.auth-server-url=${azure.provider.url}
quarkus.oidc-client.client-id=quarkus-app
quarkus.oidc-client.credentials.secret=secret
quarkus.oidc-client.grant.type=jwt
quarkus.oidc-client.grant-options.jwt.requested_token_use=on_behalf_of
quarkus.oidc-client.scopes=https://graph.microsoft.com/user.read,offline_access
quarkus.resteasy-client-oidc-token-propagation.exchange-token=true
Copy to clipboardCopied
AccessTokenRequestFilter
将使用 OidcClient
来交换当前令牌,您可以使用 quarkus.oidc-client.grant-options.exchange
设置 OpenID Connect 提供程序期望的额外交换属性。
AccessTokenRequestFilter
默认使用 OidcClient
。可以使用 quarkus.resteasy-client-oidc-token-propagation.client-name
配置属性来选择命名的 OidcClient
。
1.5.2. RestClient JsonWebTokenRequestFilter
如果使用 Bearer JWT 令牌,则建议使用 JsonWebTokenRequestFilter
,其中这些令牌可以具有其声明,如 签发者
和 使用者
修改,以及再次修改更新的令牌(如重新签名)。它需要一个注入的 org.eclipse.microprofile.jwt.JsonWebToken
,因此无法使用不透明令牌。另外,如果您的 OpenID Connect Provider 支持 Token Exchange 协议,则建议使用 AccessTokenRequestFilter
,因为 JWT 和不透明 bearer 令牌都可以安全地与 AccessTokenRequestFilter
交换。
JsonWebTokenRequestFilter
可使 Service A
实施轻松更新注入的 org.eclipse.microprofile.jwt.WebToken
及新的 签发者
和 audience
声明值,并使用新的签名再次保护更新的令牌。唯一的困难是确保服务 A
具有从安全文件系统或远程安全存储(如 Vault)置备的签名密钥。
您可以使用 io.quarkus.oidc.token.propagation.JsonWebToken
或 org.eclipse.microprofile.rest.client.annotation.RegisterProvider
来选择性地注册 JsonWebTokenRequestFilter
,例如:
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import io.quarkus.oidc.token.propagation.JsonWebToken;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
@RegisterRestClient
@JsonWebToken
@Path("/")
public interface ProtectedResourceService {
@GET
String getUserName();
}
Copy to clipboardCopied或者
import org.eclipse.microprofile.rest.client.annotation.RegisterProvider;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import io.quarkus.oidc.token.propagation.JsonWebTokenRequestFilter;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
@RegisterRestClient
@RegisterProvider(JsonWebTokenRequestFilter.class)
@Path("/")
public interface ProtectedResourceService {
@GET
String getUserName();
}
Copy to clipboardCopied
另外,如果 quarkus.resteasy-client-oidc-token-propagation.register-filter
和 quarkus.resteasy-client-oidgation.register-filter 和 quarkus.resteasy-client-oidc-token-propagation.json-web-token
属性都会自动注册 JsonWebTokenRequestFilter
。
1.5.2.1. 在传播前更新令牌
如果注入的令牌需要有其 iss
(issuer)或 aud
(audience)声明使用新签名再次更新和保护,则可以配置 JsonWebTokenRequestFilter
,如下所示:
quarkus.resteasy-client-oidc-token-propagation.secure-json-web-token=true
smallrye.jwt.sign.key.location=/privateKey.pem
# Set a new issuer
smallrye.jwt.new-token.issuer=http://frontend-resource
# Set a new audience
smallrye.jwt.new-token.audience=http://downstream-resource
# Override the existing token issuer and audience claims if they are already set
smallrye.jwt.new-token.override-matching-claims=true
Copy to clipboardCopied
如前文所述,如果使用 Keycloak 或支持 Token Exchange 协议的 OpenID Connect Provider,请使用 AccessTokenRequestFilter
。
1.5.3. 测试
通常,您必须准备两个 REST 测试端点。第一个端点使用带有注册的令牌传播过滤器注入的 MP REST 客户端来调用第二个端点。
要了解它如何实现,请特别遵循 OpenID Connect 客户端和令牌传播 快速入门及其 测试 部分。