Python

Gravatar for evan.sims@auth0.com
By Evan Sims

This tutorial demonstrates how to add user login to a Python web Application built with the Flask framework and Authlib OAuth library. We recommend that you log in to follow this quickstart with examples configured for your account.

I want to explore a sample app

2 minutes

Get a sample configured with your account settings or check it out on Github.

View on Github
System requirements: Python 3 | Authlib 1.0 | Flask 2.0

Configure Auth0

Get Your Application Keys

When you signed up for Auth0, a new application was created for you, or you could have created a new one. You will need some details about that application to communicate with Auth0. You can get these details from the Application Settings section in the Auth0 dashboard.

App Dashboard

You need the following information:

  • Domain
  • Client ID
  • Client Secret

Configure Callback URLs

A callback URL is a URL in your application where Auth0 redirects the user after they have authenticated. The callback URL for your app must be added to the Allowed Callback URLs field in your Application Settings. If this field is not set, users will be unable to log in to the application and will get an error.

Configure Logout URLs

A logout URL is a URL in your application that Auth0 can return to after the user has been logged out of the authorization server. This is specified in the returnTo query parameter. The logout URL for your app must be added to the Allowed Logout URLs field in your Application Settings. If this field is not set, users will be unable to log out from the application and will get an error.

Install dependencies

For the purposes of this example, we'll be using the Authlib OAuth library and Flask.

Begin by creating a requirements.txt file in your project directory:

# 📁 requirements.txt -----

flask>=2.0.3
python-dotenv>=0.19.2
authlib>=1.0
requests>=2.27.1

Was this helpful?

/

You should now run pip install -r requirements.txt from your shell to make these dependencies available to your project.

Configure your .env file

Next, create an .env file in your project directory. This file will hold your client keys and other configuration details.

# 📁 .env -----

AUTH0_CLIENT_ID={yourClientId}
AUTH0_CLIENT_SECRET={yourClientSecret}
AUTH0_DOMAIN={yourDomain}
APP_SECRET_KEY=

Was this helpful?

/
  • Generate a suitable string for APP_SECRET_KEY using openssl rand -hex 32 from your shell.

Setup your application

Now you're ready to start writing your application. Create a server.py file in your project directory - this file will hold all of your application logic.

Begin by importing all the libraries your application will be making use of:

# 📁 server.py -----

import json
from os import environ as env
from urllib.parse import quote_plus, urlencode

from authlib.integrations.flask_client import OAuth
from dotenv import find_dotenv, load_dotenv
from flask import Flask, redirect, render_template, session, url_for

Was this helpful?

/

Next, your application will need to load the configuration .env file you made in the previous step:

# 👆 We're continuing from the steps above. Append this to your server.py file.

ENV_FILE = find_dotenv()
if ENV_FILE:
    load_dotenv(ENV_FILE)

Was this helpful?

/

Now you can configure Flask for your application's needs:

# 👆 We're continuing from the steps above. Append this to your server.py file.

app = Flask(__name__)
app.secret_key = env.get("APP_SECRET_KEY")

Was this helpful?

/

Finally, you can now configure Authlib to handle your application's authentication with Auth0:

# 👆 We're continuing from the steps above. Append this to your server.py file.

oauth = OAuth(app)

oauth.register(
    "auth0",
    client_id=env.get("AUTH0_CLIENT_ID"),
    client_secret=env.get("AUTH0_CLIENT_SECRET"),
    client_kwargs={
        "scope": "openid profile email",
    },
    server_metadata_url=f'https://{env.get("AUTH0_DOMAIN")}/.well-known/openid-configuration'
)

Was this helpful?

/

You can learn more about the configuration options available for Authlib's OAuth register() method from their documentation.

Setup your routes

For this demonstration, we'll be adding 4 routes for your application: your login, callback, logout and home routes.

Triggering authentication with /login

When visitors to your app visit the /login route, they'll be redirected to Auth0 to begin the authentication flow.

# 👆 We're continuing from the steps above. Append this to your server.py file.

@app.route("/login")
def login():
    return oauth.auth0.authorize_redirect(
        redirect_uri=url_for("callback", _external=True)
    )

Was this helpful?

/

Finalizing authentication with /callback

After your users finish logging in with Auth0, they'll be returned to your application at the /callback route. This route is responsible for actually saving the session for the user, so when they visit again later, they won't have to sign back in all over again.

# 👆 We're continuing from the steps above. Append this to your server.py file.

@app.route("/callback", methods=["GET", "POST"])
def callback():
    token = oauth.auth0.authorize_access_token()
    session["user"] = token
    return redirect("/")

Was this helpful?

/

Clearing a session with /logout

As you might expect, this route handles signing a user out from your application. It will clear the user's session in your app, and briefly redirect to Auth0's logout endpoint to ensure their session is completely clear, before they are returned to your home route (covered next.)

# 👆 We're continuing from the steps above. Append this to your server.py file.

@app.route("/logout")
def logout():
    session.clear()
    return redirect(
        "https://" + env.get("AUTH0_DOMAIN")
        + "/v2/logout?"
        + urlencode(
            {
                "returnTo": url_for("home", _external=True),
                "client_id": env.get("AUTH0_CLIENT_ID"),
            },
            quote_via=quote_plus,
        )
    )

Was this helpful?

/

There's no place like /home

Last but not least, your home route will serve as a place to either render an authenticated user's details, or offer to allow visitors to sign in.

# 👆 We're continuing from the steps above. Append this to your server.py file.

@app.route("/")
def home():
    return render_template("home.html", session=session.get('user'), pretty=json.dumps(session.get('user'), indent=4))

Was this helpful?

/

Server instantiation

Finally, you'll need to add some small boilerplate code for Flask to actually run your app and listen for connections.

# 👆 We're continuing from the steps above. Append this to your server.py file.

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=env.get("PORT", 3000))

Was this helpful?

/

Add templates

Now we just need to create the simple template files used in the routes about (during render_template() calls).

Create a new sub-directory in your project folder named templates, and create two files within: dashboard.html and home.html. You can paste the content from the two fields below into those files, respectfully:

# 📁 templates/home.html -----

<html>
  <head>
    <meta charset="utf-8" />
    <title>Auth0 Example</title>
  </head>
  <body>
    {% if session %}
        <h1>Welcome {{session.userinfo.name}}!</h1>
        <p><a href="/logout">Logout</a></p>
        <div><pre>{{pretty}}</pre></div>
    {% else %}
        <h1>Welcome Guest</h1>
        <p><a href="/login">Login</a></p>
    {% endif %}
  </body>
</html>

Was this helpful?

/

Run your application

You're ready to run your application! From your project directory, open a shell and use:

python3 server.py

Was this helpful?

/

Your application should now be ready to open from your browser at http://localhost:3000.