Rownd SDK for iOS
Rownd iOS SDK 为原生 iPhone、iPad 以及甚至 macOS 应用程序提供身份验证、账户和用户资料管理、深度链接、加密等功能。
使用 Rownd 平台,您可以将与网站相同的身份验证轻松带到您的移动应用中。或者,如果您只在移动应用中验证用户,则可以使用 Rownd 的无密码登录链接简化验证过程,使您能够无缝地通过发送到用户邮箱或电话号码的应用链接进行身份验证。
一旦用户完成身份验证,您就可以使用原生 API 在线获取和更新用户的资料信息。利用 Rownd 预构建的移动应用组件,为用户提供资料管理工具。另外,您可以在发送回 Rownd 或您的后端之前,在设备上管理数据的加密。
安装
在 Xcode 中,选择您的项目文件,选择主目标,然后滚动到“框架”部分,为您的项目添加包依赖项。有关具体步骤,请参阅官方文档。
将此作为包存储库 URL 输入
https://github.com/rownd/ios.git
使用
初始化Rownd SDK
在您的AppDelegate
文件中,在应用启动期间调用Rownd.configure()
方法
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
Task {
await Rownd.configure(launchOptions: launchOptions, appKey: "YOUR_API_KEY")
}
return true
}
初始化后,您的应用通常会在某个时刻调用Rownd.requestSignIn()
,如果用户尚未认证。这将显示用于用户认证的Rownd界面。一旦他们完成登录过程,访问令牌和用户个人资料信息将可用于您的应用。
处理认证
Rownd利用可观察的架构来向您的应用公开数据。这意味着随着Rownd状态的变化,应用可以动态更新而无需复杂的逻辑。例如,视图可以根据用户的认证状态显示不同的信息。
以下是一个 SwiftUI 视例,根据用户的认证状态显示不同的信息
import SwiftUI
import Rownd
struct MyView: View {
@StateObject var authState = Rownd.getInstance().state().subscribe { $0.auth }
@StateObject var user = Rownd.getInstance().state().subscribe { $0.user.data }
var body: some View {
VStack {
HStack {
Button(action: {
if authState.current.isAuthenticated {
Rownd.signOut()
} else {
Rownd.requestSignIn()
}
},
label: {
Text(!authState.current.isAuthenticated ? "Sign in" : "Sign out")
})
Spacer()
if authState.current.isAuthenticated {
Button(action: {
}, label: {
Text(user.current?["first_name"]?.value as? String)
})
}
}
.padding(.horizontal)
}
}
}
struct MyView_Previews: PreviewProvider {
static var previews: some View {
MyView()
}
}
您可以订阅Rownd支持的所有状态对象。以下是可用状态及其结构的列表
.auth
public struct AuthState {
public var accessToken: String? // Current, valid access token for the user (valid for one hour)
public var isVerifiedUser: Bool? // Whether the current user has verified at least one identifier (e.g., email)
public var hasPreviouslySignedIn: Bool // Whether the app has been previously signed in before
}
.user
public struct UserState {
public var id: String? // The user's ID as known to Rownd
public var data: Dictionary<String, AnyCodable> // Contains key/value pairs for the current user based on your Rownd's app config
public var redacted: [String] // An array of field keys that the current user has disabled your app from accessing
}
自定义用户界面
虽然大多数自定义操作可通过Rownd仪表板处理,但有几项需要直接在SDK中进行自定义。
RowndCustomizations
类存在就是为了方便这些自定义操作。它提供了以下属性,这些属性可以被继承或覆盖。
sheetBackgroundColor: UIColor
(默认:light: .white
,dark: .systemGray6
;需要继承子类)- 允许改变显示登录界面、管理用户账号、传输加密密钥等时出现的底栏背景颜色。sheetCornerBorderRadius: CGFloat
(默认:25.0
)- 修改底栏角的弧度半径。loadingAnimation: Lottie.Animation
(默认:nil)- 用自定义动画替换Rownd使用的系统默认加载旋转器(即UIActivityIndicatorView
或ProgressView
)。任何与Lottie兼容的动画都可以工作,但将被缩放以适应1:1的宽高比(通常宽度/高度的CGRect
框架为100
)
要应用自定义设置,我们建议继承RowndCustomizations
类。以下是一个例子
class AppCustomizations : RowndCustomizations {
override var sheetBackgroundColor: UIColor {
return UIColor(red: 31/255, green: 37/255, blue: 80/255, alpha: 1.0)
}
}
// AppDelegate.swift
import Rownd
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
Rownd.config.customizations = AppCustomizations() // Apply the customizations
Task {
await Rownd.configure(launchOptions: launchOptions, appKey: "YOUR_API_KEY")
}
return true
}
}
API参考
Rownd除了提供可观察的状态API之外,还提供了一些命令式API供您调用,以发起登录请求、获取和检索用户配置文件信息、检索当前访问令牌或使用用户的本地密钥加密用户数据。
Rownd.requestSignIn() -> Void
打开Rownd登录对话框进行认证。
https://my-domain.com")) -> Void
Rownd.requestSignIn(RowndSignInOptions(postSignInRedirect: "打开Rownd登录对话框进行认证,如同上文。当用户通过电子邮件或短信完成认证挑战后,他们将被重定向到为 postSignInRedirect
设置的URL。如果这是一个 通用链接,则将用户重定向回您的应用程序。
Rownd.requestSignIn(with: RowndSignInHint) -> Void
请求登录,但使用特定的认证提供者(例如,使用Apple ID登录)。Rownd将此信息视为提示。如果指定的认证提供者在您的Rownd应用程序配置中已启用,它将被尊重。如果没有,Rownd将回退到默认流程。
支持的值
.appleId
- 提示用户使用他们的Apple ID登录
Rownd.getAccessToken() async throws -> String?
假设用户已登录,返回有效的访问令牌,如果需要则刷新当前令牌。如果由于临时条件(例如,不可访问的网络)无法返回访问令牌,此函数将抛出异常。如果由于刷新令牌无效而无法返回访问令牌,将返回 nil
,并且 Rownd 状态将注销用户。
示例
do {
let accessToken = try await Rownd.getAccessToken()
} catch {
// Alert the user that they should try again due to some recoverable error
}
}
Rownd.getAccessToken(_ token: String) async -> String?
尽可能地将非 Rownd 访问令牌交换为 Rownd 访问令牌。这主要用于应用程序从其他身份验证机制迁移到 Rownd 的场景。使用 Rownd 集成,系统将接受第三方令牌。如果成功验证,Rownd 将登录用户并向调用方返回新的 Rownd 访问令牌。
如果令牌未经过验证和交换,则此 API 返回 nil
。如果发生这种情况,用户可能需要通过 Rownd.requestSignIn()
正常登录。
注意:此 API 通常仅使用一次。Rownd 令牌可用后,其他令牌应被丢弃。示例
// Assume `oldToken` was retrieved from some prior authenticator.
let accessToken = await Rownd.getAccessToken(oldToken)
if (accessToken != nil) {
// Navigate to the UI that a user should typically see
} else {
Rownd.requestSignIn()
}
Rownd.transferEncryptionKey() -> Void
显示一个底部弹窗,允许用户将他们的加密密钥和账户转移到另一台设备。当用户进行身份验证时,他们将看到生成可以由另一台设备扫描的二维码或扫描另一台设备生成的二维码的选项。当用户未进行登录时,可用的唯一选项是扫描由另一台设备生成的二维码。
当未进行身份验证的设备扫描二维码时,它将自动进行身份验证,并接收和存储在设备上的加密密钥,以便两台设备能够同步其数据。
Rownd.user.get() -> Dictionary<String, AnyCodable>
返回整个用户配置文件作为字典对象
Rownd.user.get(field: String) -> T?
返回用户数据字典中特定字段的值。`"id"` 是一个特殊情况,将返回用户的 ID,尽管技术上它不在字典中。
您的应用程序代码负责知道值应该转换为哪种类型。如果转换失败或条目不存在,将返回一个 nil
值。
) -> void
Rownd.user.set(data: Dictionary用字典中包含的数据替换用户的数据。这可能会覆盖现有的值,但必须与您在 Rownd 应用程序仪表板中定义的架构相匹配。任何标记为 encrypted
的字段将在存储到 Rownd 平台之前在设备上进行加密。
提示:使用 AnyCodable.init(value)
使您的值符合所需类型。
Rownd.user.set(field: String, value: AnyCodable) -> void
将特定用户配置文件字段设置为提供的值,如果该字段已存在,则将其覆盖。如果该字段标记为 encrypted
,则将在存储到 Rownd 平台之前在设备上进行加密。
提示:使用 AnyCodable.init(value)
使您的值符合所需类型。
数据加密
如前所述,Rownd可以通过在用户设备上使用用户的唯一加密密钥对敏感用户数据进行加密,在保存到Rownd自己的平台存储之前保护这些数据。
当您在Rownd平台内配置您的应用程序时,您可以指定它支持设备端加密。当这个标志被设置后,Rownd会在用户登录后自动在用户设备上生成一个加密安全、不可恢复的加密密钥。密钥存储在设备Keychain中,并且所有加密都由设备处理。密钥永远不会传输到Rownd的服务器,Rownd SDK不提供任何API供您代码以编程方式检索加密密钥。
只有您指定的encrypted
字段在Rownd存储前会被设备端加密。一些识别字段如电子邮件和电话号码目前不支持设备端加密,因为它们经常用于索引目的。
当然,Rownd平台中的所有数据在磁盘上和传输过程中都会被加密,但这并不提供与用户本地设备上加密数据相同的隐私保证。对于特别敏感的数据,我们建议启用字段级加密。
注意:设备加密的数据您(应用程序开发者)在外部应用程序上下文中无法访问。换句话说,您的应用程序可以在用户登录时使用加密数据的明文(解密)形式,但是您无法以解密形式从Rownd服务器检索这些数据。对于您选择加密的数据,您绝对不应该通过网络传输明文值。
在某些情况下,您可能想要加密发送到您自己的服务器进行存储的数据。Rownd提供了简化方法来使用相同用户拥有的密钥加密和解密这些数据。
Rownd.user.encrypt(plaintext: String) throws -> String
使用用户的对称加密密钥加密提供的data
字符串,并将密文作为字符串返回。您可以加密任何可以表示为字符串的内容(例如,Int、Dictionary、Array等),但您需要将其先将这些内容转换为字符串格式。
如果加密失败,将抛出包含说明失败原因的EncryptionError
。
Rownd.user.decrypt(ciphertext: String) throws -> String
尝试解密提供的字符串 data
,返回明文字符串。如果数据原本是其他类型(例如,字典),则需要将数据解码回其原始类型。
如果解密失败,将抛出带有错误说明的 EncryptionError
。
注意:只有在用户认证之后才能进行加密。Rownd 支持多个认证级别(例如,访客、未验证和已验证),但在加密或解密数据之前必须先达到最低认证级别。如果您需要在特定时间点显式检查加密是否可行,请在使用
encrypt()
或decrypt()
之前调用Rownd.user.isEncryptionPossible() -> Bool
。