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 & Capabilitiessection 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
- You must have an Apple Developer Account
- Go to the
Signing & Capabilitiessection of your application - Add a capability by clicking the
+ Capabilitybutton - Choose
Associated Domains - 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
- In Xcode, open your project.
- Go to File → Add Package Dependencies….
- In the search bar, paste:
https://github.com/loginid1/loginid-ios
- Select the target(s) where you want to add the SDK and click Add Package.
- Swift
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...
}
}
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.
| Parameter | Type | Required | Description |
|---|---|---|---|
| config | LoginIDConfig | Yes | The configuration object for the LoginID API. |
| config.baseUrl | String | Yes | The base URL of the LoginID service. This value is used to resolve the App ID and make API calls. |
| config.useTrustId | Bool | No | If true, uses TrustID, a Crypto–derived device identifier, as a device possession factor. Defaults to false. |
| config.disableAnalytics | Bool | No | If true, disables sending analytics/events to LoginID. Defaults to false. |
LoginIDAuth
init(baseUrl: String)
Creates a new LoginIDAuth instance using a base URL string.
| Parameter | Type | Required | Description |
|---|---|---|---|
| baseUrl | String | Yes | The 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?)
| Parameter | Type | Required | Description |
|---|---|---|---|
| username | String | Yes | The username for which to create the passkey. |
| options | CreatePasskeyOptions? | No | Optional parameters for passkey creation. |
| options.authzToken | String? | No | Authorization token used for accessing protected resources. |
| options.usernameType | UsernameType | No | The type of username validation to be used. Defaults to .other and is omitted from the payload when .other. |
| options.displayName | String? | No | A human-palatable name for the user account, intended only for display on your passkeys and modals. |
| options.passkeyName | String? | No | A custom label or nickname when creating a passkey. Useful for distinguishing between multiple passkeys. |
| options.deviceId | String? | No | An 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?)
| Parameter | Type | Required | Description |
|---|---|---|---|
| username | String | Yes | The username for which to create the passkey. |
| authzToken | String | Yes | An authorization token from a previous authentication step. |
| options | CreatePasskeyOptions? | No | Optional parameters for passkey creation. |
| options.authzToken | String? | No | Authorization token used for accessing protected resources. |
| options.usernameType | UsernameType | No | The type of username validation to be used. Defaults to .other and is omitted from the payload when .other. |
| options.displayName | String? | No | A human-palatable name for the user account, intended only for display on your passkeys and modals. |
| options.passkeyName | String? | No | A custom label or nickname when creating a passkey. Useful for distinguishing between multiple passkeys. |
| options.deviceId | String? | No | An 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?)
| Parameter | Type | Required | Description |
|---|---|---|---|
| username | String | Yes | The username of the user to authenticate. |
| options | AuthenticateWithPasskeyOptions? | No | Optional parameters for passkey authentication. |
| options.usernameType | UsernameType | No | The type of username validation to be used. Defaults to .other and is omitted from the payload when .other. |
| options.autofill | Bool? | No | When 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?)
| Parameter | Type | Required | Description |
|---|---|---|---|
| options | AuthenticateWithPasskeyOptions? | No | Optional parameters for passkey authentication. |
| options.usernameType | UsernameType | No | The type of username validation to be used. Defaults to .other and is omitted from the payload when .other. |
| options.autofill | Bool? | No | When 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?)
| Parameter | Type | Required | Description |
|---|---|---|---|
| username | String | Yes | The username of the account holder confirming the transaction. |
| txPayload | String | Yes | A string representing the transaction details, such as an amount or action. |
| options | ConfirmTransactionOptions? | No | Optional parameters to customize the transaction, like providing a nonce or specifying the txType. |
| options.nonce | String? | No | A unique nonce to ensure the transaction's integrity and prevent replay attacks If not provided, a new UUID will be generated. |
| options.txType | String? | No | The 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?)
| Parameter | Type | Required | Description |
|---|---|---|---|
| options | ListPasskeysOptions? | No | Options for the request, including an optional authorization token. |
| options.authzToken | String? | No | An 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)
| Parameter | Type | Required | Description |
|---|---|---|---|
| authzToken | String | Yes | Authorization 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?)
| Parameter | Type | Required | Description |
|---|---|---|---|
| id | String | Yes | The unique identifier of the passkey to rename. |
| name | String | Yes | The new name for the passkey. |
| options | RenamePasskeyOptions? | No | Options for the request, including an optional authorization token. |
| options.authzToken | String? | No | An 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)
| Parameter | Type | Required | Description |
|---|---|---|---|
| id | String | Yes | The unique identifier of the passkey to rename. |
| name | String | Yes | The new name for the passkey. |
| authzToken | String | Yes | Authorization 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?)
| Parameter | Type | Required | Description |
|---|---|---|---|
| id | String | Yes | The unique identifier of the passkey to delete. |
| options | DeletePasskeyOptions? | No | Options for the request, including an optional authorization token. |
| options.authzToken | String? | No | An 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)
| Parameter | Type | Required | Description |
|---|---|---|---|
| id | String | Yes | The unique identifier of the passkey to delete. |
| authzToken | String | Yes | Authorization 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?)
| Parameter | Type | Required | Description |
|---|---|---|---|
| options | RequestOtpOptions? | No | Options for the request, including an optional authorization token. |
| options.authzToken | String? | No | An 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?)
| Parameter | Type | Required | Description |
|---|---|---|---|
| username | String | Yes | The username of the account being authenticated. |
| otp | String | Yes | The one-time password entered by the user. |
| options | ValidateOtpOptions? | No | Optional parameters to customize the request, such as usernameType. |
| options.usernameType | UsernameType | No | The 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?)
| Parameter | Type | Required | Description |
|---|---|---|---|
| username | String | Yes | The username to send the OTP to. |
| method | .email.sms | No | The delivery channel, either .email or .sms. Defaults to .email. |
| options | RequestAndSendOtpOptions? | No | Optional parameters to customize the request, such as usernameType. |
| options.usernameType | UsernameType | No | The 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.
| Field | Type | Details |
|---|---|---|
| msg | string | The error code associated with the login error. |
| msgCode | string | The detailed message or description of the error. |
| message | string | The 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)")
}