具有 Windows Hello 配套 (IoT) 设备的 Windows 解锁Windows Unlock with Windows Hello companion (IoT) devices

Windows Hello 配套设备是可以与你的 Windows 10 桌面版一起使用来增强用户身份验证体验的设备。A Windows Hello companion device is a device that can act in conjunction with your Windows 10 desktop to enhance the user authentication experience. 使用 Windows Hello 配套设备框架,配套设备即使在生物识别不可用时也可以为 Windows Hello 提供丰富的体验(例如,如果 Windows 10 桌面缺少人脸身份验证或指纹读取器设备的照相机,例如)。Using the Windows Hello companion device framework, a companion device can provide a rich experience for Windows Hello even when biometrics are not available (for example, if the Windows 10 desktop lacks a camera for face authentication or fingerprint reader device, for example).

注意Microsoft 将在2020的弃用中为 Windows Hello 配套设备框架 API。Note Microsoft will be deprecating the API for the Windows Hello companion device framework in the first half of 2020.

注意 Windows Hello 配套设备框架是不向所有应用开发人员提供的特定功能。Note The Windows Hello companion device framework is a specialized feature not available to all app developers. 若要使用此框架,应用必须由 Microsoft 专门设置,并且在它的清单中列出受限制的 secondaryAuthenticationFactor 功能。To use this framework, your app must be specifically provisioned by Microsoft and list the restricted secondaryAuthenticationFactor capability in its manifest. 若要获得批准,请联系 cdfonboard@microsoft.comTo obtain approval, contact cdfonboard@microsoft.com.

简介Introduction

有关视频概述,请参阅第 9 频道上来自内部版本 2016 的具有 IoT 设备的 Windows 解锁会话。For a video overview, see the Windows Unlock with IoT Devices session from Build 2016 on Channel 9.

有关代码示例,请参阅 Windows Hello 配套设备框架 Github 存储库For code samples, see the Windows Hello companion device framework Github repository.

用例Use cases

有很多方法可以将 Windows Hello 配套设备框架与配套设备结合使用,从而生成出色的 Windows 解锁体验。There are numerous ways one can use the Windows Hello companion device framework to build a great Windows unlock experience with a companion device. 例如,用户可以:For example, users could:

  • 通过 USB 将配套设备连接到电脑、触摸配套设备上的按钮,并自动解锁电脑。Attach their companion device to PC via USB, touch the button on the companion device, and automatically unlock their PC.
  • 在口袋中携带已通过蓝牙与电脑配对的手机。Carry a phone in their pocket that is already paired with PC over Bluetooth. 当在电脑上点击空格键时,手机会收到通知。Upon hitting the spacebar on their PC, their phone receives a notification. 同意该通知,电脑即会解锁。Approve it and the PC simply unlocks.
  • 点击 NFC 读卡器的配套设备,快速解锁电脑。Tap their companion device to an NFC reader to quickly unlock their PC.
  • 戴上已验证穿戴者身份的健身环。Wear a fitness band that has already authenticated the wearer. 接近电脑,通过执行特殊手势(例如鼓掌),解锁电脑。Upon approaching PC, and by performing a special gesture (like clapping), the PC unlocks.

启用生物识别的 Windows Hello 配套设备Biometric enabled Windows Hello companion devices

如果配套设备支持生物识别,在某些情况下,Windows 生物识别框架可能是比 Windows Hello 配套设备框架更好的解决方案。If the companion device supports biometrics, in some cases the Windows Biometric framework may be a better solution than the Windows Hello companion device framework. 请联系 cdfonboard@microsoft.com,我们将帮助你选取正确的方法。Please contact cdfonboard@microsoft.com and we'll help you pick the right approach.

解决方案的构成Components of the solution

下图描述了解决方案的构成以及构建它们的责任方。The diagram below depicts the components of the solution and who is responsible for building them.

框架概述

Windows Hello 配套设备框架实现为在 Windows 上运行的服务(在本文中称为配套身份验证服务)。The Windows Hello companion device framework is implemented as a service running on Windows (called the Companion Authentication Service in this article). 此服务负责生成需要由存储在 Windows Hello 配套设备上的 HMAC 密钥保护的解锁令牌。This service is responsible for generating an unlock token which needs to be protected by an HMAC key stored on the Windows Hello companion device. 这可保证访问解锁令牌需要有 Windows Hello 配套设备。This guarantees that access to the unlock token requires Windows Hello companion device presence. 每个(电脑,Windows 用户)元组都会有唯一的解锁令牌。Per each (PC, Windows user) tuple, there will be a unique unlock token.

与 Windows Hello 配套设备框架集成需要:Integration with the Windows Hello Companion Device Framework requires:

  • 从 Windows 应用商店下载的配套设备的通用 Windows 平台 (UWP) Windows Hello 配套设备应用。A Universal Windows Platform (UWP) Windows Hello companion device app for the companion device, downloaded from the Windows app store.
  • 能够在 Windows Hello 配套设备上创建两个 256 位的 HMAC 密钥,并通过它生成 HMAC(使用 SHA-256)。The ability to create two 256 bit HMAC keys on the Windows Hello companion device and generate HMAC with it (using SHA-256).
  • 正确配置 Windows 10 桌面版的安全设置。Security settings on the Windows 10 desktop properly configured. 配套身份验证服务将要求在任何 Windows Hello 配套设备插入此 PIN 前先设置它。The Companion Authentication Service will require this PIN to be set up before any Windows Hello companion device can be plugged into it. 用户必须通过“设置”>“帐户”>“登录”选项来设置 PIN。The users must set up a PIN via Settings > Accounts > Sign-in options.

除上述要求外,Windows Hello 配套设备应用还负责:In addition to the above requirements, the Windows Hello companion device app is responsible for:

  • 用户体验和初始注册的品牌,以及在以后取消 Windows Hello 配套设备注册。User experience and branding of initial registration and later de-registration of the Windows Hello companion device.
  • 在后台运行、发现 Windows Hello 配套设备,与 Windows Hello 配套设备和配套身份验证服务通信。Running in the background, discovering the Windows Hello companion device, communicating to the Windows Hello companion device and also Companion Authentication Service.
  • 错误处理Error handling

正常情况下,配套设备随附在用于初始设置的应用上,例如首次设置健身环。Normally, companion devices ship with an app for initial setup, like setting up a fitness band for the first time. 本文档介绍的功能可能是该应用的一部分,而且也不需要单独的应用。The functionality described in this document can be part of that app and a separate app should not be required.

用户信号User signals

每个 Windows Hello 配套设备均应与支持三种用户信号的应用结合。Each Windows Hello companion device should be combined with an app that supports three user signals. 这些信号可以采用操作或手势的形式。These signals can be in form of an action or gesture.

  • 意图信号:通过诸如点击 Windows Hello 配套设备上的按钮等方式,允许用户显示解锁意图。Intent signal: Allows the user to show his intent for unlock by, for example, hitting a button on the Windows Hello companion device. 意图信号必须在 Windows Hello 配套设备端收集。The intent signal must be collected on Windows Hello companion device side.
  • 用户存在信号:证明存在用户。User presence signal: Proves the presence of the user. 例如,Windows Hello 配套设备可能在可用于解锁电脑前需要 PIN(不要与电脑 PIN 混淆),或者它可能需要按某个按钮。The Windows Hello companion device might, for instance, require a PIN before it can be used for unlocking PC (not to be confused with PC PIN), or it might require press of a button.
  • 消除歧义信号:当向 Windows Hello 配套设备提供多个选项时,消除用户想要解锁哪台 Windows 10 桌面版的疑虑。Disambiguation signal: Disambiguates which Windows 10 desktop the user wants to unlock when multiple options are available to the Windows Hello companion device.

上述任意数量的用户信号都可以组合成一个信号。Any number of these user signals can be combined into one. 每次使用时都必须要有用户存在信号和意图信号。User presence and intent signals must be required on each use.

注册以及电脑和 Windows Hello 配套设备之间的未来通信Registration and future communication between a PC and Windows Hello companion devices

在 Windows Hello 配套设备可插入 Windows Hello 配套设备框架前,它需要先向该框架注册。Before a Windows Hello companion device can be plugged into the Windows Hello companion device framework, it needs to be registered with the framework. 注册体验完全归 Windows Hello 配套设备应用所有。The experience for registration is completely owned by the Windows Hello companion device app.

Windows Hello 配套设备和 Windows 10 桌面版设备的关系可以是一对多的关系(即,一台配套设备可用于多台 Windows 10 桌面版设备)。The relationship between the Windows Hello companion device and the Windows 10 desktop device can be one to many (i.e., one companion device can be used for many Windows 10 desktop devices). 但是,每台 Windows Hello 配套设备在每台 Windows 10 桌面版设备上仅可用于一个用户。However, each Windows Hello companion device can only be used for one user on each Windows 10 desktop device.

在 Windows Hello 配套设备能与电脑通信前,它们需要同意使用某种传输。Before a Windows Hello companion device can communicate with a PC, they need to agree on a transport to use. 此类选择留待 Windows Hello 配套设备应用做出;Windows Hello 配套设备框架不会对传输类型(USB、NFC、WLAN、BT、BLE 等)或在 Windows Hello 配套设备和 Windows 10 桌面版设备端的 Windows Hello 配套设备应用之间使用的协议施加任何限制。Such choice is left to the Windows Hello companion device app; the Windows Hello companion device framework does not impose any limitations on transport type (USB, NFC, WiFi, BT, BLE, etc) or protocol being used between the Windows Hello companion device and the Windows Hello companion device app on the Windows 10 desktop device side. 但是,就像在本文档的“安全要求”部分中所示那样,它会提示传输层的某些安全注意事项。It does, however, suggest certain security considerations for the transport layer as outlined in the "Security Requirements" section of this document. 提供这些要求是设备提供商的责任。It is the device provider’s responsibility to provide those requirements. 框架不会为你提供它们。The framework does not provide them for you.

用户交互模型User Interaction Model

Windows Hello 配套设备应用发现、安装和首次注册Windows Hello companion device app discovery, installation, and first-time registration

典型的用户工作流如下所示:A typical user workflow is as follows:

  • 用户在想要通过该 Windows Hello 配套设备解锁的每台目标 Windows 10 桌面版设备上设置 PIN。The user sets up the PIN on each of target Windows 10 desktop devices she wants to unlock with that Windows Hello companion device.
  • 用户在 Windows 10 桌面版设备上运行 Windows Hello 配套设备应用,以将 Windows Hello 配套设备注册到 Windows 10 桌面版。The user runs the Windows Hello companion device app on their Windows 10 desktop device to register her Windows Hello companion device with Windows 10 desktop.

注意:Notes:

  • 建议优化 Windows Hello 设备应用的发现、下载和启动,如有可能,自动(例如,可以在 Windows 10 桌面版设备上的 NFC 读卡器上点击 Windows Hello 设备时下载该应用端)。We recommend the discovery, download, and launch of the Windows Hello companion device app is streamlined and, if possible, automated (for example, the app can be downloaded upon tapping the Windows Hello companion device on an NFC reader on Windows 10 desktop device side). 但是,这是 Windows Hello 配套设备和 Windows Hello 配套设备应用的责任。This is, however, the responsibility of the Windows Hello companion device and Windows Hello companion device app.
  • 在企业环境中,Windows Hello 配套设备应用可通过 MDM 部署。In an enterprise environment, the Windows Hello companion device app can be deployed via MDM.
  • Windows Hello 配套设备应用负责向用户显示任何在注册时发生的错误消息。The Windows Hello companion device app is responsible for showing the user any error messages that happen as part of registration.

注册和注销协议Registration and de-registration protocol

下图说明了在注册期间 Windows Hello 配套设备如何与配套身份验证服务交互。The following diagram illustrates how the Windows Hello companion device interacts with Companion Authentication Service during registration.

注册流程

在协议中要用到两个密钥:There are two keys used in our protocol:

  • 设备密钥 (devicekey):用于保护电脑解锁 Windows 所需的解锁令牌。Device key (devicekey): used to protect unlock tokens that the PC needs to unlock Windows.
  • 身份验证密钥 (authkey):用于共同验证 Windows Hello 配套设备和配套身份验证服务。The authentication key (authkey): used to mutually authenticate the Windows Hello companion device and Companion Authentication Service.

设备密钥和身份验证密钥在注册时会在 Windows Hello 配套设备应用和 Windows Hello 配套设备之间交换。The device key and authentication keys are exchanged at registration time between the Windows Hello companion device app and Windows Hello companion device. 因此,Windows Hello 配套设备应用和 Windows Hello 配套设备必须使用安全传输来保护密钥。As a result, the Windows Hello companion device app and Windows Hello companion device must use a secure transport to protect keys.

此外请注意,虽然上图显示了两个在 Windows Hello 配套设备上生成的 HMAC 密钥,但应用也可以生成它们并将它们发送到 Windows Hello 配套设备以进行存储。Also, note that while the diagram above displays two HMAC keys generating on the Windows Hello companion device, it is also possible for the app to generate them and send them to the Windows Hello companion device for storage.

启动身份验证流程Starting authentication flows

通过使用 Windows Hello 配套设备框架(即提供意图信号),用户有两种方法可以启动 Windows 10 桌面版的登录流程:There are two ways for the user to start the signing in flow to Windows 10 desktop using Windows Hello companion device framework (i.e., provide intent signal):

  • 打开笔记本电脑的盖子,或者点击电脑空格键或轻扫。Open up the lid on laptop, or hit the space bar or swipe up on PC.
  • 在 Windows Hello 配套设备端执行手势或操作。Perform a gesture or an action on the Windows Hello companion device side.

由 Windows Hello 配套设备选择哪一个是起始点。It is the Windows Hello companion device's choice to select which one is the starting point. 当选项一发生时,Windows Hello 配套设备框架会通知配套设备应用。The Windows Hello companion device framework will inform companion device app when option one happens. 对于选项二,Windows Hello 配套设备应用应查询配套设备以查看是否已捕获该事件。For option two, the Windows Hello companion device app should query the companion device to see if that event has been captured. 这确保了在解锁成功前 Windows Hello 配套设备能收集意图信号。This ensures the Windows Hello companion device collects the intent signal before the unlock succeeds.

Windows Hello 配套设备凭据提供程序Windows Hello companion device credential provider

Windows 10 拥有处理所有 Windows Hello 配套设备的全新凭据提供程序。There is a new credential provider in Windows 10 that handles all Windows Hello companion devices.

Windows Hello 配套设备凭据提供程序负责通过激活某个触发器来启动配套设备后台任务。The Windows Hello companion device credential provider is responsible for launching the companion device background task via activating a trigger. 该触发器在唤醒电脑并且显示锁屏界面时进行首次设置。The trigger is set the first time when the PC awakens and a lock screen is displayed. 第二次是在电脑进入登录 UI 并且 Windows Hello 配套设备凭据提供程序已是选定磁贴时。The second time is when the PC is entering logon UI and the Windows Hello companion device credential provider is the selected tile.

Windows Hello 配套设备应用的帮助程序库会侦听锁屏界面状态更改,并发送对应 Windows Hello 配套设备后台任务的事件。The helper library for the Windows Hello companion device app will listen to the lock screen status change and send the event corresponding to the Windows Hello companion device background task.

如果有多个 Windows Hello 配套设备后台任务,则第一个完成身份验证过程的后台任务将解锁电脑。If there are multiple Windows Hello companion device background tasks, the first background task that has finished the authentication process will unlock the PC. 配套设备身份验证服务将忽略任何其余的身份验证调用。The companion device authentication service will ignore any remaining authentication calls.

Windows Hello 配套设备端的体验归 Windows Hello 配套设备应用所有并由其管理。The experience on the Windows Hello companion device side is owned and managed by the Windows Hello companion device app. Windows Hello 配套设备框架无法控制此部分的用户体验。The Windows Hello companion device framework has no control over this part of the user experience. 更具体地说,伴随身份验证提供程序通知 Windows Hello 设备应用程序(通过其后台应用)有关登录 UI 中状态更改的信息(例如,锁定屏幕刚刚关闭,或者用户只需通过按空格键 dispelled 锁定屏幕)。Windows Hello 设备应用程序负责构建围绕该体验的体验(例如,当用户点击空格键并 dispelling 解锁屏幕时,开始通过 USB 查找设备)。More specifically, the companion authentication provider informs the Windows Hello companion device app (via its background app) about state changes in logon UI (for example, lock screen just came down, or the user just dispelled lock screen by hitting spacebar), and it is the responsibility of the Windows Hello companion device app to build an experience around that (for example, upon user hitting spacebar and dispelling unlock screen, start looking for the device over USB).

