Skip to content

Commit c6aebac

Browse files
committed
feat(fake-govbr): adiciona suporte a modo fake para desenvolvimento
Adiciona a funcionalidade de simulação de autenticação Gov.br com endpoints fake para facilitar o desenvolvimento local. Inclui configuração de usuários de teste e páginas de login simuladas.
1 parent 8a1231a commit c6aebac

File tree

9 files changed

+1695
-21
lines changed

9 files changed

+1695
-21
lines changed

.env.example

Lines changed: 70 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,70 @@
1-
GOVBR_REDIRECT_URI=
2-
GOVBR_CLIENT_ID=
3-
GOVBR_CLIENT_SECRET=
4-
GOVBR_CODE_CHALLENGE_METHOD=S256
5-
GOVBR_SCOPE=openid email profile
6-
GOVBR_RESPONSE_TYPE=code
7-
CRIPT_VERIFIER_SECRET=
8-
GOVBR_AUTH_URL=https://sso.staging.acesso.gov.br/authorize
9-
GOVBR_TOKEN_URL=https://sso.staging.acesso.gov.br/token
10-
GOVBR_USER_INFO=https://api.acesso.gov.br/userinfo
11-
JWT_SECRET=chave_super_secreta
12-
JWT_EXPIRES_MINUTES=60
13-
JWT_ALGORITHM=HS256
1+
# ============================================================================
2+
# Configuração de Ambiente - Gov.br Auth
3+
# ============================================================================
4+
5+
# ─────────────────────────────────────────────────────────────────────────────
6+
# 🧪 MODO DE DESENVOLVIMENTO (Fake Gov.br)
7+
# ─────────────────────────────────────────────────────────────────────────────
8+
# Descomente estas linhas para usar o simulador fake (sem precisar de Gov.br real)
9+
10+
USE_FAKE_GOVBR=true
11+
CRIPT_VERIFIER_SECRET=Vvd9H5VC2Aqk-dwFOJX6MvQTuZZARmb37y7un9wkj0c=
12+
13+
14+
# ─────────────────────────────────────────────────────────────────────────────
15+
# 🌐 MODO HOMOLOGAÇÃO/PRODUÇÃO (Gov.br Real)
16+
# ─────────────────────────────────────────────────────────────────────────────
17+
# Descomente e preencha estas linhas para usar o Gov.br real
18+
19+
# USE_FAKE_GOVBR=false
20+
21+
# Credenciais OAuth (obtidas no portal Gov.br)
22+
# GOVBR_CLIENT_ID=seu-client-id-aqui
23+
# GOVBR_CLIENT_SECRET=seu-client-secret-aqui
24+
# GOVBR_REDIRECT_URI=https://sua-aplicacao.com.br/auth/govbr/callback
25+
26+
# Chave de criptografia (gere com: python -c "from govbr_auth.utils import generate_cript_verifier_secret; print(generate_cript_verifier_secret())")
27+
# CRIPT_VERIFIER_SECRET=gere-uma-chave-segura-aqui
28+
29+
# URLs do Gov.br
30+
# GOVBR_AUTH_URL=https://sso.staging.acesso.gov.br/authorize
31+
# GOVBR_TOKEN_URL=https://sso.staging.acesso.gov.br/token
32+
# GOVBR_USER_INFO=https://api.acesso.gov.br/userinfo
33+
34+
# Configurações OAuth
35+
# GOVBR_SCOPE=openid email profile
36+
# GOVBR_RESPONSE_TYPE=code
37+
# GOVBR_CODE_CHALLENGE_METHOD=S256
38+
39+
40+
# ─────────────────────────────────────────────────────────────────────────────
41+
# 🔐 JWT (Opcional - se você gerar seus próprios tokens)
42+
# ─────────────────────────────────────────────────────────────────────────────
43+
44+
# JWT_SECRET=chave_super_secreta_para_jwt
45+
# JWT_EXPIRES_MINUTES=60
46+
# JWT_ALGORITHM=HS256
47+
48+
49+
# ─────────────────────────────────────────────────────────────────────────────
50+
# 📝 NOTAS
51+
# ─────────────────────────────────────────────────────────────────────────────
52+
53+
# 1. Para desenvolvimento local, use USE_FAKE_GOVBR=true
54+
# - Não precisa de credenciais reais do Gov.br
55+
# - Funciona totalmente offline
56+
# - Usuários de teste estão pré-configurados
57+
#
58+
# 2. Para homologação/produção, use USE_FAKE_GOVBR=false
59+
# - Preencha todas as credenciais do Gov.br
60+
# - Certifique-se de que a GOVBR_REDIRECT_URI está cadastrada no portal Gov.br
61+
# - Gere uma CRIPT_VERIFIER_SECRET segura
62+
#
63+
# 3. URLs do Gov.br:
64+
# - Homologação: https://sso.staging.acesso.gov.br
65+
# - Produção: https://sso.acesso.gov.br
66+
#
67+
# 4. Nunca commite este arquivo com credenciais reais!
68+
# - Adicione .env ao .gitignore
69+
# - Use variáveis de ambiente no servidor de produção
70+

examples/example_simple_app.py

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
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+

govbr_auth/__init__.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,14 @@
55
from .core.govbr import GovBrAuthorize, GovBrIntegration, GovBrException, GovBrAuthenticationError
66
from .controller import GovBrConnector
77
from .utils import generate_cript_verifier_secret
8+
from .fake_govbr import (
9+
FakeUserData,
10+
FakeGovBrService,
11+
AuthorizationRequest,
12+
render_fake_login_page,
13+
process_fake_login,
14+
create_default_fake_users
15+
)
816
except ImportError:
917
pass # noqa: E402
1018

0 commit comments

Comments
 (0)