Skip to content

Conversation

@Spomky
Copy link
Contributor

@Spomky Spomky commented Jan 23, 2026

feat: Add granular client override policy system for WebAuthn options

Problem

Fixes #797

The ProfileBasedCreationOptionsBuilder was not consistently using profile configuration values, allowing client requests to override server-defined policies. Additionally, there was no way for developers to selectively allow certain client overrides while maintaining security.

Issue Details

  • Request values could override profile configuration for authenticator selection criteria
  • This created inconsistent behavior where client input affected security policies
  • Server administrators couldn't enforce consistent WebAuthn options
  • No granular control over which fields clients could override

Solution

This PR implements a granular client override policy system that provides developers with fine-grained control over which WebAuthn options clients can override, while maintaining backward compatibility and security by default.

🎯 Key Features

1. ClientOverridePolicy System

  • New ClientOverridePolicy class manages opt-in override permissions
  • YAML configuration for each WebAuthn field
  • Per-field enabled flags and allowed_values constraints
  • All policies disabled by default (maintains current behavior)

2. Granular Field Control

Configure which fields clients can override:

webauthn:
  client_override_policy:
    user_verification:
      enabled: true
      allowed_values: ['required', 'preferred']  # Only these values allowed
    authenticator_attachment:
      enabled: false  # Clients cannot override this field
    resident_key:
      enabled: true
      allowed_values: ['required', 'preferred', 'discouraged']
    attestation_conveyance:
      enabled: true  
      allowed_values: ['none', 'direct']  # Restrict to specific values
    extensions:
      enabled: false  # Disabled by default

3. Smart Override Logic

  • Profile-first: Profile values have priority unless override explicitly enabled
  • Value validation: Client values must be in allowed_values list
  • Fallback behavior: Invalid client values fall back to profile configuration
  • Null-safe: Missing client values always use profile defaults

🔧 Implementation Details

Service Integration

  • ClientOverridePolicy registered as Symfony service
  • Automatically injected into both creation and request options builders
  • Works with both manual builder instantiation and Symfony DI

Backward Compatibility

  • Constructor compatibility: Old signatures still work with default parameters
  • Default behavior: All overrides disabled by default
  • Configuration optional: Existing apps work without changes
  • Profile priority: Maintains current security-first approach

Builder Integration

// Before (profile always wins)
$options = $factory->create($profile, $userEntity, $excludedCredentials, null, null, null);

// After (with policy control)
$authenticatorSelection = $this->overridePolicy->getEffectiveValue(
    'user_verification', 
    $clientValue,      // From request  
    null              // Falls back to profile
);

📋 Usage Examples

Example 1: Allow Limited User Verification Override

webauthn:
  client_override_policy:
    user_verification:
      enabled: true
      allowed_values: ['preferred']  # Clients can only request 'preferred'
    # All other fields use profile values exclusively

Example 2: Development Environment (More Permissive)

webauthn:
  client_override_policy:
    user_verification:
      enabled: true
      allowed_values: ['required', 'preferred', 'discouraged']
    authenticator_attachment:
      enabled: true
      allowed_values: ['platform', 'cross-platform']
    attestation_conveyance:
      enabled: true
      allowed_values: ['none', 'indirect', 'direct']

Example 3: Production Environment (Strict Control)

webauthn:
  client_override_policy:
    # All disabled - profile configuration has absolute priority
    user_verification:
      enabled: false
    authenticator_attachment:
      enabled: false
    # ... (all fields disabled by default)

🧪 Testing Coverage

  • 84/84 functional tests pass (including existing regression tests)
  • Backward compatibility verified with constructor signature tests
  • Policy behavior tested with various configuration scenarios
  • Edge cases covered (null values, invalid values, missing config)
  • Both builders tested (creation and request options)

🔒 Security Benefits

  1. Opt-in by design: Overrides must be explicitly enabled
  2. Value validation: Only pre-approved values accepted from clients
  3. Profile fallback: Invalid client values always fall back to secure defaults
  4. Granular control: Enable overrides only for specific fields that make sense
  5. Audit trail: Clear configuration showing which overrides are allowed

