HttpSecurity.oauth2Login() OAuth 2.0 da avtorizatsiyani sozlash uchun bir qator konfiguratsiya imkoniyatlarini taqdim etadi. Asosiy konfiguratsiya imkoniyatlari protokolning nuqtalariga mos keladigan guruhlarga bo'linadi.
Masalan, oauth2Login().authorizationEndpoint() avtorizatsiya nuqtasini sozlash imkonini beradi, holbuki oauth2Login().tokenEndpoint() tokenlar nuqtasini sozlash imkonini beradi.
Quyidagi kodda misol ko'rsatilgan:
@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()
}
}
DSL asosidagi oauth2Login() yaratishning asosiy maqsadi spetsifikatsiyalar bilan yaqindan muvofiqligini ta'minlash edi.
OAuth 2.0 avtorizatsiya freymvurki protokol nuqtalarini quyidagicha belgilaydi:
Avtorizatsiya jarayonida avtorizatsiya serverining ikkita nuqtasi ishlatiladi (HTTP resurslari):
-
Avtorizatsiya nuqtasi: resurs egasidan avtorizatsiya olish uchun foydalanuvchi agentini qayta yo'naltirish orqali mijoz tomonidan ishlatiladi.
-
Tokenlar nuqtasi: odatda mijozni autentifikatsiyalash paytida kirish ruxsatnomasini almashish uchun mijoz tomonidan ishlatiladi.
Shuningdek, bitta mijoz nuqtasi mavjud:
-
Pereadresatsiya nuqtasi: avtorizatsiya serveri tomonidan avtorizatsiya ma'lumotlarini o'z ichiga olgan javoblarni foydalanuvchi agenti orqali mijozga qaytarish uchun ishlatiladi.
OpenID Connect Core 1.0 spetsifikatsiyasi UserInfo nuqtasini quyidagicha belgilaydi:
UserInfo nuqtasi autentifikatsiya qilingan oxirgi foydalanuvchi ma'lumotlarini qaytaradigan OAuth 2.0 tomonidan himoyalangan resursdir. Oxirgi foydalanuvchi so'ralgan ma'lumotlarni olish uchun mijoz OpenID Connect autentifikatsiyasi orqali olingan kirish tokenidan foydalangan holda UserInfo nuqtasiga so'rov yuboradi. Bu da'vo qilingan qiymatlar odatda JSON ob'ekti shaklida taqdim etiladi, bu erda "nom-qiymat" juftliklar to'plamini o'z ichiga oladi.
Quyidagi kodda DSL asosidagi oauth2Login() uchun mavjud barcha konfiguratsiya parametrlarini ko'rsatadi:
@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()
}
}
DSL asosidagi oauth2Login() qo'shimcha ravishda XML konfiguratsiyasini ham qo'llab-quvvatlaydi.
Quyidagi kodda <Security Namespace> da mavjud bo'lgan barcha konfiguratsiya parametrlari ko'rsatilgan:
<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>
Quyidagi bo'limlarda mavjud bo'lgan har bir konfiguratsiya variantiga batafsilroq izoh berilgan:
-
OAuth 2.0 kirish sahifasi
-
Pereadresatsiya nuqtasi
-
UserInfo nuqtasi
-
ID token signaturasini tasdiqlash
-
OpenID Connect 1.0 tizimdan chiqish
OAuth 2.0 kirish sahifasi
OAuth 2.0 kirish sahifasi odatda DefaultLoginPageGeneratingFilter orqali avtomatik ravishda hosil qilinadi. Standart kirish sahifasi har bir moslashtirilgan OAuth mijozini o'z ClientRegistration.clientName bilan bog'laydi, bu orqali avtorizatsiya so'rovini (yoki OAuth 2.0 kirish) boshlash mumkin.
DefaultLoginPageGeneratingFilter moslashtirilgan OAuth mijozlar uchun havolalarni ko'rsatsa, ro'yxatdan o'tgan
ClientRegistrationRepository shuningdek,
Iterable<ClientRegistration> ni amalga oshirishi kerak. Qo'shimcha ma'lumot uchun
InMemoryClientRegistrationRepository ga qarang.
Har bir OAuth mijoz uchun standart havola quyidagi ko'rinishda bo'ladi:
OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI + "/{registrationId}"
Quyidagi qator misol keltirilgan:
<a href="/oauth2/authorization/google">Google</a>
Standart kirish sahifasini o'zgartirish uchun oauth2Login().loginPage() ni va (ixtiyoriy ravishda) oauth2Login().authorizationEndpoint().baseUri() ni sozlang.
Quyidagi listda misol keltirilgan:
@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 annotatsiyasida parametr
@RequestMapping("/login/oauth2") ni ko'rsatishingiz kerak bo'ladi, u sizning moslashtirilgan kirish sahifangizni vizuallashtiradi.
Ilgari aytilganidek, oauth2Login().authorizationEndpoint().baseUri() ni konfiguratsiyaga qo'shish ixtiyoriy. Ammo agar o'zgartirishni amalga oshirmoqchi bo'lsangiz, har bir OAuth mijoziga havola authorizationEndpoint().baseUri() ga mos kelayotganiga ishonch hosil qiling.
Quyidagi qator misol keltirilgan:
<a href="/login/oauth2/authorization/google">Google</a>
Pereadresatsiya nuqtasi
Pereadresatsiya nuqtasi foydalanuvchi agenti orqali mijozga javobni (autentifikatsiya kimligini o'z ichiga olgan) qaytarish uchun avtorizatsiya serveri tomonidan ishlatiladi.
Default baseUri uchun avtorizatsiya javobi (pereadresatsiya nuqtasi) /login/oauth2/code/* bo'lib, u OAuth2LoginAuthenticationFilter.DEFAULT_FILTER_PROCESSES_URI da aniqlangan.
Agar avtorizatsiya javobining baseUri nuqtasini sozlash kerak bo'lsa, uni quyidagi misolda ko'rsatilganidek sozlang:
@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>
Siz shuningdek, ClientRegistration.redirectUri ni moslashtirilgan avtorizatsiya javobining baseUri ga mos kelayotganligiga ishonch hosil qilishingiz kerak.
Quyidagi listda misol keltirilgan:
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 nuqtasi
UserInfo nuqtasi bir qator konfiguratsiya imkoniyatlarini o'z ichiga oladi, ular quyidagi kichik bo'limlarda bayon etilgan:
-
Foydalanuvchi huquqlarini tasvirlash
-
OAuth 2.0 UserService
-
OpenID Connect 1.0 UserService
Foydalanuvchi huquqlarini tasvirlash
OAuth 2.0 orqali muvaffaqiyatli autentifikatsiyaga ega bo'lgan foydalanuvchining OAuth2User.getAuthorities() (yoki OidcUser.getAuthorities()) yangi GrantedAuthority instance to'plamiga tasvirlanishi mumkin, ular autentifikatsiyani yakunlashda OAuth2AuthenticationToken ga o'tkaziladi.
OAuth2AuthenticationToken.getAuthorities() kirishlar uchun autentifikatsiya qilishda ishlatiladi, masalan,
hasRole('USER') yoki
hasRole('ADMIN').
Foydalanuvchi huquqlarini tasvirlash uchun bir nechta variant mavjud:
-
GrantedAuthoritiesMapper dan foydalanish
-
OAuth2UserService orqali delegatsiya asosida strategiya
GrantedAuthoritiesMapper dan foydalanish
GrantedAuthoritiesMapper ni amalga oshirishni belgilaymiz va uni quyidagi misolda ko'rsatilganidek sozlaymiz:
@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 va/yo userInfo da topilgan da'vo qilingan qiymatlarni
// bir yoki bir nechta GrantedAuthority ga tasvirlaymiz va mappedAuthorities ga qo'shamiz
} else if (OAuth2UserAuthority.class.isInstance(authority)) {
OAuth2UserAuthority oauth2UserAuthority = (OAuth2UserAuthority)authority;
Map<String, Object> userAttributes = oauth2UserAuthority.getAttributes();
// userAttributes da topilgan atributlarni
// bir yoki bir nechta GrantedAuthority ga tasvirlaymiz va mappedAuthorities ga qo'shamiz
}
});
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 va/yo userInfo da topilgan da'vo qilingan qiymatlarni
// bir yoki bir nechta GrantedAuthority ga tasvirlaymiz va mappedAuthorities ga qo'shamiz
} else if (authority is OAuth2UserAuthority) {
val userAttributes = authority.attributes
// userAttributes da topilgan atributlarni
// bir yoki bir nechta GrantedAuthority ga tasvirlaymiz va mappedAuthorities ga qo'shamiz
}
}
mappedAuthorities
}
}
<http>
<oauth2-login user-authorities-mapper-ref="userAuthoritiesMapper"
...
/>
</http>
Bundan tashqari, GrantedAuthoritiesMapper uchun @Bean ni ro'yxatdan o'tkazishingiz mumkin, shunda u avtomatik ravishda konfiguratsiyaga qo'llaniladi, quyidagi misolda ko'rsatilganidek:
@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 {
...
}
}
Delegatsiya asosida strategiya OAuth2UserService orqali
Ushbu strategiya GrantedAuthoritiesMapper dan foydalanishga qaraganda yanada rivojlangan, lekin u ham yanada moslashuvchan, chunki u OAuth2UserRequest va OAuth2User (OAuth 2.0 UserService dan foydalanish orqali) yoki OidcUserRequest va OidcUser (OpenID Connect 1.0 UserService dan foydalanish orqali) ga kirish imkonini beradi.
OAuth2UserRequest (va OidcUserRequest) tegishli OAuth2AccessToken ga kirish imkonini beradi, bu juda foydali, agar "delegate" ob'ekti foydalanuvchi uchun moslashtirilgan vakolatlarni tasvirlamasdan oldin qo'riqlanadigan resursdan ruxsatnoma ma'lumotlarini olish kerak bo'lsa.
Quyidagi misolda OpenID Connect 1.0 UserService dan foydalanib, delegatsiya asosida strategiyani amalga oshirish va sozlash ko'rsatilgan:
@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) -> {
// Standart implementatsiyani vakolatlarni yuklash uchun delegatsiya qilamiz
OidcUser oidcUser = delegate.loadUser(userRequest);
OAuth2AccessToken accessToken = userRequest.getAccessToken();
Set<GrantedAuthority> mappedAuthorities = new HashSet<>();
// TODO
// 1) Kirish tokenidan foydalanib himoyalangan resursdan vakolatlar ma'lumotlarini olish
// 2) Vakolatlar ma'lumotlarini bir yoki bir nechta GrantedAuthority ga tasvirlaymiz va mappedAuthorities ga qo'shamiz
// 3) oidcUser ning nusxasini yarating, lekin mappedAuthorities dan foydalaning
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 ->
// Standart implementatsiyani vakolatlarni yuklash uchun delegatsiya qilamiz
var oidcUser = delegate.loadUser(userRequest)
val accessToken = userRequest.accessToken
val mappedAuthorities = HashSet<GrantedAuthority>()
// TODO
// 1) Kirish tokenidan foydalanib himoyalangan resursdan vakolatlar ma'lumotlarini olish
// 2) Vakolatlar ma'lumotlarini bir yoki bir nechta GrantedAuthority ga tasvirlaymiz va mappedAuthorities ga qo'shamiz
// 3) oidcUser ning nusxasini yarating, lekin mappedAuthorities dan foydalaning
oidcUser = DefaultOidcUser(mappedAuthorities, oidcUser.idToken, oidcUser.userInfo)
oidcUser
}
}
}
<http>
<oauth2-login oidc-user-service-ref="oidcUserService"
...
/>
</http>
OAuth 2.0 UserService
DefaultOAuth2UserService – OAuth 2.0 standart yetkazib beruvchilarini qo'llab-quvvatlaydigan OAuth2UserService implementatsiyasi.
OAuth2UserService oxirgi foydalanuvchining (resurs egasining) foydalanuvchi atributlarini UserInfo nuqtasidan (avtorizatsiya jarayonida mijozga taqdim etilgan kirish tokenidan foydalanib) oladi va
AuthenticatedPrincipal ni
OAuth2User shaklida qaytaradi.
DefaultOAuth2UserService foydalanuvchi atributlari uchun UserInfo nuqtasiga so'rov yuborishda RestOperations dan foydalanadi.
Agar UserInfo so'rovini oldindan qayta ishlashni sozlash kerak bo'lsa, DefaultOAuth2UserService.setRequestEntityConverter() ga moslashuvchan Converter<OAuth2UserRequest, RequestEntity<?>> ni o'tkazing. Standart implementatsiya OAuth2UserRequestEntityConverter UserInfo so'rovini taqdim etish uchun RequestEntity ni quradi, bu esa OAuth2AccessToken ni Authorization headeriga qo'yadi.
Aks holda, agar UserInfo javobini post-qayta ishlashni sozlash kerak bo'lsa, DefaultOAuth2UserService.setRestOperations() ni moslashtirilgan RestOperations bilan o'tkazing. Default RestOperations quyidagicha sozlangan:
RestTemplate restTemplate = new RestTemplate();
restTemplate.setErrorHandler(new OAuth2ErrorResponseErrorHandler());
OAuth2ErrorResponseErrorHandler – bu ResponseErrorHandler bo'lib, OAuth 2.0 xatolarini (400 Bad Request) qayta ishlay oladi. Bu OAuth2ErrorHttpMessageConverter dan OAuth 2.0 xato parametrlarini OAuth2Error ga aylantirish uchun foydalanadi.
Nima bo'lganda ham, siz DefaultOAuth2UserService ni sozlaysizmi yoki OAuth2UserService ni o'z implementatsiyangizni o'tkazasizmi, quyidagi misolda ko'rsatilganidek uni sozlashingiz kerak bo'ladi:
@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 – bu OpenID Connect 1.0 uchun OAuth2UserService implementatsiyasi.
OidcUserService UserInfo nuqtasiga so'rov yuborishda DefaultOAuth2UserService dan foydalanadi.
Agar UserInfo so'rovinioldindan qayta ishlashni va/yoki UserInfo javobini qayta ishlashni sozlash kerak bo'lsa, OidcUserService.setOauth2UserService() ga moslashtirilgan DefaultOAuth2UserService ni o'tkazing.
Nima bo'lganda ham, siz OidcUserService ni sozlaysizmi yoki OpenID Connect 1.0 uchun o'z OAuth2UserService implementatsiyangizni o'tkazasizmi, quyidagi misolda ko'rsatilganidek uni sozlashingiz kerak bo'ladi:
@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 token signaturasini tasdiqlash
OpenID Connect 1.0 autentifikatsiyasi asosida mijoz tomonidan serveridan avtorizatsiya qilingan oxirgi foydalanuvchi tasdiq ma'lumotlarini o'z ichiga olgan ID token mavjud.
ID token JSON veb-tokeni (JWT) shaklida taqdim etiladi va JSON veb-sigatura (JWS) yordamida imzolanadi.
OidcIdTokenDecoderFactory imzo OidcIdToken ni tasdiqlash uchun foydalaniladigan JwtDecoder ni ta'minlaydi. Default algoritmi RS256 bo'lsa-da, u klient uchun belgilangan bo'lsa, o'zgartirilishi mumkin. Bunday holatlarda dekoder klient uchun belgilangan JWS algoritmini qaytarish uchun o'zgartiriladi.
JWS algoritmi dekoderi ClientRegistration ni oladigan va klient uchun kerakli JwsAlgorithm ni qaytaradigan Function hisoblanadi, masalan SignatureAlgorithm.RS256 yoki MacAlgorithm.HS256.
Quyidagi kodda barcha ClientRegistration uchun default MacAlgorithm.HS256 dan foydalanadigan OidcIdTokenDecoderFactory uchun @Bean ni qanday sozlash ko'rsatilgan:
@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 yoki
HS512 uchun simmetrik kalit imzoni tasdiqlashda mijozning maxfiy kaliti, client-id ga mos keladigan client-secret sifatida ishlatiladi.
ClientRegistration ni sozlashda, JWS algoritmini tanlaydigan dekoder client's
ClientRegistration ni tekshirib, qaysi algoritmni qaytarish kerakligini aniqlashi mumkin.
OpenID Connect 1.0 tizimdan chiqish
OpenID Connect Session Management 1.0 mijoz tomonidan xizmat ko'rsatuvchi tomonidan oxirgi foydalanuvchini tizimdan chiqishni ro'yxatdan o'tkazishni qo'llab-quvvatlash imkoniyatini ta'minlaydi. Mavjud strategiyalar haqida biri – mijoz tomonidan boshqariladigan chiqish (RP-Initiated Logout).
Agar OpenID yetkazib beruvchi sessiya boshqaruvi va aniqlovchi ni qo'llab-quvvatlasa, mijoz end_session_endpoint ni OpenID yetkazib beruvchi aniqlovchi metadata dan URL manzilini olishi mumkin. Bu issuer-uri bilan ClientRegistration ni sozlash orqali amalga oshirilishi mumkin, quyidagi misolda ko'rsatilgan:
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
…va OidcClientInitiatedLogoutSuccessHandler, client tomonidan boshlatilgan chiqishni amalga oshiradi, quyidagicha sozlanishi mumkin:
@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);
// Foydalanuvchi agentining joylashuvi, xizmat ko'rsatuvchidan chiqqandan so'ng, ko'chirilishi kerak bo'lgan manzilni o'rnatadi
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)
// Foydalanuvchi agentining joylashuvi, xizmat ko'rsatuvchidan chiqqandan so'ng, ko'chirilishi kerak bo'lgan manzilni o'rnatadi
oidcLogoutSuccessHandler.setPostLogoutRedirectUri("{baseUrl}")
return oidcLogoutSuccessHandler
}
}
OidcClientInitiatedLogoutSuccessHandler
{baseUrl} ploshchadkasini qo'llab-quvvatlaydi. Asosiy URL manzil holatida, masalan,
app.example.org, uni so'rov paytida almashtiradi.
GO TO FULL VERSION