Configuring Well-Known OpenID Connect Providers

Introduction

如果您使用 OpenID Connect Authorization Code Flow 保护 Quarkus 端点,那么您需要配置 Quarkus 来告诉它如何连接到 OpenID Connect 提供者,如何对这些提供者进行身份验证,要使用的作用域,等等。

有时,您需要使用配置来解决某些提供者尚未完全实现 OpenID Connect 或它们实际上是 OAuth2 providers only 的问题。

此类提供程序的配置可能变得复杂、技术性很强以及难以理解。

quarkus.oidc.provider 配置属性已被引入以引用众所周知的 OpenID Connect 和 OAuth2 提供者。该属性可用于引用诸如 github 的提供者,只需最少数量的自定义,通常,帐户特定的 client idclient secret 并且必须设置一些属性来完成配置。

该属性可用于 application.properties 中,如果必须配置多个提供者则使用 multi-tenant 设置(例如,请参见 ` Quarkus Renarde security documentation),如果租户配置是动态创建的,则在自定义 `TenantConfigResolvers 中使用。

Well Known Providers

Apple

为了为 Apple 设置 OIDC,您需要创建一个开发者帐户并注册 99€/年的计划,但是您无法像大多数其他 OIDC 提供者那样在 localhost 上测试您的应用程序:您需要通过 HTTPS 运行它并使其公开可访问,因此,出于开发目的,您可能希望使用像 [role="bare"]https://ngrok.com 这样的服务。

转至 ` Create a new identifier` 并按 +

oidc apple 1

不要碰任何东西,保持 App IDs 选中,然后按 Continue

oidc apple 2

不要碰任何东西,保持 App 选中,然后按 Continue

oidc apple 3

输入描述和包 ID(使用您的应用程序包名称):

oidc apple 4

然后向下滚动以查找 Sign in with Apple 功能,选择它,然后按 Continue

oidc apple 5

记下您的应用程序 ID 前缀,然后按 Register

oidc apple 6

回到 Identifiers 页面,按 +

oidc apple 7

选择 Service IDs 并按 Continue

oidc apple 8

输入描述和包 ID(使用您的应用程序包名称),然后按 Continue

oidc apple 9

现在按 Register

oidc apple 10

回到服务列表,单击您新创建的服务:

oidc apple 11

启用 Sign in with Apple 并按 Configure

oidc apple 12

添加您的域名和返回 URL(设置为 <host>/_renarde/security/oidc-success)并按 Next

oidc apple 13

现在按下 Done

oidc apple 14

现在按下 Continue

oidc apple 15

现在按下 Save

oidc apple 16

前往左侧菜单中的 Keys 页面,然后按下 +

oidc apple 17

填写一个键名称,启用 Sign in with Apple,然后按下 Configure

oidc apple 18

选择你的主要应用 ID,然后按下 Save

oidc apple 19

返回到该键页面,按下 Continue

oidc apple 20

现在按 Register

oidc apple 21

写下你的 Key ID,下载你的键,然后将其保存在 src/main/resources/AuthKey_<KEYID>.p8 中的 Quarkus 应用程序中

oidc apple 22

你现在可以配置你的 application.properties

quarkus.oidc.provider=apple
quarkus.oidc.client-id=<Bundle ID>
quarkus.oidc.credentials.jwt.key-file=AuthKey_<Key ID>.p8
quarkus.oidc.credentials.jwt.token-key-id=<Key ID>
quarkus.oidc.credentials.jwt.issuer=<App ID Prefix>
quarkus.oidc.credentials.jwt.subject=<Bundle ID}

quarkus.oidc.provider=apple 将请求 Apple 将 openidemailname 范围添加到颁发的访问令牌。关于覆盖这些范围或请求更多范围的信息,请参阅 Provider scopes 部分。

Discord

创建一个 Discord application

oidc discord 1

你现在可以获取你的客户端 ID 和 secret

oidc discord 2

你现在可以配置你的 application.properties

quarkus.oidc.provider=discord
quarkus.oidc.client-id=<Client ID>
quarkus.oidc.credentials.client-secret=<Client Secret>

Facebook

