Используйте Keycloak Gatekeeper перед API бэкенда - PullRequest
0 голосов
/ 21 октября 2019

В одностраничном приложении (SPA), работающем на DOMAIN, вызовы DOMAIN / graphql перенаправляются на серверную часть. И внешний, и внутренний интерфейсы защищены экземпляром Keycloak Gatekeeper.

Идея состоит в том, что интерфейс и бэкэнд совместно используют токен kc-access.

Теперь токен доступа истекает в бэкэнде Gatekeeper. Если SPA обновляется в браузере, веб-интерфейс перенаправляется на Keycloak, и требуется новый токен доступа. Но если обновления не происходит, POST-запросы к DOMAIN / graphql завершаются ошибкой с кодом состояния 307, когда токен истек. Браузер не знает, как с этим справиться. Вход в браузер дает "{"error":"RESTEASY003065: Cannot consume content type"}". Если заголовок типа содержимого в POST удален, то ошибка будет означать, что «client_id не указан», а client_id включен в строку запроса.

Перенаправление запроса POST на Keycloak, вероятно, не будет лучшим решением. Очиститель будет, если сервер обновит свой токен доступа.

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

- --discovery-url=DISCOVERY_URL
- --client-id=CLIENT_ID
- --client-secret=****
- --enable-refresh-tokens=true
- --encryption-key=0123456789012345
- --store-url=boltdb:///boltdb
- --listen=0.0.0.0:3001
- --verbose=true
- --redirection-url=REDIRECTION_URL
- --upstream-url=http://127.0.0.1:3000

Это создает файл / boltdb в гейткипере, но, похоже, он не используется, так как файл не изменяется.

БэкэндГейткипер выдает следующую запись:

|1.5716729131430433e+09|debug|keycloak-gatekeeper/session.go:51|found the user identity|{"id": "b5b659cd-148e-4f23-bf2f-28e6f207f6c7", "name": "piet", "email": "", "roles": "offline_access,dashboard_viewer,uma_authorization,account:manage-account,account:manage-account-links,account:view-profile", "groups": ""}|
|1.5716729131462774e+09|info|keycloak-gatekeeper/middleware.go:154|accces token for user has expired, attemping to refresh the token|{"client_ip": "****", "email": ""}|
|1.5716729131463811e+09|error|keycloak-gatekeeper/middleware.go:161|unable to find a refresh token for user|{"client_ip": "**", "email": "", "error": "no session state found"}|

Таким образом, мы «не можем найти токен обновления для пользователя», так как «не найдено состояние сеанса» в соответствии с журналированием.

Кто-нибудь знает, как включить обновление токена?

Ответы [ 2 ]

1 голос
/ 21 октября 2019

Не похоже на хороший дизайн. Keycloak Gatekeeper использует поток кода предоставления, который не является лучшим потоком для SPA, как вы обнаружили (кажется, очень хакерским считывать идентификацию пользователя, предоставленную Gatekeeper в случае SPA).

SPA использует кодовый поток с PKCE или неявным потоком, и эти потоки используют автоматическое обновление токена (а не обновление токена). ИМХО, лучшим вариантом будет использование одного и того же идентификатора клиента во внешнем интерфейсе (SPA) и во внутреннем интерфейсе (например, API). Но интерфейс будет защищен Code Flow с PKCE и будет обрабатывать обновление собственных токенов. Gatekeeper будет защищать только бэкэнд (настройка + --no-redirects имеет смысл для защиты API)

0 голосов
/ 24 октября 2019

Также установив enable-refresh-tokens=true с тем же ключом шифрования в гейткипере на внешнем интерфейсе, проект работает.

Пользователь получает внешний интерфейс и перенаправляется на Keycloak. Там код авторизации получен. Этот код авторизации заменяется интерфейсным гейткипером на токен доступа и обновления, который помещается в cookie на внешнем интерфейсе. Когда бэкэнд вызывается с токеном с истекшим сроком действия, токен обновления дешифруется и используется для получения нового токена доступа.

Срок действия маркера обновления может истечь или быть недействительным. Когда 401 возвращается, веб-интерфейс должен обновить страницу, чтобы пользователь был перенаправлен на Keycloak.

Более безопасным было бы хранить токены не в файлах cookie внешнего интерфейса, а в общем хранилище.

...