Files
MySMSAPio/SESSION_MIDDLEWARE_FIX.md
2025-10-22 17:22:17 +08:00

4.8 KiB

Session & Flash Middleware Fix

Issue

undefined method 'flash' for an instance of ActionDispatch::Request

This error occurred because the application was configured as API-only mode (config.api_only = true), which disables session and flash middleware by default. However, the admin interface needs these features for:

  • Session-based authentication
  • Flash messages (success/error notifications)
  • CSRF protection

Solution

Manually include the required middleware in the application configuration while keeping API-only mode for the API endpoints.

Changes Made

1. Updated Application Configuration

File: config/application.rb

Added middleware explicitly:

# Configure API-only mode (but keep session middleware for admin interface)
config.api_only = true

# Include session and flash middleware for admin interface
# Even though this is an API-only app, we need sessions for the admin UI
config.middleware.use ActionDispatch::Cookies
config.middleware.use ActionDispatch::Session::CookieStore
config.middleware.use ActionDispatch::Flash

2. Updated Admin Base Controller

File: app/controllers/admin/base_controller.rb

Added CSRF protection:

module Admin
  class BaseController < ActionController::Base
    include Pagy::Backend

    # Enable session and flash for admin controllers
    # (needed because the app is in API-only mode)
    protect_from_forgery with: :exception

    layout "admin"
    before_action :require_admin
    # ...
  end
end

Why This Works

API-Only Mode Benefits (Kept)

  • Faster API responses (no session overhead for API endpoints)
  • RESTful API design
  • No unnecessary middleware for API calls
  • Better performance for mobile/external clients

Admin Interface Benefits (Added)

  • Session-based authentication
  • Flash messages for user feedback
  • CSRF protection
  • Cookie support for "remember me" features
  • Standard Rails web app behavior

How Both Coexist

  1. API Controllers (ApplicationController < ActionController::API)

    • Don't use sessions or flash
    • Use token-based authentication
    • Remain lightweight and fast
  2. Admin Controllers (Admin::BaseController < ActionController::Base)

    • Use sessions and flash
    • Use cookie-based authentication
    • Full Rails web app features

Architecture

Rails Application (API-only mode)
├── API Controllers (ActionController::API)
│   ├── /api/v1/sms
│   ├── /api/v1/otp
│   └── /api/v1/gateway/*
│   └── Uses: Token auth, JSON responses
│
└── Admin Controllers (ActionController::Base)
    ├── /admin/login
    ├── /admin/dashboard
    ├── /admin/api_keys
    ├── /admin/logs
    └── /admin/gateways
    └── Uses: Session auth, HTML responses, flash messages

Middleware Stack

Now includes (in order):

  1. ActionDispatch::Cookies - Cookie handling
  2. ActionDispatch::Session::CookieStore - Session storage
  3. ActionDispatch::Flash - Flash messages

These are available to all controllers, but only admin controllers use them.

Verification

Check middleware is loaded:

bin/rails middleware | grep -E "(Session|Flash|Cookies)"

Should output:

use ActionDispatch::Cookies
use ActionDispatch::Session::CookieStore
use ActionDispatch::Flash

Test application:

bin/rails runner "puts 'AdminUser: ' + AdminUser.first.email"

Security Considerations

CSRF Protection

  • Enabled for admin controllers via protect_from_forgery with: :exception
  • Automatically includes CSRF token in forms
  • Validates token on POST/PUT/PATCH/DELETE requests

Session Security

  • Uses encrypted cookie store
  • Session expires when browser closes (default)
  • Session data is signed and verified

Default configuration uses secure cookies in production:

  • HttpOnly: Yes (prevents XSS)
  • Secure: Yes in production (HTTPS only)
  • SameSite: Lax (prevents CSRF)

No Impact on API

The API endpoints remain unchanged:

  • No session overhead
  • No CSRF checks
  • Token-based authentication still works
  • Same performance characteristics

Testing

Test Admin Login

# Start server
bin/rails server

# Visit in browser
open http://localhost:3000/admin/login

Test API Endpoint

# Should work without sessions
curl -H "Authorization: Bearer your_api_key" \
  http://localhost:3000/api/v1/sms/received

Summary

Fixed: Flash messages work in admin interface Fixed: Sessions work for authentication Kept: API-only mode for API endpoints Kept: Performance benefits of API-only Added: CSRF protection for admin Added: Cookie support for admin

Both the API and admin interface now work correctly side-by-side! 🎉