In this tutorial, you'll build a web app that implements an OAuth authorization flow. The main goal of OAuth authorization is to allow third-party applications to interact with a Zendesk Support instance without having to store and use the passwords of Zendesk Support users, which is sensitive information that the apps shouldn't know.

When you use basic authentication, you have to specify a username with a password or an API token. Example:

If the user doesn't have an access token, the app has to send the user to a Zendesk Support authorization page where the user may or may not authorize the app to access Zendesk Support on their behalf. If the user authorizes access, Zendesk Support provides the app with an authorization code that it can exchange for an access token. A different access token is provided for each user who authorizes the app. The app never learns the user's Zendesk Support password.

The goal of this tutorial is to show you how to implement the OAuth authorization grant flow in a web application. To keep things simple, the app is built using a Python micro web framework called Bottle. The framework helps keep technical details to a minimum so you can focus on the authorization flow.

Disclaimer: Zendesk provides this article for instructional purposes only. Zendesk does not support or guarantee the code. Zendesk also can't provide support for third-party technologies such as Python and the Bottle framework. Please post any issue in the comments section or search for a solution online.

What you need

You need a text editor and a command-line interface like the command prompt in Windows or the Terminal on the Mac.

You'll also need Python and a few Python libraries to develop the web app, as described next.

Install Python 3

Install version 3 of Python on your computer if you don't already have it. Python is a powerful but beginner-friendly scripting and programming language with a clear and readable syntax. Visit the Python website to learn more. To download and install it, see http://www.python.org/download/.

Get the tutorial app files

You need a working web app before you can implement the OAuth authorization flow. To keep things simple, the tutorial app uses a micro web framework called Bottle. All the logic of a Bottle app can fit comfortably in a single file. Because this isn't a Bottle tutorial, a set of starter files is provided.

To also keep the spotlight on the OAuth flow, the app will limit itself to getting and displaying the user's Zendesk Support user name and role, which could be admin, agent, or end-user.

Download the tutorial app files

Download and unzip the oauth_tutorial_app.zip file attached to this article in your tutorials folder.

The zip file contains starter files for the tutorial application. See the next section to learn more about the files and how Bottle works.

Bottle app basics

Navigate to the oauthtutorialapp folder in a file browser. The app consists of the following folders and files:

/oauth_tutorial
oauth_app.py
/static
/views

The oauth_app.py file is the app's nerve center. Open it in a text editor to take a look:

The file consist of routes that map HTTP requests to functions. The return value of each function is sent in the HTTP response.

For example, when a browser requests the page at the /home relative URL, the app looks up the /home route and runs the show_home() custom function. The show_home() function returns the results of the framework's template() function in the HTTP response. The template() function renders a template named 'home' in HTML. Templates are located in the views folder and have .tpl file extensions.

The template() function passes the information contained in the profile_data variable to the template using the data keyword argument. The argument name is arbitrary. For now, the function sends dummy data until you add the request code later.

The argument values are inserted at placeholders in the details.tpl template:

Run the app

In your command-line interface, navigate to the oauthtutorialapp folder.

Run the following command to start the local server:

$ python3 oauth_app.py

In a browser, go to http://localhost:8080/home.

You should see the tutorial app's admittedly plain home page:

Run some tests.

Try clicking the link on the home page. Try opening http://localhost:8080/.

When you're done, switch to your command-line interface and press Ctrl+C to shut down the server.

You're ready to start implementing the OAuth authorization flow. The first step is to register your new app with Zendesk Support.

Register your app with Zendesk Support

Before you can use OAuth authentication, you need to tell Zendesk Support about your application. You must be signed in as a Zendesk Support administrator to register an app.

In Zendesk Support, click Manage () and then select API in the Channels category.

Click the OAuth Clients tab on the Channels/API page, and then click Add a Client on the right side of the client list.

A page for registering your application appears. The Secret field is pre-populated.

Complete the following fields:

Client Name - Enter OAuth Tutorial App. This is the name that users will see when asked to grant access to your application and when they check the list of third-party apps that have access to their Zendesk Support instance.

Description - Optional, but you can enter something like "This app gets information from your Zendesk Support profile." Users will see this short description when asked to grant access to it.

Company - Optional, but you can enter your company's name if you like. This is the company name that users will see when asked to grant access to your application. The information can help them understand who they're granting access to.

Logo - Optional, but you can upload the logo-small.jpg sample image in the /static/images/ folder in the starter files. This is the logo that users will see when asked to grant access to your application. The image can be a JPG, GIF, or PNG. For best results, upload a square image. It'll be resized for the authorization page.

Unique Identifier - Click the field to auto-populate it with the name you entered for your app. You can change it if you want.

Redirect URLs - Enter the following URL:

http://localhost:8080/handle_user_decision

This is the URL that Zendesk Support will use to send the user's decision to grant access to your application. You'll create a route for handle_user_decision later.

Click Save.

You'll be prompted to save the secret on the next page.

Copy the Secret value and save it somewhere safe.

The characters may extend past the width of the text box, so make sure to select everything before copying.

Important: For security reasons, your secret is displayed fully only once. After clicking Save, you'll only have access to the first nine characters.

Click Save.

Now that you've registered the app with Zendesk Support, you can modify it to send users to a Zendesk Support authorization page the first time they attempt to use your app to access Zendesk Support data.

Send the user to the Zendesk Support authorization page

The first change to make to the app is to send users to the Zendesk Support authorization page if they haven't authorized your app yet. Here's the logic that you'll implement: If the user has an access token, make the request. If not, kick off the authorization flow.

Open the oauth_app.py file and change the /zendesk_profile route as follows:

