JavaRush /Курсы /Модуль 5. Spring /Лекция 107: OAuth2 с использованием Spring Security

Лекция 107: OAuth2 с использованием Spring Security

Модуль 5. Spring
11 уровень , 6 лекция
Открыта

Когда вы думаете о безопасности в распределённых системах или микросервисах, вам хочется, чтобы это было унифицированным, масштабируемым и удобным в управлении. OAuth2 предоставляет централизованный подход к аутентификации, позволяя вам делегировать авторизацию сторонним провайдерам (например, Google, GitHub). С Spring Security можно настроить всё это с минимальными усилиями благодаря мощной интеграции, которую мы сейчас и разберём.


Ключевые особенности OAuth2 с Spring Security

Прежде, чем мы начнём ковыряться в коде, давайте кратко рассмотрим, что мы получим благодаря интеграции OAuth2 с Spring Security:

  1. Унификация аутентификации: теперь вам не нужно реализовывать собственный механизм входа и проверки пользователей. Вы можете использовать готовые решения от Google, GitHub и других популярных сервисов.
  2. Обмен токенами: OAuth2 позволяет получать токены доступа и Refresh токены, которые затем используются для защиты ресурсов.
  3. Гибкость ролей и прав доступа: у вас появляется возможность легко управлять ролями пользователей и защищать ресурсы, используя их.

Настройка Spring Security для работы с OAuth2

1. Добавление зависимостей

Для начала нам понадобится подключить необходимые зависимости в ваш pom.xml (в случае Maven) или build.gradle (если вы используете Gradle). Для работы с OAuth2 в Spring Security добавьте вот такие зависимости:

Maven:


<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-security</artifactId>
</dependency>

Gradle:


implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
implementation 'org.springframework.boot:spring-boot-starter-security'

2. Конфигурация OAuth2 клиента

Spring Boot уже отлично умеет работать с OAuth2 провайдерами, такими как Google и GitHub, поэтому настройка предельно проста. Всё, что нужно, — это добавить конфигурацию в файл application.yml:


spring:
  security:
    oauth2:
      client:
        registration:
          google:
            client-id: YOUR_GOOGLE_CLIENT_ID
            client-secret: YOUR_GOOGLE_CLIENT_SECRET
            scope:
              - email
              - profile
            redirect-uri: "{baseUrl}/login/oauth2/code/google"
            client-name: Google
        provider:
          google:
            authorization-uri: https://accounts.google.com/o/oauth2/v2/auth
            token-uri: https://oauth2.googleapis.com/token
            user-info-uri: https://openidconnect.googleapis.com/v1/userinfo
Важно:

Не забудьте заменить YOUR_GOOGLE_CLIENT_ID и YOUR_GOOGLE_CLIENT_SECRET на свои значения. Вы можете получить их, зарегистрировав приложение в Google Cloud Console.

3. Настройка контроллера

После настройки конфигурации нам нужно убедиться, что наш пользователь будет перенаправлен на страницу входа OAuth2. Это делается автоматически с помощью Spring Security, но контроллер понадобится для проверки авторизации.

Создадим тестовый контроллер:


@RestController
public class HelloController {

    @GetMapping("/")
    public String home(@AuthenticationPrincipal OAuth2User principal) {
        String email = principal.getAttribute("email");
        return "Hello, " + email + "! You are successfully authenticated.";
    }
}

Здесь мы использовали аннотацию @AuthenticationPrincipal, чтобы получить объект текущего пользователя из контекста безопасности.


Как всё это работает?

Вот схема взаимодействия с OAuth2 провайдером на практике:

  1. Пользователь нажимает на кнопку входа на вашем сайте.
  2. Его перенаправляют на страницу авторизации провайдера (например, Google).
  3. После успешного входа провайдер возвращает токен.
  4. Ваше приложение использует токен для доступа к данным пользователя (например, имя или email).

Защита ресурсов с помощью ролей

Допустим, вам нужно ограничить доступ к некоторым ресурсам только для определённых ролей. Вот как это можно сделать:

1. Добавьте фильтр безопасности в конфигурации Spring Security

Создайте класс настройки безопасности:


@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/admin/**").hasRole("ADMIN")
                .antMatchers("/", "/login").permitAll()
                .anyRequest().authenticated()
            .and()
            .oauth2Login(); // Включаем OAuth2 для логина
    }
}

2. Работайте с ролями пользователей

По умолчанию Spring Security позволяет использовать пользовательские роли. Убедитесь, что ваш OAuth2 провайдер предоставляет их. Если нет — можно расширить функциональность с помощью кастомного маппера:


@Component
public class CustomOAuth2UserService implements OAuth2UserService<OAuth2UserRequest, OAuth2User> {

    @Override
    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
        OAuth2User oAuth2User = new DefaultOAuth2UserService().loadUser(userRequest);

        // Добавляем роль "USER" ко всем аутентифицированным пользователям
        List<GrantedAuthority> authorities = new ArrayList<>(oAuth2User.getAuthorities());
        authorities.add(new SimpleGrantedAuthority("ROLE_USER"));

        return new DefaultOAuth2User(authorities, oAuth2User.getAttributes(), "name");
    }
}

С помощью этой настройки вы можете добавлять свои роли для пользователей, например, на основе данных, полученных от OAuth2 провайдера.


Практическое задание

  1. Настройте Spring Boot приложение для аутентификации через Google.
  2. Реализуйте контроллер, который возвращает приветственное сообщение с email аутентифицированного пользователя.
  3. Ограничьте доступ к определённым URL-адресам только для пользователей с ролью "ADMIN".

Частые вопросы и типичные ошибки

  • Я получаю ошибку "invalid_client" при входе через Google. Проверьте, правильно ли указаны client-id и client-secret. Также убедитесь, что redirect URL совпадает с указанным в Google Cloud Console.
  • OAuth2 игнорирует роль, указанную в настройке. Убедитесь, что ваш провайдер передаёт роли в ответе. Если нет, используйте кастомный OAuth2UserService.
  • Токен быстро истекает. Это может быть связано с настройкой времени жизни токена у провайдера. Рассмотрите использование Refresh токенов для обновления доступа.

На этом всё для данной лекции. Вы узнали, как настроить OAuth2 в Spring Security, аутентифицировать пользователей через сторонние сервисы (Google, GitHub) и защитить ресурсы с использованием ролей. В следующих лекциях мы углубимся в работу JWT, Refresh токенов и настройку микросервисов. Увидимся!

Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