此 SDK 的目的是能够通过 Passwordless.dev 管理系统的帮助,轻松将 passkeys 集成到您的 iOS 应用中。为确保正确使用,提供了一个名为 DemoPasswordless
的示例项目,并将其包含在此仓库中以及 SDK 内。
Passwordless.dev 由三个关键部分组成:
- 一个开源客户端 SDK(例如,此 iOS SDK),由您的应用/网站使用,在终端用户的设备上初始化 passkey 授权请求,并请求与 passwordless.dev API 交互。
- 一个公共 RESTful API,用于完成 FIDO2 WebAuthn 密码学交换。
- 一个私有 RESTful API,用于初始化密钥注册、验证登录和检索终端用户的密钥。
有关详细信息,请参阅 Passwordless.dev 文档。
Apple 需要设置相关域以执行 passkey 注册和声明。有关设置 apple-app-site-association 的更多详细信息,请参阅 Apple 的文档。
对于 passkeys,您需要为您的应用设置一个 webcredentials
部分。
您可以在此示例中查看与应用此仓库中提供的 DemoPasswordless
应用对应的 apple-app-site-association。
以下是在 demo.passwordless.dev
上托管 AASA 时 Xcode 中应呈现的底盘示例
- **最低 iOS 版本**: iOS 16
- 附加功能
- **相关域**:需要添加 AASA 文件托管的域。
您可以通过 Swift 包管理器 将 SDK 添加到您的项目中。然后您可以使用 import Passwordless
访问 SDK 功能。
您可以通过 CocoaPods 将 SDK 添加到您的项目中。在您的 Podfile 中指定以下内容:
pod 'Passwordless', '~> 0.0.1'
SDK 提供一个需要使用 PasswordlessConfig
配置初始化的 PasswordlessClient
对象。该配置包含与 Passwordless.dev 交互所需的 API URL 和 API 密钥。它还需要代表您托管具有您的应用团队 ID 和 bundle ID 的 apple-app-site-association 文件的服务的域名依赖方 ID。
您需要注册 Passwordless.dev 以获取 API 密钥。
以下是一个配置示例
let passwordlessClient = PasswordlessClient(
config: PasswordlessConfig(
apiKey: "<YOUR API KEY>",
rpId: "demo.passwordless.dev"
)
)
- 使用给定的用户名从您的公共 RESTful API 请求注册令牌。
- 通过
register(token:)
函数将注册令牌传递给PasswordlessClient
。这将提示用户使用生物识别创建用于验证的本地私钥,并将公钥发送到Passwordless.dev API。完成后,将返回一个验证令牌。有关可能抛出的错误,请参阅错误部分。
let verifyToken = try await passwordlessClient.register(token: registrationToken)
- 将验证令牌传递到您的公共RESTful API进行验证,并返回一个授权令牌。用户现在已登录到您的应用。
passkey 登录有两种主要方法:自动填充和别名。还提供了signinWithDiscoverable()
和signIn(userId:)
,以便用于更复杂的使用场景。
当用户点按用户名字段并显示键盘时,这就是自动填充的情况。如果用户点按键盘上方的自动填充选项,那么这就是自动填充的方法。为了正确工作,当您的视图首次出现时,您必须调用signInWithAutofill
。这样,当键盘出现时,操作系统将准备好要显示的结果。
- 当您的视图首次出现时调用
signInWithAutofill()
。一旦完成,将返回一个验证令牌。- 此函数将等待用户点按自动填充项、在passkey对话框中取消或发生错误。
- 如果抛出错误,您的应用将需要决定是否重新启动自动填充登录过程。
- 如果它未运行,则键盘上不会显示任何选项,因此通常仅在
authorizationCancelled
情况下重新启动过程才有意义。 - 收到
authorizationError
可能表明您的应用内部有一些配置不正确,因此最好不再次运行自动填充以防止无限循环错误。请参阅错误部分,了解可能抛出的错误。
let verifyToken = try await passwordlessClient.signInWithAutofill()
- 将验证令牌传递到您的公共RESTful API进行验证,并返回一个授权令牌。用户现在已登录到您的应用。
当用户输入用户名并点击视图中用于登录的按钮时,这就是别名的情况。这将为用户提供不同的passkey窗口版本进行选择。
- 使用给定的别名调用
signIn(alias:)
。一旦完成,将返回一个验证令牌。有关可能抛出的错误,请参阅错误部分。
let verifyToken = try await passwordlessClient.signIn(alias: username)
- 将验证令牌传递到您的公共RESTful API进行验证,并返回一个授权令牌。用户现在已登录到您的应用。
如果您希望手动显示passkey模态而不用键盘快捷键或让用户输入别名。
如果您已有用户 Id并且想进行声明过程。
PasswordlessClient对象可以抛出以下错误
错误 | 描述 |
---|---|
authorizationCancelled | 从密钥凭证提供者取消了操作系统授权。 |
authorizationError(Error) | 从密钥凭证提供者处失败的操作系统授权。 |
internalErrorDecodingJson(Error) | 从网络响应中解码json到对象时出现问题。 |
internalErrorEncodingPayload(Error) | 在为网络请求编码json时出现问题。 |
internalErrorInvalidURL(String) | 用于发出网络请求的url无效。 |
internalErrorNetworkRequestFailed(Error) | 发出网络请求时发生错误。 |
internalErrorNetworkRequestResponseError(Int?, PasswordlessErrorResponse?) | 在网络请求中发生错误响应,给定状态代码和错误响应(如有)。 |
internalErrorUnableToDecodeChallenge | 提供的挑战格式不正确。 |
internalErrorUnableToEncodeUserId | 用户 ID 无法编码为 base 64 Url。 |
对于internalErrorNetworkRequestResponseError,可以提供PasswordlessErrorResponse,其中包含有关响应中错误的详细信息。以下是一个可能返回的响应错误示例
{
"type": "https://docs.passwordless.dev/errors#missing_register_token",
"title": "The token you sent was not correct. The token used for this endpoint should start with 'register_'. Make sure you are not sending the wrong value.",
"status": 400,
"errorCode": "missing_register_token"
}
以下是如何在您的应用中查看此示例
do {
let verifyToken = try await passwordlessClient.signIn()
}
catch PasswordlessClientError.authorizationCancelled {
print("Cancelled")
}
catch let PasswordlessClientError.internalErrorNetworkRequestResponseError(code, response) {
print("Network Error occurred. Response status code: \(code ?? -1)")
dump(response)
}
catch {
print("Some other error occurred: \(error)")
}
本项目包含一个名为DemoPasswordless的示例应用程序。需要注意,如果您计划运行此应用程序,您必须事先进行一些配置。
- 密钥认证与存储在您的公共API上的apple-app-site-association (AASA) 文件直接关联。
- 运行应用程序时,您的开发者帐户必须在对应的AASA文件指定的Apple团队中,并且有一个匹配的包标识符。
例如,假设您的AASA文件如下所示
{
"webcredentials": {
"apps": [
"Q999999997.com.8bit.bitwarden.passwordlessios"
]
}
}
为了正确运行演示应用程序,应用程序的包标识符必须为com.8bit.bitwarden.passwordlessios
。此外,您的个人开发者帐户必须有权访问团队标识符Q999999997
。
在DemoServices.swift
文件中,可信方ID(rpID
)应设置为存放此AASA文件的域名。