编辑此页面

OpenID Connect (OIDC) 和 OAuth2 客户端和过滤器

您可以使用 Quarkus 扩展来管理 OpenID Connect 和 OAuth 2.0 访问令牌,专注于获取、刷新和传播令牌。

这包括以下内容:

  • 使用 quarkus-oidc-clientquarkus-rest-client-oidc-filterquarkus-resteasy-client-oidc-filter 扩展,从符合 OpenID Connect 和 OAuth 2.0 的授权服务器(如 Keycloak)获取和刷新访问令牌。

  • 使用 quarkus-rest-client-oidc-token-propagationquarkus-resteasy-client-oidc-token-propagation 扩展来传播当前的 BearerAuthorization Code Flow 访问令牌。

这些扩展管理的访问令牌可以用作 HTTP Authorization Bearer 令牌来访问远程服务。

OidcClient

添加以下依赖项

<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-oidc-client</artifactId>
</dependency>

quarkus-oidc-client 扩展提供了一个响应式的 io.quarkus.oidc.client.OidcClient,可用于使用 SmallRye Mutiny 的 UniVert.x WebClient 来获取和刷新令牌。

OidcClient 在构建时使用 IDP 令牌端点 URL 进行初始化,该 URL 可以自动发现或手动配置。OidcClient 使用此端点通过 client_credentialspassword 等令牌授予来获取访问令牌,并通过 refresh_token 授予来刷新令牌。

令牌端点配置

默认情况下,令牌端点地址是通过将 /.well-known/openid-configuration 路径添加到已配置的 quarkus.oidc-client.auth-server-url 来发现的。

例如,给定这个 Keycloak URL:

quarkus.oidc-client.auth-server-url=https://:8180/auth/realms/quarkus

OidcClient 将会发现令牌端点 URL 是 https://:8180/auth/realms/quarkus/protocol/openid-connect/tokens

或者,如果发现端点不可用,或者您想节省发现端点的往返次数,您可以禁用发现并使用相对路径值配置令牌端点地址。例如:

quarkus.oidc-client.auth-server-url=https://:8180/auth/realms/quarkus
quarkus.oidc-client.discovery-enabled=false
# Token endpoint: https://:8180/auth/realms/quarkus/protocol/openid-connect/tokens
quarkus.oidc-client.token-path=/protocol/openid-connect/tokens

配置令牌端点 URL 的一个更简洁的方式,无需发现,只需将 quarkus.oidc-client.token-path 设置为绝对 URL:

quarkus.oidc-client.token-path=https://:8180/auth/realms/quarkus/protocol/openid-connect/tokens

在这种情况下,不需要设置 quarkus.oidc-client.auth-server-urlquarkus.oidc-client.discovery-enabled

支持的令牌授予

OidcClient 可以用来获取令牌的主要令牌授予是 client_credentials(默认)和 password 授予。

客户端凭据授予

以下是配置 OidcClient 以使用 client_credentials 授予的方法:

quarkus.oidc-client.auth-server-url=https://:8180/auth/realms/quarkus/
quarkus.oidc-client.client-id=quarkus-app
quarkus.oidc-client.credentials.secret=secret

client_credentials 授予允许通过使用 quarkus.oidc-client.grant-options.client.<param-name>=<value> 为令牌请求设置额外的参数。以下是如何通过使用 audience 参数设置目标令牌接收者:

quarkus.oidc-client.auth-server-url=https://:8180/auth/realms/quarkus/
quarkus.oidc-client.client-id=quarkus-app
quarkus.oidc-client.credentials.secret=secret
# 'client' is a shortcut for `client_credentials`
quarkus.oidc-client.grant.type=client
quarkus.oidc-client.grant-options.client.audience=https://example.com/api

密码授予

以下是配置 OidcClient 以使用 password 授予的方法:

quarkus.oidc-client.auth-server-url=https://:8180/auth/realms/quarkus/
quarkus.oidc-client.client-id=quarkus-app
quarkus.oidc-client.credentials.secret=secret
quarkus.oidc-client.grant.type=password
quarkus.oidc-client.grant-options.password.username=alice
quarkus.oidc-client.grant-options.password.password=alice

与客户端凭据授予的自定义方式类似,可以使用 quarkus.oidc-client.grant-options.password 配置前缀进一步自定义。

其他授予

OidcClient 还可以通过使用需要无法在配置中捕获的额外输入参数的授予来帮助获取令牌。这些授予是 refresh_token(带有外部刷新令牌)、authorization_code,以及可用于交换当前访问令牌的两个授予,即 urn:ietf:params:oauth:grant-type:token-exchangeurn:ietf:params:oauth:grant-type:jwt-bearer

如果您需要获取访问令牌,并且已将现有刷新令牌发布到当前的 Quarkus 端点,则必须使用 refresh_token 授予。此授予使用带外刷新令牌来获取新的令牌集。在这种情况下,请按如下方式配置 OidcClient

quarkus.oidc-client.auth-server-url=https://:8180/auth/realms/quarkus/
quarkus.oidc-client.client-id=quarkus-app
quarkus.oidc-client.credentials.secret=secret
quarkus.oidc-client.grant.type=refresh

然后,您可以使用 OidcClient.refreshTokens 方法以及提供的刷新令牌来获取访问令牌。

如果您正在构建复杂的微服务应用程序,并希望避免相同的 Bearer 令牌被传播到多个服务或被多个服务使用,则可能需要使用 urn:ietf:params:oauth:grant-type:token-exchangeurn:ietf:params:oauth:grant-type:jwt-bearer 授予。有关更多详细信息,请参阅 Quarkus REST 的令牌传播RESTEasy Classic 的令牌传播

如果您由于某种原因无法使用 Quarkus OIDC 扩展来支持授权码流,则可能需要使用 OidcClient 来支持 authorization code 授予。如果您有充分的理由实现授权码流,那么您可以按如下方式配置 OidcClient

quarkus.oidc-client.auth-server-url=https://:8180/auth/realms/quarkus/
quarkus.oidc-client.client-id=quarkus-app
quarkus.oidc-client.credentials.secret=secret
quarkus.oidc-client.grant.type=code

然后,您可以使用 OidcClient.accessTokens 方法接受额外的属性 Map,并传递当前的 coderedirect_uri 参数来用授权码交换令牌。

OidcClient 还支持 urn:openid:params:grant-type:ciba 授予。

quarkus.oidc-client.auth-server-url=https://:8180/auth/realms/quarkus/
quarkus.oidc-client.client-id=quarkus-app
quarkus.oidc-client.credentials.secret=secret
quarkus.oidc-client.grant.type=ciba

然后,您可以使用 OidcClient.accessTokens 方法接受额外的属性 Map,并传递 auth_req_id 参数来交换令牌授权码。

授予范围

您可能需要请求将特定范围集与发出的访问令牌相关联。使用专用的 quarkus.oidc-client.scopes 列表属性,例如:quarkus.oidc-client.scopes=email,phone

直接使用 OidcClient

您可以直接使用 OidcClient 获取访问令牌,并将其设置为 HTTP Authorization 标头中的 Bearer 方案值。

例如,假设 Quarkus 端点需要访问一个返回用户名的微服务。首先,创建一个 REST 客户端:

package org.acme.security.openid.connect.client;

import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;

import io.smallrye.mutiny.Uni;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.HeaderParam;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;

@RegisterRestClient
@Path("/")
public interface RestClientWithTokenHeaderParam {

    @GET
    @Produces("text/plain")
    @Path("userName")
    Uni<String> getUserName(@HeaderParam("Authorization") String authorization);
}

现在,使用 OidcClient 获取令牌并传播它们:

package org.acme.security.openid.connect.client;

import org.eclipse.microprofile.rest.client.inject.RestClient;

import io.quarkus.oidc.client.runtime.TokensHelper;
import io.quarkus.oidc.client.OidcClient;

import io.smallrye.mutiny.Uni;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;

@Path("/service")
public class OidcClientResource {

    @Inject
    OidcClient client;
    TokensHelper tokenHelper = new TokensHelper(); (1)

    @Inject
    @RestClient
    RestClientWithTokenHeaderParam restClient;

    @GET
    @Path("user-name")
    @Produces("text/plain")
    public Uni<String> getUserName() {
    	return tokenHelper.getTokens(client).onItem()
        		.transformToUni(tokens -> restClient.getUserName("Bearer " + tokens.getAccessToken()));
    }
}
1 io.quarkus.oidc.client.runtime.TokensHelper 负责管理访问令牌的获取和刷新。

注入令牌

您可以注入在内部使用 OidcClientTokensTokens 可用于获取访问令牌并在必要时刷新它们。

import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;

import io.quarkus.oidc.client.Tokens;

@Path("/service")
public class OidcClientResource {

    @Inject Tokens tokens;

    @GET
    public String getResponse() {
        //  Get the access token, which might have been refreshed.
        String accessToken = tokens.getAccessToken();
        // Use the access token to configure MP RestClient Authorization header/etc
    }
}

使用 OidcClients

io.quarkus.oidc.client.OidcClientsOidcClient 的容器,它包括一个默认的 OidcClient 和命名的客户端,可以这样配置:

quarkus.oidc-client.client-enabled=false

quarkus.oidc-client.jwt-secret.auth-server-url=https://:8180/auth/realms/quarkus/
quarkus.oidc-client.jwt-secret.client-id=quarkus-app
quarkus.oidc-client.jwt-secret.credentials.jwt.secret=AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow

