Introdução ao OAuth 2.0 e JWT em Go
Aplicações web modernas e APIs exigem um sistema de autenticação e autorização robusto e seguro. Dois dos padrões mais populares nesta área são OAuth 2.0 e JWT (JSON Web Tokens). Na linguagem Go (Golang), a implementação desses mecanismos torna-se especialmente eficiente devido ao suporte embutido para concorrência, alta performance e um rico ecossistema de bibliotecas.
Neste artigo, vamos detalhar como implementar autorização OAuth 2.0 e JWT em Go. Você aprenderá como configurar o servidor, gerar e verificar tokens, além de proteger seus endpoints. O material será útil tanto para desenvolvedores Go iniciantes quanto para os experientes.
Fundamentos de OAuth 2.0 e JWT
O que é OAuth 2.0?
OAuth 2.0 é um protocolo de autorização que permite que aplicações obtenham acesso limitado aos recursos do usuário sem transmitir a senha. Em vez disso, são utilizados tokens de acesso (access tokens). Os principais participantes do processo são:
- Resource Owner — o usuário proprietário dos dados
- Client — a aplicação que solicita acesso
- Authorization Server — o servidor que emite os tokens
- Resource Server — o servidor que fornece os recursos protegidos
O que é JWT?
JWT (JSON Web Token) é um formato compacto e autossuficiente para transmitir dados entre partes na forma de um objeto JSON. O token é composto por três partes separadas por pontos:
header.payload.signature
Vantagens do JWT:
- Não requer armazenamento de sessões no servidor (stateless)
- Contém todas as informações necessárias (claims)
- É assinado para verificação de integridade
Implementação de autorização JWT em Go
Para trabalhar com JWT em Go, utilizaremos a biblioteca popular golang-jwt/jwt/v5. Instale-a com o comando:
go get github.com/golang-jwt/jwt/v5
Geração de token JWT
Vamos criar uma função para gerar tokens de acesso e refresh:
package auth
import (
"time"
"github.com/golang-jwt/jwt/v5"
)
var jwtSecret = []byte("your-secret-key")
type Claims struct {
UserID uint `json:"user_id"`
Email string `json:"email"`
jwt.RegisteredClaims
}
func GenerateAccessToken(userID uint, email string) (string, error) {
claims := &Claims{
UserID: userID,
Email: email,
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Now().Add(15 * time.Minute)),
IssuedAt: jwt.NewNumericDate(time.Now()),
Issuer: "myapp",
},
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
return token.SignedString(jwtSecret)
}
func GenerateRefreshToken(userID uint) (string, error) {
claims := &Claims{
UserID: userID,
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Now().Add(7 * 24 * time.Hour)),
IssuedAt: jwt.NewNumericDate(time.Now()),
},
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
return token.SignedString(jwtSecret)
}
Verificação de token JWT
Middleware para verificação do token em requisições HTTP:
package middleware
import (
"net/http"
"strings"
"github.com/gin-gonic/gin"
"myapp/auth"
)
func AuthMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
authHeader := c.GetHeader("Authorization")
if authHeader == "" {
c.JSON(http.StatusUnauthorized, gin.H{"error": "missing authorization header"})
c.Abort()
return
}
tokenString := strings.TrimPrefix(authHeader, "Bearer ")
if tokenString == authHeader {
```