Windows Hello 配套设备框架会提供大量(本地化的)文本和错误消息以供 Windows Hello 配套设备应用进行选择。The Windows Hello companion device Framework will provide a stock of (localized) text and error messages for the Windows Hello companion device app to choose from. 这些都将在锁屏界面顶部(或登录 UI 中)显示。These will be displayed on top of lock screen (or in logon UI). 有关更多详细信息,请参阅“处理消息和错误”部分。See the Dealing with Messages and Errors section for more details.

身份验证协议Authentication protocol

在与 Windows Hello 配套设备应用关联的后台任务的触发器启动后,它有责任请求 Windows Hello 配套设备验证配套身份验证服务计算的某个 HMAC 值,来帮助计算两个 HMAC 值:Once the background task associated with a Windows Hello companion device app is trigger started, it is responsible for asking the Windows Hello companion device to validate an HMAC value computed by the Companion Authentication Service and help calculate two HMAC values:

  • 验证服务 HMAC = HMAC(authentication key, service nonce || device nonce || session nonce)。Validate Service HMAC = HMAC(authentication key, service nonce || device nonce || session nonce).
  • 计算具有 nonce 的设备密钥的 HMAC。Calculate the HMAC of the device key with a nonce.
  • 计算第一个 HMAC 值与配套身份验证服务生成的 nonce 串联的身份验证密钥的 HMAC。Calculate the HMAC of the authentication key with first HMAC value concatenated with a nonce generated by the Companion Authentication Service.

第二个计算值由服务用于验证设备身份,并且还阻止传输通道中的重播攻击。The second computed value is used by the service to authenticate the device and also prevent replay attack in transport channel.

注册流程

生命周期管理Lifecycle management

一次注册,随处使用Register once, use everywhere

如果没有后端服务器,用户必须将他们的 Windows Hello 配套设备分别注册到每台 Windows 10 桌面版设备上。Without a backend server, users must register their Windows Hello companion device with each Windows 10 desktop device separately.

配套设备供应商或 OEM 可以实现 Web 服务以在用户的 Windows 10 桌面版或移动设备上漫游注册状态。A companion device vendor or OEM can implement a web service to roam the registration state across user Windows 10 desktops or mobile devices. 有关更多详细信息,请参阅“漫游、吊销和筛选器服务”部分。For more details, see the Roaming, Revocation, and Filter Service section.

PIN 管理PIN management

在配套设备可以使用前,需要在 Windows 10 桌面设备上设置 PIN。Before a companion device can be used, a PIN needs to be set up on Windows 10 desktop device. 这可确保用户拥有一份备份,以防 Windows Hello 配套设备无法运行。This ensures the user has a backup in case their Windows Hello companion device is not working. PIN 受到 Windows 管理,但应用永远无法看到。The PIN is something that Windows manages and that apps never see. 若要更改它,用户应导航到“设置”>“帐户”>“登录”选项。To change it, the user navigates to Settings > Accounts > Sign-in options.

管理和策略Management and policy

通过在 Windows 10 桌面版上运行 Windows Hello 配套设备应用,用户可从该桌面版删除 Windows Hello 配套设备。Users can remove a Windows Hello companion device from a Windows 10 desktops by running the Windows Hello companion device app on that desktop device.

企业有两个选择可以控制 Windows Hello 配套设备框架:Enterprises have two options for controlling the Windows Hello companion device framework:

  • 打开或关闭功能Turn the feature on or off
  • 使用 Windows 应用保险箱定义允许的 Windows Hello 配套设备白名单Define the whitelist of Windows Hello companion devices allowed using Windows app locker

Windows Hello 配套设备框架不支持任何保留可用配套设备清单的集中式方法,或者是进一步筛选允许哪一个 Windows Hello 配套设备类型的实例的方法(例如仅允许序列号在 X 和 Y 之间的配套设备)。The Windows Hello companion device framework does not support any centralized way to keep inventory of available companion devices, or a method to further filter which instances of a Windows Hello companion device type is allowed (for example, only a companion device with a serial number between X and Y are allowed). 但是,应用开发人员可以生成提供此类功能的服务。Apps developers can, however, build a service to provide such functionality. 有关更多详细信息,请参阅“漫游、吊销和筛选器服务”部分。For more details, see the Roaming, Revocation, and Filter Service section.

吊销Revocation

Windows Hello 配套设备框架不支持远程删除特定 Windows 10 桌面版设备的配套设备。The Windows Hello companion device framework does not support removing a companion device from a specific Windows 10 desktop device remotely. 用户可以转而通过在该 Windows 10 桌面版上运行的 Windows Hello 配套设备应用来删除 Windows Hello 配套设备。Instead, users can remove the Windows Hello companion device via the Windows Hello companion device app running on that Windows 10 desktop.

但是,配套设备供应商可以生成能提供远程吊销功能的服务。Companion device vendors, however, can build a service to provide remote revocation functionality. 有关更多详细信息,请参阅“漫游、吊销和筛选器服务”部分。For more details, see Roaming, Revocation, and Filter Service section.

漫游和筛选器服务Roaming and filter services

配套设备供应商可以实现可用于以下方案的 Web 服务:Companion device vendors can implement a web service that can be used for the following scenarios:

  • 企业的筛选器服务:企业可以将能够在它们的环境中运行的 Windows Hello 配套设备集限制为特定供应商的少数精选设备。A filter service for enterprise: An enterprise can limit the set of Windows Hello companion devices that can work in their environment to a select few from a specific vendor. 例如,公司 Contoso 可以从供应商 X 订购 10000 台 Y 型号配套设备,并确保仅这些设备能够在 Contoso 域中运行(并且供应商 X 的任何其他设备型号都不行)。For example, the company Contoso could order 10,000 Model Y companion devices from Vendor X and ensure only those devices will work in the Contoso domain (and not any other device model from Vendor X).
  • 清单:企业可以确定在企业环境中使用的现有配套设备的列表。Inventory: An enterprise can determine the list of existing companion devices used in an enterprise environment.
  • 实时吊销:如果员工报告配套设备丢失或失窃,可使用 Web 服务吊销该设备。Real time revocation: If an employee reports that his companion device is lost or stolen, the web service can be used to revoke that device.
  • 漫游:用户仅需注册配套设备一次,它就可以在所有 Windows 10 桌面版和移动版上运行。Roaming: A user only has to register his companion device once and it works on all of his Windows 10 desktops and Mobile.

实现这些功能要求 Windows Hello 配套设备应用在注册和使用时检查 Web 服务。Implementing these features requires the Windows Hello companion device app to check with the web service at registration and usage time. Windows Hello 配套设备应用可以为要求一天仅检查一次 Web 服务之类的缓存登录方案进行优化(代价是将吊销事件延长至最多一天)。The Windows Hello companion device app can optimize for cached logon scenarios like requiring checking with web service only once a day (at the cost of extending the revocation time to up to one day).

Windows Hello 配套设备框架 API 模型Windows Hello companion device framework API model

概述Overview

Windows Hello 配套设备应用应包含两个组件:UI 负责注册和注销设备的前台应用,以及处理身份验证的后台任务。A Windows Hello companion device app should contain two components: a foregroud app with UI responsible for registering and unregistering the device, and a background task that handles authentication.