Facebook 与大多数其他 OIDC 提供商不同,它不允许你对应用程序在 localhost 上进行测试:你需要通过 HTTPS 来运行它,并使其面向公众开放访问,因此出于开发目的,你可能希望使用如下服务 [role="bare"][role="bare"]https://ngrok.com

为了开始设置 Facebook 的 OIDC,首先 Creating an application,选择 None 作为一种应用程序类型,然后按下 Next

oidc facebook 1

现在,输入一个应用程序名称和联系电子邮箱,然后按下 Create app

oidc facebook 2

在应用程序页面上,点击 Facebook login 产品中的 Set up

oidc facebook 3

快速访问 Quickstarts 页面,然后点击左侧菜单中的 Facebook login > Settings

oidc facebook 4

输入你的 Redirect URIs(设置为 <host>/_renarde/security/oidc-success),然后按下 Save changes

oidc facebook 5

现在前往左侧菜单中的 Settings > Basic,然后写下你的 App IDApp secret

oidc facebook 6

你现在可以配置你的 application.properties

quarkus.oidc.provider=facebook
quarkus.oidc.client-id=<App ID>
quarkus.oidc.credentials.secret=<App secret>

quarkus.oidc.provider=facebook 将请求 Facebook 把 emailpublic_profile 范围添加到颁发的访问令牌。有关覆盖这些范围或请求更多范围的信息,请参见 Provider scopes 部分。

GitHub

为了设置 GitHub 的 OIDC,你需要在 GitHub developer settings 中创建一个新的 OAuth 应用程序:

oidc github 1

务必填写适当的详细信息,但更重要的是授权回调 URL,设置为 http://localhost:8080/_renarde/security/github-success(如果你打算使用 Quarkus 开发模式测试此功能)。

现在点击 Register application,你将看到你的应用程序页面:

oidc github 2

你需要点击 Generate a new client secret,确认你的凭据,并写下你的客户端 ID 和客户端密钥(特别是客户端密钥,因为你以后无法再从该页面看到它,但你可以随时重新创建一个,所以不用太担心):

oidc github 3

现在将以下配置添加到你的 application.properties

quarkus.oidc.provider=github
quarkus.oidc.client-id=<Client ID>
quarkus.oidc.credentials.secret=<Secret>

quarkus.oidc.provider=github 将请求 GitHub 将 user:email 范围添加到颁发的访问令牌。有关覆盖此范围或请求更多范围的信息,请参见 Provider scopes 部分。

你还可以将由 GitHub 颁发的访问令牌发送到 quarkus.oidc.application-type=servicequarkus.oidc.application-type=hybrid Quarkus 应用程序。

Google

为了设置 Google 的 OIDC,你需要在 Google Cloud Platform console 中创建一个新项目:

选择一个项目名称,然后点击 CREATE

oidc google 1

现在确保在顶部选择器中选择你的项目,然后点击左侧栏菜单中的 APIs and Services > OAuth consent screen

oidc google 2

选择 External 授权任何 Google 用户登录你的应用程序,然后按 CREATE

oidc google 3

现在你可以填写你的应用程序名称、支持电子邮件、开发人员联系人信息,然后按 SAVE AND CONTINUE

oidc google 4

不要在下一页添加任何范围,然后按 SAVE AND CONTINUE

oidc google 5

不要在下一页添加任何测试用户,然后按 SAVE AND CONTINUE

oidc google 6

点击顶部菜单 CREATE CREDENTIALS> OAuth client ID

oidc google 7

Application type 选择为 Web application,在 Authorised redirect URIs 列表中添加 http://localhost:8080/_renarde/security/oidc-success,然后按 CREATE

oidc google 8

复制你的客户端 ID 和客户端密钥:

oidc google 9

你现在可以配置你的 application.properties

quarkus.oidc.provider=google
quarkus.oidc.client-id=<Client ID>
quarkus.oidc.credentials.secret=<Secret>

quarkus.oidc.provider=google 将请求 Google 把 openidemailprofile 范围添加到颁发的访问令牌。有关覆盖这些范围或请求更多范围的信息,请参见 Provider scopes 部分。

您还可以将 Google 发出的访问权限令牌发送到 quarkus.oidc.application-type=servicequarkus.oidc.application-type=hybrid Quarkus 应用程序。

