Fase 5 6 horas Avançado

# A Grande Corrida

Na reta final, só passa quem tem credencial. OAuth 2.0, OIDC e JWT são os portões da segurança digital — saber abri-los é chegar primeiro.

Progresso: 0/8 (0%)

## Objetivos da Fase

#### O que você vai aprender:

- OAuth 2.0: fluxo de autorização passo a passo
- OIDC (OpenID Connect): identidade sobre OAuth
- Estrutura de um JWT (header.payload.signature)
- Scopes, claims e o princípio do menor privilégio
- Diferença entre autenticação e autorização
- Provedores OIDC: Google, GitHub, Microsoft
- Biblioteca `python-jose` para JWT em Python

#### O que você vai criar:

- Decodificador de JWT manual (base64url)
- Simulador do fluxo OAuth 2.0
- Validador de token OIDC com `python-jose`
- Dashboard HTTP com rota protegida

#### 🏰 Convite ao Reino OIDC

Para reforçar OAuth 2.0, OIDC e JWT com uma narrativa complementar, visite o Reino OIDC antes de seguir para o projeto da fase.

Entrar no Reino OIDC

## 5.1 — O Portão da Corrida: OAuth 2.0

Imagina a largada: o fiscal pede sua credencial, você apresenta sua identidade, ele emite um crachá temporário. Esse crachá é o access token.

#### 🔑 Fluxo Authorization Code

1. Usuário clica em "Entrar com Google"
2. App redireciona para o provedor com `client_id` + `scope`
3. Usuário autentica e autoriza
4. Provedor retorna um `authorization_code`
5. App troca o código por `access_token` + `id_token`
6. App usa o token para acessar recursos protegidos

    # Simulador do fluxo OAuth 2.0 em Python
    import secrets
    import urllib.parse

    CLIENT_ID = "circuito_ferradura_app"
    REDIRECT_URI = "http://localhost:8080/callback"
    SCOPE = "openid profile email"

    state = secrets.token_urlsafe(16)  # proteção CSRF

    params = {
        "response_type": "code",
        "client_id": CLIENT_ID,
        "redirect_uri": REDIRECT_URI,
        "scope": SCOPE,
        "state": state,
    }
    url = (
        "https://accounts.google.com/o/oauth2/auth?"
        + urllib.parse.urlencode(params)
    )
    print(f"→ Redirecionar para:\n{url}")

## 5.2 — O Número do Peito: JWT

Cada piloto tem um número no peito — único e verificável. O JWT funciona assim: três partes separadas por ponto, codificadas em base64url.

    # Estrutura de um JWT
    # HEADER.PAYLOAD.SIGNATURE
    #
    # Header  → {"alg": "RS256", "typ": "JWT"}
    # Payload → {"sub": "12345", "name": "Ciclano",
    #             "email": "ci@ferradura.dev", "iat": 1702930800}

    import base64
    import json

    def decodificar_jwt(token: str) -> dict:
        partes = token.split(".")

        def decode_b64(valor: str) -> dict:
            padding = "=" * (-len(valor) % 4)
            dados = base64.urlsafe_b64decode(valor + padding)
            return json.loads(dados)

        header = decode_b64(partes[0])
        payload = decode_b64(partes[1])

        return {
            "header": header,
            "payload": payload,
            "assinatura": partes[2][:20] + "...",
        }

    # Exemplo com python-jose (validação com chave pública)
    from jose import jwt
    claims = jwt.decode(
        token,
        chave_publica,
        algorithms=["RS256"],
        audience=CLIENT_ID,
    )
    print(f"Bem-vindo, {claims['name']}!")

## 5.3 — OIDC: A Identidade sobre o OAuth

OAuth diz "você pode acessar". OIDC responde "mas quem é você?". O `id_token` contém as claims de identidade verificáveis.

    # Claims típicas de um id_token OIDC
    import time

    id_token_payload = {
        "iss": "https://accounts.google.com",  # quem emitiu
        "sub": "103456789012345678901",  # ID único do usuário
        "aud": CLIENT_ID,  # para quem é o token
        "exp": 1702934400,  # quando expira (Unix)
        "iat": 1702930800,  # quando foi emitido
        "name": "Ciclano da Corrida",
        "email": "ciclano@ferradura.dev",
        "email_verified": True,
    }

    def piloto_autenticado(claims: dict) -> bool:
        return (
            claims.get("email_verified") is True
            and claims["exp"] > time.time()
        )

## ✅ Checklist da Fase 5

Expliquei os 6 passos do fluxo Authorization Code para alguém
Construí a URL de autorização OAuth 2.0 dinamicamente
Decodifiquei manualmente o header e payload de um JWT real
Validei um JWT com `python-jose` e verifiquei as claims
Identifiquei as diferenças entre OAuth 2.0 e OIDC
Implementei `piloto_autenticado()` com verificação de expiração
Criei uma rota HTTP protegida que exige Bearer token
Explorei o Reino OIDC e resumo os conceitos principais

#### 🔐 Projeto da Fase 5

Crie um micro-servidor Flask com duas rotas: `/login` (redireciona para Google OAuth) e `/dashboard` (protegida — exige `id_token` válido na sessão). Use `python-jose` para validar o token e exiba o nome do piloto autenticado.

🔒 LGPD — Usamos localStorage para salvar progresso.