整体 API 流程如下所示:The overall API flow is as follows:

  1. 注册 Windows Hello 配套设备Register the Windows Hello companion device
    • 确保设备在附近并查询其功能(如果需要)Make sure the device is nearby and query its capability (if required)
    • 生成两个 HMAC 密钥(在配套设备端或在应用端)Generate two HMAC keys (either on the companion device side or the app side)
    • 调用 RequestStartRegisteringDeviceAsyncCall RequestStartRegisteringDeviceAsync
    • 调用 FinishRegisteringDeviceAsyncCall FinishRegisteringDeviceAsync
    • 确保 Windows Hello 配套设备应用存储了 HMAC 密钥(如果支持),并且 Windows Hello 配套设备应用放弃了其副本Make sure Windows Hello companion device app stores HMAC keys (if supported) and Windows Hello companion device app discards its copies
  2. 注册后台任务Register your background task
  3. 等待后台任务的正确事件Wait for the right event in the background task
    • WaitingForUserConfirmation:如果开始身份验证流程需要 Windows Hello 配套设备端上的用户操作/手势,请等待此事件WaitingForUserConfirmation: Wait for this event if the user action/gesture on the Windows Hello companion device side is required to start authentication flow
    • CollectingCredential:如果 Windows Hello 设备依赖于电脑端的用户操作/手势来启动身份验证流(例如,按空格键),请等待此事件CollectingCredential: Wait for this event if the Windows Hello companion device relies on user action/gesture on the PC side to start authentication flow (for example, by hitting spacebar)
    • 其他触发器(例如智能卡):确保查询当前身份验证状态,以调用正确的 API。Other trigger, like a smartcard: Make sure to query for current authentication state to call the right APIs.
  4. 通过调用 ShowNotificationMessageAsync,随时通知用户错误消息或要求的后续步骤。Keep user informed about error messages or required next steps by calling ShowNotificationMessageAsync. 仅在收集了意图信号后调用此 APIOnly call this API once an intent signal is collected
  5. 解除锁定Unlock
    • 确保已收集意图和用户存在信号Make sure intent and user presence signals were collected
    • 调用 StartAuthenticationAsyncCall StartAuthenticationAsync
    • 与配套设备通信,执行所需的 HMAC 操作Communicate with the companion device to perform required HMAC operations
    • 调用 FinishAuthenticationAsyncCall FinishAuthenticationAsync
  6. 在用户提出相关请求时(例如用户丢失了配套设备),取消 Windows Hello 配套设备注册Un-register a Windows Hello companion device when the user requests it (for example, if they've lost their companion device)
    • 通过 FindAllRegisteredDeviceInfoAsync 为登录的用户枚举 Windows Hello 配套设备Enumerate the Windows Hello companion device for logged in user via FindAllRegisteredDeviceInfoAsync
    • 使用 UnregisterDeviceAsync 取消注册Un-register it using UnregisterDeviceAsync

注册和注销Registration and de-registration

注册需要配套身份验证服务的两个 API 调用:RequestStartRegisteringDeviceAsync 和 FinishRegisteringDeviceAsync。Registration requires two API calls to the Companion Authentication Service: RequestStartRegisteringDeviceAsync and FinishRegisteringDeviceAsync.

在执行任何这些调用前,Windows Hello 配套设备应用必须确保 Windows Hello 配套设备可用。Before any of these calls are made, the Windows Hello companion device app must make sure that the Windows Hello companion device is available. 如果 Windows Hello 配套设备负责生成 HMAC 密钥(身份验证和设备密钥),Windows Hello 配套设备应用还应要求配套设备在执行任何上述两个调用前生成这些密钥。If the Windows Hello companion device is responsible for generating HMAC keys (authentication and device keys), then the Windows Hello companion device app should also ask the companion device to generate them before making any of the above two calls. 如果 Windows Hello 配套设备应用负责生成 HMAC 密钥,则它在调用上述两个调用前也应这样做。If the Windows Hello companion device app is responsible for generating HMAC keys, then it should do so before calling the above two calls.

此外,作为第一个 API 调用 (RequestStartRegisteringDeviceAsync) 的一部分,Windows Hello 配套设备应用必须确定设备功能,并准备将其作为 API 调用的一部分进行传递(例如 Windows Hello 配套设备是否支持安全存储 HMAC 密钥)。Additionally, as part of first API call (RequestStartRegisteringDeviceAsync), the Windows Hello companion device app must decide on device capability and be prepared to pass it as part of the API call; for example, whether the Windows Hello companion device supports secure storage for HMAC keys. 如果相同 Windows Hello 配套设备应用用于管理多个版本的相同配套设备,并且这些功能会更改(还要求进行设备查询才能做出决定),我们建议此查询要在执行第一个 API 调用前发生。If the same Windows Hello companion device app is used to manage multiple versions of the same companion device and those capabilities change (and requires a device query to decide), we recommend this queries occurs before first API call is made.

第一个 API (RequestStartRegisteringDeviceAsync) 将返回第二个 API (FinishRegisteringDeviceAsync) 使用的句柄。The first API (RequestStartRegisteringDeviceAsync) will return a handle used by the second API (FinishRegisteringDeviceAsync). 首次调用注册将启动 PIN 提示符以确保用户已存在。The first call for registration will launch the PIN prompt to make sure user is present. 如果没有设置任何 PIN,此调用将失败。If no PIN is set up, this call will fail. Windows Hello 配套设备应用还可通过 KeyCredentialManager.IsSupportedAsync 调用查询 PIN 是否已设置。The Windows Hello companion device app can query whether PIN is set up or not via KeyCredentialManager.IsSupportedAsync call as well. 如果策略已禁用 Windows Hello 配套设备,RequestStartRegisteringDeviceAsync 调用也可能会失败。RequestStartRegisteringDeviceAsync call can also fail if policy has disabled the usage of the Windows Hello companion device.

第一个调用的结果通过 SecondaryAuthenticationFactorRegistrationStatus 枚举返回:The result of first call is returned via SecondaryAuthenticationFactorRegistrationStatus enum:

{
    Failed = 0,         // Something went wrong in the underlying components
    Started,            // First call succeeded
    CanceledByUser,     // User cancelled PIN prompt
    PinSetupRequired,   // PIN is not set up
    DisabledByPolicy,   // Companion device framework or this app is disabled
}

第二个调用 (FinishRegisteringDeviceAsync) 完成注册。The second call (FinishRegisteringDeviceAsync) finishes the registration. 作为注册过程的一部分,Windows Hello 配套设备应用可以使用配套身份验证服务来存储配套设备配置数据。As part of registration process, the Windows Hello companion device app can store companion device configuration data with Companion Authentication Service. 此数据的大小限制为 4K。There is a 4K size limit for this data. 在进行身份验证时,此数据将提供给 Windows Hello 配套设备应用。This data will be available to the Windows Hello companion device app at authentication time. 例如,此数据可用于连接 Windows Hello 配套设备(例如 MAC 地址),或者如果 Windows Hello 配套设备没有存储,但配套设备想要将电脑用于存储,则可使用配置数据。This data can be used, as an example, to connect to the Windows Hello companion device like a MAC address, or if the Windows Hello companion device does not have storage and companion device wants to use PC for storage, then configuration data can be used. 注意,任何作为配置数据的一部分存储的敏感数据都必须使用仅 Windows Hello 配套设备知道的密钥加密。Note that any sensitive data stored as part of configuration data must be encrypted with a key that only the Windows Hello companion device knows. 另外,考虑到配置数据由 Windows 服务存储,它在用户配置文件上可用于 Windows Hello 配套设备应用。Also, given that configuration data is stored by a Windows service, it is available to the Windows Hello companion device app across user profiles.

Windows Hello 配套设备应用可调用 AbortRegisteringDeviceAsync 以取消注册,并传入错误代码。The Windows Hello companion device app can call AbortRegisteringDeviceAsync to cancel the registration and pass in an error code. 配套身份验证服务将在遥测数据中记录错误。The Companion Authentication Service will log the error in the telemetry data. 此调用的一个很好的示例是当 Windows Hello 配套设备出现问题时,它无法完成注册(例如,无法存储 HMAC 密钥或 BT 连接丢失)。A good example for this call would be when something went wrong with the Windows Hello companion device and it could not finish registration (for example, it cannot store HMAC keys or BT connection was lost).

Windows Hello 设备的设备应用必须提供一个选项,让用户从其 Windows 10 桌面取消注册其 Windows Hello 设备(例如,如果他们失去了其配套设备或购买了较新版本)。The Windows Hello companion device app must provide an option for the user to de-register their Windows Hello companion device from their Windows 10 desktop (for example, if they lost their companion device or bought a newer version). 当用户选择该选项时,Windows Hello 配套设备应用必须调用 UnregisterDeviceAsync。When the user selects that option, then the Windows Hello companion device app must call UnregisterDeviceAsync. 此 Windows Hello 配套设备应用的调用将触发配套设备身份验证服务从电脑端删除与调用方应用的特定设备 Id 和 AppId 对应的所有数据(包括 HMAC 密钥)。This call by the Windows Hello companion device app will trigger the companion device authentication service to delete all data (including HMAC keys) corresponding to the specific device Id and AppId of the caller app from PC side. 此 API 调用不会尝试从 Windows Hello 配套设备应用或配套设备端删除 HMAC 密钥。This API call does not attempt to delete HMAC keys from either the Windows Hello companion device app or companion device side. 这留待 Windows Hello 配套设备应用来实现。That is left for the Windows Hello companion device app to implement.

Windows Hello 配套设备应用负责显示在注册和注销阶段发生的任何错误消息。The Windows Hello companion device app is responsible for showing any error messages that happen in registration and de-registration phase.

using System;
using Windows.Security.Authentication.Identity.Provider;
using Windows.Storage.Streams;
using Windows.Security.Cryptography;
using Windows.UI.Popups;

namespace SecondaryAuthFactorSample
{
    public class DeviceRegistration
    {

        public void async OnRegisterButtonClick()
        {
            //
            // Pseudo function, the deviceId should be retrieved by the application from the device
            //
            string deviceId = await ReadSerialNumberFromDevice();

            IBuffer deviceKey = CryptographicBuffer.GenerateRandom(256/8);
            IBuffer mutualAuthenticationKey = CryptographicBuffer.GenerateRandom(256/8);

            SecondaryAuthenticationFactorRegistration registrationResult =
                await SecondaryAuthenticationFactorRegistration.RequestStartRegisteringDeviceAsync(
                    deviceId,  // deviceId: max 40 wide characters. For example, serial number of the device
                    SecondaryAuthenticationFactorDeviceCapabilities.SecureStorage |
                        SecondaryAuthenticationFactorDeviceCapabilities.HMacSha256 |
                        SecondaryAuthenticationFactorDeviceCapabilities.StoreKeys,
                    "My test device 1", // deviceFriendlyName: max 64 wide characters. For example: John's card
                    "SAMPLE-001", // deviceModelNumber: max 32 wide characters. The app should read the model number from device.
                    deviceKey,
                    mutualAuthenticationKey);

            switch(registerResult.Status)
            {
            case SecondaryAuthenticationFactorRegistrationStatus.Started:
                //
                // Pseudo function:
                // The app needs to retrieve the value from device and set into opaqueBlob
                //
                IBuffer deviceConfigData = ReadConfigurationDataFromDevice();

                if (deviceConfigData != null)
                {
                    await registrationResult.Registration.FinishRegisteringDeviceAsync(deviceConfigData); //config data limited to 4096 bytes
                    MessageDialog dialog = new MessageDialog("The device is registered correctly.");
                    await dialog.ShowAsync();
                }
                else
                {
                    await registrationResult.Registration.AbortRegisteringDeviceAsync("Failed to connect to the device");
                    MessageDialog dialog = new MessageDialog("Failed to connect to the device.");
                    await dialog.ShowAsync();
                }
                break;

            case SecondaryAuthenticationFactorRegistrationStatus.CanceledByUser:
                MessageDialog dialog = new MessageDialog("You didn't enter your PIN.");
                await dialog.ShowAsync();
                break;

            case SecondaryAuthenticationFactorRegistrationStatus.PinSetupRequired:
                MessageDialog dialog = new MessageDialog("Please setup PIN in settings.");
                await dialog.ShowAsync();
                break;

            case SecondaryAuthenticationFactorRegistrationStatus.DisabledByPolicy:
                MessageDialog dialog = new MessageDialog("Your enterprise prevents using this device to sign in.");
                await dialog.ShowAsync();
                break;
            }
        }

        public void async UpdateDeviceList()
        {
            IReadOnlyList<SecondaryAuthenticationFactorInfo> deviceInfoList =
                await SecondaryAuthenticationFactorRegistration.FindAllRegisteredDeviceInfoAsync(
                    SecondaryAuthenticationFactorDeviceFindScope.User);

            if (deviceInfoList.Count > 0)
            {
                foreach (SecondaryAuthenticationFactorInfo deviceInfo in deviceInfoList)
                {
                    //
                    // Add deviceInfo.FriendlyName and deviceInfo.DeviceId into a combo box
                    //
                }
            }
        }

        public void async OnUnregisterButtonClick()
        {
            string deviceId;
            //
            // Read the deviceId from the selected item in the combo box
            //
            await SecondaryAuthenticationFactorRegistration.UnregisterDeviceAsync(deviceId);
        }
    }
}

AuthenticationAuthentication

身份验证需要配套身份验证服务的两个 API 调用:StartAuthenticationAsync 和 FinishAuthencationAsync。Authentication requires two API calls to the Companion Authentication Service: StartAuthenticationAsync and FinishAuthencationAsync.

第一个启动 API 将返回第二个 API 使用的句柄。The first initiation API will return a handle used by the second API. 在其他事项中,第一个调用返回需要通过存储在 Windows Hello 配套设备上的设备密钥进行 HMAC 处理的 nonce(在与其他内容串联后)。The first call returns, among other things, a nonce that – once concatenated with other things - needs to be HMAC'ed with the device key stored on the Windows Hello companion device. 第二个调用返回 HMAC 的结果和设备密钥,并且最后可能验证身份成功(即用户将看到桌面)。The second call returns the results of HMAC with device key and can potentially end in successful authentication (i.e., the user will see their desktop).

如果在初始注册后策略禁用了该 Windows Hello 配套设备,则第一个启动 API (StartAuthenticationAsync) 可能失败。The first initiation API (StartAuthenticationAsync) can fail if policy has disabled that Windows Hello companion device after initial registration. 如果在 WaitingForUserConfirmation 或 CollectingCredential 状态之外执行了 API 调用,它也可能失败(稍后在本部分还会有详细介绍)。It can also fail if the API call was made outside WaitingForUserConfirmation or CollectingCredential states (more on this later in this section). 如果未注册的配套设备应用进行调用,它也可能失败。It can also fail if an unregistered companion device app calls it. SecondaryAuthenticationFactorAuthenticationStatus 枚举总结了以下可能的结果:SecondaryAuthenticationFactorAuthenticationStatus Enum summarizes the possible outcomes:

{
    Failed = 0,                     // Something went wrong in the underlying components
    Started,
    UnknownDevice,                  // Companion device app is not registered with framework
    DisabledByPolicy,               // Policy disabled this device after registration
    InvalidAuthenticationStage,     // Companion device framework is not currently accepting
                                    // incoming authentication requests
}

如果第一个 API 调用提供的 nonce 到期(20 秒),第二个调用 (FinishAuthencationAsync) 可能会失败。The second API call (FinishAuthencationAsync) can fail if the nonce that was provided in the first call is expired (20 seconds). SecondaryAuthenticationFactorFinishAuthenticationStatus 枚举捕获可能的结果。SecondaryAuthenticationFactorFinishAuthenticationStatus enum captures possible outcomes.

{
    Failed = 0,     // Something went wrong in the underlying components
    Completed,      // Success
    NonceExpired,   // Nonce is expired
}

两个 API 调用(StartAuthenticationAsync 和 FinishAuthencationAsync)的计时需要符合 Windows Hello 配套设备收集意图、用户存在和消除歧义信号的方式(有关详细信息,请参阅“用户信号”)。The timing of two API calls (StartAuthenticationAsync and FinishAuthencationAsync) needs to align with how the Windows Hello companion device collects intent, user presence, and disambiguation signals (see User Signals for more details). 例如,禁止在意图信号可用前提交第二个调用。For example, the second call must not be submitted until intent signal is available. 换句话说,在用户没有表达意图前,电脑不应解锁。In other words, the PC should not unlock if the user has not expressed intent for it. 为了使表达更加清楚,假定蓝牙邻近感应用于电脑解锁,则必须收集显式意图信号;否则,只要用户走向厨房路过电脑旁边,电脑就会解锁。To make this more clear, assume that Bluetooth proximity is used for PC unlock, then an explicit intent signal must be collected, otherwise, as soon as user walks by his PC on the way to kitchen, the PC will unlock. 另外,从第一个调用返回的 nonce 是有时间限制的(20 秒),并且在某段时间后将到期。Also, the nonce returned from the first call is time bound (20 seconds) and will expire after certain period. 因此,仅当 Windows Hello 设备的设备应用有良好的指示设备存在时,才应进行第一次调用,例如,将设备插入 USB 端口,或在 NFC 读卡器上点击。As a result, the first call only should be made when the Windows Hello companion device app has good indication of companion device presence, for example, the companion device is inserted into USB port, or tapped on NFC reader. 使用蓝牙时,必须小心避免影响电脑端的电池或避免在检查 Windows Hello 配套设备存在时影响正在进行的其他蓝牙活动。With Bluetooth, care must be taken to avoid affecting battery on PC side or affecting other Bluetooth activities going on at that point when checking for Windows Hello companion device presence. 此外,如果需要提供用户状态信号(例如,通过键入 PIN),建议仅在收集该信号后才进行第一次身份验证呼叫。Also, if a user presence signal needs to be provided (for example, by typing in PIN), it is recommended that the first authentication call is only made after that signal is collected.

通过提供用户所处的身份验证流程的全貌,Windows Hello 配套设备框架可帮助 Windows Hello 配套设备应用明智地作出何时执行上述两个调用的决定。The Windows Hello companion device framework helps the Windows Hello companion device app to make informed decision on when to make above two calls by providing a complete picture of where user is in authentication flow. 通过向应用后台任务提供锁定状态更改通知,Windows Hello 配套设备框架可提供此功能。Windows Hello companion device framework provides this functionality by providing lock state change notification to app background task.

配套设备流

这些状态的详细信息如下所示:Details of each of these states are as follows:

省/市/自治区State 描述Description
WaitingForUserConfirmationWaitingForUserConfirmation 锁定屏幕关闭时(例如,用户按下 Windows + L)会触发此状态更改通知事件。This state change notification event is fired when the lock screen comes down (for example, user pressed Windows + L). 我们不建议请求与在此状态中难以查找设备相关的任何错误消息。We recommend not to request any error messages relating to having difficulty finding a device in this state. 一般情况下,我们建议仅在提供意图信号时显示消息。In general, we recommend to only show messages when intent signal is available. 如果配套设备收集意向信号(例如,点击 NFC 读卡器,在配套设备上按按钮或特定手势,如拍手),则 Windows Hello 助理设备应用应进行第一次 API 调用进行身份验证。)和 Windows Hello 设备应用后台任务会接收到检测到意向信号的伴随设备的指示。The Windows Hello companion device app should make the first API call for authentication in this state if the companion device collects the intent signal (for example, tapping on NFC reader, press of a button on the companion device or a specific gesture, like clapping), and the Windows Hello companion device app background task receives indication from the companion device that intent signal was detected. 否则,如果 Windows Hello 配套设备应用依赖电脑启动身份验证流程(通过让用户轻扫解锁屏幕或点击空格键),则 Windows Hello 配套设备应用需要等待下一个状态 (CollectingCredential)。Otherwise, if the Windows Hello companion device app relies on the PC to start authentication flow (by having user swipe up the unlock screen or hitting space bar), then the Windows Hello companion device app needs to wait for the next state (CollectingCredential).
CollectingCredentialCollectingCredential 当用户打开笔记本电脑盖子、点击任意键盘按键或轻扫解锁屏幕时,将触发此状态更改通知事件。This state change notification event is fired when the user either opens their laptop lid, hits any key on their keyboard, or swipes up to the unlock screen. 如果 Windows Hello 设备设备依赖上述操作来开始收集意向信号,则 Windows Hello 辅助设备应用应开始收集该信号(例如,通过伴随设备上的弹出窗口询问用户是否要解锁 PC).If the Windows Hello companion device relies on the above actions to start collecting the intent signal, then the Windows Hello companion device app should start collecting it (for example, via a pop up on the companion device asking whether user wants to unlock the PC). 如果 Windows Hello 配套设备应用需要用户在配套设备上提供用户存在信号(例如在 Windows Hello 配套设备上键入 PIN),这将是提供错误情况的良好时机。This would be a good time to provide error cases if the Windows Hello companion device app needs the user to provide a user presence signal on the companion device (like typing in PIN on the Windows Hello companion device).
SuspendingAuthenticationSuspendingAuthentication 当 Windows Hello 配套设备应用接收此状态时,这意味着配套身份验证服务已停止接收身份验证请求。When the Windows Hello companion device app receives this state, it means that the Companion Authentication Service has stopped accepting authentication requests.
CredentialCollectedCredentialCollected 这表示另一个 Windows Hello 配套设备应用已调用了第二个 API,并且配套身份验证服务正在验证提交内容。This means that another Windows Hello companion device app has called the second API and that the Companion Authentication Service is verifying what was submitted. 此时,除非当前提交的身份验证请求没有通过验证,否则配套身份验证服务不会接受任何其他身份验证请求。At this point, the Companion Authentication Service is not accepting any other authentication requests unless the currently submitted one does not pass verification. Windows Hello 配套设备应用应继续关注,直到到达下一个状态。The Windows Hello companion device app should stay tuned until next state is reached.
CredentialAuthenticatedCredentialAuthenticated 这表示提交的凭据有效。This means that the submitted credential worked. CredentialAuthenticated 拥有已成功的 Windows Hello 配套设备的设备 ID。The credentialAuthenticated has the device ID of the Windows Hello companion device that succeeded. Windows Hello 配套设备应用应确保查看它的关联设备是否是入选方。The Windows Hello companion device app should make sure to check on that to see if its associated device was the winner. 如果不是,则 Windows Hello 配套设备应用应避免显示任何后身份验证流程(例如配套设备上的成功消息或者可能是该设备的振动)。If not, then the Windows Hello companion device app should avoid showing any post authentication flows (like success message on the companion device or perhaps a vibration on that device). 请注意,如果提交的凭据无效,则状态将更改为 CollectingCredential 状态。Note that if the submitted credential did not work, the state will change to CollectingCredential state.
StoppingAuthenticationStoppingAuthentication 身份验证已成功,并且用户已看到桌面。Authentication succeeded and user saw the desktop. 现在应终止后台任务。Time to kill your background task. 在退出后台任务之前,显式注销 StageEvent 处理程序。Before exiting the backround task, explicitly unregister the StageEvent handler. 这将有助于快速退出后台任务。This will help the background task exit quickly.

