1. David Larlet
  2. django-oauth-plus


Clone wiki

django-oauth-plus / consumer_xauth_example

xAuth flow example (consumer side tutorial)

This page provides simple tutorial on consumer side OAuth authentication.

xAuth Authentication is done in two steps:

  1. The Consumer exchanges the hes credentials and user credentials for an Access Token.

This page shows example interaction with oauth_provider on consumer side

Initial assumptions

In this tutorial we will use following terms:

Provider - Web application providing OAuth authentication for accessing it's resources.

Consumer - Application accessing OAuth protected resources on behalf of User.

User - User of Provider's application. Has access to some resources and can grant them to Consumer.

For the purpose of this example we need some basic assumptions. The Service Provider documentation explains how to register for a Consumer Key and Consumer Secret, and declares the following URLs:

Request Token URL: http://photos.example.net/request_token, using HTTP POST

Access Token URL: http://photos.example.net/access_token, using HTTP POST

Photo (Protected Resource) URL: http://photos.example.net/photo with required parameter file and optional parameter size

The Service Provider declares support for the HMAC-SHA1 signature method for all requests, and PLAINTEXT only for secure (HTTPS) requests.

The Consumer printer.example.com already established a Consumer Key and Consumer Secret with photos.example.net and advertizes its printing services for photos stored on photos.example.net. The Consumer registration is:

  • Consumer Key: dpf43f3p2l4k3l03
  • Consumer Secret: kd94hf93k423kf44

We assume that Service Provider has authorized Consumer to use xAuth flow. In django-oauth-plus it is done by setting field xauth_allowed=True on Consumer model object. If you're using Oauth 2.0.0, you must also register XAuthAuthentication backend in your settings file (see installation)

Step 1. Obtaining Access Token

Note: In further code examples we will use python-oauth2 and python-requests for making OAuth signed requests. There is a plenty of other tools you can use to communicate with different APIs (like slumber) but oauth2 should still remain useful in signing OAuth requests.

After User informs printer.example.com that she would like to print her vacation photo stored at photos.example.net the Consumer website tries to access the photo and receives HTTP 401 Unauthorized indicating it is private. The Service Provider includes the following header with the response:

WWW-Authenticate: OAuth realm=""

In this step Consumer must obtain from user his credentials to Provider's site. This credentials should not be ever stored by Consumer. User's data is transfered in additional parameters:

  • x_auth_username the login credential of the User the client is obtaining a token on behalf of
  • x_auth_password the password credential of the User the client is obtaining a token on behalf of
  • x_auth_mode this value must be "client_auth"

If these parameters are present, then Provider will know that Consumer tries to authenticate with xAuth flow:

access_token_url = 'http://photos.example.net/access_token'
consumer = oauth.Consumer(key='dpf43f3p2l4k3l03', secret='kd94hf93k423kf44')

oauth_request = oauth.Request.from_consumer_and_token(consumer, parameters={"x_auth_username": "username", "x_auth_password": "password", "x_auth_mode": "client_auth"} http_url=access_token_url)
oauth_request.sign_request(oauth.SignatureMethod_HMAC_SHA1(), consumer, None)

response = requests.get(access_token_url, headers=oauth_request.to_header())
access_token = dict(urlparse.parse_qsl(response.content))
# - oauth_token:        access_token['oauth_token']
# - oauth_token_secret: access_token['oauth_token_secret']

Using access token

Access token can now be used for signing all further requests to OAuth protected resources.

resource_url = 'http://photos.example.net/photo'

token = oauth.Token(access_token['oauth_token'], access_token['oauth_token_secret'])
client = oauth.Client(consumer, token)
oauth_request = oauth.Request.from_consumer_and_token(consumer, http_url=resource_url)
oauth_request.sign_request(oauth.SignatureMethod_HMAC_SHA1(), consumer, None)

# get the resource
response = requests.get(resource_url, headers=oauth_request.to_header())