LinkedIn

oidc linkedin 1

添加 Sign In with LinkedIn using OpenId Connect 产品:

oidc linkedin 2

您现在可以获取您的客户端 ID 和加密信息。别忘了还要为您的应用程序添加已授权的重定向 URL:

oidc linkedin 3

你现在可以配置你的 application.properties

quarkus.oidc.provider=linkedin
quarkus.oidc.client-id=<Client ID>
quarkus.oidc.credentials.client-secret=<Client Secret>

Mastodon

创建 Mastodon account。例如,您必须 pick a server mastodon.social。在您的帐户中选择一个 Development 选项并注册一个应用程序,例如:

oidc mastodon register app

选择已注册的应用程序:

oidc mastodon registered apps

并记下其客户端 ID 和客户端加密信息属性,使用它们来配置您的 application.properties

quarkus.oidc.provider=mastodon
quarkus.oidc.client-id=<Client ID>
quarkus.oidc.credentials.client-secret.value=<Client Secret>

默认情况下,quarkus.oidc.provider=mastodonquarkus.oidc.auth-server-url 设置为 https://mastodon.social Mastodon 服务器地址。

如果您在另一个 Mastodon 服务器中创建了您的帐户,您可以覆盖 quarkus.oidc.auth-server-url,例如:

quarkus.oidc.provider=mastodon
quarkus.oidc.auth-server-url=https://infosec.exchange
quarkus.oidc.client-id=<Client ID>
quarkus.oidc.credentials.client-secret.value=<Client Secret>

Microsoft

为了设置微软的 OIDC,您需要转到您的 Microsoft Azure Portal,并搜索 Azure Active Directory,然后点击它:

oidc microsoft 1

进入之后,在左侧的 Manage 下,点击 App registrations,然后点击 New registration

oidc microsoft 2

填写您的应用程序名称,选择 Accounts in any organizational directory (Any Azure AD directory - Multitenant) and personal Microsoft accounts (e.g. Skype, Xbox) 允许任何人登录,并添加 Web 重定向 URI 为 http://localhost:8080/_renarde/security/oidc-success,然后点击 Register

oidc microsoft 3

在结果页面上,复制 Client Id(在 Application (client) ID 下),然后点击 Add a certificate or secret

oidc microsoft 4

现在,在 Client secrets (0) 下,点击 New client secret

oidc microsoft 5

在该对话框中点击 Add,无需更改任何内容:

oidc microsoft 6

在结果页面上,复制您的 Secret Value

oidc microsoft 7

你现在可以配置你的 application.properties

quarkus.oidc.provider=microsoft
quarkus.oidc.client-id=<Client ID>
quarkus.oidc.credentials.secret=<Secret>

quarkus.oidc.provider=microsoft 将请求 Microsoft 为所发行的访问权限令牌添加 openidemailprofile 范围。有关覆盖这些范围或请求更多范围的信息,请参阅 Provider scopes 部分。

您还可以将 Microsoft 发出的访问权限令牌发送到 quarkus.oidc.application-type=servicequarkus.oidc.application-type=hybrid Quarkus 应用程序,但是如果您发送的 Microsoft 访问权限令牌不是 JWT 格式,则可能需要将 quarkus.oidc.verify-access-token-with-user-info 配置属性设置为 true

某些 Microsoft 服务可能会颁发令牌,其签名的验证需要使用当前令牌的 nonce 头重置为其 SHA-256 摘要值。如果您的应用程序必须处理此类令牌,请启用 Azure 令牌定制器:

quarkus.oidc.provider=microsoft
quarkus.oidc.client-id=<Client ID>
quarkus.oidc.credentials.secret=<Secret>
quarkus.oidc.token.customizer-name=azure-access-token-customizer

Spotify

oidc spotify 1

别忘了将 http://localhost:8080 添加为开发目的的测试重定向 URI。在 Spotify 应用程序设置完成后,您应该会获得一个已生成的客户端 ID 和密钥,例如:

oidc spotify 2

你现在可以配置你的 application.properties

quarkus.oidc.provider=spotify
quarkus.oidc.client-id=<Client ID>
quarkus.oidc.credentials.secret=<Client Secret>

