Setting Up OAuth 2.0 Flows in FastAPI

FastAPI is a modern, fast (high-performance) web framework for building APIs with Python based on standard Python type hints. OAuth 2.0 is an industry-standard protocol for authorization that enables third - party applications to access user resources in a secure and controlled manner. Integrating OAuth 2.0 flows into a FastAPI application can enhance security and provide a seamless user experience when dealing with external services. This blog will guide you through the process of setting up OAuth 2.0 flows in FastAPI, covering fundamental concepts, usage methods, common practices, and best practices.

Table of Contents

  1. Fundamental Concepts
  2. Setting Up a Basic FastAPI Application
  3. Implementing OAuth 2.0 Flows in FastAPI
  4. Common Practices
  5. Best Practices
  6. Conclusion
  7. References

Fundamental Concepts

OAuth 2.0

OAuth 2.0 is an authorization framework that allows applications to access resources on behalf of a user. It involves several key components:

  • Resource Owner: The user who owns the protected resources.
  • Client: The application that wants to access the user’s resources.
  • Authorization Server: Issues access tokens to the client after the user’s authorization.
  • Resource Server: Holds the user’s protected resources and accepts access tokens for authentication.

Flows

There are several OAuth 2.0 flows, but the most common ones are:

  • Authorization Code Flow: Suitable for web applications. The client redirects the user to the authorization server, and after the user approves, the authorization server returns an authorization code. The client then exchanges this code for an access token.
  • Implicit Flow: Used mainly for single - page applications. The authorization server directly returns an access token to the client without the intermediate authorization code.
  • Client Credentials Flow: Used when the client wants to access its own resources on the resource server, without the involvement of a user.
  • Resource Owner Password Credentials Flow: The client directly receives the user’s username and password and exchanges them for an access token.

Setting Up a Basic FastAPI Application

First, make sure you have FastAPI and Uvicorn installed. You can install them using pip:

pip install fastapi uvicorn

Here is a simple FastAPI application:

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def read_root():
    return {"Hello": "World"}

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)

Save this code in a file named main.py and run it using the command python main.py. You can then access the application at http://localhost:8000.

Implementing OAuth 2.0 Flows in FastAPI

We will focus on the Authorization Code Flow as an example. First, install python - jwt and requests for handling tokens and making HTTP requests:

pip install python-jwt requests

Here is a simplified example of implementing the Authorization Code Flow in FastAPI:

from fastapi import FastAPI, Request, HTTPException
from fastapi.responses import RedirectResponse
import requests
import jwt
import os

app = FastAPI()

# Replace these values with your actual client ID, client secret, and authorization endpoints
CLIENT_ID = os.getenv("CLIENT_ID")
CLIENT_SECRET = os.getenv("CLIENT_SECRET")
AUTHORIZATION_URL = "https://example.com/oauth/authorize"
TOKEN_URL = "https://example.com/oauth/token"
REDIRECT_URI = "http://localhost:8000/callback"


@app.get("/login")
def login():
    params = {
        "client_id": CLIENT_ID,
        "redirect_uri": REDIRECT_URI,
        "response_type": "code",
        "scope": "openid profile email"
    }
    url = f"{AUTHORIZATION_URL}?{'&'.join([f'{k}={v}' for k, v in params.items()])}"
    return RedirectResponse(url)


@app.get("/callback")
async def callback(request: Request):
    code = request.query_params.get("code")
    if not code:
        raise HTTPException(status_code=400, detail="Authorization code not provided")

    data = {
        "client_id": CLIENT_ID,
        "client_secret": CLIENT_SECRET,
        "code": code,
        "redirect_uri": REDIRECT_URI,
        "grant_type": "authorization_code"
    }
    response = requests.post(TOKEN_URL, data=data)
    if response.status_code != 200:
        raise HTTPException(status_code=400, detail="Failed to obtain access token")

    token_data = response.json()
    access_token = token_data.get("access_token")
    try:
        decoded_token = jwt.decode(access_token, options={"verify_signature": False})
        return decoded_token
    except jwt.exceptions.DecodeError:
        raise HTTPException(status_code=400, detail="Invalid access token")

In this example, the /login endpoint redirects the user to the authorization server. After the user approves, the authorization server redirects the user back to the /callback endpoint with an authorization code. The /callback endpoint then exchanges the code for an access token and decodes it.

Common Practices

  • Securely Store Credentials: Store client IDs, client secrets, and other sensitive information in environment variables or a secure secrets manager.
  • Validate Tokens: Always validate the access tokens received from the authorization server. This can involve checking the token’s signature, expiration time, and issuer.
  • Error Handling: Implement proper error handling in your application to handle cases such as invalid authorization codes, expired tokens, and network errors.

Best Practices

  • Use HTTPS: Always use HTTPS in production to protect the confidentiality and integrity of the data transmitted between the client, authorization server, and resource server.
  • Limit Token Scope: Request only the necessary scopes when obtaining an access token. This reduces the risk of unauthorized access to user resources.
  • Refresh Tokens: Implement the use of refresh tokens to obtain new access tokens when the current ones expire, without requiring the user to re - authorize.

Conclusion

Setting up OAuth 2.0 flows in FastAPI can significantly enhance the security and functionality of your application. By understanding the fundamental concepts, following common practices, and implementing best practices, you can create a robust and secure authentication and authorization system. Remember to always test your application thoroughly and stay updated with the latest security standards.

References