Skip to main content

Wallet SDK (iOS)

Overview

The Wallet SDK for iOS enables secure identity verification and transaction authorization during checkout. It is optimized for native Swift apps and leverages multi-factor authentication (MFA) with passkeys.

This SDK allows your wallet app to:

  • Initiate an MFA session tied to a transaction.
  • Guide users through passkey authentication, passkey creation, or fallback login.
  • Streamline checkout flows directly within a native iOS experience.

Use this SDK when building wallet apps that require frictionless and secure checkout with passkeys.

Requirements

  • iOS 16+
  • XCode 16+
  • Swift 6+

Prerequisites

  • Create an application to obtain a base URL. The SDK uses this base URL to interact with the LoginID authentication service.
  • Create an API key with at least the external:verify scope. You’ll need this to request authorization tokens from your backend.

Configure apple-app-site-association File

In order for passkeys to work with your iOS application, you need to link your application with a website. You do this by creating an apple-app-site-association and hosting it on your domain website. More info here.

You Need an Apple Developer Account

An Apple Developer Account is a requirement as the Associated Domains capability is not available for free. Currently, an Apple Developer Account can be obtained from https://developer.apple.com/support/enrollment.

Obtain Team ID and Bundler ID

  • The team ID can be obtained on your developer account console at https://developer.apple.com/account.
  • The bundler ID can be obtained on your Signing & Capabilities section of your application.

Host apple-app-site-association JSON File on Your Website Directory

To host an apple-app-site-association file, you need to serve it as a static JSON file on your website. Note that the file must be named exactly apple-app-site-association without the .json extension and your server must be configured to serve it as JSON. The file should be located at <WEBSITE_DOMAIN>/.well-known/apple-app-site-association in the root directory of your website.

Here is an example of the minimum required fields in the file:

{
"webcredentials": {
"apps": ["<TEAM_ID>.<BUNDLER_ID>"]
}
}

Use the following example as a template and replace TEAM_ID and BUNDLER_ID with your values.

More information here.

Create an Associated Domains Capability on Your iOS App

To enable this capability

  1. You must have an Apple Developer Account
  2. Go to the Signing & Capabilities section of your application
  3. Add a capability by clicking the + Capability button
  4. Choose Associated Domains
  5. Enter the domain of your hosted website. Make sure to prefix it with webcredentials. Here's an example of what it should look like:
webcredentials:example.com

Setup SDK

Using the Swift Package Manager

  1. In Xcode, open your project.
  2. Go to File → Add Package Dependencies….
  3. In the search bar, paste:
https://github.com/loginid1/loginid-ios
  1. Select the target(s) where you want to add the SDK and click Add Package.

Import the class within your view models:

import LoginIDWalletAuth

@main
struct MyApp: App {
private let lid: LoginID

init() {
let baseUrl = "<LOGINID_BASE_URL>"
LoginID(baseUrl: baseUrl)

// Other setup code...
}
}
info

You can view the source code here.

Class LoginIDWalletAuth

A specialized authentication helper built on top of LoginID's MFA flow, designed for checkout scenarios where you need both authentication and identity trust.

This helps orchestrate the MFA flow tied to a transaction (e.g., confirming a purchase) using passkeys.

constructor

Initializes a new instance of the LoginIDWalletAuth.

final public class LoginID : Sendable

public init(baseUrl: String)

ParameterTypeRequiredDescription
baseUrlStringYesThe LoginID environment base URL (e.g., from your environment configuration).

public init(config: LoginIDConfig)

ParameterTypeRequiredDescription
configLoginIDConfigYesThe complete configuration used to initialize the underlying LoginID SDK.
config.baseUrlStringYesThe base URL of the LoginID service.

LoginID

beginFlow

Begins the MFA authentication flow for a checkout session.

This starts an MFA session bound to a specific transaction payload and optional identifiers such as merchant checkoutId.

public func beginFlow(
options: BeginFlowOptions
) async throws -> MFASessionResult

ParameterTypeRequiredDescription
optionsBeginFlowOptionsYesContains the transaction payload and optional identifiers.
options.checkoutId?StringNoAn identifier generated on the merchant side to identify the current checkout session. This identifier is used as a key to retrieve associated trust information.

It is passed to the wallet to link the session with wallet-issued identity data, enabling secure transaction confirmation without revealing end-user identity to the merchant.
options.traceId?StringNoA unique identifier used to trace and correlate all events associated with a single MFA interaction.

This ID is useful for end-to-end observability, logging, and debugging across distributed systems. It can be generated by the client or left unset—if not provided, a secure random ID will be created automatically by LoginID.

Example: 6957cf6e-a86c-44fb-b25a-bd97cb9ff830
options.txPayloadStringYesA transaction payload generated by the merchant to represent the purchase or operation being confirmed.
options.username?StringNoThe username of the user initiating the checkout session. If not provided, the wallet may retrieve it from an embedded context.

public struct MFASessionResult: Sendable {
public let flow: MfaNext.Flow?
public let remainingFactors: [RemainingAction]
public let username: String?
public let isComplete: Bool
public let session: String?
public let idToken: String?
public let accessToken: String?
public let refreshToken: String?
public let payloadSignature: String?
public let nextAction: MfaActionAction.Name?
}

performAction

Performs an MFA action using the provided factor and optional payload.

In a checkout context, this method commonly covers:

  • Passkey Registration (.passkeyReg): Register a new passkey (e.g., WebAuthn) during account creation.
  • Passkey Authentication (.passkeyAuth): signin into a wallet account using a passkey.
  • Passkey Transaction Confirmation (.passkeyTx): Confirm a specific transaction using a passkey.
  • External Authentication (.external): Signin with a third-party authentication (e.g. bank login).

public func performAction(action: MfaActionAction.Name, options: PerformActionOptions?)

public func performAction(
action: MfaActionAction.Name,
options: PerformActionOptions?
) async throws -> MFASessionResult

ParameterTypeRequiredDescription
actionpasskeyReg
passkeyAuth
passkeyTx
otpEmail
otpSms
otpVerify
external
YesThe MFA factor to be executed.
optionsPerformActionOptions = {}NoThe payload for the factor.
options.autoFill?booleanNoEnables passkey support in browser autofill suggestions (Keyboard autofil).
options.displayName?stringNoA human-palatable name for the user account, intended only for display on your passkeys.
options.payload?stringNoThe payload required for completing the authentication factor. This typically contains user input or challenge-response data.
options.txPayload?stringNoAn updated transaction payload generated by the merchant to represent the purchase or operation being confirmed. This updates the initial txPayload used in the beginFlow method.

public struct MFASessionResult: Sendable {
public let flow: MfaNext.Flow?
public let remainingFactors: [RemainingAction]
public let username: String?
public let isComplete: Bool
public let session: String?
public let idToken: String?
public let accessToken: String?
public let refreshToken: String?
public let payloadSignature: String?
public let nextAction: MfaActionAction.Name?
}

public func performAction(action: MfaActionAction.Name)

public func performAction(
action: MfaActionAction.Name,
) async throws -> MFASessionResult

ParameterTypeRequiredDescription
actionpasskeyReg
passkeyAuth
passkeyTx
otpEmail
otpSms
otpVerify
external
YesThe MFA factor to be executed.

public struct MFASessionResult: Sendable {
public let flow: MfaNext.Flow?
public let remainingFactors: [RemainingAction]
public let username: String?
public let isComplete: Bool
public let session: String?
public let idToken: String?
public let accessToken: String?
public let refreshToken: String?
public let payloadSignature: String?
public let nextAction: MfaActionAction.Name?
}