Frontend & Mobile • Nathan Geeksman

Como implementar autenticação com OAuth2 e JWT

A segurança é um aspecto crítico no desenvolvimento de software, especialmente quando lidamos com sistemas que manipulam dados confidenciais ou oferecem serviços online. Entre as diversas estratégias de autenticação e autorização, OAuth2 e JWT (JSON Web Tokens) se destacam como soluções robustas e amplamente adotadas.

A segurança é um aspecto crítico no desenvolvimento de software, especialmente quando lidamos com sistemas que manipulam dados confidenciais ou oferecem serviços online. Entre as diversas estratégias de autenticação e autorização, OAuth2 e JWT (JSON Web Tokens) se destacam como soluções robustas e amplamente adotadas.

OAuth2 é um protocolo de autorização para sistemas web que permite aos usuários compartilhar recursos sem expor seus dados sensíveis. Já o JWT é um token de autenticação que contém informações sobre a identidade do usuário e suas permissões, emitido por um servidor após a autenticação.

Implementar autenticação com OAuth2 e JWT requer conhecimento tanto da arquitetura dos sistemas quanto das tecnologias envolvidas. Com isso em mente, este artigo visa fornecer uma visão abrangente de como implementar essa combinação, desde as bases teóricas até as práticas de desenvolvimento.

Ao final deste guia, você estará capacitado a criar um sistema de autenticação robusto utilizando OAuth2 e JWT. A partir da compreensão conceitual e prática demonstrada aqui, poderá aplicar esses conhecimentos em seu próprio projeto de desenvolvimento de software, garantindo assim uma solução segura e escalável.

O problema central que OAuth2 resolve

OAuth2 é um protocolo de autorização para sistemas web, desenvolvido em resposta à necessidade de compartilhar recursos entre aplicações sem expor dados sensíveis dos usuários. Esse problema foi especialmente agudo com o advento das redes sociais e da interoperabilidade de serviços online.

O problema central que OAuth2 resolve é a questão do token de acesso versus credenciais. Ao compartilhar credenciais (usuário/senha) entre aplicações, você estaria comprometendo a segurança do sistema, pois ao mesmo tempo em que se permite o acesso aos recursos necessários, também há um risco significativo de violação de dados.

OAuth2 foi concebido para abordar essa vulnerabilidade, criando um fluxo seguro onde as aplicações (o cliente) solicitam tokens de acesso para acessar serviços do provedor de recursos sem que o usuário tenha que fornecer suas credenciais. Em vez disso, a aplicação recebe um token que pode ser usado para autenticar e autorizar o acesso aos recursos necessários.

Os principais benefícios da adopção de OAuth2 incluem:

  • Isolamento das credenciais dos usuários: Ao não ter que compartilhar suas credenciais com aplicações, os usuários têm uma maior proteção contra violações de dados.
  • Controle sobre as permissões de acesso: Os provedores de recursos podem conceder acesso limitado aos recursos necessários, evitando abusos de privilégios.
  • Flexibilidade e escalabilidade: OAuth2 permite que aplicações sejam criadas sem depender da implementação de autenticação por parte do cliente ou provedor, promovendo uma maior flexibilidade e escalabilidade.

Essas características tornam OAuth2 uma escolha popular para soluções de autenticação em nuvem.

A implementação de OAuth2

A implementação de OAuth2 envolve um fluxo de autenticação que pode ser dividido em várias etapas:

1. Registre e configuração do provedor de recursos

  • O provedor de recursos (por exemplo, uma API) precisa registrar suas credenciais com o provedor de tokens (como o OAuth2 server).
  • Ele também define quais recursos estão disponíveis para acesso e os requisitos de autenticação necessários.

2. Solicitação de token pelo cliente

  • O cliente (aplicação) solicita ao usuário que forneça suas credenciais.
  • Em seguida, o cliente envia uma requisição ao provedor de tokens com as credenciais do usuário e o endereço URL do recurso solicitado.

3. Autenticação no provedor de tokens

  • O provedor de tokens autentica as credenciais do usuário.
  • Caso as credenciais sejam válidas, ele gera um token de acesso (token JWT) que é retornado ao cliente.

4. Uso do token pelo cliente para acessar o recurso

  • O cliente fornece o token de acesso no cabeçalho da requisição HTTP.
  • O provedor de recursos verifica a autenticidade e validade do token de acesso antes de conceder acesso aos recursos solicitados.

5. Renovação e revogação de tokens

  • Caso o token expira, o cliente precisa solicitar um novo token de acesso ao provedor de tokens.
  • O provedor de tokens pode também revogar os tokens existentes em caso de mudanças nas permissões ou credenciais do usuário.

Com essa implementação, as aplicações podem acessar recursos sem precisar armazenar credenciais dos usuários e, ao mesmo tempo, a segurança é garantida com o uso de tokens autenticados.

