电子邮件/密码身份验证
Overview
电子邮件/密码身份验证允许用户使用电子邮件地址进行注册和登录。Atlas App Services 必须先确认用户的电子邮件/密码,然后才能登录。
下图展示登录的流程:
注意
用户电子邮件地址区分大小写。例如,具有电子邮件地址 TestAccount@example.com
的用户无法使用 testaccount@example.com
地址登录。
配置
在左侧导航栏中,单击 Authentication(身份验证)。
在身份验证提供程序列表中,选择 Email/Password 。 在此屏幕中,您可以配置并启用提供商。 使用以下部分来指南您完成此进程。
要使用App Services CLI启用和配置电子邮件/密码身份验证提供者程序,请在/auth/providers.json
中为其定义一个配置对象。
电子邮件/密码提供商配置采用以下形式:
{ "local-userpass": { "name": "local-userpass", "type": "local-userpass", "config": { "autoConfirm": <boolean>, "emailConfirmationUrl": <string>, "confirmEmailSubject": <string>, "runConfirmationFunction": <boolean>, "confirmationFunctionName": <string>, "resetPasswordUrl": <string>, "resetPasswordSubject": <string>, "runResetFunction": <boolean>, "resetFunctionName": <string>, }, "disabled": <boolean> } }
提示
身份验证提供者的 name
始终与其 type
相同。
用户确认
在电子邮件/密码用户进行身份验证之前,您的应用必须注册并确认该用户的新帐户。注册电子邮件/密码用户会创建一个新的用户对象。然后,App Services 会要求对账户进行确认。有如下三种方法来确认新用户账户:
下图展示确认用户的流程:
新用户帐户状态
用户账户可以处于两种状态之一:待处理和已确认。
启动确认进程后,Atlas App Services 将创建一个用户账户并将状态设置为 Pending Confirmation。在这种状态下,用户无法登录。由于该电子邮件地址现已与用户帐户关联,因此无法重新注册同一电子邮箱。
如果账户处于待处理状态,则用户必须在登录前确认其账户。用户确认其账户时,Atlas App Services 会将状态设置为 Confirmed(已确认),用户可以登录。
如果自动确认用户,则创建账户时状态设置为 Confirmed,用户注册后可立即登录。
警告
仅在开发和测试应用时使用自动确认。生产应用程序应始终使用安全的确认流程。
可以在用户界面中或通过 App Services API 查看待处理的用户帐户列表:
在左侧导航栏中的 Data Access 下,单击 App Users。
在用户列表的顶部,选择 Pending 过滤器。
要使用Realm 命令行界面(Realm CLI)查看待处理用户,请使用appservices users list命令并包含--pending
选项。
要使用 Admin API查看待处理的用户,请使用List Users端点。
发送确认电子邮件
使用此确认方法,用户必须在注册后回复电子邮件。该电子邮件包含指向确认 URL 的链接。用户必须在 30 分钟内访问此链接,以确认他们控制了该电子邮件地址。
配置以下设置,以便 App Services 自动发送确认电子邮件:
Email Confirmation URL:每封确认电子邮件中包含的 URL 的基础。App Services 会向此 URL 附加一个唯一的
token
和tokenId
。它们将用作查询参数,以便为每个确认创建唯一链接。要确认用户,请首先从该用户的唯一 URL 中提取这些查询参数。然后,将token
和tokenId
传递给客户端 SDK 的confirmUser
函数。移动应用程序可以直接在应用程序中处理电子邮件确认。 为此,请配置 深层链接 在 Android 或 通用链接 中 在iOS中。
Email Confirmation Subject:App Services 发送的电子邮件的主题行。此值为可选项,如果省略,App Services 会改用默认主题行。自定义电子邮件确认主题最多可包含 256 个字符。
注意
目前,除基本 URL 和标题行之外,无法自定义确认电子邮件。特别是,它们总是来自 mongodb.com
电子邮件地址。
对于生产应用程序,您可以使用确认函数,而不是内置的确认电子邮件方法。确认函数允许您创建完全自定义的电子邮件确认。有关更多信息,请参阅“运行确认函数”。
运行确认函数
您可以在新用户注册时 Run a Confirmation Function(运行确认函数)。App Services 会将确认令牌、令牌 ID 和用户的电子邮件传递给您创建的函数。然后您的函数将执行确认用户所需的逻辑,并返回以下结果对象之一,下文将予以详细说明:
{ status: 'success' }
{ status: 'fail' }
{ status: 'pending' }
通过使用函数,您可以定义自定义逻辑来确认用户。例如,您的函数可能:
从特定域发送自定义确认电子邮件。使用外部服务通过特定模板发送这些内容。
从 MongoDB Atlas 的集合或外部 REST 服务中读取用户权限。
通过电子邮件以外的服务(例如短信)发送确认消息。
该自定义确认函数签名有一个参数。它是包含用户数据和确认令牌的对象。这些字段是:
字段 | 说明 |
---|---|
username | 用户的电子邮件地址。 |
token | 用于确认用户身份的唯一值。调用 SDK 的“确认用户”函数时,您可以使用该值。 |
tokenId | 用于确认用户身份的唯一值。调用 SDK 的“确认用户”函数时,您可以使用该值。 |
自定义用户确认函数会返回一个带有状态字段的对象。下表描述了此字段的潜在值:
状态 | 效果 |
---|---|
success | App Services 确认用户身份,允许用户登录新账户。 |
pending | App Services 会将用户的确认状态更改为 Pending Confirmation 。这不会确认用户的身份或允许登录。客户端应用程序必须调用 SDK 的“确认用户”函数来完成此过程。 |
fail | App Services 不会创建用户帐户。用户只能通过重新注册来重试帐户确认。由于之前的帐户不存在,用户可以重复使用相同的用户名(电子邮件)。 |
用户确认函数的示例如下:
检查提供的电子邮件是否有效。
确认给定的电子邮件地址可以访问特定服务。
向用户发送短信。
如果消息发送成功,则通知 Atlas App Services 创建一个处于“待处理”状态的新帐户。
exports = ({ token, tokenId, username }) => { // Validate the username const isValidEmail = myCustomValidatorService.validate(username); // Check if the user has access to this service const isPrivileged = myCustomAuthorizationService.hasAccess(username) // Send a message to the user so that they can confirm themselves const msgSendSuccessful = isValidEmail && isPrivileged && mySmsService.send(username, token, tokenId) if ( msgSendSuccessful ) { return { status: 'pending' }; } else { return { status: 'fail' }; } }
除非自定义函数自动确认用户,否则您必须提供一种方法让用户在函数触发后完成确认过程。完成其他确认步骤后,调用 SDK 的“确认用户”方法,从而在 Atlas App Services 上完成用户账户创建。
自动确认用户
您可以将提供商配置为 Automatically Confirm Users。选中后,App Services 将在注册后立即确认新的电子邮件/密码用户。
警告
App Services 不会验证自动确认的电子邮件地址。因此,有几个原因可能导致您无法通过电子邮件与这些用户取得联系:
自动确认的用户电子邮件地址可能实际上并不属于该用户。(例如,用户可以注册为
steve.jobs@apple.com
)用户的电子邮件地址甚至可能不是有效的电子邮件地址。(例如,用户可以注册为
my.name@gmail
或asdavaskljj
)
请谨慎使用此选项。在没有有效联系信息的情况下安全地重置用户帐户的密码可能非常困难。
密码重置
电子邮件/密码用户可能会忘记密码并需要重置密码。出于安全原因,应该在完成密码重置之前确认用户的身份。App Services 提供两种方法执行此操作:
确认用户身份后,即可完成密码重置请求。密码重置完成后,用户即可使用新密码登录。
发送密码重置电子邮件
您可以配置该提供商以便Send a Password Reset Email.。当用户请求重置密码时,App Services 会将密码重置 URL 发送到用户的电子邮件地址。该用户必须在 30 分钟内访问此 URL。
配置密码重置电子邮件时,您可以配置以下设置:
Password Reset URL:这是每封密码重置电子邮件中包含的 URL 的基础。App Services 会向此 URL 附加一个唯一的
token
和tokenId
。这些查询参数用于为每次密码重置创建唯一的链接。要重置用户的密码,请从用户的唯一 URL 中提取这些查询参数。将 token 和 tokenId 传递给 Client SDK 的resetPassword
函数。Reset Password Email Subject:App Services 发送的电子邮件的主题行。此值是可选的:如果省略,App Services 会改用默认主题行。自定义密码重置主题最多可包含 256 个字符。
移动应用程序可以直接在应用中处理密码重置。在 Android 中配置深度链接或在 iOS 中配置通用链接。
注意
目前,除了基础 URL 和主题行之外,无法自定义密码重置电子邮件。它们始终来自 mongodb.com
电子邮件地址的情况下尤其如此。
对于生产应用,您可以使用自定义密码重置功能而不是内置的密码重置电子邮件方法。自定义功能允许您构建完全自定义的电子邮件确认,或使用电子邮件以外的方法来确认密码重置请求。
运行密码重置功能
您可以将提供商配置为 Run a Password Reset
Function。您可以为 App Services 定义一个函数,当您在 SDK 中 callResetPasswordFunction()
时,该函数运行。App Services 将用户的电子邮件、所需的新密码、确认令牌和令牌 ID 传递给您创建的函数。然后,在重置密码之前,该函数执行确认用户身份所需的逻辑。
App Services 可以立即重置用户的密码。或者您可以要求客户端应用程序的其他确认。
App Services 函数必须返回一个包含 status
键的对象。键映射到具有以下值之一的字符串,下面将详细说明这些值:
{ status: 'success' }
{ status: 'fail' }
{ status: 'pending' }
警告
Realm SDK 函数callResetPasswordFunction()
未经过身份验证。其密码恢复功能仅适用于无法以其他方式登录帐户的用户。因此,无法将对此函数的任何调用与特定的 App Services 用户关联起来。返回success
状态会将密码永久更改为该函数的password
参数中的新值。因此,返回 success
可能会导致任何用户重置其他应用程序用户的密码。为了安全起见,应该通过可信的通信模式向帐户所有者发送消息并返回pending
。
您可以使用自定义密码重置函数来定义自己的密码重置流程:
使用外部服务,通过特定模板从特定域发送自定义密码重置电子邮件。
与 MongoDB Atlas 集合交互以实施密码重置“冷却期”。这可以防止在特定时间范围内对单个帐户进行过多的密码重置尝试。
通过电子邮件以外的服务发送自定义密码重置消息。
注意
使用密码重置功能与将 App Services 配置为发送密码重置电子邮件是相互排斥的。配置密码重置以使用自定义函数时,在客户端 SDK 中调用 sendResetPasswordEmail()
会返回错误。
自定义密码重置函数签名是可变的:它可接受任意数量的参数。第一个始终是包含用户数据和确认令牌的对象。以下所有参数均为自定义参数。它们作为参数集合传递到客户端 SDK。例如,客户端 SDK 调用:
callResetPasswordFunction("myUsername", "newPassword", ["Security Question Answer 1", "Security Question Answer 2", "securityCode:0510"])
成为密码重置函数的自定义签名:
resetFunc({username, password, token, tokenId, currentPasswordValid}, securityAnswer1, securityAnswer2, securitySMSCode)
在自定义密码重置函数中,必须将对象作为第一个参数传递。下表描述了在此对象中找到的字段:
字段 | 说明 |
---|---|
username | 用户的电子邮件地址。 |
password | 为用户建议的新密码。如果此函数返回成功状态,这就是用户的新密码。 |
token | 用于更新用户密码的唯一值。 |
tokenId | 用于使用 SDK confirmUser 函数确认用户身份的唯一值。 |
currentPasswordValid | 一个布尔值,如果用户请求将其密码更改为现有密码,则该布尔值为 True。 |
自定义密码重置函数必须返回包含 status
字段的对象。这个 status
字段的值可以是:
状态 | 密码重置状态 | SDK 效果 |
---|---|---|
success | App Services 会立即将用户密码更改为提供的 password 参数。仅当您在自定义函数中验证用户的身份时,才返回 success 。您可以通过安全问题或其他安全方式来执行此操作。 | 如果自定义函数调用返回 success ,客户端应用程序就可以将没有错误解释为密码重置成功。用户可以使用新密码登录。 |
pending | App Services 待客户端应用程序执行某些附加操作,完成密码重置。例如,自定义密码重置功能可以通过电子邮件或发送短信到 token 和 tokenId ,验证用户的身份。 | 调用此函数的 SDK 方法不带返回值,因此不会直接处理 pending 情况。 您必须在应用程序中实现自定义逻辑,才能完成密码重置进程。 示例,您可以在客户端中实现深层链接或通用链接来提取token 和tokenId ,然后调用resetPassword 方法完成重置。 |
fail | 什么都没发生。 | 调用自定义密码重置函数时,SDK 将返回的 fail 解释为错误或异常。 |
自定义密码重置函数可能包括与这个示例类似的元素:
exports = ({ token, tokenId, username, password, currentPasswordValid }) => { // check if the username corresponds to a real user const isUser = myCustomValidator.validate(username); // check if the user is attempting to reset their password to their current password if (currentPasswordValid) { myCustomNotifier.sendMessage(username, "Cannot reset password to current password."); return { status: 'fail' }; } // check if the user has requested a password reset too often recently const isNotCoolingDown = myCustomCooldownService.canReset(username, 'myCustomService') // send a message to the user in some way so that the user can confirm themselves const msgSendSuccessful = isUser && isNotCoolingDown && myCustomMsgr.send(username, token, tokenId) if ( msgSendSuccessful ) { return { status: 'pending' }; } else { return { status: 'fail' }; } }
示例
有关使用电子邮件/密码身份验证的注册、登录和密码重置流程的示例,请参阅 Realm 软件开发工具包: