Skip to main content

iOS

Overview

The LoginID iOS SDK enables you to add passkey authentication in your native iOS application without having to redirect the user to any pages outside your application.

The SDK leverages the Authentication Services framework for creating and syncing passkeys with iCloud Keychain.

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 LoginIDAuth

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

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

// Other setup code...
}
}
info

You can view the source code here.

Class LoginIDAuth

The main entry point for the LoginIDAuth package. Provides access to all SDK functionality, including configuration, and LoginID standalone authentication services.

constructor

Initializes a new instance of the LoginIDAuth.

final public class LoginIDAuth: Sendable

init(config: LoginIDConfig)

Creates a new LoginIDAuth instance using a LoginIDConfig object.

ParameterTypeRequiredDescription
configLoginIDConfigYesThe configuration object for the LoginID API.
config.baseUrlStringYesThe base URL of the LoginID service.

This value is used to resolve the App ID and make API calls.
config.useTrustIdBoolNoIf true, uses TrustID, a Crypto–derived device identifier, as a device possession factor. Defaults to false.
config.disableAnalyticsBoolNoIf true, disables sending analytics/events to LoginID. Defaults to false.

LoginIDAuth

init(baseUrl: String)

Creates a new LoginIDAuth instance using a base URL string.

ParameterTypeRequiredDescription
baseUrlStringYesThe base URL for the LoginID API.

LoginIDAuth

createPasskey

createPasskey(username: String, options: CreatePasskeyOptions?)

This method helps to create a passkey. The only required parameter is the username, but additional attributes can be provided in the options parameter. Note: While the authorization token is optional, it must always be used in a production environment. You can skip it during development by adjusting the app configuration in the LoginID dashboard. A short-lived authorization token is returned, allowing access to protected resources for the given user such as listing, renaming or deleting passkeys.

createPasskey(username: String, options: CreatePasskeyOptions?)

ParameterTypeRequiredDescription
usernameStringYesThe username for which to create the passkey.
optionsCreatePasskeyOptions?NoOptional parameters for passkey creation.
options.authzTokenString?NoAuthorization token used for accessing protected resources.
options.usernameTypeUsernameTypeNoThe type of username validation to be used.

Defaults to .other and is omitted from the payload when .other.
options.displayNameString?NoA human-palatable name for the user account, intended only for display on your passkeys and modals.
options.passkeyNameString?NoA custom label or nickname when creating a passkey. Useful for distinguishing between multiple passkeys.
options.deviceIdString?NoAn identifier for the device used when creating a passkey.

This value helps LoginID determine whether device-specific authentication
flows are supported and allows future authentications to identify the
device correctly.
- Note: Only used by createPasskey.

struct AuthResult {
let token: String?
let isAuthenticated: Bool
let isFallback: Bool
let userId: String?
let passkeyId: String?
let deviceId: String?
}

createPasskey(username: String, authzToken: String, options: CreatePasskeyOptions?)

This method helps to create a passkey. The only required parameter is the username, but additional attributes can be provided in the options parameter. Note: While the authorization token is optional, it must always be used in a production environment. You can skip it during development by adjusting the app configuration in the LoginID dashboard. A short-lived authorization token is returned, allowing access to protected resources for the given user such as listing, renaming or deleting passkeys.

createPasskey(username: String, authzToken: String, options: CreatePasskeyOptions?)

ParameterTypeRequiredDescription
usernameStringYesThe username for which to create the passkey.
authzTokenStringYesAn authorization token from a previous authentication step.
optionsCreatePasskeyOptions?NoOptional parameters for passkey creation.
options.authzTokenString?NoAuthorization token used for accessing protected resources.
options.usernameTypeUsernameTypeNoThe type of username validation to be used.

Defaults to .other and is omitted from the payload when .other.
options.displayNameString?NoA human-palatable name for the user account, intended only for display on your passkeys and modals.
options.passkeyNameString?NoA custom label or nickname when creating a passkey. Useful for distinguishing between multiple passkeys.
options.deviceIdString?NoAn identifier for the device used when creating a passkey.

This value helps LoginID determine whether device-specific authentication
flows are supported and allows future authentications to identify the
device correctly.
- Note: Only used by createPasskey.

struct AuthResult {
let token: String?
let isAuthenticated: Bool
let isFallback: Bool
let userId: String?
let passkeyId: String?
let deviceId: String?
}

authenticateWithPasskey

authenticateWithPasskey(username: String, options: AuthenticateWithPasskeyOptions?)

