OAuth 2.0 e autorização JWT em Go: da teoria à prática
\n\nAplicações web e APIs modernas raramente funcionam sem um sistema robusto de autenticação e autorização. Dois padrões — OAuth 2.0 e JWT (JSON Web Tokens) — tornaram-se os padrões de facto no mundo do desenvolvimento. Neste artigo, com exemplos práticos, vamos analisar como implementar a autorização OAuth 2.0 usando JWT na linguagem Go (Golang).
\n\nCriaremos um servidor REST API simples que emitirá tokens JWT após autenticação bem-sucedida através de um provedor OAuth 2.0 (por exemplo, Google) e os verificará em cada requisição.
\n\n1. Fundamentos de OAuth 2.0 e JWT
\n\nAntes de escrever código, vamos entender rapidamente os termos.
\n\n- \n
- OAuth 2.0 — um protocolo de autorização que permite que usuários concedam a terceiros acesso limitado aos seus recursos sem compartilhar login e senha. Papéis principais: Resource Owner (usuário), Client (nossa aplicação), Authorization Server (servidor que emite tokens), Resource Server (servidor com dados protegidos). \n
- JWT — um formato de token compacto e seguro para URL, composto por três partes: header, payload e signature. O JWT pode conter quaisquer dados (claims) e é assinado com uma chave secreta ou um par de chaves RSA. \n
Na nossa implementação, o OAuth 2.0 será usado para obter um token de identidade do provedor (Google) e, em seguida, geraremos nosso próprio JWT para uso posterior com nossa API.
\n\n2. Configuração do projeto e dependências
\n\nVamos criar um novo projeto em Go e instalar os pacotes necessários:
\n\nmkdir go-oauth-jwt\ncd go-oauth-jwt\ngo mod init example.com/go-oauth-jwt\ngo get github.com/gin-gonic/gin\ngo get github.com/golang-jwt/jwt/v5\ngo get golang.org/x/oauth2\ngo get golang.org/x/oauth2/google\n\nUsaremos:
\n- \n
- Gin — um framework HTTP rápido para Go. \n
- golang-jwt — biblioteca para trabalhar com JWT. \n
- oauth2 — biblioteca padrão do Go para OAuth 2.0. \n
Você também precisará registrar um aplicativo no Google Cloud Console, criar um OAuth 2.0 Client ID e Secret, e especificar a Redirect URI (por exemplo, http://localhost:8080/auth/google/callback).
3. Implementação do login OAuth 2.0 via Google
\n\nVamos começar criando a configuração OAuth 2.0 e os endpoints para login e callback.
\n\npackage main\n\nimport (\n "crypto/rand"\n "encoding/base64"\n "net/http"\n "os"\n\n "github.com/gin-gonic/gin"\n "golang.org/x/oauth2"\n "golang.org/x/oauth2/google"\n)\n\nvar (\n googleOauthConfig *oauth2.Config\n oauthStateString string\n)\n\nfunc init() {\n googleOauthConfig = &oauth2.Config{\n RedirectURL: "http://localhost:8080/auth/google/callback",\n ClientID: os.Getenv("GOOGLE_CLIENT_ID"),\n ClientSecret: os.Getenv("GOOGLE_CLIENT_SECRET"),\n Scopes: []string{"https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.profile"},\n Endpoint: google.Endpoint,\n }\n // Geramos um token state aleatório para proteção contra CSRF\n b := make([]byte, 32)\n rand.Read(b)\n oauthStateString = base64.StdEncoding.EncodeToString(b)\n}\n\nfunc main() {\n r := gin.Default()\n\n r.GET("/auth/google/login", handleGoogleLogin)\n r.GET("/auth/google/callback", handleGoogleCallback)\n\n r.Run(":8080")\n}\n\nfunc handleGoogleLogin(c *gin.Context) {\n url := googleOauthConfig.AuthCodeURL(oauthStateString)\n c.Redirect(http.StatusTemporaryRedirect, url)\n}\n\nfunc handleGoogleCallback(c *gin.Context) {\n state := c.Query("state")\n if state != oauthStateString {\n c.JSON(http.StatusBadRequest, gin.H{"error": "invalid oauth state"})\n return\n }\n\n code := c.Query("code")\n token, err := googl