Files
test_deploy/internal/auth/keycloak/jwt.go
Alex Shevchuk d84487d238 1
2025-08-18 17:12:04 +03:00

77 lines
1.7 KiB
Go

package keycloak
import (
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/auth"
"github.com/golang-jwt/jwt/v5"
"time"
)
type TokenManager interface {
GetUserInfoFromToken(token string) (*auth.UserInfoFromToken, error)
VerifyEmailToken(token string, expectedUserID string) error
}
type tokenManager struct {
parser *jwt.Parser
}
func NewJWTManager() TokenManager {
return &tokenManager{
parser: jwt.NewParser(),
}
}
func (t *tokenManager) GetUserInfoFromToken(token string) (*auth.UserInfoFromToken, error) {
userToken, _, err := t.parser.ParseUnverified(token, jwt.MapClaims{})
if err != nil {
return nil, ErrInvalidToken
}
if claims, ok := userToken.Claims.(jwt.MapClaims); ok {
resp := auth.UserInfoFromToken{}
resp.UserId, ok = claims["sub"].(string)
if !ok {
return nil, ErrInvalidToken
}
return &resp, nil
}
return nil, ErrInvalidToken
}
func (t *tokenManager) VerifyEmailToken(token string, expectedUserID string) error {
// Parse token without verification (we'll verify signature manually)
parsedToken, _, err := t.parser.ParseUnverified(token, jwt.MapClaims{})
if err != nil {
return ErrInvalidToken
}
// Extract claims
claims, ok := parsedToken.Claims.(jwt.MapClaims)
if !ok {
return ErrInvalidToken
}
// Check if token is for email verification
purpose, ok := claims["purpose"].(string)
if !ok || purpose != "email_verification" {
return ErrInvalidToken
}
// Check if subject matches expected user ID
sub, ok := claims["sub"].(string)
if !ok || sub != expectedUserID {
return ErrInvalidToken
}
// Check expiration
exp, ok := claims["exp"].(float64)
if !ok || float64(time.Now().Unix()) > exp {
return ErrInvalidToken
}
return nil
}