401 Ошибка клиента: URL-адрес неавторизован [mozilla-django-oidc - Keycloack]

Я интегрирую аутентификацию keycloak в свое приложение django.

После того, как я вошел в систему на сервере keycloak, я столкнулся с ошибкой в ​​​​обратном вызове входа в систему. HTTPError в /oidc/callback/ 401 Ошибка клиента: не авторизован для URL-адреса: http://keycloak:8080/realms/SquadStack/protocol/openid-connect/userinfo

вот мой docker-compose.yml


services:
  db:
    image: postgres:13
    environment:
      - POSTGRES_DB=squadrun
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=123456
    volumes:
      - ~/.siq/pg_data:/var/lib/postgresql/data
    ports:
      - "5432:5432"
    networks:
      - local-keycloak
  redis:
    image: redis
    expose:
      - 6379
    networks:
      - local-keycloak
  celery:
    build:
      context: .
      dockerfile: Dockerfile
    command: celery --app=squadrun worker -Q voice_make_ivr_india_queue,voice_send_email_india_queue,voice_send_email_india_upstox_queue,voice_send_sms_india_queue,voice_workflow_india_queue,celery_voice,ivr_queue,voice_analytics_and_metrics_queue,voice_fsm_india_queue,dnd_queue,voice_bulk_sync,voice_dnd_and_compliance_actions_queue,voice_notifications_queue,voice_make_ivr_india_queue,voice_send_email_india_queue,voice_send_email_india_upstox_queue,voice_send_sms_india_queue,voice_sync_ivr_details_india_queue,voice_workflow_india_queue,voice_sync_sms_details_india_queue,voice_send_sms_india_upstox_queue,voice_dnd_and_compliance_actions_upstox_queue,voice_imports_queue --concurrency=3 --without-heartbeat --without-gossip -n celery.%%h --loglevel=INFO
    container_name: celery
    working_dir: /home/docker/code
    volumes:
      - .:/home/docker/code
    depends_on:
      - db
      - redis
    networks:
      - local-keycloak
  web:
    build:
      context: .
      dockerfile: Dockerfile
    command: python -Wignore manage.py runserver 0.0.0.0:8001
    container_name: django_web3
    volumes:
      - .:/home/docker/code
    ports:
      - "8001:8001"
    depends_on:
      - db
      - redis
    networks:
      - local-keycloak
  keycloak:
    image: quay.io/keycloak/keycloak:20.0.2
    command: start-dev
    container_name: keycloak
    ports:
      - "8080:8080"
    environment:
      - KEYCLOAK_ADMIN=admin
      - KEYCLOAK_ADMIN_PASSWORD=admin
    networks:
      - local-keycloak
networks:
  local-keycloak:
    driver: bridge

вот моя настройка.py

AUTHENTICATION_BACKENDS = [
    'apps.voice.voice_auth.auth.KeycloakOIDCAuthenticationBackend',
    'django.contrib.auth.backends.ModelBackend',
]

OIDC_RP_CLIENT_ID = "voice-dashboard"
OIDC_RP_CLIENT_SECRET = "rnX0eo0R43xnZficrZTkQQseyBip4V7t"
OIDC_RP_SIGN_ALGO = "RS256"
OIDC_OP_JWKS_ENDPOINT = "http://keycloak:8080/realms/SquadStack/protocol/openid-connect/certs"
OIDC_OP_AUTHORIZATION_ENDPOINT = "http://172.20.0.3:8080/realms/SquadStack/protocol/openid-connect/auth"
OIDC_OP_TOKEN_ENDPOINT = "http://keycloak:8080/realms/SquadStack/protocol/openid-connect/token"
OIDC_OP_USER_ENDPOINT = "http://keycloak:8080/realms/SquadStack/protocol/openid-connect/userinfo"
LOGIN_REDIRECT_URL = "/voice/dashboard/index/"
LOGOUT_REDIRECT_URL = "/voice/dashboard/index/"

вот auth.py


class KeycloakOIDCAuthenticationBackend(OIDCAuthenticationBackend):

    def create_user(self, claims):
        """ Overrides Authentication Backend so that Django users are
            created with the keycloak preferred_username.
            If nothing found matching the email, then try the username.
        """
        user = super(KeycloakOIDCAuthenticationBackend, self).create_user(claims)
        user.first_name = claims.get('given_name', '')
        user.last_name = claims.get('family_name', '')
        user.email = claims.get('email')
        user.username = claims.get('preferred_username')
        user.save()
        return user

    def filter_users_by_claims(self, claims):
        """ Return all users matching the specified email.
            If nothing found matching the email, then try the username
        """
        email = claims.get('email')
        preferred_username = claims.get('preferred_username')

        if not email:
            return self.UserModel.objects.none()
        users = self.UserModel.objects.filter(email__iexact=email)

        if len(users) < 1:
            if not preferred_username:
                return self.UserModel.objects.none()
            users = self.UserModel.objects.filter(username__iexact=preferred_username)
        return users

    def update_user(self, user, claims):
        user.first_name = claims.get('given_name', '')
        user.last_name = claims.get('family_name', '')
        user.email = claims.get('email')
        user.username = claims.get('preferred_username')
        user.save()
        return user

журналы джанго

django_web3       | django 02/Jan/2023:14:02:14,278955 +0000 [ERROR] django.request: thread=281473135460832 extra:status_code=500&request=<WSGIRequest:GET'/oidc/callback/?state=R1OaaRk4jfr5nNNI4gr5CSdfX6sXoEqg&session_state=ea277a99-7da4-4904-abb6-63fa9bb7fb75&code=4b3c49b6-11c9-4cef-b847-fe356dfe86c3.ea277a99-7da4-4904-abb6-63fa9bb7fb75.bad660f7-7969-42d3-8475-536e4955c554'> Internal Server Error: /oidc/callback/
django_web3       | Traceback (most recent call last):
django_web3       |   File "/usr/local/lib/python3.5/site-packages/django/core/handlers/base.py", line 149, in get_response
django_web3       |     response = self.process_exception_by_middleware(e, request)
django_web3       |   File "/usr/local/lib/python3.5/site-packages/django/core/handlers/base.py", line 147, in get_response
django_web3       |     response = wrapped_callback(request, *callback_args, **callback_kwargs)
django_web3       |   File "/usr/local/lib/python3.5/site-packages/django/views/generic/base.py", line 68, in view
django_web3       |     return self.dispatch(request, *args, **kwargs)
django_web3       |   File "/usr/local/lib/python3.5/site-packages/django/views/generic/base.py", line 88, in dispatch
django_web3       |     return handler(request, *args, **kwargs)
django_web3       |   File "/usr/local/lib/python3.5/site-packages/mozilla_django_oidc/views.py", line 88, in get
django_web3       |     self.user = auth.authenticate(**kwargs)
django_web3       |   File "/usr/local/lib/python3.5/site-packages/django/contrib/auth/__init__.py", line 74, in authenticate
django_web3       |     user = backend.authenticate(**credentials)
django_web3       |   File "/usr/local/lib/python3.5/site-packages/mozilla_django_oidc/auth.py", line 242, in authenticate
django_web3       |     return self.get_or_create_user(access_token, id_token, verified_id)
django_web3       |   File "/usr/local/lib/python3.5/site-packages/mozilla_django_oidc/auth.py", line 259, in get_or_create_user
django_web3       |     user_info = self.get_userinfo(access_token, id_token, verified_id)
django_web3       |   File "/usr/local/lib/python3.5/site-packages/mozilla_django_oidc/auth.py", line 202, in get_userinfo
django_web3       |     user_response.raise_for_status()
django_web3       |   File "/usr/local/lib/python3.5/site-packages/requests/models.py", line 943, in raise_for_status
django_web3       |     raise HTTPError(http_error_msg, response=self)
django_web3       | requests.exceptions.HTTPError: 401 Client Error: Unauthorized for url: http://keycloak:8080/realms/SquadStack/protocol/openid-connect/userinfo
django_web3       | django 02/Jan/2023:14:02:14,398185 +0000 [INFO] qinspect.middleware: thread=281473135460832 extra: [SQL] 0 queries (0 duplicates), 0 ms SQL time, 201 ms total request time
django_web3       | [02/Jan/2023 19:32:14] "GET /oidc/callback/?state=R1OaaRk4jfr5nNNI4gr5CSdfX6sXoEqg&session_state=ea277a99-7da4-4904-abb6-63fa9bb7fb75&code=4b3c49b6-11c9-4cef-b847-fe356dfe86c3.ea277a99-7da4-4904-abb6-63fa9bb7fb75.bad660f7-7969-42d3-8475-536e4955c554 HTTP/1.1" 500 269936

Эта проблема такая же, как эта https://github.com/mozilla/mozilla-django-oidc/issues/481 В соответствии с этим решением я думаю, что мне нужно изменить OIDC_OP_AUTHORIZATION_ENDPOINT на "http://keycloak:8080/realms/SquadStack/protocol/openid-connect/auth" но я не могу зайти на этот сайт http://keycloak:8080 Я не могу связаться с сервером keycloak, используя имя контейнера докеров вместо localhost в имени хоста я не могу понять, связана ли проблема с докером, mozilla-django-oidc или Keycloak, и я застрял здесь Я новичок в докере, и keycloak, возможно, сделал какую-то наивную ошибку Любая помощь будет оценена!

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
77
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Я использовал kubernetes.docker.internal в качестве доменного имени вместо localhost и keycloak, что решает мою проблему. Мои измененные настройки:

KEYCLOACK_BASE_URI = "http://kubernetes.docker.internal:8080"
KEYCLOACK_REALM_NAME = "SquadStack"
OIDC_AUTH_URI = KEYCLOACK_BASE_URI + "/realms/" + KEYCLOACK_REALM_NAME
OIDC_OP_JWKS_ENDPOINT = OIDC_AUTH_URI + "/protocol/openid-connect/certs"
OIDC_OP_AUTHORIZATION_ENDPOINT = OIDC_AUTH_URI + "/protocol/openid-connect/auth"
OIDC_OP_TOKEN_ENDPOINT = OIDC_AUTH_URI + "/protocol/openid-connect/token"
OIDC_OP_USER_ENDPOINT = OIDC_AUTH_URI + "/protocol/openid-connect/userinfo"
OIDC_OP_LOGOUT_ENDPOINT = OIDC_AUTH_URI + "/protocol/openid-connect/logout"

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