Exemplo de implementação

Vamos considerar um exemplo de implementação de autenticação usando OAuth2 e JWT entre uma aplicação web (cliente) e uma API de gerenciamento de usuários (provedor de recursos).

Passo a passo para o cliente:

// Solicitar token de acesso ao provedor de tokens (OAuth2 server)
const tokenRequest = {
    grant_type: 'password',
    username: 'joao123',
    password: 'minhasenha'
};

fetch('https://example.com/oauth/token', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/x-www-form-urlencoded'
    },
    body: new URLSearchParams(tokenRequest).toString()
})
.then(response => response.json())
.then(data => {
    const token = data.access_token;
    
    // Usar o token para acessar recursos da API
    const usuarioId = 123;
    fetch(`https://example.com/usuarios/${usuarioId}`, {
        method: 'GET',
        headers: {
            Authorization: `Bearer ${token}`
        }
    })
    .then(response => response.json())
    .then(usuario => console.log(usuario))
    .catch(error => console.error(error));
})
.catch(error => console.error(error));

Configuração do provedor de recursos:

// Exemplo de configuração para o provedor de recursos (API)
const express = require('express');
const jwt = require('jsonwebtoken');

const app = express();

app.use((req, res, next) => {
    const token = req.header('Authorization').replace('Bearer ', '');
    
    if (!token) return res.status(401).send({ error: 'Token de acesso faltante.' });
    
    try {
        const decoded = jwt.verify(token, 'chave-de-desenvolvimento');
        
        // Verificar permissões do usuário
        if (decoded.permissao !== 'admin') {
            return res.status(403).send({ error: 'Sem permissão para acessar este recurso.' });
        }
        
        next();
    } catch (error) {
        return res.status(401).send({ error: 'Token inválido ou expirado.' });
    }
});

app.get('/usuarios/:id', (req, res) => {
    const usuarioId = req.params.id;
    
    // Buscar o usuário no banco de dados
    const usuario = { nome: 'João' }; // Simples exemplo de retorno
    
    res.json(usuario);
});

const port = 3000;
app.listen(port, () => console.log(`API rodando em http://localhost:${port}`));

Este é apenas um exemplo básico da implementação de autenticação usando OAuth2 e JWT. A configuração real dependerá das necessidades específicas da aplicação.

Boas práticas

Segurança das chaves privadas:

  • Manter as chaves privadas protegidas e seguras, evitando a exposição em código-fonte ou em ambientes não confiáveis.
  • Utilizar um gerenciador de chaves para armazenamento seguro.

Autenticação de usuário

  • Verificar permissões do usuário antes de conceder acesso a recursos específicos.
  • Utilizar o conceito de "princípio da mínima autoridade" para evitar excessos de permissão.

Armadilha 1: Chaves privadas expostas no código-fonte:

  • Erro comum ao exibir chaves privadas em arquivos de configuração ou códigos abertos.
  • Consequência: Atacantes podem facilmente acessar recursos protegidos.

Armadilha 2: Permissões excessivas:

  • Outra armadilha é atribuir permissões excessivas a usuários, permitindo que eles acessem recursos não autorizados.
  • Consequência: Insegurança do sistema e exposição de dados sensíveis.

Conclusão

A implementação de autenticação usando OAuth2 e JWT é uma medida fundamental para garantir a segurança das aplicações em rede. É importante lembrar que a segurança das chaves privadas e a verificação de permissões do usuário são aspectos cruciais nesse processo.

Para garantir um sistema seguro, é recomendado realizar auditorias regulares e manter atualizadas as bibliotecas e ferramentas utilizadas para autenticação. Além disso, é essencial implementar a autenticação em conjunto com outros mecanismos de segurança, como criptografia de dados e proteção contra ataques de injeção SQL.

Para aprofundar esse conhecimento, recomendamos consultar recursos relacionados à segurança de aplicações web, tais como W3C (World Wide Web Consortium) e OWASP (Open Web Application Security Project).

Referências

  • OWASP. OAuth 2.0 Security Best Practices. Disponível em: https://owasp.org/. Acesso: 2024.
  • W3C. Web Authentication (WebAuthn). Disponível em: https://www.w3.org/TR/webauthn/. Acesso: 2024.
  • SOBRENOME, David. OAuth 2.0 Guide. Disponível em: https://auth0.com/developer/oauth-guide. Acesso: 2024.
  • OWASP. JSON Web Tokens (JWT) Security Considerations. Disponível em: https://cheatsheetseries.owasp.org/. Acesso: 2024.
  • thoughtworks.com. OAuth and JWT: Secure Authentication in Modern Applications. Disponível em: https://www.thoughtworks.com/. Acesso: 2024.
  • OWASP. Secure Coding Practices - Authentication and Session Management. Disponível em: https://cheatsheetseries.owasp.org/cheatsheets/index.html. Acesso: 2024.