github.com/Jeffail/benthos/v3@v3.65.0/lib/util/http/auth/jwt.go (about) 1 package auth 2 3 import ( 4 "crypto/rsa" 5 "fmt" 6 "net/http" 7 "os" 8 "sync" 9 10 "github.com/golang-jwt/jwt" 11 ) 12 13 //------------------------------------------------------------------------------ 14 15 // JWTConfig holds the configuration parameters for an JWT exchange. 16 type JWTConfig struct { 17 Enabled bool `json:"enabled" yaml:"enabled"` 18 Claims jwt.MapClaims `json:"claims" yaml:"claims"` 19 SigningMethod string `json:"signing_method" yaml:"signing_method"` 20 PrivateKeyFile string `json:"private_key_file" yaml:"private_key_file"` 21 22 // internal private fields 23 rsaKeyMx *sync.Mutex 24 rsaKey **rsa.PrivateKey 25 } 26 27 // NewJWTConfig returns a new JWTConfig with default values. 28 func NewJWTConfig() JWTConfig { 29 var privKey *rsa.PrivateKey 30 return JWTConfig{ 31 Enabled: false, 32 Claims: map[string]interface{}{}, 33 SigningMethod: "", 34 PrivateKeyFile: "", 35 rsaKeyMx: &sync.Mutex{}, 36 rsaKey: &privKey, 37 } 38 } 39 40 //------------------------------------------------------------------------------ 41 42 // Sign method to sign an HTTP request for an JWT exchange. 43 func (j JWTConfig) Sign(req *http.Request) error { 44 if !j.Enabled { 45 return nil 46 } 47 48 if err := j.parsePrivateKey(); err != nil { 49 return err 50 } 51 52 var bearer *jwt.Token 53 switch j.SigningMethod { 54 case "RS256": 55 bearer = jwt.NewWithClaims(jwt.SigningMethodRS256, j.Claims) 56 case "RS384": 57 bearer = jwt.NewWithClaims(jwt.SigningMethodRS384, j.Claims) 58 case "RS512": 59 bearer = jwt.NewWithClaims(jwt.SigningMethodRS512, j.Claims) 60 default: 61 return fmt.Errorf("jwt signing method %s not acepted. Try with RS256, RS384 or RS512", j.SigningMethod) 62 } 63 64 ss, err := bearer.SignedString(*j.rsaKey) 65 if err != nil { 66 return fmt.Errorf("failed to sign jwt: %v", err) 67 } 68 69 req.Header.Set("Authorization", "Bearer "+ss) 70 return nil 71 } 72 73 // parsePrivateKey parses once the RSA private key. 74 // Needs mutex locking as Sign might be called by parallel threads. 75 func (j JWTConfig) parsePrivateKey() error { 76 j.rsaKeyMx.Lock() 77 defer j.rsaKeyMx.Unlock() 78 79 if *j.rsaKey != nil { 80 return nil 81 } 82 83 privateKey, err := os.ReadFile(j.PrivateKeyFile) 84 if err != nil { 85 return fmt.Errorf("failed to read private key: %v", err) 86 } 87 88 *j.rsaKey, err = jwt.ParseRSAPrivateKeyFromPEM(privateKey) 89 if err != nil { 90 return fmt.Errorf("failed to parse private key: %v", err) 91 } 92 93 return nil 94 } 95 96 //------------------------------------------------------------------------------