大多数浏览器和
Developer App 均支持流媒体播放。
-
通行密钥简介
这是一次安全性的升级:了解如何添加通行密钥支持以便为用户提供快速而简单的登录体验,同时大幅提高帐户安全性。通行密钥是简单的强凭证,旨在消除网络钓鱼攻击。我们将分享通行密钥的安全设计,说明它的使用方法,讨论如何将通行密钥集成到您的登录流程,并且探索需要采用此功能的平台和网页 API。
资源
相关视频
WWDC23
WWDC22
WWDC20
-
下载
♪ 柔和乐器演奏的嘻哈音乐 ♪ ♪ 嗨 我是 Garrett 身份验证体验团队的工程师 在这个视频中 我很高兴能和大家聊聊通行密钥 通行密钥是新一代的验证技术 但首先 我需要谈谈 当今的身份验证技术:密码 您可能已经习惯用密码登录 几乎所有的 App 和网站 密码真的很难安全地使用 我们都知道每个帐户都应该创建 强大 独特的密码 但实际上没有多少人会这么做 在设计 App 和网站时 在保持帐户安全与设计良好体验之间 需要不断地权衡 即使您的 App 和网站一切正常 网络钓鱼和密码重用等问题 仍然可能导致帐户泄露 在 macOS Monterey 和 iOS 15 中 我们宣布了这个解决方案的 开发者预览版 也就是通行密钥 并获得了很多很棒的反馈 在 macOS Ventura 和 iOS 16 中 我们很高兴通行密钥将向所有人提供 现在是采用通行密钥的时候了 使用通行密钥 不仅能提供比密码更好的用户体验 而且整个类别的安全问题 如弱密码和重用密码凭据 密码凭据泄露和网络钓鱼 都不复存在了 而且通行密钥非常易于使用 让我来给您展示 从我们最爱的 演示 App Shiny 开始 这个 App 每天会 为我展示一张可爱的照片 并具有典型的基于密码的登录流程 我可以点击用户名字段 看到我的帐户的自动填充建议 选择填充建议 登录 然后 填写密码
然后 我稍等片刻 直到短信传来一次性验证码
收到了 最后 登录上了 花了几个步骤 但在自动填充 和密码管理器的帮助下 我成功登录了
现在登录上了 我将向帐户添加通行密钥 帐户管理 添加通行密钥 这里是用于创建通行密钥的系统表 继续 完毕! 只需几下按键 我的设备就为帐户 生成了一个独特的 加密性强的通行密钥对 并存储在 iCloud 钥匙串中 从而让通行密钥在我的所有运行 macOS Ventura 和 iOS 16 的 设备上同步和工作
现在有了通行密钥 让我来展示一下通行密钥多么容易使用 我先退出登录 又回到了之前用过的登录表单 像之前一样 点击用户名字段 现在我已经为帐户保存了一个通行密钥 通行密钥会显示在 QuickType 栏中 只要点击它 就能登录了 一步就能完成 保存通行密钥时 我不需要设置新密码 也不需要满足密码复杂度要求 每个通行密钥由系统生成 并保证通行密钥强度大 且只用于一个帐户 当我用通行密钥登录时 它可以显示 在我习惯的现有登录流程中 而且只需轻轻一点就可以使用 而且系统会让我仅在 正确的 App 或网站上使用通行密钥 内置了强大的防钓鱼功能 当然 通行密钥也可以在网络页面上使用 我在 Safari 浏览器上 浏览 Shiny 网站 就像在我的手机上 我点击用户名字段 多亏了 iCloud 钥匙串 通行密钥已经可以使用了 只需要触控 ID 就能登录 就这么容易 Apple 的通行密钥实现 是建立在开放标准之上 我们一直在与 FIDO 联盟内的 其他平台供应商合作 以确保通行密钥实现兼容跨平台 并能在尽可能多的设备上工作 把我的帐户升级为使用通行密钥后 我仍然可以在我朋友的电脑上登录 当然 我朋友的电脑 没有本地储存通行密钥 但我仍然可以在这里输入我的用户名 我点击登录时 收到一张允许我使用手机的表单 然后我收到一个二维码 我来扫描一下
我的手机识别出此二维码 是用通行密钥登录的 当我选择这个选项时 我的手机和浏览器 就安全地连接在一起了 接下来点击继续 就能登录上了 这种跨平台的登录体验 是一流的系统功能 是通行密钥背后标准的一部分 表面上 它看起来非常简单 但这不仅仅是一个二维码 在后台 设备正在执行本地通行密钥协议 证明接近性 建立一个端到端加密通信通道 这些都是为了简化登录方式 但又能保持通行密钥强大的对抗钓鱼能力 它可以让我在任何设备上 安全地登录我的帐户 密码替换的另一个重要功能 是可以在两人或多人之间共享帐户 要与其他人共享通行密钥 我可以使用 AirDrop
我和我的伙伴也有一个 共享的 Shiny 帐户 我已经将帐户升级为使用通行密钥 有了通行密钥 我就无需输入密码凭证 但我仍然可以与我信任的人分享通行密钥 在我的手机上 我打开帐户详细信息
这是我所有使用 密码和通行密钥的帐户 我可以点击我们的共享帐户 调出更多细节 在这里 我可以看到 关于我保存的通行密钥的信息 或向此帐户添加备注 我也可以分享我的通行密钥 这是我伙伴的手机 我来选择它
现在我的伙伴也有了通行密钥
可以看出来 到处都能用通行密钥 多么容易 我刚刚介绍了使用通行密钥的体验 接下来说说什么是通行密钥 以及使用通行密钥时的一些界面指南 然后 我将向您展示 如何利用自动填充 将通行密钥集成到您的 App 和网站中现有的登录流程中 然后是一些额外的选项 可以进一步简化您的登录过程 接下来 我将详细介绍 密匙的工作原理 最后 讨论密匙和多因素身份验证 首先 通行密钥的设计 说到通行密钥 首先也是最重要的是 通行密钥是密码的替代品 登录速度更快 使用起来更容易 也更安全 以下是有关如何 在您的 App 和网站中 使用通行密钥的指导方针 “Passkey” (通行密钥) 是一个通用的 用户可见的术语 本视频重点介绍 Apple 的实施 但正如我刚才向开发者展示的 其他主要平台 已经开始建立自己对通行密钥的支持 “Passkey” (通行密钥) 也是个普通名词 就像“密码”一样 在英语中 这个词是小写的 并能像“密码”一样变成复数 我的帐户有通行密钥 可以去“设置” 查看我所有的帐户的通行密钥 在 Apple 平台上 您还可以使用 SF Symbol person.key.badge 和 .fill 变体 来提供与系统一致的图标 在您的 App 和网站中 提供通行密钥时 您不需要设计全新的界面 用户名字段是目前大多数 App 和网站登录的中心点 几乎每个人都知道如何使用 许多 App 和网站已经利用通行密钥 来定制每个帐户的登录体验 现在用户名字段还有另一个大特点 虽然通行密钥为登录工作带来了新的范式 但摆脱密码的过渡 也需要平稳和简单 您现在可以使用自动填充 作为一级特性来提供通行密钥 让您可以将通行密钥 直接放入现有的登录流中 在熟悉且人们知道如何使用的界面中 使用自动填充提供通行密钥 是使用通行密钥的主要方式 不过 对于更高级的用户 Apple 平台也有 很多额外的 UI 选项 可以使用通行密钥登录 接下来看一下如何开始使用通行密钥 并使用自动填充显示通行密钥 通行密钥是基于 WebAuthentication 构建的 其又名 WebAuthn 标准 并使用公钥加密 每个帐户生成唯一的加密通行密钥对 而不是使用可键入的字或字符串 您需要在服务器后端采用 WebAuthn 来执行通行密钥登录 任何标准的 WebAuthn 服务器实现 应该使用通行密钥 在 Apple 平台上的 App 中 通行密钥是 AuthenticationServices 框架中的 ASAuthorization API 系列的一部分 这是我们的 API 用于处理 各种不同的凭证 包括密码 安全通行密钥和使用 Apple 登录 我们还添加了一些 您可以使用的新方法 像自动填充支持 使这个 API 更加灵活 并让您无缝地将它 融入到现有的登录流中 要开始在 您的 App 中使用通行密钥 首先 您需要 使用 webcredentials 服务 设置相关的域 您可以在 “Introducing Password AutoFill for Apps”(App 密码自动填充介绍) 和“通用链接中的新功能” (What's new in Universal Links) 视频中 了解更多细节 在您的 App 界面中 请确保您的用户名字段 使用的是用户名 textContentTtype 这让系统知道在哪里提供通行密钥建议 配置完成后 下面是启动自动填充 辅助通行密钥请求所需的代码 分解时只需几个简单的步骤 与任何 WebAuthn 请求 一样 您首先需要 从服务器获取一个质询 然后创建提供者和请求 ASAuthorizationPlatformPublicKeyCredentialProvider 是 ASAuthorizationProvider 用于处理通行密钥请求 在 WebAuthn 术语中 登录时使用断言 所以在这里 我创建一个断言 请求来使用现有的通行密钥进行登录 ASAuthorizationController 是实际处理请求的内容 使用通行密钥请求创建实例 并配置它的委托 和 presentationContextProvider 最后 调用 performAutoFillAssistedRequests 开始请求 当这个请求在 App 中运行时 每当点击一个用户名字段时 系统将在 QuickType 栏中 提供可用的通行密钥 确保在视图生命周期的早期 在点击用户名字段之前启动这个请求 这样当键盘出现时 通行密钥就准备好了 当 QuickType 栏中的 一个项目被选中时 面容 ID 被调用 然后您会收到 一个 ASAuthorizationController 委托回调 来完成登录 文本框中实际上不会填充内容 当对任何凭据类型的授权成功时 您将获得 didCompleteWithAuthorization 回调 您首先应该 检查您获得的凭证的类型 在使用通行密钥登录的情况下 它将是 ASAuthorizationPlatformPublicKeyCredentialAssertion 断言对象将包含在后端验证登录 所需的字段 您应该读这些值 用服务器验证它们 然后完成登录 自动填充辅助通行密钥请求功能强大 通过这个小小的代码更改 您的 App 的登录流程 现在有了很大的灵活性 当然 主要的情况是从 QuickType 栏中选择通行密钥建议 以便使用通行密钥快速登录 这是应该是最经常发生的情况 不过 还有其他选择 我刚才向您展示的代码还允许 从附近的设备 进行通行密钥登录 无需进行额外的更改 您可以点击钥匙图标以调出视图 列出所有可用的通行密钥和密码 并点击使用附近设备登录的选项 然后可以执行跨设备通行密钥登录 在这两种情况下 如果使用通行密钥 您会收到相同的 ASAuthorizationController 委托回调 要支持这个功能 您不需要做什么特别的操作 如果用户还没有通行密钥 他们可以照旧使用您的登录表单 他们将在 QuickType 栏中 获得密码建议 或直接在输入栏中输入密码 如果选择了密码项 则仍然会将凭据填写到文本字段中 您可以取消正在运行的请求 我们设计这个 API 是为了让您 把它直接放到您现有的登录流中 这对您的用户来说非常容易 如果用户已经升级到使用通行密钥 还是决定输入他们的用户名 而不是使用自动填充建议 您应该取消自动填充请求 并使用 ASAuthorizationController 来呈现模式通行密钥登录表 这里 依旧只需要轻点一下 您会收到相同的 ASAuthorizationController 委托回调 这是之前的代码 要从自动填充请求切换到模态请求 只需将 performAutoFillAssistedRequests 方法调用 与 performRequests() 调用交换 这将显示一个 包含所有可用通行密钥的模式表 以及使用附近设备的通行密钥的选项 这些是您需要在 App 中 支持通行密钥的唯一代码更改 网页平台还支持自动填充辅助 和模态通行密钥请求 在网页上 通行密钥是通过标准的 WebAuthn API 使用的 这个 API 也用于安全通行密钥 就像在 App 中一样 采用自动填充辅助请求功能 只需触控 ID 即可快速登录 获取所有可用的通行密钥和密码 或者使用附近设备的通行密钥 这些都只需要很少的代码 首先 确保在您的网页上 以用户名和 webauthn 自动完成细节标记 注释您的用户名字段 以便在正确的位置 显示密码和通行密钥建议 完成后 这是一个在 JavaScript 中 典型的 WebAuthn 登录 在 WebAuthn 中 使用条件中介调用 自动填充样式的请求 您应该首先使用 标准 JavaScript 特性检测 来检查它是否可用 如果可用 您可以继续提出您的请求 就像使用原生 API 一样 首先使用 从服务器获取的质询发起请求 要使它成为自动填充辅助请求 将 mediation: "conditional" 参数添加到选项中 然后 使用 navigator.credentials.get 启动请求 .get 调用返回一个承诺 如果解析成功 您将收到一个断言对象 您可以将对象发送回服务器进行验证 然后完成登录 就像在 App 中 如果有人手动输入一个 带有通行密钥的帐户的用户名 您应该使用 API 来呈现一个模态登录表 要切换到模态请求 您需要做的就是删除 mediation: "conditional" 参数 使用 WebAuthn 时要注意的一件事 是 Apple 平台如何处理 用户验证 简称 UV UV 是 WebAuthn 响应中的 布尔字段 表示验证者是否 试图验证当前用户 是设备的所有者 在 Apple 设备上 值 1 表示生物识别技术 或使用的密码 当生物识别技术可用时 Apple 平台 将始终需要 UV 用于通行密钥 所以您不必担心这一点 当提出 WebAuthn 请求时 有一个选项可以指定用户验证要求 默认值为 userVerification: "preferred" 请始终使用默认值 以避免在没有生物识别的设备上 造成不良体验 以下是在网页上 使用通行密钥的一些附加说明 当您提出自动填充辅助请求时 您应该在页面生命周期的早期进行 就像在 App 中一样 对于模态 WebAuthn 请求 您应该从用户手势事件 比如点击按钮 来触发它们 模态请求可以在用户手势事件之外的 每次页面加载触发一次 但如果您这样做 WebKit 可能会 限制页面的后续调用 自动填充请求不是模态的 所以它们不需要用户手势 并且有更长的超时时间 最后 通行密钥正在 取代 Safari 浏览器的 传统平台验证器 现有凭证仍然有效 并且仍然绑定到创建它们的设备上 但新的平台凭据将被创建为通行密钥 在注册期间可以将它们 与遗留凭证区分开来 因为通行密钥不会提供认证声明 以上是通行密钥和自动填充 接下来 我将介绍一些其他平台功能 这可以进一步简化登录体验 除了自动填充辅助的登录 ASAuthorization API 还提供了许多更有用的功能 我将介绍 这个 API 的三个附加功能 以及何时需要使用它们 首先来说说通行密钥允许列表 当用户名输入后 显示模态通行密钥表时 设备上可能保存了 多个帐户的通行密钥 默认情况下 所有可用的通行密钥 都将显示在表单中 您可以使用一个通行密钥允许列表 来限制哪些通行密钥显示在工作表中 以便只提供匹配的帐户 要向模态请求添加允许列表 首先需要用户名 您可以使用该用户名获取 匹配凭据 ID 的列表 并将它转换为允许列表 凭证 ID 是通行密钥的唯一标识符 Webauthn 服务器应该 有一种方法来查找 给定用户名的凭证 ID 接下来 像以前一样继续您的请求 现在 设备上有三个 使用通行密钥的 Shiny 帐户 表单只提供了 我想要使用的一个帐户 发出模态请求时 当您有关于用户 试图用哪个帐户登录的附加场景时 您应该使用允许列表 例如用户是否 已经输入了他们的用户名 接下来 我将介绍 在当前设备上没有保存通行密钥的情况下 发出模态通行密钥请求会发生什么 这同样适用于 当您使用允许列表 而所保存的通行密钥 与该列表不匹配的情况 默认情况下 当您发出模态通行密钥请求时 如果没有匹配的可用通行密钥 将显示模态表 并会立即显示二维码 用于从附近的设备使用通行密钥登录 这在登录时提供了最大的灵活性 并且当您知道正在使用通行密钥时 这是最好的选择 但 API 中有一个新选项 可以优先选择 可以选择立即可用的凭证 并在没有凭证时 使用委托回调静默回退 这可以用于在可能的情况下 甚至在显示传统的登录表单之前 如果当前设备上没有匹配的通行密钥 使用默认选项的模态请求 将退回到显示二维码 如果当前设备上没有匹配的通行密钥 如果您使用 preferImmediatelyAvailableCredentials 选项 您将获得一个带有错误的 委托回调函数 而不是二维码 如果您收到 ASAuthorizationError 代码为 canceled 这意味着 要么用户看到了这个表并手动取消了 要么您传递了 preferImmediatelyAvailableCredentials 而没有立即可用的凭证 要怎么做 取决于 您调用它的场景 例如 如果您使用此选项 作为在显示正常登录表单之前 测试本地凭据的一种方法 那么这就是触发显示表单的地方 如果设备上至少有一个匹配的凭据 则将显示完整的模态表 无论使用什么选项 确保您也在使用 自动填充辅助请求或模态请求 在您的 App 中有默认的回退 因此 如果当前设备上没有通行密钥 仍然可以使用 通过手边的设备 来登录的选项 我要介绍 ASAuthorization API 的 最后一个功能是发出组合凭证请求 在本例中 App 提交了通行密钥、密码 以及通过 Apple 登录的请求 我的设备恰好保存了 三个不同帐户的三个不同凭证 都在表单里 但更有可能的情况是 用户只有一个帐户 在这种情况下 同样的组合凭证请求 将只提供工作表中的一个帐户 向现有的 ASAuthorization 请求 添加额外的凭证类型非常容易 您只需要为额外的请求类型 创建提供程序和请求 然后将这些新请求传递给控制器 现在 模态表将提供任何凭据 从这些凭证类型中获得的任何凭证 无论使用哪种凭据类型 您都将获得相同的委托回调 您应该检查接收到的凭据类型 并根据该凭据类型 完成登录 这就涵盖了 ASAuthorization API 系列的 一些更高级的特性 现在 我将深入探讨一些技术细节 通行密钥工作原理 以及通行密钥为何如此安全 现在 当您使用密码登录时 通常情况下 在您输入密码之后 会被 hash 和 salt 以及由此产生的混淆值 被发送到服务器得以储存 稍后 如果您可以生成 相同的哈希加盐值 则允许您进入帐户 这意味着服务器负责 存储您的密码来源 这对攻击者非常有价值 如果攻击者能获得 他们就有可能知道 您的密码是什么并访问您的帐户 但是 通行密钥的工作原理非常不同 通行密钥不是单独的可输入字符串 而是一对相关的通行密钥 这些通行密钥由您的设备生成 安全而唯一 为每个帐户服务 一个是公开的 存储在服务器上 另一个是私人的 即使在登录时 也会保留在您的设备上 公钥不是私密的 就像您的用户名一样公开 私钥是实际登录所需要的 服务器永远不会知道您的私钥是什么 您的设备会保护它的安全 当您登录时 服务器会向您的设备 发送一个一次性的质询 WebAuthn 会允许 许多不同的质询-响应算法 但 Apple 平台上的通行密钥 使用标准 ES256 只有您的私钥才能 为您的帐户质询产生有效的解决方案 您的设备在本地生成这个解决方案 叫做签名 并且只将解决方案发送回服务器 您的私钥是保密的 并且只保存在您的设备上 然后 服务器 使用您的公钥验证解决方案 如果您的设备提供的解决方案有效 您就登录了! 公钥可用于检查解决方案是否有效 但不能产生解决方案本身 这意味着服务器可以确定 您拥有正确的私钥 而不需要知道私钥是什么 而且由于服务器不知道任何私钥 因此对攻击者来说 这是一个价值较低的目标 因为没有用户凭证可以泄露 这些加密和通行密钥保护都是完全透明的 并由设备执行 您的客户不需要知道或思考通行密钥 从他们的角度来看 通行密钥超级简单 可以随时随地使用 通行密钥也可用于跨设备登录 以安全、防网络钓鱼的方式登录 工作原理如下 这里有两个设备 客户端 也就是我登录的设备 或网页浏览器 以及身份验证器 也就是拥有我的通行密钥的设备 首先 客户端显示一个二维码 身份验证器扫描二维码 此二维码包含一个 URL 这个 URL 编码了 一对一次性使用的加密通行密钥 然后 身份认证器生成一个包含 网络中继服务器路由信息的蓝牙广告 这种本地交换 允许选择服务器和共享路由信息 但也有两个额外的功能 它执行一个服务器看不到的 带外通行密钥协议 因此网络上的 所有内容都是端到端加密的 服务器无法读取任何内容 它还有力地证明了 这两种设备在物理上是接近的 这意味着通过电子邮件发送的二维码 或在虚假网站上生成的二维码 将无法工作 因为远程攻击者将无法接收到 蓝牙广告并完成本地交换 以上就是本地部分 一旦本地交换和通行密钥协议发生 两台设备连接到由手机选择的 中继服务器 然后 执行一个标准的 FIDO CTAP 操作 这是使用前面的通行密钥加密的 所以中继服务器 看不到任何进行中的过程
整个过程是由设备 和网页浏览器执行的 网站在任何时候都不涉及 跨设备通信的过程 跨设备跨平台登录是系统功能 它可以在任何 能够使用通行密钥的平台工作 以上我们更专业地了解了 通行密钥的工作原理 通行密钥如何提供如此强大的安全保证 甚至为何跨设备使用都如此安全 接下来是多因素身份验证 目前 考虑身份验证的一种常见方法 是使用因素 不同的因素 对不同类型的攻击有强弱之分 结合因素 可以提供更好的集体覆盖率 但是有了通行密钥 您就不需要这么考虑了 以下是目前最常用的一些 登录方法 您光凭记忆设置的密码 是很不可靠的 密码管理器 擅长生成独特的、高熵的字符串 可能具有本地保护措施 防止设备被盗 并提供一些关于网络钓鱼的提示 添加短信或实时验证码 在某些情况下 可以帮助防止盗窃或网络钓鱼 但并不能真正解决这两个问题 而有了通行密钥 每个通行密钥都是唯一的 由设备生成的通行密钥对 在 Apple 设备上 通行密钥是在本地设备保护的 强大基础上设立的 通行密钥还完全消除了 网络钓鱼的人为因素 并且通行密钥不会 被 App 或网站服务器泄露 因为服务器没有私钥 在基于密码的登录流程中 添加因素是有意义的 因为与单独使用密码相比 结合在一起可以抵御更多类型的攻击 但单凭通行密钥就能抵御的东西太多了 不需要额外的因素 我很期待一个 不再需要密码的未来 以下是您可以 开始实现这一目标的方法 首先 如果还没有采用 WebAuthn 您需要在服务器上采用它 通行密钥应该可以用于 任何标准的 WebAuthn 服务器的实施 服务器准备就绪后 在您的 App 和网站中采用我们的新 API 自动填充辅助通行密钥请求可以 直接放到您现有的登录流程中 此外 如果您需要 我们还有一系列 更高级的 UI 选项 最后 帮助您的用户 从密码转移到通行密钥 通行密钥是行业标准的解决方案 它能解决安全登录 App 和 网站的便利性和安全性等问题 通过引导您的用户 使用通行密钥来替代密码 您可以给用户带来 非常快速和方便的登录体验 同时为大家提高安全标准 谢谢 ♪
-
-
11:30 - Associated Domains setup
{ "webcredentials": { "apps": [ "A1B2C3D4E5.com.example.Shiny" ] } }
-
11:47 - Annotating user name text field
override func viewDidLoad() { super.viewDidLoad() //Additional setup… userNameField.textContentType = .username }
-
11:59 - AutoFill-assisted passkey sign in
// AutoFill-assisted passkey request func signIn() { let challenge: Data = … // Fetched from server let provider = ASAuthorizationPlatformPublicKeyCredentialProvider( relyingPartyIdentifier: "example.com") let request = provider.createCredentialAssertionRequest( challenge: challenge) let controller = ASAuthorizationController( authorizationRequests: [request]) controller.delegate = self controller.presentationContextProvider = self // Start the request controller.performAutoFillAssistedRequests() }
-
13:29 - ASAuthorizationControllerDelegate callback
// Completing a passkey sign in func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) { guard let passkeyAssertion = authorization.credential as? ASAuthorizationPlatformPublicKeyCredentialAssertion else { … } let signature = passkeyAssertion.signature let clientDataJSON = passkeyAssertion.rawClientDataJSON // Pass these values to your server, and complete the sign in … }
-
16:05 - Modal passkey sign in
// Modal passkey request func signIn() { let challenge: Data = … // Fetched from server let provider = ASAuthorizationPlatformPublicKeyCredentialProvider( relyingPartyIdentifier: "example.com") let request = provider.createCredentialAssertionRequest( challenge: challenge) let controller = ASAuthorizationController( authorizationRequests: [request]) controller.delegate = self controller.presentationContextProvider = self // Start the request controller.performRequests() }
-
16:53 - HTML user name field annotation
<input type="text" id="username-field" autocomplete="username webauthn" >
-
17:09 - AutoFill-assisted passkey sign in on the web
// AutoFill-assisted WebAuthn request (JavaScript) function signIn() { if (!PublicKeyCredential.isConditionalMediationAvailable || !PublicKeyCredential.isConditionalMediationAvailable()) { // Browser doesn't support AutoFill-assisted requests. return; } const options = { "publicKey": { challenge: … // Fetched from server }, mediation: "conditional" }; navigator.credentials.get(options) .then(assertion => { // Pass the assertion to your server. }); }
-
18:14 - Modal passkey sign in on the web
// Modal WebAuthn request (JavaScript) function signIn() { var options = { "publicKey": { challenge: … // Fetched from server } }; navigator.credentials.get(options) .then(function (assertion) { // Pass the assertion to your server. }); }
-
20:55 - Modal passkey request with allow list
// Modal request with allow list func signIn(userName: String) { let challenge: Data = … // Fetched from server let provider = ASAuthorizationPlatformPublicKeyCredentialProvider( relyingPartyIdentifier:"example.com") let request = provider.createCredentialAssertionRequest( challenge: challenge) let credentialIDs: [Data] = … // Fetched from server for provided userName request.allowedCredentials = credentialIDs.map( ASAuthorizationPlatformPublicKeyCredentialDescriptor.init(credentialID:)) let controller = ASAuthorizationController(authorizationRequests: [request]) controller.delegate = self controller.presentationContextProvider = self // Start the request controller.performRequests() }
-
22:56 - Modal passkey request with silent fallback
// Modal passkey request, silent fallback func signIn() { let challenge: Data = … // Fetched from server let provider = ASAuthorizationPlatformPublicKeyCredentialProvider( relyingPartyIdentifier:"example.com") let request = provider.createCredentialAssertionRequest( challenge: challenge) let controller = ASAuthorizationController(authorizationRequests: [request]) controller.delegate = self controller.presentationContextProvider = self // Start the request controller.performRequests(options: .preferImmediatelyAvailableCredentials) }
-
23:06 - Silent fallback delegate callback
// Handling a silent fallback func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) { guard let error = error as? ASAuthorizationError else { … } if error.code == .canceled { // Either the user canceled the sheet, or there were no credentials available. showSignInForm() } }
-
24:40 - Combined credential request
// Combined credential modal request func signIn() { let challenge: Data = … // Fetched from server let passkeyProvider = ASAuthorizationPlatformPublicKeyCredentialProvider( relyingPartyIdentifier:"example.com") let passkeyRequest = passkeyProvider.createCredentialAssertionRequest( challenge: challenge) let passwordRequest = ASAuthorizationPasswordProvider().createRequest() let signInWithAppleRequest = ASAuthorizationAppleIDProvider().createRequest() let controller = ASAuthorizationController( authorizationRequests: [passkeyRequest, passwordRequest, signInWithAppleRequest]) controller.delegate = self controller.presentationContextProvider = self // Start the request controller.performRequests() }
-
25:02 - Combined credential callback
// Completing a combined credential request func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) { switch authorization.credential { case let passkeyAssertion as ASAuthorizationPlatformPublicKeyCredentialAssertion: finishSignIn(with: passkeyAssertion) case let signInWithAppleCredential as ASAuthorizationAppleIDCredential: finishSignIn(with: signInWithAppleCredential) case let passwordCredential as ASPasswordCredential: finishSignIn(with: passwordCredential) default: // Handle other credential types break } }
-
-
正在查找特定内容?在上方输入一个主题,就能直接跳转到相应的精彩内容。
提交你查询的内容时出现错误。请检查互联网连接,然后再试一次。