在这种情况下,默认客户端被 client-enabled=false 属性禁用。jwt-secret 客户端可以这样访问:

import org.eclipse.microprofile.rest.client.inject.RestClient;

import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import io.smallrye.mutiny.Uni;
import io.quarkus.oidc.client.OidcClient;
import io.quarkus.oidc.client.OidcClients;
import io.quarkus.oidc.client.runtime.TokensHelper;

@Path("/clients")
public class OidcClientResource {

    @Inject
    OidcClients clients;
    TokensHelper tokenHelper = new TokensHelper();

    @Inject
    @RestClient
    RestClientWithTokenHeaderParam restClient; (1)

    @GET
    @Path("user-name")
    @Produces("text/plain")
    public Uni<String> getUserName() {
    	OidcClient client = clients.getClient("jwt-secret");
    	return tokenHelper.getTokens(client).onItem()
        		.transformToUni(tokens -> restClient.getUserName("Bearer " + tokens.getAccessToken()));
    }
}
1 请参阅 直接使用 OidcClient 部分中的 RestClientWithTokenHeaderParam 声明。

如果您还使用 OIDC 多租户,并且每个 OIDC 租户都有其关联的 OidcClient,则可以使用 Vert.x 的 RoutingContext tenant-id 属性。例如:

import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;

import io.quarkus.oidc.client.OidcClient;
import io.quarkus.oidc.client.OidcClients;
import io.vertx.ext.web.RoutingContext;

@Path("/clients")
public class OidcClientResource {

    @Inject
    OidcClients clients;
    @Inject
    RoutingContext context;

    @GET
    public String getResponse() {
        String tenantId = context.get("tenant-id");
        // named OIDC tenant and client configurations use the same key:
        OidcClient client = clients.getClient(tenantId);
        //Use this client to get the token
    }
}

您也可以通过编程方式创建新的 OidcClient。例如,假设您必须在启动时创建它:

package org.acme.security.openid.connect.client;

import java.util.Map;

import org.eclipse.microprofile.config.inject.ConfigProperty;

import io.quarkus.oidc.client.OidcClient;
import io.quarkus.oidc.client.runtime.OidcClientConfig;
import io.quarkus.oidc.client.runtime.OidcClientConfig.Grant.Type;
import io.quarkus.oidc.client.OidcClients;
import io.quarkus.runtime.StartupEvent;
import io.smallrye.mutiny.Uni;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.event.Observes;
import jakarta.inject.Inject;

@ApplicationScoped
public class OidcClientCreator {

    @Inject
    OidcClients oidcClients;
    @ConfigProperty(name = "quarkus.oidc.auth-server-url")
    String oidcProviderAddress;

    private volatile OidcClient oidcClient;

    public void startup(@Observes StartupEvent event) {
    	createOidcClient().subscribe().with(client -> {oidcClient = client;});
    }

    public OidcClient getOidcClient() {
        return oidcClient;
    }

    private Uni<OidcClient> createOidcClient() {
        OidcClientConfig cfg = OidcClientConfig
            .authServerUrl(oidcProviderAddress)
            .id("myclient")
            .clientId("backend-service")
            .credentials("secret")
            .grant(Type.PASSWORD)
            .grantOptions("password", Map.of("username", "alice", "password", "alice"))
            .build();
        return oidcClients.newClient(cfg);
    }
}

现在,您可以这样使用此客户端:

import org.eclipse.microprofile.rest.client.inject.RestClient;

import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import io.smallrye.mutiny.Uni;
import io.quarkus.oidc.client.runtime.TokensHelper;

@Path("/clients")
public class OidcClientResource {

    @Inject
    OidcClientCreator oidcClientCreator;
    TokensHelper tokenHelper = new TokensHelper();

    @Inject
    @RestClient
    RestClientWithTokenHeaderParam restClient; (1)

    @GET
    @Path("user-name")
    @Produces("text/plain")
    public Uni<String> getUserName() {
    	return tokenHelper.getTokens(oidcClientCreator.getOidcClient()).onItem()
        		.transformToUni(tokens -> restClient.getUserName("Bearer " + tokens.getAccessToken()));
    }
}
1 请参阅 直接使用 OidcClient 部分中的 RestClientWithTokenHeaderParam 声明。

注入命名的 OidcClient 和令牌

在有多个配置的 OidcClient 对象的情况下,您可以通过额外的限定符 @NamedOidcClient 来指定 OidcClient 注入目标,而不是使用 OidcClients

package org.acme.security.openid.connect.client;

import org.eclipse.microprofile.rest.client.inject.RestClient;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import io.smallrye.mutiny.Uni;
import io.quarkus.oidc.client.NamedOidcClient;
import io.quarkus.oidc.client.OidcClient;
import io.quarkus.oidc.client.runtime.TokensHelper;

@Path("/clients")
public class OidcClientResource {

    @Inject
    @NamedOidcClient("jwt-secret")
    OidcClient client;

    TokensHelper tokenHelper = new TokensHelper();

    @Inject
    @RestClient
    RestClientWithTokenHeaderParam restClient; (1)

    @GET
    @Path("user-name")
    @Produces("text/plain")
    public Uni<String> getUserName() {
    	return tokenHelper.getTokens(client).onItem()
        		.transformToUni(tokens -> restClient.getUserName("Bearer " + tokens.getAccessToken()));
    }
}
1 请参阅 直接使用 OidcClient 部分中的 RestClientWithTokenHeaderParam 声明。

同样的限定符也可用于指定用于 Tokens 注入的 OidcClient

import java.io.IOException;

import jakarta.annotation.Priority;
import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.Priorities;
import jakarta.ws.rs.client.ClientRequestContext;
import jakarta.ws.rs.client.ClientRequestFilter;
import jakarta.ws.rs.core.HttpHeaders;
import jakarta.ws.rs.ext.Provider;

import io.quarkus.oidc.client.NamedOidcClient;
import io.quarkus.oidc.client.Tokens;

@Provider
@Priority(Priorities.AUTHENTICATION)
@RequestScoped
public class OidcClientRequestCustomFilter implements ClientRequestFilter {

    @Inject
    @NamedOidcClient("jwt-secret")
    Tokens tokens;

    @Override
    public void filter(ClientRequestContext requestContext) throws IOException {
        requestContext.getHeaders().add(HttpHeaders.AUTHORIZATION, "Bearer " + tokens.getAccessToken());
    }
}

在 RestClient Reactive ClientFilter 中使用 OidcClient

添加以下 Maven 依赖:

<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-rest-client-oidc-filter</artifactId>
</dependency>
这将也会引入 io.quarkus:quarkus-oidc-client

quarkus-rest-client-oidc-filter 扩展提供了 io.quarkus.oidc.client.filter.OidcClientRequestReactiveFilter

它的工作方式与 OidcClientRequestFilter 类似(请参阅 在 MicroProfile RestClient 客户端过滤器中使用 OidcClient)——它使用 OidcClient 获取访问令牌,在需要时刷新它,并将其设置为 HTTP Authorization Bearer 方案值。区别在于它与 Reactive RestClient 一起工作,并实现了一个非阻塞的客户端过滤器,在获取或刷新令牌时不会阻塞当前的 IO 线程。

OidcClientRequestReactiveFilter 会延迟初始令牌的获取,直到它被执行,以避免阻塞 IO 线程。

您可以通过使用 io.quarkus.oidc.client.reactive.filter.OidcClientFilterorg.eclipse.microprofile.rest.client.annotation.RegisterProvider 注解来选择性地注册 OidcClientRequestReactiveFilter

import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import io.quarkus.oidc.client.filter.OidcClientFilter;
import io.smallrye.mutiny.Uni;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;

@RegisterRestClient
@OidcClientFilter
@Path("/")
public interface ProtectedResourceService {

    @GET
    Uni<String> getUserName();
}

import org.eclipse.microprofile.rest.client.annotation.RegisterProvider;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import io.quarkus.oidc.client.reactive.filter.OidcClientRequestReactiveFilter;
import io.smallrye.mutiny.Uni;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;

@RegisterRestClient
@RegisterProvider(OidcClientRequestReactiveFilter.class)
@Path("/")
public interface ProtectedResourceService {

    @GET
    Uni<String> getUserName();
}

OidcClientRequestReactiveFilter 默认使用一个默认的 OidcClient。可以通过 quarkus.rest-client-oidc-filter.client-name 配置属性选择一个命名的 OidcClient。您还可以通过设置 @OidcClientFilter 注解的 value 属性来选择 OidcClient。通过注解设置的客户端名称比 quarkus.rest-client-oidc-filter.client-name 配置属性具有更高的优先级。例如,给定 这个 jwt-secret 命名的 OIDC 客户端声明,您可以这样引用此客户端:

import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import io.quarkus.oidc.client.filter.OidcClientFilter;
import io.smallrye.mutiny.Uni;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;

@RegisterRestClient
@OidcClientFilter("jwt-secret")
@Path("/")
public interface ProtectedResourceService {

    @GET
    Uni<String> getUserName();
}

在 RestClient ClientFilter 中使用 OidcClient

添加以下 Maven 依赖:

<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-resteasy-client-oidc-filter</artifactId>
</dependency>
这将也会引入 io.quarkus:quarkus-oidc-client

quarkus-resteasy-client-oidc-filter 扩展提供了 io.quarkus.oidc.client.filter.OidcClientRequestFilter Jakarta REST ClientRequestFilter,它使用 OidcClient 来获取访问令牌,在需要时刷新它,并将其设置为 HTTP Authorization Bearer 方案值。

