REST API上的用户注册/身份验证流程

方法

我知道这不是第一次在StackOverflow中处理该主题,但是,我有一些我找不到答案的问题,或者其他问题有相反的答案。

我正在做一个相当简单的REST API(Silex-PHP),最初仅由一个SPA(主干应用程序)使用。我不想评论此问题中的所有几种身份验证方法,因为该主题已经在SO上完全介绍了。我将基本上为每个用户创建一个令牌,并且该令牌将附加到需要SPA进行身份验证的每个请求中。所有SPA服务器事务将在HTTPS下运行。目前,我的决定是令牌不会过期。每个会话的过期令牌/令牌不符合REST的无状态性,对吗?我知道安全性还有很大的改进空间,但这是我目前的范围。

我有一个令牌模型,因此在数据库中有一个表,其中包含FK到user_id的令牌。我的意思是令牌不是我的用户模型的一部分。

寄存器

我有一个POST / users(无需身份验证),它在数据库中创建一个用户并返回新用户。这符合一个请求一个资源规则。但是,这给我带来了一些疑问:

  • 我的想法是,在创建一个新用户,为该用户创建一个新令牌,立即将其与Response一起返回时,从而改进了UX。用户将立即能够开始使用Web应用程序。但是,为此类响应返回令牌将破坏仅返回资源的规则。我应该一起提出两个请求吗?一个是创建用户,另一个是检索令牌,而无需用户重新输入凭据?

  • 如果我决定与用户一起返回令牌,那么我相信POST / users对于API使用者会造成混淆,然后出现类似POST / auth / register的信息。再一次,我不喜欢这个想法,因为它涉及一个动词。我真的很喜欢这个答案提供的简单性但是再一次,我需要一起执行两个请求,一个POST / users和一个POST / tokens。同时执行两个请求是多么的错误,而且,如果两个请求一起发送,我将如何准确发送要附加到特定用户的令牌的相关信息?

现在,我的流程如下所示:

1. Register form makes a POST /users request
2. Server creates a new user and a new token, returns both in the response (break REST rule)
3. Client now attaches token to every Request that needs Authorization

令牌永不过期,从而保持REST无状态。

电子邮件验证

当前的大多数Web应用程序都需要在不破坏用户体验的情况下进行电子邮件验证,即用户可以在注册后立即使用Web应用程序。另一方面,如果我按照上述建议将令牌与注册请求一起返回,则用户无需验证电子邮件即可立即访问每个资源。

通常,我会执行以下工作流程:

1. Register form sends POST /users request.
2. Server creates a new user with validated_email set to false and stores an email_validation_token. Additionally, the server sends an email generating an URL that contains the email_validation_token. 
3. The user clicks on the URL that makes a request: For example POST /users/email_validation/{email_validation_token}
4. Server validates email, sets validated_email to true, generates a token and returns it in the response, redirecting the user to his home page at the same time.

这看起来过于复杂,并且完全破坏了UX。你怎么样了?

登录

这很简单,因为现在我是用这种方式做的,所以如果出错,请纠正我:

1. User fills a log in form which makes a request to POST /login sending Basic Auth credentials.
2. Server checks Basic Auth credentials and returns token for the given user.
3. Web app attached the given token to every future request.

login是一个动词,因此违反了REST规则,尽管每个人似乎都同意这样做。

登出

为什么每个人似乎都需要/ auth / logout端点?从我的角度来看,在Web应用程序中单击“注销”基本上应该从应用程序中删除令牌,而不是在其他请求中发送令牌。服务器对此不起作用。

由于可能会将令牌保留在localStorage中,以防止在可能的页面刷新时丢失令牌,因此注销也将意味着从localStorage中删除令牌。但这仍然不会影响服务器。我了解需要POST / logout的人基本上都在使用会话令牌,这再次打破了REST的无状态性。

记得我

我了解记住我基本上是指在我的情况下是否将返回的令牌保存到localStorage。这是正确的吗?

如果您建议进一步阅读该主题,我将非常感激。谢谢!

翻转

寄存器

每个会话的过期令牌/令牌不符合REST的无状态性,对吗?

不,这没有错。许多HTTP身份验证方案确实具有过期令牌。OREST2在REST服务中非常流行,许多OAuth2实现强制客户端不时刷新访问令牌。

我的想法是,在创建一个新用户,为该用户创建一个新令牌,立即将其与Response一起返回时,从而改进了UX。用户将立即能够开始使用Web应用程序。但是,为此类响应返回令牌将破坏仅返回资源的规则。我应该一起提出两个请求吗?一个是创建用户,另一个是检索令牌,而无需用户重新输入凭据?

通常,如果您遵循REST最佳实践创建新资源,则不会返回任何信息来响应这样的POST。这样做会使调用更像RPC,因此在这里我同意您的观点……它不是完全RESTful的。我将为此提供两种解决方案:

  1. 忽略这一点,打破最佳实践。在这种情况下,这可能是最好的选择,最好是做一些事(经过仔细考虑),以使它们更加有意义。
  2. 如果您想要更RESTful,我将提供另一种选择。

