Skip to content

IDP Client-Side Implementation Overview (Version 2)

Introduction

The client-side IDP implementation provides device registration, token management, and authentication for Angular applications using NGXS state management. This implementation supports two OAuth2 authentication flows with platform-specific service implementations:

  • Client Credentials Grant (client_credentials): OTP-based device registration with client_id/client_secret authentication
  • JWT Bearer Assertion Grant (jwt-bearer): Certificate-based authentication using X.509 client certificates

The architecture centralizes authentication state, coordinates cross-module integration, and provides a robust foundation for both credential-based and certificate-based authentication flows across web, Capacitor (iOS/Android), and Electron environments.

Architecture Overview

┌─────────────────────┐    ┌──────────────────┐    ┌─────────────────────┐
│   NGXS State        │    │   Component      │    │   Federated         │
│   Management        │───►│   Layer          │───►│   Service Layer     │
└─────────────────────┘    └──────────────────┘    └─────────────────────┘
        │                           │                         │
        ├─ Centralized State        ├─ User Interface         ├─ Platform Detection
        ├─ Action Dispatching       ├─ Form Management        ├─ Service Federation
        ├─ Side Effects             ├─ Error Handling         ├─ OAuth2 Flow
        └─ Cross-Module Coord       └─ Navigation Flow        └─ Token Caching
                                                                       │
                                                               ┌───────┼───────┐
                                                               │       │       │
                                                        ┌─────────┐ ┌──────┐ ┌─────────┐
                                                        │   Web   │ │ Cap. │ │Electron │
                                                        │ Service │ │Plugin│ │ Plugin  │
                                                        └─────────┘ └──────┘ └─────────┘

Core Architecture Components

1. State Management Layer (idp.state.ts)

The IDP state management provides centralized control over authentication flow and coordinates with other application modules:

Action Handlers:

Token Management Actions: - ResetToken: Clears authentication token from application state - SetToken: Updates state with new access token and expiration information
- ResetClientCredentials: Removes stored client credentials via service layer

Authentication Orchestration: - IdpAuthenticate: Orchestrates the complete authentication flow: 1. Calls federated service to retrieve access token using stored client credentials 2. Parses JWT token to extract device and server configuration claims 3. Creates provisioning data structure with device metadata from JWT 4. Dispatches provisioning initialization with extracted configuration 5. Triggers bootstrap initialization with authenticated server URL from JWT claims

2. Federated Service Layer (federated-idp-access-token.service.ts)

The federated service acts as a platform-aware facade that automatically detects the runtime environment and loads the appropriate IDP implementation:

Platform Detection Logic:

  • Electron Detection: Checks for window.openposElectron API
  • Capacitor Detection: Checks for window.Capacitor.isNativePlatform()
  • Web Fallback: Defaults to web implementation for browser environments

Service Loading Strategy:

  • Electron: Loads ElectronIdpAccessTokenService directly from bootstrap module
  • Web/Capacitor: Uses module federation to load remote IDP service from federated modules

3. Platform-Specific Service Implementations

Web Service (web-idp-access-token.service.ts)

  • Local Storage: Uses browser localStorage for credential persistence
  • Fetch API: Standard HTTP requests for OAuth2 operations
  • Token Caching: In-memory and localStorage token caching with expiration validation
  • Encryption: Base64 encoding for basic credential protection

Capacitor Plugin (idp-access-token.service.ts + Native Plugins)

  • Secure Storage: Platform-native secure storage (Keychain/Keystore)
  • Native HTTP: Uses Capacitor's native HTTP capabilities
  • Token Caching: Encrypted token storage with platform security
  • Cross-Platform: Unified interface for iOS and Android implementations

Electron Service (electron-idp-access-token.service.ts)

  • IPC Communication: Uses Electron's IPC to communicate with main process
  • Main Process Implementation: JWT Bearer assertion and client credentials in main process
  • Secure Storage: Electron's safeStorage API for credential encryption
  • Token Management: Automatic token caching and refresh in main process

4. Component Architecture (device-registration.component.ts)

The device registration component provides the user interface for OTP-based device activation:

User Interface Logic:

User Interaction Flow: - Registration Process: Collects user input and triggers device registration through service layer - Error Feedback: Visual error indication with retry capabilities - Skip Functionality: Alternative flow for manual device configuration - State Coordination: Dispatches authentication actions upon successful registration

