github.com/Jeffail/benthos/v3@v3.65.0/lib/util/http/auth/oauth.go (about)

     1  package auth
     2  
     3  import (
     4  	"crypto/hmac"
     5  	"crypto/sha1"
     6  	"encoding/base64"
     7  	"fmt"
     8  	"math/rand"
     9  	"net/http"
    10  	"net/url"
    11  	"strconv"
    12  	"time"
    13  )
    14  
    15  //------------------------------------------------------------------------------
    16  
    17  // OAuthConfig holds the configuration parameters for an OAuth exchange.
    18  type OAuthConfig struct {
    19  	Enabled           bool   `json:"enabled" yaml:"enabled"`
    20  	ConsumerKey       string `json:"consumer_key" yaml:"consumer_key"`
    21  	ConsumerSecret    string `json:"consumer_secret" yaml:"consumer_secret"`
    22  	AccessToken       string `json:"access_token" yaml:"access_token"`
    23  	AccessTokenSecret string `json:"access_token_secret" yaml:"access_token_secret"`
    24  	RequestURL        string `json:"request_url" yaml:"request_url"`
    25  }
    26  
    27  // NewOAuthConfig returns a new OAuthConfig with default values.
    28  func NewOAuthConfig() OAuthConfig {
    29  	return OAuthConfig{
    30  		Enabled:           false,
    31  		ConsumerKey:       "",
    32  		ConsumerSecret:    "",
    33  		AccessToken:       "",
    34  		AccessTokenSecret: "",
    35  		RequestURL:        "",
    36  	}
    37  }
    38  
    39  //------------------------------------------------------------------------------
    40  
    41  // Sign method to sign an HTTP request for an OAuth exchange.
    42  func (oauth OAuthConfig) Sign(req *http.Request) error {
    43  	if !oauth.Enabled {
    44  		return nil
    45  	}
    46  
    47  	nonceGenerator := rand.New(rand.NewSource(time.Now().UnixNano()))
    48  	nonce := strconv.FormatInt(nonceGenerator.Int63(), 10)
    49  	ts := fmt.Sprintf("%d", time.Now().Unix())
    50  
    51  	params := &url.Values{}
    52  	params.Add("oauth_consumer_key", oauth.ConsumerKey)
    53  	params.Add("oauth_nonce", nonce)
    54  	params.Add("oauth_signature_method", "HMAC-SHA1")
    55  	params.Add("oauth_timestamp", ts)
    56  	params.Add("oauth_token", oauth.AccessToken)
    57  	params.Add("oauth_version", "1.0")
    58  
    59  	sig, err := oauth.getSignature(req, params)
    60  	if err != nil {
    61  		return err
    62  	}
    63  
    64  	str := fmt.Sprintf(
    65  		` oauth_consumer_key="%s", oauth_nonce="%s", oauth_signature="%s",`+
    66  			` oauth_signature_method="%s", oauth_timestamp="%s",`+
    67  			` oauth_token="%s", oauth_version="%s"`,
    68  		url.QueryEscape(oauth.ConsumerKey),
    69  		nonce,
    70  		url.QueryEscape(sig),
    71  		"HMAC-SHA1",
    72  		ts,
    73  		url.QueryEscape(oauth.AccessToken),
    74  		"1.0",
    75  	)
    76  	req.Header.Add("Authorization", str)
    77  
    78  	return nil
    79  }
    80  
    81  func (oauth OAuthConfig) getSignature(
    82  	req *http.Request,
    83  	params *url.Values,
    84  ) (string, error) {
    85  	baseSignatureString := req.Method + "&" +
    86  		url.QueryEscape(req.URL.String()) + "&" +
    87  		url.QueryEscape(params.Encode())
    88  
    89  	signingKey := url.QueryEscape(oauth.ConsumerSecret) + "&" +
    90  		url.QueryEscape(oauth.AccessTokenSecret)
    91  
    92  	return oauth.computeHMAC(baseSignatureString, signingKey)
    93  }
    94  
    95  func (oauth OAuthConfig) computeHMAC(
    96  	message string,
    97  	key string,
    98  ) (string, error) {
    99  	h := hmac.New(sha1.New, []byte(key))
   100  	if _, err := h.Write([]byte(message)); err != nil {
   101  		return "", err
   102  	}
   103  	return base64.StdEncoding.EncodeToString(h.Sum(nil)), nil
   104  }
   105  
   106  //------------------------------------------------------------------------------