Skip to content

mahendraxceed/rails_api

Repository files navigation

Rails API with Doorkeeper & Devise

A Rails 8 API-only application with OAuth2 authentication using Doorkeeper and Devise, featuring role-based authorization with CanCanCan.

Features

  • Rails 8.0.2 - Latest Rails version configured as API-only
  • Devise - User authentication
  • Doorkeeper - OAuth2 provider
  • CanCanCan - Role-based authorization
  • MySQL - Database
  • Password Grant Flow - Direct username/password authentication
  • Refresh Tokens - Automatic token refresh support
  • User Roles - Admin and User roles using enum
  • RESTful API - Complete Users CRUD with authorization

Requirements

  • Ruby 3.x
  • MySQL
  • Rails 8.0.2

Setup

1. Install Dependencies

bundle install

2. Database Setup

Configure your database credentials in config/database.yml, then run:

rails db:create
rails db:migrate
rails db:seed

The seed file creates:

  • Admin user: admin@example.com / password123
  • OAuth application for API access

3. Start Server

rails server

Postman Collection

A complete Postman collection is available at postman_collection.json with all API endpoints configured.

Import to Postman

  1. Open Postman
  2. Click Import button
  3. Select postman_collection.json file
  4. The collection includes:
    • Environment variables (base_url, access_token, refresh_token)
    • All authentication endpoints
    • All user management endpoints
    • Auto-save tokens after authentication

Using the Collection

  1. Get Access Token: Run "Get Access Token" request first
    • Tokens are automatically saved to collection variables
  2. Use API Endpoints: All subsequent requests use the saved token
  3. Refresh Token: Use "Refresh Token" when access token expires

API Usage

Authentication

Get Access Token

POST /oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=password&username=admin@example.com&password=password123

Response:

{
  "access_token": "...",
  "token_type": "Bearer",
  "expires_in": 86400,
  "refresh_token": "...",
  "created_at": 1234567890
}

Refresh Token

POST /oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token&refresh_token=YOUR_REFRESH_TOKEN

Use Access Token

Include the access token in the Authorization header:

GET /api/your_endpoint
Authorization: Bearer YOUR_ACCESS_TOKEN

Revoke Token

POST /oauth/revoke
Content-Type: application/x-www-form-urlencoded

token=YOUR_ACCESS_TOKEN

Users API Endpoints

All user endpoints require authentication via Bearer token.

Get Current User

GET /api/v1/users/me
Authorization: Bearer YOUR_ACCESS_TOKEN

Response:

{
  "id": 1,
  "email": "admin@example.com",
  "name": "Admin User",
  "role": "admin",
  "created_at": "2025-11-23T10:52:54.000Z",
  "updated_at": "2025-11-23T10:52:54.000Z"
}

List All Users

GET /api/v1/users
Authorization: Bearer YOUR_ACCESS_TOKEN

Response:

[
  {
    "id": 1,
    "email": "admin@example.com",
    "name": "Admin User",
    "role": "admin",
    "created_at": "2025-11-23T10:52:54.000Z",
    "updated_at": "2025-11-23T10:52:54.000Z"
  }
]

Get User by ID

GET /api/v1/users/:id
Authorization: Bearer YOUR_ACCESS_TOKEN

Create User (Admin Only)

POST /api/v1/users
Authorization: Bearer YOUR_ACCESS_TOKEN
Content-Type: application/json

{
  "user": {
    "email": "newuser@example.com",
    "name": "New User",
    "password": "password123",
    "password_confirmation": "password123",
    "role": "user"
  }
}

Response:

{
  "id": 2,
  "email": "newuser@example.com",
  "name": "New User",
  "role": "user",
  "created_at": "2025-11-23T11:00:00.000Z",
  "updated_at": "2025-11-23T11:00:00.000Z"
}

Update User

PATCH /api/v1/users/:id
Authorization: Bearer YOUR_ACCESS_TOKEN
Content-Type: application/json

{
  "user": {
    "name": "Updated Name"
  }
}

