Por que eu devo ler este artigo:Este artigo apresenta um novo padrão, denominado JSON Web Token (JWT), para a criação de tokens capazes de transportar informações de uma forma compacta e confiável. Além disso, aborda também uma maneira de utilizar esses tokens como uma alternativa stateless, de forma semelhante a utilizada por gigantes como Google e Microsoft, aos processos existentes de autenticação para APIs RESTful. No artigo, será analisada a implementação de uma API RESTful com segurança via JWT, baseada no framework Spring Security, para exemplificar todos os conceitos.

Segurança é um requisito fundamental em grande parte dos sistemas atuais, pois é necessário garantir que cada usuário possua acesso somente às funcionalidades que se adequem às suas competências, visando manter a integridade do sistema e das informações armazenadas.

Para aplicações web, a utilização da forma tradicional de segurança, que mantém, após uma autenticação, todas as autorizações de um usuário em sua sessão, geralmente é adequada. Serviços RESTful, por outro lado, são, por definição, stateless. Isso elimina essa forma como opção e nos obriga a buscar alternativas. Atualmente, duas das alternativas mais conhecidas são:

  • HTTP Basic Authentication(BA) – Nesse tipo de autenticação, as credencias de acesso (username/password) são enviadas, no header Authorization, em todas as requisições. Elas devem seguir o formato “username:password”, serem codificadas com base64 e precedidas por “Basic ”. Por exemplo: para o username “Alladin” com password “open sesame”, o header seria "Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==". Deve-se notar que, por conta de suas características, o sistema cliente deve guardar as credenciais do usuário para evitar solicitá-las em cada requisição, o que pode representar uma nova vulnerabilidade;
    Nota: O padrão para o header Authorization foi apresentado pela W3C na definição do HTTP 1.0 (RFC 1945) e segue o formato "Authorization: <type> <credentials>", onde <type> indica o tipo de autenticação.
  • Token Based Authentication – Nesse tipo de autenticação, o cliente realiza um login passando as credenciais do usuário e recebe um token, que possui uma assinatura que inviabiliza sua adulteração. As requisições subsequentes adicionam o token a um header e as informações contidas nele garantem acesso aos serviços desejados.

Neste artigo, focaremos em um tipo específico de Token Based Authentication, que utiliza um novo padrão de token, denominado JSON Web Token (JWT). Além de conhecer esse novo tipo de token, veremos como utilizá-lo em conjunto com o framework Spring Security para proteger uma API RESTful.

JWT

JSON Web Token, ou JWT, é um padrão aberto (RFC 7519), de uso geral, que possibilita a troca segura de informações entre partes, na forma de objetos JSON. Como vantagens, o JWT possui o fato de ser mais compacto que alternativas baseadas em XML e a capacidade de ser autocontido, ou seja, possuir todas as informações relevantes sobre um assunto, dispensando consultas adicionais a um eventual banco de dados para recuperar os dados.

Um JWT é composto por três partes: header, payload e signature (assinatura); todas codificadas com base64 (vide BOX 1) e separadas por pontos (.). A seguir, analisaremos cada uma delas em detalhes.

BOX 1. Base64
Base64 é um método para codificação de dados para transferência na internet definido pelo padrão RFC 4648, que, como seu nome indica, utiliza apenas 64 caracteres ([A-Z], [a-z],[0-9], "/" e "+").

O método consiste em, primeiramente, transformar o texto original em um número binário. Essa transformação leva em consideração a codificação original do texto (ASCII). Após isso, o número binário resultante é convertido, por meio de uma tabela, para base64. O texto em ASCII "teste", por exemplo, corresponde ao número binário "01110100 01100101 01110011 01110100 01100101", que, por sua vez, pode ser codificado em base64 como "dGVzdGU=".

Header

O header (cabeçalho) de um JWT é um JSON e, geralmente, contém o algoritmo de hashing utilizado na assinatura e o tipo de token (JWT).

A seguir é apresentado um exemplo de header não codificado:

  {
    "alg": "HS256",
    "typ": "JWT"
  }

Mesmo header codificado com base64:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

Payload

O payload (ou corpo) de um JWT é também um JSON e contém as informações relevantes ao assunto, denominadas claims, na forma de pares chave/valor.

Existem três tipos de claims, a saber:

  • Registradas – Um conjunto de claims cujo uso não é obrigatório, mas recomendado. São elas: iss (Issuer), identificador de quem gerou o JWT; sub (Subject), identificador único que representa o assunto do JWT; aud (Audience), identifica o recipiente do JWT; exp (Expiration Time), data/hora de expiração do JWT; nbf (Not Before), data/hora de ativação do JWT, a partir da qual ele será válido; iat (Issued At), data/hora de geração do JWT; e jti (JWT Id), identificador único do JWT. Aqui, é interessante notar que, para manter o token compacto, os nomes das claims possuem apenas três caracteres;
  • Públicas Claims criadas por usuários de JWTs. Para evitar colisões, os nomes dessas claims devem ser registrados na IANA ou definidos como URIs que contenham um namespace resistente a colisão (como um nome de domínio, por exemplo);
    Nota: Uma colisão ocorre quando um mesmo nome pode possuir diferentes significados/usos. Isso gera problemas de comunicação, fazendo com que informações sejam interpretadas incorretamente quando transferidas para diferentes sistemas ou módulos.
  • Privadas Claims criadas com nomes não registrados na IANA (vide BOX 2) e não resistentes a colisão. Devem ser utilizadas com cuidado, em comum acordo entre as partes envolvidas (consumidores e produtores).
BOX 2. IANA
A IANA (Internet Assigned Numbers Authority) é uma organização privada, sem fins lucrativos, responsável pela atribuição de nomes e números globalmente únicos, utilizados em padrões técnicos que regem a Internet. Suas atividades podem ser agrupadas em três categorias: nomes de domínio, recursos numéricos e atribuições de protocolos.

Um exemplo de payload, contendo claims registradas e privadas, é apresentado na Listagem 1.

Listagem 1. Exemplo de payload com claims registradas e privadas.

  {
    "adm": "true",
    "app": "Postal",
    "iss": "br.com.javamagazine",
    "sub": "Administrator",
    "exp": 1477781160
  }
Nota: É importante mencionar que, geralmente, as informações contidas no payload não são criptografadas. Nada impede, no entanto, de se proteger informações sigilosas. Isso, contudo, pode aumentar a quantidade de processamento necessária p ...

Quer ler esse conteúdo completo? Seja um assinante e descubra as vantagens.
  • 473 Cursos
  • 10K Artigos
  • 100 DevCasts
  • 30 Projetos
  • 80 Guias
Tenha acesso completo