Python Friday #228: HTTP Basic Authentication in FastAPI

There are many ways we can secure an endpoint in FastAPI. As a first approach we explore HTTP basic authentication, a not so secure way but it allows us to get a first glimpse into the different parts of FastAPI that we need to protect an endpoint.

This post is part of my journey to learn Python. You find the code for this post in my PythonFriday repository on GitHub.

 

HTTP basic authentication?

For this authentication method the browser sends the username and password as part of the header to the application. While we cannot see the password in clear text, it is only encoded as a Base64 string and completely unprotected:

Authorization: Basic c3RhbmxleTpzZWNyZXQ=

When we use FastAPI in development mode, we use HTTP and not HTTPS, what allows everyone to scan the traffic and read the password. With HTTPS that will be less of a problem, but still not up to the state of the art. We will explore better approaches in the next posts.

 

Test the authentication

As with the posts in the past, we first start with a few tests to define what behaviour we expect from our API. I created a new project in the folder basic_auth and it has no connection to the to-do list API we used so far with FastAPI. Do not forget to add an empty __init__.py next to the test file.

As always, write one test, then write the implementation. Repeat until you have the complete feature. Here are the 4 basic tests we need to check if the endpoint is protected:

 

Create the FastAPI application

We can now create a new FastAPI application in the main.py file and add these parts:

  • The users dictionary is our mock data store and contains 2 users.
  • The get_current_username() method is the bridge between the HTTP Basic authentication and our user store. It will check if the password match and throw an exception if this is not the case.
  • To prevent timing attacks, we go through the process of verifying the password even when there is no user for the given username. That little extra work gives us near identical runtimes for all tests that check credentials (you can verify that with pytest --durations=0 )
  • The read_current_user() method gets the injected user name and reads the data we have about that user.

The example here is the HTTP Basic Auth example from the official documentation, extended with Bcrypt and offers a second user:

We can now run our tests and they all should pass:

 

Access the endpoint in the browser

First, we must start our API with this command:

If we open the endpoint in the browser, we get the HTTP Basic Auth message from the server that lets the browser open a form to enter the username and the password:

The browser asks for the username and the password.

We can enter stanley and secret to get access to the data:

With the successfully entered username and password we now see the details of our user stanley.

 

Access the endpoint in the documentation

We can go to the OpenAPI documentation in /docs and use the button “Authorize” at the top of the page to enter our credentials:

The username and password form pops up in Swagger.

We can enter mike and password to get the login for the other user. In our endpoint documentation we can use the “Try it out” button and then click on execute to get the data we have about the user mike:

The documentation works with our credentials and shows the details for mike.

 

Next

We can now use HTTP basic authentication to protect our endpoint from unauthorised people. As explained above, the password is only encoded and not protected as long as we use HTTP. We fix that later when it comes to the deployment.

Next week we use OAuth2 and JWT tokens to better protect our API.

1 thought on “Python Friday #228: HTTP Basic Authentication in FastAPI”

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.