mirror of
https://github.com/hanzoai/metrics.git
synced 2026-10-30 20:03:39 +00:00
### Describe Your Changes It was [decided](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9439#issuecomment-3612299461) that OIDC authentication in vmauth will be part of open source repo. That requires opensourcing lib/jwt. PR does not contain any changes in logic, just copy-paste from enterprise repository. Related to https://github.com/VictoriaMetrics/VictoriaMetrics/issues/9439 ### Checklist The following checks are **mandatory**: - [ ] My change adheres to [VictoriaMetrics contributing guidelines](https://docs.victoriametrics.com/victoriametrics/contributing/#pull-request-checklist). - [ ] My change adheres to [VictoriaMetrics development goals](https://docs.victoriametrics.com/victoriametrics/goals/).
136 lines
3.3 KiB
Go
136 lines
3.3 KiB
Go
package jwt
|
|
|
|
import (
|
|
"crypto/ecdsa"
|
|
"crypto/rsa"
|
|
"fmt"
|
|
)
|
|
|
|
var (
|
|
// ErrSignatureVerificationFailed token signature verification failed
|
|
ErrSignatureVerificationFailed = fmt.Errorf("failed to verify token signature")
|
|
// ErrSignatureAlgorithmNotSupported signature algorithm not supported
|
|
ErrSignatureAlgorithmNotSupported = fmt.Errorf("signature algorithm verification not supported, supported algorithms: RS256, RS384, RS512, PS256, PS384, PS512, ES256, ES384, ES512")
|
|
)
|
|
|
|
// VerifierPool is a pool of verifiers for different algorithms
|
|
type VerifierPool struct {
|
|
rsaVerifiers map[string][]Verifier
|
|
psVerifiers map[string][]Verifier
|
|
esVerifiers map[string][]Verifier
|
|
}
|
|
|
|
// NewVerifierPool creates a new verifier pool for a set of keys
|
|
func NewVerifierPool(keys []any) (*VerifierPool, error) {
|
|
rsaVerifiers := make(map[string][]Verifier)
|
|
psVerifiers := make(map[string][]Verifier)
|
|
esVerifiers := make(map[string][]Verifier)
|
|
|
|
rsaAlgs := []string{"RS256", "RS384", "RS512"}
|
|
psAlgs := []string{"PS256", "PS384", "PS512"}
|
|
|
|
for _, key := range keys {
|
|
switch k := key.(type) {
|
|
case *rsa.PublicKey:
|
|
for _, alg := range rsaAlgs {
|
|
verifier, err := newVerifierRS(Algorithm(alg), k)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to create RSA verifier for algorithm %s: %w", alg, err)
|
|
}
|
|
rsaVerifiers[alg] = append(rsaVerifiers[alg], verifier)
|
|
}
|
|
|
|
for _, alg := range psAlgs {
|
|
verifier, err := newVerifierPS(Algorithm(alg), k)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to create RSA-PSS verifier for algorithm %s: %w", alg, err)
|
|
}
|
|
psVerifiers[alg] = append(psVerifiers[alg], verifier)
|
|
}
|
|
|
|
case *ecdsa.PublicKey:
|
|
alg := getAlgorithmForKey(k)
|
|
if alg == "" {
|
|
return nil, fmt.Errorf("failed to create ECDSA verifier: unsupported key")
|
|
}
|
|
|
|
verifier, err := newVerifierES(alg, k)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to create ES verifier for algorithm %s: %w", alg, err)
|
|
}
|
|
esVerifiers[string(alg)] = append(esVerifiers[string(alg)], verifier)
|
|
|
|
default:
|
|
return nil, fmt.Errorf("unknown key type: %T", key)
|
|
}
|
|
}
|
|
|
|
return &VerifierPool{
|
|
rsaVerifiers: rsaVerifiers,
|
|
psVerifiers: psVerifiers,
|
|
esVerifiers: esVerifiers,
|
|
}, nil
|
|
}
|
|
|
|
func (vp *VerifierPool) getVerifiers(alg string) []Verifier {
|
|
if len(alg) < 2 {
|
|
return nil
|
|
}
|
|
|
|
switch alg[:2] {
|
|
case "RS":
|
|
return vp.getRSVerifiers(alg)
|
|
case "PS":
|
|
return vp.getPSVerifiers(alg)
|
|
case "ES":
|
|
return vp.getESVerifiers(alg)
|
|
default:
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// Verify verifies a token signature by using keys provided to verifier pool
|
|
func (vp *VerifierPool) Verify(token *Token) error {
|
|
verifiers := vp.getVerifiers(token.header.Alg)
|
|
if verifiers == nil {
|
|
return ErrSignatureAlgorithmNotSupported
|
|
}
|
|
|
|
for _, verifier := range verifiers {
|
|
err := verifier.Verify(token)
|
|
if err == nil {
|
|
// Token verified, returning success immediately
|
|
return nil
|
|
}
|
|
}
|
|
|
|
return ErrSignatureVerificationFailed
|
|
}
|
|
|
|
func (vp *VerifierPool) getRSVerifiers(alg string) []Verifier {
|
|
v, ok := vp.rsaVerifiers[alg]
|
|
if ok {
|
|
return v
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (vp *VerifierPool) getPSVerifiers(alg string) []Verifier {
|
|
v, ok := vp.psVerifiers[alg]
|
|
if ok {
|
|
return v
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (vp *VerifierPool) getESVerifiers(alg string) []Verifier {
|
|
v, ok := vp.esVerifiers[alg]
|
|
if ok {
|
|
return v
|
|
}
|
|
|
|
return nil
|
|
}
|