Как выполнить реализацию backchannel logout для OAuth2 OIDC в Spring?

Привет всем! <br/> <br/> Мне требуется помощь в понимании механизма работы backchannel logout в OIDC. <br/> <br/> Я прочитал следующие материалы: <br/> <br/> <a href="https://openid.net/specs/openid-connect-backchannel-1_0.html#Backchannel" rel="nofollow">https://openid.net/specs/openid-connect-backchannel-1_0.html#Backchannel</a> <br/> <a href="https://docs.spring.io/spring-security/reference/servlet/oauth2/login/logout.html" rel="nofollow">https://docs.spring.io/spring-security/reference/servlet/oauth2/login/logout.html</a> <br/> <br/> Из документации я понял, что сервис авторизации выдает OidcIdToken, а сервер клиента сохраняет информацию (authorizedClient) в сессии и использует refresh token для обновления access_token. <br/> <br/> Затем сервис авторизации начинает процесс выхода из системы, создавая OidcLogoutToken, и отправляет запросы к клиентам через HTTP POST на адрес /logout/connect/back-channel/{registrationId}. Инициация выхода может осуществляться как "по нажатию кнопки на фронте", так и "по проверке валидности сессии". <br/> <br/> Могу ли я считать, что я правильно понял этот процесс? Почему в Spring на стороне oauth2-authorization-server не был реализован обработчик logout, который мог бы отправлять запросы клиентам по REST? Также верно ли, что OidcLogoutToken необходимо преобразовать в logout_token и отправить его на сервер клиента по URL: /logout/connect/back-channel/{registrationId}?logout_token=....? <br/> <br/> Что касается реализации на стороне сервера авторизации, то мы используем RestOidcLogoutHandler для обхода по нашим клиентам, а на стороне сервиса клиента добавляем следующее: <br/> <br/> <pre><code class="java">//...
.oidcLogout { oidcLogoutSpec -&gt;
                oidcLogoutSpec.backChannel { }
                oidcLogoutSpec.oidcSessionRegistry(redisReactiveOidcSessionRepository)
            }
//..</code></pre> <br/>
  • 2 апреля 2025 г. 11:15
Ответы на вопрос 2
Да, вы правильно понимаете основные концепции механизма backchannel logout в OpenID Connect (OIDC). Давайте разложим этот процесс на более понятные детали и попробуем прояснить ваши вопросы.

### Основные концепции backchannel logout

1. **Инициация выхода**: Сервис авторизации инициирует выход из системы, создавая OidcLogoutToken. Этот токен включает информацию о сессиях пользователей, которые должны быть завершены.

2. **HTTP POST к клиенту**: Сервис авторизации отправляет HTTP POST запросы к зарегистрированным клиентам (то есть приложениям, использующим этот сервис аутентификации) по URL-адресу, указанному в спецификации: `/logout/connect/back-channel/{registrationId}`. 

3. **Обработка на стороне клиента**: Когда клиент получает запрос на выход, он должен соответствующим образом обработать токен выхода (например, завершить сессии пользователя).

### Вопросы о реализации в Spring

1. **Почему нет обработчика logout в Spring OAuth2 Authorization Server?**
   - На момент написания документации по Spring Security обработка backchannel logout не была встроена, поэтому разработчики должны самостоятельно реализовать эту часть, используя имеющиеся инструменты.

2. **Требуется ли преобразование OidcLogoutToken в logout_token?**
   - Да, OidcLogoutToken должен быть сериализован и передан клиенту как часть URL-параметра в запросе. Клиент должен быть в состоянии обработать этот токен, чтобы завершить соответствующие сессии.

### Пример реализации на стороне клиента

На стороне клиента вам нужно будет настроить обработку запросов logout следующим образом:

```java
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class LogoutController {

    @PostMapping("/logout/connect/back-channel/{registrationId}")
    public void handleLogout(@RequestParam("logout_token") String logoutToken) {
        // Здесь должна быть ваша логика для завершения сессии пользователя
        // например, удалить информацию из сессии или маркера
        // включите проверку и валидацию logoutToken для безопасности
    }
}
```

### Конфигурация в Spring Security

Как вы упомянули в вашем примере кода, настройка может выглядеть следующим образом. Также, вы должны убедиться, что вы настроили свой OidcSessionRegistry и другие компоненты:

```java
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
        .authorizeRequests()
            .anyRequest().authenticated()
            .and()
        .logout()
            .logoutSuccessUrl("/") // перенаправление после выхода
            .and()
        .oauth2Login()
            .and()
        .oidcLogout(oidcLogoutSpec -> {
            oidcLogoutSpec.backChannel(backChannelSpec -> {
                // можно добавить дополнительные опции, если нужно
            });
            oidcLogoutSpec.oidcSessionRegistry(redisReactiveOidcSessionRepository);
        });
    return http.build();
}
```

### Заключение

Процесс backchannel logout требует тщательной настройки и реализации как на стороне сервера авторизации, так и на стороне клиента. При правильной конфигурации и реализации он будет обеспечивать безопасное управление сессиями пользователей. Не забудьте тщательно протестировать реализацию и все возможные сценарии выхода из системы.
Привет! Давай разберем, как работает Backchannel Logout в OpenID Connect (OIDC) и как это можно реализовать с использованием Spring Security для OAuth2. 

