# 이미 존재하는 것
- 장고 프로젝트 (with django-admin-interface)
- 연동할 키클락
# 원하는 것
장고 어드민의 기본 로그인 화면은 아래와 같다. (admin_interface를 사용하는 경우)
LOG IN 버튼 밑에 Keycloak용 로그인 버튼을 만들고, 키클락 유저로 로그인 가능하도록 만들겠다.
# 시작! 🚀
1) social auth 세팅
social-auth-app-django 설치
pip install social-auth-app-django
settings.py에 social_django 추가
# settings.py
INSTALLED_APPS = [
...
'social_django', # 추가
]
migration 수행
python manage.py migrate
여기까지 하면, python social auth 탭이 생긴 것을 확인할 수 있다.
2) keycloak 세팅
keycloak과 realm은 이미 있다는 가정 하에, client부터 만들어본다.
방금 복사한 시크릿은 SOCIAL_AUTH_KEYCLOAK_SECRET 로 쓰이게 된다.
- Included Client Audience : 클라이언트 선택
- Add to access token : ON
Audience mapper까지 만들었으니, 이제 Public key만 복사하면 keycloak에서 할 일은 끝이다.
이 public key는 SOCIAL_AUTH_KEYCLOAK_PUBLIC_KEY 로 쓰이게 된다.
3) django - keycloak 연동
settings.py에 아래 내용들을 추가한다.
# Keycloak 설정
AUTHENTICATION_BACKENDS = (
'social_core.backends.keycloak.KeycloakOAuth2', # Keycloak 백엔드 추가
'django.contrib.auth.backends.ModelBackend',
)
SOCIAL_AUTH_KEYCLOAK_KEY = '본인_키클락_클라이언트_이름'
SOCIAL_AUTH_KEYCLOAK_SECRET = '본인_키클락_클라이언트_시크릿'
SOCIAL_AUTH_KEYCLOAK_PUBLIC_KEY = '본인_키클락_퍼블릭_키'
SOCIAL_AUTH_KEYCLOAK_DOMAIN = '본인_키클락_도메인'
SOCIAL_AUTH_KEYCLOAK_REALM = '본인_키클락_REALM'
SOCIAL_AUTH_KEYCLOAK_AUTHORIZATION_URL = 'https://{domain}/realms/{realm}/protocol/openid-connect/auth'.format(domain=SOCIAL_AUTH_KEYCLOAK_DOMAIN, realm=SOCIAL_AUTH_KEYCLOAK_REALM)
SOCIAL_AUTH_KEYCLOAK_ACCESS_TOKEN_URL = 'https://{domain}/realms/{realm}/protocol/openid-connect/token'.format(domain=SOCIAL_AUTH_KEYCLOAK_DOMAIN, realm=SOCIAL_AUTH_KEYCLOAK_REALM)
SOCIAL_AUTH_KEYCLOAK_USERINFO_URL = 'https://{domain}/realms/{realm}/protocol/openid-connect/userinfo'.format(domain=SOCIAL_AUTH_KEYCLOAK_DOMAIN, realm=SOCIAL_AUTH_KEYCLOAK_REALM)
SOCIAL_AUTH_JWT_AUDIENCE = None
SOCIAL_AUTH_PIPELINE = (
'social_core.pipeline.social_auth.social_details',
'social_core.pipeline.social_auth.social_uid',
'social_core.pipeline.social_auth.social_user',
'social_core.pipeline.user.get_username',
'social_core.pipeline.user.create_user',
'social_core.pipeline.social_auth.associate_user',
'social_core.pipeline.social_auth.load_extra_data',
'social_core.pipeline.user.user_details',
)
urls.py에 아래 내용을 추가해준다.
urls.py
urlpatterns = [
...
path('social-auth/', include('social_django.urls', namespace='social')),
]
admin login 페이지를 수정해야 하므로... templates/admin/login.html 파일을 추가해주자.
여기서 참고로, 내 프로젝트의 tree는 아래와 같다.
.
├── manage.py
├── honglab
│ ├── __init__.py
│ ├── asgi.py
│ ├── wsgi.py
│ ├── urls.py
│ └── settings.py
├── templates
│ └── admin
│ └── login.html
└── db.sqlite3
이 구조에서 templates/admin/login.html을 아래와 같이 작성해준다.
{% extends "admin/login.html" %}
{% block content %}
<div id="content-main">
{{ block.super }} <!-- 기존 로그인 폼을 불러옵니다. -->
<!-- Keycloak 로그인 버튼 추가 -->
<div class="submit-row">
<input type="button" value="Keycloak 로그인"
onclick="location.href='{% url 'social:begin' 'keycloak' %}?next={{ request.GET.next }}'"
style="background: #ff3d00; color: white; width: 100%;">
</div>
</div>
{% endblock %}
settings.py에서 TEMPLATES 의 DIRS를 수정해준다.
TEMPLATES = [
{
...
'DIRS': [BASE_DIR / "templates"], # 본인 templates 폴더 위치에 맞게 적절히 조정
...
},
]
migration 한번 더 해주자
python manage.py migrate
다시 서버 띄워서 admin 접근해보면...
오!! 원하는대로 keycloak 로그인 버튼이 이쁘게 뜬다.
(버튼색은 admin.html 파일에서 알아서 고치자)
내 keycloak client에는 test란 유저가 존재한다. > 해당 유저로 로그인 해봤는데...
test란 유저는 접근권한이 없다고 뜬다.
당연하다. django admin 페이지에 접속하기 위해서는 staff 권한이 존재해야 한다.
일단 다시 admin 유저(superuser)로 로그인해보자.
test란 유저가 생성은 되어 있다.
staff도 주고, superuser도 줘보자.
그리고 다시 test로 로그인하면..
test 유저로 admin 페이지 접근에 성공했다.
그러나 키클락 유저가 처음 로그인할때마다 매번 staff 권한을 넣어주려면 너무 번거롭겠지?
키클락유저의 그룹을 확인해서, 특정 그룹에 따라 staff / superuser 권한을 넣어줘보자.
4) keycloak 그룹 연동
먼저 키클락에서 test용 group을 만들어줬다.
django-staff는 staff 권한만, django-superuser는 superuser 권한까지 줄 것이다.
staff-user : django-staff 그룹 조인
super-user : django-superuser 그룹 조인
그리고 openid client scope를 만들어줘야 한다.
- Name : openid
- Type : Default
마지막으로 group membership에 대한 mapper를 만들어줘야 한다.
Add mapper > By configuration > Group Membership을 클릭해준다.
이제 django project로 돌아와, pipeline을 추가해주자.
일단 pipeline은 core라는 app을 만들어서 그 안에 위치시킬 생각이다.
python manage.py startapp core
core/pipeline.py 파일을 생성해주자.
# core/pipeline.py
from django.contrib.auth.models import Group
def save_keycloak_groups(backend, user, response, *args, **kwargs):
if backend.name == 'keycloak':
keycloak_groups = response.get('groups', [])
print(keycloak_groups)
# Django의 Group 모델과 연동하여 사용자에게 그룹을 할당
for group_name in keycloak_groups:
# Django Group 모델에서 그룹을 찾거나 새로 생성
group, created = Group.objects.get_or_create(name=group_name)
# 사용자를 그룹에 추가
user.groups.add(group)
# 변경사항을 저장
user.save()
def rbac_for_admin(backend, user, response, *args, **kwargs):
if backend.name == 'keycloak':
keycloak_groups = response.get('groups', [])
# django-staff -> staff 권한 자동 획득
if 'django-staff' in keycloak_groups:
user.is_staff = True
user.save()
# django-superuser -> staff & superuser 권한 자동 획득
if 'django-superuser' in keycloak_groups:
user.is_staff = True
user.is_superuser = True
user.save()
메인 앱 (여기서는 홍랩) 의 settings.py를 손봐주자.
# honglab/settings.py
INSTALLED_APPS = [
'core', # 추가
...
]
SOCIAL_AUTH_PIPELINE = (
...
'core.pipeline.save_keycloak_groups', # 추가
'core.pipeline.rbac_for_admin', # 추가
)
마이그레이션이 필요하면 해주고, staff-user로 로그인해보자.
staff 권한은 있지만, 아무 모델에 대해서도 권한이 없기 때문에 이렇게만 보인다.
이번엔 super-user로 로그인해보겠다.
모든 메뉴가 잘 보인다.
Groups를 확인해보면,
키클락 그룹이 잘 연동되어 저장된 것을 확인할 수 있다.
위 내용들은 모두 github에 올려두었다.
https://github.com/suminhong/django/tree/main/admin-keycloak-login
끝!
'공부 > Python' 카테고리의 다른 글
[Python] 파이썬 실행 & 메모리 관리 방식, mutable & immutable 객체, 깊은 복사 (deep copy) (0) | 2022.12.04 |
---|---|
[boto3/paginator] EC2 Name Tag를 포함한 엑셀 뽑기 (0) | 2022.05.13 |
[Python] Python to Slack 2 : Slack Bot Message 보내기 + 쉽게 Formatting하기 (Block Kit Builder) (0) | 2022.01.22 |
[Python] Python to Slack 1 : Slack Bot 만들고 설정하기 (0) | 2022.01.22 |
[Python] CSV 파일 읽기/쓰기 (0) | 2021.04.30 |
댓글