quarkus.oidc.provider=spotify 会请求 Spotify 将 user-read-privateuser-read-email 范围添加到已颁发的访问令牌。有关覆盖这些范围或请求更多范围的信息,请参阅 Provider scopes 部分。

Strava

创建 Strava application

oidc strava 1

例如,将 Category 设置为 SocialMotivation,并将 ApplicationCallbackDomain 设置为 localhost 或 Ngrok 提供的域名,有关详细信息,请参阅 HTTPS Redirect URI

你现在可以配置你的 application.properties

quarkus.oidc.provider=strava
quarkus.oidc.client-id=<Client ID>
quarkus.oidc.credentials.client-secret=<Client Secret>
# default value is '/strava'
quarkus.oidc.authentication.redirect-path=/fitness/welcome 1
1 Strava 不强制要求提供作为授权代码流程参数的重定向 (回调) URI 等于在 Strava 应用程序中注册的 URI,因为它只需要配置 ApplicationCallbackDomain。例如,如果 ApplicationCallbackDomain 设置为 www.my-strava-example.com,Strava 将接受 www.my-strava-example.com/awww.my-strava-example.com/path/a 等重定向 URI,这并不符合 OAuth2 最佳安全实践,有关详细信息,请参阅 Insufficent redirect_uri validation。因此,当使用 Strava 提供商和 Quarkus 时,您必须配置重定向路径,并且 Quarkus 将强制要求当前请求路径与配置的 quarkus.oidc.authentication.redirect-path 值匹配后才能完成授权代码流程。有关详细信息,请参阅 Exact redirect URI match

Twitch

创建 Twitch application

oidc twitch 1

你现在可以配置你的 application.properties

quarkus.oidc.provider=twitch
quarkus.oidc.client-id=<Client ID>
quarkus.oidc.credentials.client-secret.value=<Client Secret>

[id="twitter"] X (formerly Twitter)

您可以使用 X (以前的 Twitter) 进行 OIDC 登录,但目前它限制了对用户电子邮件的访问,这意味着您必须自行获取并验证它。

要为 X 设置 OIDC,首先 Creating a project,输入一个项目名称,然后按 Next

oidc twitter 1

输入用例,然后按 Next

oidc twitter 2

输入项目说明,然后按 Next

oidc twitter 3

现在输入应用程序名称,然后按 Next

oidc twitter 4

记下您的密钥,因为它们不会再次显示,然后按 App Settings

oidc twitter 5

向下导航到 User authentication settings 部分,然后按 Set up

oidc twitter 6

选中 OAuth 2.0 复选框:

oidc twitter 7

选择 Web App`作为应用程序类型,然后填写您的应用程序详细信息(在 `Callback URI 中使用 <host>/_renarde/security/twitter-success)。

X 在实践中不要求使用 https,但在没有 https 的情况下也不会接受您的 Website URL,因此您仍然可以使用 ngrok 来处理它。

现在按 Save

oidc twitter 8

你现在可以复制你的 Client IDClient Secret,然后按下 Done

oidc twitter 9

你现在可以配置你的 application.properties

quarkus.oidc.provider=x
quarkus.oidc.client-id=<Client ID>
quarkus.oidc.credentials.secret=<Client Secret>

quarkus.oidc.provider=x 会要求 X 将 offline.accesstweet.readusers.read 范围添加到已颁发的访问令牌。有关覆写这些范围或请求更多范围的信息,请参阅 Provider scopes 部分。

X 供应商需要代码交换证明密钥 (PKCE),这受 quarkus.oidc.provider=x 声明支持。在使用 X 进行授权代码流时,Quarkus 必须在状态 cookie 中加密当前的 PKCE 代码验证器,并且会为其生成一个安全随机密钥以进行加密。 如果你愿意,可以使用 quarkus.oidc.authentication.state-secret 属性提供自己的密钥以加密 PKCE 代码验证器,但请注意此密钥应为 32 个字符长,如果少于 16 个字符,则会报告错误。

X 是 Twitter 的新名称。目前你仍可以使用 quarkus.oidc.provider=twitter,但将来可能不再推荐使用。

Provider scopes

