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  //------------------------------------------------------------------------------