默认情况下,此过滤器将在其初始化时获取第一个访问令牌和刷新令牌对。如果访问令牌的有效期很短且没有刷新令牌,则应通过 quarkus.oidc-client.early-tokens-acquisition=false 来延迟令牌的获取。

您可以通过使用 io.quarkus.oidc.client.filter.OidcClientFilterorg.eclipse.microprofile.rest.client.annotation.RegisterProvider 注解来选择性地注册 OidcClientRequestFilter

import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import io.quarkus.oidc.client.filter.OidcClientFilter;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;

@RegisterRestClient
@OidcClientFilter
@Path("/")
public interface ProtectedResourceService {

    @GET
    String getUserName();
}

import org.eclipse.microprofile.rest.client.annotation.RegisterProvider;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import io.quarkus.oidc.client.filter.OidcClientRequestFilter;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;

@RegisterRestClient
@RegisterProvider(OidcClientRequestFilter.class)
@Path("/")
public interface ProtectedResourceService {

    @GET
    String getUserName();
}

或者,如果将 quarkus.resteasy-client-oidc-filter.register-filter=true 属性设置为 true,则可以自动将 OidcClientRequestFilter 注册到所有 MP Rest 或 Jakarta REST 客户端。

OidcClientRequestFilter 默认使用一个默认的 OidcClient。可以通过 quarkus.resteasy-client-oidc-filter.client-name 配置属性选择一个命名的 OidcClient。您还可以通过设置 @OidcClientFilter 注解的 value 属性来选择 OidcClient。通过注解设置的客户端名称比 quarkus.resteasy-client-oidc-filter.client-name 配置属性具有更高的优先级。例如,给定 这个 jwt-secret 命名的 OIDC 客户端声明,您可以这样引用此客户端:

import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import io.quarkus.oidc.client.filter.OidcClientFilter;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;

@RegisterRestClient
@OidcClientFilter("jwt-secret")
@Path("/")
public interface ProtectedResourceService {

    @GET
    String getUserName();
}

使用自定义 RestClient ClientFilter

如果需要,您可以使用自己的自定义过滤器并注入 Tokens

import java.io.IOException;
import jakarta.annotation.Priority;
import jakarta.inject.Inject;
import jakarta.ws.rs.Priorities;
import jakarta.ws.rs.client.ClientRequestContext;
import jakarta.ws.rs.client.ClientRequestFilter;
import jakarta.ws.rs.core.HttpHeaders;
import jakarta.ws.rs.ext.Provider;
import io.quarkus.oidc.client.Tokens;

@Provider
@Priority(Priorities.AUTHENTICATION)
public class OidcClientRequestCustomFilter implements ClientRequestFilter {

    @Inject
    Tokens tokens;

    @Override
    public void filter(ClientRequestContext requestContext) throws IOException {
        requestContext.getHeaders().add(HttpHeaders.AUTHORIZATION, "Bearer " + tokens.getAccessToken());
    }
}

Tokens 生产者将获取并刷新令牌,而自定义过滤器将决定如何以及何时使用令牌。

您也可以注入命名的 Tokens,请参阅 注入命名的 OidcClient 和令牌

刷新访问令牌

OidcClientRequestReactiveFilterOidcClientRequestFilterTokens 生产者将在刷新令牌可用时刷新当前过期的访问令牌。此外,quarkus.oidc-client.refresh-token-time-skew 属性可用于抢先刷新访问令牌,以避免发送接近过期的访问令牌,这可能会导致 HTTP 401 错误。例如,如果此属性设置为 3S,并且访问令牌将在 3 秒内过期,则该令牌将被自动刷新。

如果需要刷新访问令牌,但没有可用的刷新令牌,则会尝试通过使用已配置的授予(如 client_credentials)来获取新令牌。

某些 OpenID Connect 提供商在 client_credentials 授予响应中不会返回刷新令牌。例如,从 Keycloak 12 开始,默认情况下不会为 client_credentials 返回刷新令牌。提供商也可能限制刷新令牌的使用次数。

撤销访问令牌

如果您的 OpenID Connect 提供商(如 Keycloak)支持令牌撤销端点,则可以使用 OidcClient#revokeAccessToken 来撤销当前访问令牌。撤销端点 URL 将与令牌请求 URI 一起发现,或者可以使用 quarkus.oidc-client.revoke-path 进行配置。

您可能希望在通过 REST 客户端使用此令牌失败并出现 HTTP 401 状态码时,或者在访问令牌已使用很长时间并且您想刷新它时,撤销访问令牌。

这可以通过请求使用刷新令牌来刷新访问令牌来实现。但是,如果刷新令牌不可用,则可以通过先撤销它,然后请求新的访问令牌来刷新它。

OidcClient 身份验证

OidcClient 必须向 OpenID Connect Provider 进行身份验证,以便 client_credentials 和其他授予请求能够成功。所有 OIDC 客户端身份验证 选项都受到支持,例如:

client_secret_basic:

quarkus.oidc-client.auth-server-url=https://:8180/auth/realms/quarkus/
quarkus.oidc-client.client-id=quarkus-app
quarkus.oidc-client.credentials.secret=mysecret

quarkus.oidc-client.auth-server-url=https://:8180/auth/realms/quarkus/
quarkus.oidc-client.client-id=quarkus-app
quarkus.oidc-client.credentials.client-secret.value=mysecret

或者使用从 CredentialsProvider 获取的 secret:

quarkus.oidc-client.auth-server-url=https://:8180/auth/realms/quarkus/
quarkus.oidc-client.client-id=quarkus-app

# This key is used to retrieve a secret from the map of credentials returned from CredentialsProvider
quarkus.oidc-client.credentials.client-secret.provider.key=mysecret-key
# This is the keyring provided to the CredentialsProvider when looking up the secret, set only if required by the CredentialsProvider implementation
quarkus.oidc.credentials.client-secret.provider.keyring-name=oidc
# Set it only if more than one CredentialsProvider can be registered
quarkus.oidc-client.credentials.client-secret.provider.name=oidc-credentials-provider

client_secret_post:

quarkus.oidc-client.auth-server-url=https://:8180/auth/realms/quarkus/
quarkus.oidc-client.client-id=quarkus-app
quarkus.oidc-client.credentials.client-secret.value=mysecret
quarkus.oidc-client.credentials.client-secret.method=post

client_secret_jwt,签名算法为 HS256

quarkus.oidc-client.auth-server-url=https://:8180/auth/realms/quarkus/
quarkus.oidc-client.client-id=quarkus-app
quarkus.oidc-client.credentials.jwt.secret=AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow

或者使用从 CredentialsProvider 获取的 secret,签名算法为 HS256

quarkus.oidc-client.auth-server-url=https://:8180/auth/realms/quarkus/
quarkus.oidc-client.client-id=quarkus-app

# This is a key that will be used to retrieve a secret from the map of credentials returned from CredentialsProvider
quarkus.oidc-client.credentials.jwt.secret-provider.key=mysecret-key
# This is the keyring provided to the CredentialsProvider when looking up the secret, set only if required by the CredentialsProvider implementation
quarkus.oidc.credentials.client-secret.provider.keyring-name=oidc
# Set it only if more than one CredentialsProvider can be registered
quarkus.oidc-client.credentials.jwt.secret-provider.name=oidc-credentials-provider

private_key_jwt,PEM 密钥内联在 application.properties 中,签名算法为 RS256

quarkus.oidc-client.auth-server-url=https://:8180/auth/realms/quarkus/
quarkus.oidc-client.client-id=quarkus-app
quarkus.oidc-client.credentials.jwt.key=Base64-encoded private key representation

private_key_jwt,使用 PEM 密钥文件,签名算法为 RS256

quarkus.oidc-client.auth-server-url=https://:8180/auth/realms/quarkus/
quarkus.oidc-client.client-id=quarkus-app
quarkus.oidc-client.credentials.jwt.key-file=privateKey.pem

private_key_jwt,使用密钥库文件,签名算法为 RS256

quarkus.oidc-client.auth-server-url=https://:8180/auth/realms/quarkus/
quarkus.oidc-client.client-id=quarkus-app
quarkus.oidc-client.credentials.jwt.key-store-file=keystore.pkcs12
quarkus.oidc-client.credentials.jwt.key-store-password=mypassword
quarkus.oidc-client.credentials.jwt.key-password=mykeypassword

# Private key alias inside the keystore
quarkus.oidc-client.credentials.jwt.key-id=mykeyAlias

使用 client_secret_jwtprivate_key_jwt 身份验证方法可以确保客户端 secret 不会在网络上传输。

其他 JWT 身份验证选项

如果使用 client_secret_jwtprivate_key_jwt 身份验证方法,则可以自定义 JWT 签名算法、密钥标识符、受众、主题和发行者,例如:

# private_key_jwt client authentication

quarkus.oidc-client.auth-server-url=https://:8180/auth/realms/quarkus/
quarkus.oidc-client.client-id=quarkus-app
quarkus.oidc-client.credentials.jwt.key-file=privateKey.pem

# This is a token key identifier 'kid' header - set it if your OpenID Connect provider requires it.
# Note that if the key is represented in a JSON Web Key (JWK) format with a `kid` property, then
# using 'quarkus.oidc-client.credentials.jwt.token-key-id' is unnecessary.
quarkus.oidc-client.credentials.jwt.token-key-id=mykey

# Use the RS512 signature algorithm instead of the default RS256
quarkus.oidc-client.credentials.jwt.signature-algorithm=RS512

# The token endpoint URL is the default audience value; use the base address URL instead:
quarkus.oidc-client.credentials.jwt.audience=${quarkus.oidc-client.auth-server-url}

# custom subject instead of the client ID:
quarkus.oidc-client.credentials.jwt.subject=custom-subject

# custom issuer instead of the client ID:
quarkus.oidc-client.credentials.jwt.issuer=custom-issuer

JWT Bearer

RFC7523 解释了如何使用 JWT Bearer 令牌来对客户端进行身份验证,有关更多信息,请参阅 使用 JWT 进行客户端身份验证 部分。

可以按如下方式启用它:

quarkus.oidc-client.auth-server-url=${auth-server-url}
quarkus.oidc-client.client-id=quarkus-app
quarkus.oidc-client.credentials.jwt.source=bearer

接下来,必须将 JWT bearer 令牌作为 client_assertion 参数提供给 OIDC 客户端。

Quarkus 可以从文件系统加载 JWT bearer 令牌。例如,在 Kubernetes 中,服务帐户令牌投影可以挂载到 /var/run/secrets/tokens 路径。然后,您只需配置 JWT bearer 令牌路径,如下所示:

quarkus.oidc-client.credentials.jwt.token-path=/var/run/secrets/tokens (1)
1 JWT bearer 令牌的路径。Quarkus 从文件系统加载新令牌,并在令牌过期时重新加载它。

您的另一个选择是使用 OidcClient 方法来获取或刷新令牌,这些方法接受额外的授予参数,例如 oidcClient.getTokens(Map.of("client_assertion", "ey…​"))

如果您使用 OIDC 客户端过滤器,则必须注册一个自定义过滤器来提供此断言。

以下是 Quarkus REST(以前称为 RESTEasy Reactive)自定义过滤器的示例:

package io.quarkus.it.keycloak;

import java.util.Map;

import io.quarkus.oidc.client.reactive.filter.runtime.AbstractOidcClientRequestReactiveFilter;
import io.quarkus.oidc.common.runtime.OidcConstants;
import jakarta.annotation.Priority;
import jakarta.ws.rs.Priorities;

@Priority(Priorities.AUTHENTICATION)
public class OidcClientRequestCustomFilter extends AbstractOidcClientRequestReactiveFilter {

    @Override
    protected Map<String, String> additionalParameters() {
        return Map.of(OidcConstants.CLIENT_ASSERTION, "ey...");
    }
}

以下是 RESTEasy Classic 自定义过滤器的示例:

package io.quarkus.it.keycloak;

import java.util.Map;

import io.quarkus.oidc.client.filter.runtime.AbstractOidcClientRequestFilter;
import io.quarkus.oidc.common.runtime.OidcConstants;
import jakarta.annotation.Priority;
import jakarta.ws.rs.Priorities;

@Priority(Priorities.AUTHENTICATION)
public class OidcClientRequestCustomFilter extends AbstractOidcClientRequestFilter {

    @Override
    protected Map<String, String> additionalParameters() {
        return Map.of(OidcConstants.CLIENT_ASSERTION, "ey...");
    }
}

Apple POST JWT

Apple OpenID Connect 提供商使用 client_secret_post 方法,其中 secret 是使用 private_key_jwt 身份验证方法生成的 JWT,但具有 Apple 帐户特定的发行者和主题属性。

quarkus-oidc-client 支持非标准的 client_secret_post_jwt 身份验证方法,可以按如下方式配置:

quarkus.oidc-client.auth-server-url=${apple.url}
quarkus.oidc-client.client-id=${apple.client-id}
quarkus.oidc-client.credentials.client-secret.method=post-jwt

quarkus.oidc-client.credentials.jwt.key-file=ecPrivateKey.pem
quarkus.oidc-client.credentials.jwt.signature-algorithm=ES256
quarkus.oidc-client.credentials.jwt.subject=${apple.subject}
quarkus.oidc-client.credentials.jwt.issuer=${apple.issuer}

Mutual TLS

某些 OpenID Connect 提供商要求客户端在 mutual TLS (mTLS) 身份验证过程中进行身份验证。

可以按如下方式配置 quarkus-oidc-client 以支持 mTLS

quarkus.oidc-client.tls.tls-configuration-name=oidc-client

# configure hostname verification if necessary
#quarkus.tls.oidc-client.hostname-verification-algorithm=NONE

# Keystore configuration
quarkus.tls.oidc-client.key-store.p12.path=client-keystore.p12
quarkus.tls.oidc-client.key-store.p12.password=${key-store-password}

# Add more keystore properties if needed:
#quarkus.tls.oidc-client.key-store.p12.alias=keyAlias
#quarkus.tls.oidc-client.key-store.p12.alias-password=keyAliasPassword

# Truststore configuration
quarkus.tls.oidc-client.trust-store.p12.path=client-truststore.p12
quarkus.tls.oidc-client.trust-store.p12.password=${trust-store-password}
# Add more truststore properties if needed:
#quarkus.tls.oidc-client.trust-store.p12.alias=certAlias

OIDC Client SPI

当您的自定义扩展必须使用 OIDC 客户端支持的 OIDC 令牌授予之一来获取 OIDC 令牌时,此扩展可以仅依赖 OIDC Client SPI,并让 OIDC 客户端本身根据需要获取和刷新访问令牌。

添加以下依赖项

<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-oidc-client-spi</artifactId>
</dependency>

接下来,更新您的扩展以使用所需的 io.quarkus.oidc.client.spi.TokenProvider CDI bean,例如:

package org.acme.extension;

import jakarta.inject.Inject;
import io.quarkus.oidc.client.spi.TokenProvider;

public class ExtensionOAuth2Support {

   @Inject
   TokenProvider tokenProvider;

   public Uni<String> getAccessToken() {
       return tokenProvider.getAccessToken();
   }
}

目前,io.quarkus.oidc.client.spi.TokenProvider 仅适用于默认的 OIDC 客户端,因为自定义扩展不太可能感知多个命名的 OIDC 客户端。

测试

首先将以下依赖项添加到您的测试项目中

<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-junit5</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.awaitility</groupId>
    <artifactId>awaitility</artifactId>
    <scope>test</scope>
</dependency>

Wiremock

将以下依赖项添加到您的测试项目中:

<dependency>
    <groupId>org.wiremock</groupId>
    <artifactId>wiremock</artifactId>
    <scope>test</scope>
    <version>${wiremock.version}</version> (1)
</dependency>
1 使用正确的 Wiremock 版本。所有可用版本都可以在 这里 找到。

编写一个基于 Wiremock 的 QuarkusTestResourceLifecycleManager,例如:

package io.quarkus.it.keycloak;

import static com.github.tomakehurst.wiremock.client.WireMock.matching;
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;

import java.util.HashMap;
import java.util.Map;

import com.github.tomakehurst.wiremock.WireMockServer;
import com.github.tomakehurst.wiremock.client.WireMock;
import com.github.tomakehurst.wiremock.core.Options.ChunkedEncodingPolicy;

import io.quarkus.test.common.QuarkusTestResourceLifecycleManager;

public class KeycloakRealmResourceManager implements QuarkusTestResourceLifecycleManager {
    private WireMockServer server;

    @Override
    public Map<String, String> start() {

        server = new WireMockServer(wireMockConfig().dynamicPort().useChunkedTransferEncoding(ChunkedEncodingPolicy.NEVER));
        server.start();

        server.stubFor(WireMock.post("/tokens")
                .withRequestBody(matching("grant_type=password&username=alice&password=alice"))
                .willReturn(WireMock
                        .aResponse()
                        .withHeader("Content-Type", "application/json")
                        .withBody(
                                "{\"access_token\":\"access_token_1\", \"expires_in\":4, \"refresh_token\":\"refresh_token_1\"}")));
        server.stubFor(WireMock.post("/tokens")
                .withRequestBody(matching("grant_type=refresh_token&refresh_token=refresh_token_1"))
                .willReturn(WireMock
                        .aResponse()
                        .withHeader("Content-Type", "application/json")
                        .withBody(
                                "{\"access_token\":\"access_token_2\", \"expires_in\":4, \"refresh_token\":\"refresh_token_1\"}")));


        Map<String, String> conf = new HashMap<>();
        conf.put("keycloak.url", server.baseUrl());
        return conf;
    }

    @Override
    public synchronized void stop() {
        if (server != null) {
            server.stop();
            server = null;
        }
    }
}

准备 REST 测试端点。您可以有一个测试前端端点,该端点使用已注册 OidcClient 过滤器的注入的 MP REST 客户端来调用下游端点。此端点会将其接收到的令牌回显。例如,请参阅 Quarkus 主仓库中的 integration-tests/oidc-client-wiremock

设置 application.properties,例如:

# Use the 'keycloak.url' property set by the test KeycloakRealmResourceManager
quarkus.oidc-client.auth-server-url=${keycloak.url:replaced-by-test-resource}
quarkus.oidc-client.discovery-enabled=false
quarkus.oidc-client.token-path=/tokens
quarkus.oidc-client.client-id=quarkus-service-app
quarkus.oidc-client.credentials.secret=secret
quarkus.oidc-client.grant.type=password
quarkus.oidc-client.grant-options.password.username=alice
quarkus.oidc-client.grant-options.password.password=alice

最后,编写测试代码。给定上述基于 Wiremock 的资源,第一次测试调用应返回 access_token_1 访问令牌,该令牌将在 4 秒后过期。使用 awaitility 等待大约 5 秒钟,然后下一次测试调用应返回 access_token_2 访问令牌,这证实了已过期的 access_token_1 访问令牌已被刷新。

