# 8.4.3. OAuth2

[OAuth2](https://oauth.net/2/)是 Spring 支持的广泛使用的授权框架。

**客户端**

如果您的类路径上有`spring-security-oauth2-client`，您可以利用一些自动配置来设置 OAuth2/Open ID Connect 客户端。此配置利用`OAuth2ClientProperties` 下的属性。相同的属性适用于 servlet 和反应式应用程序。

您可以在`spring.security.oauth2.client`前缀下注册多个 OAuth2 客户端和提供程序，如下例所示：

```properties
spring.security.oauth2.client.registration.my-login-client.client-id=abcd
spring.security.oauth2.client.registration.my-login-client.client-secret=password
spring.security.oauth2.client.registration.my-login-client.client-name=Client for OpenID Connect
spring.security.oauth2.client.registration.my-login-client.provider=my-oauth-provider
spring.security.oauth2.client.registration.my-login-client.scope=openid,profile,email,phone,address
spring.security.oauth2.client.registration.my-login-client.redirect-uri={baseUrl}/login/oauth2/code/{registrationId}
spring.security.oauth2.client.registration.my-login-client.client-authentication-method=client_secret_basic
spring.security.oauth2.client.registration.my-login-client.authorization-grant-type=authorization_code

spring.security.oauth2.client.registration.my-client-1.client-id=abcd
spring.security.oauth2.client.registration.my-client-1.client-secret=password
spring.security.oauth2.client.registration.my-client-1.client-name=Client for user scope
spring.security.oauth2.client.registration.my-client-1.provider=my-oauth-provider
spring.security.oauth2.client.registration.my-client-1.scope=user
spring.security.oauth2.client.registration.my-client-1.redirect-uri={baseUrl}/authorized/user
spring.security.oauth2.client.registration.my-client-1.client-authentication-method=client_secret_basic
spring.security.oauth2.client.registration.my-client-1.authorization-grant-type=authorization_code

spring.security.oauth2.client.registration.my-client-2.client-id=abcd
spring.security.oauth2.client.registration.my-client-2.client-secret=password
spring.security.oauth2.client.registration.my-client-2.client-name=Client for email scope
spring.security.oauth2.client.registration.my-client-2.provider=my-oauth-provider
spring.security.oauth2.client.registration.my-client-2.scope=email
spring.security.oauth2.client.registration.my-client-2.redirect-uri={baseUrl}/authorized/email
spring.security.oauth2.client.registration.my-client-2.client-authentication-method=client_secret_basic
spring.security.oauth2.client.registration.my-client-2.authorization-grant-type=authorization_code

spring.security.oauth2.client.provider.my-oauth-provider.authorization-uri=https://my-auth-server.com/oauth2/authorize
spring.security.oauth2.client.provider.my-oauth-provider.token-uri=https://my-auth-server.com/oauth2/token
spring.security.oauth2.client.provider.my-oauth-provider.user-info-uri=https://my-auth-server.com/userinfo
spring.security.oauth2.client.provider.my-oauth-provider.user-info-authentication-method=header
spring.security.oauth2.client.provider.my-oauth-provider.jwk-set-uri=https://my-auth-server.com/oauth2/jwks
spring.security.oauth2.client.provider.my-oauth-provider.user-name-attribute=name
```

对于支持 [OpenID Connect discovery 的](https://openid.net/specs/openid-connect-discovery-1_0.html)OpenID Connect 提供商，可以进一步简化配置。提供者需要配置一个`issuer-uri`，该 URI 被断言为其发行者标识符。例如，如果`issuer-uri`提供的是“<https://example.com”，则将向“https://example.com/.well-known/openid-configuration”发出“OpenID> 提供商配置请求”。结果预计是“OpenID 提供商配置响应”。以下示例显示了如何使用以下命令配置 OpenID Connect 提供程序`issuer-uri`：

```properties
spring.security.oauth2.client.provider.oidc-provider.issuer-uri=https://dev-123456.oktapreview.com/oauth2/default/
```

默认情况下，Spring Security的`OAuth2LoginAuthenticationFilter`仅处理匹配`/login/oauth2/code/*`的URL. 如果您想自定义`redirect-uri`以使用不同的模式，则需要提供配置来处理该自定义模式。例如，对于 Servlet 应用程序，您可以添加自己的应用`SecurityFilterChain`程序，如下所示：

```java
@Configuration(proxyBeanMethods = false)
@EnableWebSecurity
public class MyOAuthClientConfiguration {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests((requests) -> requests
                .anyRequest().authenticated()
            )
            .oauth2Login((login) -> login
                .redirectionEndpoint((endpoint) -> endpoint
                    .baseUri("/login/oauth2/callback/*")
                )
            );
        return http.build();
    }

}
```

> Spring Boot 自动配置一个`InMemoryOAuth2AuthorizedClientService`以便Spring Security 用来管理客户端注册的文件。`InMemoryOAuth2AuthorizedClientService`功能有限，我们建议仅将其用于开发环境。对于生产环境，请考虑使用`JdbcOAuth2AuthorizedClientService`或`OAuth2AuthorizedClientService`创建您自己的.

**常见提供商的 OAuth2 客户端注册**

对于常见的 OAuth2 和 OpenID 提供商（包括 Google、Github、Facebook 和 Okta），我们提供了一组提供商默认值（分别为`google`、`github`、`facebook`、 和`okta`）。

如果您不需要自定义这些提供程序，则可以将`provider`属性设置为需要推断默认值的提供程序。此外，如果客户端注册的密钥与默认支持的提供程序匹配，Spring Boot 也会推断出这一点。

换句话说，以下示例中的两个配置都使用 Google 提供程序：

```properties
spring.security.oauth2.client.registration.my-client.client-id=abcd
spring.security.oauth2.client.registration.my-client.client-secret=password
spring.security.oauth2.client.registration.my-client.provider=google
spring.security.oauth2.client.registration.google.client-id=abcd
spring.security.oauth2.client.registration.google.client-secret=password
```

**资源服务器**

如果您的类路径上有`spring-security-oauth2-resource-server`，Spring Boot 可以设置 OAuth2 资源服务器。对于 JWT 配置，需要指定 JWK Set URI 或 OIDC Issuer URI，如以下示例所示：

```properties
spring.security.oauth2.resourceserver.jwt.jwk-set-uri=https://example.com/oauth2/default/v1/keys
```

```properties
spring.security.oauth2.resourceserver.jwt.issuer-uri=https://dev-123456.oktapreview.com/oauth2/default/
```

> 如果授权服务器不支持 JWK Set URI，您可以使用用于验证 JWT 签名的公钥配置资源服务器。这可以使用`spring.security.oauth2.resourceserver.jwt.public-key-location` 属性来完成，其中值需要指向包含 PEM 编码的 x509 格式的公钥的文件。

`spring.security.oauth2.resourceserver.jwt.audiences`属性可用于指定 JWT 中 aud 声明的预期值。例如，要求 JWT 包含值为 `my-audience`的 aud 声明：

```properties
spring.security.oauth2.resourceserver.jwt.audiences[0]=my-audience
```

相同的属性适用于 servlet 和反应式应用程序。或者，您可以为 servlet 应用程序或`ReactiveJwtDecoder`反应式应用程序定义自己的`JwtDecoder` bean。

如果使用不透明令牌而不是 JWT，您可以配置以下属性以通过内省验证令牌：

```properties
spring.security.oauth2.resourceserver.opaquetoken.introspection-uri=https://example.com/check-token
spring.security.oauth2.resourceserver.opaquetoken.client-id=my-client-id
spring.security.oauth2.resourceserver.opaquetoken.client-secret=my-client-secret
```

同样，相同的属性适用于 servlet 和反应式应用程序。或者，您可以为 servlet 应用程序或`ReactiveOpaqueTokenIntrospector`反应式应用程序定义自己的`OpaqueTokenIntrospector` bean。

**授权服务器**

如果您的类路径上有`spring-security-oauth2-authorization-server`，则可以利用一些自动配置来设置基于 Servlet 的 OAuth2 授权服务器。

您可以在`spring.security.oauth2.authorizationserver.client`前缀下注册多个 OAuth2 客户端，如下例所示：

```properties
spring.security.oauth2.authorizationserver.client.my-client-1.registration.client-id=abcd
spring.security.oauth2.authorizationserver.client.my-client-1.registration.client-secret={noop}secret1
spring.security.oauth2.authorizationserver.client.my-client-1.registration.client-authentication-methods[0]=client_secret_basic
spring.security.oauth2.authorizationserver.client.my-client-1.registration.authorization-grant-types[0]=authorization_code
spring.security.oauth2.authorizationserver.client.my-client-1.registration.authorization-grant-types[1]=refresh_token
spring.security.oauth2.authorizationserver.client.my-client-1.registration.redirect-uris[0]=https://my-client-1.com/login/oauth2/code/abcd
spring.security.oauth2.authorizationserver.client.my-client-1.registration.redirect-uris[1]=https://my-client-1.com/authorized
spring.security.oauth2.authorizationserver.client.my-client-1.registration.scopes[0]=openid
spring.security.oauth2.authorizationserver.client.my-client-1.registration.scopes[1]=profile
spring.security.oauth2.authorizationserver.client.my-client-1.registration.scopes[2]=email
spring.security.oauth2.authorizationserver.client.my-client-1.registration.scopes[3]=phone
spring.security.oauth2.authorizationserver.client.my-client-1.registration.scopes[4]=address
spring.security.oauth2.authorizationserver.client.my-client-1.require-authorization-consent=true
spring.security.oauth2.authorizationserver.client.my-client-2.registration.client-id=efgh
spring.security.oauth2.authorizationserver.client.my-client-2.registration.client-secret={noop}secret2
spring.security.oauth2.authorizationserver.client.my-client-2.registration.client-authentication-methods[0]=client_secret_jwt
spring.security.oauth2.authorizationserver.client.my-client-2.registration.authorization-grant-types[0]=client_credentials
spring.security.oauth2.authorizationserver.client.my-client-2.registration.scopes[0]=user.read
spring.security.oauth2.authorizationserver.client.my-client-2.registration.scopes[1]=user.write
spring.security.oauth2.authorizationserver.client.my-client-2.jwk-set-uri=https://my-client-2.com/jwks
spring.security.oauth2.authorizationserver.client.my-client-2.token-endpoint-authentication-signing-algorithm=RS256
```

> `client-secret` 属性的格式必须能够与配置的 `PasswordEncoder` 匹配。 `PasswordEncoder` 的默认实例是通过`PasswordEncoderFactories.createDelegatingPasswordEncoder()` 创建的。

Spring Boot 为 Spring Authorization Server 提供的自动配置旨在快速入门。大多数应用程序都需要定制，并且需要定义多个 bean 来覆盖自动配置。

以下组件可以定义为 bean 来覆盖特定于 Spring Authorization Server 的自动配置：

* `RegisteredClientRepository`
* `AuthorizationServerSettings`
* `SecurityFilterChain`
* `com.nimbusds.jose.jwk.source.JWKSource<com.nimbusds.jose.proc.SecurityContext>`
* `JwtDecoder`

  Spring Boot 自动配置的`InMemoryRegisteredClientRepository`其只能被Spring 授权服务器用于管理注册客户端的权限。`InMemoryRegisteredClientRepository`功能有限，我们建议仅将其用于开发环境。对于生产环境，请考虑使用`JdbcRegisteredClientRepository`或创建您自己的`RegisteredClientRepository`.

[其他信息可以在《Spring 授权服务器参考指南》](https://docs.spring.io/spring-authorization-server/reference/1.2/index.html)的[“入门”](https://docs.spring.io/spring-authorization-server/reference/1.2/getting-started.html)一章中找到。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://doc.shiker.tech/spring-boot-can-kao-wen-dang/8.-wang-luo/8.4.-spring-an-quan/8.4.3.-oauth2.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
