장고 OAuth2.0 제공
172.17.0.1 (토론)님의 2025년 5월 14일 (수) 18:03 판
1 개요편집
django-oauth-toolkit을 통해 OAuth2.0 로그인을 제공한다. 공식 문서(https://django-oauth-toolkit.readthedocs.io/en/latest/)
애시당초 공급을 목표로 하는 라이브러리.
이미 로그인 뷰 등 기본적인 서비스는 구현된 상태라 가정한다.
과정 | 설명 | 비고 |
---|---|---|
설치 | pip install django-oauth-toolkit | |
settings.py 설정 | INSTALLED_APPS += [
"oauth2_provider",
]
AUTHENTICATION_BACKENDS = [ # 보통 소셜로그인 등을 구현했다면 이미 있음.
"django.contrib.auth.backends.ModelBackend",
]
OAUTH2_PROVIDER = {
# 토큰 만료 시간(초)
"ACCESS_TOKEN_EXPIRE_SECONDS": 36000,
}
|
|
url 등록 | path("o/", include("oauth2_provider.urls", namespace="oauth2_provider")),
path("auth/", include("myapp.auth_urls")), # 사용자 인증용
path("clients/", include("myapp.client_urls")), # 클라이언트 등록용
|
보통 custom_account를 구성하기에, auth 따위는 이쪽으로 넘기는 것도 좋을듯. |
form 제작 | from oauth2_provider.models import get_application_model
Application = get_application_model()
class ClientRegisterForm(forms.ModelForm):
class Meta:
model = Application
fields = ['name', 'redirect_uris']
widgets = {
'redirect_uris': forms.Textarea(attrs={'rows': 3}),
}
|
2 클라이언트 페이지 만들기.편집
과정 | 설명 | 비고 |
---|---|---|
url 설정. | # OAuth2.0 관련.
path('OAuth2.0/client_list', views.OAuth_client_list, name='OAuth_client_list'),
path('OAuth2.0/detail/<int:pk>', views.OAuth_client_edit, name='OAuth_client_edit'),
path('OAuth2.0/register', views.OAuth_register_client, name='OAuth_register_client'),
path('OAuth2.0/delete/<int:pk>', views.OAuth_delete_client, name='OAuth_delete_client'),
|
예시. 각 사정에 맞게 설정. |
view | ## OAuth2.0 제공 관련.
from oauth2_provider.models import get_application_model
from .forms import ClientRegisterForm
Application = get_application_model()
@login_required
def OAuth_client_list(request):
'''사용자가 가진 어플리케이션의 설정 보기.(어플리케이션을 여러 개 만들 수 있게 해야 할듯)'''
apps = Application.objects.filter(user=request.user)
return render(request, 'custom_account/OAuth2/client_list.html', {'apps': apps})
@login_required
def OAuth_client_edit(request, pk):
'''어플리케이션 수정 페이지.'''
app = get_object_or_404(Application, pk=pk, user=request.user)
if request.method == 'POST':
form = ClientRegisterForm(request.POST, instance=app)
if form.is_valid():
form.save()
return redirect('custom_account:OAuth_client_list') # 수정 후 목록 페이지로 리다이렉트
else:
form = ClientRegisterForm(instance=app)
return render(request, 'custom_account/OAuth2/register.html', {'form': form, 'is_edit':True})
@login_required
def OAuth_register_client(request):
'''어플리케이션 등록.'''
if request.method == 'POST':
form = ClientRegisterForm(request.POST)
if form.is_valid():
app = form.save(commit=False)
app.user = request.user
app.client_type = Application.CLIENT_CONFIDENTIAL
app.authorization_grant_type = Application.GRANT_AUTHORIZATION_CODE
app.save()
return redirect('custom_account:OAuth_client_list')
else:
form = ClientRegisterForm()
return render(request, 'custom_account/OAuth2/register.html', {'form': form})
@login_required
def OAuth_delete_client(request, pk):
'''어플리케이션 등록.'''
app = get_object_or_404(Application, pk=pk, user=request.user)
if app.user == request.user:
app.delete()
return redirect('custom_account:OAuth_client_list')
return render(request, 'custom_account/OAuth2/register.html', {'form': form})
|
|
list 탬플릿 | {% extends 'custom_account/section.html' %}
{% block content %}
<div class="row row-cols-1 row-cols-md-2 g-4">
{% for app in apps %}
<div class="col">
<div class="card h-100 shadow-sm">
<div class="card-body">
<h5 class="card-title d-flex justify-content-between align-items-center">
{{ app.name }}
<span>
<a class="btn btn-outline-primary btn-sm" href="{% url 'custom_account:OAuth_client_edit' app.pk %}">정보 수정</a>
<a class="btn btn-outline-danger btn-sm" href="{% url 'custom_account:OAuth_delete_client' app.pk %}"
onclick="return confirm('정말로 삭제하시겠습니까? 되돌릴 수 없습니다.');">삭제</a>
</span>
</h5>
<p><strong>Client ID:</strong> {{ app.client_id }}</p>
<p><strong>Client Secret:</strong> {{ app.client_secret }}</p>
<p><strong>Redirect URIs:</strong></p>
<ul class="list-group list-group-flush">
{% for uri in app.redirect_uris.splitlines %}
<li class="list-group-item">{{ uri }}</li>
{% empty %}
<li class="list-group-item text-muted">(등록된 URI가 없습니다)</li>
{% endfor %}
</ul>
</div>
</div>
</div>
{% empty %}
<p class="text-muted">등록된 클라이언트 애플리케이션이 없습니다.</p>
{% endfor %}
</div>
<a href="{% url 'custom_account:OAuth_register_client' %}" class="btn btn-outline-primary">
새 어플리케이션 등록.</a>
{% endblock %}
|
|
등록, 수정 탬플릿. | {% extends 'custom_account/section.html' %}
{% block content %}
<h2>{{ is_edit|yesno:"클라이언트 수정,클라이언트 등록" }}</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary">
{{ is_edit|yesno:"수정,등록" }}
</button>
</form>
{% endblock %}
|
비밀키 갱신 기능 구현 필요.