Go - Auth (JWT)

Beginner 10/10 Teacher 10/10 Architect 10/10

JWT Authentication

JSON Web Tokens (JWT) are signed tokens that assert claims (e.g., user ID, roles). Commonly used for stateless auth.

Try it: Generate an HMAC-SHA256 JWT in code and verify it.

Sign (HMAC-SHA256) without third-party libs

package main

import (
  "crypto/hmac"
  "crypto/sha256"
  "encoding/base64"
  "encoding/json"
  "fmt"
  "strings"
  "time"
)

type header struct{ Alg, Typ string }
type claims struct{ Sub string; Exp int64 }

func b64url(b []byte) string { return strings.TrimRight(base64.URLEncoding.EncodeToString(b), "=") }

func main(){
  secret := []byte("supersecret")
  h := header{Alg:"HS256", Typ:"JWT"}
  c := claims{Sub:"user-123", Exp: time.Now().Add(10*time.Minute).Unix()}
  hb, _ := json.Marshal(h)
  cb, _ := json.Marshal(c)
  part1 := b64url(hb)
  part2 := b64url(cb)
  signingInput := part1 + "." + part2
  mac := hmac.New(sha256.New, secret)
  mac.Write([]byte(signingInput))
  sig := b64url(mac.Sum(nil))
  token := signingInput + "." + sig
  fmt.Println(token)
}

Verify

func verify(token string, secret []byte) (claims, bool){
  var c claims
  parts := strings.Split(token, ".")
  if len(parts) != 3 { return c, false }
  signingInput := parts[0] + "." + parts[1]
  mac := hmac.New(sha256.New, secret)
  mac.Write([]byte(signingInput))
  expected := b64url(mac.Sum(nil))
  if expected != parts[2] { return c, false }
  // decode claims
  b, _ := base64.URLEncoding.WithPadding(base64.NoPadding).DecodeString(parts[1])
  json.Unmarshal(b, &c)
  if time.Now().Unix() > c.Exp { return c, false }
  return c, true
}

HTTP Middleware (concept)

func Auth(next http.Handler) http.Handler {
  return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request){
    auth := r.Header.Get("Authorization")
    if !strings.HasPrefix(auth, "Bearer ") { http.Error(w, "missing", 401); return }
    tok := strings.TrimPrefix(auth, "Bearer ")
    c, ok := verify(tok, []byte("supersecret"))
    if !ok { http.Error(w, "invalid", 401); return }
    // attach claims to context if needed
    next.ServeHTTP(w, r)
  })
}

Common errors

  • Not checking token expiration (exp).
  • Confusing encoding (URL-safe base64 without padding) vs standard base64.
  • Leaking secrets in logs. Never log JWTs in production.

Practice

  • Add iat (issued at) and nbf (not before) claims and enforce them.
  • Write tests for signature tampering and expired tokens.

Quick quiz

  1. Is JWT encryption the same as signing?
Show answer No. Signing ensures integrity; encryption ensures confidentiality. Most JWTs are signed, not encrypted.