Skip to content

feat: Add Device Authorization Grant (RFC 8628) support #49

@spajxo

Description

@spajxo

Device Authorization Grant (RFC 8628) Support

Summary

Implement support for the Device Authorization Grant flow as defined in RFC 8628. This flow enables OAuth 2.0 authorization for devices that lack a web browser or have limited input capabilities.

Motivation

The Device Authorization Grant is essential for:

  • IoT devices without web browsers
  • Smart TVs and streaming devices
  • CLI applications and tools
  • Devices with limited input capabilities (no keyboard)
  • Applications running in constrained environments

Many major providers (Google, Microsoft, GitHub, etc.) support this flow, making it crucial for modern OIDC implementations.

Flow Overview

  1. Device Authorization Request - Client requests device code from authorization server
  2. User Code Display - Device displays user code and verification URI to user
  3. User Authorization - User visits URI on another device and enters code
  4. Token Polling - Client polls token endpoint until user completes authorization
  5. Token Response - Authorization server returns access token and optional refresh token

Proposed Implementation

New Classes

// src/Client/
- DeviceAuthorization

// src/Config/
- DeviceAuthorizationRequest  
- DeviceAuthorizationResponse
- DeviceTokenRequest

// src/Exception/
- DeviceAuthorizationPendingException
- DeviceAuthorizationExpiredException  
- DeviceAuthorizationDeniedException
- SlowDownException

Usage Example

$oidc = $factory->createFromDiscovery('https://provider.example.com');
$deviceAuth = $oidc->deviceAuthorization();

// Step 1: Request device authorization
$deviceResponse = $deviceAuth->requestDeviceAuthorization(
    clientId: 'client_id',
    scopes: ['openid', 'profile']
);

// Step 2: Display to user
echo "Visit: " . $deviceResponse->getVerificationUri() . "\n";
echo "Enter code: " . $deviceResponse->getUserCode() . "\n";

// Step 3: Poll for tokens
$tokens = $deviceAuth->pollForTokens(
    deviceCode: $deviceResponse->getDeviceCode(),
    interval: $deviceResponse->getInterval()
);

Required Endpoints

// Discovery document additions:
- device_authorization_endpoint (required)

// IssuerMetadata updates:
public readonly ?string $deviceAuthorizationEndpoint;

Technical Details

Device Authorization Request

  • Endpoint: device_authorization_endpoint
  • Method: POST
  • Parameters: client_id, scope, optional audience
  • Authentication: Client authentication (if required)

Device Authorization Response

{
  "device_code": "GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS",
  "user_code": "WDJB-MJHT", 
  "verification_uri": "https://example.com/device",
  "verification_uri_complete": "https://example.com/device?user_code=WDJB-MJHT",
  "expires_in": 1800,
  "interval": 5
}

Token Polling

  • Endpoint: token_endpoint
  • Grant Type: urn:ietf:params:oauth:grant-type:device_code
  • Parameters: grant_type, device_code, client_id
  • Error Handling: authorization_pending, slow_down, access_denied, expired_token

Error Handling

try {
    $tokens = $deviceAuth->pollForTokens($deviceCode);
} catch (DeviceAuthorizationPendingException $e) {
    // User hasn't completed authorization yet - continue polling
} catch (SlowDownException $e) {
    // Increase polling interval by 5 seconds
} catch (DeviceAuthorizationExpiredException $e) {
    // Device code expired - restart flow
} catch (DeviceAuthorizationDeniedException $e) {
    // User denied authorization
}

Integration Points

Factory Integration

// Add to Oidc facade:
public function deviceAuthorization(): DeviceAuthorization
{
    return new DeviceAuthorization(
        $this->config,
        $this->httpClient
    );
}

Configuration Support

  • Extend IssuerMetadata with device_authorization_endpoint
  • Support in both DiscoveryConfig and StaticConfig
  • Client metadata updates for device-specific settings

Benefits

  • Enables OAuth for browserless devices
  • Supports IoT and embedded applications
  • Better user experience for constrained devices
  • Compliance with modern OAuth 2.0 best practices

Acceptance Criteria

  • Implement DeviceAuthorization client class
  • Add device authorization request/response models
  • Implement token polling with proper error handling
  • Support for all RFC 8628 error codes
  • Integration with existing discovery and configuration
  • Comprehensive test coverage including error scenarios
  • Documentation and usage examples
  • Support for optional verification_uri_complete
  • Configurable polling intervals and timeouts

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions