https://github.com/pd/apiauth
ApiAuth-compatible package for signing and verifying HTTP requests in golang.
https://github.com/pd/apiauth
Last synced: about 1 year ago
JSON representation
ApiAuth-compatible package for signing and verifying HTTP requests in golang.
- Host: GitHub
- URL: https://github.com/pd/apiauth
- Owner: pd
- License: mit
- Created: 2015-05-06T16:54:53.000Z (about 11 years ago)
- Default Branch: master
- Last Pushed: 2023-02-15T20:31:09.000Z (over 3 years ago)
- Last Synced: 2024-10-23T22:30:59.487Z (over 1 year ago)
- Language: Go
- Homepage: https://github.com/pd/apiauth
- Size: 12.7 KB
- Stars: 8
- Watchers: 2
- Forks: 5
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: MIT-LICENSE
Awesome Lists containing this project
README
# apiauth [](https://travis-ci.org/pd/apiauth) [](https://godoc.org/github.com/pd/apiauth)
[ApiAuth][]-compatible package for signing and verifying HTTP requests in golang.
## IMPORTANT!: Security Update
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.
## Usage
Signing a request:
~~~go
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:
~~~go
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:
~~~go
// Given a request, returns the `,,,` 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)
~~~
## Caveats
This implementation is intentionally somewhat less "friendly" than mgomes' [Ruby implementation][ApiAuth]:
* Only the `Authorization` header is set for you by `apiauth.Sign`; setting the `Date`, `Content-Type`
and `Content-MD5` headers is the caller's responsibility.
* The `apiauth.Verify` function does *not* enforce a maximum time duration between the `Date` header
in a request and the matching `Date` value 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.Verify` function does *not* validate the `Content-MD5` header: 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.
[ApiAuth]: https://github.com/mgomes/api_auth