Autorização, Autenticação e Golang

Michelle Mesquita
6 min readJul 4, 2021

--

Uma dúvida bem comum que acontece com as pessoas que estão iniciando na área de segurança, é saber a diferença entre autorização e autenticação.

Dessa forma, resolvi criar um exemplo, escrito em Golang para mostrar a diferença entre esses dois métodos.

Primeiramente, vamos entender essa diferença semântica :)

Autenticação: Ela verifica a identidade do usuário, ou seja, permite que o usuário consiga se logar no sistema.

Autorização: Ela ocorre após a autenticação do sistema, ou seja, está relacionado ao privilégio do usuário. Como por exemplo, se um sistema possui um usuário comum e um usuário administrador. Esse último terá mais acesso ao sistema, ele poderá ter acesso as funções de editar ou cadastrar um usuário no sistema, por exemplo.

Pensando nessas diferenças, resolvi criar um sistema bem simples utilizando o Keycloack e Golang.

Utilizei o Keycloack, pois é uma ferramenta muito utilizada atualmente para o gerenciamento de serviços utilizando login único. Enquanto Golang (Go), linguagem desenvolvida pelo Google, é uma linguagem extremamente performática, cada vez mais utilizada para o backend das aplicações.

Além disso, Golang era uma linguagem da qual eu queria me aprofundar e nada melhor do que criarmos um projeto do zero, para evoluirmos nesse aprendizado. No entanto, vale ressaltar, que eu não recomendo essa linguagem para quem está iniciando com programação. Ela é uma linguagem bem tipada (você precisa dizer os tipos das variáveis que irão retornar de uma determinada função, por exemplo, se é inteiro, byte, string) e com uma documentação/comunidade menor do que Python e JavaScript, por exemplo.

Dessa forma, vamos iniciar o nosso exemplo, configurando o Keycloack!

Para ficar mais fácil o aprendizado, iremos utilizar docker, seguindo esse comando:

docker run -p 8080:8080 -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=admin quay.io/keycloak/keycloak:14.0.0

Agora, iremos seguir os passos que no próprio site do Keycloack está muito bem documentado:

Após iniciarmos o container do Keycloack, iremos para a página de administração do mesmo, que se encontra na porta 8080 do localhost.

Iremos colocar o usuário e senha "admin", conforme passamos como parâmetro anteriormente para iniciarmos o docker.

Ao entrarmos na tela de principal, iremos criar o Realm (o qual irá criar um grupo isolado), conforme mostrado na documentação e assim, criaremos também um usuário.

Após isso, iremos mudar o tipo de autenticação em "Clients". Utilizaremos o OpenID Connect, que é utilizado para fazer login. Além disso, é importante sabermos que OAuth2, a base do OpenID Connect, é um protocolo de delegação que ajuda a acessar APIs de terceiros.

Depois de configurado, precisamos clicar em "save" para salvarmos as alterações.

Na aba Credentials, tenha em mente, que você precisará mais tarde dessa Secret para se autenticar com a aplicação.

Agora, iremos criar uma role, para adicionarmos no nosso usuário, como exemplo de autorização.

Na aba "role", você irá criar um exemplo de perfil de acesso. No exemplo, eu criei o "admin" após clicar em "add role".

Depois, você irá adicionar a role criada para o seu usuário criado, como no exemplo, o usuário "myclient".

Assim, o usuário já possui a role "admin". Agora, precisamos adicionar ao cliente para que a aplicação consiga "enxergar" essa configuração.

Utilizaremos a aba de clientsscope e selecionaremos apenas "admin". Caso contrário, todos as outras roles estariam presentes no token.

Após tudo configurado, iremos para o Golang!

Criei um repositório onde ensino como instalar as bibliotecas necessárias para o projeto.

Feito isso, será necessário trocar o nome do usuário e a secret do arquivo .env Essas informações são provenientes da aba Clients, onde seu usuário foi criado.

É importante criarmos um arquivo .env para não deixarmos nossas credenciais expostas. Como também, não devemos enviar esse arquivo ao Github. 

Dessa forma, quando você digitar http://localhost:8081 , você será direcionado a tela de login da aplicação. Nessa tela, você colocará seu usuário e senha criados anteriormente.

Conforme podemos observar nessa linha de código, a porta que nosso servidor está rodando.

log.Fatal(http.ListenAndServe(":8081", nil))

Após colocar suas credenciais certas, você será redirecionado para http://localhost:8081/auth/callback e verá a seguinte tela:

Pronto, você está autenticado na aplicação!

Caso contrário:

Após autenticado, iremos testar nossas 2 rotas criadas:

http.HandleFunc("/hello", func(writer http.ResponseWriter, request *http.Request)
http.HandleFunc("/lock", func(writer http.ResponseWriter, request *http.Request)

Antes disso, utilizaremos o nosso token de autorização para sabermos se o nosso usuário está logado a aplicação.

Caso esteja, ao passarmos esse token, esse usuário irá retornar um token de autorização.

rawAccessToken := request.Header.Get("Authorization")

Dessa forma, ele poderá tentar acessar uma rota, conforme o seu perfil de acesso "role").

No exemplo criado, para facilitar a compreensão da autorização, foi feita uma comparação, onde se o usuário tivesse determinado valor na role, conseguiria ter permissão para acessar ou não determinada rota.

json_obj := result["roles"].([]interface{})

for _, value := range json_obj {

if value.(string) != "admin"{
http.Error(writer, "Forbidden", http.StatusForbidden)
return
}

if value.(string) == "admin"{
writer.Write([]byte("hello world"))
return
}

}

Dessa maneira, é possível observar que o usuário "myclient" não pode acessar a rota /lock .

Uma dica importante:

Dependendo de como for implementado esse token, um atacante pode facilmente burlar esse sistema de roles e escalar privilégio em uma aplicação. Isso pode ocorrer apenas com o usuário trocando o valor da role, conforme mostrado a seguir:

JWT Authorization ( JSON Web Token ou JWT, um formato de token padrão) → base64

InJvbGVzIjogWyJ0ZXN0Il0=

token2str,_ := base64.StdEncoding.DecodeString(rawAccessToken)

“roles”: [ “test”] → “roles”: [ “admin”]

token2base64,_ := base64.StdEncoding.EncodeToString(token2str)

Referências:

--

--

Michelle Mesquita
Michelle Mesquita

Written by Michelle Mesquita

DevSecOps & AppSec Engineer & Developer girl 👩‍💻

No responses yet