github.com/mailgun/holster/v4@v4.20.0/httpsign/README.md (about)

     1  httpsign
     2  =========
     3  
     4  Mailgun tools for signing and authenticating HTTP requests between web services.
     5  
     6  **Overview**
     7  
     8  An keyed-hash message authentication code (HMAC) is used to provide integrity and
     9  authenticity of a message between web services. The following elements are input
    10  into the HMAC. Only the items in bold are required to be passed in by the user, the
    11  other elements are either optional or build by httpsign for you.
    12  
    13  * **Shared secret**, a randomly generated number from a CSPRNG.
    14  * Timestamp in epoch time (number of seconds since January 1, 1970 UTC).
    15  * Nonce, a randomly generated number from a CSPRNG.
    16  * **Request body.**
    17  * Optionally the HTTP Verb and HTTP Request URI.
    18  * Optionally an additional headers to sign.
    19  
    20  Each request element is delimited with the character `|` and each request element is
    21  preceded by its length. A simple example with only the required parameters:
    22  
    23  ```
    24  shared_secret = '042DAD12E0BE4625AC0B2C3F7172DBA8'
    25  timestamp     = '1330837567'
    26  nonce         = '000102030405060708090a0b0c0d0e0f'
    27  request_body  = '{"hello": "world"}'
    28  
    29  signature     = HMAC('042DAD12E0BE4625AC0B2C3F7172DBA8',
    30     '10|1330837567|32|000102030405060708090a0b0c0d0e0f|18|{"hello": "world"}')
    31  ```
    32  
    33  The timestamp, nonce, signature, and signature version are set as headers for the
    34  HTTP request to be signed. They are then verified on the receiving side by running the
    35  same algorithm and verifying that the signatures match.
    36  
    37  Note: By default the service can securely handle authenticating 5,000 requests per
    38  second. If you need to authenticate more, increase the capacity of the nonce 
    39  cache when initializing the package.
    40  
    41  **Examples**
    42  
    43  
    44  _Signing a Request_
    45  
    46  ```go
    47  import (
    48      "net/http"
    49      "strings"
    50  
    51      "github.com/mailgun/lemma/httpsign"
    52  )
    53  
    54  auths := httpsign.New(&httpsign.Config{Keypath: "/path/to/file.key"})
    55  
    56  [...]
    57  
    58  // build new request
    59  requestBody := strings.NewReader(`{"hello":"world"}`)
    60  request, _ := http.NewRequest("POST", "", requestBody)
    61  
    62  // sign request
    63  err := auths.SignRequest(request)
    64  if err != nil {
    65      return err
    66  }
    67  
    68  // submit request
    69  client := &http.Client{}
    70  response, _ := client.Do(request)
    71  ```
    72  
    73  _Signing a Request with Headers_
    74  
    75  ```go
    76  import (
    77      "net/http"
    78      "strings"
    79  
    80      "github.com/mailgun/lemma/httpsign"
    81  )
    82  
    83  auths := httpsign.New(&httpsign.Config{
    84      Keypath: "/path/to/file.key",
    85      HeadersToSign: []string{"X-Mailgun-Header"},
    86  })
    87  
    88  [...]
    89  
    90  // build new request
    91  requestBody := strings.NewReader(`{"hello":"world"}`)
    92  request, _ := http.NewRequest("POST", "", requestBody)
    93  request.Header.Set("X-Mailgun-Header", "foobar")
    94  
    95  // sign request
    96  err := auths.SignRequest(request)
    97  if err != nil {
    98      return err
    99  }
   100  
   101  // submit request
   102  client := &http.Client{}
   103  response, _ := client.Do(request)
   104  ```
   105  
   106  _Signing a Request with HTTP Verb and URI_
   107  
   108  ```go
   109  import (
   110      "net/http"
   111      "strings"
   112  
   113      "github.com/mailgun/lemma/httpsign"
   114  )
   115  
   116  auths := httpsign.New(&httpsign.Config{
   117      Keypath: "/path/to/file.key",
   118      SignVerbAndURI: true,
   119  })
   120  
   121  [...]
   122  
   123  // build new request
   124  requestBody := strings.NewReader(`{"hello":"world"}`)
   125  request, _ := http.NewRequest("POST", "", requestBody)
   126  
   127  // sign request
   128  err := auths.SignRequest(request)
   129  if err != nil {
   130      return err
   131  }
   132  
   133  // submit request
   134  client := &http.Client{}
   135  response, _ := client.Do(request)
   136  ```
   137  
   138  _Authenticating a Request_
   139  
   140  ```go
   141  import (
   142      "fmt"
   143      "net/http"
   144      "strings"
   145  
   146      "github.com/mailgun/lemma/httpsign"
   147  )
   148  
   149  auths := httpsign.New(&httpsign.Config{Keypath: "/path/to/file.key"})
   150  
   151  [...]
   152  
   153  func handler(w http.ResponseWriter, r *http.Request) {
   154      // authenticate request
   155      err := auths.AuthenticateRequest(r)
   156     
   157      // request is invalid
   158      if err != nil {
   159          fmt.Fprintf(w, "<p>Unable to Authenticate Request: %v</p>", err)
   160          return
   161      }
   162    
   163      // valid request
   164      fmt.Fprintf(w, "<p>Request Authenticated, welcome!</p>")
   165  }
   166  ```