2026-05-18 13:17:28 -04:00
2026-05-18 13:17:28 -04:00
2026-05-18 13:17:28 -04:00
2026-05-18 13:17:28 -04:00
2026-05-18 13:17:28 -04:00
2026-05-18 13:17:28 -04:00
2026-05-18 13:17:28 -04:00
2026-05-18 13:17:28 -04:00
2026-05-18 13:17:28 -04:00
2026-05-18 13:17:28 -04:00
2026-05-18 13:17:28 -04:00
2026-05-18 13:17:28 -04:00
2026-05-18 13:17:28 -04:00
2026-05-18 13:17:28 -04:00
2026-05-18 13:17:28 -04:00
2026-05-18 13:17:28 -04:00
2026-05-18 13:17:28 -04:00
2026-05-18 13:17:28 -04:00
2026-05-18 13:17:28 -04:00
2026-05-18 13:17:28 -04:00
2026-05-18 13:17:28 -04:00
2026-05-18 13:17:28 -04:00
2026-05-18 13:17:28 -04:00
2026-05-18 13:17:28 -04:00
2026-05-18 13:17:28 -04:00
2026-05-18 13:17:28 -04:00
2026-05-18 13:17:28 -04:00
2026-05-18 13:17:28 -04:00

Ruby Rails RSpec Swagger

rails-api-auth-template

fast start rails api auth setup with devise + jwt

🚀 what is this?

this is a rails 7.2 api-only template with jwt authentication using devise. you can skip the boring setup and jump straight into building cool stuff.

screenshot

🧠 why tho?

because every time you start a new project, you forget one step. or five. or all of them.

this template saves you from:

  • repeating the same setup 900 times
  • googling “rails api jwt devise setup” again
  • crying over untracked .env files

🔧 stack

  • ruby 3.3.1
  • rails 7.2.2.1 (api-only)
  • devise (user auth)
  • jwt (hand-rolled, no devise-jwt dependency)
  • rspec + rswag (for testing + swagger docs)
  • dotenv (for managing secrets)
  • rack-cors (so your frontend doesnt scream)
  • rack-attack (rate limiting — no room for brute force bots)

🧪 how to use this as a template

  1. click the green “Use this template” button on the top-right
  2. name your new repo (e.g. my-next-api)
  3. clone it
  4. run the setup:
bundle install
cp .env.example .env
rails db:create db:migrate

⚙️ or setup as a starter project

git clone https://github.com/yourname/rails-api-auth-template.git
cd rails-api-auth-template
bundle install
yarn install # (if needed)
cp .env.example .env
rails db:create db:migrate

🔐 auth flow

signup

POST /api/v1/signup
{
  "email": "bob@random.com",
  "password": "123456",
  "password_confirmation": "123456"
}

returns access token + refresh token + user json

login

POST /api/v1/login
{
  "email": "bob@random.com",
  "password": "123456"
}

returns access token + refresh token + user json

refresh

POST /api/v1/refresh
{
  "refresh_token": "<your_refresh_token>"
}

returns a new access token (keeps you logged in without re-entering credentials)

profile (protected)

GET /api/v1/profile
Authorization: Bearer <your_access_token>

returns current user

logout

POST /api/v1/logout
Authorization: Bearer <your_access_token>

blacklists the current token (real logout, token becomes invalid)

👥 role-based authorization

users have roles: user (default), moderator, or admin

example: admin-only endpoint

GET /api/v1/admin/dashboard
Authorization: Bearer <admin_access_token>

returns admin dashboard data (403 forbidden for non-admins)

using roles in your controllers

class MyController < ApplicationController
  include AuthorizeRequest
  include AuthorizeRole

  before_action :require_admin  # only admins
  # or
  before_action :require_moderator  # admins + moderators
end

🔒 security features

  • no secret fallbacks: JWT_SECRET_KEY must be set (crashes if missing)
  • token blacklisting: logout actually invalidates tokens
  • refresh tokens: short-lived access tokens (1 hour) + long-lived refresh tokens (7 days)
  • rate limiting: login, signup, and refresh endpoints are throttled
  • JTI tracking: every token has a unique identifier for precise control
  • automatic cleanup: expired tokens can be cleaned via scheduled jobs

📖 swagger ui

run:

RAILS_ENV=test bundle exec rake rswag:specs:swaggerize
rails s

open http://localhost:3000/api-docs

🧪 test

rspec

🚀 production considerations

cleanup jobs

add these to your scheduled jobs (sidekiq, cron, etc):

# clean up expired blacklisted tokens
BlacklistedToken.cleanup_expired

# clean up old refresh tokens
RefreshToken.cleanup_old_tokens

environment variables

make sure to set these in production:

JWT_SECRET_KEY=your_super_secret_key_here_use_rails_secret
DATABASE_URL=your_database_url
REDIS_URL=your_redis_url (optional, for rack-attack)

database indexes

migrations include proper indexes for performance:

  • blacklisted_tokens.jti (unique)
  • blacklisted_tokens.exp
  • refresh_tokens.token (unique)
  • refresh_tokens.user_id + revoked
  • users.role

🤝 contribute

open to contributions, improvements, or just saying hi. open issues or pull requests.

features

  • JWT authentication with secure token generation (includes JTI for tracking)
  • Token blacklisting for real logout (tokens are invalidated on logout)
  • Refresh tokens (7-day expiry, keeps users logged in securely)
  • Role-based authorization (user, moderator, admin roles)
  • Rate limiting with Rack::Attack (prevents brute force attacks)
  • Comprehensive test coverage with RSpec
  • Swagger API documentation via rswag
  • Security best practices (no fallback secrets, proper validation)

🧼 todo

  • add email confirmation for signup 📧
  • add password reset functionality 🔑
  • add remember me token (long-lived sessions) 💾
  • add oauth providers (google, github, etc) 🔗

📢 shoutout

built to help devs like you (and me) avoid setup fatigue. feel free to fork, star, share, or improve.

⚠️ disclaimer

this template includes production-grade features like token blacklisting, refresh tokens, and role-based auth. however, you should still:

  • review security settings for your specific use case
  • set up proper monitoring and logging
  • configure ssl/tls in production
  • add email confirmation if needed
  • implement proper error tracking

use responsibly and test thoroughly before deploying.


made with ♥ by rustam

S
Description
No description provided
Readme 108 KiB
Languages
Ruby 96.7%
Dockerfile 2.4%
Shell 0.7%
HTML 0.2%