Python API

You can get started by either downloading the seed project or if you would like to add Auth0 to an existing application you can follow the tutorial steps.

Sample Project

Download this sample project configured with your Auth0 API Keys.

System Requirements
  • Python 2.7
  • Flask 0.10.1
  • Flask-Cors 2.1.0
  • PyJWT 1.4.0
Show requirements

If you have an existing application, please follow the steps below.

1. Add the needed dependencies

In this example, we'll be using Flask and we'll be validating the JWT. For that, add the following dependencies to your requirements.txt.

flask
PyJWT
flask-cors

2. Create the JWT Validation annotation

Now, you need to validate the JWT. For that, we'll create a custom annotation.

import jwt
import os

from functools import wraps
from flask import Flask, request, jsonify, _request_ctx_stack
from werkzeug.local import LocalProxy
from flask.ext.cors import cross_origin

app = Flask(__name__)
# Authentication annotation
current_user = LocalProxy(lambda: _request_ctx_stack.top.current_user)

# Authentication attribute/annotation
def authenticate(error):
  resp = jsonify(error)

  resp.status_code = 401

  return resp

def requires_auth(f):
  @wraps(f)
  def decorated(*args, **kwargs):
    auth = request.headers.get('Authorization', None)
    if not auth:
      return authenticate({'code': 'authorization_header_missing', 'description': 'Authorization header is expected'})

    parts = auth.split()

    if parts[0].lower() != 'bearer':
      return {'code': 'invalid_header', 'description': 'Authorization header must start with Bearer'}
    elif len(parts) == 1:
      return {'code': 'invalid_header', 'description': 'Token not found'}
    elif len(parts) > 2:
      return {'code': 'invalid_header', 'description': 'Authorization header must be Bearer + \s + token'}

    token = parts[1]
    try:
        payload = jwt.decode(
            token,
            'YOUR_CLIENT_SECRET',
            audience='YOUR_CLIENT_ID'
        )
    except jwt.ExpiredSignature:
        return authenticate({'code': 'token_expired', 'description': 'token is expired'})
    except jwt.InvalidAudienceError:
        return authenticate({'code': 'invalid_audience', 'description': 'incorrect audience, expected: YOUR_CLIENT_ID'})
    except jwt.DecodeError:
        return authenticate({'code': 'token_invalid_signature', 'description': 'token signature is invalid'})

    _request_ctx_stack.top.current_user = user = payload
    return f(*args, **kwargs)

  return decorated

3. Use this annotation in your methods

Now, you can just use this annotation in your methods

# Controllers API

# This doesn't need authentication
@app.route("/ping")
@cross_origin(headers=['Content-Type', 'Authorization'])
def ping():
    return "All good. You don't need to be authenticated to call this"

# This does need authentication
@app.route("/secured/ping")
@cross_origin(headers=['Content-Type', 'Authorization'])
@requires_auth
def securedPing():
    return "All good. You only get this message if you're authenticated"

4. Call Your API

You can now make requests against your secure API by providing the Authorization header in your requests with a valid JWT id_token.


curl --request GET \
  --url http://localhost:8000/path_to_your_api \
  --header 'authorization: Bearer YOUR_ID_TOKEN_HERE'
var client = new RestClient("http://localhost:8000/path_to_your_api");
var request = new RestRequest(Method.GET);
request.AddHeader("authorization", "Bearer YOUR_ID_TOKEN_HERE");
IRestResponse response = client.Execute(request);
package main

import (
	"fmt"
	"net/http"
	"io/ioutil"
)

func main() {

	url := "http://localhost:8000/path_to_your_api"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("authorization", "Bearer YOUR_ID_TOKEN_HERE")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := ioutil.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
HttpResponse<String> response = Unirest.get("http://localhost:8000/path_to_your_api")
  .header("authorization", "Bearer YOUR_ID_TOKEN_HERE")
  .asString();
var settings = {
  "async": true,
  "crossDomain": true,
  "url": "http://localhost:8000/path_to_your_api",
  "method": "GET",
  "headers": {
    "authorization": "Bearer YOUR_ID_TOKEN_HERE"
  }
}

$.ajax(settings).done(function (response) {
  console.log(response);
});
var request = require("request");

var options = { method: 'GET',
  url: 'http://localhost:8000/path_to_your_api',
  headers: { authorization: 'Bearer YOUR_ID_TOKEN_HERE' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
#import <Foundation/Foundation.h>

NSDictionary *headers = @{ @"authorization": @"Bearer YOUR_ID_TOKEN_HERE" };

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://localhost:8000/path_to_your_api"]
                                                       cachePolicy:NSURLRequestUseProtocolCachePolicy
                                                   timeoutInterval:10.0];
[request setHTTPMethod:@"GET"];
[request setAllHTTPHeaderFields:headers];

NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request
                                            completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
                                                if (error) {
                                                    NSLog(@"%@", error);
                                                } else {
                                                    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;
                                                    NSLog(@"%@", httpResponse);
                                                }
                                            }];
[dataTask resume];
$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_PORT => "8000",
  CURLOPT_URL => "http://localhost:8000/path_to_your_api",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "GET",
  CURLOPT_HTTPHEADER => array(
    "authorization: Bearer YOUR_ID_TOKEN_HERE"
  ),
));

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
  echo "cURL Error #:" . $err;
} else {
  echo $response;
}
import http.client

conn = http.client.HTTPConnection("localhost:8000")

headers = { 'authorization': "Bearer YOUR_ID_TOKEN_HERE" }

conn.request("GET", "/path_to_your_api", headers=headers)

res = conn.getresponse()
data = res.read()

print(data.decode("utf-8"))
require 'uri'
require 'net/http'

url = URI("http://localhost:8000/path_to_your_api")

http = Net::HTTP.new(url.host, url.port)

request = Net::HTTP::Get.new(url)
request["authorization"] = 'Bearer YOUR_ID_TOKEN_HERE'

response = http.request(request)
puts response.read_body
import Foundation

let headers = ["authorization": "Bearer YOUR_ID_TOKEN_HERE"]

var request = NSMutableURLRequest(URL: NSURL(string: "http://localhost:8000/path_to_your_api")!,
                                        cachePolicy: .UseProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.HTTPMethod = "GET"
request.allHTTPHeaderFields = headers

let session = NSURLSession.sharedSession()
let dataTask = session.dataTaskWithRequest(request, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    println(error)
  } else {
    let httpResponse = response as? NSHTTPURLResponse
    println(httpResponse)
  }
})

dataTask.resume()

5. You're done!

Now you have both your FrontEnd and Backend configured to use Auth0. Congrats, you're awesome!

Note for Python 2.7

If you're using Python 2.7 and you already have the jwt package installed, you need to do the following to get this working:

pip uninstall jwt
pip uninstall pyjwt
pip install pyjwt
Use Auth0 for FREECreate free Account