Keycloak

如果您使用 Keycloak,可以使用在 OpenID Connect Bearer Token 集成测试 Keycloak 部分中描述的相同方法。

如何检查日志中的错误

启用 io.quarkus.oidc.client.runtime.OidcClientImplTRACE 级别日志记录,以查看有关令牌获取和刷新错误的更多详细信息。

quarkus.log.category."io.quarkus.oidc.client.runtime.OidcClientImpl".level=TRACE
quarkus.log.category."io.quarkus.oidc.client.runtime.OidcClientImpl".min-level=TRACE

启用 io.quarkus.oidc.client.runtime.OidcClientRecorderTRACE 级别日志记录,以查看有关 OidcClient 初始化错误的更多详细信息。

quarkus.log.category."io.quarkus.oidc.client.runtime.OidcClientRecorder".level=TRACE
quarkus.log.category."io.quarkus.oidc.client.runtime.OidcClientRecorder".min-level=TRACE

OIDC 请求过滤器

您可以通过注册一个或多个 OidcRequestFilter 实现来过滤 OIDC 客户端向 OIDC 提供商发出的 OIDC 请求,这些实现可以更新或添加新的请求标头,或分析请求正文。

您可以有一个过滤器拦截对所有 OIDC 提供商端点的请求,或者使用 @OidcEndpoint 注解将此过滤器应用于仅对特定端点的请求。例如:

package io.quarkus.it.keycloak;

import jakarta.enterprise.context.ApplicationScoped;

import io.quarkus.arc.Unremovable;
import io.quarkus.oidc.common.OidcEndpoint;
import io.quarkus.oidc.common.OidcRequestFilter;
import io.vertx.core.http.HttpMethod;

@ApplicationScoped
@OidcEndpoint(value = Type.TOKEN)
@Unremovable
public class OidcRequestCustomizer implements OidcRequestFilter {

    @Override
    public void filter(OidcRequestContext requestContext) {
        HttpMethod method = requestContext.request().method();
        String uri = requestContext.request().uri();
        if (method == HttpMethod.POST && uri.endsWith("/token") && requestContext.requestBody() != null) {
            requestContext.request().putHeader("Digest", calculateDigest(requestContext.requestBody().toString()));
        }
    }

    private String calculateDigest(String bodyString) {
        // Apply the required digest algorithm to the body string
    }
}

OidcRequestContextProperties 可用于访问请求属性。目前,您可以使用 client_id 键来访问客户端租户 ID,使用 grant_type 键来访问 OIDC 客户端用于获取令牌的授予类型。

OIDC 响应过滤器

您可以通过注册一个或多个 OidcResponseFilter 实现来过滤对 OIDC 客户端请求的响应,这些实现可以检查响应状态、标头和正文,以便记录它们或执行其他操作。

您可以有一个过滤器拦截对所有 OIDC 客户端请求的响应,或者使用 @OidcEndpoint 注解将此过滤器应用于仅对特定 OIDC 客户端请求的响应。例如:

package io.quarkus.it.keycloak;

import jakarta.enterprise.context.ApplicationScoped;

import org.jboss.logging.Logger;

import io.quarkus.arc.Unremovable;
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;

@ApplicationScoped
@Unremovable
@OidcEndpoint(value = Type.TOKEN) (1)
public class TokenEndpointResponseFilter implements OidcResponseFilter {
    private static final Logger LOG = Logger.getLogger(TokenEndpointResponseFilter.class);

    @Override
    public void filter(OidcResponseContext rc) {
        String contentType = rc.responseHeaders().get("Content-Type"); (2)
        if (contentType.equals("application/json")
                && "refresh_token".equals(rc.requestProperties().get(OidcConstants.GRANT_TYPE)) (3)
                && rc.responseBody().toJsonObject().containsKey("refresh_token")) { (4)
            LOG.debug("Tokens have been refreshed");
        }
    }

}
1 将此过滤器限制为仅针对 OIDC 令牌端点的请求。
2 检查响应 Content-Type 标头。
3 使用 OidcRequestContextProperties 请求属性来确认这是 refresh_grant 令牌授予的响应。
4 确认响应 JSON 包含 refresh_token 属性。

Quarkus REST 的令牌传播

quarkus-rest-client-oidc-token-propagation 扩展提供了一个 REST 客户端过滤器 io.quarkus.oidc.token.propagation.reactive.AccessTokenRequestReactiveFilter,它简化了身份验证信息的传播。此客户端将当前活动请求中存在的 bearer 令牌 或从 authorization code flow 机制获取的令牌作为 HTTP Authorization 标头中的 Bearer 方案值进行传播。

您可以通过使用 io.quarkus.oidc.token.propagation.common.AccessTokenorg.eclipse.microprofile.rest.client.annotation.RegisterProvider 注解来选择性地注册 AccessTokenRequestReactiveFilter,例如:

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();
}

import org.eclipse.microprofile.rest.client.annotation.RegisterProvider;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import io.quarkus.oidc.token.propagation.reactive.AccessTokenRequestReactiveFilter;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;

@RegisterRestClient
@RegisterProvider(AccessTokenRequestReactiveFilter.class)
@Path("/")
public interface ProtectedResourceService {

    @GET
    String getUserName();
}

此外,AccessTokenRequestReactiveFilter 可以支持需要先交换令牌再进行传播的复杂应用程序。

如果您使用 Keycloak 或其他支持 Token Exchange 令牌授予的 OIDC 提供商,则可以按如下方式配置 AccessTokenRequestReactiveFilter 来交换令牌:

quarkus.oidc-client.auth-server-url=https://: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.rest-client-oidc-token-propagation.exchange-token=true (1)
1 请注意,当 OidcClient 名称通过 io.quarkus.oidc.token.propagation.common.AccessToken#exchangeTokenClient 注解属性设置时,exchange-token 配置属性将被忽略。
AccessTokenRequestReactiveFilter 将使用 OidcClient 来交换当前令牌,您可以使用 quarkus.oidc-client.grant-options.exchange 来设置您的 OpenID Connect 提供商期望的额外交换属性。

如果您使用 Azure 等提供商,它们 要求使用 JWT bearer token grant 来交换当前令牌,则可以按如下方式配置 AccessTokenRequestReactiveFilter 来交换令牌:

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

AccessTokenRequestReactiveFilter 默认使用一个默认的 OidcClient。可以通过 quarkus.rest-client-oidc-token-propagation.client-name 配置属性或 io.quarkus.oidc.token.propagation.common.AccessToken#exchangeTokenClient 注解属性来选择一个命名的 OidcClient

RESTEasy Classic 的令牌传播

quarkus-resteasy-client-oidc-token-propagation 扩展提供了两个 Jakarta REST jakarta.ws.rs.client.ClientRequestFilter 类实现,它们简化了身份验证信息的传播。io.quarkus.oidc.token.propagation.AccessTokenRequestFilter 将当前活动请求中存在的 Bearer 令牌 或从 Authorization code flow 机制获取的令牌作为 HTTP Authorization 标头中的 Bearer 方案值进行传播。io.quarkus.oidc.token.propagation.JsonWebTokenRequestFilter 提供相同的功能,但此外还支持 JWT 令牌。

当您需要传播当前的 Authorization Code Flow 访问令牌时,即时令牌传播将工作得很好——因为代码流访问令牌(与 ID 令牌相对)旨在被传播,以便当前的 Quarkus 端点可以代表当前已进行身份验证的用户来访问远程服务。

但是,应避免直接的端到端 Bearer 令牌传播。例如,Client → Service A → Service B,其中 Service B 接收由 Client 发送到 Service A 的令牌。在这种情况下,Service B 无法区分令牌是来自 Service A 还是直接来自 Client。为了让 Service B 验证令牌来自 Service A,它应该能够断言新的发行者和受众声明。

此外,复杂的应用程序可能需要先交换或更新令牌,然后再进行传播。例如,当 Service A 访问 Service B 时,访问上下文可能不同。在这种情况下,Service A 可能被授予更窄或完全不同的范围集来访问 Service B

以下各节将展示 AccessTokenRequestFilterJsonWebTokenRequestFilter 如何提供帮助。

RestClient AccessTokenRequestFilter

AccessTokenRequestFilter 将所有令牌视为字符串,因此它可以处理 JWT 和不透明令牌。

您可以通过使用 io.quarkus.oidc.token.propagation.common.AccessTokenorg.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();
}

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();
}

或者,如果将 quarkus.resteasy-client-oidc-token-propagation.register-filter 属性设置为 true 并且 quarkus.resteasy-client-oidc-token-propagation.json-web-token 属性设置为 false(这是默认值),则可以自动将 AccessTokenRequestFilter 注册到所有 MP REST 或 Jakarta REST 客户端。

传播前交换令牌

如果需要在传播前交换当前访问令牌,并且您使用的是 Keycloak 或其他支持 Token Exchange 令牌授予的 OpenID Connect 提供商,则可以按如下方式配置 AccessTokenRequestFilter

quarkus.oidc-client.auth-server-url=https://: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

如果您使用 Azure 等提供商,它们 要求使用 JWT bearer token grant 来交换当前令牌,则可以按如下方式配置 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
AccessTokenRequestFilter 将使用 OidcClient 来交换当前令牌,您可以使用 quarkus.oidc-client.grant-options.exchange 来设置您的 OpenID Connect 提供商期望的额外交换属性。

