The OAuth protocol enables interaction between a Web Service Provider(SP) and Consumer website or application. An example use case would be allowing Moo.com, the OAuth Consumer, to access private photos stored on Flickr.com, the OAuth Service Provider. This allows access to protected resources (Protected Resources) via an API without requiring the User to provide their Flickr.com (Service Provider) credentials to Moo.com (Consumer). More generically, OAuth creates a freely implementable and generic methodology for API authentication creating benefit to developers wishing to have their Consumer interact with various Service Providers.
While OAuth does not require a certain form of user interface or interaction with a User, recommendations and emerging best practices are described below. OAuth does not specify how the Service Provider should authenticate the User which makes the protocol ideal in cases where authentication credentials are not available to the Consumer, such as with OpenID.
OAuth aims to unify the experience and implementation of delegated web service authentication into a single community driven protocol. OAuth builds on top of existing protocols and best practices that have been implemented independently by various web sites. An open standard supported by large and small providers alike promotes a consistent and trusted experience for both consumer application developers and the users of those applications.
OAuth includes a Consumer Key and matching Consumer Secret allowing the Service Provider to authenticate the Consumer (as opposed to authenticate the User). This allows the Service Provider to provide different access levels to Consumers (such as disabling API throttling or allowing access to more resources). The Service Provider must allow Consumer Developers to obtain a Consumer Key and corresponding Consumer Secret. The provisioning of these is entirely up to the Service Provider. The Consumer Key must be a string suitable for transmission in HTTP request parameters. The Consumer Secret may be either a randomized string or a Public/Private Key Pair. In the case that the Consumer Secret is a Public/Private Key Pair, the Service Provider only requires the Public Key, and should verify that the Consumer Developer is in fact the owner of the Private Key.
The Service Provider must also provide documentation detailing the following:
When registering for a Consumer Key, the Service Provider asks the Consumer Developer for information regarding the nature of the Consumer (web application, desktop application, mobile application etc). If the Consumer is a web application, the Consumer Developer must provide the callback URL where the Service Provider will send the OAuth Tokens. Libraries implementing OAuth for the convenience of Consumer applications must support configurable API Endpoint URLs.
UI Note: It should be noted that if the User will be entering the Single-Use Token manually, such as on a mobile device, Service Providers should create a shorter “simplified” token.
Web-based Consumers obtain the Single-Use Token by way of an HTTP Redirect from the Service Provider to the Consumer’s Callback Endpoint URL. The request/response cycle is as follows:
To request a Single-Use Token, the Consumer constructs an
application/x-www-form-urlencoded HTTP GET request to the Service Provider’s
Authorization Endpoint URL which will be sent via the end user’s user-agent
(i.e., Web Browser).
This request contains the following parameters:
oauth_consumer_key - The Consumer Key oauth_state (optional) - An application/x-www-form-urlencoded string that
will be passed through unmodified to the Consumer (this parameter should only
be used in the case of stateless web-based Consumers) Once the request URL has been generated the Consumer issues an HTTP 302 Redirect to the Service Provider using that URL.
In this example, the Consumer is requesting a Single-Use Token from the
Authorization Endpoint URL https://sp.example.com/oauth/authorize
with the Consumer Key 0685bd91.
https://sp.example.com/oauth/authorize?oauth_consumer_key=0685bd91
Once the user has been authenticated by the Service Provider, the Service Provider must present the user with the option to grant access to the Consumer. The Service Provider should specify to the user which Protected Resources the Client is requesting, for how long the Client will have access to the resources, and other important information about the authorization that will be granted to the Client. If the user grants permission, the Service Provider should retain information about the transaction, including the token, associated user and Client data, the Requested Resources, time limits, etc. If the user denies the Client access, the Service Provider will not provide the Protected Resources to the Client.
Proposed UI? Too many protocols just leave user interaction as a hand-wavy
step. It would be great to at least provide best practices and/or sample
mock-ups. - Rich Conlan, 08/14/07 8:27 AM
Assuming permission is granted, the Service Provider will create a Single-Use Token and Token Secret and deliver it to the Consumer via an HTTP Redirect.
The response for a Web-based Consumer includes the following
application/x-www-form-urlencoded GET parameters:
oauth_token - The Single-Use Token. oauth_secret - The Token Secret. oauth_state (if provided in request) - The unmodified content provided by
the Consumer during the Request step.In this example, the Service Provider has created a Single-Use Token
c3e347b6a5001c16 and Secret 678dfge7dghek243 for the Consumer whose
Callback Endpoint URL is https://consumer.example.com/validate, so
the Service Provider will redirect the User to the following URL:
https://consumer.example.com/validate?oauth_token=c3e347b6a5001c16&oath_token_secret=678dfge7dghek243
Desktop consumers MUST first obtain a Single-Use Token, since they aren’t able to provide a Callback URL to which the Service Provider redirects the User. This is done by making a request to the appropriate Service Provider’s API Endpoint URL.
To request a Single-Use Token, the consumer constructs a request to the Service Provider’s API Endpoint URL. The request is signed as described in “Signing an API Request”. Because the Consumer does not yet have a Token or Token Secret, these fields are left empty.
Assuming the request is properly signed and accepted by the Service Provider, the Service Provider then returns the Single-Use Token and a Single-Use Authentication Secret in the body of the response as newline separated name-value pairs, followed by any additional data the Service Provider wishes to provide.
In this example, the Consumer has a Consumer Key 1b20acc6 and a
Consumer Secret 427a5979d9df7722. The Service Provider’s API Endpoint URL
for requesting a Single-Use Token is
http://sp.example.com/oauth/get_su_token, and the request is using the
HTTP GET method. The nonce is 17907867114999140772853922434221488511 and
the timestamp of 1186953553. Using SHA1 as the signing algorithm, the
signature is then 26287279e66f7f183af02653e823625871167d16, and the request
is as follows:
https://sp.example.com/oauth/get_su_token?oauth_consumer_key=1b20acc6&oauth_nonce=17907867114999140772853922434221488511&oauth_ts=1186953553&oauth_sigalg=sha1&oauth_sig=26287279e66f7f183af02653e823625871167d16
The Service Provider generates a Single-Use Token 37bb49b4 and a
corresponding secret d0e46c19, and returns the following as the body of the
response:
token=37bb49b4
secret=d0e46c19
To exchange a Single-Use Token for a Multi-Use Token and Secret, the Consumer
must obtain approval from the User by directing the User to the Service
Provider. The Consumer constructs an application/x-www-form-urlencoded
HTTP GET request to the Service Provider’s Authorization Endpoint URL which
will be sent via the end user’s user-agent (i.e., Web Browser).
This request contains the following parameters:
oauth_consumer_key
: The Consumer Key oauth_token
: The Single-Use Token obtained in the previous step.oauth_state (optional)
: An application/x-www-form-urlencoded string that will be passed through
unmodified to the Consumer (this parameter should only be used in the case of
stateless web-based Consumers) Once the request URL has been generated the Consumer directs the User to the URL.
In this example, the Consumer is requesting a Single-Use Token and Secret from
the Service Provider’s Authorization Endpoint URL
https://sp.example.com/oauth/authorize with the Consumer Key 0685bd91 and
Single-Use Token 37bb49b4.
https://sp.example.com/oauth/authorize?oauth_consumer_key=0685bd91&oauth_token=37bb49b4
The Service Provider Obtains User Consent in the same manner and with the same requirements as for Web-based Consumers.
Assuming permission is granted, the Service Provider will instruct the User to inform the Consumer that authorization has completed at the appropriate prompt within the Consumer application.
Once the Single-Use Token and Secret have been authorized, the Consumer can exchange them for a Multi-Use Token and Secret.
To request a Multi-Use Token, the Consumer makes an HTTP request to an Endpoint for Token Exchange as specified by the Service Provider’s documentation. It is suggested that this is a POST request, and that the Service Provider’s documentation specifies the HTTP verb (GET or POST). The request MUST be signed with the Single-Use Token and Secret per the signing instructions below.
If the request is valid, the Service Provider SHALL respond with text like so:
token=37bb49b4
secret=d0e46c19
Where the token and secret are encoded like application/x-www-form-urlencoded,
followed by Service Provider specific data, as defined by the Service Provider’s
API documentation. The Multi-Use Token and Secret are stored by the Consumer to
use when signing future requests.
If the request is not successful, the Service Provider MUST respond with a HTTP 401 Not Authorized, and MAY include some further details about why the request wasn’t authorized.
All OAuth API requests MUST be signed by the Consumer and the signature verified by the Service Provider. The following steps describe the signature process:
All are required except where stated.
oauth_consumer_key
: An API key. This is an arbitrary Consumer application specific identifier. oauth_secret
: The Secret that corresponds to the Consumer key. oauth_token
: An OAuth token. See the “Obtaining a Token” sections. oauth_token_secret
: An OAuth token secret. See the “Obtaining a Token” sections.oauth_nonce
: A one-time use value to verify the request has not been made before. See the
“Generating Nonces” section. oauth_ts
: An integer representing the time of request, expressed in number of
seconds after January 1, 1970 00:00:00 GMT.oauth_sigalg
: The hashing algorithm that the Consumer used to sign the request. oauth_sig
: The signature. The request parameters must be concatenated in the following order:
oauth_secret, oauth_consumer_key, oauth_token, oath_token_secret,
http_request_method, http_request_uri, normalized_request_parameters,
oauth_nonce, oauth_ts
After the Consumer has normalized the request parameters (see below), the
following signing algorithm SHALL be used to generate the value of the
oauth_sig:
generate an oauth_nonce (see Generating Nonces)
normalize OAuth Request Parameters
Concatenate the resulting name-value pairs into one string separated by the ASCII ‘&’ symbol in the following order:
oauthsecret, oauthconsumerkey, oauthtoken, httprequestmethod, httprequesturi, normalizedrequestparameters, oauthnonce, oauthts
sign or hash the concatenated string according to the chosen value of oauth_sigalg:
oauthsig = md5(concatenatedstring)
oauthsig = sha1(concatenatedstring)
oauthsig = hmacsha256(oauthsecret, concatenatedstring)
oauthsig = opensslx509sign(privatecertificate, concatenated_string) (in the case of using x509 certs, the Service Provider would have the Consumer’s public key and therefore would provide an empty string as the secret)
The basic API request looks like so:
http://twitter.com/statuses/with_friends/123456.json?page=3&count=50
Assuming the use of the SHA1 signature method and the following values:
oauth_ts => 1185517832
oauthsig = SHA1(“oauthsecret=3a2cd35&oauthconsumerkey=0685bd91&oauthtoken=540ad18&oauthtokensecret=x2s55k0&httprequestmethod=GET&httprequesturi=http%3A%2F%2Ftwitter.com%2Fstatuses%2Ffriends/123456.json&normalizedrequestparameters=count%3D50%26page%3D3&oauthnonce=MTgzNTYxODk4Mw&oauth_ts=1185517832”)
We need to pass to the server (in cleartext) the Consumer key (oauth_consumer_key),
the Token (oauth_token), the timestamp (oauth_ts), the nonce
(oauth_nonce), the signing algorithm (oauth_sigalg), and the signed
request (oauth_sig).
Clients MUST NOT send any of the secrets with the request, since doing so
would compromise the entire request, as well as subsequent requests.
The full signed request is then:
GET http://twitter.com/statuses/friends/123456.json?page=3&count=50&oauthkey=0685bd91&oauthtoken=540ad18&oauthnonce=MTgzNTYxODk4Mw&oauthts=1181537927&oauthsigalg=sha1&oauthsig=2d047740b53ae16f670750bef5bb5c2a0f398f30
The Consumer MUST first normalize request parameters by following the steps below. OAuth Request Parameters (see above) MUST NOT be included in this process. The normalized string MUST then be used when generating the signature for a request.
The encoding and format of the parameter names and their values MUST not be changed during this process. The Service Provider will perform this same set of steps when verifying the signature.
A nonce is a random string, uniquely generated for each request. The nonce allows the Service Provider to verify that this request has never been made before and helps prevent against replay attacks. More information about nonces can be found on Wikipedia (http://en.wikipedia.org/wiki/Cryptographic_nonce).
This section defines an RFC 2617 extension to support OAuth. It uses the standard Authorization and WWW-Authenticate headers to pass credentials rather than using URL parameters. All Consumers SHOULD be able to supply an OAuth Authorization header as an alternative to passing URL parameters. It is RECOMMENDED that Service Providers accept such a header and such Service Providers MUST signal Consumers by returning the OAuth WWW-Authenticate header upon all requests for the protected resource. For the remainder of this section, we assume that the Service Provider under discussion has chosen to support this extension.
When using a HTTP-Authorization header, the OAuth Request Parameters are not included in the body of the request. Rather they are included as the value of the header.
Authorization: OAuth oauth_token="540ad18" oauth_key="0685bd91" oauth_nonce="MTgzNTYxODk4Mw" oauth_ts="1185517832" oauth_sigalg="SHA1" oauth_sig="2d047740b53ae16f670750bef5bb5c2a0f398f30"
To reject a request that lacks appropriate credentials, the Service Provider MUST respond with a 401 Unauthorized response. Such a response MUST include at least one OAuth WWW-Authenticate header and MAY include additional WWW-Authenticate headers:
401 Unauthorized
...
WWW-Authenticate: OAuth
A Consumer MAY also include an empty, token-less OAuth Authorization header on any HTTP request to inform a Service Provider that it supports OAuth. The Service Provider MUST then respond with the appropriate WWW-Authenticate header for the requested resource in the response. For example, a Consumer could inquire using HEAD and then adjust its UI if the Service Provider supports OAuth.
Timestamps should be good for 5 minutes, this gives sufficient time to deal with network latency, without becoming a security hole, or placing an unbearable burden on the server for tracking and storing nonces. Ideally servers would provide a method for retrieving what they think the current time is.