Add files to support brakeman and standardrb. Fix some SRB warnings

This commit is contained in:
Dan Milne
2026-01-01 13:18:30 +11:00
parent 9234904e47
commit c03034c49f
17 changed files with 4440 additions and 43 deletions

View File

@@ -0,0 +1,418 @@
# 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.