84 lines
2.3 KiB
Go
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)
|
|
}
|
|
}
|