Почему мой пользователь анонимен после входа в систему по OAuth2 с помощью Spring Boot?

Я пытаюсь подключить авторизацию OAuth к своему проекту через Github, но после успеха мой пользователь остается анонимным:

@RestController
@RequestMapping(path = "/")
public class HomeController {

    @GetMapping
    public String home() {
        return "Hello, %s".formatted(SecurityContextHolder.getContext().getAuthentication().getName());
    }
}

и вывод:

Hello, anonymousUser

Вот мой компонент SecurityFilterChain и настройки application.yaml:

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http, Converter<Jwt, UsernamePasswordAuthenticationToken> converter) throws Exception {
        http
                .authorizeHttpRequests(authorize ->
                                authorize
                                        .anyRequest()
                                        .permitAll()
                )
                .csrf(AbstractHttpConfigurer::disable)
                .cors(AbstractHttpConfigurer::disable)
                .httpBasic(AbstractHttpConfigurer::disable)
                .oauth2Login(withDefaults())
                .oauth2ResourceServer(configurer ->
                        configurer
                                .jwt((jwt) -> jwt.jwtAuthenticationConverter(converter))
                )
                .sessionManagement(configurer ->
                        configurer
                                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                )
                .exceptionHandling(configurer ->
                        configurer
                                .authenticationEntryPoint(new BearerTokenAuthenticationEntryPoint())
                                .accessDeniedHandler(new BearerTokenAccessDeniedHandler())
                );
        return http.build();
    }
spring:
  security:
    oauth2:
      client:
        registration:
          github:
            clientId: <hidden>
            clientSecret: <hidden>
            redirect-uri: '{baseUrl}/login/oauth2/code/{registrationId}'

УПД: Я так понял, что это происходит из-за настроек:

.sessionManagement(configurer ->
    configurer
        .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)

, но я не понимаю, как это отключить? Я хочу, чтобы в моем приложении не было сеансов и общение осуществлялось исключительно через токены доступа, выданные Github, но вместо этого я получаю JSESSIONID, установленный в файле cookie. Как сделать так, чтобы после успешной авторизации возвращались токены доступа вместо установки Cookies?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
0
117
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

Вероятно, вам следует прочитать раздел Основы OAuth2 моих руководств.

oauth2Login (код авторизации и токены обновления в клиенте Spring OAuth2) — это что-то:

  • на основе сессий
  • требуется защита от CSRF (поскольку он основан на сеансах)
  • реализовано на клиентах OAuth2 (на стороне сервера), а не на серверах ресурсов
  • используется для получения токенов с сервера авторизации и сохранения их в сеансе, а не для создания контекста безопасности из токена-носителя
  • обработка обновления токенов (если токен обновления предоставлен сервером авторизации и когда срок действия токена доступа истек или скоро закончится)

Сервер авторизации, клиент и сервер ресурсов — это три разных субъекта OAuth2. Авторизация запросов на основе Bearer токена доступа — это бизнес сервера ресурсов => oauth2Login не имеет никакого отношения к серверу ресурсов.

В качестве примечания: если ваш интерфейс представляет собой одностраничное или мобильное приложение, вам не следует пытаться авторизовать свои запросы с помощью токенов Bearer . Вместо этого вам следует использовать сеансы на бэкэнде OAuth2 для фронтенда.

Почему мне следует хранить токен JWT? Смысл токена не в том, чтобы их хранить. А разве нет? Я связался с Github, перенаправил пользователя, он залогинился, а затем я обменял код авторизации на токен. Могу ли я просто передать этот токен интерфейсу, а затем он будет взаимодействовать с сервером, просто поместив его в заголовок авторизации?

ulxanxv 25.05.2024 17:04

Я, наверное, неправильно понял ваш вопрос. У меня есть мобильное приложение, которое взаимодействует с REST API. Я хочу сохранить токен в мобильном приложении.

ulxanxv 25.05.2024 17:35

Если вас интересует, почему вам следует использовать сеансы между интерфейсом и сервером, вы можете прочитать этот пост от команды Spring Security: github.com/spring-projects/spring-authorization-server/issue‌​s/…

ch4mp 25.05.2024 19:29

Я обменял код авторизации на токен. Ты этого не сделал. Ваш клиент Spring OAuth2 сделал это на сервере. Вы ничего не кодировали для сервера для отправки токена в мобильный интерфейс, а также для этого интерфейса для хранения токенов, предоставления токена доступа в качестве заголовка авторизации Bearer для следующих запросов к серверу или обновления токена доступа по истечении срока его действия с использованием токена обновления, обычно примерно каждые 5 минут. И в любом случае вам не следует пытаться отправлять токены во фронтенд. Просто научитесь работать с сессиями между фронт-эндом и бэк-эндом.

ch4mp 25.05.2024 19:37

Отлично. Я понял, что этот стандарт предполагает использование сессий. Остается еще один вопрос: допустима ли практика получать информацию о пользователе от стороннего сервиса и выпускать на ее основе собственный токен JWT? Чтобы избавить пользователя от необходимости регистрироваться и подтверждать телефон или электронную почту, но не более того.

ulxanxv 25.05.2024 22:13

Это делает любой сервер авторизации, соответствующий OIDC (Keycloak, Auth0, Spring Authorization Server и многие другие).

ch4mp 25.05.2024 22:22

этот стандарт предполагает использование сеансов. Это справедливо только для сервера авторизации и серверных клиентов, а не для серверов ресурсов, которые могут (и должны) быть без сохранения состояния.

ch4mp 25.05.2024 23:12

Другие вопросы по теме