Skip to main content

Command Palette

Search for a command to run...

Complete FastAPI JWT + Role-Based Authentication Tutorial with MySQL & Argon2

Updated
4 min read
Complete FastAPI JWT + Role-Based Authentication Tutorial with MySQL & Argon2
M
My journey from software engineer to Technical Product Manager gives me a unique perspective—I've built products with my own hands and now I lead the teams that build them. Currently contributing as Product Manager for news portal, eCommerce, inventory ERP, education management and school management platforms at Unite Business Automation. I specialize in turning complex business requirements into scalable, user-focused SaaS solutions. Let's connect if you're passionate about product strategy, technology and building things that users love.

In this tutorial, we’ll build a FastAPI authentication system with JWT tokens, role-based access (USER and ADMIN), and secure password hashing using Argon2. The backend will use MySQL. This project is fully structured and ready-to-run.

Project Overview

We will create:

  • Signup & Signin routes – register and login users

  • JWT authentication – secure endpoints with tokens

  • Role-based access – only specific roles can access certain routes

  • Argon2 password hashing – store passwords securely in the database

Bangla Summary: এই প্রোজেক্টে আমরা FastAPI ব্যবহার করে একটি সম্পূর্ণ অথেনটিকেশন সিস্টেম বানাবো। এখানে JWT টোকেন, রোল-বেসড এক্সেস এবং Argon2 পাসওয়ার্ড হ্যাশিং থাকবে। ডেটাবেস হিসেবে ব্যবহার করা হবে MySQL।

Project Structure

fastapi_auth/
│
├── auth/
│   ├── __init__.py
│   ├── model.py
│   ├── schema.py
│   ├── utils.py
│   └── roles.py
│
├── database.py
├── create_table.py
├── key.py
├── main.py
└── requirements.txt

Bangla Summary: ফোল্ডার স্ট্রাকচারটি এমনভাবে সাজানো যাতে কোডটি পড়া ও বুঝা সহজ হয়।

Step 1: Define Roles (auth/roles.py)

from enum import Enum

class Role(str, Enum):
    USER = "user"
    ADMIN = "admin"

Explanation:

  • We define USER and ADMIN roles using Python Enum.

  • This will help control which user can access which route.

Bangla: এখানে আমরা USER এবং ADMIN রোল তৈরি করেছি। এটি রাউটগুলিতে অ্যাক্সেস কন্ট্রোলের জন্য ব্যবহার হবে।

Step 2: Create User Model (auth/model.py)

from sqlalchemy import Column, String, Integer, Enum
from database import Base
from auth.roles import Role

class User(Base):
    __tablename__ = 'users'

    id = Column(Integer, primary_key=True, index=True)
    username = Column(String(100), unique=True, index=True)
    hashed_password = Column(String(500))
    email = Column(String(255), unique=True, index=True)
    role = Column(Enum(Role), default=Role.USER)

Explanation:

  • Defines the users table in MySQL.

  • Stores username, email, hashed password, and role.

Bangla: MySQL-এ users টেবিল তৈরী করা হয়েছে। এখানে ইউজারের নাম, ইমেইল, হ্যাশ করা পাসওয়ার্ড এবং রোল রাখা হবে।

Step 3: Pydantic Schemas (auth/schema.py)

from pydantic import BaseModel, EmailStr
from auth.roles import Role

class UserLogin(BaseModel):
    username: str
    password: str

class UserRegister(BaseModel):
    username: str
    password: str
    email: EmailStr
    role: Role

Explanation:

  • Pydantic schemas help validate request data.

Bangla: ইনপুট ডেটা ভ্যালিডেশনের জন্য Pydantic ব্যবহার করা হয়েছে।

Step 4: Password Hashing (auth/utils.py)

from passlib.context import CryptContext

pwd_context = CryptContext(
    schemes=["argon2"],
    deprecated="auto"
)

def hash_password(password: str):
    return pwd_context.hash(password)

def verify_password(plain_password, hashed_password):
    return pwd_context.verify(plain_password, hashed_password)

Explanation:

  • Uses Argon2 for secure password hashing.

Bangla: পাসওয়ার্ড নিরাপদ রাখতে Argon2 হ্যাশিং ব্যবহার করা হয়েছে।

Step 5: Database Connection (database.py)

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base

MYSQL_USER = "root"
MYSQL_PASSWORD = "12345"
MYSQL_HOST = "localhost"
MYSQL_PORT = 3306
MYSQL_DATABASE = "testmariadb"

DATABASE_URL = f"mysql+pymysql://{MYSQL_USER}:{MYSQL_PASSWORD}@{MYSQL_HOST}:{MYSQL_PORT}/{MYSQL_DATABASE}"

engine = create_engine(DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

Base = declarative_base()

Bangla: MySQL এর সাথে সংযোগ করার জন্য SQLAlchemy ব্যবহার করা হয়েছে।

Step 6: Create Tables (create_table.py)

from database import engine, Base
from auth.model import User

Base.metadata.create_all(bind=engine)
print("Tables created successfully!")

Bangla: এই স্ক্রিপ্টটি চালালে users টেবিল MySQL-এ তৈরী হবে।

Step 7: Secret Key (key.py)

import secrets

SECRET_KEY = secrets.token_urlsafe(32)
print("Your secret key:", SECRET_KEY)

Bangla: JWT টোকেনের জন্য একটি সিক্রেট কী তৈরি করা হয়েছে।

Step 8: Main App (main.py)

  • Implements signup, signin, JWT token generation, role-based routes.

Bangla: এখানে FastAPI দিয়ে অ্যাপ তৈরি হয়েছে। JWT টোকেন এবং রোল-বেসড অ্যাক্সেস কন্ট্রোলও রয়েছে।

Key Features:

  • /signup – register users

  • /signin – login users & get JWT

  • /profile – accessible to USER & ADMIN

  • /user/dashboard – only USER

  • /admin/dashboard – only ADMIN

Step 9: Install Dependencies (requirements.txt)

fastapi
uvicorn
SQLAlchemy
pymysql
python-jose
passlib[argon2]
python-dotenv

Bangla: প্রয়োজনীয় প্যাকেজগুলো এখানে উল্লেখ করা হয়েছে।Step 10: Run the App

  1. Install dependencies:
pip install -r requirements.txt
  1. Create tables:
python create_table.py
  1. Run FastAPI:
uvicorn main:app --reload
  1. Visit Swagger UI: http://127.0.0.1:8000/docs

Bangla: এই ধাপগুলো অনুসরণ করলে আপনি আপনার লোকাল সার্ভারে FastAPI অ্যাপ চালাতে পারবেন।

Conclusion:

You now have a fully functional JWT authentication system in FastAPI with:

  • Secure password hashing using Argon2

  • JWT token authentication

  • Role-based access control

  • MySQL database backend

Bangla: এখন আপনার কাছে একটি সম্পূর্ণ FastAPI অথেনটিকেশন সিস্টেম আছে, যেখানে নিরাপদ পাসওয়ার্ড হ্যাশিং, JWT টোকেন এবং রোল-বেসড এক্সেস কন্ট্রোল রয়েছে।