first commit
This commit is contained in:
127
app/services/jwt_service.go
Normal file
127
app/services/jwt_service.go
Normal file
@@ -0,0 +1,127 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
configs "goGin/config"
|
||||
"time"
|
||||
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
)
|
||||
|
||||
// TokenTypeAccess sabiti, auth middleware'in beklediği token türünü temsil eder.
|
||||
const TokenTypeAccess = "access"
|
||||
|
||||
// JWTClaim, authorization middleware'inin beklediği claim yapısını temsil eder.
|
||||
// İleride ihtiyaç oldukça alanlar genişletilebilir.
|
||||
type JWTClaim struct {
|
||||
TokenType string
|
||||
IsAdmin bool
|
||||
UserID any
|
||||
}
|
||||
|
||||
// JWTService, JWT ile ilgili operasyonları kapsayan servis.
|
||||
type JWTService struct {
|
||||
secret []byte
|
||||
}
|
||||
|
||||
// NewJWTService yeni bir JWTService örneği döner.
|
||||
// Secret, config içindeki JWT_SECRET üzerinden okunur.
|
||||
func NewJWTService() *JWTService {
|
||||
secret := ""
|
||||
if configs.AppConfig != nil {
|
||||
secret = configs.AppConfig.JWTSecret
|
||||
}
|
||||
return &JWTService{
|
||||
secret: []byte(secret),
|
||||
}
|
||||
}
|
||||
|
||||
// ValidateToken verilen JWT'yi doğrular ve claim'leri döner.
|
||||
// HMAC (HS256 vb.) ile imzalanmış token'lar beklenir.
|
||||
func (s *JWTService) ValidateToken(tokenString string) (*JWTClaim, error) {
|
||||
if len(s.secret) == 0 {
|
||||
return nil, errors.New("jwt secret is not configured")
|
||||
}
|
||||
|
||||
token, err := jwt.Parse(tokenString, func(t *jwt.Token) (interface{}, error) {
|
||||
// Sadece HMAC algoritmalarına izin veriyoruz.
|
||||
if _, ok := t.Method.(*jwt.SigningMethodHMAC); !ok {
|
||||
return nil, fmt.Errorf("unexpected signing method: %v", t.Header["alg"])
|
||||
}
|
||||
return s.secret, nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !token.Valid {
|
||||
return nil, errors.New("invalid token")
|
||||
}
|
||||
|
||||
claims, ok := token.Claims.(jwt.MapClaims)
|
||||
if !ok {
|
||||
return nil, errors.New("invalid token claims")
|
||||
}
|
||||
|
||||
// Token tipi (access / refresh vs.)
|
||||
var tokenType string
|
||||
if v, ok := claims["token_type"].(string); ok {
|
||||
tokenType = v
|
||||
} else if v, ok := claims["tokenType"].(string); ok {
|
||||
tokenType = v
|
||||
}
|
||||
|
||||
// Yönetici flag'i
|
||||
var isAdmin bool
|
||||
if v, ok := claims["is_admin"]; ok {
|
||||
switch vv := v.(type) {
|
||||
case bool:
|
||||
isAdmin = vv
|
||||
case float64:
|
||||
isAdmin = vv != 0
|
||||
}
|
||||
} else if v, ok := claims["isAdmin"]; ok {
|
||||
if vv, ok2 := v.(bool); ok2 {
|
||||
isAdmin = vv
|
||||
}
|
||||
}
|
||||
|
||||
// Kullanıcı ID'si (sub claim'i üzerinden)
|
||||
var userID any
|
||||
if v, ok := claims["sub"]; ok {
|
||||
userID = v
|
||||
} else if v, ok := claims["user_id"]; ok {
|
||||
userID = v
|
||||
}
|
||||
|
||||
return &JWTClaim{
|
||||
TokenType: tokenType,
|
||||
IsAdmin: isAdmin,
|
||||
UserID: userID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GenerateToken creates a short-lived access token
|
||||
func (s *JWTService) GenerateToken(userID uint, isAdmin bool) (string, error) {
|
||||
claims := jwt.MapClaims{
|
||||
"sub": userID,
|
||||
"is_admin": isAdmin,
|
||||
"token_type": TokenTypeAccess,
|
||||
"exp": jwt.NewNumericDate(time.Now().Add(time.Duration(configs.AppConfig.AccessTokenExpireMinutes) * time.Minute)),
|
||||
"iat": jwt.NewNumericDate(time.Now()),
|
||||
}
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
return token.SignedString(s.secret)
|
||||
}
|
||||
|
||||
// GenerateRefreshToken creates a long-lived refresh token
|
||||
func (s *JWTService) GenerateRefreshToken(userID uint) (string, error) {
|
||||
claims := jwt.MapClaims{
|
||||
"sub": userID,
|
||||
"token_type": "refresh",
|
||||
"exp": jwt.NewNumericDate(time.Now().Add(time.Duration(configs.AppConfig.RefreshTokenExpireDays) * 24 * time.Hour)),
|
||||
"iat": jwt.NewNumericDate(time.Now()),
|
||||
}
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
return token.SignedString(s.secret)
|
||||
}
|
||||
Reference in New Issue
Block a user