Este projeto implementa um Identity Provider (IdP) OAuth2 completo e seguro, focado em fornecer autenticação e autorização robusta para aplicações web e móveis. O sistema implementa o fluxo OAuth2 Authorization Code com PKCE (Proof Key for Code Exchange) para máxima segurança.
O Aetheris Identity Provider tem como objetivo principal:
- Centralizar a autenticação de usuários em um único sistema
- Implementar OAuth2 seguindo as melhores práticas de segurança
- Suportar múltiplos clientes (aplicações) com diferentes níveis de acesso
- Fornecer tokens JWT seguros para autenticação de API
- Implementar PKCE para prevenir ataques de interceptação de código
- Gerenciar escopos granulares para controle de acesso detalhado
- Suportar OpenID Connect para identidade federada
- Backend: Go 1.24.2 com Echo framework
- Banco de Dados: MongoDB 7.0
- Autenticação: JWT + OTP (One-Time Password)
- Containerização: Docker + Docker Compose
- Injeção de Dependência: Uber Dig
- Validação: Go Playground Validator
- Testes: Testify + Mocks
backend/
├── cmd/api/ # Ponto de entrada da aplicação
├── internal/ # Lógica interna da aplicação
│ ├── api/ # Utilitários da API (validação, resposta, erro)
│ ├── bootstrap/ # Configuração e inicialização
│ ├── domain/ # Entidades e regras de negócio
│ ├── handlers/ # Controladores HTTP
│ ├── middlewares/ # Middlewares de autenticação e autorização
│ ├── models/ # Modelos de dados e DTOs
│ ├── repositories/ # Camada de acesso a dados
│ ├── server/ # Configuração do servidor HTTP
│ └── services/ # Lógica de negócio
├── pkg/ # Pacotes reutilizáveis
├── configs/ # Configurações da aplicação
├── infra/ # Infraestrutura (banco de dados)
└── mocks/ # Mocks para testes
sequenceDiagram
participant Client as Aplicação Cliente
participant User as Usuário
participant IdP as Aetheris IdP
participant Auth as Sistema de Auth
Client->>User: Redireciona para login
User->>IdP: GET /oauth/authorize
Note over IdP: Valida parâmetros OAuth2
IdP->>Auth: Verifica autenticação
Auth-->>IdP: Usuário não autenticado
IdP->>User: Redireciona para login
User->>Auth: POST /auth/login
Auth-->>User: Envia código OTP
User->>Auth: POST /auth/authenticate
Auth-->>User: Autenticação bem-sucedida
User->>IdP: GET /oauth/authorize (autenticado)
IdP->>IdP: Valida client_id, redirect_uri, scope
IdP->>IdP: Gera authorization_code
IdP->>Client: Redireciona com code + state
sequenceDiagram
participant Client as Aplicação Cliente
participant IdP as Aetheris IdP
participant DB as MongoDB
Client->>IdP: POST /oauth/token
Note over Client: Inclui: code, code_verifier, client_id, redirect_uri
IdP->>IdP: Valida authorization_code
IdP->>IdP: Verifica PKCE (code_challenge vs code_verifier)
IdP->>DB: Busca dados do usuário e cliente
IdP->>IdP: Gera access_token, refresh_token, id_token
IdP-->>Client: Retorna tokens JWT
Note over Client: access_token, refresh_token, id_token, expires_in
| Parâmetro | Obrigatório | Descrição |
|---|---|---|
client_id |
Sim | Identificador único do cliente OAuth2 |
redirect_uri |
Sim | URI de redirecionamento após autorização |
response_type |
Sim | Deve ser code para Authorization Code |
scope |
Sim | Escopos solicitados (separados por espaço) |
state |
Sim | Valor para prevenir ataques CSRF |
code_challenge |
Sim | Hash do code_verifier para PKCE |
code_challenge_method |
Sim | Método de hash (S256 recomendado) |
| Parâmetro | Obrigatório | Descrição |
|---|---|---|
code |
Sim | Código de autorização recebido |
code_verifier |
Sim | Verificador PKCE original |
client_id |
Sim | ID do cliente OAuth2 |
redirect_uri |
Sim | URI de redirecionamento |
profile:read- Leitura de informações públicas do perfilprofile:write- Modificação de informações do perfilpassword:write- Alteração da própria senhaaccount:delete:self- Exclusão da própria conta
notifications:read- Leitura de notificaçõesnotifications:write- Gerenciamento de notificações
openid- Identificação OpenID Connect
users:read,users:create,users:update,users:deleteclients:read,clients:create,clients:update,clients:delete
- Code Challenge: Hash SHA256 do code_verifier
- Code Verifier: String aleatória de 43-128 caracteres
- Prevenção: Ataques de interceptação de código
- Verificação de
client_idválido - Validação de
redirect_uriregistrada - Verificação de escopos autorizados
- Expiração de códigos de autorização
- Validação de
statepara CSRF
- Access Token: Acesso a recursos protegidos
- Refresh Token: Renovação de tokens expirados
- ID Token: Informações de identidade do usuário
- Expiração: Controle de tempo de vida dos tokens
- Go 1.24.2+
- Docker e Docker Compose
- MongoDB (via Docker)
git clone https://github.com/g-villarinho/o-auth2.git
cd o-auth2cd backend
cp .env.example .env
# Editar .env com suas configuraçõesdocker-compose up -dcd backend
go mod download
go run cmd/api/main.gocurl http://localhost:8080/api/dev/healthGET /api/oauth/authorize- Iniciar fluxo de autorizaçãoPOST /api/oauth/token- Trocar código por tokens
POST /api/auth/login- Login do usuárioPOST /api/auth/register- Registro de usuárioPOST /api/auth/authenticate- Autenticação OTPPOST /api/auth/code/resend- Reenvio de código OTP
POST /api/clients- Criar novo cliente OAuth2
GET /api/dev/health- Status da aplicaçãoGET /api/dev/envs- Variáveis de ambiente
curl -X POST http://localhost:8080/api/clients \
-H "Content-Type: application/json" \
-d '{
"client_id": "meu-app",
"client_secret": "secret123",
"redirect_uris": ["https://meu-app.com/callback"],
"scopes": ["profile:read", "openid"]
}'GET /api/oauth/authorize?
client_id=meu-app&
redirect_uri=https://meu-app.com/callback&
response_type=code&
scope=profile:read openid&
state=abc123&
code_challenge=hash_do_code_verifier&
code_challenge_method=S256
curl -X POST http://localhost:8080/api/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "code=AUTHORIZATION_CODE&code_verifier=CODE_VERIFIER&client_id=meu-app&redirect_uri=https://meu-app.com/callback"- users: Usuários do sistema
- clients: Clientes OAuth2 registrados
- authorization_codes: Códigos de autorização temporários
- refresh_tokens: Tokens de renovação
- otps: Códigos OTP para autenticação
cd backend
go test ./...go test -coverprofile=coverage.out ./...
go tool cover -html=coverage.out