Backchannel Logout в OpenID Connect — это механизм, при котором сервер авторизации уведомляет сервис клиентов о выходе пользователя (logout). Этот механизм предназначен для того, чтобы клиент мог корректно обработать выход, даже если пользователь не взаимодействует с фронтендом, а все происходит в "тени" (через сервер).

Инициация Logout: Когда пользователь выходит из системы, например, нажимая кнопку "выход" на фронте, сервер авторизации может отправить запрос на клиентский сервер, чтобы сообщить ему о выходе пользователя.

Сообщение о выходе: Сервер авторизации генерирует OIDC Logout Token (logout_token), который будет отправлен на сервер клиента для подтверждения выхода.

Обработка Logout на клиенте: Клиент должен обрабатывать запросы на URL типа /logout/connect/back-channel/{registrationId}, получая logout_token в запросе.

Почему нет LogoutHandler в Spring OAuth2 Authorization Server?
LogoutHandler, о котором вы упоминаете, не является частью Spring Security OAuth2 Authorization Server, потому что Backchannel Logout — это специфическая часть протокола OpenID Connect, который работает на уровне серверов авторизации и клиентов. В Spring Security Authorization Server фокус в основном на обработке авторизации и выдачи токенов, а не на действиях, которые происходят в процессе выхода (logout) в клиентских приложениях.

Кроме того, реализация Backchannel Logout зависит от конфигурации вашего OIDC-поставщика и сервисов клиентов, а также от того, как обрабатываются сессии в вашем приложении. Это делает задачу не универсальной для всех клиентов и серверов.

Пошаговое объяснение реализации
Сервер авторизации инициирует запрос на выход (Backchannel Logout):

Когда на сервере авторизации происходят события выхода (например, через кнопку "выход" на фронте или по таймеру сессии), сервер авторизации генерирует OIDCLogoutToken.

Отправка logout-запроса клиенту:

Сервер авторизации отправляет HTTP POST запрос на URL /logout/connect/back-channel/{registrationId} с параметром logout_token. Это уведомление о том, что пользователь должен выйти из системы на стороне клиента.

POST /logout/connect/back-channel/{registrationId}
Content-Type: application/json

{
"logout_token": "someLogoutTokenValue"
}
Регистрация клиента: В URL {registrationId} вы указываете идентификатор регистрации клиента, который был настроен на сервере авторизации. Это используется для точной идентификации клиента, которому нужно отправить уведомление о выходе.

Настройка клиента (Spring):

На стороне клиента вам нужно настроить Spring Security для обработки Backchannel Logout.

В частности, вам нужно настроить Spring Security с использованием OIDC и обеспечить корректную обработку сообщения о выходе через oidcLogout и настройку backChannel.

Пример конфигурации клиента:
.oidcLogout { oidcLogoutSpec ->
oidcLogoutSpec.backChannel { backChannelSpec ->
// Конфигурация обработки backchannel logout
}
oidcLogoutSpec.oidcSessionRegistry(redisReactiveOidcSessionRepository)
}
Здесь oidcSessionRegistry управляет сессиями пользователя (например, хранит их в Redis), а backChannel отвечает за обработку запросов на выход от сервера авторизации.

Преобразование OidcLogoutToken в logout_token
На сервере авторизации вы получаете OidcLogoutToken. Для того, чтобы отправить его клиенту, вам нужно:

Преобразовать OidcLogoutToken в строку (если требуется, вы можете закодировать его, например, в Base64, чтобы передать через HTTP как параметр logout_token).

Отправить POST-запрос на сервер клиента по URL /logout/connect/back-channel/{registrationId}?logout_token=..., где {registrationId} — это идентификатор клиента, а logout_token — сам токен.

Реализация на стороне клиента:
На стороне клиента вам нужно настроить механизм для получения уведомлений о выходе через Backchannel. Это можно сделать следующим образом:

На клиенте будет обработка URL /logout/connect/back-channel/{registrationId}, который будет обрабатывать POST-запросы, отправленные сервером авторизации.

Когда клиент получает такой запрос, он может выполнить действия по удалению сессии пользователя или очистке других данных (например, удаление access_token).

Пример настройки клиента:
Вот пример, как это может выглядеть в Spring:

// Конфигурация клиента для обработки logout
http.oauth2Login()
.oidcLogout { oidcLogoutSpec ->
oidcLogoutSpec.backChannel { backChannelSpec ->
// Пример конфигурации для backchannel logout
// Вы можете здесь указать дополнительные параметры, например, Redis репозиторий сессий
}
oidcLogoutSpec.oidcSessionRegistry(redisReactiveOidcSessionRepository)
}

Backchannel Logout — это способ уведомления клиентов о выходе пользователя без необходимости взаимодействовать с фронтендом.

Spring Security OAuth2 предоставляет инструменты для настройки Backchannel Logout в клиентской части через oidcLogout и backChannel.

На сервере авторизации вы генерируете OidcLogoutToken и отправляете его клиенту через HTTP POST запрос по URL /logout/connect/back-channel/{registrationId}.

На стороне клиента необходимо настроить обработку этих запросов, чтобы выполнить действия по очистке сессий или другим действиям.
Похожие вопросы