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

🏰 Reino OIDC — Leitura complementar

## 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 urllib.parse, secrets 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, json def decodificar_jwt(token: str) -> dict: partes = token.split(".") def decode_b64(s): padding = 4 - len(s) % 4 return json.loads(base64.urlsafe_b64decode(s + "=" * padding)) 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 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: import time return claims.get("email_verified") 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.