OAuth em aplicações SPA / Mobile (PKCE extension)
Tags: security, webdev, mobile, oauth
Published: 2024-07-08 03:25:46

Em diversas implementações OAuth / OpenID Connect nos deparamos com o uso de clientes confidenciais (clientes registrados que possuem um par `client_id` e `client_secret`), porém, em aplicações client-side, como SPAs e apps mobile, é impossível garantir a confidencialidade do `client_secret`. Portanto, torna-se necessário um meio seguro para obter o access token através de algum fluxo do OAuth.

Para resolver esse problema de clientes públicos, entra em ação a [RFC 7636 Proof Key for Code Exchange by OAuth Public Clients](https://datatracker.ietf.org/doc/html/rfc7636), que adiciona uma extensão ao fluxo do authorization code, tornando a comunicação mais segura. É dessa RFC que quero aprofundar um pouco neste post.

## Qual problema o PKCE tenta mitigar?

Primeiramente, lê-se piquici (pixy), a sigla PKCE, haha.

O PKCE mitiga um conhecido ataque do tipo `man in the midle` , aplicado principalmente em aplicações mobile, segue um diagrama abaixo demostrando esse tipo de ataque.


![authz-code-attack-mitm](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wu5cstarlt22kj4fad66.png)


Explicando brevemente:

1. A aplicação cliente inicia o fluxo `authorization code` utilizando um browser
2. Browser faz o request para o endpoint /authorize do authorization server
3. Browser recebe de volta a resposta do servidor com o `authorization code` (code)
4. Um app malicioso instalado no dispositivo cliente intercepta essa resposta que seria encaminhada do browser para a aplicação cliente (normalmente utilizando um custom URI scheme)
5. O app malicioso, em posse do `authorization code` , completa o fluxo trocando o code pelo access token e tendo acesso aos recursos protegidos autorizados pelo usuário.

Desta forma, um app malicioso que tenha infectado o dispositivo do cliente pode obter acesso a um access token interceptando code da resposta do request para o endpoint /authorize.

Um ponto importante a se destacar é que devido a natureza dos clientes públicos de não conseguirem guardar de maneira segura suas credenciais, o fluxo do authorization code permite que estes obtenham o access token somente através da posse do code e do cliente_id da aplicação cliente. Este tipo de ataque se tornaria bem menos eficaz caso fosse possível autenticar a aplicação cliente através de seu client_secret.

### OBS sobre custom URI schemes

Para quem não é da área mobile ou front-end, custom URI schemes é uma forma de criar um protocolo custom para sua aplicação, assim como http:// ou https://, algo como myapp://.

Assim, quando um usuário clicar ou for redirecionado para uma URL que utilize este protocolo, sua aplicação será inicializada com os parâmetros associados a URL.

Para saber mais sobre indico este ótimo e breve artigo, [Launching Applications from the Web: The Power of Custom URL Schemes](https://alirezahamid.medium.com/launching-applications-from-the-web-the-power-of-custom-url-schemes-4d9fa3e6cdbe).

## Como o PKCE mitiga este tipo de ataque?

O PKCE mitiga este tipo de ataque introduzindo alguns parâmetros adicional nos requests envolvidos no fluxo do authorization code.

No diagrama abaixo ilustramos essa nova dinâmica:


![pkce-athz-code-flow](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nuwzklpf93idtb0jmo6m.png)


Explicando o novo fluxo:

1. Aplicação cliente cria um `code_verifier`, uma string aleatória de alta entropia criptográfica
2. Aplicação cliente deriva o `code_challenge` do code_verifier aplicando algum algoritmo como SHA256, sendo este algoritmo denomiado `code_challenge_method`
3. Aplicação cliente encaminha o `code_challenge` e o `code_challenge_method` , junto dos demais parâmetros, no request para o /authorize
4. O authorization server guarda o code_challenge e o code_challenge_method, associando-os ao authorization code emitido na resposta do /authorize
5. No request para o /token a aplicação cliente envia junto do code o `code_verifier` gerado no passo 1, além dos demais parâmetros necessários
6. Authorization server vai aplicar as transformações no code_verifier baseado no code_challenge e code_challenge_method associados com o authorization code recebido
7. Caso a verificação seja bem sucedida, o authorization server retorna o access code para a aplicação cliente

Então, com a introdução destes novos parâmetros, mesmo que algum app malicioso seja capaz de interceptar o authorization code, este não será capaz de trocar o code por um access token no endpoint /token por não saber o `code_verifier` e o `code_challenge_method` utilizado na comunicação com o authorization server. 

## Considerações de segurança

A extensão do PKCE parte do princípio que o code verifier pode ser mantido em segredo do atacante (app malicioso) e que é praticamente impossível de ser adivinhado ou derivado pelo atacante.

Para que o code verifier atinja o requisito satisfatório de aleatoriedade criptográfica, sugere-se utilizar pelo menos 256 bits de entropia.

Pessoalmente, sugiro que utilize bibliotecas open-source confiáveis para gerar o code_challege e verifier, uma vez que são padrões conhecidos. Recorrer a experiência e poder do open-source é sempre bem vindo.

## Concluindo

O PKCE resolve o problema de clientes públicos, como SPAs e Mobile apps, em obter de maneira segura o access token, usufruindo assim dos benefícios do OAuth sem precisar comprometer sua segurança, então lembre-se sempre de utilizar essa extensão ao implementar clientes OAuth públicos.

Para saber mais sobre OAuth e OpenID Connect, deixo aqui a minha coletânea de posts sobre o tema.