Autenticação JWT com DRF

Pedro Fonseca
4 min readJan 28, 2023

--

De todas as features importantes que devem existir em uma aplicação, a autenticação é uma das mais importantes. É claro, estamos falando de aplicações que envolvem a utilização de usuários dentro das diversas regras de negócio que existirão na aplicação.

Existem inúmeras formas de nos autenticar com Django, uma delas é a por sessão, que por padrão já é utilizada. Entretanto, para a grande maioria dos sistemas desenvolvidos uma autenticação por sessão não seria a melhor recomendada. Para isso, temos diversas formas de nos autenticar, uma delas é por JSON Web Tokens (JWT), na qual usaremos nesse artigo.

Eu também gravei um vídeo, narrando e trazendo com mais detalhes a criação de uma aplicação usando a autenticação mencionada. Fiquem à vontade para escolher a melhor forma de apreender.

crucx

Setup Environment

Antes de tudo, precisamos criar nosso ambiente virtual, para isso, podemos utilizar virtualenv, pipenv, poetry ou outras ferramentas. Se você ainda não tem o virtualenv instalado em sua máquina, faça a instalação usando

pip install virtualenv

criando o ambiente virtual

python3 -m venv [nome_do_seu_ambiente]

ou

virtualenv [nome_do_seu_ambiente]

Finalmente, para ativar o nosso ambiente

source [nome_do_seu_ambiente]/bin/activate

Install django

Com o nosso ambiente ativado, iremos começar a construir o nosso projeto. Necessitaremos adicionar as seguintes dependências

pip install django djangorestframework djangorestframework-simplejwt 

Estarei usando as seguintes versões

Django==4.1.5
djangorestframework==3.14.0
djangorestframework-simplejwt==5.2.2
PyJWT==2.6.0

Concluindo a instalação das bibliotecas, precisaremos criar o projeto, onde teremos todas as configurações da nossa aplicação e também a nossa aplicação de autenticação.

django-admin startproject core . 

e

django-admin startapp profile

Com o projeto e nosso app de autenticação criados, poderemos adicionar o rest_framework, simplejwt e o app profile dentro das configurações do nosso projeto.

 INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'profile',
'rest_framework_simplejwt',
]

App User

Temos dois caminhos, criar um modelo específico que determina os usuários da nossa aplicação ou usar o próprio modelo que o django nos fornece, para este último podemos importar com o seguinte caminho:

from django.contrib.auth.models import User

Sendo bem franco, para uma aplicação mínima, não vejo problema em usar a presente abordagem, entretanto, se você pensa em escalar sua aplicação, ou customizar seu usuário ao longo do tempo, será melhor fazer um override nesse User.

from django.db import models
from django.contrib.auth.models import AbstractUser #1


class Profile(AbstractUser):
class GenderChoices(models.IntegerChoices):
MAN = 1, 'Man'
WOMAN = 2, 'Woman'

full_name = models.CharField(max_length=100, blank=True)
cpf = models.CharField(max_length=11, blank=True)
gender = models.IntegerField(default=GenderChoices.MAN, choices=GenderChoices.choices)
email = models.EmailField(max_length=254, unique=True) #2

USERNAME_FIELD = 'email' # 3
REQUIRED_FIELDS = [] # 4
  1. O AbstractUser como o próprio nome diz é um modelo abstrato que o User padrão usa, herdando os atributos que o mesmo possui. Também podemos adicionar novos campos, como assim fazemos com o full_name, cpf, gender e email.
  2. Já temos esse campo email no AbstractUser, entretanto, como esse será o nosso campo para fazer login, necessitamos defini-lo como um campo único. Ou seja, não podemos ter dois emails iguais.
  3. USERNAME_FIELD define o campo que iremos usar para fazer o login na nossa api. Por padrão é usado o próprio username do AbstractUser, porém, a grande maioria das aplicações hoje em dia continua usando o email.
  4. Precisa estar junto do USERNAME_FIELD

Create migrations

Para consolidar tudo o que fizemos até agora, criaremos o arquivo de migração e criar o modelo de usuário no nosso banco de dados. Antes de fazermos isso, precisamos definir qual o nosso novo usuário .

core/settings.py

AUTH_USER_MODEL = 'profile.Profile'

profile: representa o nome do app que você criou e o modelo do seu usuário

Necessitamos fazer essa alteração porque por padrão o django marca o User como modelo correspondente ao usuário. Se investigarmos essa mesma variável no projeto do django veremos

django/conf/global_settings.py

AUTH_USER_MODEL = "auth.User"
AUTHENTICATION_BACKENDS = ["django.contrib.auth.backends.ModelBackend"]

Por isso, se você optou em fazer o override do seu usuário, não se esqueça de mudar. Com as devidas configurações feitas, podemos criar nossa migração.

python manage.py makemigrations

Se tivermos sucesso, receberemos a seguinte mensagem no terminal

Migrations for 'profile':
profile/migrations/0001_initial.py

- Create model Profile

Com o arquivo de migração criado, podemos enfim criar o nosso usuário dentro do banco de dados com o python manage.py migrate

Create user

python manage.py shell

from profile.models import Profile
profile = Profile.objects.create(email='peidrao@email.com')
profile.set_password('123')
profile.save()

Agora temos o nosso primeiro usuário e usaremos ele para fazer o login.

Configure JWT

E importante definir nas nossas configurações a forma que o django se autenticará, por padrão a autenticação e por sessão, como foi falado no inicio.

REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
)
}

Para concluir, vamos adicionar a url onde existe o endpoint para autenticação.

core/urls.py

from django.contrib import admin
from django.urls import path
from rest_framework_simplejwt.views import TokenObtainPairView

urlpatterns = [
path('admin/', admin.site.urls),
path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
]

Testing

curl \
-X POST \
-H "Content-Type: application/json" \
-d '{"email": "peidrao@email.com", "password": "123"}' \
http://localhost:8000/api/token/

Repositório: https://gitlab.com/peidrao/django-jwt-auth

Se ficou alguma duvida ou questionamento, fique a vontade para comentar. Criticas também, são sempre bem vidas.

--

--

Pedro Fonseca

Um iniciante em desenvolvimento web que ama o que faz. “Prefiro o Paraíso”, São Felipe Néri — https://github.com/peidrao/