Files
Rango/pkg/auth/validator.go
2026-08-13 20:20:47 +03:30

84 lines
2.3 KiB
Go

package auth
import (
"crypto/ed25519"
"crypto/rsa"
"fmt"
"os"
pkgjwt "github.com/openware/pkg/jwt"
)
const (
ValidatorRSA = "rsa"
ValidatorEdDSA = "eddsa"
)
// Validator verifies Barong JWT tokens using RS256 or EdDSA depending on configured key material.
type Validator struct {
Mode string
RSA *rsa.PublicKey
EdDSA ed25519.PublicKey
}
type Claims struct {
UID string
Role string
}
// LoadValidator reads JWT_PUBLIC_KEY (base64 PEM) or -pubKey file path.
// OpenDAX / Barong 2.6 uses RS256; upstream Rango 3.1.2+ defaults to EdDSA.
func LoadValidator(pubKeyPath string) (Validator, error) {
if encPem := os.Getenv("JWT_PUBLIC_KEY"); encPem != "" {
rsaStore := KeyStore{}
if err := rsaStore.LoadPublicKeyFromString(encPem); err == nil && rsaStore.PublicKey != nil {
return Validator{Mode: ValidatorRSA, RSA: rsaStore.PublicKey}, nil
}
edStore := pkgjwt.KeyStoreEdDSA{}
if err := edStore.LoadPublicKeyFromString(encPem); err == nil && edStore.PublicKey != nil {
return Validator{Mode: ValidatorEdDSA, EdDSA: edStore.PublicKey}, nil
}
return Validator{}, fmt.Errorf("JWT_PUBLIC_KEY is neither a valid RSA nor EdDSA public key")
}
rsaStore := KeyStore{}
if err := rsaStore.LoadPublicKeyFromFile("config/rsa-key.pub"); err == nil && rsaStore.PublicKey != nil {
return Validator{Mode: ValidatorRSA, RSA: rsaStore.PublicKey}, nil
}
edStore := pkgjwt.KeyStoreEdDSA{}
if err := edStore.LoadPublicKeyFromFile(pubKeyPath); err != nil {
return Validator{}, fmt.Errorf("load public key from %q: %w", pubKeyPath, err)
}
if edStore.PublicKey == nil {
return Validator{}, fmt.Errorf("public key not loaded from %q", pubKeyPath)
}
return Validator{Mode: ValidatorEdDSA, EdDSA: edStore.PublicKey}, nil
}
func (v Validator) ParseAndValidate(token string) (Claims, error) {
if token == "" {
return Claims{}, fmt.Errorf("missing token")
}
switch v.Mode {
case ValidatorRSA:
auth, err := ParseAndValidate(token, v.RSA)
if err != nil {
return Claims{}, err
}
return Claims{UID: auth.UID, Role: auth.Role}, nil
case ValidatorEdDSA:
auth, err := pkgjwt.ParseAndValidateEdDSA(token, v.EdDSA)
if err != nil {
return Claims{}, err
}
return Claims{UID: auth.UID, Role: auth.Role}, nil
default:
return Claims{}, fmt.Errorf("unknown validator mode %q", v.Mode)
}
}