Authorization and Authentication in Go (Golang)
Security of web applications in Go starts with the proper implementation of authentication (verifying "who you are") and authorization (verifying "what you are allowed to do") mechanisms. In this article, we will cover three main approaches: JWT (JSON Web Tokens), OAuth2, and session-based authentication. Each of them has its own use cases, advantages, and disadvantages.
1. Authentication with JWT (JSON Web Token)
JWT is a compact and self-contained way to transmit information between parties as a JSON object. In Go, the library github.com/golang-jwt/jwt/v5 is most commonly used for working with JWT.
Installation:
go get github.com/golang-jwt/jwt/v5Example of creating and validating JWT:
package main
import (\t"fmt"\t"time"\t"github.com/golang-jwt/jwt/v5")
var jwtSecret = []byte("my_secret_key")
// Creating a tokenfunc createToken(userID string) (string, error) {\tclaims := jwt.MapClaims{\t\t"user_id": userID,\t\t"exp": time.Now().Add(24 * time.Hour).Unix(),\t}\ttoken := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)\treturn token.SignedString(jwtSecret)}
// Validating a tokenfunc validateToken(tokenString string) (string, error) {\ttoken, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {\t\tif _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {\t\t\treturn nil, fmt.Errorf("invalid signing method")\t\t}\t\treturn jwtSecret, nil\t})
\tif err != nil {\t\treturn "", err\t}
\tif claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {\t\treturn claims["user_id"].(string), nil\t}\treturn "", fmt.Errorf("invalid token")}
func main() {\ttoken, _ := createToken("user123")\tfmt.Println("Token:", token)
\tuserID, err := validateToken(token)\tif err != nil {\t\tfmt.Println("Error:", err)\t} else {\t\tfmt.Println("User:", userID)\t}}2. Authentication via OAuth2
OAuth2 is a delegated access protocol that allows users to log in through third-party services (Google, GitHub, VK, etc.). In Go, the library golang.org/x/oauth2 is popular.
Installation:
go get golang.org/x/oauth2Example OAuth2 with Google:
package main
import (\t"context"\t"encoding/json"\t"fmt"\t"net/http"\t"golang.org/x/oauth2"\t"golang.org/x/oauth2/google")
var googleOauthConfig = &oauth2.Config{\tRedirectURL: "http://localhost:8080/callback",\tClientID: "your-client-id",\tClientSecret: "your-client-secret",\tScopes: []string{"https://www.googleapis.com/auth/userinfo.email"},\tEndpoint: google.Endpoint,}
func handleGoogleLogin(w http.ResponseWriter, r *http.Request) {\turl := googleOauthConfig.AuthCodeURL("state-token")\thttp.Redirect(w, r, url, http.StatusTemporaryRedirect)}
func handleCallback(w http.ResponseWriter, r *http.Request) {\tcode := r.URL.Query().Get("code")\ttoken, err := googleOauthConfig.Exchange(context.Background(), code)\tif err != nil {\t\thttp.Error(w, "Token exchange error", http.StatusInternalServerError)\t\treturn\t}
\t// Getting user data\tclient := googleOauthConfig.Client(context.Background(), token)\tresp, _ := client.Get("https://www.googleapis.com/oauth2/v2/userinfo")\tdefer resp.Body.Close()
\tvar userInfo map[string]interface{}\tjson.NewDecoder(resp.Body).Decode(&userInfo)\tfmt.Fprintf(w, "Email: %v", userInfo["email"])}
func main() {\thttp.HandleFunc("/auth/google", handleGoogleLogin)\thttp.HandleFunc("/callback", handleCallback)\thttp.ListenAndServe(":8080", nil)}3. Session-based Authentication
A classic approach using cookies and server-side sessions. In Go, it is often used...