AccessTokenRequestFilter 默认使用一个默认的 OidcClient。可以通过 quarkus.resteasy-client-oidc-token-propagation.client-name 配置属性来选择一个命名的 OidcClient

RestClient JsonWebTokenRequestFilter

如果您使用 Bearer JWT 令牌,并且这些令牌的声明(如 issueraudience)可以被修改并重新签名,则建议使用 JsonWebTokenRequestFilter。它需要注入 org.eclipse.microprofile.jwt.JsonWebToken,因此无法处理不透明令牌。此外,如果您的 OpenID Connect 提供商支持令牌交换协议,则建议改用 AccessTokenRequestFilter——因为 AccessTokenRequestFilter 可以安全地交换 JWT 和不透明的 bearer 令牌。

JsonWebTokenRequestFilter 使 Service A 实现能够轻松地使用新的 issueraudience 声明值更新注入的 org.eclipse.microprofile.jwt.JsonWebToken,并使用新的签名再次保护更新后的令牌。唯一困难的步骤是确保 Service A 拥有签名密钥,该密钥应从安全的文件系统或远程安全存储(如 Vault)提供。

您可以通过使用 io.quarkus.oidc.token.propagation.JsonWebTokenorg.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();
}

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();
}

或者,如果将 quarkus.resteasy-client-oidc-token-propagation.register-filterquarkus.resteasy-client-oidc-token-propagation.json-web-token 属性都设置为 true,则可以自动将 JsonWebTokenRequestFilter 注册到所有 MicroProfile REST 或 Jakarta REST 客户端。

传播前更新令牌

如果需要更新注入的令牌的 iss(发行者)或 aud(受众)声明并使用新签名再次保护,则可以按如下方式配置 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

如前所述,如果您使用 Keycloak 或支持令牌交换协议的 OpenID Connect 提供商,请使用 AccessTokenRequestFilter

测试

通常,您需要准备两个 REST 测试端点。第一个端点使用注入的 MP REST 客户端和已注册的令牌传播过滤器来调用第二个端点。

要了解如何执行此操作,请遵循 OpenID Connect 客户端和令牌传播 快速入门,特别是其 测试 部分。

GraphQL 客户端集成

quarkus-oidc-client-graphql 扩展提供了一种将 OIDC 客户端集成到 GraphQL 客户端 中的方法,该方法与 REST 客户端的方法类似。当此扩展激活时,通过属性配置的任何 GraphQL 客户端(而非通过生成器以编程方式配置)将使用 OIDC 客户端获取访问令牌,然后将其设置为 Authorization 标头值。OIDC 客户端还将刷新过期的访问令牌。

要配置 GraphQL 客户端使用的 OIDC 客户端,请使用 quarkus.oidc-client-graphql.client-name 属性选择一个已配置的 OIDC 客户端,例如:

quarkus.oidc-client-graphql.client-name=oidc-client-for-graphql

# example declaration of the OIDC client itself
quarkus.oidc-client.oidc-client-for-graphql.auth-server-url=${keycloak.url}
quarkus.oidc-client.oidc-client-for-graphql.grant.type=password
quarkus.oidc-client.oidc-client-for-graphql.grant-options.password.username=${username}
quarkus.oidc-client.oidc-client-for-graphql.grant-options.password.password=${password}
quarkus.oidc-client.oidc-client-for-graphql.client-id=${quarkus.oidc.client-id}
quarkus.oidc-client.oidc-client-for-graphql.credentials.client-secret.value=${keycloak.credentials.secret}
quarkus.oidc-client.oidc-client-for-graphql.credentials.client-secret.method=POST
如果您不指定 quarkus.oidc-client-graphql.client-name 属性,GraphQL 客户端将使用默认的 OIDC 客户端(无显式名称)。

特别对于类型安全的 GraphQL 客户端,您可以通过用 @io.quarkus.oidc.client.filter.OidcClientFilter 注解 GraphQLClientApi 接口来覆盖此设置,每个客户端一个。例如:

@GraphQLClientApi(configKey = "order-client")
@OidcClientFilter("oidc-client-for-graphql")
public interface OrdersGraphQLClient {
    // Queries, mutations, and subscriptions go here.
}

要使用程序创建的 GraphQL 客户端来实现此目的,构建器(VertxDynamicGraphQLClientBuilderVertxTypesafeGraphQLClientBuilder)都包含一个 dynamicHeader(String, Uni<String>) 方法,允许您插入一个可能在每次请求时都会更改的标头。要将其插入 OIDC 客户端,请使用:

@Inject
OidcClients oidcClients;

VertxTypesafeGraphQLClientBuilder builder = ....;
Uni<String> tokenUni = oidcClients.getClient("OIDC_CLIENT_NAME")
    .getTokens().map(t -> "Bearer " + t.getAccessToken());
builder.dynamicHeader("Authorization", tokenUni);
VertxDynamicGraphQLClient client = builder.build();

配置参考

OIDC 客户端

构建时固定的配置属性 - 所有其他配置属性都可以在运行时覆盖

配置属性

类型

默认

如果 OIDC 客户端扩展已启用。

环境变量:QUARKUS_OIDC_CLIENT_ENABLED

显示更多

布尔值

true

quarkus.oidc-client."id".auth-server-url

OpenID Connect (OIDC) 服务器的基础 URL,例如 https://host:port/auth。如果使用 'quarkus-oidc' 并且需要公钥验证(public-key)或仅证书链验证(certificate-chain),请不要设置此属性。默认情况下,通过将 .well-known/openid-configuration 路径附加到此 URL 来调用 OIDC 发现端点。对于 Keycloak,请使用 https://host:port/realms/{realm},将 {realm} 替换为 Keycloak 领域名称。

环境变量:QUARKUS_OIDC_CLIENT_AUTH_SERVER_URL

显示更多

字符串

quarkus.oidc-client."id".discovery-enabled

OIDC 端点的发现。如果未启用,您必须单独配置 OIDC 端点 URL。

环境变量:QUARKUS_OIDC_CLIENT_DISCOVERY_ENABLED

显示更多

布尔值

true

quarkus.oidc-client."id".registration-path

OIDC 动态客户端注册端点的相对路径或绝对 URL。如果 discovery-enabledfalse 或必须自定义发现的令牌端点路径,则进行设置。

环境变量:QUARKUS_OIDC_CLIENT_REGISTRATION_PATH

显示更多

字符串

quarkus.oidc-client."id".connection-delay

尝试初始连接到 OIDC 服务器的持续时间。例如,将持续时间设置为 20S 允许重试 10 次,每次间隔 2 秒。此属性仅在创建初始 OIDC 连接时生效。对于已断开的连接,请改用 connection-retry-count 属性。

环境变量:QUARKUS_OIDC_CLIENT_CONNECTION_DELAY

显示更多

Duration 

quarkus.oidc-client."id".connection-retry-count

如果现有的 OIDC 连接暂时丢失,则重试重新建立连接的次数。与仅适用于初始连接尝试的 connection-delay 不同。例如,如果对 OIDC 令牌端点的请求因连接问题而失败,它将根据此设置进行重试。

环境变量:QUARKUS_OIDC_CLIENT_CONNECTION_RETRY_COUNT

显示更多

整数

3

quarkus.oidc-client."id".connection-timeout

当前 OIDC 连接请求超时的秒数。

环境变量:QUARKUS_OIDC_CLIENT_CONNECTION_TIMEOUT

显示更多

Duration 

10S

quarkus.oidc-client."id".use-blocking-dns-lookup

是否应在工作线程上执行 DNS 查找。当您看到有关 HTTP 请求阻塞 Vert.x 事件循环的已记录警告时,请使用此选项。

环境变量:QUARKUS_OIDC_CLIENT_USE_BLOCKING_DNS_LOOKUP

显示更多

布尔值

false

quarkus.oidc-client."id".max-pool-size

WebClient 使用的连接池的最大大小。

环境变量:QUARKUS_OIDC_CLIENT_MAX_POOL_SIZE

显示更多

整数

quarkus.oidc-client."id".follow-redirects

当 WebClient 收到 HTTP 302 时自动遵循重定向。禁用此属性后,只允许单个重定向到完全相同的原始 URI,但前提是在重定向请求期间设置了一个或多个 cookie。

环境变量:QUARKUS_OIDC_CLIENT_FOLLOW_REDIRECTS

显示更多

布尔值

true

quarkus.oidc-client."id".token-path

颁发访问令牌和刷新令牌的 OIDC 令牌端点;指定为相对路径或绝对 URL。如果 discovery-enabledfalse,或者必须自定义发现的令牌端点路径,请设置此属性。

环境变量:QUARKUS_OIDC_CLIENT_TOKEN_PATH

显示更多

字符串

quarkus.oidc-client."id".revoke-path

OIDC 令牌吊销端点的相对路径或绝对 URL。

环境变量:QUARKUS_OIDC_CLIENT_REVOKE_PATH

显示更多

字符串

quarkus.oidc-client."id".client-id

应用程序的客户端 ID。每个应用程序都有一个客户端 ID,用于标识该应用程序。如果 application-typeservice 并且不需要令牌内省,则不需要设置客户端 ID。

环境变量:QUARKUS_OIDC_CLIENT_CLIENT_ID

显示更多

字符串

quarkus.oidc-client."id".client-name

应用程序的客户端名称。它用于表示您在 OIDC 提供商的仪表板中注册应用程序(客户端)时可以提供的应用程序的可读描述。例如,您可以设置此属性以获得更具信息性的日志消息,这些消息记录给定客户端的活动。