Windows Hello 配套设备应用在前两种状态中应当仅调用两个身份验证 API。Windows Hello companion device apps should only call the two authentication APIs in the first two states. Windows Hello 配套设备应用应查看触发此事件的方案。Windows Hello companion device apps should check for what scenario this event is being fired. 存在两种可能性:解锁或后解锁。There are two possibilities: unlock or post unlock. 当前仅支持解锁。Currently, only unlock is supported. 在即将推出的版本中,后解锁方案可能会受支持。In upcoming releases, post unlock scenarios may be supported. SecondaryAuthenticationFactorAuthenticationScenario 枚举捕获以下两个选项:The SecondaryAuthenticationFactorAuthenticationScenario enum captures these two options:

{
    SignIn = 0,         // Running under lock screen mode
    CredentialPrompt,   // Running post unlock
}

完整代码示例:Complete code sample:

using System;
using Windows.Security.Authentication.Identity.Provider;
using Windows.Storage.Streams;
using Windows.Security.Cryptography;
using System.Threading;
using Windows.ApplicationModel.Background;

namespace SecondaryAuthFactorSample
{
    public sealed class AuthenticationTask : IBackgroundTask
    {
        private string _deviceId;
        private static AutoResetEvent _exitTaskEvent = new AutoResetEvent(false);
        private static IBackgroundTaskInstance _taskInstance;
        private BackgroundTaskDeferral _deferral;

