OAuth (Open Authorization) from scratch

Published on
OAuth (Open Authorization) from scratch
Warning: This post is not completed yet or is in draft or not-publised yet. Please do not consider this as a final version. It may contain errors or incomplete information.

Let’s code an OAuth (Open Authorization) server from Scratch

In this tutorial, we will create an OAuth service from scratch using FastAPI and MongoDB. This service can be used for private organizations or government usage.

Prerequisites

  • Python 3.8+
  • MongoDB
  • FastAPI
  • Virtualenv (venv)

Step 1: Setting Up the Virtual Environment

First, we need to set up a virtual environment to manage our project dependencies.

# Install virtualenv if you haven't already
pip install venv

# Create a virtual environment
python -m venv .venv

# Activate the virtual environment
# --------------------------------
# On Windows
.venv\Scripts\activate

# On Unix or MacOS
source .venv/bin/activate

# [Optional]: Add .gitignore for venv files
echo "*" > .venv/.gitignore

Step 2: Installing Dependencies

Next, we need to install FastAPI and MongoDB dependencies.

pip install "fastapi[standard]" uvicorn pymongo

Step 3: Setting Up FastAPI

Create a new file called main.py and set up a basic FastAPI application.

# main.py
from fastapi import FastAPI

app = FastAPI()

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

Run the application using Uvicorn.

uvicorn main:app --reload

Step 4: Connecting to MongoDB

We will use the pymongo library to connect to MongoDB. Update main.py to include the MongoDB connection.

# main.py
from fastapi import FastAPI
from pymongo import MongoClient

app = FastAPI()

client = MongoClient("mongodb://localhost:27017/") # for now, local mongodb server in docker-container
db = client.oauth_db

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

Step 5: Creating OAuth Endpoints

Now, let’s create some basic OAuth endpoints. We will need endpoints for registering clients, generating tokens, and validating tokens.

# main.py
from fastapi import FastAPI, HTTPException
from pymongo import MongoClient
from pydantic import BaseModel
import uuid

app = FastAPI()

client = MongoClient("mongodb://localhost:27017/")
db = client.oauth_db

class Client(BaseModel):
    client_name: str
    client_id: str = None
    client_secret: str = None

@app.post("/register")
def register_client(client: Client):
    client.client_id = str(uuid.uuid4())
    client.client_secret = str(uuid.uuid4())
    db.clients.insert_one(client.dict())
    return client

@app.post("/token")
def generate_token(client_id: str, client_secret: str):
    client = db.clients.find_one({"client_id": client_id, "client_secret": client_secret})
    if not client:
        raise HTTPException(status_code=400, detail="Invalid client credentials")
    token = str(uuid.uuid4())
    db.tokens.insert_one({"client_id": client_id, "token": token})
    return {"access_token": token}

@app.get("/validate")
def validate_token(token: str):
    token_data = db.tokens.find_one({"token": token})
    if not token_data:
        raise HTTPException(status_code=400, detail="Invalid token")
    return {"status": "valid"}

Step 6: API Documentation with ReDoc

FastAPI automatically generates API documentation. You can access it at /docs for Swagger UI and /redoc for ReDoc.

# Run the application
uvicorn main:app --reload

Visit http://127.0.0.1:8000/redoc to see the ReDoc documentation.

>> Work in progress…!…!…!

Conclusion

In this tutorial, we created a basic OAuth service using FastAPI and MongoDB. This service includes endpoints for registering clients, generating tokens, and validating tokens. You can expand this service by adding more features and security measures as needed.

Happy coding 👍