Mert Tosun
← Yazılar
Go ile JWT Authentication: Access Token, Refresh Token ve Güvenli Saklama

Go ile JWT Authentication: Access Token, Refresh Token ve Güvenli Saklama

Mert TosunGo

JWT (JSON Web Token), mikroservislerde ve tek parça uygulamalarda kimlik taşımak için en yaygın formatlardan biri. Ancak “JWT kullandık, güvenlik bitti” demek mümkün değil: saklama, süre, yenileme ve iptal stratejisi olmadan üretim ortamında risk büyür.

Bu yazı, Go ile JWT authentication kurmak isteyen geliştiriciler için access / refresh ayrımına ve güvenli pratiklere odaklanır.

JWT kısa hatırlatma

Üç parça: header.payload.signature. İmzayı sadece sunucu (veya güvenilir anahtar sahibi) üretir; payload genelde base64url ile kodlanmış JSON’dur ve şifrelenmiş değildir — içeriği herkes okuyabilir; bu yüzden hassas veri koymayın.


Access token vs refresh token

Access token Refresh token
Ömür Kısa (dakika–saat) Uzun (gün–hafta), ama dikkatli
Kullanım API isteklerinde Yeni access almak için
Saklama Bellek / kısa süreli Güvenli depo, rotasyon

Kural: Access token çalınsa bile pencerenin kısa olması zararı sınırlar. Refresh token çok daha kritiktir.


Go’da imzalama ve doğrulama

Yaygın kütüphane: github.com/golang-jwt/jwt/v5.

import "github.com/golang-jwt/jwt/v5"

type Claims struct {
    UserID string `json:"uid"`
    jwt.RegisteredClaims
}

func SignAccess(userID string, secret []byte, ttl time.Duration) (string, error) {
    claims := Claims{
        UserID: userID,
        RegisteredClaims: jwt.RegisteredClaims{
            ExpiresAt: jwt.NewNumericDate(time.Now().Add(ttl)),
            IssuedAt:  jwt.NewNumericDate(time.Now()),
        },
    }
    t := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
    return t.SignedString(secret)
}

Doğrulama:

func Parse(tokenString string, secret []byte) (*Claims, error) {
    tok, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(t *jwt.Token) (interface{}, error) {
        return secret, nil
    })
    if err != nil { return nil, err }
    if c, ok := tok.Claims.(*Claims); ok && tok.Valid {
        return c, nil
    }
    return nil, jwt.ErrSignatureInvalid
}

HS256 paylaşımlı giz; mikroservislerde çoklu servis için RS256 (asimetrik) ile public key ile doğrulama sık tercih edilir.


Refresh token’ı güvenli tutma

Yapmayın: Refresh token’ı localStorage’a yazmak (XSS riski).

Daha iyi:

  • HttpOnly + Secure + SameSite çerezde refresh token
  • Access token’ı kısa ömürlü tutup bellekte veya aynı çerez stratejisiyle vermek
  • Refresh token rotation: Her kullanımda yeni refresh üret, eskiyi geçersiz kıl; çalınan eski token tek kullanımlık olmasın

Sunucu tarafında refresh kayıtlarını Redis veya veritabanında tutup iptal listesi (logout, şüpheli aktivite) uygulayın.


Yaygın hatalar

  1. Uzun ömürlü access token ve içinde fazla claim
  2. İmzayı doğrulamadan payload’a güvenmek
  3. Alg confusion: Sunucunun alg: none veya beklenmeyen algoritmaları kabul etmesi — kütüphane ayarlarını sıkılaştırın
  4. Sızdırılmış secret — ortam değişkenleri ve secret manager kullanın

Özet

  • Go ile JWT authentication için net bir access / refresh ayrımı ve kısa access ömrü şart.
  • Refresh token’ı HttpOnly cookie + rotasyon ile koruyun.
  • Üretimde mümkünse RS256 ve merkezi anahtar yönetimi düşünün.

Bu konu, rate limiting ve API güvenliği için Redis ile rate limiting yazısıyla birlikte düşünülmeli; giriş noktasında limit + kimlik birlikte çalışır.