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 👍