Как выйти из Keycloak из кода Django - PullRequest
0 голосов
/ 02 октября 2019

Невозможно выйти из IDC keycloak изнутри кода приложения Django. Все ответы на вопросы stackoverflow не сработали (большинство из них для более старых версий задействованных компонентов), то же самое относится и к документации по keycloak.

Недавно мы внедрили аутентификацию на основе keycloak для нашего сайта на Django. Работает нормально для аутентификации. Приложение построено на Docker, три контейнера: веб-сайт на порту 8000, keycloak db (образ postgres), keycloak (образ jboss / keycloak) на порту 8080.

Теперь мне нужно добавить функцию «Выход» вэто означает выделение клавиатуры из моего кода Django и перенаправление пользователя обратно на экран регистрации клавиатуры.

Моя настройка:

Django 2.2
Python 3.5
keycloak 7
social-auth-app-django         3.1.0
social-auth-core               3.2.0

Документация о ключах предлагает следующее:

POST /{realm}/users/{id}/logout

с идентификатором пользователя и именем области.

Это возвращает 403 и ошибку: «Запрещено (файл cookie CSRF не установлен.): / {Имя области} / пользователи / {идентификатор пользователя} / logout /»

urls. py

urlpaterns = [
....
    url(r'logout/$', logout_view, name='logout'),
...
]

views.py

from django.http import HttpResponseRedirect
import requests
def logout_view(request):
    url = '%s<realm name>/users/<user id>/logout/' % settings.LOGOUT_REDIRECT_URL

    r = requests.post(url, data = {})
    #r.status_code at this point is 403

    #also tried another sugestion: 
    url = '%sauth/realms/%s/protocol/openid-connect/logout/' % (settings.LOGOUT_REDIRECT_URL, '<some realm name>')

    r = requests.post(url, data = {})
    #r.status_code at this point is 403

    #also tried with refresh_token and client_id:
    url = "http://<website ip>:8000/<realm name>/users/<user id>/logout/"
    refresh_token = '<some refresh token pulled out from stout>'
    r = requests.post(url, data = {'refresh_token': refresh_token, 'client_id': '<user id>'})
    #for 'client_id' above tried both user id and user name
    #r.status_code at this point is also 403

    return HttpResponseRedirect("http://<website ip>:8000")

Это возвращает меня на главную страницу моего сайта, я все еще вошел в систему и могу просматриватьсайт нормально. Нажатие на экран входа в систему Keycloak в этот момент возвращает меня на мою первую страницу веб-сайта, на которой вы уже авторизованы, так что я все еще аутентифицирован. Сеанс убийства перед кодом POST в Django ничего не меняет. По сути, нет выхода ни из websste, ни из keycloak, когда я проходил аутентификацию через keycloak. Истечение срока действия Keycloak происходит со временем, поэтому настройки realm.json работают.

Я пытался установить это в моих settings.py:

CSRF_COOKIE_SECURE = False
SESSION_COOKIE_SECURE = False

.. но безрезультатно.

Итак, где я могу найти пример работающего кода Django, который отключает пользователя от Keycloak? Спасибо


Другие произведения (вероятно, неактуальные):

settings.py

.....
LOGIN_URL = SCRIPT_NAME +  '/login/keycloak'

#yes, I tried this:
CSRF_COOKIE_SECURE = False
SESSION_COOKIE_SECURE = False

SOCIAL_AUTH_KEYCLOAK_KEY = '<some keycloak key>'
SOCIAL_AUTH_KEYCLOAK_SECRET = 'some keycloak secret'
SOCIAL_AUTH_KEYCLOAK_PUBLIC_KEY = 'some public key'
SOCIAL_AUTH_KEYCLOAK_AUTHORIZATION_URL = 'http://<some ip>:8080/auth/realms/<some realm>/protocol/openid-connect/auth'
SOCIAL_AUTH_KEYCLOAK_ACCESS_TOKEN_URL = 'http://<some ip>:8080/auth/realms/<some realm>/protocol/openid-connect/token'

SOCIAL_AUTH_STRATEGY = 'social_django.strategy.DjangoStrategy'
SOCIAL_AUTH_STORAGE = 'social_django.models.DjangoStorage'

SOCIAL_AUTH_KEYCLOAK_ID_KEY = 'email'
SOCIAL_AUTH_POSTGRES_JSONFIELD = True
SOCIAL_AUTH_URL_NAMESPACE = 'social'
LOGIN_REDIRECT_URL = 'http://<website ip>:8000/'
LOGOUT_REDIRECT_URL = 'http://<website ip>:8000/'

SOCIAL_AUTH_POSTGRES_JSONFIELD = True

