From 1930a7cd76129b34601cd6e4dc3ff4a737b7d0c1 Mon Sep 17 00:00:00 2001 From: Dalton Hubble Date: Sun, 26 Apr 2015 21:57:26 -0700 Subject: [PATCH] Improve README summary and usage docs --- README.md | 44 ++++++++++++++++++++++++------- config.go | 6 ++--- doc.go | 66 ++++++++++++++++++++++++++++++++++++++++++++++ examples/README.md | 35 +++++++++++++----------- 4 files changed, 123 insertions(+), 28 deletions(-) create mode 100644 doc.go diff --git a/README.md b/README.md index ea4f9c9..0a5b0b3 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,9 @@ # OAuth1 [![Build Status](https://travis-ci.org/dghubble/oauth1.png)](https://travis-ci.org/dghubble/oauth1) [![GoDoc](http://godoc.org/github.com/dghubble/oauth1?status.png)](http://godoc.org/github.com/dghubble/oauth1) -OAauth1 is a Go client implementation of the OAuth1 spec. It supports authorizing HTTP requests. +OAauth1 is a Go implementation of the [OAuth 1 spec](https://tools.ietf.org/html/rfc5849). -The OAuth1 package takes design cues from the [golang.org/x/oauth2](https://godoc.org/golang.org/x/oauth2), providing an http.Client which handles signing requests and authorization via a custom Transport. - -If an official oauth1 package were to be developed by the Go authors, I'd recommend you use that implementation instead. However, at this time, no official implementation exists. - -## Note - -This library is currently under development. It provides a signing http.Client, but does not yet completely implement the spec or handle credential retrieval from a provider backend. +It takes design cues from [golang.org/x/oauth2](https://godoc.org/golang.org/x/oauth2), providing an `http.Client` which handles authorization and signing. ## Install @@ -19,11 +13,39 @@ This library is currently under development. It provides a signing http.Client, Read [GoDoc](https://godoc.org/github.com/dghubble/oauth1) -## Usage +### Components + +An `Endpoint` groups an OAuth provider's URLs for getting a request token, allowing users to authorize applications, and getting access tokens. Endpoints for common providers like [twitter](twitter) and [dropbox](dropbox) are provided in subpackages. + +A `Config` stores a consumer application's consumer key and secret, the callback URL, and the Endpoint to which the consumer is registered. It provides OAuth 1 authorization flow methods and a `Client(token *Token)` method which returns an `http.Client` which will transparently authorize requests. + +An OAuth1 `Token` is an access token which allows requests to be made as a particular user. It has fields `Token` and `TokenSecret`. If you already have an access token, skip to [Authorized Requests](#Authorized Requests). + +If you've used [golang.org/x/oauth2](https://godoc.org/golang.org/x/oauth2) before, this organization is similar. -Create an application `Config` with a `ConsumerKey` and `ConsumerSecret`. Obtain a token credential in some way (many providers offer a web interface or command line tool for this) and create a `Token`. +### Authorization Flow + +The OAuth 1 authorization flow to request that a user grant an application access to his/her account (via an access token) typically looks like: + +* User visits Consumer's "/login" route (via "Login with Provider" button) +* Login handler calls `config.GetRequestToken()` +* Login handler redirects user to `config.AuthorizationURL(rt *RequestToken)` +* Provider calls Consumer's CallbackURL with a `verifier` +* `config.GetAccessToken(rt *RequestToken, verifier string)` +* Consumer application stores access token. Optionally creates some form of unforgeable session state. + +For more details, see the Twitter PIN-based login [example](examples) or the +[go-twitter](https://github.com/dghubble/go-twitter) `login` package. + +### Authorized Requests + +After an access `Token` has been obtained, authorized requests can be made on behalf of the user. ```go +import ( + "github.com/dghubble/oauth1" +) + func main() { config := oauth1.NewConfig("consumerKey", "consumerSecret") token := oauth1.NewToken("token", "tokenSecret") @@ -40,4 +62,6 @@ func main() { } ``` +See more request [examples](examples). + diff --git a/config.go b/config.go index 8317ce4..266917b 100644 --- a/config.go +++ b/config.go @@ -59,7 +59,7 @@ type RequestToken struct { // RequestTokenURL. The request is signed by the consumer secret and an empty // token secret. The response body form is validated to ensure // oauth_callback_confirmed is true. Returns a new RequestToken with the -// oauth_token and oauth_token_secret in the body. +// oauth_token and oauth_token_secret from the body. // See RFC 5849 2.1 Temporary Credentials. func (c *Config) GetRequestToken() (*RequestToken, error) { req, err := http.NewRequest("POST", c.Endpoint.RequestTokenURL, nil) @@ -115,7 +115,7 @@ func (c *Config) AuthorizationURL(rt *RequestToken) (*url.URL, error) { // and oauth_verifier are parsed and returned. The oauth_token (temporary // credential) identifies the RequestToken pair obtained from GetRequestToken // previously. -// See RFC 2.2 Resource Owner Authorization. +// See RFC 5849 2.2 Resource Owner Authorization. func (c *Config) HandleAuthorizationCallback(req *http.Request) (tokenKey, verifier string, err error) { // parse the raw query from the URL into req.Form err = req.ParseForm() @@ -135,7 +135,7 @@ func (c *Config) HandleAuthorizationCallback(req *http.Request) (tokenKey, verif // Endpoint AccessTokenURL. The request is signed by the consumer secret and // request token secret pair. The access oauth_token and oauth_secret are // read from the response body form to return an AccessToken. -// See RFC 2.3 Token Credentials. +// See RFC 5849 2.3 Token Credentials. func (c *Config) GetAccessToken(requestToken *RequestToken, verifier string) (*Token, error) { req, err := http.NewRequest("POST", c.Endpoint.AccessTokenURL, nil) if err != nil { diff --git a/doc.go b/doc.go new file mode 100644 index 0000000..b3c9de8 --- /dev/null +++ b/doc.go @@ -0,0 +1,66 @@ +/* +Package oauth1 is a Go implementation of the OAuth1 spec. + +Components + +An Endpoint groups an OAuth provider's URLs for getting a request token, +allowing users to authorize applications, and getting access tokens. Endpoints +for common providers like Twitter and Dropbox are provided in subpackages. + +A Config stores a consumer application's consumer key and secret, the +callback URL, and the Endpoint to which the consumer is registered. It +provides OAuth 1 authorization flow methods and a Client(token *Token) +method which returns an http.Client which will transparently authorize +requests. + +An OAuth1 Token is an access token which allows requests to be made as a +particular user. It has fields Token and TokenSecret. If you already have +an access token, skip to Authorized Requests. + +If you've used https://godoc.org/golang.org/x/oauth2 before, this organization +is similar. + +Authorization Flow + +The OAuth 1 authorization flow to request that a user grant an application +access to his/her account (via an access token) typically looks like: + + * User visits Consumer's "/login" route (via "Login with Provider" + button) + * Login handler calls config.GetRequestToken() + * Login handler redirects user to config.AuthorizationURL(rt *RequestToken) + * Provider calls Consumer's CallbackURL with a verifier + * config.GetAccessToken(rt *RequestToken, verifier string) + * Consumer application stores access token. Optionally creates some form of + unforgeable session state. + +For more details, see the Twitter PIN-based login example or the +https://github.com/dghubble/go-twitter login package. + +Authorized Requests + +After an access Token has been obtained, authorized requests can be made on +behalf of the user. + + import ( + "github.com/dghubble/oauth1" + ) + + func main() { + config := oauth1.NewConfig("consumerKey", "consumerSecret") + token := oauth1.NewToken("token", "tokenSecret") + + // httpClient will automatically authorize http.Request's + httpClient := config.Client(token) + + // example Twitter API request + path := "https://api.twitter.com/1.1/statuses/home_timeline.json?count=2" + resp, _ := httpClient.Get(path) + defer resp.Body.Close() + body, _ := ioutil.ReadAll(resp.Body) + fmt.Printf("Raw Response Body:\n%v\n", string(body)) + } + +See more request examples in the examples subpackage. +*/ +package oauth1 diff --git a/examples/README.md b/examples/README.md index a909966..f8a295b 100644 --- a/examples/README.md +++ b/examples/README.md @@ -3,21 +3,26 @@ ## Twitter -### Login Flow (PIN) - -A consumer application can obtain a Twitter Access Token for a user by requesting the user grant access via [3-legged](https://dev.twitter.com/oauth/3-legged) or [PIN-based](https://dev.twitter.com/oauth/pin-based) OAuth 1. - - export TWITTER_CONSUMER_KEY=xxx - export TWITTER_CONSUMER_SECRET=yyy - - go run twitter-login.go - - Open this URL in your browser: - https://api.twitter.com/oauth/authenticate?oauth_token=xxx - Paste your PIN here: ddddddd - Consumer was granted an access token to act on behalf of a user. - token: ddddd-xxxxx - secret: yyyyyy +### Login Flow (PIN-based) + +An application can obtain a Twitter Access Token for a user by requesting the user grant access via [3-legged](https://dev.twitter.com/oauth/3-legged) or [PIN-based](https://dev.twitter.com/oauth/pin-based) OAuth 1. + +``` +export TWITTER_CONSUMER_KEY=xxx +export TWITTER_CONSUMER_SECRET=yyy +``` + +Run `twitter-login.go` to authorize the consumer application to a Twitter account. + +``` +go run twitter-login.go +Open this URL in your browser: +https://api.twitter.com/oauth/authenticate?oauth_token=xxx +Paste your PIN here: ddddddd +Consumer was granted an access token to act on behalf of a user. +token: ddddd-xxxxx +secret: yyyyyy +``` Note that website backends should define a CallbackURL which can receive a verifier string and request an access token, "oob" is for PIN-based agents such as the command line.