package auth import ( "strings" "time" "aidanwoods.dev/go-paseto" "github.com/FernandoJVideira/simple_bank/internal/config" "github.com/google/uuid" ) type PasetoMaker struct { config config.Config symmetricKey paseto.V4SymmetricKey implicit []byte } func NewPasetoMaker(config config.Config) (Maker, error) { maker := &PasetoMaker{ config: config, symmetricKey: paseto.NewV4SymmetricKey(), implicit: []byte("implicit"), } return maker, nil } func (maker *PasetoMaker) CreateToken(username string, role string, duration time.Duration) (string, *Payload, error) { payload, err := NewPayload(username, role, duration) if err != nil { return "", nil, err } token := paseto.NewToken() token.SetIssuedAt(payload.IssuedAt) token.SetExpiration(payload.ExpiredAt) token.SetString("role", payload.Role) token.SetAudience(maker.config.TokenAUD) token.SetIssuer(maker.config.TokenISS) token.SetSubject(payload.Username) token.SetJti(payload.ID.String()) signedToken := token.V4Encrypt(maker.symmetricKey, maker.implicit) return signedToken, payload, nil } func (maker *PasetoMaker) VerifyToken(token string) (*Payload, error) { parser := paseto.NewParser() parser.AddRule(paseto.NotExpired()) parsedToken, err := parser.ParseV4Local(maker.symmetricKey, token, maker.implicit) if err != nil { if strings.Contains(err.Error(), "token has expired") { return nil, ErrExpiredToken } return nil, ErrInvalidToken } payload, err := parseClaims(parsedToken) if err != nil { return nil, err } return payload, nil } func parseClaims(t *paseto.Token) (*Payload, error) { id, err := t.GetJti() if err != nil { return nil, ErrInvalidToken } username, err := t.GetSubject() if err != nil { return nil, ErrInvalidToken } role, err := t.GetString("role") if err != nil { return nil, ErrInvalidToken } issuedAt, err := t.GetIssuedAt() if err != nil { return nil, ErrInvalidToken } expiredAt, err := t.GetExpiration() if err != nil { return nil, ErrInvalidToken } payload := &Payload{ ID: uuid.MustParse(id), Username: username, Role: role, IssuedAt: issuedAt, ExpiredAt: expiredAt, } return payload, nil }