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 визначає href="https://openid.net/specs/openid-connect-core-1_0.html#UserInfo">кінцеву точку UserInfo наступним чином:
Кінцева точка UserInfo є захищеним ресурсом OAuth 2.0, який повертає дані про автентифікованого кінцевого користувача. Щоб отримати запитані дані про кінцевого користувача, клієнт запитує кінцеву точку UserInfo, використовуючи токен доступу, отриманий через автентифікацію OpenID Connect. Ці заявлені значення зазвичай представлені об'єктом JSON, який містить набір пар "ім'я-значення" для заявлених значень. 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&&
. Див. 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) Здійснюємо вибірку інформації про повноваження із захищеного ресурсу, використовуючи accessToken
// 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) Здійснюємо вибірку інформації про повноваження із захищеного ресурсу, використовуючи accessToken
// 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, можна передати
DefaultOAuth2UserServ
з кастомним 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()
з кастомно налаштованою DefaultOAuth2User
.
Незалежно від того, чи ти налаштовуєш 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
, заміни її під час запиту.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