Приклад на Spring Boot 2.x
Spring Boot 2.x передбачає можливість повноцінно використовувати автоконфігурацію для налаштування входу в систему через OAuth 2.0.
У цьому розділі показано, як налаштувати приклад коду для входу в систему в OAuth 2.0, використовуючи Google як постачальника аутентифікації, а також розглянуті наступні теми:
Початкове налаштування
Налаштування URI для переадресації
Конфігуруємо файл application.yml
-
Завантаження програми
Initial setup
Щоб використовувати систему автентифікації Google у OAuth 2.0 для входу в систему, необхідно налаштувати проєкт у Google API Console для отримання облікових даних OAuth 2.0.
Слідуй інструкціям на сторінці OpenID Connect, починаючи з розділу "Налаштування OAuth 2.0".
Після виконання інструкції з "Отримання облікових даних OAuth 2.0" повинен з'явитися новий клієнт OAuth з обліковими даними, що складаються з ідентифікатора клієнта та секрету клієнта.
Налаштування URI для переадресації
URI для переадресації — це шлях у додатку, на який перенаправляється користувач кінцевого користувача після аутентифікації в Google і надання доступу до OAuth-клієнту (створеного на попередньому етапі) на сторінці Згоди.
У
розділі "Установка URI для переадресації" переконайся, що у полі авторизованих URI для
переадресації встановлено значення localhost:8080/login
/oauth2/code/google
.
{baseUrl}/login
/oauth2/code/{registrationId}
. RegistrationId — це унікальний ідентифікатор для
ClientRegistration
.
URI
для redirect-uri
.
Конфігуруємо файл application.yml
Тепер, коли отримано новий OAuth-клієнт через Google, необхідно налаштувати програму використання OAuth-клієнта для потоку аутентифікації. Для цього:
Перейди до
application.yml
і встанови наступну конфігурацію:spring: security: oauth2: client: registration: google: client-id: google-client-id client-secret: google-client-secret
Властивості OAuth-клієнтаspring.security.oauth2.client.registration
— це базовий префікс властивостей для властивостей OAuth-клієнта.- Після префікса базової властивості слідує ідентифікатор для
ClientRegistration
, наприклад google.
Заміни значення у властивостях
client-id
таclient-secret
на облікові дані OAuth 2.0, які були створені раніше.
Завантаження програми
Запусти приклад Spring Boot 2.x та перейди на localhost:8080
.
Потім тебе перенаправлять на автоматично створену стандартну сторінку входу в систему, на якій відображається
посилання для Google.
Натисни на посилання Google, після чого тебе перенаправлять у Google для автентифікації.
Після аутентифікації за допомогою облікових даних облікового запису Google на наступній сторінці з'явиться екран Згоди. На екрані "Злагода" буде запропоновано дозволити або заборонити доступ до OAuth-клієнта, який було створено раніше. Натисни "Дозволити", щоб дозволити OAuth-клієнту доступ до своєї адреси електронної пошти та основної інформації профілю.
На цьому етапі OAuth-клієнт отримує твою адресу електронної пошти та основну інформацію про профілі з кінцевої точки UserInfo та встановлює автентифіковану сесію.
Відображення властивостей Spring Boot 2.x
У наступній таблиці описано відображення властивостей Spring Boot 2.x OAuth Client на властивості ClientRegistration
.
Spring Boot 2.x | ClientRegistration |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ClientRegistration
можна спочатку конфігурувати за допомогою
виявлення кінцевої
точки конфігурації постачальника OpenID Connect або кінцевої точки метаданих сервера
авторизації, вказавши властивість spring.security.oauth2.client.provider.[providerId].issuer-uri
.
CommonOAuth2Provider
CommonOAuth2Provider
визначає набір стандартних властивостей клієнта для
низки відомих постачальників: Google, GitHub, Facebook та Okta.
Наприклад, authorization-uri
,
token-uri
та
user-info-uri
не часто змінюються для будь-якого постачальника. Тому є сенс вказати значення за
замовчуванням, щоб скоротити необхідну конфігурацію.
Як було показано раніше, коли ми налаштовували клієнт Google, обов'язковими є лише властивості client-id
та client-secret
.
У наступному лістингу наведено приклад:
spring:
security:
oauth2:
client:
registration:
google:
client-id: google-client-id
client-secret: google-client-secret
registrationId
(google
) збігається з enum
GOOGLE
(без урахування регістру) у CommonOAuth2Provider
.
Для випадків, коли
необхідно встановити інший registrationId
, наприклад, google-login
, все одно можна
використовувати автоматичне визначення властивостей клієнта за замовчуванням, налаштувавши властивість provider
.
У наступному лістингу наведено приклад:
spring:
security:
oauth2:
client:
registration:
google-login:
provider: google
client-id: google-client-id
client-secret: google-client-secret
- Для
registrationId
встановлено значенняgoogle-login
. - Властивість
provider
встановлено на значенняgoogle
, що дозволить використовувати автоматичне визначення властивостей клієнта за замовчуванням, встановлене вCommonOAuth2Provider. GOOGLE.getBuilder()
.
Конфігурування кастомних властивостей постачальника
Деякі постачальники OAuth 2.0 підтримують роботу в режимі колективної оренди, що призводить до створення різних кінцевих точок протоколів для кожного орендаря (або піддомена).
Наприклад, OAuth-клієнт, зареєстрований в Okta, присвоюється певному піддомену і має власні кінцеві точки протоколів.
Для таких випадків Spring Boot 2.x передбачає наступну базову властивість для конфігурування кастомних
властивостей постачальника: spring.security.oauth2.client.provider.[providerId]
.
У наступному лістингу наведено приклад:
spring:
security:
oauth2:
client:
registration:
okta:
client-id: okta-client-id
client-secret: okta-client-secret
provider:
okta:
authorization-uri: https://your-subdomain.oktapreview.com/oauth2/v1/authorize
token-uri: https://your-subdomain.oktapreview.com/oauth2/v1/token
user-info-uri: https://your-subdomain.oktapreview.com/oauth2/v1/userinfo
user-name-attribute: sub
jwk-set-uri: https://your-subdomain.oktapreview.com/oauth2/v1/keys
- Базова властивість
(spring.security.oauth2.client.provider.okta
) дозволяє кастомно конфігурувати розташування кінцевих точок протоколів.
Перевизначення автоконфігурації Spring Boot 2.x
Клас автоконфігурації Spring Boot 2.x для підтримки OAuth-клієнта — OAuth2ClientAutoConfiguration
.
Він виконує такі завдання:
Реєструє
@Bean
дляClientRegistrationRepository
, що складається з екземпляра(ів)ClientRegistration
зі сконфігурованих властивостей OAuth-клієнта.Реєструє
@Bean
дляSecurityFilterChain
та активує авторизацію в OAuth 2.0 черезhttpSecurity.oauth2Login()
.
Якщо необхідно перевизначити автоконфігурацію під конкретні потреби, зробити це можна такими способами:
Реєструємо @Bean для ClientRegistrationRepository
Реєструємо @Bean для SecurityFilterChain
Повне перевизначення автоконфігурації
Реєструємо @Bean для ClientRegistrationRepository
У наступному прикладі показано, як зареєструвати @Bean
для
ClientRegistrationRepository
:
@Configuration
public class OAuth2LoginConfig {
@Bean
public ClientRegistrationRepository clientRegistrationRepository() {
return new InMemoryClientRegistrationRepository(this.googleClientRegistration());
}
private ClientRegistration googleClientRegistration() {
return ClientRegistration.withRegistrationId("google")
.clientId("google-client-id")
.clientSecret("google-client-secret")
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.redirectUri("{baseUrl}/login/oauth2/code/{registrationId}")
.scope("openid", "profile", "email", "address", "phone")
.authorizationUri("https://accounts.google.com/o/oauth2/v2/auth")
.tokenUri("https://www.googleapis.com/oauth2/v4/token")
.userInfoUri("https://www.googleapis.com/oauth2/v3/userinfo")
.userNameAttributeName(IdTokenClaimNames.SUB)
.jwkSetUri("https://www.googleapis.com/oauth2/v3/certs")
.clientName("Google")
.build();
}
}
@Configuration
class OAuth2LoginConfig {
@Bean
fun clientRegistrationRepository(): ClientRegistrationRepository {
return InMemoryClientRegistrationRepository(googleClientRegistration())
}
private fun googleClientRegistration(): ClientRegistration {
return ClientRegistration.withRegistrationId("google")
.clientId("google-client-id")
.clientSecret("google-client-secret")
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.redirectUri("{baseUrl}/login/oauth2/code/{registrationId}")
.scope("openid", "profile", "email", "address", "phone")
.authorizationUri("https://accounts.google.com/o/oauth2/v2/auth")
.tokenUri("https://www.googleapis.com/oauth2/v4/token")
.userInfoUri("https://www.googleapis.com/oauth2/v3/userinfo")
.userNameAttributeName(IdTokenClaimNames.SUB)
.jwkSetUri("https://www.googleapis.com/oauth2/v3/certs")
.clientName("Google")
.build()
}
}
Реєструємо @Bean для SecurityFilterChain
У наступному прикладі показано, як зареєструвати @Bean
для SecurityFilterChain
з
використанням анотації @EnableWebSecurity
та активувати авторизацію в OAuth 2.0 через httpSecurity.oauth2Login()
:
@EnableWebSecurity
public class OAuth2LoginSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authorize -> authorize
.anyRequest().authenticated()
)
.oauth2Login(withDefaults());
return http.build();
}
}
@EnableWebSecurity
class OAuth2LoginSecurityConfig {
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
authorizeRequests {
authorize(anyRequest, authenticated)
}
oauth2Login { }
}
return http.build()
}
}
Повне перевизначення автоконфігурації
У наступному прикладі показано, як повністю перевизначити
автоконфігурацію, зареєструвавши @Bean
для ClientRegistrationRepository
та
@Bean
для SecurityFilterChain
.
@Configuration
public class OAuth2LoginConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authorize -> authorize
.anyRequest().authenticated()
)
.oauth2Login(withDefaults());
return http.build();
}
@Bean
public ClientRegistrationRepository clientRegistrationRepository() {
return new InMemoryClientRegistrationRepository(this.googleClientRegistration());
}
private ClientRegistration googleClientRegistration() {
return ClientRegistration.withRegistrationId("google")
.clientId("google-client-id")
.clientSecret("google-client-secret")
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.redirectUri("{baseUrl}/login/oauth2/code/{registrationId}")
.scope("openid", "profile", "email", "address", "phone")
.authorizationUri("https://accounts.google.com/o/oauth2/v2/auth")
.tokenUri("https://www.googleapis.com/oauth2/v4/token")
.userInfoUri("https://www.googleapis.com/oauth2/v3/userinfo")
.userNameAttributeName(IdTokenClaimNames.SUB)
.jwkSetUri("https://www.googleapis.com/oauth2/v3/certs")
.clientName("Google")
.build();
}
}
@Configuration
class OAuth2LoginConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
authorizeRequests {
authorize(anyRequest, authenticated)
}
oauth2Login { }
}
return http.build()
}
@Bean
fun clientRegistrationRepository(): ClientRegistrationRepository {
return InMemoryClientRegistrationRepository(googleClientRegistration())
}
private fun googleClientRegistration(): ClientRegistration {
return ClientRegistration.withRegistrationId("google")
.clientId("google-client-id")
.clientSecret("google-client-secret")
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.redirectUri("{baseUrl}/login/oauth2/code/{registrationId}")
.scope("openid", "profile", "email", "address", "phone")
.authorizationUri("https://accounts.google.com/o/oauth2/v2/auth")
.tokenUri("https://www.googleapis.com/oauth2/v4/token")
.userInfoUri("https://www.googleapis.com/oauth2/v3/userinfo")
.userNameAttributeName(IdTokenClaimNames.SUB)
.jwkSetUri("https://www.googleapis.com/oauth2/v3/certs")
.clientName("Google")
.build()
}
}
Конфігурація на базі Java без Spring Boot 2.x
Якщо використовувати Spring Boot 2.x неможливо, але потрібно налаштувати одного з наперед визначених
постачальників в CommonOAuth2Provider
(наприклад, Google), застосуй наступну конфігурацію:
@EnableWebSecurity
public class OAuth2LoginConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authorize -> authorize
.anyRequest().authenticated()
)
.oauth2Login(withDefaults());
return http.build();
}
@Bean
public ClientRegistrationRepository clientRegistrationRepository() {
return new InMemoryClientRegistrationRepository(this.googleClientRegistration());
}
@Bean
public OAuth2AuthorizedClientService authorizedClientService(
ClientRegistrationRepository clientRegistrationRepository) {
return new InMemoryOAuth2AuthorizedClientService(clientRegistrationRepository);
}
@Bean
public OAuth2AuthorizedClientRepository authorizedClientRepository(
OAuth2AuthorizedClientService authorizedClientService) {
return new AuthenticatedPrincipalOAuth2AuthorizedClientRepository(authorizedClientService);
}
private ClientRegistration googleClientRegistration() {
return CommonOAuth2Provider.GOOGLE.getBuilder("google")
.clientId("google-client-id")
.clientSecret("google-client-secret")
.build();
}
}
@EnableWebSecurity
open class OAuth2LoginConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
authorizeRequests {
authorize(anyRequest, authenticated)
}
oauth2Login { }
}
return http.build()
}
@Bean
open fun clientRegistrationRepository(): ClientRegistrationRepository {
return InMemoryClientRegistrationRepository(googleClientRegistration())
}
@Bean
open fun authorizedClientService(
clientRegistrationRepository: ClientRegistrationRepository?
): OAuth2AuthorizedClientService {
return InMemoryOAuth2AuthorizedClientService(clientRegistrationRepository)
}
@Bean
open fun authorizedClientRepository(
authorizedClientService: OAuth2AuthorizedClientService?
): OAuth2AuthorizedClientRepository {
return AuthenticatedPrincipalOAuth2AuthorizedClientRepository(authorizedClientService)
}
private fun googleClientRegistration(): ClientRegistration {
return CommonOAuth2Provider.GOOGLE.getBuilder("google")
.clientId("google-client-id")
.clientSecret("google-client-secret")
.build()
}
}
<http auto-config="true">
<intercept-url pattern="/**" access="authenticated"/>
<oauth2-login authorized-client-repository-ref="authorizedClientRepository"/>
</http>
<client-registrations>
<client-registration registration-id="google"
client-id="google-client-id"
client-secret="google-client-secret"
provider-id="google"/>
</client-registrations>
<b:bean id="authorizedClientService"
class="org.springframework.security.oauth2.client.InMemoryOAuth2AuthorizedClientService"
autowire="constructor"/>
<b:bean id="authorizedClientRepository"
class="org.springframework.security.oauth2.client.web.AuthenticatedPrincipalOAuth2AuthorizedClientRepository">
<b:constructor-arg ref="authorizedClientService"/>
</b:bean><
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