Introdução a Oauth
A primeira coisa que você precisa ter em mente sobre OAuth e que muito provavelmente o motivo que te levou a buscar sobre OAuth, e que te levou a esse post, é no minimo parcialmente incorreto! A grande amioria das implementações de cliente OAuth buscam um single sign on (SSO), em outras palavras compartilha a autenticação com outro sistema, arrisco dizer que a maioria das pessoas tem contato com OAuth na busca por implementar o famoso “login com o google”, talvez com o Facebook, sim esse é uma das possibilidades mas esse protocolo não é exclusivo a esse caso de uso. Inclusive existem outras formas de implementar SSO, desde compartilhar o segredo de um token JWT até protocolos empresariais mais avançados e seguros como SAML.
A ideia da sepecificação é permitir a serviços de terceiros o acesso aos dados dos seus serviços de maneira segura e granular. Então quando você passa por aquela famosa tela de login do google para logar naquele site de conteúdo duvidoso você esta dando aquele site uma forma de acessar os seus dados no google, geralmente as suas informações pessoais básicas como seu nome endereço de email.
Mas esse mesmo fluxo pode ser utilizado para garantir acesso a várias outras informações e até mesmo ações dentro da sua conta do google. Por exemplo, muitos clientes de e-mail como o thunderbird implementam cliente Oauth para ter acesso aos seus e-mails google, permitindo assim que o thunderbird envie os emails com a sua conta do Gmail. Para isso que o Oauth server, garantir que serviços de terceiros tenham acesso aos seus serviços.
Esse é um exemplo bem legal pra mostrar alguns dos conceitos principais da especificação Oauth as roles, ou os papéis de cada parte dentro do fluxo dessa autorização:
- Resource owner: bem esse é você! O dono da conta do google, quem tem o poder de autorizar ou não o acesso aos seus recursos dentro dos sistemas do google, seu gmail, seus arquivos do drive etc.
- Resource server: todos os serviços do google compartilham da mesma estrutura para autenticação, nesse caso é o servidor do gmail
- Client: o “terceiro”, no nosso caso o thunderbird, o sistema que vai ser autorizado a fazer alguma coisa com os seus recursos do google
- Authorization Server: O servidor da google que guarda as credenciais, email e senha, dos usuarios.
Um ultimo conceito que dá pra explicar com esse exemplo são os scopes, os escopos, do token: você deu acesso pro thunderbird interagir com o gmail, não com o google drive, esses são os escopos desta autorização, são os limites que aquele sistema de terceiros vai poder acessar.
O resultado final dessa autorização é um token, um texto unico e temporário que deve ser passado em cada requisição que o client fizer para os serviços do google, afinal a ideia de toda essa dança maluca de servidores e que você não tenha de entregar a sua preciosa senha para ninguém.
Aqui entra mais uma, talvez a mais importante, particularidade do OAuth: o fluxo e os Grant-Types.
O fluxo para se obter o token é quase sempre o mesmo exemplificado a seguir:
- O Resource Owner acessa um serviço de terceiro, o nosso Client
- O Client redireciona o usuario para uma pagina de login do Authorization Server, passando as identificações do Client e o escopo que ele precisa
- O Auth Server pede para que o Resource Owner logue e autorize o Client
- O Auth Server redireciona para o Client passando uma resposta, um erro caso o Resource Owner não tenha autorizado, ou um code que servirá para obter o token na etapa seguinte
- O Client fará uma requisição para o Auth Server passando o codigo
- O Auth Server retorna um token
Com esse token em mãos podemos fazer requisições para os Resource Servers, que o escopo do token autorizar é claro.
Você deve estar pensando: Ok, isso é muito lindo mas é muito abstrato, muita conversa eu gosto de ver algo mais mão na massa, quais as urls que eu devo redirecionar? O que eu tenho de passar em cada um desses passos? Como eu faço um login com isso?
Vamos a um exemplo de login usando um fluxo de authorization code com o AD da Microsoft, depois posso escrever um do google, mas implementei isso cm microsoft mais recentemente…
Anter de qualquer coisa você vai precisar de um Client, já que nesse caso você é o “terceiro”, um client tem duas informações principais: client_id e client_secret, o client_id é meio que público e serve apenas para identificar o nosso sitema, já o secret, bem ele é secreto e vai ser usado para obter o token
- O usuário quer logar no seu sistema
- O seu sitema vai redirecionar o usuario para
/oauth2/v2.0/authorize?client_id=...&response_type=code&scope=user.read
passando o client_id e os scopes, - O usuário vai permitir
- A microsoft vai redirecionar para o seu sistema novamente, passando um parametro code na query
- O seu sistema vai fazer uma requisição para
/oauth2/v2.0/token
, passando o code e o client_secret - Agora você ja tem um token!
Com esse token você pode fazer uma requisição para obter os dados do usuario, como o email, para referenciar isso dentro do seu sistema e da sua autenticação, por isso passamos o escopo user.read
.
Infelizmente não terei tempo de continuar explicando os demais grant-types, mas deixo aqui algums questionamentos, e os principais motivos de que precisamos de mais de uma forma de obter tokens:
- Esse exemplo é bem legal se você estiver em um sistema que seja renderizado no servidor, PHP, Django ou RubyOnRails, mas e as SPAs? Você não pode deixar o secret exposto certo? O mesmo para aplicativos Moveis!
- E se eu não quiser iteração de usuario? Tenho meus sistemas e quero deixar uma empresa parceira buscar ou enviar dados sem esse negócio todo do login
Diferentes necessidades levam a diferentes soluções, eu espero poder trazer algumas em um post futuro, fique de olho!
Este é mais um post super do meu desafio de escrever posts por 30 dias, você pode ver outros posts na tag 30daysOfPosts