A full-stack demonstration of JWT authentication with automatic token refresh, built with Rails (backend) and React (frontend). This project showcases enterprise-level authentication patterns and modern development practices.
- Purpose
- Architecture Overview
- Quick Start
- Access the applications
- Demo credentials (automatically created)
- Authentication Flow
This project was inspired by my first React.js project that leveraged GraphQL and an Apollo library for automatic authentication renewal. Wanting to expand my Full-stack skills, I decided to write my own simple token renewal library but I wanted it to be framework agnostic (apollo-link-token-refresh could only be used with Apollo GQL libraries) and dead simple so it could be used with any framework or even vanilla Javascript.
This project is a proof-of-concept that ties a simple Authentication service written in Rails with a React.js frontend using simple-jwt-refresh as a way for the client to authenticate and manage sessions.
flowchart LR
Frontend["<b>React.js Frontend</b><br/><br/>• Authentication Context API<br/>• Login/Registration<br/>• Protected Routing"]
Backend["<b>Authentication Service</b><br/><br/>• Refresh/Access tokens<br/>• Session Management<br/>• CORS Config"]
JWTLib["<b>simple-jwt-refresh</b><br/><br/>• Auto Refresh<br/>• Secure Token Storage<br/>• Error Handling"]
Backend -->|JSON Response| Frontend
JWTLib <--> Backend
Frontend <--> JWTLib
style Frontend fill:#33a,color:#fff,text-align:left
style Backend fill:#a33,color:#fff,text-align:left
style JWTLib fill:#cc6,color:#000,text-align:left
- Authentication Service (Rails) - Leverages Rails 8
Currentfeature for Session management - Frontend (React.js) - TanStack Form/Router, TailwindCSS, Zod for validation
- JWT Token Library (simple-jwt-refresh) - Token management with automatic refresh
- Docker Setup - Complete containerized environment
git clone https://github.com/aarona/jwt-refresh-app
cd jwt-refresh-app
# Edit .env with your configuration
cp .env.example .env# Move to the Authentication Service folder
# And build a new master.key and credentials file from scratch
cd auth-service
rm config/credentials.yml.enc
bundle exec rails credentials:edit
# Copy the master key from auth-service/config/master.key
# You may need to generate one. See the auth-service documentation
# for more details.
cat config/master.key
# Add this value to your .env file as RAILS_MASTER_KEYFrom the project root directory:
docker compose up --build# Stop and remove containers and networks for this project
docker compose down
# Stop and remove containers, networks, and volumes for this project
docker compose down -v
# Remove project-specific images and rebuild from scratch
docker compose down --rmi allIf you're having gem installation issues, you can force a rebuild with no cache:
docker compose build --no-cacheExpect the images to take about 2GB of disk space:
| Service | Description | Port | Approximate Size |
|---|---|---|---|
| jwt-refresh-app-auth-service | Rails API server | 3000 | 1.2GB |
| jwt-refresh-app-frontend | React development server | 3001 | 600MB+ |
| Volume Name | Purpose |
|---|---|
| jwt-refresh-app_auth-service-gems | Persistent storage for gems |
| jwt-refresh-app_frontend-node-modules | Persistent storage for node_modules |
Authentication Service local setup instructions
Front end Application local setup instructions
- Application: http://localhost:3001
- API Health Check: http://localhost:3000/up
| Name | Password | |
|---|---|---|
| Demo User | [email protected] | password123 |
| John Doe | [email protected] | password123 |
| Jane Smith | [email protected] | password123 |
(Optional) Create a new user. Check the "Keep me signed in" box to test longer refresh token lifetimes.
User submits credentials. Check the "Keep me signed in" box to test longer refresh token lifetimes.
For convenience, I built a logging panel that uses React Context API so you can watch authentication, routing and other logs easily without needing to open a developer console. The main purpose for this panel is to observe that the refresh token library I built automatically updates and manages access tokens with out the user needing to do anything.
On token expiry, library uses the refresh token to get new access tokens. You can observe this with the built-in logging panel mentioned above.
You can test session revocation by logging in with the same user using different browsers or even different devices on the network. To test this, revoke another device's session and the refresh the page from that device. You will then be logged out on that device as expected.
Sessions that were created with the "Keep me signed in" flag on with be marked as "extended".
You can test that your session is restored automatically by reloading the page.
Clears tokens and invalidates server session