5. Module Federation Strategy

The client-v2 implementation uses Angular's module federation for dynamic service loading:

Federation Configuration:

  • Manifest Loading: Loads bootstrap-federation.manifest.json for remote module configuration
  • Remote Module: IDP functionality loaded as federated remote module loadRemoteModule('idp', './Idp')
  • Service Resolution: Dynamic service instantiation based on federated module exports

Client Credentials OAuth2 Flow

Grant Type Implementation

All platform implementations use the OAuth2 Client Credentials Grant (grant_type=client_credentials) for device authentication:

Flow Characteristics:

  • Device-Based Authentication: Each device receives unique client credentials (client_id, client_secret)
  • OTP Registration: One-time password (OTP) based device registration with IDP service
  • Token Endpoint: Device-specific token endpoint provided during registration
  • Scope: device scope for device-level access permissions

Token Caching Strategy:

  • Automatic Caching: Tokens cached automatically upon acquisition
  • Expiration Validation: 5-minute refresh threshold before token expiry
  • Platform Storage: Encrypted storage using platform-specific secure storage
  • Cache Invalidation: Automatic cache clearing on credential reset

JWT Bearer Assertion OAuth2 Flow

Grant Type Implementation

Capacitor and Electron platforms support an alternative OAuth2 JWT Bearer Assertion Grant (grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer) for certificate-based device authentication:

Flow Characteristics:

  • Certificate-Based Authentication: Uses client certificates (X.509) for device identity
  • Self-Signed JWT: Device creates and signs JWT assertions using private key
  • No Device Registration: Certificates pre-provisioned, eliminating OTP registration step
  • Enhanced Security: PKI-based authentication with certificate chain validation

JWT Assertion Structure

JWT Header:

{
  "alg": "RS256",           // RSA-SHA256 or ES256 for EC keys
  "typ": "JWT",
  "x5c": ["cert1", "cert2"] // X.509 certificate chain (Base64 encoded)
}

JWT Claims:

{
  "iss": "client",                    // Issuer (fixed value)
  "sub": "device_id",                 // Subject (device identifier)
  "aud": "https://idp.server/token",  // Audience (token endpoint)
  "iat": 1640995200,                  // Issued at timestamp
  "exp": 1640998800,                  // Expiration (5 minutes from iat)
  "scope": "device"                   // Requested scope
}

Platform-Specific Implementation

Android Implementation (JwtAssertionBuilder.java)

Certificate Management: - Android KeyChain API: Accesses device-installed client certificates - Certificate Alias: Configurable alias for certificate selection (default: "commerce") - Automatic Algorithm Detection: Supports RSA (RS256) and EC (ES256) key algorithms - Certificate Chain: Full X.509 certificate chain included in JWT header

Electron Implementation (JwtBearerAssertionService.js)

Certificate Management: - File-Based Certificates: Loads certificates from local file system - PEM Format Support: Standard PEM-encoded private keys and certificate chains - Configurable Paths: Certificate and private key file paths via configuration - Automatic Key Detection: Supports RSA and EC private keys

Configuration Requirements

Android Configuration (via Android Device Policy/MDM):

{
  "grant_type": "jwt-bearer",
  "cert_alias": "commerce",
  "device_id": "unique-device-identifier",
  "token_endpoint": "https://idp.server/oauth2/token"
}

Electron Configuration (electron-config.json):

{
  "activeClient": "jwt-bearer",
  "algorithm": "RS256",
  "certificateChainFileName": "device.chain.crt",
  "privateKeyFileName": "device.key",
  "tokenUrl": "https://idp.server/oauth2/token",
  "assertionSubject": "device-identifier",
  "assertionAudience": "https://idp.server",
  "assertionIssuer": "client",
  "assertionScope": "device"
}

Security Considerations

Certificate Security:

  • Private Key Protection: Private keys stored in platform secure storage (Android KeyChain, Electron safeStorage)
  • Certificate Validation: Server validates certificate chain and signature
  • Key Rotation: Supports certificate renewal and key rotation processes

JWT Security:

  • Signature Verification: Server verifies JWT signature using certificate public key
  • Certificate Chain Validation: Full X.509 certificate chain validation including root CA

Integration Components

1. HTTP Authentication Interceptor (auth.interceptor.ts)

