This repository serves as a foundational backend project built with FastAPI, SQLAlchemy (ORM), and PostgreSQL, featuring robust user authentication using JSON Web Tokens (JWT) and role-based access control (RBAC). It's designed as a starting point for building scalable and secure web APIs.
- FastAPI Framework: Modern, fast (high-performance), web framework for building APIs with Python 3.7+ based on standard Python type hints.
- SQLAlchemy ORM: Powerful and flexible Object Relational Mapper for interacting with PostgreSQL.
- PostgreSQL Database: Robust and widely used relational database.
- Alembic Migrations: Database schema version control to manage database changes.
- User Management: Endpoints for creating and retrieving user accounts.
- Password Hashing: Secure password storage using Bcrypt.
- JWT Authentication: Secure user login and session management using Access Tokens.
- Role-Based Access Control (RBAC): Fine-grained control over API endpoint access based on user roles (e.g.,
user,hr,admin). - Modular API Structure: Organized
apiendpoints into separate modules (auth,users) for better maintainability. - Pydantic Schemas: Data validation and serialization for API requests and responses, providing automatic OpenAPI documentation.
- Environment Configuration: Secure loading of sensitive settings via
.envfiles usingPydantic-Settings.
Before you begin, ensure you have the following installed on your system:
- Python 3.8+: Download from python.org.
- PostgreSQL: Install PostgreSQL from postgresql.org.
- For Debian/Ubuntu, typically:
sudo apt update sudo apt install postgresql postgresql-contrib sudo systemctl start postgresql sudo systemctl enable postgresql
- For Debian/Ubuntu, typically:
Follow these steps to get the project up and running on your local machine.
If you have a remote repository:
git clone [https://github.com/YOUR_GITHUB_USERNAME/fastapi-auth-base.git](https://github.com/YOUR_GITHUB_USERNAME/fastapi-auth-base.git)
cd fastapi-auth-baseIf you're starting locally and will connect to GitHub later:
mkdir fastapi-auth-base
cd fastapi-auth-base
git init
git branch -M main # Ensure your default branch is 'main'It's highly recommended to use a virtual environment to manage project dependencies.
python3 -m venv .venv
source .venv/bin/activateYou should see (.venv) in your terminal prompt, indicating the environment is active.
Install all required Python packages using pip:
pip install -r requirements.txtConnect to your PostgreSQL server (e.g., as the postgres user) and create a database and a dedicated user for your application.
sudo -i -u postgres
psqlAt the psql prompt:
CREATE DATABASE learnobots_db;
CREATE USER learnobots_user WITH ENCRYPTED PASSWORD 'your_strong_password';
GRANT ALL PRIVILEGES ON DATABASE learnobots_db TO learnobots_user;
\qThen exit the postgres user shell:
exitRemember to replace 'your_strong_password' with a secure password.
Create a .env file in the root of your project directory. This file will store your database connection string and JWT secret key. This file is excluded from Git using .gitignore for security.
touch .envOpen .env and add the following, replacing placeholders with your actual details:
DATABASE_URL="postgresql://learnobots_user:your_strong_password@localhost:5432/learnobots_db"
PROJECT_NAME="Learnobots Job Portal API"
API_V1_STR="/api/v1"
SECRET_KEY="YOUR_GENERATED_JWT_SECRET_KEY" # Generate with: python -c 'import secrets; print(secrets.token_urlsafe(32))'
ALGORITHM="HS256"
ACCESS_TOKEN_EXPIRE_MINUTES=30
REFRESH_TOKEN_EXPIRE_DAYS=7Generate a unique SECRET_KEY!
Alembic is set up to read the DATABASE_URL from your environment variables. Ensure the alembic.ini and alembic/env.py files are configured as follows:
alembic.ini: Findsqlalchemy.url == and set it to${DATABASE_URL}.
# alembic.ini (snippet)
# ...
sqlalchemy.url = ${DATABASE_URL}
# ...alembic/env.py: Ensuretarget_metadatapoints toBasefromapp.db.sessionandload_dotenvis called.
# alembic/env.py (snippet)
# ...
from app.db.session import Base
from dotenv import load_dotenv, find_dotenv
load_dotenv(find_dotenv()) # This loads variables from .env
target_metadata = Base
# ...
def run_migrations_online():
url = os.getenv("DATABASE_URL") # Ensure this line fetches from environment
connectable = engine_from_config(
{"sqlalchemy.url": url}, # Pass the URL fetched from environment
prefix="sqlalchemy.",
poolclass=pool.NullPool,
)
# ... rest of the functionApply the initial database schema to your PostgreSQL database.
# Ensure your .env variables are loaded for Alembic, or that alembic/env.py handles it
# If alembic/env.py has load_dotenv(), this step is just:
alembic upgrade head
# Otherwise, you might need:
# export $(grep -v '^#' .env | xargs) && alembic upgrade headFrom the project root directory (fastapi-auth-base), start the Uvicorn server:
uvicorn app.api.main:app --reloadThe application will be accessible at http://127.0.0.1:8000.
Once the server is running, you can access the interactive API documentation (Swagger UI) at http://127.0.0.1:8000/docs. This interface allows you to explore and test all available endpoints.
All API endpoints are prefixed with /api/v1.
- Create User (Public Registration):
POST /api/v1/users- Request Body:
{"email": "your@example.com", "password": "your_strong_password"} - Purpose: Register a new user with a default role of "user".
- Request Body:
- Login & Get Token:
POST /api/v1/auth/token- Request Body (Form Data):
username: your@example.com, password: your_strong_password - Purpose: Authenticate and receive a JWT
access_token. Copy this token for authenticated requests.
- Request Body (Form Data):
To test RBAC, you'll need users with different roles. Initially, new users are created with role="user".
You can manually update a user's role in the PostgreSQL database for testing purposes:
- Connect to your database using
psql:
psql -U learnobots_user -d learnobots_db- Update a user's role (replace with your user's email):
UPDATE users SET role = 'hr' WHERE email = 'test_hr@example.com';
UPDATE users SET role = 'admin' WHERE email = 'test_admin@example.com';
\q-
Authorize in Swagger UI:
- Click the Authorize button (top right of Swagger UI).
- In the dialog, enter your
access_tokenprefixed withBearer(e.g.,Bearer eyJ...). - Click Authorize, then Close.
-
Test Endpoints:
-
Get All Users
GET /api/v1/users/
Expected Behavior:- Unauthenticated:
401 Unauthorized - Authenticated with user role:
403 Forbidden - Authenticated with hr or admin role:
200 OK(returns list of users)
- Unauthenticated:
-
Get User by ID
GET /api/v1/users/{user_id}
Expected Behavior:- Unauthenticated:
401 Unauthorized - Authenticated with user role:
403 Forbidden - Authenticated with hr or admin role:
200 OK(returns specific user details)
- Unauthenticated:
-
```text . ├── app/ │ ├── api/ │ │ ├── __init__.py │ │ ├── auth.py # Authentication related endpoints (login, token) │ │ ├── main.py # Main FastAPI application instance and router inclusion │ │ └── users.py # User management endpoints (create, retrieve) │ ├── core/ │ │ ├── __init__.py │ │ ├── auth.py # JWT token creation and validation utilities │ │ ├── config.py # Application settings loaded from .env │ │ └── deps.py # FastAPI dependencies for authentication and RBAC │ ├── db/ │ │ ├── __init__.py │ │ ├── base_class.py # SQLAlchemy declarative base and common model fields │ │ ├── models.py # SQLAlchemy ORM models (e.g., User) │ │ └── session.py # SQLAlchemy engine and session setup │ └── schemas/ │ ├── __init__.py │ ├── token.py # Pydantic schemas for JWT tokens │ └── user.py # Pydantic schemas for user data validation ├── alembic/ # Alembic migration environment │ ├── versions/ # Migration scripts │ └── env.py # Alembic environment configuration ├── alembic.ini # Alembic configuration file ├── tests/ # Unit and integration tests (empty for now) │ └── __init__.py ├── .env # Environment variables (IGNORED by Git) ├── .gitignore # Specifies files/directories to ignore in Git └── requirements.txt # Project dependencies ``` Contributions are welcome! Please follow standard Git Flow or GitHub Flow for feature development and bug fixes.
This project is licensed under the MIT License - see the LICENSE file for details.