每个供应商声明都会要求将一个或多个令牌范围添加到由某个特定供应商颁发的访问令牌中。例如,quarkus.oidc.provider=google 将要求 Google 添加 openidemailprofile 范围。

你可以使用 quarkus.oidc.authentication.scopes 属性覆写这些范围,例如,如果你使用 Google 并且不想在访问令牌中添加 email 范围:

quarkus.oidc.provider=google
quarkus.oidc.authentication.scopes=oidc,profile

你可能还想根据默认情况下请求的范围,额外添加一个或多个范围。例如,如果你想使用 Google 发行的访问令牌访问 Google Calendar 服务,你可以按如下方式进行操作:

quarkus.oidc.provider=google
quarkus.oidc.authentication.extra-params.scope=https://www.googleapis.com/auth/calendar

这比使用 quarkus.oidc.authentication.scopes 添加新范围简单,因为 quarkus.oidc.authentication.scopes 会覆写供应商声明已设置的范围,这就是为什么你必须在这种情况下列出所有必需的范围:

quarkus.oidc.provider=google
quarkus.oidc.authentication.scopes=oidc,email,profile,https://www.googleapis.com/auth/calendar

Support for multiple providers

如果你想支持使用多个供应商对用户进行身份验证,则必须支持特定于供应商的租户配置解析。

有关详细信息,请参阅 Quarkus Using OpenID Connect (OIDC) Multi-Tenancy 指南。

Access provider services with token propagation

有时,仅对 用户进行社交供应商身份验证是不够的。Quarkus OIDC web-app 应用程序还需要访问特定于供应商的服务,以代表当前经过身份验证的用户从供应商服务中获取或更新数据。

OIDC code flow mechanism for protecting web applications 指南中所述,授权代码流完成后会返回 ID 和访问令牌,而像 GitHub 这样的某些供应商只会返回访问令牌。正是这个访问令牌必须传播到诸如 Google CalendarSpotify Playlists 等服务,以便当前经过身份验证的用户能够使用此类服务。

你无需引入特定于供应商的库来实现此目的,而可以使用响应式的 Token Propagation 过滤器,该过滤器可以通过简单的注释绑定到给定的 REST 客户端。有关详细信息,请参阅 Quarkus Access token propagation 指南。

例如,在配置了 Google 供应商之后,你可以使用 REST 客户端在用户的 Google 日历中添加事件,如下例所示:

package org.acme.calendar;

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

import io.quarkus.oidc.token.propagation.AccessToken;
import io.smallrye.mutiny.Uni;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;

@RegisterRestClient(configKey="google-calendar-api")
@AccessToken  1
@Path("/calendars/primary")
public interface GoogleCalendarClient {
    @POST
    @Path("events")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    Uni<String> addEvent(Event event);
    public static class Event {
        public String summary;
        public String kind = "calendar#event";
        public Time start;
        public Time end
    }

    public static class Time {
        public String dateTime;
        public String timeZone = "Europe/CET";
        public Time() {
        }
        public Time(String value) {
            dateTime = value;
	}
    }
}
1 @AccessToken 注释使访问令牌能传播到目标服务。

最后,你需要配置 Google 日历地址并请求访问令牌的 Google 日历范围,如下例所示:

quarkus.oidc.provider=google
quarkus.oidc.client-id=<Client ID>
quarkus.oidc.credentials.secret=<Secret>

# Add a required calendar scope
quarkus.oidc.authentication.extra-params.scope=https://www.googleapis.com/auth/calendar

# Point REST client to Google Calendar endpoint
quarkus.rest-client.google-calendar-api.url=https://www.googleapis.com/calendar/v3

现在,你已经准备好让用户通过 Google 身份验证,并支持代表用户更新他们的 Google 日历,例如:

package org.acme.calendar;

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

import io.quarkus.oidc.IdToken;
import io.quarkus.security.Authenticated;
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("/calendar")
@Authenticated
public class CalendarService {

    @Inject
    @IdToken
    JsonWebToken jwt;

    @Inject
    @RestClient
    GoogleCalendarClient calendarClient;

    @GET
    @Path("/event")
    @Produces("text/plain")
    public Uni<String> get() {
        return calendarClient.addEvent(new Event()).onItem()
           .transform(c -> ("Hello " + jwt.getName() + ", new event: " + c));
    }
}