        private void Authenticate()
        {
            int retryCount = 0;

            while (retryCount < 3)
            {
                //
                // Pseudo code, the svcAuthNonce should be passed to device or generated from device
                //
                IBuffer svcAuthNonce = CryptographicBuffer.GenerateRandom(256/8);

                SecondaryAuthenticationFactorAuthenticationResult authResult = await
                    SecondaryAuthenticationFactorAuthentication.StartAuthenticationAsync(
                        _deviceId,
                        svcAuthNonce);
                if (authResult.Status != SecondaryAuthenticationFactorAuthenticationStatus.Started)
                {
                    SecondaryAuthenticationFactorAuthenticationMessage message;
                    switch (authResult.Status)
                    {
                        case SecondaryAuthenticationFactorAuthenticationStatus.DisabledByPolicy:
                            message = SecondaryAuthenticationFactorAuthenticationMessage.DisabledByPolicy;
                            break;
                        case SecondaryAuthenticationFactorAuthenticationStatus.InvalidAuthenticationStage:
                            // The task might need to wait for a SecondaryAuthenticationFactorAuthenticationStageChangedEvent
                            break;
                        default:
                            return;
                    }

                    // Show error message. Limited to 512 characters wide
                    await SecondaryAuthenticationFactorAuthentication.ShowNotificationMessageAsync(null, message);
                    return;
                }

                //
                // Pseudo function:
                // The device calculates and returns sessionHmac and deviceHmac
                //
                await GetHmacsFromDevice(
                    authResult.Authentication.ServiceAuthenticationHmac,
                    authResult.Authentication.DeviceNonce,
                    authResult.Authentication.SessionNonce,
                    out deviceHmac,
                    out sessionHmac);
                if (sessionHmac == null ||
                    deviceHmac == null)
                {
                    await authResult.Authentication.AbortAuthenticationAsync(
                        "Failed to read data from device");
                    return;
                }

                SecondaryAuthenticationFactorFinishAuthenticationStatus status =
                    await authResult.Authentication.FinishAuthencationAsync(deviceHmac, sessionHmac);
                if (status == SecondaryAuthenticationFactorFinishAuthenticationStatus.NonceExpired)
                {
                    retryCount++;
                    continue;
                }
                else if (status == SecondaryAuthenticationFactorFinishAuthenticationStatus.Completed)
                {
                    // The credential data is collected and ready for unlock
                    return;
                }
            }
        }

