Skip to content

Human Presence Verification for iOS

License: Apache-2.0

Presence SDK — verify human presence before consequential actions execute.

Applications send intent and context. Presence verifies the person. Decionis decides whether execution proceeds.

This SDK is the subject side of a Presence Check: it runs in the person's own app, handles the invitation handoff, and produces the biometric guard and passkey proof. It never accepts a tenant key — tenant credentials belong on trusted servers only.

Install

Requires iOS 15+ / macOS 12+ and Swift tools 5.9. Passkey assertion requires iOS 16+ / macOS 13+.

In Xcode: File → Add Package Dependencies…

https://github.com/decionis/presence-swift

Set the Dependency Rule to Exact Version v0.2.0. Or in Package.swift:

dependencies: [
    .package(url: "https://github.com/decionis/presence-swift", exact: "0.2.0")
],
targets: [
    .target(
        name: "YourApp",
        dependencies: [.product(name: "PresenceSDK", package: "presence-swift")]
    )
]

Thirty seconds to a verdict

import PresenceSDK

let presence = PresenceClient()
let token = try presence.invitationToken(from: url)
let preview = try await presence.previewInvitation(token)
print(preview.request.envelope.presentation.title)
let claimed = try await presence.claimInvitation(token)

let localAuth = await PresenceBiometricAuthenticator().authenticate(
    reason: "Confirm this Presence Check"
)
guard localAuth == .passed else { return }

if #available(iOS 16.0, macOS 13.0, *) {
    let passkeys = PresencePasskeyClient(
        sessionToken: claimed.sessionToken,
        authorizer: PresenceSystemPasskeyAuthorizer()
    )
    let proof = try await passkeys.assert(sessionId: claimed.request.sessionId)
    guard proof.userVerified else { return }
}

url is the Invitation your app receives — a Universal Link like https://presence.decionis.com/mobile-verify#invitation_token=presence_it_….

The security model, in five lines

  • The invitation token parses locally; the Intent you display comes from Presence, never from the link.
  • The biometric prompt (system LocalAuthentication) is only a client-side guard — it gates the flow, it proves nothing by itself.
  • The passkey becomes trusted proof only after the Presence server verifies the server-minted, session-bound challenge and records the assertion.
  • This SDK never holds a tenant credential; your backend opens sessions with a server-side SDK.
  • Fail closed: no verified proof means the consequential action does not proceed.

What ships

Type Role
PresenceClient Parse (invitationToken(from:)), preview, and claim an Invitation.
PresenceBiometricAuthenticator The system biometric confirmation used as the local guard before proof.
PresencePasskeyClient register(actorId:) and assert(sessionId:) against server-minted challenges.
PresenceSystemPasskeyAuthorizer The AuthenticationServices implementation of the passkey ceremony.

How a check flows

invitation URL → preview the sealed Intent → claim → biometric guard → passkey assertion (server-verified) → signed Presence Record → Decionis verdict

Every Presence Check produces a signed Presence Record — portable evidence of who approved what, where, when, and on which device.

Examples

Example What it shows
simple Your first Presence Check.
banking A wire transfer with a verified Presence Record.
zoom An executive meeting instruction held for review.
treasury A treasury wire read through Shadow Mode enforcement.

Documentation

Product documentation lives at presence.decionis.com.

Support

License

Apache-2.0. Use of the hosted Presence service is governed separately.

Releases

Packages

Used by

Contributors

Languages