Return only scopes requested ( OpenID conformance test. Update README

This commit is contained in:
Dan Milne
2026-01-02 14:05:54 +11:00
parent 07cddf5823
commit b2030df8c2
3 changed files with 48 additions and 23 deletions

View File

@@ -347,27 +347,39 @@ services:
Create a `.env` file in the same directory:
```bash
# Generate with: openssl rand -hex 64
SECRET_KEY_BASE=your-secret-key-here
**Generate required secrets first:**
# Application URLs
```bash
# Generate SECRET_KEY_BASE (required)
openssl rand -hex 64
# Generate OIDC private key (optional - auto-generated if not provided)
openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048
cat private_key.pem # Copy the output into OIDC_PRIVATE_KEY below
```
**Then create `.env`:**
```bash
# Rails Secret (REQUIRED)
SECRET_KEY_BASE=paste-output-from-openssl-rand-hex-64-here
# Application URLs (REQUIRED)
CLINCH_HOST=https://auth.yourdomain.com
CLINCH_FROM_EMAIL=noreply@yourdomain.com
# SMTP Settings
# SMTP Settings (REQUIRED for invitations and password resets)
SMTP_ADDRESS=smtp.example.com
SMTP_PORT=587
SMTP_DOMAIN=yourdomain.com
SMTP_USERNAME=your-smtp-username
SMTP_PASSWORD=your-smtp-password
# OIDC (optional - generates temporary key if not set)
# Generate with: openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048
# Then: OIDC_PRIVATE_KEY=$(cat private_key.pem)
# OIDC Private Key (OPTIONAL - generates temporary key if not provided)
# For production, generate a persistent key and paste the ENTIRE contents here
OIDC_PRIVATE_KEY=
# Optional: Force SSL redirects (if not behind a reverse proxy handling SSL)
# Optional: Force SSL redirects (only if NOT behind a reverse proxy handling SSL)
FORCE_SSL=false
```

View File

@@ -3,7 +3,7 @@ class OidcJwtService
class << self
# Generate an ID token (JWT) for the user
def generate_id_token(user, application, consent: nil, nonce: nil, access_token: nil, auth_time: nil, acr: nil)
def generate_id_token(user, application, consent: nil, nonce: nil, access_token: nil, auth_time: nil, acr: nil, scopes: "openid")
now = Time.current.to_i
# Use application's configured ID token TTL (defaults to 1 hour)
ttl = application.id_token_expiry_seconds
@@ -11,18 +11,30 @@ class OidcJwtService
# Use pairwise SID from consent if available, fallback to user ID
subject = consent&.sid || user.id.to_s
# Parse scopes (space-separated string)
requested_scopes = scopes.to_s.split
# Required claims (always included per OIDC Core spec)
payload = {
iss: issuer_url,
sub: subject,
aud: application.client_id,
exp: now + ttl,
iat: now,
email: user.email_address,
email_verified: true,
preferred_username: user.username.presence || user.email_address,
name: user.name.presence || user.email_address
iat: now
}
# Email claims (only if 'email' scope requested)
if requested_scopes.include?("email")
payload[:email] = user.email_address
payload[:email_verified] = true
end
# Profile claims (only if 'profile' scope requested)
if requested_scopes.include?("profile")
payload[:preferred_username] = user.username.presence || user.email_address
payload[:name] = user.name.presence || user.email_address
end
# Add nonce if provided (OIDC requires this for implicit flow)
payload[:nonce] = nonce if nonce.present?
@@ -44,12 +56,13 @@ class OidcJwtService
payload[:at_hash] = at_hash
end
# Add groups if user has any
if user.groups.any?
# Groups claims (only if 'groups' scope requested)
if requested_scopes.include?("groups") && user.groups.any?
payload[:groups] = user.groups.pluck(:name)
end
# Merge custom claims from groups (arrays are combined, not overwritten)
# Note: Custom claims from groups are always merged (not scope-dependent)
user.groups.each do |group|
payload = deep_merge_claims(payload, group.parsed_custom_claims)
end

View File

@@ -204,13 +204,13 @@ This checklist ensures Clinch meets security, quality, and documentation standar
- [ ] Document backup code security (single-use, store securely)
- [ ] Document admin password security requirements
### Future Security Enhancements
- [ ] Rate limiting on authentication endpoints
- [ ] Account lockout after N failed attempts
### Future Security Enhancements (Post-Beta)
- [x] Rate limiting on authentication endpoints (comprehensive coverage implemented)
- [ ] Account lockout after N failed attempts (rate limiting provides similar protection)
- [ ] Admin audit logging
- [ ] Security event notifications
- [ ] Brute force detection
- [ ] Suspicious login detection
- [ ] Security event notifications (email/webhook alerts for suspicious activity)
- [ ] Advanced brute force detection (pattern analysis beyond rate limiting)
- [ ] Suspicious login detection (geolocation, device fingerprinting)
- [ ] IP allowlist/blocklist
## External Security Review