        public void OnAuthenticationStageChanged(
            object sender,
            SecondaryAuthenticationFactorAuthenticationStageChangedEventArgs args)
        {
            // The application should check the args.StageInfo.Stage to determine what to do in next. Note that args.StageInfo.Scenario will have the scenario information (SignIn vs CredentialPrompt).

            switch(args.StageInfo.Stage)
            {
            case SecondaryAuthenticationFactorAuthenticationStage.WaitingForUserConfirmation:
                // Show welcome message
                await SecondaryAuthenticationFactorAuthentication.ShowNotificationMessageAsync(
                    null,
                    SecondaryAuthenticationFactorAuthenticationMessage.WelcomeMessageSwipeUp);
                break;

            case SecondaryAuthenticationFactorAuthenticationStage.CollectingCredential:
                // Authenticate device
                Authenticate();
                break;

            case SecondaryAuthenticationFactorAuthenticationStage.CredentialAuthenticated:
                if (args.StageInfo.DeviceId = _deviceId)
                {
                    // Show notification on device about PC unlock
                }
                break;

            case SecondaryAuthenticationFactorAuthenticationStage.StoppingAuthentication:
                // Quit from background task
                _exitTaskEvent.Set();
                break;
            }

            Debug.WriteLine("Authentication Stage = " + args.StageInfo.AuthenticationStage.ToString());
        }

        //
        // The Run method is the entry point of a background task.
        //
        public void Run(IBackgroundTaskInstance taskInstance)
        {
            _taskInstance = taskInstance;
            _deferral = taskInstance.GetDeferral();

            // Register canceled event for this task
            taskInstance.Canceled += TaskInstanceCanceled;

            // Find all device registred by this application
            IReadOnlyList<SecondaryAuthenticationFactorInfo> deviceInfoList =
                await SecondaryAuthenticationFactorRegistration.FindAllRegisteredDeviceInfoAsync(
                    SecondaryAuthenticationFactorDeviceFindScope.AllUsers);

            if (deviceInfoList.Count == 0)
            {
                // Quit the task silently
                return;
            }
            _deviceId = deviceInfoList[0].DeviceId;
            Debug.WriteLine("Use first device '" + _deviceId + "' in the list to signin");

            // Register AuthenticationStageChanged event
            SecondaryAuthenticationFactorRegistration.AuthenticationStageChanged += OnAuthenticationStageChanged;

            // Wait the task exit event
            _exitTaskEvent.WaitOne();

            _deferral.Complete();
        }

        void TaskInstanceCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
        {
            _exitTaskEvent.Set();
        }
    }
}

注册后台任务Register a background task

当 Windows Hello 配套设备应用注册第一台配套设备时,它还应注册该配套设备能够在设备和配套设备身份验证服务之间传递身份验证信息的后台任务组件。When the Windows Hello companion device app registers the first companion device, it should also register its background task component which will pass authentication information between device and companion device authentication service.

using System;
using Windows.Security.Authentication.Identity.Provider;
using Windows.Storage.Streams;
using Windows.ApplicationModel.Background;

namespace SecondaryAuthFactorSample
{
    public class BackgroundTaskManager
    {
        // Register background task
        public static async Task<IBackgroundTaskRegistration> GetOrRegisterBackgroundTaskAsync(
            string bgTaskName,
            string taskEntryPoint)
        {
            // Check if there's an existing background task already registered
            var bgTask = (from t in BackgroundTaskRegistration.AllTasks
                          where t.Value.Name.Equals(bgTaskName)
                          select t.Value).SingleOrDefault();
            if (bgTask == null)
            {
                BackgroundAccessStatus status =
                    BackgroundExecutionManager.RequestAccessAsync().AsTask().GetAwaiter().GetResult();

                if (status == BackgroundAccessStatus.Denied)
                {
                    Debug.WriteLine("Background Execution is denied.");
                    return null;
                }

                var taskBuilder = new BackgroundTaskBuilder();
                taskBuilder.Name = bgTaskName;
                taskBuilder.TaskEntryPoint = taskEntryPoint;
                taskBuilder.SetTrigger(new SecondaryAuthenticationFactorAuthenticationTrigger());
                bgTask = taskBuilder.Register();
                // Background task is registered
            }

            bgTask.Completed += BgTask_Completed;
            bgTask.Progress += BgTask_Progress;

            return bgTask;
        }
    }
}

错误和消息Errors and messages

Windows Hello 配套设备框架负责向用户提供有关登录成功或失败的反馈。The Windows Hello companion device framework is responsible for providing feedback to the user about success or failure of signing in. Windows Hello 配套设备框架会提供大量(本地化的)文本和错误消息以供 Windows Hello 配套设备应用进行选择。The Windows Hello companion device framework will provide a stock of (localized) text and error messages for the Windows Hello companion device app to choose from. 这些内容将显示在登录 UI 中。These will be displayed in the logon UI.

配套设备错误

Windows Hello 配套设备应用可使用 ShowNotificationMessageAsync 向用户显示作为登录 UI 一部分的消息。Windows Hello companion device apps can use ShowNotificationMessageAsync to show messages to user as part of the logon UI. 在意图信号可用时,调用此 API。Call this API when an intent signal is available. 请注意,意图信号必须始终在 Windows Hello 配套设备端上收集。Note that an intent signal must always be collected on the Windows Hello companion device side.

有两种消息类型:指导和错误消息。There are two types of messages: guidance and errors.

指导消息旨在向用户显示如何启动解锁过程。Guidance messages are designed to show the user how to start the unlock process. 这些消息只会在设备第一次注册时在锁屏界面上向用户显示一次,并且不会再显示。These messages are only shown to the user once on the lock screen, upon first device registration, and never shown there again. 这些消息将继续显示在锁屏界面下。These messages will continue to be shown under the lock screen.

