419 lines
11 KiB
Markdown
419 lines
11 KiB
Markdown
# 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
|
|
```ruby
|
|
# 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
|
|
```ruby
|
|
# 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...
|
|
- [x] Standards compliance (OpenID certified)
|
|
- [x] Multiple grant types (Client Credentials, Device Code, etc.)
|
|
- [x] Token revocation/introspection
|
|
- [x] Refresh tokens
|
|
- [x] Advanced logout (front/back-channel)
|
|
- [x] Session management
|
|
- [x] Token hashing/security best practices
|
|
- [x] Hands-off maintenance
|
|
- [x] Production-battle-tested code
|
|
|
|
### Keep Your Implementation If You...
|
|
- [x] Only need Authorization Code + PKCE
|
|
- [x] Want zero Roda/external framework learning
|
|
- [x] Value Rails patterns over standards
|
|
- [x] Like to understand every line of code
|
|
- [x] Can allocate time for ongoing maintenance
|
|
- [x] 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**
|
|
```bash
|
|
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**
|
|
```bash
|
|
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.
|