Skip to content

joartola/simple-jwt-authentication

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

JWT Authentication Example

A simple full-stack application demonstrating JWT (JSON Web Token) authentication with Express API, React web frontend, and React Native mobile app. Perfect for teaching students the basics of token-based authentication across different platforms.

📁 Project Structure

This is a monorepo using npm workspaces:

JWT-Token-Example/
├── api/                    # Express backend
│   ├── middleware/         # Authentication middleware
│   ├── routes/            # API routes
│   ├── server.js          # Main server file
│   └── .env               # Environment variables
├── client/                # React web frontend
│   ├── src/
│   │   ├── components/    # React components
│   │   ├── App.jsx        # Main App component
│   │   └── main.jsx       # Entry point
│   └── index.html
├── mobile/                # React Native mobile app (Expo)
│   ├── src/
│   │   ├── screens/       # Mobile screens
│   │   └── services/      # API services
│   ├── App.js             # Main mobile app
│   └── app.json           # Expo configuration
├── documentation/         # Educational documentation
│   └── conceptos-jwt.md   # JWT concepts in Spanish
└── package.json           # Root workspace configuration

🚀 Getting Started

Prerequisites

  • Node.js (v16 or higher)
  • npm (v7 or higher)
  • For mobile: Expo Go app on your phone OR iOS Simulator/Android Emulator

Installation

  1. Install all dependencies (API, web client, and mobile):
npm install

This will install dependencies for the root workspace and all three workspaces (API, client, and mobile).

Running the Application

Web App (React)

You have several options:

Option 1: Run both API and web client together (recommended)

npm run dev

This will start:

Option 2: Run API and web client separately

Terminal 1 - Start the API:

npm run dev:api

Terminal 2 - Start the web client:

npm run dev:client

Mobile App (React Native + Expo)

Terminal 1 - Start the API (if not already running):

npm run dev:api

Terminal 2 - Start the mobile app:

npm run dev:mobile

Then:

  • Scan the QR code with Expo Go app (iOS/Android)
  • Or press i for iOS Simulator (Mac only)
  • Or press a for Android Emulator

Important for mobile: If testing on a physical device, update the API URL in mobile/src/services/api.js to use your computer's IP address instead of localhost.

See detailed mobile setup instructions in mobile/README.md

🔐 How JWT Authentication Works

1. Registration/Login

  • User submits credentials
  • Server validates and creates a JWT token
  • Token is signed with a secret key and contains user data
  • Token is sent back to the client

2. Storing the Token

  • Client stores the token in localStorage
  • Token is included in subsequent API requests

3. Protected Routes

  • Client sends token in Authorization header: Bearer <token>
  • Server middleware validates the token
  • If valid, request proceeds; if not, returns 401 Unauthorized

4. Token Expiration

  • Tokens expire after 1 hour (configurable in .env)
  • User must log in again after expiration

🎓 Teaching Points

For Students

  1. Token Structure: JWT tokens have three parts separated by dots:

    • Header (algorithm & token type)
    • Payload (user data & claims)
    • Signature (verification)
  2. Security Best Practices:

    • Never store sensitive data in the token payload (it's base64 encoded, not encrypted)
    • Always use HTTPS in production
    • Keep the JWT_SECRET secure and never commit it to version control
    • Set appropriate token expiration times
  3. API Endpoints:

    Public Endpoints:

    • POST /api/auth/register - Register a new user
    • POST /api/auth/login - Login and receive token
    • GET /api/auth/me - Verify token and get current user

    Protected Endpoints:

    • GET /api/protected/dashboard - Requires valid JWT token
    • GET /api/protected/profile - Requires valid JWT token
  4. Testing with cURL:

    # Register
    curl -X POST http://localhost:5000/api/auth/register \
      -H "Content-Type: application/json" \
      -d '{"username":"john","email":"john@example.com","password":"password123"}'
    
    # Login
    curl -X POST http://localhost:5000/api/auth/login \
      -H "Content-Type: application/json" \
      -d '{"email":"john@example.com","password":"password123"}'
    
    # Access protected route
    curl -X GET http://localhost:5000/api/protected/dashboard \
      -H "Authorization: Bearer YOUR_TOKEN_HERE"

🔧 Configuration

API Environment Variables (api/.env)

PORT=5000
JWT_SECRET=your_super_secret_jwt_key_change_this_in_production
JWT_EXPIRES_IN=1h

Important: Change the JWT_SECRET before deploying to production!

📦 Technologies Used

Backend (API)

  • Express.js - Web framework
  • jsonwebtoken - JWT token generation and verification
  • bcryptjs - Password hashing
  • cors - Cross-origin resource sharing
  • dotenv - Environment variables

Frontend (Web Client)

  • React - UI library
  • Vite - Build tool and dev server
  • Fetch API - HTTP requests

Mobile (React Native)

  • React Native - Mobile framework
  • Expo - Development platform
  • AsyncStorage - Local data persistence
  • Axios - HTTP client

🧪 Testing the Application

  1. Start both servers (npm run dev)
  2. Open http://localhost:3000 in your browser
  3. Register a new account
  4. You'll be automatically logged in and see:
    • Your user information
    • Protected content from the API
    • Your JWT token (for educational purposes)
  5. Try logging out and logging back in
  6. Check the Network tab in browser DevTools to see the token being sent

📝 Notes for Instructors

  • In-memory storage: The API uses an array to store users for simplicity. In production, use a proper database (MongoDB, PostgreSQL, etc.)
  • No refresh tokens: This example uses simple access tokens. Production apps should implement refresh tokens
  • CORS: The API accepts all origins. Configure this properly for production
  • Error handling: Basic error handling is implemented. Expand it for production use
  • Password requirements: Add stronger password validation in production

🔍 Common Issues

Port already in use: Change ports in api/.env (for API) and client/vite.config.js (for client)

CORS errors: Make sure both servers are running and the proxy is configured correctly

Token invalid: Check that the JWT_SECRET matches between requests and that the token hasn't expired

📚 Further Learning

  • Add a database (MongoDB with Mongoose, or PostgreSQL with Sequelize)
  • Implement refresh tokens
  • Add password reset functionality
  • Add email verification
  • Implement role-based access control (RBAC)
  • Add rate limiting to prevent abuse

📄 License

MIT - Feel free to use this for educational purposes!

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published