This method authenticates a user with a passkey and may trigger additional browser dialogs to guide the user through the process. A short-lived authorization token is returned, allowing access to protected resources for the given user such as listing, renaming or deleting passkeys.

authenticateWithPasskey(username: String, options: AuthenticateWithPasskeyOptions?)

ParameterTypeRequiredDescription
usernameStringYesThe username of the user to authenticate.
optionsAuthenticateWithPasskeyOptions?NoOptional parameters for passkey authentication.
options.usernameTypeUsernameTypeNoThe type of username validation to be used.

Defaults to .other and is omitted from the payload when .other.
options.autofillBool?NoWhen true it will enable passkey keyboard autofill suggestions. Username does not need to be set.

struct AuthResult {
let token: String?
let isAuthenticated: Bool
let isFallback: Bool
let userId: String?
let passkeyId: String?
let deviceId: String?
}

authenticateWithPasskeyAutofill

authenticateWithPasskeyAutofill(options: AuthenticateWithPasskeyOptions?)

Authenticates a user by utilizing the browser's passkey autofill capabilities. A short-lived authorization token is returned, allowing access to protected resources for the given user such as listing, renaming or deleting passkeys.

authenticateWithPasskeyAutofill(options: AuthenticateWithPasskeyOptions?)

ParameterTypeRequiredDescription
optionsAuthenticateWithPasskeyOptions?NoOptional parameters for passkey authentication.
options.usernameTypeUsernameTypeNoThe type of username validation to be used.

Defaults to .other and is omitted from the payload when .other.
options.autofillBool?NoWhen true it will enable passkey keyboard autofill suggestions. Username does not need to be set.

struct AuthResult {
let token: String?
let isAuthenticated: Bool
let isFallback: Bool
let userId: String?
let passkeyId: String?
let deviceId: String?
}

confirmTransaction

confirmTransaction(username: String, txPayload: String, options: ConfirmTransactionOptions?)

This method initiates a non-repudiation signature process by generating a transaction-specific challenge and then expects the client to provide an assertion response using a passkey. This method is useful for confirming actions such as payments or changes to sensitive account information, ensuring that the transaction is being authorized by the rightful owner of the passkey. For a more detailed guide click here.

confirmTransaction(username: String, txPayload: String, options: ConfirmTransactionOptions?)

ParameterTypeRequiredDescription
usernameStringYesThe username of the account holder confirming the transaction.
txPayloadStringYesA string representing the transaction details, such as an amount or action.
optionsConfirmTransactionOptions?NoOptional parameters to customize the transaction, like providing a nonce or specifying the txType.
options.nonceString?NoA unique nonce to ensure the transaction's integrity and prevent replay attacks

If not provided, a new UUID will be generated.
options.txTypeString?NoThe type of transaction payload, such as raw or a custom format.

Defaults to raw if not specified.

struct TxConfirmResult {
let token: String
let credentialId: String
let passkey: PasskeyDetails?
}

listPasskeys

listPasskeys(options: ListPasskeysOptions?)

This method returns list of passkeys associated with the current user. The user must be fully authorized for this call to succeed.

listPasskeys(options: ListPasskeysOptions?)

ParameterTypeRequiredDescription
optionsListPasskeysOptions?NoOptions for the request, including an optional authorization token.
options.authzTokenString?NoAn optional authorization token for the request.

If not provided, the SDK will use a stored token if available.

[struct PasskeyDetails {
let aaguid: String
let id: String
let credentialId: String?
let name: String
let providerName: String?
let createdAt: String
let lastUsedAt: String?
let credentialSynced: Bool
let lastUsedFromDevice: DeviceDetails?
}]

listPasskeys(authzToken: String)

This method returns list of passkeys associated with the current user. The user must be fully authorized for this call to succeed.

listPasskeys(authzToken: String)

ParameterTypeRequiredDescription
authzTokenStringYesAuthorization token.

[struct PasskeyDetails {
let aaguid: String
let id: String
let credentialId: String?
let name: String
let providerName: String?
let createdAt: String
let lastUsedAt: String?
let credentialSynced: Bool
let lastUsedFromDevice: DeviceDetails?
}]

renamePasskey

renamePasskey(id: String, name: String, options: RenamePasskeyOptions?)

Renames a specified passkey by ID. The user must be fully authorized for this call to succeed.

renamePasskey(id: String, name: String, options: RenamePasskeyOptions?)

ParameterTypeRequiredDescription
idStringYesThe unique identifier of the passkey to rename.
nameStringYesThe new name for the passkey.
optionsRenamePasskeyOptions?NoOptions for the request, including an optional authorization token.
options.authzTokenString?NoAn optional authorization token for the request.

