🔐 Cap 20: Login na Arena: Auth e Tokens

🎯 Objetivo da Aula: Ao final desta aula, você entenderá como os aplicativos mantêm você “logado” com segurança. Você aprenderá o que é um Token JWT e como enviá-lo para o servidor para provar que você é você mesmo antes de entrar em uma batalha online.


🏢 O Cenário Prático (Seu Desafio): Hackers estão tentando burlar o ranking do seu jogo enviando pontuações falsas! Eles fazem isso fingindo que são outros jogadores. Seu desafio é implementar a Trava de Segurança: o jogador deve fazer login com senha e receber um “Cartão de Acesso” (o Token). O servidor só aceitará comandos de quem mostrar esse cartão.


🧠 Fundamentos: A Teoria Traduzida

📖 Dicionário do Programador

🎨 Padrão de Cabeçalho (Header)

Toda vez que você pede algo ao servidor (como ver seus itens), você coloca o token num “envelope” invisível chamado HTTP Header, na chave Authorization.

graph TD
    A["App: Envia Senha"] --> B["Servidor: Valida"]
    B --> C["Entrega Crachá: JWT"]
    C --> D["App: Salva o Crachá"]
    D --> E["Próxima Chamada: Mostra Crachá"]

🏗️ Construindo o Projeto (Checklist Studio)

No seu código que chama a API (Retrofit), você deve adicionar o cabeçalho: Authorization: Bearer <SEU_TOKEN>


📦 Imports Necessários

Antes de copiar o código abaixo, adicione estes imports no topo do seu arquivo .kt:

import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory

💡 okhttp3.Interceptor, OkHttpClient e Response já vêm como dependência transitiva do retrofit (Cap 13) — não é necessário adicionar nada novo no Gradle.


📖 Exemplo Passo a Passo: Formatando o Crachá

Parte 1 — O Formato do Cabeçalho:

fun prepararCabecalho(token: String): String {
    // Adicionamos a palavra mágica 'Bearer' antes do código
    return "Bearer $token"
}

fun main() {
    val meuToken = "abc123xyz"
    println(prepararCabecalho(meuToken)) 
    // Resultado: Bearer abc123xyz
}

Parte 2 — O Interceptor Real: em vez de adicionar o cabeçalho manualmente em cada chamada, criamos um Interceptor. Ele “intercepta” toda requisição do Retrofit e anexa o token automaticamente, antes de ela seguir para o servidor:

class AuthInterceptor(private val token: String) : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        val requisicaoOriginal = chain.request()

        val requisicaoComToken = requisicaoOriginal.newBuilder()
            .addHeader("Authorization", prepararCabecalho(token))
            .build()

        return chain.proceed(requisicaoComToken)
    }
}

fun criarRetrofit(token: String): Retrofit {
    val client = OkHttpClient.Builder()
        .addInterceptor(AuthInterceptor(token))
        .build()

    return Retrofit.Builder()
        .baseUrl("https://meu-jogo.beeceptor.com/")
        .client(client)
        .addConverterFactory(GsonConverterFactory.create())
        .build()
}

💡 Repare que criarRetrofit é parecido com o Retrofit.Builder() do Cap 13, mas com uma linha extra: .client(client), que conecta o OkHttpClient (e seu AuthInterceptor) ao Retrofit.


🛠️ Prática Obrigatória 1: Crie uma função chamada gerarHeader. Ela recebe uma String token e retorna a String formatada para o cabeçalho. Teste com o token "pokedex_gold_2026".


🛠️ Prática Obrigatória 2: Pesquise e anote: Por que é perigoso deixar o Token guardado para sempre no celular? O que é o “tempo de expiração” de um token?


🛠️ Prática Obrigatória 3: Usando AuthInterceptor como referência, crie a classe LogInterceptor, que também implementa Interceptor. No método intercept, antes de chamar chain.proceed(...), ela deve imprimir println("📡 Chamando: ${chain.request().url}").


🔑 Gabarito Passo a Passo:

Exercício 2: O token expira para que, se alguém roubar o seu celular, o “crachá” pare de funcionar depois de algum tempo (ex: 1 hora), obrigando um novo login.

Exercício 3:

class LogInterceptor : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        val requisicao = chain.request()
        println("📡 Chamando: ${requisicao.url}")
        return chain.proceed(requisicao)
    }
}

📤 Instruções de Entrega (Microsoft Teams):

  1. Envie o código da sua função de Header e da classe AuthInterceptor.
  2. Envie sua resposta sobre a expiração de tokens e o código do LogInterceptor.
  3. Submeta no canal de tarefas.

⬅️ Voltar para a Home