DeviceClient

public class DeviceClient : @unchecked Sendable

Client for managing user devices

DeviceClient provides a type-safe interface for managing various types of authentication devices registered to a user.

Supported Device Types

Mutable (Full CRUD)

  • Oath: TOTP/HOTP authentication devices
  • Push: Push notification authentication devices
  • Bound: Device binding for 2FA
  • Profile: Device profiling information
  • WebAuthn: WebAuthn/FIDO2 credentials

Usage

// Initialize with configuration
let config = DeviceClientConfig(
    serverUrl: "https://openam.example.com",
    realm: "alpha",
    cookieName: "iPlanetDirectoryPro",
    ssoToken: token
)
let client = DeviceClient(config: config)

// Fetch devices
let result = await client.oath.get()
switch result {
case .success(let devices):
    print("Found \(devices.count) devices")
case .failure(let error):
    print("Error: \(error)")
}

// Update a device
if case .success(let devices) = await client.bound.get(),
   var device = devices.first {
    device.deviceName = "My Updated Device"
    let updateResult = await client.bound.update(device)
    if case .success = updateResult {
        print("Device updated successfully")
    }
}

// Delete a device
let deleteResult = await client.oath.delete(deviceToDelete)
if case .failure(let error) = deleteResult {
    print("Failed to delete: \(error)")
}

Error Handling

All operations return Result types:

let result = await client.oath.get()
switch result {
case .success(let devices):
    print("Fetched \(devices.count) devices")
case .failure(let error):
    switch error {
    case .requestFailed(let statusCode, let message):
        print("Request failed: \(statusCode) - \(message)")
    case .networkError(let error):
        print("Network error: \(error)")
    default:
        print("Error: \(error.localizedDescription)")
    }
}

Thread Safety

DeviceClient is safe to use from any thread. All async methods are marked with appropriate concurrency annotations and will execute on appropriate queues.

Important

Ensure the SSO token in the configuration is valid before making requests

Note

The client does not automatically refresh tokens; token management is the caller’s responsibility

Initialization

  • Initializes a new DeviceClient

    Creates a client instance configured for device management operations.

    Example:

    let config = DeviceClientConfig(
        serverUrl: "https://openam.example.com",
        realm: "alpha",
        cookieName: "iPlanetDirectoryPro",
        ssoToken: token
    )
    let client = DeviceClient(config: config)
    

    Declaration

    Swift

    public init(config: DeviceClientConfig)

    Parameters

    config

    The configuration containing server details, credentials, and HTTP client

Device Type Accessors

  • Provides access to Oath devices

    Oath devices support TOTP (Time-based One-Time Password) and HOTP (HMAC-based One-Time Password) These devices are mutable - they support full CRUD operations.

    Supported operations:

    • get(): Retrieve all Oath devices for the user
    • update(_:): Update device properties (e.g., device name)
    • delete(_:): Delete a specific Oath device

    Example:

    let result = await client.oath.get()
    switch result {
    case .success(let devices):
        if var device = devices.first {
            device.deviceName = "My Work Phone"
            let updateResult = await client.oath.update(device)
            if case .success = updateResult {
                print("Device updated")
            }
    
            let deleteResult = await client.oath.delete(device)
            if case .success = deleteResult {
                print("Device deleted")
            }
        }
    case .failure(let error):
        print("Error: \(error)")
    }
    

    Declaration

    Swift

    public lazy var oath: any DeviceRepository<OathDevice> { get set }
  • Provides access to Push devices

    Push devices support push notification-based authentication. These devices are mutable - they support full CRUD operations.

    Supported operations:

    • get(): Retrieve all Push devices for the user
    • update(_:): Update device properties (e.g., device name)
    • delete(_:): Delete a specific Push device

    Example:

    let result = await client.push.get()
    switch result {
    case .success(let devices):
        if var device = devices.first {
            device.deviceName = "My Work Phone"
            let updateResult = await client.push.update(device)
            if case .success = updateResult {
                print("Device updated")
            }
    
            let deleteResult = await client.push.delete(device)
            if case .success = deleteResult {
                print("Device deleted")
            }
        }
    case .failure(let error):
        print("Error: \(error)")
    }
    

    Declaration

    Swift

    public lazy var push: any DeviceRepository<PushDevice> { get set }
  • Provides access to Bound devices

    Bound devices represent device bindings for two-factor authentication. These devices are mutable - they support full CRUD operations.

    Supported operations:

    • get(): Retrieve all Bound devices for the user
    • update(_:): Update device properties (e.g., device name)
    • delete(_:): Delete a specific Bound device

    Example:

    let result = await client.bound.get()
    switch result {
    case .success(let devices):
        if var device = devices.first {
            device.deviceName = "My Work Phone"
            let updateResult = await client.bound.update(device)
            if case .success = updateResult {
                print("Device updated")
            }
    
            let deleteResult = await client.bound.delete(device)
            if case .success = deleteResult {
                print("Device deleted")
            }
        }
    case .failure(let error):
        print("Error: \(error)")
    }
    

    Declaration

    Swift

    public lazy var bound: any DeviceRepository<BoundDevice> { get set }
  • Provides access to Profile devices

    Profile devices store device profiling information including location and metadata. These devices are mutable - they support full CRUD operations.

    Supported operations:

    • get(): Retrieve all Profile devices for the user
    • update(_:): Update device properties (e.g., device name)
    • delete(_:): Delete a specific Profile device

    Example:

    let result = await client.profile.get()
    switch result {
    case .success(let devices):
        if var device = devices.first {
            device.deviceName = "My iPhone"
            let updateResult = await client.profile.update(device)
            if case .success = updateResult {
                print("Device updated")
            }
    
            let deleteResult = await client.profile.delete(device)
            if case .success = deleteResult {
                print("Device deleted")
            }
        }
    case .failure(let error):
        print("Error: \(error)")
    }
    

    Declaration

    Swift

    public lazy var profile: any DeviceRepository<ProfileDevice> { get set }
  • Provides access to WebAuthn devices

    WebAuthn devices represent FIDO2/WebAuthn credentials for passwordless authentication. These devices are mutable - they support full CRUD operations.

    Supported operations:

    • get(): Retrieve all WebAuthn devices for the user
    • update(_:): Update device properties (e.g., device name)
    • delete(_:): Delete a specific WebAuthn device

    Example:

    let result = await client.webAuthn.get()
    switch result {
    case .success(let devices):
        if var device = devices.first {
            device.deviceName = "My YubiKey"
            let updateResult = await client.webAuthn.update(device)
            if case .success = updateResult {
                print("Device updated")
            }
    
            let deleteResult = await client.webAuthn.delete(device)
            if case .success = deleteResult {
                print("Device deleted")
            }
        }
    case .failure(let error):
        print("Error: \(error)")
    }
    

    Declaration

    Swift

    public lazy var webAuthn: any DeviceRepository<WebAuthnDevice> { get set }