ApiAuth-compatible package for signing and verifying HTTP requests in golang.
In order to prevent a security vulnerability present in the reference version of
ApiAuth we have added functions in order to sign and verify requests with a
canonical string that includes the HTTP method. We have added the fucntions
SignWithMethod and CanonicalStringWithMethod, and the Verify function has
been modified to accept requests where the request signature matches
CanonicalString OR CanonicalStringWithMethod. In the future the old versions
will be removed and canonical strings will only be considered a match if they
include the request method. We recommend you start using the new way of siging
requests immediately.
Signing a request:
import "github.com/pd/apiauth"
req, _ := http.NewRequest("GET", "http://example.com", nil)
// The `Date` header _must_ be present.
// If the request body is set, `Content-Type` and `Content-MD5` must
// also be present.
req.Header.Set("Date", apiauth.Date())
err := apiauth.Sign(req, "access_id", "secret_key")Verifying a request:
err := apiauth.Verify(req, "secret_key")
if err != nil {
// Failed.
}Functions are exposed for the lower-level operations, as well, in case you need more granular control:
// Given a request, returns the `<Content-Type>,<MD5>,<URI>,<Date>` string used for the HMAC.
str := apiauth.CanonicalString(req)
// Given a canonical string and secret key, computes the signature using HMAC-SHA1:
signature := apiauth.Compute(str, "secret_key")
// A helper for generating a RFC1123-formatted date using the current time:
apiauth.Date()
// Or a given time:
t := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
apiauth.DateForTime(t)This implementation is intentionally somewhat less "friendly" than mgomes' Ruby implementation:
- Only the
Authorizationheader is set for you byapiauth.Sign; setting theDate,Content-TypeandContent-MD5headers is the caller's responsibility. - The
apiauth.Verifyfunction does not enforce a maximum time duration between theDateheader in a request and the matchingDatevalue computed by the server. Protection against replay attacks is the caller's responsibility. (NB: but maybe shouldn't be; I'm just being lazy right now, as it's already handled in the application I'm writing this for) - The
apiauth.Verifyfunction does not validate theContent-MD5header: doing so would require reading the entire request body into memory at least once, which is undesirable in many use cases. Verification of the payload MD5 is the caller's responsibility.

