DeviceBindingApi

final class DeviceBindingApi

Binds this device to the current user and later proves the device still holds that binding.

The device key pair is kept in the Keychain; the server stores the public key per binding. Get an instance with AppIntegrityModuleApi.getDeviceBindingApi(clientConfiguration:username:password:restPath:).

  • Register this device using the scanned QR payload.

    Expected QR shape: unblu-bind://<host>/<account>?token=<t>&v=1 (only token is inspected; the rest is host-app-defined).

    Flow:

    1. Parse the token out of the QR payload.
    2. Generate (or reuse) the device key pair, return public key base64.
    3. Ask the server (via JS) for an enrollment challenge.
    4. Sign the decoded challenge locally.
    5. Send the signature back to the server (via JS) and receive the bindingId.

    Declaration

    Swift

    func registerWithQrPayload(qrPayload: String, completion: @escaping (Result<String, DeviceBindingError>) -> Void)
  • Registers the current device using a raw enrollment token (the token value of the QR payload) — for when the user types or pastes the code manually instead of scanning. Same flow as registerWithQrPayload(qrPayload:completion:) without the unblu-bind://… URI parsing.

    Declaration

    Swift

    func registerWithToken(token: String, completion: @escaping (Result<String, DeviceBindingError>) -> Void)
  • The bindingId persisted on this device, or nil if there’s no binding for this app (never enrolled, or revoked, or local data cleared). Reads from the Keychain — no network or JS round-trip. Pair this with verify(bindingId:) to silently re-confirm a binding on startup.

    Declaration

    Swift

    var localBindingId: String? { get }
  • The session cookies (name -> value) obtained for the device-binding REST calls, or nil if no server call has completed yet (or the bridge isn’t REST-backed). After enrollment/verify you can reuse these to authenticate the WebView (e.g. by mapping them to UnbluCookies and assigning UnbluClient.customCookies) so it doesn’t have to log in again.

    Declaration

    Swift

    var sessionCookies: [String : String]? { get }
  • The device identifier the server assigned during login (the value of the …-device cookie), or nil if no server call has completed yet (or the bridge isn’t REST-backed). The server creates a DeviceInfo for this id at login, and the device binding is anchored to it.

    Declaration

    Swift

    var deviceId: String? { get }
  • The session obtained during the device-binding login as UnbluCookies — the same set the binding calls used, including the …-device cookie carrying deviceId. Returns nil if no server call has completed yet. Assign directly to UnbluClient.customCookies so the WebView reuses the session (and the device id) without logging in again:

    if let cookies = deviceBinding.sessionUnbluCookies {
        client.customCookies = cookies
    }
    

    Declaration

    Swift

    var sessionUnbluCookies: Set<UnbluCookie>? { get }
  • Confirms that this device still controls an existing binding.

    Asks the server for a fresh challenge for bindingId, signs it locally with the device’s private key, and sends the signature back for the server to verify against the public key it stored at registration. This proves liveness without re-enrolling.

    Declaration

    Swift

    func verify(bindingId: String, completion: @escaping (Result<Void, DeviceBindingError>) -> Void)

    Parameters

    bindingId

    The binding to verify (as returned by registerWithQrPayload/registerWithToken). Empty fails with .bindingNotFound.

    completion

    .success(()) if the server accepts the signature. Common failures: .signingFailed (local key unavailable), .signatureRejected (server refused the signature), or a transport/login error surfaced as .bridgeUnavailable.

  • Asks the server to revoke the binding; on success, clears the local key pair and the persisted bindingId.

    Declaration

    Swift

    func revoke(bindingId: String, completion: @escaping (Result<Void, DeviceBindingError>) -> Void)