使用Laravel API实现OAuth 2.0身份验证


Implementing OAuth 2.0 authentication with a Laravel API

我目前正在构建一个web应用程序,它是一个AngularJS前端,与使用Laravel构建的RESTful API进行通信。我正在取得良好的进展,但发现很难弄清楚如何处理用户身份验证。

有人建议我应该使用OAuth进行身份验证,我决定使用它,因为它对我来说也是一次学习经验。我用来处理这个的包是oauth2-server-laravel。

基本的用户故事是用户可以为应用程序注册他们的用户名/密码组合,然后他们使用相同的用户名和密码登录到应用程序。它们只通过用户名和密码进行身份验证,而不需要任何客户端秘密。登录后,应该给他们一个访问令牌,该令牌将与未来的每个请求一起发送,以便在不同的API端点上对他们进行身份验证。

OAuth2库有一个"密码流"授予类型,这似乎是我需要的,但它也需要client_idclient_secret参数,这是我不想要的。请求URI是这样的:

POST https://www.example.com/oauth/access_token?
grant_type=password&
client_id=the_client_id&
client_secret=the_client_secret&
username=the_username&
password=the_password&
scope=scope1,scope2&
state=123456789

但是我想要的只是:

POST https://www.example.com/oauth/access_token?
grant_type=password&
username=the_username&
password=the_password

我要如何提供一个客户端ID和一个用户的秘密,尚未进行身份验证?

我是否可以使用不同的授权,或者我想要实现的目标根本不适合OAuth ?

考虑到,client idclient secret不是你必须强迫最终用户传递的参数。它们是静态的,在/中为你的客户端应用(在这里是angular应用)定义。

你所需要做的就是在oauth_clients表中为你的主应用程序创建一条记录,并在oauth_scopes表中创建一个具有完全访问权限的范围,并在请求令牌时发送此值。

事实上,这就是全部。

另外,在构建纯js应用程序的情况下,你可能要考虑使用隐式授权流,因为在js应用程序中存储客户端秘密和刷新令牌是不安全的。在最终产品中使用隐式授权可能看起来像soundcloud上的登录窗口,并且更安全,因为令牌是在服务器端获得的,而不会暴露客户端的秘密。

如果您仍然希望使用密码流,另一种方法是创建一个代理来刷新令牌。代理可以将刷新令牌隐藏在加密的http-only cookie中,并且js-app不会向api请求新的令牌,而是向代理请求。代理从加密的cookie中读取刷新令牌,向api请求新的令牌并返回它。因此刷新令牌永远不会公开。如果您将令牌ttl设置为一小时,那么在正常应用程序的情况下窃取令牌将是相当"无意义的*",并且窃取刷新令牌将是"不可能的*"。

*当然,如果有人真的想要,他可能会破解它。

是的,我知道这一切看起来有点hack -模态窗口登录,代理等。但也搜索这个话题,我找不到任何更好的和更优雅的方式来做到这一点。我认为,如果你想要一个基于令牌的身份验证,这仍然是所有js-app都必须解决的问题。

您在OAuth规范中遗漏了一些东西。当使用OAuth v2的密码方法请求访问令牌时,client_idclient_secret非常重要。事实上,它们对于提供访问令牌的每个方法都很重要。它们标识了执行请求的应用程序或服务器。

例如,假设你有你的API, 2个移动应用程序和另一个服务器用你的API执行一些任务。您将使用自己的client_idclient_secret创建3个客户端。如果你的应用程序有不同的访问级别(它们在OAuth v2中被称为scopes),对应于其他服务器的client_id将能够调用需要admin作用域的API函数,而如果你定义了这样的作用域,你的移动应用程序将只能调用需要basic作用域的API函数。

如果你的API在未来发展,这是非常必要的。另一个例子,假设你给了一个API密钥(一对client_idclient_secret)给你的一个朋友,他用你的API构建了一个不错的移动应用程序。如果有一天他开始用你的API做一些调皮的事情,你很难阻止他。然而,如果您遵循OAuth v2原则,您可以直接删除他的密钥对。

OAuth v2不是一件容易理解的事情,在开发API之前花点时间阅读规范和好的教程。

一些有用的链接:

  • 官方RFC: https://www.rfc-editor.org/rfc/rfc6749
  • Tutsplus教程:http://code.tutsplus.com/articles/oauth-20-the-good-the-bad-the-ugly--net-33216

只是添加一点到plunntic的优秀答案:记住"客户端"与"用户"无关,所以当我使用密码流时,我只是将client_id和client_secret定义为AngularJS应用程序上的常量,以告诉api后端:嘿,这是用于请求令牌的浏览器应用程序