Note: Regular users can only update their own profile. Admins can update any user.

Delete User (Admin Only)

DELETE /api/v1/users/:id
Authorization: Bearer YOUR_ACCESS_TOKEN

Response: 204 No Content

Configuration

Doorkeeper Settings

Located in config/initializers/doorkeeper.rb:

  • Grant Flow: Password (Resource Owner Password Credentials)
  • Token Expiration: 24 hours
  • Refresh Tokens: Enabled
  • Client Authentication: Skipped for password grant
  • API Mode: Enabled

User Model

Users have the following attributes:

  • email - Unique identifier for authentication
  • name - User's display name
  • role - Enum with values: user (default), admin
  • password - Encrypted with bcrypt via Devise

Role Methods:

user.admin?  # Check if admin
user.user?   # Check if regular user
user.admin!  # Set role to admin
user.user!   # Set role to user

Authorization Rules

Defined in app/models/ability.rb:

Admin Users:

  • Full access (manage) to all resources
  • Can create, read, update, and delete any user

Regular Users:

  • Can read all resources
  • Can only update their own user profile
  • Cannot create or delete users

Guest Users (not authenticated):

  • No access (authentication required for all endpoints)

Project Structure

app/
├── controllers/
│   ├── application_controller.rb    # Base controller with Doorkeeper & CanCanCan
│   └── api/
│       └── v1/
│           └── users_controller.rb  # Users CRUD with authorization
├── models/
│   ├── ability.rb                   # CanCanCan authorization rules
│   └── user.rb                      # User model with Devise & roles
├── serializers/
│   └── user_serializer.rb           # User JSON serialization
config/
├── initializers/
│   ├── devise.rb                    # Devise configuration
│   └── doorkeeper.rb                # Doorkeeper OAuth2 configuration
├── routes.rb                        # API routes
└── database.yml                     # Database configuration
db/
├── migrate/
│   ├── *_devise_create_users.rb
│   ├── *_create_doorkeeper_tables.rb
│   └── *_add_name_and_role_to_users.rb
└── seeds.rb                         # Admin user & OAuth app seeds

Security Notes

  • Password grant flow is enabled for simplicity but has security considerations
  • Use HTTPS in production
  • Access tokens expire after 24 hours
  • Refresh tokens are available for seamless re-authentication
  • Passwords are encrypted using bcrypt
  • All API endpoints require authentication (Doorkeeper OAuth2 token)
  • Authorization is enforced via CanCanCan based on user roles
  • Unauthorized access returns 403 Forbidden error

Development

Create New User

User.create!(
  email: "user@example.com",
  name: "John Doe",
  password: "password123",
  password_confirmation: "password123",
  role: :user
)

Check OAuth Applications

Doorkeeper::Application.all

Check Access Tokens

Doorkeeper::AccessToken.all

Testing

The application includes comprehensive integration tests for all API endpoints.

Run Tests

# Run all tests
rails test

# Run specific test file
rails test test/integration/oauth_token_test.rb
rails test test/integration/api/v1/users_test.rb

# Run with verbose output
rails test -v

Test Coverage

OAuth Token Tests (test/integration/oauth_token_test.rb):

  • Get access token with valid credentials
  • Reject invalid credentials
  • Refresh access token
  • Revoke access token

Users API Tests (test/integration/api/v1/users_test.rb):

  • Get current user (authenticated)
  • List all users (admin & regular user)
  • Get user by ID
  • Create user (admin only, with authorization checks)
  • Update user (own profile & admin permissions)
  • Delete user (admin only)
  • Authorization error handling

Test Fixtures

User fixtures are defined in test/fixtures/users.yml:

Test Helpers

Helper methods in test/test_helper.rb:

  • create_access_token(user) - Create Doorkeeper access token for testing
  • auth_headers(token) - Generate authorization headers with Bearer token

License

This project is available as open source under the terms of the MIT License.

About

Rails API with Doorkeeper & Devise

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published