错误消息将始终显示并且会在提供意图信号后进行显示。Error messages are always shown and will be shown after an intent signal is provided. 考虑到必须先收集意图信号再向用户显示消息,并且用户将仅使用其中一台 Windows Hello 配套设备提供该意图,所以禁止出现多台 Windows Hello 配套设备争相显示错误消息的情况。Given that an intent signal must be collected before showing messages to the user, and the user will provide that intent only using one of the Windows Hello companion devices, there must not be a situation where multiple Windows Hello companion devices race for showing error messages. 因此,Windows Hello 配套设备框架不会保持任何队列。As a result, the Windows Hello companion device framework does not maintain any queue. 当调用方请求错误消息时,这会显示 5 秒钟,并且在这 5 秒钟时间内其他所有显示错误消息的请求都会被弃用。When a caller asks for an error message, it will be shown for 5 seconds and all other requests for showing an error message in that 5 seconds are dropped. 5 秒钟过后,其他调用方就有机会显示错误消息。Once 5 seconds has passed, then the opportunity arises for another caller to show an error message. 我们禁止任何调用方堵塞错误通道。We prohibit any caller from jamming the error channel.

指导和错误消息如下所示。Guidance and error messages are as follows. 设备名称是配套设备应用作为 ShowNotificationMessageAsync 的一部分传递的参数。Device name is a parameter passed by the companion device app as part of ShowNotificationMessageAsync.

指导Guidance

  • “轻扫或按空格键以使用设备名称登录。”"Swipe up or press space bar to sign in with device name."
  • “正在设置配套设备。"Setting up your companion device. 请等待或使用其他登录选项。”Please wait or use another sign-in option."
  • “点击 NFC 读卡器的设备名称以登录。”"Tap device name to the NFC reader to sign in."
  • “查找设备名称...”"Looking for device name ..."
  • “将设备名称插入 USB 端口以登录。”"Plug device name into a USB port to sign in."

错误Errors

  • “有关登录说明,请参阅设备名称。”"See device name for sign-in instructions."
  • “打开蓝牙以使用设备名称登录。”"Turn on Bluetooth to use device name to sign in."
  • “打开 NFC 以使用设备名称登录。”"Turn on NFC to use device name to sign in."
  • “连接到 WLAN 网络以使用设备名称登录。”"Connect to a Wi-Fi network to use device name to sign in."
  • “再次点击设备名称。”"Tap device name again."
  • “你的企业阻止使用设备名称登录。"Your enterprise prevents sign in with device name. 请使用其他登录选项。”Use another sign-in option."
  • “点击设备名称以登录。”"Tap device name to sign in."
  • “将你的手指放在设备名称上以登录。”"Rest your finger on device name to sign in."
  • “用手指在设备名称上轻扫以登录。”"Swipe your finger on device name to sign in."
  • “无法使用设备名称登录。"Couldn’t sign in with device name. 请使用其他登录选项。”Use another sign-in option."
  • “出现了一些问题。"Something went wrong. 请使用其他登录选项,然后再次设置设备名称。”Use another sign-in option, and then set up device name again."
  • “再试一次。”"Try again."
  • “在设备名称中说出你的口令密码。”"Say your Spoken Passphrase into device name."
  • “准备好使用设备名称登录。”"Ready to sign in with device name."
  • “请先使用其他登录选项,然后再使用设备名称登录。”"Use another sign-in option first, then you can use device name to sign in."

枚举已注册的设备Enumerating registered devices

Windows Hello 配套设备应用可通过 FindAllRegisteredDeviceInfoAsync 调用来枚举注册的配套设备列表。The Windows Hello companion device app can enumerate the list of registered companion devices via FindAllRegisteredDeviceInfoAsync call. 此 API 支持两种由枚举 SecondaryAuthenticationFactorDeviceFindScope 定义的查询类型:This API supports two query types defined via enum SecondaryAuthenticationFactorDeviceFindScope:

{
    User = 0,
    AllUsers,
}

第一个作用域为登录的用户返回设备列表。The first scope returns the list of devices for the logged on user. 第二个作用域在该电脑上为所有用户返回该列表。The second one returns the list for all users on that PC. 第一个作用域必须在注销时使用,以避免注销其他用户的 Windows Hello 配套设备。The first scope must be used at un-registration time to avoid un-registering another user's Windows Hello companion device. 第二个作用域必须在身份验证或注册时使用:在注册时,此枚举可帮助应用避免尝试注册相同的 Windows Hello 配套设备两次。The second one must be used at authentication or registration time: at registration time, this enumeration can help the app avoid trying to register the same Windows Hello companion device twice.

请注意,即使应用不会执行此检查,电脑也会这样做,将拒绝多次注册相同的 Windows Hello 配套设备。Note that even if the app does not perform this check, the PC does and will reject the same Windows Hello companion device from being registered more than once. 在进行身份验证时,使用 AllUsers 作用域可帮助 Windows Hello 配套设备应用支持切换用户流:当用户 B 登录时用户 A 也登录(这要求两个用户都安装了 Windows Hello 配套设备应用,并且用户 A 已将配套设备注册到了电脑且电脑正显示锁屏界面(或登录屏幕))。At authentication time, using the AllUsers scope helps the Windows Hello companion device app support switch user flow: log on user A when user B is logged in (this requires that both users have installed the Windows Hello companion device app and user A has registered their companion devices with the PC and the PC is sitting on lock screen (or logon screen)).

安全要求Security requirements

配套身份验证服务提供以下安全保护。The Companion Authentication Service provides the following security protections.

  • 在 Windows 10 桌面版设备上作为媒介用户或应用容器运行的恶意软件无法在电脑上以静默方式使用 Windows Hello 配套设备访问用户凭据密钥(存储为 Windows Hello 的一部分)。Malware on a Windows 10 desktop device running as a medium user or app container cannot use the Windows Hello companion device to access user credential keys (stored as part of Windows Hello) on a PC silently.
  • 使用 Windows 10 桌面版设备的恶意用户无法使用属于该 Windows 10 桌面版设备上的其他用户的 Windows Hello 配套设备静默访问其用户凭据密钥(在相同的 Windows 10 桌面版设备上)。A malicious user on a Windows 10 desktop device cannot use the Windows Hello companion device that belongs to another user on that Windows 10 desktop device to get silent access to his user credential keys (on the same Windows 10 desktop device).
  • Windows Hello 配套设备上的恶意软件无法在 Windows 10 桌面版设备上静默访问用户凭据密钥,包括利用专为 Windows Hello 配套设备框架开发的功能或代码。Malware on the Windows Hello companion device cannot silently get access to user credential keys on a Windows 10 desktop device, including leveraging functionality or code developed specifically for the Windows Hello companion device framework.
  • 恶意用户无法通过捕获 Windows Hello 配套设备和 Windows 10 桌面版设备之间的通信并在以后重播它,来解锁 Windows 10 桌面版设备。A malicious user cannot unlock a Windows 10 desktop device by capturing traffic between the Windows Hello companion device and the Windows 10 desktop device and replaying it later. 在协议中使用 nonce、authkey 和 HMAC 可保证防止重播攻击。Usage of nonce, authkey, and HMAC in our protocol guarantees protection against a replay attack.
  • 恶意电脑上的恶意软件或恶意用户无法使用 Windows Hello 配套设备访问真实的用户电脑。Malware or a malicious user on a rouge PC cannot use Windows Hello companion device to get access to honest user PC. 这通过在协议中使用 authkey 和 HMAC 相互验证配套身份验证服务和 Windows Hello 配套设备来实现。This is achieved through mutual authentication between Companion Authentication Service and Windows Hello companion device through usage of authkey and HMAC in our protocol.

实现上述枚举的安全保护的关键是保护 HMAC 密钥不受未经授权的访问,并验证用户存在。The key to achieve the security protections enumerated above is to protect HMAC keys from unauthorized access and also verifying user presence. 更具体地说,它必须满足以下要求:More specifically, it must satisfy these requirements:

  • 防止克隆 Windows Hello 配套设备Provide protection against cloning the Windows Hello companion device
  • 防止在注册期间将 HMAC 密钥发送到电脑时窃听Provide protection against eavesdropping when sending HMAC keys at registration time to the PC
  • 确保用户存在信号可用Make sure that user presence signal is available