🔄 Migration Path

For Existing Applications

  • No changes required - all policies disabled by default
  • Existing behavior preserved (profile priority)
  • Can gradually enable specific overrides as needed

For New Applications

  • Start with default secure configuration (all disabled)
  • Enable specific overrides based on application requirements
  • Use allowed_values constraints to limit client input

📚 Configuration Reference

Available Fields

  • user_verification: Controls userVerification requirement
  • authenticator_attachment: Controls authenticator type preference
  • resident_key: Controls resident key requirement
  • attestation_conveyance: Controls attestation preference
  • extensions: Controls WebAuthn extensions

Policy Structure

field_name:
  enabled: boolean        # Whether clients can override this field
  allowed_values: array   # List of permitted values (optional for extensions)

This implementation provides the flexibility developers need while maintaining the security-first approach that makes WebAuthn reliable. The opt-in design ensures that existing applications continue to work unchanged, while new applications can selectively enable the client override capabilities they need.

@Spomky Spomky self-assigned this Jan 23, 2026
@Spomky Spomky added this to the 5.2.4 milestone Jan 23, 2026
@Spomky Spomky linked an issue Jan 23, 2026 that may be closed by this pull request
@Spomky Spomky force-pushed the fix/authenticator-selection-criteria-config-v2 branch 5 times, most recently from c0570fe to 098e838 Compare January 23, 2026 23:26
Spomky and others added 3 commits January 24, 2026 01:01
…ermediate CA certificates (#793)

* Set the trust anchor with the trusted certificates when validating the certificate path

* test: add unit tests for PhpCertificateChainValidator with intermediate CA trust anchor

Add comprehensive tests for certificate chain validation including:
- Validation with self-signed root CA as trust anchor
- Validation when leaf certificate matches trust anchor
- Rejection of invalid certificate chains

The tests include test certificates (root CA, intermediate CA, and leaf certificate)
that simulate real-world scenarios like the Yubico Security Key NFC case.

These tests verify that the bug fix for issue #788 works correctly by ensuring
intermediate CA certificates can be used as trust anchors.

* test: refactor PhpCertificateChainValidatorTest for improved readability and consistency

---------

Co-authored-by: zll600 <3400692417@qq.com>
- Implement ClientOverridePolicy class for opt-in client value overrides
- Add YAML configuration section 'client_override_policy' with per-field controls
- Support user_verification, authenticator_attachment, resident_key, attestation_conveyance, and extensions
- Each field has 'enabled' flag and 'allowed_values' constraints
- Integrate policy into ProfileBasedCreationOptionsBuilder and ProfileBasedRequestOptionsBuilder
- Update security firewall service definitions to include ClientOverridePolicy
- Add backward compatible constructor defaults to preserve existing API
- All overrides disabled by default - maintains profile priority for BC
- Add comprehensive tests for new functionality

Closes #797
@Spomky Spomky force-pushed the fix/authenticator-selection-criteria-config-v2 branch from 4a34dad to 7a13a6c Compare January 24, 2026 00:07
@Spomky Spomky changed the base branch from 5.2.x to 5.3.x January 24, 2026 00:09
@Spomky Spomky changed the title fix: respect authenticator_selection_criteria configuration when request body is empty feat: Add granular client override policy system for WebAuthn options Jan 24, 2026
@Spomky Spomky modified the milestones: 5.2.4, 5.3.0 Jan 24, 2026
@Spomky Spomky added feature New feature enhancement New feature or request DX Developer Experience labels Jan 24, 2026
- Update webauthn-lib composer.json to match root dependency ^5.3|^6.0
- Resolves failing ComposerJsonTest::packageDependenciesMatchRootDependencies
- All 272 PHPUnit tests now passing
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

DX Developer Experience enhancement New feature or request feature New feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Configuration "authenticator_selection_criteria" section doesn't work

1 participant