This repository contains an example implementation of registration, login, application login, and application registration processes using Django and OAuth 2.0.
Writed by: Osvaldo Calombe
Why: I still love and want more than a friendship with Will
- Introdução
- Instalação
- Configuração
- Estrutura do Projeto
- Processo de Registro
- Processo de Login
- Login de Aplicação
- Registro de Aplicação
- Testando o Código
- Contribuição
Este projeto demonstra como configurar um sistema de autenticação e autorização usando Django e OAuth 2.0. Ele cobre os processos de registro e login de usuário, bem como login e registro de aplicação.
-
Adicione
oauth2_provider
ao seuINSTALLED_APPS
nosettings.py
.# settings.py INSTALLED_APPS = [ # Outros apps 'oauth2_provider', ]
-
Configure as URLs do OAuth 2.0 no seu projeto:
# urls.py from django.urls import path, include urlpatterns = [ # Outras URLs path('o/', include('oauth2_provider.urls', namespace='oauth2_provider')), ]
Estrutura sugerida para o projeto Django:
myproject/
manage.py
myproject/
__init__.py
settings.py
urls.py
wsgi.py
myapp/
__init__.py
admin.py
apps.py
forms.py
models.py
tests.py
views.py
templates/
register.html
login.html
verification_failed.html
register_application.html
application_detail.html
utils.py
-
Criação do Formulário de Registro -
myapp/forms.py
:from django import forms from django.contrib.auth.models import User class RegistrationForm(forms.ModelForm): password = forms.CharField(widget=forms.PasswordInput) confirm_password = forms.CharField(widget=forms.PasswordInput) class Meta: model = User fields = ['username', 'email', 'password'] def clean(self): cleaned_data = super().clean() password = cleaned_data.get("password") confirm_password = cleaned_data.get("confirm_password") if password != confirm_password: raise forms.ValidationError("As senhas não correspondem.")
-
View para Registro -
myapp/views.py
:from django.shortcuts import render, redirect from django.contrib.auth.models import User from django.contrib.auth.hashers import make_password from .forms import RegistrationForm from .models import EmailVerificationToken from .utils import send_verification_email def register(request): if request.method == 'POST': form = RegistrationForm(request.POST) if form.is_valid(): user = form.save(commit=False) user.password = make_password(form.cleaned_data['password']) user.is_active = False # Desativa a conta até que o e-mail seja verificado user.save() # Gera um token de verificação e envia e-mail token = EmailVerificationToken.objects.create(user=user) send_verification_email(user.email, token.token) return redirect('registration_success') else: form = RegistrationForm() return render(request, 'register.html', {'form': form})
-
Envio de E-mail de Verificação -
myapp/utils.py
:from django.core.mail import send_mail from django.conf import settings def send_verification_email(email, token): subject = "Verifique seu e-mail" message = f"Por favor, clique no link para verificar seu e-mail: http://seusite.com/verify-email/?token={token}" from_email = settings.DEFAULT_FROM_EMAIL recipient_list = [email] send_mail(subject, message, from_email, recipient_list)
-
Modelo para o Token de Verificação de E-mail -
myapp/models.py
:from django.db import models from django.contrib.auth.models import User class EmailVerificationToken(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) token = models.CharField(max_length=50, unique=True) created_at = models.DateTimeField(auto_now_add=True)
-
View para Verificação de E-mail -
myapp/views.py
:from django.shortcuts import render, redirect from .models import EmailVerificationToken from django.contrib.auth.models import User def verify_email(request): token = request.GET.get('token') try: verification_token = EmailVerificationToken.objects.get(token=token) user = verification_token.user user.is_active = True user.save() verification_token.delete() return redirect('login') except EmailVerificationToken.DoesNotExist: return render(request, 'verification_failed.html')
-
Templates:
myapp/templates/register.html
myapp/templates/verification_failed.html
-
Criação do Formulário de Login -
myapp/forms.py
:from django import forms class LoginForm(forms.Form): username = forms.CharField() password = forms.CharField(widget=forms.PasswordInput)
-
View para Login -
myapp/views.py
:from django.shortcuts import render, redirect from django.contrib.auth import authenticate, login from .forms import LoginForm def login_view(request): if request.method == 'POST': form = LoginForm(request.POST) if form.is_valid(): username = form.cleaned_data['username'] password = form.cleaned_data['password'] user = authenticate(request, username=username, password=password) if user is not None: if user.is_active: login(request, user) return redirect('home') else: return render(request, 'login.html', {'form': form, 'error': 'Conta não verificada.'}) else: return render(request, 'login.html', {'form': form, 'error': 'Credenciais inválidas.'}) else: form = LoginForm() return render(request, 'login.html', {'form': form})
-
Template:
myapp/templates/login.html
-
Configuração do Cliente OAuth 2.0 -
settings.py
:INSTALLED_APPS = [ # Outros apps 'oauth2_provider', ]
-
Configuração das URLs -
urls.py
:from django.urls import path, include urlpatterns = [ # Outras URLs path('o/', include('oauth2_provider.urls', namespace='oauth2_provider')), ]
-
View para Iniciar o Login de Aplicação -
myapp/views.py
:from django.shortcuts import redirect def initiate_app_login(request): client_id = 'SEU_CLIENT_ID' redirect_uri = 'SUA_REDIRECT_URI' response_type = 'code' scope = 'read write' state = 'algum_estado_unico' authorization_url = f"https://idp.com/o/authorize/?client_id={client_id}&redirect_uri={redirect_uri}&response_type={response_type}&scope={scope}&state={state}" return redirect(authorization_url)
-
View para Lidar com o Callback do IDP -
myapp/views.py
:import requests from django.conf import settings def handle_idp_callback(request): authorization_code = request.GET.get('code') state = request.GET.get('state') token_url = 'https://idp.com/o/token/' client_id = 'SEU_CLIENT_ID' client_secret = 'SEU_CLIENT_SECRET' redirect_uri = 'SUA_REDIRECT_URI' grant_type = 'authorization_code' response = requests.post(token_url, data={ 'code': authorization_code, 'client_id': client
_id, 'client_secret': client_secret, 'redirect_uri': redirect_uri, 'grant_type': grant_type })
if response.status_code == 200:
tokens = response.json()
access_token = tokens['access_token']
refresh_token = tokens['refresh_token']
# Armazene os tokens de forma segura
store_tokens(access_token, refresh_token)
return redirect('home')
else:
return render(request, 'callback_failed.html')
```
-
Função para Armazenar Tokens -
myapp/utils.py
:def store_tokens(access_token, refresh_token): # Implementar armazenamento seguro de tokens pass
-
Template:
myapp/templates/callback_failed.html
-
Criação do Modelo de Aplicação -
myapp/models.py
:from django.db import models from django.contrib.auth.models import User class Application(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) name = models.CharField(max_length=255) client_id = models.CharField(max_length=255, unique=True) client_secret = models.CharField(max_length=255, unique=True) redirect_uri = models.URLField() created_at = models.DateTimeField(auto_now_add=True)
-
Criação do Formulário de Registro de Aplicação -
myapp/forms.py
:from django import forms from .models import Application class ApplicationRegistrationForm(forms.ModelForm): class Meta: model = Application fields = ['name', 'redirect_uri']
-
View para Registrar a Aplicação -
myapp/views.py
:from django.shortcuts import render, redirect from .forms import ApplicationRegistrationForm from .models import Application import secrets def register_application(request): if request.method == 'POST': form = ApplicationRegistrationForm(request.POST) if form.is_valid(): application = form.save(commit=False) application.user = request.user application.client_id = secrets.token_urlsafe(16) application.client_secret = secrets.token_urlsafe(32) application.save() return redirect('application_detail', application.id) else: form = ApplicationRegistrationForm() return render(request, 'register_application.html', {'form': form})
-
View para Detalhar a Aplicação -
myapp/views.py
:from django.shortcuts import render, get_object_or_404 from .models import Application def application_detail(request, application_id): application = get_object_or_404(Application, id=application_id) return render(request, 'application_detail.html', {'application': application})
-
Templates:
myapp/templates/register_application.html
myapp/templates/application_detail.html
-
Crie um superusuário para acessar o admin do Django:
python manage.py createsuperuser
-
Execute o servidor de desenvolvimento:
python manage.py runserver
-
Abra seu navegador e vá para
http://localhost:8000/admin
para acessar o admin do Django. -
Teste o registro de usuário:
- Vá para a URL de registro de usuário e preencha o formulário.
- Verifique se o e-mail de verificação foi enviado e clique no link de verificação.
-
Teste o login de usuário:
- Vá para a URL de login de usuário e faça login com as credenciais registradas.
-
Teste o registro de aplicação:
- Vá para a URL de registro de aplicação e preencha o formulário.
- Verifique se a aplicação foi registrada corretamente.
-
Teste o login de aplicação:
- Inicie o login de aplicação e autorize a aplicação na IDP.
- Faça um fork do projeto
- Crie uma branch para sua feature (
git checkout -b feature/fooBar
) - Faça commit das suas mudanças (
git commit -am 'Add some fooBar'
) - Faça push para a branch (
git push origin feature/fooBar
) - Crie um novo Pull Request