If not provided, the SDK will use a stored token if available.

renamePasskey(id: String, name: String, authzToken: String)

Renames a specified passkey by ID. The user must be fully authorized for this call to succeed.

renamePasskey(id: String, name: String, authzToken: String)

ParameterTypeRequiredDescription
idStringYesThe unique identifier of the passkey to rename.
nameStringYesThe new name for the passkey.
authzTokenStringYesAuthorization token.

deletePasskey

deletePasskey(id: String, options: DeletePasskeyOptions?)

Delete a specified passkey by ID from LoginID. The user must be fully authorized for this call to succeed.

deletePasskey(id: String, options: DeletePasskeyOptions?)

ParameterTypeRequiredDescription
idStringYesThe unique identifier of the passkey to delete.
optionsDeletePasskeyOptions?NoOptions for the request, including an optional authorization token.
options.authzTokenString?NoAn optional authorization token for the request.

If not provided, the SDK will use a stored token if available.

deletePasskey(id: String, authzToken: String)

Delete a specified passkey by ID from LoginID. The user must be fully authorized for this call to succeed.

deletePasskey(id: String, authzToken: String)

ParameterTypeRequiredDescription
idStringYesThe unique identifier of the passkey to delete.
authzTokenStringYesAuthorization token.

requestOtp

requestOtp(options: RequestOtpOptions?)

This method returns a one-time OTP to be displayed on the current device. The user must be authenticated on this device. The OTP is meant for cross-authentication, where the user reads the OTP from the screen and enters it on the target device.

requestOtp(options: RequestOtpOptions?)

ParameterTypeRequiredDescription
optionsRequestOtpOptions?NoOptions for the request, including an optional authorization token.
options.authzTokenString?NoAn optional authorization token for the request.

If not provided, the SDK will use a stored token if available.

struct OTPResult {
let code: String
let expiresAt: String
}

validateOtp

validateOtp(username: String, otp: String, options: ValidateOtpOptions?)

This method verifies the OTP and returns an authorization token, which can be used with the passkeyCreate() method to create a new passkey. The authorization token has a short validity period and should be used immediately.

validateOtp(username: String, otp: String, options: ValidateOtpOptions?)

ParameterTypeRequiredDescription
usernameStringYesThe username of the account being authenticated.
otpStringYesThe one-time password entered by the user.
optionsValidateOtpOptions?NoOptional parameters to customize the request, such as usernameType.
options.usernameTypeUsernameTypeNoThe type of username validation to be used.

Defaults to .other and is omitted from the payload when .other.

struct AuthResult {
let token: String?
let isAuthenticated: Bool
let isFallback: Bool
let userId: String?
let passkeyId: String?
let deviceId: String?
}

requestAndSendOtp

requestAndSendOtp(username: String, method: MessageMethod, options: RequestAndSendOtpOptions?)

This method requests an OTP from the backend to be sent via the selected method. The method of delivery should be based on the user's choice from the list of available options. This can be found in the result of authenticateWithPasskey method as fallbackOptions.

requestAndSendOtp(username: String, method: MessageMethod, options: RequestAndSendOtpOptions?)

ParameterTypeRequiredDescription
usernameStringYesThe username to send the OTP to.
method.email
.sms
NoThe delivery channel, either .email or .sms. Defaults to .email.
optionsRequestAndSendOtpOptions?NoOptional parameters to customize the request, such as usernameType.
options.usernameTypeUsernameTypeNoThe type of username validation to be used.

Defaults to .other and is omitted from the payload when .other.

verifyConfigSettings

verifyConfigSettings()

Validates the application's configuration settings and provides a suggested correction if any issues are detected.

verifyConfigSettings()

struct LoginIDConfigResult {
let solution: String
let code: String
let errorMessage: String
}

getSessionInfo

getSessionInfo()

Check whether the user of the current browser session is authenticated and returns user info. This info is retrieved locally and no requests to backend are made.

getSessionInfo()

struct SessionInfo {
let username: String
let id: String
let rpId: String
}

logout

logout()

Clears current user session. This method ideletes the authorization token locally.

logout()

Errors

LoginIDError

Can occur during the authentication process. It is designed to encapsulate detailed information about login-related errors, making it easier to handle and debug issues related to user authentication.

FieldTypeDetails
msgstringThe error code associated with the login error.
msgCodestringThe detailed message or description of the error.
messagestringThe detailed message or description of the error. (alias of msgCode)

Here is an example:


...
...

} catch let error as LoginIDError {
print("Failed with error: \(error.message)")
print("Failed with error code: \(error.msgCode)")
}