Files
clinch/docs/rodauth-oauth-quick-reference.md

11 KiB

Rodauth-OAuth: Quick Reference Guide

What Is It?

A production-ready Ruby gem implementing OAuth 2.0 and OpenID Connect. Think of it as a complete, standards-certified OAuth/OIDC server library for Ruby apps.

Key Stats

  • Framework: Roda (not Rails, but works with Rails via wrapper)
  • Features: 34 modular features you can enable/disable
  • Certification: Officially certified for 11 OpenID Connect profiles
  • Test Coverage: Hundreds of tests
  • Status: Production-ready, actively maintained

Why Consider It?

Advantages Over Your Implementation

  1. Complete OAuth/OIDC Implementation

    • All major grant types supported
    • Certified compliance with standards
    • 20+ RFC implementations
  2. Security Features

    • Token hashing (bcrypt) by default
    • DPoP support (token binding)
    • TLS mutual authentication
    • Proper scope enforcement
  3. Advanced Token Management

    • Refresh tokens (you don't have)
    • Token revocation
    • Token introspection
    • Token rotation policies
  4. Low Maintenance

    • Well-tested codebase
    • Active community
    • Regular spec updates
    • Battle-tested in production
  5. Extensible

    • Highly configurable
    • Override any behavior you need
    • Database-agnostic
    • Works with any SQL DB

What Your Implementation Does Better

  1. Simplicity - Fewer lines of code, easier to understand
  2. Rails Native - No need to learn Roda
  3. Control - Full ownership of the codebase
  4. Minimal Dependencies - Just JWT and OpenSSL

Architecture Overview

Your Current Setup

Rails App
  └─ OidcController (450 lines)
      ├─ /oauth/authorize
      ├─ /oauth/token
      ├─ /oauth/userinfo
      └─ /logout

Models:
  ├─ OidcAuthorizationCode
  ├─ OidcAccessToken
  └─ OidcUserConsent

Features Supported:
  ├─ Authorization Code Flow ✓
  ├─ PKCE ✓
  └─ Basic OIDC ✓

NOT Supported:
  ├─ Refresh Tokens
  ├─ Token Revocation
  ├─ Token Introspection
  ├─ Client Credentials Grant
  ├─ Device Code Flow
  ├─ Session Management
  ├─ Front/Back-Channel Logout
  └─ Dynamic Client Registration

Rodauth-OAuth Setup

Roda App (web framework)
  └─ Rodauth Plugin (authentication/authorization)
      ├─ oauth_base (foundation)
      ├─ oauth_authorization_code_grant
      ├─ oauth_pkce
      ├─ oauth_jwt (optional)
      ├─ oidc (OpenID core)
      ├─ oidc_session_management (optional)
      ├─ oidc_rp_initiated_logout (optional)
      ├─ oidc_frontchannel_logout (optional)
      ├─ oidc_backchannel_logout (optional)
      ├─ oauth_token_revocation (optional)
      ├─ oauth_token_introspection (optional)
      ├─ oauth_client_credentials_grant (optional)
      └─ ... (28+ more optional features)

Routes Generated Automatically:
  ├─ /.well-known/openid-configuration ✓
  ├─ /.well-known/jwks.json ✓
  ├─ /oauth/authorize ✓
  ├─ /oauth/token ✓
  ├─ /oauth/userinfo ✓
  ├─ /oauth/introspect (optional)
  ├─ /oauth/revoke (optional)
  └─ /logout ✓

Database Schema Comparison

Your Current Tables

oidc_authorization_codes
  ├─ id
  ├─ user_id
  ├─ application_id
  ├─ code (unique)
  ├─ redirect_uri
  ├─ scope
  ├─ nonce
  ├─ code_challenge
  ├─ code_challenge_method
  ├─ used (boolean)
  ├─ expires_at
  └─ created_at

oidc_access_tokens
  ├─ id
  ├─ user_id
  ├─ application_id
  ├─ token (unique)
  ├─ scope
  ├─ expires_at
  └─ created_at

oidc_user_consents
  ├─ user_id
  ├─ application_id
  ├─ scopes_granted
  └─ granted_at

applications
  ├─ id
  ├─ name
  ├─ client_id (unique)
  ├─ client_secret
  ├─ redirect_uris (JSON)
  ├─ app_type
  └─ ... (few more fields)

Rodauth-OAuth Tables

accounts (from rodauth)
  ├─ id
  ├─ status_id
  ├─ email
  └─ password_hash

oauth_applications (75+ columns!)
  ├─ Basic: id, account_id, name, description
  ├─ OAuth: client_id, client_secret, redirect_uri, scopes
  ├─ Config: token_endpoint_auth_method, grant_types, response_types
  ├─ JWT/JWKS: jwks_uri, jwks, jwt_public_key
  ├─ OIDC: subject_type, id_token_signed_response_alg, etc.
  ├─ PAR: require_pushed_authorization_requests
  ├─ DPoP: dpop_bound_access_tokens
  ├─ TLS: tls_client_auth_* fields
  └─ Logout: post_logout_redirect_uris, frontchannel_logout_uri, etc.

oauth_grants (consolidated - replaces your two tables!)
  ├─ id, account_id, oauth_application_id
  ├─ type (authorization_code, refresh_token, etc.)
  ├─ code, token, refresh_token (with hashed versions)
  ├─ expires_in, revoked_at
  ├─ scopes, access_type
  ├─ code_challenge, code_challenge_method (PKCE)
  ├─ user_code, last_polled_at (Device code grant)
  ├─ nonce, acr, claims (OIDC)
  ├─ dpop_jkt (DPoP)
  └─ certificate_thumbprint, resource (advanced)

[Optional tables for features you enable]

Feature Comparison Matrix

Feature Your Code Rodauth-OAuth Effort to Add*
Authorization Code Flow N/A
PKCE N/A
Refresh Tokens 1-2 weeks
Token Revocation 1 week
Token Introspection 1 week
Client Credentials Grant 2 weeks
Device Code Flow 3 weeks
JWT Access Tokens 1 week
Session Management 2-3 weeks
Front-Channel Logout 1-2 weeks
Back-Channel Logout 2 weeks
Dynamic Client Reg 3-4 weeks
Token Hashing 1 week

*Time estimates for adding to your implementation

Code Examples

Rodauth-OAuth: Minimal OAuth Server

# Gemfile
gem 'roda'
gem 'rodauth-oauth'
gem 'sequel'

# lib/auth_server.rb
class AuthServer < Roda
  plugin :sessions, secret: ENV['SESSION_SECRET']
  plugin :rodauth do
    db DB
    enable :login, :logout, :create_account, 
           :oidc, :oauth_pkce, :oauth_authorization_code_grant,
           :oauth_token_revocation
    
    oauth_application_scopes %w[openid email profile]
    oauth_require_pkce true
  end
  
  route do |r|
    r.rodauth  # All OAuth endpoints auto-mounted!
    
    # Your app logic here
  end
end

That's it! All these endpoints are automatically available:

  • GET /.well-known/openid-configuration
  • GET /.well-known/jwks.json
  • GET /oauth/authorize
  • POST /oauth/token
  • POST /oauth/revoke
  • GET /oauth/userinfo
  • GET /logout

Your Current Approach

# app/controllers/oidc_controller.rb
class OidcController < ApplicationController
  def authorize
    # 150 lines of validation logic
  end
  
  def token
    # 100 lines of token generation logic
  end
  
  def userinfo
    # 50 lines of claims logic
  end
  
  def logout
    # 50 lines of logout logic
  end
  
  private
  
  def validate_pkce(auth_code, code_verifier)
    # 50 lines of PKCE validation
  end
end

Integration Paths

Option 1: Stick with Your Implementation

  • Keep building features incrementally
  • Effort: 2-3 months to reach feature parity
  • Pro: Rails native, full control
  • Con: Continuous maintenance burden

Option 2: Switch to Rodauth-OAuth

  • Learn Roda/Rodauth (1-2 weeks)
  • Migrate database (1 week)
  • Replace 450 lines of code with config (1 week)
  • Testing & validation (2-3 weeks)
  • Effort: 4-8 weeks total
  • Pro: Production-ready, certified, maintained
  • Con: Different framework (Roda)

Option 3: Hybrid Approach

  • Keep your Rails app for business logic
  • Use rodauth-oauth as separate OAuth/OIDC service
  • Services communicate via HTTP/APIs
  • Effort: 2-3 weeks (independent services)
  • Pro: Best of both worlds
  • Con: Operational complexity

Decision Matrix

Use Rodauth-OAuth If You Need...

  • Standards compliance (OpenID certified)
  • Multiple grant types (Client Credentials, Device Code, etc.)
  • Token revocation/introspection
  • Refresh tokens
  • Advanced logout (front/back-channel)
  • Session management
  • Token hashing/security best practices
  • Hands-off maintenance
  • Production-battle-tested code

Keep Your Implementation If You...

  • Only need Authorization Code + PKCE
  • Want zero Roda/external framework learning
  • Value Rails patterns over standards
  • Like to understand every line of code
  • Can allocate time for ongoing maintenance
  • Prefer minimal dependencies

Key Differences You'll Notice

1. Framework Paradigm

  • Your impl: Rails (MVC, familiar)
  • Rodauth: Roda (routing-focused, lightweight)

2. Database ORM

  • Your impl: ActiveRecord (Rails native)
  • Rodauth: Sequel (lighter, more control)

3. Configuration Style

  • Your impl: Rails initializers, environment variables
  • Rodauth: Plugin block with DSL

4. Model Management

  • Your impl: Rails models with validations, associations
  • Rodauth: Minimal models, logic in database

5. Testing Approach

  • Your impl: RSpec, model/controller tests
  • Rodauth: Request-based integration tests

File Locations (If You Switch)

Current Structure
├── app/controllers/oidc_controller.rb
├── app/models/
│   ├── oidc_authorization_code.rb
│   ├── oidc_access_token.rb
│   └── oidc_user_consent.rb
├── app/services/oidc_jwt_service.rb
├── db/migrate/*oidc*.rb

Rodauth-OAuth Equivalent
├── lib/rodauth_app.rb           # Configuration (replaces most controllers)
├── app/views/rodauth/           # Templates (consent form, etc.)
├── config/routes.rb             # Simple: routes mount rodauth
└── db/migrate/*rodauth_oauth*.rb

Performance Considerations

Your Implementation

  • Small tables → fast queries
  • Fewer columns → less overhead
  • Simple token validation
  • Estimated: 5-10ms per token validation

Rodauth-OAuth

  • More columns, but same queries
  • Optional token hashing (slight overhead)
  • More features = more options checked
  • Estimated: 10-20ms per token validation
  • Can be optimized: disable unused features

Getting Started (If You Want to Explore)

  1. Review the code

    cd /Users/dkam/Development/clinch/tmp/rodauth-oauth
    ls -la lib/rodauth/features/  # See all features
    cat examples/oidc/authentication_server.rb  # Full working example
    
  2. Run the example

    cd /Users/dkam/Development/clinch/tmp/rodauth-oauth/examples
    ruby oidc/authentication_server.rb  # Starts server on http://localhost:9292
    
  3. Read the key files

    • README.md: Overview
    • MIGRATION-GUIDE-v1.md: Version migration (shows architecture)
    • test/migrate/*.rb: Database schema
    • examples/oidc/*.rb: Complete working implementation

Next Steps

  1. If keeping your implementation:

    • Prioritize refresh token support
    • Add token revocation endpoint
    • Consider token hashing
  2. If exploring rodauth-oauth:

    • Run the example server
    • Review the feature files
    • Check if hybrid approach works for your org
  3. For either path:

    • Document your decision
    • Plan feature roadmap
    • Set up appropriate monitoring

Bottom Line: Rodauth-OAuth is the "production-grade" option if you need comprehensive OAuth/OIDC. Your implementation is fine if you keep features minimal and have maintenance bandwidth.