环境变量:QUARKUS_OIDC_CLIENT_CLIENT_NAME

显示更多

字符串

quarkus.oidc-client."id".id

唯一的 OIDC 客户端标识符。创建动态 OIDC 客户端时必须设置此属性,在所有其他情况下它是可选的。

环境变量:QUARKUS_OIDC_CLIENT_ID

显示更多

字符串

quarkus.oidc-client."id".client-enabled

如果此客户端配置已启用。

环境变量:QUARKUS_OIDC_CLIENT_CLIENT_ENABLED

显示更多

布尔值

true

quarkus.oidc-client."id".scopes

访问令牌范围列表

环境变量:QUARKUS_OIDC_CLIENT_SCOPES

显示更多

字符串列表

quarkus.oidc-client."id".refresh-token-time-skew

刷新令牌时间偏移。如果启用了此属性,则配置的持续时间将转换为秒,并在检查访问令牌是否应刷新时加到当前时间。如果总和大于此访问令牌的过期时间,则将发生刷新。

环境变量:QUARKUS_OIDC_CLIENT_REFRESH_TOKEN_TIME_SKEW

显示更多

Duration 

quarkus.oidc-client."id".access-token-expires-in

访问令牌过期时间,相对于当前时间。仅当访问令牌获取响应不包含访问令牌过期属性时,才会检查此属性。

环境变量:QUARKUS_OIDC_CLIENT_ACCESS_TOKEN_EXPIRES_IN

显示更多

Duration 

quarkus.oidc-client."id".access-token-expiry-skew

访问令牌过期时间偏移,可以添加到计算出的令牌过期时间。

环境变量:QUARKUS_OIDC_CLIENT_ACCESS_TOKEN_EXPIRY_SKEW

显示更多

Duration 

quarkus.oidc-client."id".absolute-expires-in

是否应将访问令牌 'expires_in' 属性检查为绝对时间值,而不是相对于当前时间的持续时间。

环境变量:QUARKUS_OIDC_CLIENT_ABSOLUTE_EXPIRES_IN

显示更多

布尔值

false

quarkus.oidc-client."id".grant.type

授予类型

环境变量:QUARKUS_OIDC_CLIENT_GRANT_TYPE

显示更多

client'client_credentials' 授予,仅需要 OIDC 客户端身份验证, password'password' 授予,需要 OIDC 客户端和用户('username' 和 'password')的身份验证, code'authorization_code' 授予,需要 OIDC 客户端身份验证以及至少 'code' 和 'redirect_uri' 参数,这些参数必须在令牌请求时传递给 OidcClient。, exchange'urn\:ietf\:params\:oauth\:grant-type\:token-exchange' 授予,需要 OIDC 客户端身份验证以及至少 'subject_token' 参数,该参数必须在令牌请求时传递给 OidcClient。, jwt'urn\:ietf\:params\:oauth\:grant-type\:jwt-bearer' 授予,需要 OIDC 客户端身份验证以及至少一个 'assertion' 参数,该参数必须在令牌请求时传递给 OidcClient。, refresh'refresh_token' 授予,需要 OIDC 客户端身份验证和刷新令牌。注意,OidcClient 默认支持此授予,如果访问令牌获取响应包含刷新令牌。但是,在某些情况下,刷新令牌是带外提供的,例如,它可以由多个机密客户端的服务共享等。如果 'quarkus.oidc-client.grant-type' 设置为 'refresh',则 OidcClient 将仅支持刷新令牌。, ciba'urn\:openid\:params\:grant-type\:ciba' 授予,需要 OIDC 客户端身份验证以及 'auth_req_id' 参数,该参数必须在令牌请求时传递给 OidcClient。, device'urn\:ietf\:params\:oauth\:grant-type\:device_code' 授予,需要 OIDC 客户端身份验证以及 'device_code' 参数,该参数必须在令牌请求时传递给 OidcClient。

client'client_credentials' 授予,仅需要 OIDC 客户端身份验证

quarkus.oidc-client."id".grant.access-token-property

令牌授予响应中的访问令牌属性名

环境变量:QUARKUS_OIDC_CLIENT_GRANT_ACCESS_TOKEN_PROPERTY

显示更多

字符串

access_token

quarkus.oidc-client."id".grant.refresh-token-property

令牌授予响应中的刷新令牌属性名

环境变量:QUARKUS_OIDC_CLIENT_GRANT_REFRESH_TOKEN_PROPERTY

显示更多

字符串

refresh_token

quarkus.oidc-client."id".grant.expires-in-property

令牌授予响应中的访问令牌过期时间属性名

环境变量:QUARKUS_OIDC_CLIENT_GRANT_EXPIRES_IN_PROPERTY

显示更多

字符串

expires_in

quarkus.oidc-client."id".grant.refresh-expires-in-property

令牌授予响应中的刷新令牌过期时间属性名

环境变量:QUARKUS_OIDC_CLIENT_GRANT_REFRESH_EXPIRES_IN_PROPERTY

显示更多

字符串

refresh_expires_in

quarkus.oidc-client."id".grant-options."grant-name"

授权选项

环境变量:QUARKUS_OIDC_CLIENT_GRANT_OPTIONS__GRANT_NAME_

显示更多

Map<String,Map<String,String>>

quarkus.oidc-client."id".early-tokens-acquisition

要求所有使用 'OidcClient' 的过滤器在 post-construct 初始化时获取令牌,可能在这些令牌被使用之前很久。如果访问令牌可能在第一次使用之前过期且没有刷新令牌可用,则应禁用此属性。

环境变量:QUARKUS_OIDC_CLIENT_EARLY_TOKENS_ACQUISITION

显示更多

布尔值

true

quarkus.oidc-client."id".headers."headers"

必须发送到令牌端点的自定义 HTTP 标头

环境变量:QUARKUS_OIDC_CLIENT_HEADERS__HEADERS_

显示更多

Map<String,String>

HTTP 代理配置

类型

默认

quarkus.oidc-client."id".proxy.host

代理的主机名或 IP 地址。
注意:如果 OIDC 适配器需要代理才能与 OIDC 服务器(提供程序)通信,请设置此值以启用代理的使用。

环境变量:QUARKUS_OIDC_CLIENT_PROXY_HOST

显示更多

字符串

quarkus.oidc-client."id".proxy.port

代理的端口号。默认值为 80

环境变量:QUARKUS_OIDC_CLIENT_PROXY_PORT

显示更多

整数

80

quarkus.oidc-client."id".proxy.username

用户名(如果代理需要身份验证)。

环境变量:QUARKUS_OIDC_CLIENT_PROXY_USERNAME

显示更多

字符串

quarkus.oidc-client."id".proxy.password

密码(如果代理需要身份验证)。

环境变量:QUARKUS_OIDC_CLIENT_PROXY_PASSWORD

显示更多

字符串

TLS 配置

类型

默认

quarkus.oidc-client."id".tls.tls-configuration-name

要使用的 TLS 配置的名称。

如果配置了名称,它将使用来自 quarkus.tls.<name>.* 的配置。如果配置了名称,但找不到具有该名称的 TLS 配置,则将引发错误。

默认情况下,使用默认 TLS 配置。

环境变量:QUARKUS_OIDC_CLIENT_TLS_TLS_CONFIGURATION_NAME

显示更多

字符串

OIDC 客户端用于访问 OIDC 令牌和其他受保护端点的不同身份验证选项

类型

默认

quarkus.oidc-client."id".credentials.secret

client_secret_basic 身份验证方法使用的客户端 secret。除非在 client-secret 中设置了 secret 或需要 jwt 客户端身份验证,否则必须设置此项。您可以使用 client-secret.value 代替,但这两个属性是互斥的。

环境变量:QUARKUS_OIDC_CLIENT_CREDENTIALS_SECRET

显示更多

字符串

quarkus.oidc-client."id".credentials.client-secret.value

客户端密钥值。如果设置了 credentials.secret,则忽略此值。除非在 client-secret 中设置了密钥或需要 jwt 客户端身份验证,否则必须设置。

环境变量:QUARKUS_OIDC_CLIENT_CREDENTIALS_CLIENT_SECRET_VALUE

显示更多

字符串

quarkus.oidc-client."id".credentials.client-secret.provider.name

CredentialsProvider bean 名称,只有在注册了多个 CredentialsProvider 时才应设置

环境变量:QUARKUS_OIDC_CLIENT_CREDENTIALS_CLIENT_SECRET_PROVIDER_NAME

显示更多

字符串

quarkus.oidc-client."id".credentials.client-secret.provider.keyring-name

CredentialsProvider 的密钥库名称。当使用的 CredentialsProvider 需要密钥库名称来查找 secret 时,通常需要此密钥库名称,这在 CredentialsProvider 被多个扩展共享以从更动态的源(如 vault 实例或 secret manager)检索凭据时经常发生。

环境变量:QUARKUS_OIDC_CLIENT_CREDENTIALS_CLIENT_SECRET_PROVIDER_KEYRING_NAME

显示更多

字符串

quarkus.oidc-client."id".credentials.client-secret.provider.key

CredentialsProvider 客户端密钥

环境变量:QUARKUS_OIDC_CLIENT_CREDENTIALS_CLIENT_SECRET_PROVIDER_KEY

显示更多

字符串

quarkus.oidc-client."id".credentials.client-secret.method

身份验证方法。如果设置了 clientSecret.value 密钥,则此方法默认为 basic