The authentication interceptor provides transparent JWT token management for HTTP requests:

Interceptor Logic Flow:

  1. State Selection: Retrieves current IDP state for immediate access token availability
  2. Token Validation: Validates token existence and expiration status
  3. Header Injection: Adds Bearer authorization headers to authenticated requests
  4. Conditional Processing: Skips authentication for requests when no token available

2. WebSocket Connection Integration (personalization-listener.service.ts)

Coordinates authentication state with WebSocket connection headers:

Header Coordination:

  • State Monitoring: Watches IDP state for accessToken changes
  • Header Updates: Dispatches SharedConnectHeaders actions with Bearer tokens
  • Real-time Sync: Maintains WebSocket authentication in sync with token state

Platform-Specific Implementation Details

Shared Service Interface:

export interface IdpAccessTokenService {
  grantType(): Promise<GrantType>;  // Returns "client-credentials" or "jwt-bearer"
  registerDevice(options: { otp: string }): Promise<void>;  // Only for client-credentials
  getAccessToken(): Promise<TokenResponse | null>;
  getPrincipal(): Promise<JwtPayload | null>;
  resetDevice(): Promise<void>;
}

Grant Type Enumeration:

type GrantType = "client-credentials" | "jwt-bearer";

Token Management:

interface TokenResponse {
  access_token: string;
  token_type: string;
  expires_in: number;
  scope?: string;
}

1. Web Implementation (web-idp-access-token.service.ts)

Storage Strategy:

  • Client Credentials: Base64 encoded in localStorage with key idp_client_credentials
  • Access Tokens: Cached in localStorage with expiration tracking
  • Encryption: Simple Base64 encoding (sufficient for demo/dev environments)

HTTP Operations:

  • Fetch API: Standard browser fetch for OAuth2 operations
  • CORS Handling: Configured for cross-origin IDP service requests
  • Error Handling: Network error detection and user-friendly error messages

2. Capacitor Implementation (iOS/Android Plugins)

iOS Plugin (IdpAccessTokenPlugin.swift)

  • Secure Storage: iOS UserDefaults with automatic encryption
  • Network Operations: URLSession for HTTP requests with proper error handling
  • Token Caching: Encrypted token storage with 5-minute refresh threshold
  • JWT Decoding: Native Base64 decoding for JWT payload extraction

Android Plugin (IdpAccessTokenPlugin.java)

  • Grant Type Support: Both client credentials and JWT Bearer assertion flows
  • Configuration Detection: Automatically selects grant type via Android Device Policy (grant_type setting)
  • Certificate Management:
  • Android KeyChain API: Accesses client certificates for JWT Bearer assertions
  • Certificate Alias: Configurable certificate selection (default: "commerce")
  • Algorithm Support: Automatic detection of RSA (RS256) and EC (ES256) keys
  • Secure Storage: Android SecureSharedPreferences with Keystore encryption
  • Network Operations: Android HTTP client with SSL/TLS validation
  • Token Caching: Keystore-backed secure token storage
  • JWT Processing:
  • JWT Creation: Nimbus JOSE library for JWT Bearer assertion creation
  • Certificate Chain: Full X.509 certificate chain inclusion in JWT header
  • Token Parsing: Android Base64 utilities for access token processing

3. Electron Implementation (electron-idp-access-token.service.ts)

Architecture:

  • Grant Type Support: Both client credentials and JWT Bearer assertion flows
  • Service Selection: Configuration-driven selection via activeClient setting
  • Renderer Process: Service interface using IPC communication
  • Main Process: Full OAuth2 implementation with crypto operations
  • IPC Communication: Secure communication between renderer and main processes

Main Process Services:

  • ClientCredentialsService:
  • Full client credentials OAuth2 flow with OTP device registration
  • Encrypted credential storage using Electron's safeStorage API
  • Automatic token caching with expiration validation
  • JwtBearerAssertionService:
  • Certificate-based JWT Bearer assertion flow
  • File-Based Certificates: PEM-encoded certificate and private key loading
  • JWT Creation: jose library for standards-compliant JWT generation
  • Certificate Chain: X.509 certificate chain embedding in JWT header
  • Configurable Claims: Audience, issuer, subject, and scope configuration
  • Token Caching:
  • Unified TokenCache implementation for both grant types
  • Encrypted storage using Electron's safeStorage API