如果你想在本地主机上测试这个端点,必须更新在 Google 供应商中注册的应用程序以将 http://localhost:8080/calendar/event 列为授权的重定向 URI 之一,例如:

oidc google authorized redirects

你可能还必须注册一个或多个测试用户:

oidc google test users

如果端点必须访问其他 Google 服务,请遵循相同的方法。

使用特定供应商进行身份验证的模式,其中端点使用 ID 令牌或 UserInfo(尤其是如果使用仅 OAuth2 的供应商,例如 GitHub)获取有关当前经过身份验证的用户信息,并使用访问令牌以该用户的名义访问一些下游服务(供应商或应用程序特定的服务),无论使用哪个供应商来保护应用程序都可普遍应用。

Exact redirect URI match

大多数 OIDC 和 OAuth2 供应商(Strava 除外)都会强制执行以下操作:只有当重定向 URI 与在给定供应商的信息中心中配置的重定向 URI 完全匹配时,才能完成授权代码流程。

从实际的角度来看,你的 Quarkus 端点很可能需要将 quarkus.oidc.authentication.redirect-path 相对路径属性设置为所有经过身份验证的用户的初始入口路径,例如 quarkus.oidc.authentication.redirect-path=/authenticated,这意味着新经过身份验证的用户将登陆 /authenticated 页面,无论你的应用程序有多少安全入口点,以及他们最初访问了哪个安全资源。

这是许多 OIDC web-app 应用程序的典型流程。一旦用户登陆初始的安全页面,你的应用程序就会返回一个 HTML 页面,该页面使用链接指导用户到应用程序的其他部分,或用户可以直接在 JAX-RS API 的帮助下重定向到其他应用程序资源。

如有必要,你可以在完成身份验证后配置 Quarkus 以还原原始请求 URI。例如:

quarkus.oidc.provider=strava 1
quarkus.oidc.client-id=<Client ID>
quarkus.oidc.credentials.secret=<Secret>
quarkus.oidc.authentication.restore-path-after-redirect=true 2
1 strava 供应商配置是唯一受支持的配置,它使用 /strava 路径强制执行 quarkus.oidc.authentication.redirect-path 属性,你可以使用另一个路径(例如 /fitness)覆盖该路径。
2 如果用户在身份验证之前访问 /run 端点,那么一旦他们进行身份验证并被重定向到配置的重定向路径(例如 /strava),他们将登陆原始请求 /run 路径。

你不必立即设置 quarkus.oidc.authentication.redirect-path,因为如果未配置 quarkus.oidc.authentication.redirect-path,Quarkus 会假定当前请求 URL 是授权代码流程重定向 URL。例如,要测试 Google 身份验证是否有效,你可以让 Quarkus 端点侦听 /google,并更新 Google 信息中心以支持 http://localhost:8080/google 重定向 URI。一旦你受保护的应用程序 URL 空间增长,将需要设置 quarkus.oidc.authentication.redirect-path 属性。

HTTPS Redirect URI

一些供应商只接受基于 HTTPS 的重定向 URI。例如 ngrok can be set up 之类的工具可帮助在处于开发模式的本地主机上运行的 Quarkus 端点上测试此类供应商。

Rate Limiting

根据你的开发者 API 订阅级别,一些供应商可能会强制执行相当严格的请求速率限制策略。

当 Quarkus 从像 Google 供应商这样的符合 OIDC 的供应商中获取公共验证密钥,并通过本地密钥持续验证用户会话时,这可能不成问题。然而,对于纯 OAuth2 供应商(仅有访问令牌可用,且必须通过在经过身份验证的用户的每个请求中请求供应商端点的 UserInfo 间接验证这种供应商),这可能会成为问题。

因此,UserInfo 会嵌入到内部生成的 ID 令牌中,并在会话 Cookie 中进行加密。你可以使用 quarkus.oidc.cache-user-info-in-idtoken=false 禁用它。

或者,使用默认或自定义 UserInfo 缓存供应商,请参阅“OpenID Connect (OIDC) Bearer 令牌身份验证”指南的 Token Introspection and UserInfo cache 部分。