Files
Authentication/helper/extract_email_from_token.go
2026-03-16 09:27:08 +08:00

90 lines
2.7 KiB
Go

package helper
import (
"authentication/models"
"encoding/pem"
"errors"
"log"
"os"
"strings"
"github.com/golang-jwt/jwt/v5"
)
func ExtractEmailFromToken(tokenString string) (string, error) {
// Remove "Bearer " prefix if it exists
tokenString = strings.TrimPrefix(tokenString, "Bearer ")
// Handle null/empty token cases
if tokenString == "" || tokenString == "null" || tokenString == "undefined" {
return "", errors.New("no valid token provided")
}
token, err := jwt.ParseWithClaims(tokenString, &models.AccessToken{}, func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
return nil, errors.New("unexpected signing method: expected RSA")
}
publicKeyPEM := os.Getenv("JWT_PUBLIC_KEY")
if publicKeyPEM == "" {
return nil, errors.New("JWT public key not set")
}
block, _ := pem.Decode([]byte(publicKeyPEM))
if block == nil {
return nil, errors.New("failed to decode PEM block")
}
pubKey, err := jwt.ParseRSAPublicKeyFromPEM([]byte(publicKeyPEM))
if err != nil {
return nil, errors.New("failed to parse RSA public key")
}
return pubKey, nil
})
if err == nil && token.Valid {
if claims, ok := token.Claims.(*models.AccessToken); ok {
if claims.Email != "" && strings.Contains(claims.Email, "@") {
log.Printf("Successfully extracted email from AccessToken: %s", claims.Email)
return claims.Email, nil
}
}
}
// If AccessToken parsing failed, try MapClaims for backward compatibility
log.Printf("AccessToken parsing failed: %v, trying MapClaims fallback", err)
token, err = jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
return nil, errors.New("unexpected signing method: expected RSA")
}
publicKeyPEM := os.Getenv("JWT_PUBLIC_KEY")
if publicKeyPEM == "" {
return nil, errors.New("JWT public key not set")
}
block, _ := pem.Decode([]byte(publicKeyPEM))
if block == nil {
return nil, errors.New("failed to decode PEM block")
}
pubKey, err := jwt.ParseRSAPublicKeyFromPEM([]byte(publicKeyPEM))
if err != nil {
return nil, errors.New("failed to parse RSA public key")
}
return pubKey, nil
})
if err != nil {
log.Printf("MapClaims parsing also failed: %v", err)
return "", errors.New("invalid token signature")
}
// Extract claims from MapClaims
claims, ok := token.Claims.(jwt.MapClaims)
if !ok || !token.Valid {
return "", errors.New("invalid token claims")
}
if email, ok := claims["email"].(string); ok && strings.Contains(email, "@") {
log.Printf("Successfully extracted email from MapClaims: %s", email)
return email, nil
}
return "", errors.New("email not found in token")
}