package middleware import ( "errors" "fmt" "gitea.pena/PenaSide/codeword/internal/initialize" "github.com/golang-jwt/jwt/v5" "time" ) type JWT struct { privateKey []byte publicKey []byte algorithm *jwt.SigningMethodRSA expiresIn time.Duration issuer string audience string } func NewJWT(configuration *initialize.Config) *JWT { return &JWT{ privateKey: []byte(configuration.ExternalCfg.JwtCfg.PrivateKey), publicKey: []byte(configuration.ExternalCfg.JwtCfg.PublicKey), issuer: configuration.ExternalCfg.JwtCfg.Issuer, audience: configuration.ExternalCfg.JwtCfg.Audience, algorithm: jwt.SigningMethodRS256, expiresIn: 15 * time.Minute, } } func (j *JWT) Create(id string) (string, error) { privateKey, err := jwt.ParseRSAPrivateKeyFromPEM(j.privateKey) if err != nil { return "", fmt.Errorf("failed to parse private key on of : %w", err) } now := time.Now().UTC() claims := jwt.MapClaims{ "id": id, "exp": now.Add(j.expiresIn).Unix(), "aud": j.audience, "iss": j.issuer, } token, err := jwt.NewWithClaims(j.algorithm, claims).SignedString(privateKey) if err != nil { return "", fmt.Errorf("failed to sing on of : %w", err) } return token, nil } func (j *JWT) Validate(tokenString string) (string, error) { key, err := jwt.ParseRSAPublicKeyFromPEM(j.publicKey) if err != nil { return "", fmt.Errorf("failed to parse rsa public key on of : %w", err) } parseCallback := func(token *jwt.Token) (any, error) { if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok { return nil, fmt.Errorf("unexpected signing method: %s", token.Header["alg"]) } return key, nil } token, err := jwt.Parse( tokenString, parseCallback, jwt.WithAudience(j.audience), jwt.WithIssuer(j.issuer), ) if err != nil { return "", fmt.Errorf("failed to parse jwt token on of : %w", err) } claims, ok := token.Claims.(jwt.MapClaims) if !ok || !token.Valid { return "", errors.New("token is invalid on of ") } data, ok := claims["id"].(string) if !ok { return "", errors.New("data is empty or not a string on of ") } return data, nil }