Implementing an OAuth 2.0 client is a significant undertaking in itself. Implementing a provider is even more complicated. To make our (and your) lives easier, we’ve open-sourced a Python OAuth 2.0 provider interface, called pyoauth2, which can be easily extended to function as a complete solution for adding OAuth provider functionality to your application. In this post, I will walk through how we set up pyoauth2 for SHIFT.com.
OAuth 2.0 and pyoauth2 is for you if:
- You run a Python 2.7-based website or application
- Third-party apps need to safely connect to it to retrieve your user’s data and interact with your application
- Third-party apps need to “Login with Your App” without exposing your user’s passwords or other confidential information
When we have finished this series, we will have created a small example application that will:
- Prompt for user access to your existing application
- Receive protected user resources with OAuth validation
- Stay logged-in to your app permanently and securely through the use of refresh tokens
Note: only a subset of the very broad OAuth 2.0 Specification is supported by pyoauth2.
Authorization Overview
Before writing any code, become familiar with the authorization flow if you have not previously worked with OAuth 2.0. The following diagram is taken from the SHIFT.com authorization provider implementation. Your application’s functionality will be similar, but not necessarily identical to the SHIFT.com example. CustomApp represents any third-party app that would like to connect to SHIFT.com using OAuth. Steps 1-8 are essential and require HTTPS, and any missing portion will likely cause the entire authorization to fail, possibly silently.

This diagram was inspired by Facebook’s great explanation of it’s own Login Architecture.
Note: All requests must be made with HTTPS, and all configuration URLs should begin with https:// as well.
OAuth Terminology
| Term | Meaning |
|---|---|
| client_id | The third-party application ID pre-registered with the provider |
| client_secret | The third-party application secret generated by the provider and stored securely by the third-party app and the provider |
| redirect_uri | The third-party application OAuth 2.0 redirect endpoint |
Step 1: Get Authorization Code
The OAuth 2.0 authorization process is started with a GET request to the provider server by the user’s browser, usually by clicking a link to the third party app, containing details of the auth request.
GET https://shift.com/v1/oauth2/auth?
response_type=code
&client_id=3faf0fb4c2fe76c1c3bb7d09c21b97c2
&redirect_uri=https://customapp.com/oauth/redirect
&shift_team_id=bd6e59b73876f59d13b6fcc944810210
Note: The redirect_uri parameter must be URL encoded, it is shown unencoded here for readability purposes.
Step 2: Redirect to redirect_uri
The provider will assess whether or not it can fulfill the request, and redirect to the redirect_uri with either an error, or an authorization code:
Successful response headers:
Location: https://customapp.com/oauth/redirect?
code=hjrZryvgLYo3R833NkHHV8jYmxQhsD8TjKWzOm2f
&shift_team_id=bd6e59b73876f59d13b6fcc944810210
Step 3: Browser follows redirect
CustomApp’s server code receives the request and will now perform a series of actions. This browser request resolves via a redirect when step 8 is reached, and the remainder of the steps are performed by CustomApp within this request.
Step 4: CustomApp server-side request for token
This request includes the client_secret, which is never sent to the browser. Once this request completes, the OAuth authorization process is complete.
POST https://shift.com/v1/oauth2/token
Body:
code=hjrZryvgLYo3R833NkHHV8jYmxQhsD8TjKWzOm2f
&grant_type=authorization_code
&client_id=3faf0fb4c2fe76c1c3bb7d09c21b97c2
&client_secret=9643b7c3f59ef531931d39a3e19bcdd7
&redirect_uri=https://customapp.com/oauth/redirect
Step 5: Token request response
SHIFT validates the authorization code and other information in the request, and responds with an access and refresh token.
{"access_token": "2006b436b8f3d83ea291ececc66256c31dcfc67e3",
"refresh_token": "b669ba34fda054b5b62cd559c9c0676643867e5cd"}
Step 6: Load user information
This step is not part of the OAuth standard, and is actually the first request made with the OAuth access_token we just received. For SHIFT, CustomApp requests the user using the OAuth Bearer header so it can save the user information in the CustomApp session.
GET https://shift.com/v1/users/me
Headers:
Authorization: Bearer 2006b436b8f3d83ea291ececc66256c31dcfc67e3
Step 7: User information response
SHIFT will respond with the information of the user that authenticated through OAuth.
{"id": "781c5623c31ae512487ab26ea2e01991", "first_name": "Nate", ... }
Step 8: Redirect to App
At this point CustomApp has obtained from SHIFT:
- An access_token
- A refresh_token
- A user profile
It is now the responsibility of CustomApp to save all of this information and redirect the user. With pyoauth2, all of the required steps are implemented in 3 classes: AuthorizationProvider, ResourceProvider, and ResourceAuthorization. I’ll explain the purpose and use of each in the remainder of this series.
Continued in part 2, Implementing the Authorization Provider.