SOCIAL_AUTH_PIPELINE = (
    'social_core.pipeline.social_auth.social_details',
    'social_core.pipeline.social_auth.social_uid',
    'social_core.pipeline.social_auth.auth_allowed',
    'social_core.pipeline.social_auth.social_user',
    'social_core.pipeline.user.get_username',
    'social_core.pipeline.mail.mail_validation',
    'social_core.pipeline.user.create_user',
    'social_core.pipeline.social_auth.associate_user',
    'social_core.pipeline.debug.debug',
    'social_core.pipeline.social_auth.load_extra_data',
    'social_core.pipeline.user.user_details',
    'social_core.pipeline.debug.debug',
)
....

docker-compose.yml

version: '3'

services:
  web:
    restart: unless-stopped
    container_name: web-container
    build:
      context: .
      dockerfile: Dockerfile.dev
    ports:
      - "8000:8000"
    environment:
      PRODUCTION: 'false'
      DEBUG: 'True'
      DJANGO_SETTINGS_MODULE: '<something>.settings.postgres'
      DB_NAME: '<some name>'
      DB_USER: '<some user>'
      DB_PASS: '<some password>'
      DB_HOST: '<some host>'
    depends_on: 
      - db
    volumes:
      - ./:/usr/src/app/

  db:
    image: postgres:9.6.2
    # volumes:
    #     - ../docker-postgresql-multiple-databases:/docker-entrypoint-initdb.d
    volumes:
      - data:/var/lib/postgresql/data
    environment:
      - POSTGRES_MULTIPLE_DATABASES=<something>
      - POSTGRES_USER=<some user>
      - POSTGRES_PASSWORD=<some password>

  keycloakdb:
      image: postgres
      volumes:
        - keycloak_postgres_data:/var/lib/postgresql/data
      environment:
        POSTGRES_DB: keycloak
        POSTGRES_USER: keycloak
        POSTGRES_PASSWORD: password

  keycloak:
      image: jboss/keycloak
      command: -b 0.0.0.0 -Dkeycloak.migration.action=import -Dkeycloak.migration.provider=dir -Dkeycloak.migration.dir=/tmp/
      environment:
        DB_VENDOR: POSTGRES
        DB_ADDR: keycloakdb
        DB_DATABASE: keycloak
        DB_USER: keycloak
        DB_SCHEMA: public
        DB_PASSWORD: <some password>
        KEYCLOAK_USER: <some user>
        KEYCLOAK_PASSWORD: <some password>
        #KEYCLOAK_IMPORT: /tmp/
      ports:
        - 8080:8080
      volumes:
        - ./keycloak/:/tmp/
      depends_on:
        - keycloakdb


volumes:
  data:
    # external: true
  keycloak_postgres_data:
      driver: local

keycloak / realm.json

{
  "id" : "<some realm id>",
  "realm" : "<some realm name>",
  "notBefore" : 0,
  "revokeRefreshToken" : false,
  "refreshTokenMaxReuse" : 0,
  "accessTokenLifespan" : 300,
  "accessTokenLifespanForImplicitFlow" : 900,
  "ssoSessionIdleTimeout" : 1800,
  "ssoSessionMaxLifespan" : 36000,
  "ssoSessionIdleTimeoutRememberMe" : 0,
  "ssoSessionMaxLifespanRememberMe" : 0,
  "offlineSessionIdleTimeout" : 2592000,
  "offlineSessionMaxLifespanEnabled" : false,
  "offlineSessionMaxLifespan" : 5184000,
  "accessCodeLifespan" : 60,
  "accessCodeLifespanUserAction" : 300,
  "accessCodeLifespanLogin" : 1800,
  "actionTokenGeneratedByAdminLifespan" : 43200,
  "actionTokenGeneratedByUserLifespan" : 300,
  "enabled" : true,
  "sslRequired" : "external",
  "registrationAllowed" : false,
  "registrationEmailAsUsername" : false,
  "rememberMe" : false,
  "verifyEmail" : false,
  "loginWithEmailAllowed" : true,
  "duplicateEmailsAllowed" : false,
  "resetPasswordAllowed" : false,
  "editUsernameAllowed" : false,
  "bruteForceProtected" : false,
  "permanentLockout" : false,
  "maxFailureWaitSeconds" : 900,
  "minimumQuickLoginWaitSeconds" : 60,
  "waitIncrementSeconds" : 60,
  "quickLoginCheckMilliSeconds" : 1000,
  "maxDeltaTimeSeconds" : 43200,
  "failureFactor" : 30,
  "roles" : {
    ....bunch of roles
}
...