环境变量:QUARKUS_OIDC_CLIENT_CREDENTIALS_CLIENT_SECRET_METHOD

显示更多

basicclient_secret_basic (默认):客户端 ID 和 secret 使用 HTTP Authorization Basic 方案提交。, postclient_secret_post:客户端 ID 和 secret 作为 client_idclient_secret 表单参数提交。, post-jwtclient_secret_jwt:客户端 ID 和生成的 JWT secret 作为 client_idclient_secret 表单参数提交。, query客户端 ID 和 secret 作为 HTTP 查询参数提交。此选项仅受 OIDC 扩展支持。

quarkus.oidc-client."id".credentials.jwt.source

JWT 令牌源:OIDC 提供程序客户端或现有 JWT 持有者令牌。

环境变量:QUARKUS_OIDC_CLIENT_CREDENTIALS_JWT_SOURCE

显示更多

clientJWT 令牌由 OIDC 提供商客户端生成,用于支持 client_secret_jwtprivate_key_jwt 身份验证方法。, bearerJWT bearer 令牌用作客户端断言:https\://www.rfc-editor.org/rfc/rfc7523#section-2.2。

clientJWT 令牌由 OIDC 提供程序客户端生成,以支持 client_secret_jwtprivate_key_jwt 身份验证方法。

quarkus.oidc-client."id".credentials.jwt.token-path

包含 JWT 持有者令牌的文件的路径,该令牌应用作客户端断言。仅当 JWT 源 (source()) 设置为 Source#BEARER 时,才能设置此路径。

环境变量:QUARKUS_OIDC_CLIENT_CREDENTIALS_JWT_TOKEN_PATH

显示更多

path

quarkus.oidc-client."id".credentials.jwt.secret

如果提供,则表示 JWT 使用密钥签名。它与 keykey-filekey-store 属性互斥。

环境变量:QUARKUS_OIDC_CLIENT_CREDENTIALS_JWT_SECRET

显示更多

字符串

quarkus.oidc-client."id".credentials.jwt.secret-provider.name

CredentialsProvider bean 名称,只有在注册了多个 CredentialsProvider 时才应设置

环境变量:QUARKUS_OIDC_CLIENT_CREDENTIALS_JWT_SECRET_PROVIDER_NAME

显示更多

字符串

quarkus.oidc-client."id".credentials.jwt.secret-provider.keyring-name

CredentialsProvider 的密钥库名称。当使用的 CredentialsProvider 需要密钥库名称来查找 secret 时,通常需要此密钥库名称,这在 CredentialsProvider 被多个扩展共享以从更动态的源(如 vault 实例或 secret manager)检索凭据时经常发生。

环境变量:QUARKUS_OIDC_CLIENT_CREDENTIALS_JWT_SECRET_PROVIDER_KEYRING_NAME

显示更多

字符串

quarkus.oidc-client."id".credentials.jwt.secret-provider.key

CredentialsProvider 客户端密钥

环境变量:QUARKUS_OIDC_CLIENT_CREDENTIALS_JWT_SECRET_PROVIDER_KEY

显示更多

字符串

quarkus.oidc-client."id".credentials.jwt.key

私钥的字符串表示。如果提供,表示 JWT 使用 PEM 或 JWK 格式的私钥进行签名。它与 secretkey-filekey-store 属性互斥。您可以使用 signature-algorithm 属性来覆盖默认密钥算法 RS256

环境变量:QUARKUS_OIDC_CLIENT_CREDENTIALS_JWT_KEY

显示更多

字符串

quarkus.oidc-client."id".credentials.jwt.key-file

如果提供,表示 JWT 使用 PEM 或 JWK 格式的私钥进行签名。它与 secretkeykey-store 属性互斥。您可以使用 signature-algorithm 属性来覆盖默认密钥算法 RS256

环境变量:QUARKUS_OIDC_CLIENT_CREDENTIALS_JWT_KEY_FILE

显示更多

字符串

quarkus.oidc-client."id".credentials.jwt.key-store-file

如果提供,则表示 JWT 使用密钥库中的私钥签名。它与 secretkeykey-file 属性互斥。

环境变量:QUARKUS_OIDC_CLIENT_CREDENTIALS_JWT_KEY_STORE_FILE

显示更多

字符串

quarkus.oidc-client."id".credentials.jwt.key-store-password

用于指定密钥库文件密码的参数。

环境变量:QUARKUS_OIDC_CLIENT_CREDENTIALS_JWT_KEY_STORE_PASSWORD

显示更多

字符串

quarkus.oidc-client."id".credentials.jwt.key-id

私钥 ID 或别名。

环境变量:QUARKUS_OIDC_CLIENT_CREDENTIALS_JWT_KEY_ID

显示更多

字符串

quarkus.oidc-client."id".credentials.jwt.key-password

私钥密码。

环境变量:QUARKUS_OIDC_CLIENT_CREDENTIALS_JWT_KEY_PASSWORD

显示更多

字符串

quarkus.oidc-client."id".credentials.jwt.audience

JWT 受众 (aud) 声明值。默认情况下,受众设置为 OpenId Connect 提供程序的令牌端点的地址。

环境变量:QUARKUS_OIDC_CLIENT_CREDENTIALS_JWT_AUDIENCE

显示更多

字符串

quarkus.oidc-client."id".credentials.jwt.token-key-id

作为 JWT kid 标头添加的签名密钥的密钥标识符。

环境变量:QUARKUS_OIDC_CLIENT_CREDENTIALS_JWT_TOKEN_KEY_ID

显示更多

字符串

quarkus.oidc-client."id".credentials.jwt.issuer

作为 JWT iss 声明添加的签名密钥的颁发者。默认值为客户端 ID。

环境变量:QUARKUS_OIDC_CLIENT_CREDENTIALS_JWT_ISSUER

显示更多

字符串

quarkus.oidc-client."id".credentials.jwt.subject

作为 JWT sub 声明添加的签名密钥的主题。默认值为客户端 ID。

环境变量:QUARKUS_OIDC_CLIENT_CREDENTIALS_JWT_SUBJECT

显示更多

字符串

quarkus.oidc-client."id".credentials.jwt.claims."claim-name"

其他声明。

环境变量:QUARKUS_OIDC_CLIENT_CREDENTIALS_JWT_CLAIMS__CLAIM_NAME_

显示更多

Map<String,String>

quarkus.oidc-client."id".credentials.jwt.signature-algorithm

用于 key-file 属性的签名算法。支持的值:RS256(默认)、RS384RS512PS256PS384PS512ES256ES384ES512HS256HS384HS512

环境变量:QUARKUS_OIDC_CLIENT_CREDENTIALS_JWT_SIGNATURE_ALGORITHM

显示更多

字符串

quarkus.oidc-client."id".credentials.jwt.lifespan

JWT 生存期(以秒为单位)。此值添加到 JWT 颁发的时间,以计算到期时间。

环境变量:QUARKUS_OIDC_CLIENT_CREDENTIALS_JWT_LIFESPAN

显示更多

整数

10

quarkus.oidc-client."id".credentials.jwt.assertion

如果为 true,则客户端身份验证令牌是 JWT 持有者授权断言。将仅生成 'assertion',而不是生成 'client_assertion' 和 'client_assertion_type' 表单属性。此选项仅受 OIDC 客户端扩展支持。

环境变量:QUARKUS_OIDC_CLIENT_CREDENTIALS_JWT_ASSERTION

显示更多

布尔值

false

关于 Duration 格式

要编写持续时间值,请使用标准的 java.time.Duration 格式。有关更多信息,请参阅 Duration#parse() Java API 文档

您还可以使用简化的格式,以数字开头

  • 如果该值仅为一个数字,则表示以秒为单位的时间。

  • 如果该值是一个数字后跟 ms,则表示以毫秒为单位的时间。

在其他情况下,简化格式将被转换为 java.time.Duration 格式以进行解析

  • 如果该值是一个数字后跟 hms,则在其前面加上 PT

  • 如果该值是一个数字后跟 d,则在其前面加上 P

OIDC 令牌传播

构建时固定的配置属性 - 所有其他配置属性都可以在运行时覆盖

配置属性

类型

默认

如果 OIDC 令牌响应式传播已启用。

环境变量:QUARKUS_REST_CLIENT_OIDC_TOKEN_PROPAGATION_ENABLED

显示更多

布尔值

true

SecurityIdentity 增强期间是否启用令牌传播。

例如,您可能需要从 SecurityIdentityAugmentor 使用 REST 客户端来传播当前令牌,以便为 SecurityIdentity 获取额外的角色。

注意,此功能依赖于复制的上下文。有关 Vert.x 复制上下文的更多信息,请参阅 此指南

环境变量:QUARKUS_REST_CLIENT_OIDC_TOKEN_PROPAGATION_ENABLED_DURING_AUTHENTICATION

显示更多

布尔值

false

使用 "urn:ietf:params:oauth:grant-type:token-exchange" 或 "urn:ietf:params:oauth:grant-type:jwt-bearer" 令牌授予,将当前令牌与 OpenId Connect 提供商交换以获取新令牌,然后再进行传播。

环境变量:QUARKUS_REST_CLIENT_OIDC_TOKEN_PROPAGATION_EXCHANGE_TOKEN

显示更多

布尔值

false

已配置的 OidcClient 的名称。注意,仅当启用了 exchangeToken 属性时,才会使用此属性。

环境变量:QUARKUS_REST_CLIENT_OIDC_TOKEN_PROPAGATION_CLIENT_NAME

显示更多

字符串

相关内容