|
| 1 | +""" |
| 2 | +Exemplo SIMPLIFICADO de aplicação FastAPI com Gov.br Auth. |
| 3 | +
|
| 4 | +Os endpoints fake são registrados AUTOMATICAMENTE pelo GovBrConnector |
| 5 | +quando detecta URLs locais na configuração. Não é necessário código adicional! |
| 6 | +
|
| 7 | +Execute: |
| 8 | + USE_FAKE_GOVBR=true uvicorn example_simple_app:app --reload |
| 9 | +""" |
| 10 | + |
| 11 | +import os |
| 12 | + |
| 13 | +import httpx |
| 14 | +from fastapi import FastAPI, Request |
| 15 | +from fastapi.responses import HTMLResponse |
| 16 | +from govbr_auth import GovBrConfig, GovBrConnector, create_default_fake_users |
| 17 | + |
| 18 | +# Detectar modo (fake ou real) |
| 19 | +USE_FAKE = os.getenv("USE_FAKE_GOVBR", "true").lower() == "true" |
| 20 | + |
| 21 | +# Configurar URLs |
| 22 | +if USE_FAKE: |
| 23 | + print("🧪 Modo FAKE - Endpoints fake serão criados automaticamente!") |
| 24 | + config = GovBrConfig( |
| 25 | + client_id="fake-client-id", |
| 26 | + client_secret="fake-client-secret", |
| 27 | + redirect_uri="http://localhost:8000/auth/govbr/callback", |
| 28 | + cript_verifier_secret="Vvd9H5VC2Aqk-dwFOJX6MvQTuZZARmb37y7un9wkj0c=", |
| 29 | + # URLs locais ativam automaticamente o modo fake |
| 30 | + auth_url="http://localhost:8000/fake-govbr/authorize", |
| 31 | + token_url="http://localhost:8000/fake-govbr/token" |
| 32 | + ) |
| 33 | +else: |
| 34 | + config = GovBrConfig( |
| 35 | + client_id=os.getenv("GOVBR_CLIENT_ID"), |
| 36 | + client_secret=os.getenv("GOVBR_CLIENT_SECRET"), |
| 37 | + redirect_uri=os.getenv("GOVBR_REDIRECT_URI"), |
| 38 | + cript_verifier_secret=os.getenv("CRIPT_VERIFIER_SECRET"), |
| 39 | + auth_url="https://sso.staging.acesso.gov.br/authorize", |
| 40 | + token_url="https://sso.staging.acesso.gov.br/token" |
| 41 | + ) |
| 42 | + |
| 43 | +app = FastAPI(title="Exemplo Simplificado - Gov.br Auth") |
| 44 | + |
| 45 | + |
| 46 | +# Callback de sucesso |
| 47 | +def handle_success(data: dict, request: Request): |
| 48 | + user = data["id_token_decoded"] |
| 49 | + return HTMLResponse(f""" |
| 50 | + <!DOCTYPE html> |
| 51 | + <html> |
| 52 | + <head><title>Login Bem-sucedido</title></head> |
| 53 | + <body style="font-family: Arial; max-width: 600px; margin: 50px auto; text-align: center;"> |
| 54 | + <h1>✅ Autenticado com Sucesso!</h1> |
| 55 | + <div style="background: #f0f0f0; padding: 20px; border-radius: 8px; margin: 20px 0;"> |
| 56 | + <p><strong>Nome:</strong> {user.get('name')}</p> |
| 57 | + <p><strong>CPF:</strong> {user.get('sub') or user.get('cpf')}</p> |
| 58 | + <p><strong>E-mail:</strong> {user.get('email')}</p> |
| 59 | + </div> |
| 60 | + <a href="/" style="color: #1351b4;">← Voltar ao Início</a> |
| 61 | + </body> |
| 62 | + </html> |
| 63 | + """) |
| 64 | + |
| 65 | + |
| 66 | +# Inicializar connector |
| 67 | +# O fake_users é opcional - se não informar, usa usuários padrão |
| 68 | +connector = GovBrConnector( |
| 69 | + config=config, |
| 70 | + on_auth_success=handle_success, |
| 71 | + fake_users=create_default_fake_users() if USE_FAKE else None |
| 72 | +) |
| 73 | + |
| 74 | +# Registrar rotas - endpoints fake são adicionados automaticamente! |
| 75 | +connector.init_fastapi(app) |
| 76 | + |
| 77 | + |
| 78 | +@app.get("/", response_class=HTMLResponse) |
| 79 | +async def home(): |
| 80 | + """Página inicial""" |
| 81 | + modo = "FAKE (Dev)" if USE_FAKE else "REAL (Prod)" |
| 82 | + |
| 83 | + users_info = "" |
| 84 | + if USE_FAKE and connector.fake_service: |
| 85 | + users_info = """ |
| 86 | + <div style="background: #fff3cd; padding: 15px; border-radius: 8px; margin: 20px 0;"> |
| 87 | + <h3>👥 Usuários de Teste</h3> |
| 88 | + <p>Use qualquer CPF abaixo (senha = próprio CPF):</p> |
| 89 | + <ul style="list-style: none; padding: 0;"> |
| 90 | + <li>📋 CPF: <code>12345678901</code> - João da Silva</li> |
| 91 | + <li>📋 CPF: <code>98765432100</code> - Maria Oliveira</li> |
| 92 | + <li>📋 CPF: <code>11122233344</code> - José Santos</li> |
| 93 | + </ul> |
| 94 | + <p><small><a href="/fake-govbr/users">Ver lista completa (JSON)</a></small></p> |
| 95 | + </div> |
| 96 | + """ |
| 97 | + |
| 98 | + return f""" |
| 99 | + <!DOCTYPE html> |
| 100 | + <html> |
| 101 | + <head> |
| 102 | + <title>Gov.br Auth - Exemplo Simplificado</title> |
| 103 | + <style> |
| 104 | + body {{ |
| 105 | + font-family: Arial, sans-serif; |
| 106 | + max-width: 800px; |
| 107 | + margin: 50px auto; |
| 108 | + padding: 20px; |
| 109 | + }} |
| 110 | + .card {{ |
| 111 | + border: 1px solid #ddd; |
| 112 | + border-radius: 8px; |
| 113 | + padding: 20px; |
| 114 | + margin: 20px 0; |
| 115 | + background: #f9f9f9; |
| 116 | + }} |
| 117 | + .btn {{ |
| 118 | + display: inline-block; |
| 119 | + padding: 12px 24px; |
| 120 | + background: #1351b4; |
| 121 | + color: white; |
| 122 | + text-decoration: none; |
| 123 | + border-radius: 4px; |
| 124 | + font-weight: bold; |
| 125 | + }} |
| 126 | + .btn:hover {{ |
| 127 | + background: #0c3f8d; |
| 128 | + }} |
| 129 | + .badge {{ |
| 130 | + display: inline-block; |
| 131 | + padding: 4px 8px; |
| 132 | + background: {"#28a745" if USE_FAKE else "#1351b4"}; |
| 133 | + color: white; |
| 134 | + border-radius: 4px; |
| 135 | + font-size: 12px; |
| 136 | + font-weight: bold; |
| 137 | + }} |
| 138 | + </style> |
| 139 | + </head> |
| 140 | + <body> |
| 141 | + <h1>🇧🇷 Gov.br Auth</h1> |
| 142 | + <p>Exemplo simplificado de integração</p> |
| 143 | + |
| 144 | + <div class="card"> |
| 145 | + <h2>Modo Atual: <span class="badge">{modo}</span></h2> |
| 146 | + <p>{'🧪 Usando simulador fake - perfeito para desenvolvimento!' if USE_FAKE else '🌐 Usando Gov.br real'}</p> |
| 147 | + </div> |
| 148 | + |
| 149 | + <div class="card"> |
| 150 | + <h2>Fazer Login</h2> |
| 151 | + <p>Clique no botão abaixo para autenticar:</p> |
| 152 | + <a href="/auth/govbr/authorize" class="btn">🔐 Entrar com Gov.br</a> |
| 153 | + </div> |
| 154 | + |
| 155 | + {users_info} |
| 156 | + |
| 157 | + <div class="card"> |
| 158 | + <h3>📖 Como Funciona</h3> |
| 159 | + <ol> |
| 160 | + <li>Clique em "Entrar com Gov.br"</li> |
| 161 | + <li>{'Faça login com um dos CPFs de teste' if USE_FAKE else 'Será redirecionado para o Gov.br real'}</li> |
| 162 | + <li>Após autenticação, veja seus dados na tela de sucesso</li> |
| 163 | + </ol> |
| 164 | + {'<p><strong>💡 Dica:</strong> Os endpoints fake são criados automaticamente pelo GovBrConnector!</p>' if USE_FAKE else ''} |
| 165 | + </div> |
| 166 | + |
| 167 | + <div class="card"> |
| 168 | + <h3>🔧 Documentação</h3> |
| 169 | + <ul> |
| 170 | + <li><a href="/docs">API Docs (Swagger)</a></li> |
| 171 | + <li><a href="/redoc">API Docs (ReDoc)</a></li> |
| 172 | + {'<li><a href="/fake-govbr/users">Lista de Usuários Fake (JSON)</a></li>' if USE_FAKE else ''} |
| 173 | + </ul> |
| 174 | + </div> |
| 175 | + </body> |
| 176 | + </html> |
| 177 | + """ |
| 178 | + |
| 179 | + |
| 180 | +@app.get("/health") |
| 181 | +async def health(): |
| 182 | + """Health check""" |
| 183 | + return { |
| 184 | + "status": "ok", |
| 185 | + "modo": "fake" if USE_FAKE else "real", |
| 186 | + "fake_service_ativo": connector.fake_service is not None, |
| 187 | + "endpoints_fake_registrados": connector.is_fake_mode |
| 188 | + } |
| 189 | + |
| 190 | +@app.get("/auth/govbr/callback") |
| 191 | +async def auth_callback(request: Request): |
| 192 | + """Callback de autenticação Gov.br""" |
| 193 | + # requisição para http post para /auth/govbr/authenticate |
| 194 | + async with httpx.AsyncClient() as client: |
| 195 | + response = await client.post( |
| 196 | + "http://localhost:8000/auth/govbr/authenticate", |
| 197 | + json=dict(request.query_params.items()) |
| 198 | + ) |
| 199 | + return HTMLResponse(content=response.text, status_code=response.status_code) |
| 200 | + |
| 201 | +if __name__ == "__main__": |
| 202 | + import uvicorn |
| 203 | + |
| 204 | + print("\n" + "="*70) |
| 205 | + print("🚀 Gov.br Auth - Exemplo Simplificado") |
| 206 | + print("="*70) |
| 207 | + print(f"Modo: {'🧪 FAKE' if USE_FAKE else '🌐 REAL'}") |
| 208 | + print(f"URL: http://localhost:8000") |
| 209 | + |
| 210 | + if USE_FAKE and connector.fake_service: |
| 211 | + print(f"\n✨ Endpoints fake registrados automaticamente:") |
| 212 | + print(f" • GET /fake-govbr/authorize (página de login)") |
| 213 | + print(f" • POST /fake-govbr/login (processar login)") |
| 214 | + print(f" • POST /fake-govbr/token (trocar code por token)") |
| 215 | + print(f" • GET /fake-govbr/users (listar usuários)") |
| 216 | + print(f"\n📝 {len(connector.fake_service.users)} usuários disponíveis") |
| 217 | + |
| 218 | + print("="*70 + "\n") |
| 219 | + |
| 220 | + uvicorn.run(app, host="0.0.0.0", port=8000) |
| 221 | + |
0 commit comments