假设您要使用OAuth2(这不是一个坏主意!)。由于多种原因,OAuth2 API并不是真正的RESTful。我想最好还是使用定义良好的身份验证API,而不是为了获得RESTful而滚动自己的身份验证API。

这仍然给您带来了在API上创建用户的问题,并响应此(POST)调用,返回了可用作访问/刷新令牌的秘密。

我的替代方法如下:

您无需拥有用户即可开始会话

相反,您可以做的是创建用户之前启动会话这样可以保证在以后的通话中,您都知道自己正在与同一个客户通话。

如果您开始OAuth2流程并收到访问/刷新令牌,则只需在上执行经过身份验证的POST请求即可/users这意味着您的系统需要知道两种经过身份验证的用户:

  1. 使用用户名/密码(`grant_type = passsword1)登录的用户。
  2. “匿名”登录并打算在事实之后创建用户的用户。grant_type = client_credentials)。

创建用户后,您可以为新创建的用户实体分配以前的匿名会话,因此创建后无需进行任何访问/刷新令牌交换。

电子邮件验证

您对以下两个方面的建议:

  • 在电子邮件验证完成之前,阻止用户使用该应用程序。
  • 允许用户立即使用该应用程序

由应用程序完成。哪一个更合适,实际上取决于您的应用程序以及最适合您的应用程序。用户开始使用他们不拥有的电子邮件帐户是否有与之相关的风险?如果否,那么允许用户立即进入就可以了。

这是您不希望执行此操作的示例:如果系统的其他成员使用该电子邮件地址将用户添加为朋友,则该电子邮件地址是一种身份。如果您不强迫用户验证其电子邮件,则意味着我可以代表具有不同电子邮件地址的某人行事。这类似于能够接收邀请等。这是攻击媒介吗?然后,您可能需要考虑在验证电子邮件之前阻止用户使用该应用程序。

您可能还考虑只阻止应用程序中电子邮件地址可能敏感的某些功能。在上一个示例中,您可以阻止人们在验证电子邮件之前看到其他用户的邀请。

这里没有正确的答案,这仅取决于您打算如何使用电子邮件地址。

登录

请只使用OAuth2。您描述的流程已经非常接近OAuth2的工作方式。实际使用OAuth2更进一步这非常好,一旦您克服了理解协议的最初障碍,就会发现它比您想象的要容易得多,并且只需实现您的API特别需要的位就相当简单。

大多数PHP OAuth2服务器实现都不是很好。他们做得太多,很难整合。自己动手并不难,而且您已经接近建立类似的东西了。

登出

您可能需要注销端点的两个原因是:

  1. 如果您使用基于cookie /会话的身份验证,并且想告诉服务器忘记会话。听起来这对您来说不是问题。
  2. 如果要告诉服务器使访问/刷新令牌更早过期。是的,您可以将它们从本地存储中删除,这可能就足够了。强迫它们在服务器端过期可能会给您一点额外的信心。如果有人能够MITM您的浏览器并且现在可以访问您的令牌怎么办?我可能想快速注销并使所有现有令牌到期。这是一个极端的案例,我个人从未做过,但这可能就是您想要它的原因。

记得我

是的,用本地存储实现“记住我”听起来是个好主意。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

WP REST API - 无需身份验证的用户注册

REST API上的CakePHP身份验证

Vue.js + REST API中的身份验证流程

REST API身份验证

Jersey REST服务上的用户身份验证

REST api项目的用户身份验证方法

了解使用Android和Rest API的OneDrive中的身份验证流程

Drools JBPM 流程 - 对 SSL 身份验证的 API 进行 REST 调用

WP REST API和“只有经过身份验证的用户才能访问REST API”

CAMUNDA API REST身份验证

密钥库身份验证(REST API)

Azure WVD Rest API 身份验证

REST API基于令牌的身份验证

TFS 2015 REST API身份验证

使用 Windows 身份验证的 REST API

基于令牌的REST API身份验证

Spring rest api绕过身份验证

身份验证提供者从Spring Security通过ReST API调用对用户进行身份验证

Django Rest API:使用令牌身份验证将当前用户添加到用户字段

集成Azure AD以进行用户身份验证,并使用REST API将数据存储在用户的一驱动器上

无需用户身份验证即可保护REST Api的最佳方法

Rest API:客户端授权和最终用户身份验证

Django - 让用户登录身份验证检查每个 REST API 调用

没有用户身份验证的安全REST API(无凭据)

R - Twitter - OAuth - REST API - 用户无法通过身份验证

对eXist-db中的REST API使用经过身份验证的会话/用户

DocuSign:可以检测当前通过身份验证的用户是否无法通过REST API查看信封

来自用户登录的 Firestore ID 令牌无法在 REST API 调用中进行身份验证

OpenID Connect-使用JWT通过REST API进行身份验证的Javascript应用程序的隐式流程