Добрый день, дорогой друг.
Рассказываю интересную историю. Пишу свой SSO с spring security. Есть сервис-клиент, который получает авторизацию через SSO.
Действующие точки:
oauth2-client - c# приложение
server-oauth2 - SSO на spring security.
Что имею:
1. oauth2-client получает авторизацию через server-oauth2 и на server-oauth2 создается OAuth2Authorization, которая сохраняется в redis.
цепочка для деталий:
oauth2-client: GET
localhost:8080/oauth2/authorize? client_id=************@oauth.client....
server-oauth2: GET
localhost:5043/oauth2/charp?code=XQSuU0_hxT1nomJq5...
oauth2-client:POST
localhost:8080/token?grant_type=authorization_code
server-oauth2: return tokens (access_token, refresh_token, exp)
oauth2-client:
POST http://localhost:8080/oauth2/introspect
Authorization: Basic ************************ # clientId:secretId in base64
Content-Type: application/json
{
"token": "************************" # access token
}
server-oauth2: return token details + principal data
Соответственно, хожу рефрешить токен с oauth2-client каждые 30 минут.
2. пока пользователь пользуется oauth2-client, то с oauth2-client отправляется /oauth2/introspect на server-oauth2 (при каждом запросе) таким образом понимаю, что у пользователя OAuth2Authorization валидна и заодно обноляю пользовательские данные на oauth2-client (если необходимо).
3. Так как OAuth2Authorization содержит username нашего пользователя, то легко получить сессии пользователя через (RedisSessionRepository#findByUsername) а значит спокойно можно реализовать SLO. На oauth2-client вызывается logout - отправляем в server-oauth2 /oauth2/revoke. Что приводит к поиску сессий и их удаление. Все вроде хорошо, но нет.
Задача, которая мне пока не ясна:
Так как привязал все OAuth2Authorization к сессии и по окончанию сессии (timeout) сессия экспайрится, то пользовательская сессия умирает и с ней все OAuth2Authorization. Поведение как по мне вполне корректное, но для того чтобы сессия не умирала (пока ей пользуются внутри платформы), мне нужно обновлять lastAccessedTime при каждом вызове /oauth2/introspect. Таким образом буду говорить, что не убивай сессию, она еще активна.
Каким образом при вызове /oauth2/introspect из oauth2-client реализовать продление сессии пользователя?
@PS
Ипользую RedisIndexedSessionRepository. Соответственно пытаюсь обновить RedisSession#setLastAccessedTime таким образом, но в целом способ какой-то костыльный. Да и это не работает. Сессия продолжает экспайриться.
Redis
0.sorface.interview.session.0eb92b1f-6604-4fdc-aed2-c3105e880f8a - сессия oauth2-client
1.oauth2_auth_complete:54b15ec2-ffeb-403f-9297-9b9b3b5d8536 - OAuth2Authorization
1.sorface:session:index:org.springframework.session.FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME:developerdevpav - сессия принципала.
1.sorface.oauth2-complete - set с идентификаторами на 1.sorface.oauth2-complete:54b15ec2-ffeb-403f-9297-9b9b3b5d8536
1.sorface.oauth2-complete:54b15ec2-ffeb-403f-9297-9b9b3b5d8536 - здесь в качестве ключа выступает OAuth2Authorization#ID и проиндексированный principalName, accessToken, refreshToken. hash по сути связывает OAuth2Authorization - principal - session.
1.sorface:session:sessions:3bca540b-4d2c-45e6-8168-42a5f76aa949 - непосредственно данные сессии.
Подскажите в целом, правильный ли у меня подход к реализации таких историй? И может есть другой способ получения текущей сессии, кроме как через username, сохраненный в редис OAuth2Authorization?