Okta Mobile SDK for Swift
Okta Mobile SDK取代了我们的传统移动SDK(如okta-oidc-ios),并能够
- 简化开发
- 提高您代码中Okta部分的维护性
- 更容易扩展新功能
- 支持之前难以或无法实施的使用案例。
这个新的SDK作为一个平台来构建,允许您选择您的应用程序所需的功能组件。
目录
发布状态
此库使用语义版本控制,并遵循Okta的库版本策略。
版本 | 状态 |
---|---|
1.4.2 |
最新发布版本始终可在发布页面找到。
需要帮助?
如果您在使用SDK时遇到问题,您可以
- 查看AuthFoundation、OktaOAuth2和WebAuthenticationUI的API文档
- 在Okta开发者论坛上提问
- 在此GitHub上发起问题(用于代码错误)
SDK 架构
此SDK包含几个不同的库,每个库都有详细的文档。
graph TD;
AuthFoundation-->OktaOAuth2;
OktaOAuth2-->WebAuthenticationUI;
- AuthFoundation -- 用于管理凭证的公共类,也是其他库的基础。
- OktaDirectAuth -- 用于高级无浏览器认证(EA)的直接认证功能。
- OktaOAuth2 -- 用于高级用例的OAuth2认证功能。
- WebAuthenticationUI -- 使用基于Web的OIDC流程进行用户认证。
此SDK使您能够构建或支持各种各样的认证流程和方案。
开发路线图
此SDK正在积极开发中,计划进行未来扩展。目前,我们正在积极征求开发者社区的反馈,以评估以下内容:
- 整体SDK及其组件
- API和整体开发者体验
- 可能遗漏或与您的应用程序需求不一致的使用案例或功能
- 对未来开发的建议
- 对这一新方向的任何其他评论或反馈。
关键特性
此库引入了几个关键特性和功能,以下列举了其中一些显著的改进。
功能 |
---|
简单基于OIDC的Web登录 |
凭证管理(安全存储、检索等) |
多令牌处理(为多个用户、作用域等存储和使用令牌) |
授权码流 |
原生SSO/令牌交换流 |
设备授权授予流 |
资源所有者流 |
简化JWT解析和处理 |
使用凭证令牌简化URLSession请求的授权 |
许多扩展点,适用于定制、监控和跟踪 |
开始使用
要开始使用,您需要以下内容
- 一个 Okta 账户,称为 组织(如果您需要,请免费注册一个开发者组织)。
- 一个配置为 "原生应用" 的 Okta 应用程序。使用 Okta 管理员控制台,通过向导器并使用默认属性创建应用程序。
- Xcode 13.x,针对以下支持的平台和目标版本(请参阅下方的支持策略)。
有关如何使用此 SDK 的示例,请参阅本存储库中包含的 示例应用程序。
安装
Swift 包管理器
将以下内容添加到您的 Package.swift
文件中定义的 dependencies
属性。您可以使用 majorVersion
和 minor
参数选择版本。例如
dependencies: [
.Package(url: "https://github.com/okta/okta-mobile-swift.git", majorVersion: <majorVersion>, minor: <minor>)
]
CocoaPods
只需在您的 Podfile
中添加以下行
pod 'OktaWebAuthenticationUI'
然后将其安装到您的项目中
pod install --repo-update
如果您只想使用 OktaOAuth2 库,请使用以下命令
pod 'OktaOAuth2'
如果您正在参与 Okta Direct Authentication API 的早期访问预览,请使用以下命令
pod 'OktaDirectAuth'
使用说明
使用OIDC进行网络身份验证
在您的应用中集成身份验证最简单的方式是通过网络浏览器,利用授权代码流许可进行OIDC。
配置您的OIDC设置
在您对用户进行身份验证之前,您需要使用在Okta开发者控制台中定义的设置创建您的客户端配置。最简单的方法是使用一个Okta.plist
配置文件来指定这些设置。确保创建了以下字段:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>issuer</key>
<string>https://{yourOktaDomain}.com</string>
<key>clientId</key>
<string>{clientId}</string>
<key>redirectUri</key>
<string>{redirectUri}</string>
<key>logoutRedirectUri</key>
<string>{logoutRedirectUri}</string>
<key>scopes</key>
<string>openid profile offline_access</string>
</dict>
</plist>
或者,您也可以在下一节中将要讨论的WebAuthentication
构造函数中提供这些值。
创建一个网络身份验证会话
一旦您在Okta.plist
文件中配置完应用程序设置,共享配置将通过WebAuthentication.shared
单例属性自动可用。配置完成后,您可以使用便捷的WebAuthentication.signIn(from:)
方法提示用户登录。
import WebAuthenticationUI
func signIn() async {
let token = try await WebAuthentication.signIn(from: view.window)
let credential = try Credential.store(token)
}
signIn(from:)
函数返回一个令牌,通过使用Credential
类,您可以在您的应用程序中保存此令牌并使用它。
使用设备代码流授权进行身份验证
对于无头设备或难以使用键盘的设备(例如AppleTV),您的应用程序可以使用OktaOAuth2直接与DeviceAuthorizationFlow
类配合使用。这将使您能够向用户提供一个易于记忆的代码,他们可以在另一台设备上使用该代码来授权您的应用程序。
使用方法很简单
- 创建一个
DeviceAuthorizationFlow
的实例
let flow = DeviceAuthorizationFlow(
issuer: URL(string: "https://example.okta.com")!,
clientId: "abc123client",
scopes: "openid offline_access email profile")
- 启动一个身份验证会话以接收代码和授权URL,然后向用户展示。
let context = try await flow.start()
let code = context.userCode
let uri = context.verificationUri
- 等待用户从另一台设备授权应用程序。
let token = try await flow.resume(with: context)
使用原生SSO流程进行身份验证
当使用device_sso
作用域时,您的应用程序可以接收一个“设备密钥”,这可以与您的用户ID令牌结合使用来交换新的凭据。要在应用程序中使用此功能,您将使用TokenExchangeFlow
来交换这些令牌集。
let flow = TokenExchangeFlow(
issuer: URL(string: "https://example.okta.com")!,
clientId: "abc123client",
scopes: "openid offline_access email profile",
audience: .default)
let token = try await flow.start(with: [
.actor(type: .deviceSecret, value: "DeviceToken"),
.subject(type: .idToken, value: "IDToken")
])
使用用户名和密码进行身份验证
对于简单的身份验证用例,您可以使用ResourceOwnerFlow
类使用纯文本用户名和密码进行身份验证。
注意:ResourceOwnerFlow类已被标记为已弃用,因为其功能正被更全面的OktaDirectAuth库取代。
let flow = ResourceOwnerFlow(issuer: URL(string: "https://example.okta.com")!,
clientId: "abc123client",
scopes: "openid offline_access email profile")
let token = try await flow.start(username: "jane.doe", password: "secretPassword")
使用直接认证进行身份验证
对于简单的身份验证用例,您可以使用ResourceOwnerFlow
类使用纯文本用户名和密码进行身份验证。
注意: Okta Direct Authentication API 目前已标记为早期访问(EA),目前尚未普遍可用。
let flow = DirectAuthenticationFlow(issuer: URL(string: "https://example.okta.com")!,
clientId: "abc123client",
scopes: "openid offline_access email profile")
switch try await flow.start("[email protected]", with: .password("secretPassword")) {
case .success(let token):
// Store the token
case .mfaRequired(_):
// Continue authentication
}
有关更多信息,请参阅OktaDirectAuth API 文档。
存储和使用令牌
一旦用户完成身份验证并创建了Token
对象,应用程序可以存储和使用这些凭证。最直接的方法是使用Credential.store(_:tags:security:)
函数。
let credential = try Credential.store(token)
为了方便起见,SDK在Credential
类上提供了一个default
静态属性。这提供了一种简单的方式来识别用户是否已进行身份验证,并快速访问用户的凭证。存储新凭证时,如果没有已经存储的凭证,它会自动作为默认凭证分配。
if let credential = Credential.default {
// The user is signed in. Start by refreshing it.
try await credential.refreshIfNeeded()
}
通过唯一标识符查找凭证
当存储令牌时,它会被分配一个唯一的ID,这可以用来区分不同的令牌,并在之后检索令牌。
let tokenId = token.id
// Later, retrieve the token
if let credential = try Credential.with(id: tokenId) {
// Use the credential
}
使用自定义标签分配和查找证书
对于更复杂的应用,您可能需要管理多个证书(例如多用户登录、不同应用程序扩展的不同令牌、应用程序不同部分的细粒度作用域等)。为了更容易区分证书,您可以给它们分配标签,这些标签以后可以用来识别它们。
try Credential.store(token, tags: ["customTag": "someValue"])
可以通过这些标签检索证书。
if let credential = try Credential.find(where: { $0.tags["customTag"] == "someValue" }).first {
// Use the credential
}
证书的标签可通过其 tags
属性访问,并且可以在事后修改。
if !credential.tags.contains("someCustomTag") {
credential.tags["someCustomTag"] = "someValue"
}
// Or use the following method to intercept exceptions
try credential.setTags(["customTag": "someValue"])
使用ID令牌声明查找证书
此SDK简化了访问JWT令牌及其声明的操作。实际上,令牌的 idToken
属性自动作为 JWT
实例公开。使用它,您可以枚举并根据其令牌关联的声明检索证书。
if let credential = try Credential.find(where: { $0.email == "[email protected]" }).first {
// Use the credential
}
速率限制处理
如果在一定时间内进行了太多请求,Okta API将返回429响应。请参阅Okta的速率限制以获取完全列出哪些端点是受速率限制的完整列表。此SDK在429错误上自动重试请求。默认配置如下
配置选项 | 描述 |
---|---|
maximumCount | 重试次数。默认值是 3 。 |
自定义速率限制
要自定义速率限制的处理方式,请遵守 APIClientDelegate
协议,实现 shouldRetry(request:rateLimit:)
方法,并将您的类作为适当的客户端的代理。当通过该客户端发送的任何请求收到 HTTP 429 错误响应时,它将允许您自定义速率限制行为。
import AuthFoundation
func login() {
// Configure your authentication flow, before running the following command
flow.client.add(delegate: self)
}
extension OAuth2Client {
public func api(client: APIClient, shouldRetry request: URLRequest) -> APIRetry {
return .doNotRetry
}
}
有关更多信息,请参阅 APIRetry
枚举的 API 文档。
从遗留 SDK 迁移
此 SDK 集合旨在替代以下 SDK
如果您的应用程序当前使用 OktaOidc,已设置迁移现有用户到新 SDK 的可迁移性方案。有关更多信息,请参阅 SDKVersion.Migration
类的详细信息。
运行示例
有几个可用应用程序来演示此 SDK 的不同工作流。有关更多信息,请参阅示例应用程序。
支持策略
本政策定义了对Xcode、Swift和平台(iOS、macOS、tvOS和watchOS)版本的支持范围。
Xcode
仅支持当前可用来提交应用程序到App Store的Xcode版本。一旦Xcode版本不再受支持,停止对它的支持将不会被视为破坏性变更,并将在次要版本中完成。
Swift
最低支持的Swift 5次要版本是与最老旧支持的Xcode版本一起发布的版本。一旦Swift 5次要版本不再受支持,停止对它的支持将不会被视为破坏性变更,并将在次要版本中完成。
平台
除非有平台限制限制了我们对旧版本的兼容性,否则仅支持最新的4个大版本平台。
平台 | 受支持 | 尽力 |
---|---|---|
iOS | 12.0 | 9.0 |
tvOS | 12.0 | 10.0 |
watchOS | 8.0 | 7.0 |
macCatalyst | 13.0 | 13.0 |
macOS | 12.0 | 10.11 |
一旦平台版本不再受支持,停止对它的支持将不会被视为破坏性变更,并将在次要版本中完成。例如,随着iOS 16的发布,iOS 12将不再受支持,可能在未来某个次要版本中停止支持。
对于macOS,每年的命名版本被视为此政策的大版本平台版本,无论实际版本号如何。
注意:旧操作系统版本采取尽力支持的策略。除非API限制阻碍SDK在旧操作系统版本上有效工作,否则最低要求将不会更改。
此外,Linux的兼容性被视为尽力支持,并非官方支持。
旧版 SDK 支持
在 okta-mobile-swift SDK 成为一般可用版本后,我们打算在此新库中继续所有新功能开发。我们计划在未来一段可预见的时间内,为 okta-oidc-ios(以及 okta-mobile-swift 取代的我们其他旧版 SDK)提供关键错误和安全修复。
开发
保护测试配置
此存储库在 Samples/Shared
中包含两个文件,用于向自动化测试以及示例应用程序公开测试凭据。
为了避免意外更改这些文件,建议在克隆此存储库后使用以下命令:
git config core.hooksPath ./.githooks
这将在提交更改之前运行检查,以确保这些文件未被更改。
运行测试
可以在 macOS 上使用以下命令从命令行运行测试:
swift test
或者,如果您想在 Linux 中运行测试,您可以使用 macOS 环境中的 Docker 来运行 Linux 测试。
docker run --rm --privileged --interactive --tty \
--volume "$(pwd):/src" --workdir "/src" swift:5.6.1 \
swift test
已知问题
贡献
我们很高兴接受贡献和PR。请参阅贡献指南了解如何构建贡献。