JWT Authentication with Blacksheep and Auth0 | Python.

JWT Authentication with Blacksheep and Auth0 | Python.

Blacksheep has built-in authentication and authorization support and allows us to integrate with services like Auth0, Azure Active Directory, Azure Active Directory B2C, or Okta.

For this tutorial, we will build an API with the Blacksheep framework with JWT authentication. In our API there will be a public endpoint and a private endpoint only for authorized users.

We are going to use the same example shown in the documentation, but instead, we are going to use Auth0. So, we need an Auth0 account.

Prerequisites

  • Basic Python knowledge

  • How to create a basic web app with Blacksheep Framework

If you don't know how to create an app with Blacksheep, here is the documentation explaining it.

Auth0

According to its documentation:

Auth0 is an identity platform to add sophisticated authentication and authorization to your applications. Centralize and manage users from multiple identity providers and give them branded, seamless signup and login experiences. Finely control access with a degree of customization that can accommodate even the most complex security requirements. Easily deploy your implementation and monitor status and services.

Create an Auth0 application

image.png

After we create an account, we click on "Sign Up".

After our account is created. We go to our Dashboard a click on "Create Application".

image.png

We select "Regular Web Applications". And then, choose Python.

image.png

.env file

AUTHORITY={DOMAIN}
AUDIENCE=https://{DOMAIN}/api/v2/
ISSUERS= https://{DOMAIN}

Then, we go to our app's settings copy the "Domain" and "Client ID" and paste them inside a .env file.

We will use the Client ID when we need to request the token.

Setup

We create our virtual environment.

py -m venv venv
cd venv/Scripts
activate

Then, we install the packages we are going to use.

pip install uvicorn blacksheep[full] python-dotenv

When we import blacksheep[full] we are importing the necessary dependencies to use JWT Bearer authentication.

"The authentication and authorization logic implemented for BlackSheep was packed and published into a dedicated library:guardpost (in pypi)."

Blacksheep uses GuarPost to handle authentication and authorization. It provides a basic framework to handle authentication and authorization for any kind of Python application.

main.py

from blacksheep import Application
from blacksheep.server.authorization import auth
from guardpost.common import AuthenticatedRequirement, Policy

from blacksheep.server.authentication.jwt import JWTBearerAuthentication

from dotenv import load_dotenv
import os

load_dotenv()

app = Application()

app.use_authentication().add(
    JWTBearerAuthentication(
        authority=os.environ.get("AUTHORITY"),
        valid_audiences=[os.environ.get("AUDIENCE")],
        valid_issuers=[os.environ.get("ISSUERS")],
    )
)

authorization = app.use_authorization()

authorization += Policy("any_name", AuthenticatedRequirement())

get = app.router.get

@get("/")
def home():
    return "Hello, World"


@auth("any_name")
@get("/api/message")
def example():
    return "This is only for authenticated users"

We create an instance of JWTBearerAuthentication class and add the parameters: Authority, audiences, and issuers.

JWTBearerAuthentication is a child class of AuthenticationHandler, that can parse and verify JWT Bearer access tokens to identify users.

Creates a new instance of JWTBearerAuthentication, which tries to obtains the identity of the user from the "Authorization" request header, handling JWT Bearer tokens. Only standard authorization headers starting with the Bearer string are handled.

JWTBearerAuthentication has more attributes, we can see them here.

When we start our server we will notice that we can't access the api/message endpoint. The server returns an "Unauthorized" status code.

Getting a token

We need the following information from our Auth0 Dashboard: Client ID and Client Secret.

Using a web client, we make a POST request to the URL: https://{your domain}.com/oauth/token. And with the following body:

{"client_id":"CLIENT ID","client_secret":"CLIENT SECRET","audience":"https://{Your domain}.us.auth0.com/api/v2/","grant_type":"client_credentials"}

If the HTTP response is OK, we will receive a response body like this:

"access_token":"TOKEN","expires_in":86400,"token_type":"Bearer"}

Now, we make a GET request to our protected endpoint, but we add the "Bearer" authorization header and paste the token.

Conclusion

I liked the approach of Blacksheep, it is the first time I use an authentication service like Auth0. I think it offers something different from other frameworks. And it saves a lot of time. I still have to learn how to write a custom authentication handler, and probably write about it.

Thank you for taking the time to read this article.

If you have any recommendations about other packages, architectures, how to improve my code, English, or anything; please leave a comment or contact me through Twitter, or LinkedIn.

The source code is here

References