The make_request() function starts by checking to see if the user has an access token. If they have a token (if has_token is true), the app makes the API request right away. You'll replace the temporary has_token code later in the tutorial. You'll also add the API request code. Dummy data is used for now.

Add an else clause to kick off the authorization flow if the user doesn't have a token (if has_token is false):

Because the app uses the authorization code grant flow, you have to specify 'code' as the response type. The 'redirect_uri' value is where you want Zendesk Support to send the user's decision. The 'client_id' value is the "unique identifier" created when you registered the app in Zendesk Support. The 'scope' value is what the app is asking permission to do in Zendesk Support. If the app will only get data and not create it, you could specify 'read' as the scope.

The parameters must be url-encoded to be sent in a query string, as described next.

Pass the parameters variable to the urlencode() method in the url variable declaration (in bold below):

url = '.../oauth/authorizations/new?' + urlencode(parameters)

Add the following line at the top of the oauth_app.py file to import the urlencode method:

from urllib.parse import urlencode

The urllib.parse module is included with Python so you don't have to install it.

The updated route should look as follows with your value for the {subdomain} placeholder:

Make sure your code is indented as shown, ignore any line wraps caused by the right margin, and then test that it works:

Start the development server from the command line:

$ python3 oauth_app.py

If the server is still running from the previous session, shut it down with Ctrl+C and start it up again for the changes to take effect.

Open http://localhost:8080/home in a browser.

Click Get Zendesk profile info about myself.

You should be redirected to the Zendesk Support authorization page because has_token is false. If you're not currently signed in to Zendesk Support, you'll be asked to sign in first. This is how Zendesk Support knows who you are.

Eventually, the authorization page opens:

Don't click Allow yet. The redirect page doesn't exist yet. You'll work on it next. If you do click Allow, it's not the end of the world. You'll just get a 404 message, as expected.

Note: If you make changes to the oauth_app.py file while the local server is running, you have to stop and restart the server to see the changes. You don't have to restart the server if you make changes to static files like the templates or css. Just refresh the page in the browser.

Handle the user's authorization decision

After the user makes the decision on the Zendesk Support authorization page to allow or deny access to your app, Zendesk Support sends the decision and a few other bits of information to the redirect URL you specified.

If the user decided to authorize the application, Zendesk Support adds a query string that contains an authorization code. Example:

{redirect_url}?code=7xqwtlf3rrdj8uyeb1yf

If the user decided not to authorize the application, Zendesk Support adds a query string that contains error and error_description parameters that inform the app that the user denied access. Example:

Use the possible query string values to control the flow of your application. Here's the approach you'll take: If the query string contains the string 'error', show an error message. If not, get the access token.

Start by creating a route for the "/handle_user_decision" redirect URL:

The handle_decision() function checks to see if the string 'error' appears in the query string. In the Bottle framework, the request object refers to the current HTTP request and the query_string property refers to the request's query string, if any.

If 'error' is found, the app renders the error template with the error message from the error_description parameter.

If 'error' is not found, then an authorization code must have been sent. The app can grab the code from the query string and exchange it for an access token with a POST request to a specific API endpoint, as described next.

In the else clause, define the parameters that must be included in the POST request:

The 'grant_type' value is 'authorization_code' because you're implementing an authorization code grant flow. The 'code' value is the actual authorization code, which is retrieved from the query string with the query.code property of the framework's request object. The 'secret' value is the "Secret" generated when you registered the app in Zendesk Support. The 'redirect_uri' value is the same redirect URL as before.

Add the following statements after the parameters to make the POST request:

Make sure to replace {subdomain} in the URL with your Zendesk Support subdomain.

The requests.post() method from the requests library makes the request. The response from Zendesk Support is assigned to the r variable. (The response identifier is reserved for the Bottle response object used in the next step.)

If the request was successful (the HTTP status code was 200), the else clause is executed. The app decodes the json data and gets the token. It then saves the token in a cookie named 'owat' (for oauth web app tutorial) on the user's computer with the framework's response.set_cookie() method.

Important: To keep things simple, the app saves the token unencrypted in a cookie on the user's machine, but be aware of the security implications. It's like saving a password in a cookie. Somebody could use it to access the user's information on Zendesk Support. Unfortunately, storing access tokens securely is beyond the scope of this tutorial.

Finally, the user is redirected to the zendesk_profile page, which kicked off the authorization flow.

Add the following libraries used in the code at the top of the file:

import json
import requests

The completed /handle_user_decision route should look as follows (make sure your indentation is correct, ignoring the line wraps caused by the right margin):

Use the access token

Your app can now check to see if the user has an access token. If the token exists, the app can use it to request the user's information from Zendesk Support.

In the /zendesk_profile route, replace the following 2 lines:

has_token = False
if has_token:

with the following line at the same indent level:

if request.get_cookie('owat'):

The app checks to see if the cookie named 'owat' exists on the user's computer using the Bottle framework's request.get_cookie() method. If the cookie exists, it gets the user data from Zendesk Support. If the cookie doesn't exist, the app kicks off the authorization flow.

Replace the contents of the if clause with the following the request code:

The rest of the block makes the request with the Authorization header, updates the profile_data variable with the response data, and displays the detail page with the user's profile information. To learn more about making API requests, see Zendesk REST API tutorial - Python edition.

Code complete

The app is done and ready for testing. Here's the finished version of the oauth_app.py file:

Make sure your indentation is correct, then run the app to test it.

Start the local server:

$ python3 oauth_app.py

In a browser, go to http://localhost:8080/home.

Run some tests.

If you can, try using different browsers as different Zendesk Support users.

When you're done, switch to your command-line interface and press Ctrl+C to shut down the server.

You can keep tweaking or adding to the app if you want. See the following resources for more information: