Django集成Keycloak认证回调遇401未授权错误求助
问题:Django集成Keycloak认证回调时出现401未授权错误
登录Keycloak服务器后,在登录回调环节触发错误:HTTPError at /oidc/callback/,具体错误为:401 Client Error: Unauthorized for 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
settings.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错误日志
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
补充说明
该问题与某GitHub Issue情况一致,按照方案需要将OIDC_OP_AUTHORIZATION_ENDPOINT修改为http://keycloak:8080/realms/SquadStack/protocol/openid-connect/auth,但本地无法通过该容器名访问Keycloak,只能用localhost访问。无法定位问题出在Docker、mozilla-django-oidc还是Keycloak,请求帮助。
内容的提问来源于stack exchange,提问作者Sagar Gupta
相关产品推荐
相关产品推荐

