11 KiB
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
-
Complete OAuth/OIDC Implementation
- All major grant types supported
- Certified compliance with standards
- 20+ RFC implementations
-
Security Features
- Token hashing (bcrypt) by default
- DPoP support (token binding)
- TLS mutual authentication
- Proper scope enforcement
-
Advanced Token Management
- Refresh tokens (you don't have)
- Token revocation
- Token introspection
- Token rotation policies
-
Low Maintenance
- Well-tested codebase
- Active community
- Regular spec updates
- Battle-tested in production
-
Extensible
- Highly configurable
- Override any behavior you need
- Database-agnostic
- Works with any SQL DB
What Your Implementation Does Better
- Simplicity - Fewer lines of code, easier to understand
- Rails Native - No need to learn Roda
- Control - Full ownership of the codebase
- 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)
-
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 -
Run the example
cd /Users/dkam/Development/clinch/tmp/rodauth-oauth/examples ruby oidc/authentication_server.rb # Starts server on http://localhost:9292 -
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
-
If keeping your implementation:
- Prioritize refresh token support
- Add token revocation endpoint
- Consider token hashing
-
If exploring rodauth-oauth:
- Run the example server
- Review the feature files
- Check if hybrid approach works for your org
-
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.