Autenticação e autorização
O pacote de contexto de autenticação fornece uma estrutura simples mas poderosa para gerenciar a informação do usuário autenticado através da aplicação. Ele utiliza o mecanismo de contexto do Go para armazenar e recuperar detalhes do usuário, sendo especialmente útil em aplicações multi-tenant.
Componentes Principais
1. AuthenticationContext
A estrutura central que mantém as informações de autenticação:
type AuthenticationContext struct {
TenantID string `json:"tenantId"`
UserID string `json:"userId"`
}
2. Interface IAuthenticationContext
Define o contrato para acessar informações de autenticação:
type IAuthenticationContext interface {
GetUserID() string
GetTenantID() string
}
3. Estrutura de Usuário
type User struct {
ID string
Email string
Phone string
Name string
TenantID string
Profile string
Profiles []string
PhotoURL string
}
Funcionalidades Principais
1. Criação do Contexto de Autenticação
authContext := security.NewAuthenticationContext("tenant123", "user456")
2. Armazenamento no Contexto
// Adiciona as informações de autenticação ao contexto
ctx = authContext.SetInContext(context.Background())
3. Recuperação do Contexto
// Recupera as informações de autenticação do contexto
authContext := security.GetAuthenticationContext(ctx)
if authContext != nil {
tenantID := authContext.GetTenantID()
userID := authContext.GetUserID()
}
4. Validação do Contexto
// Verifica se o contexto de autenticação é válido
if authContext.Valid() {
// Contexto válido, prosseguir com operação
}
Exemplos de Uso
1. Middleware HTTP de Autenticação
func AuthMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Extrair e validar token de autenticação (exemplo simplificado)
token := r.Header.Get("Authorization")
// Processar token e extrair identificadores
tenantID := "tenant-extraído-do-token"
userID := "user-extraído-do-token"
// Criar contexto de autenticação
authContext := security.NewAuthenticationContext(tenantID, userID)
// Verificar validade
if !authContext.Valid() {
http.Error(w, "Credenciais inválidas", http.StatusUnauthorized)
return
}
// Adicionar ao contexto e prosseguir
ctx := authContext.SetInContext(r.Context())
next.ServeHTTP(w, r.WithContext(ctx))
})
}
2. Acesso a Dados Multi-tenant
func (r *Repository) BuscarDadosDoUsuário(ctx context.Context) (*DadosUsuário, error) {
// Recuperar contexto de autenticação
authContext := security.GetAuthenticationContext(ctx)
if authContext == nil {
return nil, errors.New("usuário não autenticado")
}
// Utilizar informações para buscar dados específicos do tenant/usuário
return r.db.Query(
"SELECT * FROM dados WHERE tenant_id = ? AND user_id = ?",
authContext.GetTenantID(),
authContext.GetUserID(),
)
}
3. Propagação em Serviços
type Service struct {
repository Repository
}
func (s *Service) ProcessarOperação(ctx context.Context, dados *Dados) error {
// O contexto já contém as informações de autenticação
// Apenas passar adiante para manter a cadeia de autenticação
return s.repository.SalvarDados(ctx, dados)
}
Boas Práticas
-
Propagação do Contexto:
- Sempre propague o contexto através das chamadas de função
- Não crie novos contextos sem necessidade
- Mantenha a cadeia de informações de autenticação
-
Validação:
- Verifique
authContext != nil
antes de acessar suas propriedades - Use para garantir que os IDs são válidos
Valid()
- Nunca assuma que o contexto está presente
- Verifique
-
Segurança:
- O contexto de autenticação deve ser criado apenas após validação de credenciais
- Não armazene informações sensíveis (senhas, tokens) no contexto
- Limite as informações ao mínimo necessário
-
Isolamento Multi-tenant:
- Use sempre o TenantID em consultas de banco de dados
- Aplique filtros de tenant em todas as operações de dados
- Mantenha isolamento rígido entre dados de diferentes tenants