Autenticação com JWT no Django Rest Framework

No desenvolvimento de APIs Rests a autenticação é um fator obrigatório. Nos dias de hoje existem inúmeros métodos de autenticação, mas sem dúvidas um dos mais utilizados é o JWT (Json Web Token), que através da utilização de tokens possibilita uma forma fácil e eficiente de autenticação em suas aplicações web.

JSON Web Tokens

Em resumo, JWT é uma string de caracteres codificados que, caso cliente e servidor estejam sob HTTPS, permite que somente o servidor que conhece o ‘segredo’ possa ler o conteúdo do token e assim confirmar a autenticidade do cliente.

Ou seja, quando um usuário se autentica no sistema (com usuário e senha), o servidor gera um token com data de expiração pra ele. Durante as requisições seguintes do cliente, o JWT é enviado no cabeçalho da requisição e, caso esteja válido, a API irá permitir acesso aos recursos solicitados sem a necessidade de se autenticar novamente.

O diagrama abaixo mostra este fluxo, passo-a-passo:

O Django Rest Framework dispõe de inúmeras bibliotecas para prover o mecanismo do JWT, a que utilizarei aqui será a django-rest-framework-jwt que é a padrão utilizada pela comunidade.

Para instalar a biblioteca, execute o comando abaixo:

$ pip install djangorestframework-jwt

Feito isso, adicione as configurações abaixo no settings.py:

No DEFAULT_PERMISSION_CLASSES indicamos que de forma global todos os endpoints serão autenticados. E no DEFAULT_AUTHENTICATION_CLASSES, indicamos os tipos de autenticação suportados por nossa API, ou seja, JWT, sessão e autenticação básica.

Criar Token

Feita essas configurações, no nosso urls.py principal, importamos a view obtain_jwt_token disponibilizada pela biblioteca que nos permite criar nosso token a partir de um usuário presente no sistema.

Feito isso, você já pode testar a criação do token. Com um usuário previamente criado no sistema, execute no seu terminal o comando abaixo:

$ curl -X POST -d "username=username&password=password" http://localhost:8000/login/

O sistema irá te retornar o token para acesso ao sistema.

Agora, para acessar as APIs protegidas, você deve incluir o Authorization: JWT <your_token> cabeçalho.

$ curl -H "Authorization: JWT <your_token>" http://localhost:8000/protected-url/

Atualizar Token

Os tokens expiram, e para atualizar um token expirado, a biblioteca disponibiliza mais uma view chamada refresh_jwt_token, para adicioná-la ao sistema basta adicionar o código no urls.py:

$ curl -X POST -H "Content-Type: application/json" -d '{"token":"<EXISTING_TOKEN>"}' http://localhost:8000/refresh-token/

Observe que apenas tokens expirados serão aceitos.

Verificação de Token

Em algumas arquiteturas de microserviços, a autenticação é feita por um único serviço. Outros serviços delegam a responsabilidade de confirmar que um usuário está conectado a esse serviço de autenticação. Isso geralmente significa que um serviço passará um JWT recebido do usuário para o serviço de autenticação e aguardará uma confirmação de que o JWT é válido antes de retornar recursos protegidos ao usuário.

Esta configuração é suportada neste pacote usando um endpoint de verificação. Adicione o seguinte padrão de URL:

Configurações Adicionais

Existem algumas configurações adicionais que você pode sobrescrever como você faria com a própria estrutura REST do Django. Aqui estão todos os padrões disponíveis.

Para um detalhamento completo de cada opção acesse: http://getblimp.github.io/django-rest-framework-jwt/#additional-settings

Criando Token Manualmente

A biblioteca disponibiliza uma forma simples de criar token manualmente (Bem útil na hora de fazer testes a propósito). No modo interativo do python execute:

>>> from rest_framework_jwt.settings import api_settings
>>> jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
>>> jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

Importe um usuário presente no banco de dados:

>>> from django.contrib.auth.models import User
>>> user = User.objects.first()

E por fim gere um token para o mesmo:

>>> payload = jwt_payload_handler(user)
>>> token = jwt_encode_handler(payload)

Conclusão

Como visto aqui, utilizar JWT para autenticação em APIs é uma das formas mais seguras e práticas hoje em dia. O django como era de se esperar, já dispõe de todo o ferramental para trabalhar com isso, cabe a você escolhe a melhor opção que te atende, mas no geral as coisas mostradas aqui funcionarão em praticamente todos os cenários, até a próxima.

❤ Gostou? Vamos espalhá-lo — curte e compartilha aí o/