HttpSecurity.oauth2Login()
предусматривает ряд вариантов конфигурации для настройки авторизации в OAuth 2.0. Основные варианты конфигурации сгруппированы по их аналогам для конечных точек протокола.
Например, oauth2Login().authorizationEndpoint()
позволяет сконфигурировать конечную точку авторизации, тогда как oauth2Login().tokenEndpoint()
позволяет сконфигурировать конечную точку токенов.
В следующем коде показан пример:
@EnableWebSecurity
public class OAuth2LoginSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.oauth2Login(oauth2 -> oauth2
.authorizationEndpoint(authorization -> authorization
...
)
.redirectionEndpoint(redirection -> redirection
...
)
.tokenEndpoint(token -> token
...
)
.userInfoEndpoint(userInfo -> userInfo
...
)
);
return http.build();
}
}
@EnableWebSecurity
class OAuth2LoginSecurityConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
oauth2Login {
authorizationEndpoint {
...
}
redirectionEndpoint {
...
}
tokenEndpoint {
...
}
userInfoEndpoint {
...
}
}
}
return http.build()
}
}
Основной целью создания oauth2Login()
на основе DSL было тесное соответствие именованию, определенному в спецификациях.
Фреймворк авторизации OAuth 2.0 определяет конечные точки протоколов следующим образом:
В процессе авторизации используются две конечные точки сервера авторизации (HTTP-ресурсы):
-
Конечная точка авторизации: Используется клиентом для получения авторизации от владельца ресурса через перенаправление пользовательского агента.
-
Конечная точка токенов: Используется клиентом для обмена разрешения на доступ на токен доступа, обычно при аутентификации клиента.
А также одна конечная точка клиентов:
-
Конечная точка переадресации: Используется сервером авторизации для возврата клиенту ответов, содержащих учетные данные авторизации, через пользовательского агента владельца ресурса.
Спецификация OpenID Connect Core 1.0 определяет конечную точку UserInfo следующим образом:
Конечная точка UserInfo является защищенным ресурсом OAuth 2.0, который возвращает данные об аутентифицированном конечном пользователе. Чтобы получить запрошенные данные о конечном пользователе, клиент делает запрос к конечной точке UserInfo, используя токен доступа, полученный через аутентификацию OpenID Connect. Эти заявленные значения обычно представлены объектом JSON, который содержит набор пар "имя-значение" для заявленных значений.
В следующем коде продемонстрированы все параметры конфигурации, доступные для oauth2Login()
на основе DSL:
@EnableWebSecurity
public class OAuth2LoginSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.oauth2Login(oauth2 -> oauth2
.clientRegistrationRepository(this.clientRegistrationRepository())
.authorizedClientRepository(this.authorizedClientRepository())
.authorizedClientService(this.authorizedClientService())
.loginPage("/login")
.authorizationEndpoint(authorization -> authorization
.baseUri(this.authorizationRequestBaseUri())
.authorizationRequestRepository(this.authorizationRequestRepository())
.authorizationRequestResolver(this.authorizationRequestResolver())
)
.redirectionEndpoint(redirection -> redirection
.baseUri(this.authorizationResponseBaseUri())
)
.tokenEndpoint(token -> token
.accessTokenResponseClient(this.accessTokenResponseClient())
)
.userInfoEndpoint(userInfo -> userInfo
.userAuthoritiesMapper(this.userAuthoritiesMapper())
.userService(this.oauth2UserService())
.oidcUserService(this.oidcUserService())
)
);
return http.build();
}
}
@EnableWebSecurity
class OAuth2LoginSecurityConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
oauth2Login {
clientRegistrationRepository = clientRegistrationRepository()
authorizedClientRepository = authorizedClientRepository()
authorizedClientService = authorizedClientService()
loginPage = "/login"
authorizationEndpoint {
baseUri = authorizationRequestBaseUri()
authorizationRequestRepository = authorizationRequestRepository()
authorizationRequestResolver = authorizationRequestResolver()
}
redirectionEndpoint {
baseUri = authorizationResponseBaseUri()
}
tokenEndpoint {
accessTokenResponseClient = accessTokenResponseClient()
}
userInfoEndpoint {
userAuthoritiesMapper = userAuthoritiesMapper()
userService = oauth2UserService()
oidcUserService = oidcUserService()
}
}
}
return http.build()
}
}
В дополнение к oauth2Login()
на основе DSL также поддерживается XML-конфигурация.
В следующем коде показаны все параметры конфигурации, доступные в <пространстве имен безопасности:
<http>
<oauth2-login client-registration-repository-ref="clientRegistrationRepository"
authorized-client-repository-ref="authorizedClientRepository"
authorized-client-service-ref="authorizedClientService"
authorization-request-repository-ref="authorizationRequestRepository"
authorization-request-resolver-ref="authorizationRequestResolver"
access-token-response-client-ref="accessTokenResponseClient"
user-authorities-mapper-ref="userAuthoritiesMapper"
user-service-ref="oauth2UserService"
oidc-user-service-ref="oidcUserService"
login-processing-url="/login/oauth2/code/*"
login-page="/login"
authentication-success-handler-ref="authenticationSuccessHandler"
authentication-failure-handler-ref="authenticationFailureHandler"
jwt-decoder-factory-ref="jwtDecoderFactory"/>
</http>
В следующих разделах более подробно описан каждый из доступных вариантов конфигурации:
-
Страница входа в систему в OAuth 2.0
-
Конечная точка переадресации
-
Конечная точка UserInfo
-
Верификация сигнатуры ID токена
-
Выход из системы OpenID Connect 1.0
Страница входа в систему в OAuth 2.0
По умолчанию страница авторизации в OAuth 2.0 автоматически генерируется через DefaultLoginPageGeneratingFilter
. Страница авторизации по умолчанию отображает каждый сконфигурированный OAuth-клиент с его ClientRegistration.clientName
в виде ссылки, по которой можно инициировать запрос на авторизацию (или вход в систему OAuth 2.0).
DefaultLoginPageGeneratingFilter
отображал ссылки для сконфигурированных OAuth-клиентов, зарегистрированный ClientRegistrationRepository
должен также реализовывать Iterable<ClientRegistration>
. См. InMemoryClientRegistrationRepository
для справки.Назначение ссылки для каждого OAuth-клиента по умолчанию следующее:
OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI + "/{registrationId}"
В следующей строке приведен пример:
<a href="/oauth2/authorization/google">Google</a>
Чтобы переопределить стандартную страницу входа в систему, сконфигурируйте oauth2Login().loginPage()
и (необязательно) oauth2Login().authorizationEndpoint().baseUri()
.
В следующем листинге приведен пример:
@EnableWebSecurity
public class OAuth2LoginSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.oauth2Login(oauth2 -> oauth2
.loginPage("/login/oauth2")
...
.authorizationEndpoint(authorization -> authorization
.baseUri("/login/oauth2/authorization")
...
)
);
return http.build();
}
}
@EnableWebSecurity
class OAuth2LoginSecurityConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
oauth2Login {
loginPage = "/login/oauth2"
authorizationEndpoint {
baseUri = "/login/oauth2/authorization"
}
}
}
return http.build()
}
}
<http>
<oauth2-login login-page="/login/oauth2"
...
/>
</http>
@Controller
параметр @RequestMapping("/login/oauth2")
, который сможет визуализировать кастомную страницу входа.Как отмечалось ранее, добавлять в конфигурацию oauth2Login().authorizationEndpoint().baseUri()
необязательно. Однако если вы решите индивидуализировать настройки, убедитесь, что ссылка на каждый OAuth-клиент соответствует authorizationEndpoint().baseUri()
.
В следующей строке приведен пример:
<a href="/login/oauth2/authorization/google">Google</a>
Конечная точка переадресации
Конечная точка переадресации используется сервером авторизации для возврата ответа авторизации (который содержит учетные данные авторизации) клиенту через пользовательского агента владельца ресурса.
По умолчанию ответ на запрос на авторизацию для baseUri
(конечная точка переадресации) – это /login/oauth2/code/*
, который определен в OAuth2LoginAuthenticationFilter.DEFAULT_FILTER_PROCESSES_URI
.
Если необходимо настроить конечную точку BaseUri
ответа авторизации, сконфигурируйте его, как показано в следующем примере:
@EnableWebSecurity
public class OAuth2LoginSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.oauth2Login(oauth2 -> oauth2
.redirectionEndpoint(redirection -> redirection
.baseUri("/login/oauth2/callback/*")
...
)
);
return http.build();
}
}
@EnableWebSecurity
class OAuth2LoginSecurityConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
oauth2Login {
redirectionEndpoint {
baseUri = "/login/oauth2/callback/*"
}
}
}
return http.build()
}
}
<http>
<oauth2-login login-processing-url="/login/oauth2/callback/*"
...
/>
</http>
Также необходимо удостовериться, что ClientRegistration.redirectUri
соответствует кастомному ответу на запрос на авторизацию для baseUri
.
В следующем листинге приведен пример:
return CommonOAuth2Provider.GOOGLE.getBuilder("google")
.clientId("google-client-id")
.clientSecret("google-client-secret")
.redirectUri("{baseUrl}/login/oauth2/callback/{registrationId}")
.build();
return CommonOAuth2Provider.GOOGLE.getBuilder("google")
.clientId("google-client-id")
.clientSecret("google-client-secret")
.redirectUri("{baseUrl}/login/oauth2/callback/{registrationId}")
.build()
Конечная точка UserInfo
Конечная точка UserInfo содержит ряд вариантов конфигурации, описанных в следующих подразделах:
-
Отображение полномочий пользователя
-
OAuth 2.0 UserService
-
OpenID Connect 1.0 UserService
Отображение полномочий пользователя
После успешной аутентификации пользователя через поставщика OAuth 2.0, OAuth2User.getAuthorities()
(или OidcUser.getAuthorities()
) может быть отображен на новый набор экземпляров GrantedAuthority
, которые будут переданы в OAuth2AuthenticationToken
при завершении аутентификации.
OAuth2AuthenticationToken.getAuthorities()
используется для авторизации запросов, например, в hasRole('USER')
или hasRole('ADMIN')
.Существует несколько вариантов отображения полномочий пользователя:
-
Использование GrantedAuthoritiesMapper
-
Стратегия на основе делегирования с помощью OAuth2UserService
Использование GrantedAuthoritiesMapper
Указываем реализацию GrantedAuthoritiesMapper
и конфигурируем ее, как показано в следующем примере:
@EnableWebSecurity
public class OAuth2LoginSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.oauth2Login(oauth2 -> oauth2
.userInfoEndpoint(userInfo -> userInfo
.userAuthoritiesMapper(this.userAuthoritiesMapper())
...
)
);
return http.build();
}
private GrantedAuthoritiesMapper userAuthoritiesMapper() {
return (authorities) -> {
Set<GrantedAuthority> mappedAuthorities = new HashSet<>();
authorities.forEach(authority -> {
if (OidcUserAuthority.class.isInstance(authority)) {
OidcUserAuthority oidcUserAuthority = (OidcUserAuthority)authority;
OidcIdToken idToken = oidcUserAuthority.getIdToken();
OidcUserInfo userInfo = oidcUserAuthority.getUserInfo();
// Отображаем заявленные значения, найденные в idToken и/или userInfo,
// на один или несколько GrantedAuthority и добавляем его в mappedAuthorities
} else if (OAuth2UserAuthority.class.isInstance(authority)) {
OAuth2UserAuthority oauth2UserAuthority = (OAuth2UserAuthority)authority;
Map<String, Object> userAttributes = oauth2UserAuthority.getAttributes();
// Отображаем атрибуты, найденные в userAttributes,
// на один или несколько GrantedAuthority и добавляем его в mappedAuthorities
}
});
return mappedAuthorities;
};
}
}
@EnableWebSecurity
class OAuth2LoginSecurityConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
oauth2Login {
userInfoEndpoint {
userAuthoritiesMapper = userAuthoritiesMapper()
}
}
}
return http.build()
}
private fun userAuthoritiesMapper(): GrantedAuthoritiesMapper = GrantedAuthoritiesMapper { authorities: Collection<GrantedAuthority> ->
val mappedAuthorities = emptySet<GrantedAuthority>()
authorities.forEach { authority ->
if (authority is OidcUserAuthority) {
val idToken = authority.idToken
val userInfo = authority.userInfo
// Отображаем заявленные значения, найденные в idToken и/или userInfo,
// на один или несколько GrantedAuthority и добавляем его в mappedAuthorities
} else if (authority is OAuth2UserAuthority) {
val userAttributes = authority.attributes
// Отображаем атрибуты, найденные в userAttributes,
// на один или несколько GrantedAuthority и добавляем его в mappedAuthorities
}
}
mappedAuthorities
}
}
<http>
<oauth2-login user-authorities-mapper-ref="userAuthoritiesMapper"
...
/>
</http>
В качестве альтернативы можно зарегистрировать @Bean
для GrantedAuthoritiesMapper
, чтобы он автоматически применялся к конфигурации, как показано в следующем примере:
@EnableWebSecurity
public class OAuth2LoginSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.oauth2Login(withDefaults());
return http.build();
}
@Bean
public GrantedAuthoritiesMapper userAuthoritiesMapper() {
...
}
}
@EnableWebSecurity
class OAuth2LoginSecurityConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
oauth2Login { }
}
return http.build()
}
@Bean
fun userAuthoritiesMapper(): GrantedAuthoritiesMapper {
...
}
}
Стратегия на основе делегирования с помощью OAuth2UserService
Эта стратегия является более продвинутой по сравнению с использованием GrantedAuthoritiesMapper
, однако, она также более гибкая, поскольку дает доступ к OAuth2UserRequest
и OAuth2User
(при использовании OAuth 2.0 UserService) или OidcUserRequest
и OidcUser
(при использовании OpenID Connect 1.0 UserService).
OAuth2UserRequest
(и OidcUserRequest
) предоставляет доступ к связанному OAuth2AccessToken
, который очень полезен в случаях, если делегирующему объекту необходимо получить информацию о разрешениях из защищенного ресурса, прежде чем он сможет отобразить кастомные полномочия для пользователя.
В следующем примере показано, как реализовать и сконфигурировать стратегию на основе делегирования, используя OpenID Connect 1.0 UserService:
@EnableWebSecurity
public class OAuth2LoginSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.oauth2Login(oauth2 -> oauth2
.userInfoEndpoint(userInfo -> userInfo
.oidcUserService(this.oidcUserService())
...
)
);
return http.build();
}
private OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService() {
final OidcUserService delegate = new OidcUserService();
return (userRequest) -> {
// Делегируем полномочия стандартной реализации для загрузки пользователя
OidcUser oidcUser = delegate.loadUser(userRequest);
OAuth2AccessToken accessToken = userRequest.getAccessToken();
Set<GrantedAuthority> mappedAuthorities = new HashSet<>();
// TODO
// 1) Осуществляем выборку информации о полномочиях из защищенного ресурса, используя accessToken
// 2) Map the authority information на один или несколько GrantedAuthority и добавляем его в mappedAuthorities
// 3) Создаем копию oidcUser, но используем mappedAuthorities
oidcUser = new DefaultOidcUser(mappedAuthorities, oidcUser.getIdToken(), oidcUser.getUserInfo());
return oidcUser;
};
}
}
@EnableWebSecurity
class OAuth2LoginSecurityConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
oauth2Login {
userInfoEndpoint {
oidcUserService = oidcUserService()
}
}
}
return http.build()
}
@Bean
fun oidcUserService(): OAuth2UserService<OidcUserRequest, OidcUser> {
val delegate = OidcUserService()
return OAuth2UserService { userRequest ->
// Делегируем полномочия стандартной реализации для загрузки пользователя
var oidcUser = delegate.loadUser(userRequest)
val accessToken = userRequest.accessToken
val mappedAuthorities = HashSet<GrantedAuthority>()
// TODO
// 1) Осуществляем выборку информации о полномочиях из защищенного ресурса, используя accessToken
// 2) Map the authority information на один или несколько GrantedAuthority и добавляем его в mappedAuthorities
// 3) Создаем копию oidcUser, но используем mappedAuthorities
oidcUser = DefaultOidcUser(mappedAuthorities, oidcUser.idToken, oidcUser.userInfo)
oidcUser
}
}
}
<http>
<oauth2-login oidc-user-service-ref="oidcUserService"
...
/>
</http>
OAuth 2.0 UserService
DefaultOAuth2UserService
– это реализация OAuth2UserService
, которая поддерживает стандартных поставщиков OAuth 2.0.
OAuth2UserService
получает пользовательские атрибуты конечного пользователя (владельца ресурса) из конечной точки UserInfo (используя токен доступа, предоставленный клиенту во время осуществления потока авторизации) и возвращает AuthenticatedPrincipal
в форме OAuth2User
.DefaultOAuth2UserService
использует RestOperations
при запросе пользовательских атрибутов в конечной точке UserInfo.
Если необходимо настроить предварительную обработку запроса UserInfo, можно передать DefaultOAuth2UserService.setRequestEntityConverter()
с кастомным Converter<OAuth2UserRequest, RequestEntity<?>>
. Стандартная реализация OAuth2UserRequestEntityConverter
строит представление RequestEntity
запроса UserInfo, который по умолчанию устанавливает OAuth2AccessToken
в заголовке Authorization
.
С другой стороны, если нужно настроить пост-обработку ответа UserInfo, нужно будет передать DefaultOAuth2UserService.setRestOperations()
с кастомно сконфигурированными RestOperations
. RestOperations
по умолчанию сконфигурированы следующим образом:
RestTemplate restTemplate = new RestTemplate();
restTemplate.setErrorHandler(new OAuth2ErrorResponseErrorHandler());
OAuth2ErrorResponseErrorHandler
– это ResponseErrorHandler
, который может обрабатывать ошибку OAuth 2.0 (400 Bad Request). Он использует OAuth2ErrorHttpMessageConverter
для преобразования параметров ошибки OAuth 2.0 в OAuth2Error
.
Независимо от того, настраиваете ли вы DefaultOAuth2UserService
или передаете собственную реализацию OAuth2UserService
, нужно будет сконфигурировать её, как показано в следующем примере:
@EnableWebSecurity
public class OAuth2LoginSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.oauth2Login(oauth2 -> oauth2
.userInfoEndpoint(userInfo -> userInfo
.userService(this.oauth2UserService())
...
)
);
return http.build();
}
private OAuth2UserService<OAuth2UserRequest, OAuth2User> oauth2UserService() {
...
}
}
@EnableWebSecurity
class OAuth2LoginSecurityConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
oauth2Login {
userInfoEndpoint {
userService = oauth2UserService()
// ...
}
}
}
return http.build()
}
private fun oauth2UserService(): OAuth2UserService<OAuth2UserRequest, OAuth2User> {
// ...
}
}
OpenID Connect 1.0 UserService
OidcUserService
– это реализация OAuth2UserService
, которая поддерживает поставщика OpenID Connect 1.0.
OidcUserService
использует DefaultOAuth2UserService
при запросе пользовательских атрибутов в конечной точке UserInfo.
Если необходимо настроить предварительную обработку запроса UserInfo и/или последующую обработку ответа UserInfo, потребуется передать OidcUserService.setOauth2UserService()
с кастомно сконфигурированной DefaultOAuth2UserService
.
Независимо от того, настраиваете ли вы OidcUserService
или передаете собственную реализацию OAuth2UserService
для поставщика OpenID Connect 1.0, нужно будет сконфигурировать её, как показано в следующем примере:
@EnableWebSecurity
public class OAuth2LoginSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.oauth2Login(oauth2 -> oauth2
.userInfoEndpoint(userInfo -> userInfo
.oidcUserService(this.oidcUserService())
...
)
);
return http.build();
}
private OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService() {
...
}
}
@EnableWebSecurity
class OAuth2LoginSecurityConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
oauth2Login {
userInfoEndpoint {
oidcUserService = oidcUserService()
// ...
}
}
}
return http.build()
}
private fun oidcUserService(): OAuth2UserService<OidcUserRequest, OidcUser> {
// ...
}
}
Верификация сигнатуры ID токена
Аутентификация OpenID Connect 1.0 предусматривает ID токен, который является маркером безопасности, содержащим заявленные значения аутентификации конечного пользователя от сервера авторизации при использовании клиентом.
ID токен представлен в виде JSON веб-токена (JWT) и ДОЛЖЕН быть подписан с помощью JSON веб-сигнатуры (JWS).
OidcIdTokenDecoderFactory
обеспечивает JwtDecoder
, используемый для верификации сигнатуры OidcIdToken
. Алгоритмом по умолчанию является RS256
, но он может быть и другим, если назначить его при регистрации клиента. Для таких случаев распознаватель можно сконфигурировать на возврат ожидаемого алгоритма для JWS, назначенного для конкретного клиента.
Распознаватель алгоритмов для JWS - это Function
, которая принимает ClientRegistration
и возвращает ожидаемый JwsAlgorithm
для клиента, например SignatureAlgorithm.RS256
или MacAlgorithm.HS256
.
В следующем коде продемонстрировано, как сконфигурировать @Bean
для OidcIdTokenDecoderFactory
, который по умолчанию будет использовать MacAlgorithm.HS256
для всех ClientRegistration
:
@Bean
public JwtDecoderFactory<ClientRegistration> idTokenDecoderFactory() {
OidcIdTokenDecoderFactory idTokenDecoderFactory = new OidcIdTokenDecoderFactory();
idTokenDecoderFactory.setJwsAlgorithmResolver(clientRegistration -> MacAlgorithm.HS256);
return idTokenDecoderFactory;
}
@Bean
fun idTokenDecoderFactory(): JwtDecoderFactory<ClientRegistration?> {
val idTokenDecoderFactory = OidcIdTokenDecoderFactory()
idTokenDecoderFactory.setJwsAlgorithmResolver { MacAlgorithm.HS256 }
return idTokenDecoderFactory
}
HS256
, HS384
или HS512
, в качестве симметричного ключа для верификации подписи используется client-secret
, соответствующий client-id
.ClientRegistration
, распознаватель алгоритмов для JWS может вычислить передаваемую ClientRegistration
, чтобы определить, какой алгоритм возвращать.Выход из системы OpenID Connect 1.0
OpenID Connect Session Management 1.0 предусматривает возможность регистрации выхода конечного пользователя из системы на стороне поставщика с помощью клиента. Одна из доступных стратегий – выход, инициированный клиентом (RP-Initiated Logout).
Если поставщик OpenID поддерживает как управление сессиями, так и обнаружение, клиент может получить URL-адрес
конечной точки конечной точки end_session_endpoint
из метаданных обнаружения поставщика OpenID. Это можно осуществить, сконфигурировав ClientRegistration
с issuer-uri
, как показано в следующем примере:
spring:
security:
oauth2:
client:
registration:
okta:
client-id: okta-client-id
client-secret: okta-client-secret
...
provider:
okta:
issuer-uri: https://dev-1234.oktapreview.com
…а OidcClientInitiatedLogoutSuccessHandler
, который реализует инициируемый клиентом выход из системы, могут быть сконфигурированы следующим образом:
@EnableWebSecurity
public class OAuth2LoginSecurityConfig {
@Autowired
private ClientRegistrationRepository clientRegistrationRepository;
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authorize -> authorize
.anyRequest().authenticated()
)
.oauth2Login(withDefaults())
.logout(logout -> logout
.logoutSuccessHandler(oidcLogoutSuccessHandler())
);
return http.build();
}
private LogoutSuccessHandler oidcLogoutSuccessHandler() {
OidcClientInitiatedLogoutSuccessHandler oidcLogoutSuccessHandler =
new OidcClientInitiatedLogoutSuccessHandler(this.clientRegistrationRepository);
// Устанавливает местоположение, куда будет переадресован пользовательский агент конечного пользователя
// после выхода из системы на стороне поставщика
oidcLogoutSuccessHandler.setPostLogoutRedirectUri("{baseUrl}");
return oidcLogoutSuccessHandler;
}
}
@EnableWebSecurity
class OAuth2LoginSecurityConfig {
@Autowired
private lateinit var clientRegistrationRepository: ClientRegistrationRepository
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
authorizeRequests {
authorize(anyRequest, authenticated)
}
oauth2Login { }
logout {
logoutSuccessHandler = oidcLogoutSuccessHandler()
}
}
return http.build()
}
private fun oidcLogoutSuccessHandler(): LogoutSuccessHandler {
val oidcLogoutSuccessHandler = OidcClientInitiatedLogoutSuccessHandler(clientRegistrationRepository)
// Устанавливает местоположение, куда будет переадресован пользовательский агент конечного пользователя
// после выхода из системы на стороне поставщика
oidcLogoutSuccessHandler.setPostLogoutRedirectUri("{baseUrl}")
return oidcLogoutSuccessHandler
}
}
OidcClientInitiatedLogoutSuccessHandler
поддерживает плейсхолдер {baseUrl}
. В случае использования основной URL-адрес приложения, например app.example.org
, заменит его во время запроса.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