A simple full-stack React application featuring JWT-based authentication with HTTP-only cookies in a monorepo structure. This project provides a secure authentication foundation for React applications with a Node.js/Express backend.
- 🔐 Secure Authentication: JWT tokens stored in HTTP-only cookies for enhanced security
- ⚛️ Modern React: Built with React 19, TypeScript, and Vite
- 🏗️ Monorepo Structure: Frontend and backend in a single repository
- 🛡️ Protected Routes: Authentication middleware for route protection
- 🎯 TypeScript: Full TypeScript support across the stack
- React 19 - Modern React with latest features
- TypeScript - Type-safe development
- Vite - Fast build tool and dev server
- React Router - Client-side routing
- Axios - HTTP client for API calls
- CSS3 - Custom styling
- Node.js - Runtime environment
- Express.js - Web framework
- TypeScript - Type-safe server development
- JWT - JSON Web Tokens for authentication
- bcryptjs - Password hashing
- HTTP-only Cookies - Secure token storage
- CORS - Cross-origin resource sharing
react-jwt/
├── frontend/ # React frontend application
│ ├── src/
│ │ ├── api/ # API communication layer
│ │ ├── components/ # Reusable React components
│ │ ├── contexts/ # React context providers
│ │ ├── pages/ # Page components
│ │ ├── utils/ # Utility functions
│ │ └── assets/ # Static assets and styles
│ ├── package.json
│ └── vite.config.ts
├── backend/ # Express.js backend API
│ ├── src/
│ │ ├── database/ # Data storage (in-memory)
│ │ ├── middleware/ # Express middleware
│ │ ├── routes/ # API route definitions
│ │ ├── services/ # Business logic
│ │ ├── types/ # TypeScript type definitions
│ │ └── server.ts # Main server file
│ ├── package.json
│ └── tsconfig.json
└── README.md
- Node.js (v18 or higher)
- npm or Yarn
-
Clone the repository
git clone <your-repo-url> cd react-jwt
-
Install backend dependencies
cd backend yarn install
-
Install frontend dependencies
cd ../frontend yarn install
-
Set up environment variables Create a
.env
file in the backend directory:PORT=3000 JWT_SECRET=your-super-secret-jwt-key-change-this-in-production NODE_ENV=development
-
Start the backend server
cd backend yarn dev
Server will run on
http://localhost:3000
-
Start the frontend development server
cd frontend yarn dev
Frontend will run on
http://localhost:5173
POST /auth/login
- User loginPOST /auth/register
- User registrationPOST /auth/logout
- User logout
GET /auth/user
- Get current user infoPOST /auth/echo-username
- Echo current usernamePOST /auth/store-data
- Store user-specific dataPOST /auth/get-data
- Retrieve user-specific data
- Registration/Login: User credentials are validated and a JWT token is generated
- HTTP-only Cookie: JWT is stored in an HTTP-only cookie for security
- Middleware Protection: Protected routes use authentication middleware
- Auto-refresh: Frontend automatically checks authentication status on app load
- Logout: Clears the HTTP-only cookie and resets client state
yarn dev
- Start development server with hot reloadyarn build
- Build for productionyarn start
- Start production serveryarn clean
- Clean build directory
yarn dev
- Start development serveryarn build
- Build for productionyarn preview
- Preview production buildyarn lint
- Run ESLint
- Port: Configure via
PORT
environment variable (default: 3000) - JWT Secret: Set
JWT_SECRET
environment variable - CORS: Currently configured for
http://localhost:5173
(Vite dev server)
- API Base URL: Configured in
src/api/auth.ts
- Vite Config: Customize build settings in
vite.config.ts
- HTTP-only Cookies: Prevents XSS attacks on JWT tokens
- Password Hashing: bcryptjs for secure password storage
- CORS Protection: Configured for specific origins
- Authentication Middleware: Server-side route protection
- TypeScript: Compile-time type checking
const handleLogin = async (username: string, password: string) => {
try {
await login(username, password);
// User is automatically updated in context
} catch (error) {
console.error('Login failed:', error);
}
};
const ProtectedComponent = () => {
const { isAuthenticated, user } = useAuth();
if (!isAuthenticated) {
return <div>Please log in</div>;
}
return <div>Welcome, {user?.username}!</div>;
};
Note: This is a development boilerplate only served "as-it-is", to be used as a base/for research purposes, not intended for production environment where ideally you would:
- Use a secure JWT secret
- Implement proper database storage
- Add rate limiting and security headers
- Set up proper logging and monitoring
- Configure HTTPS
- Add input validation and sanitization