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

Posted

技术标签:

【中文标题】使用 Laravel API 实现 OAuth 2.0 身份验证【英文标题】:Implementing OAuth 2.0 authentication with a Laravel API 【发布时间】:2014-07-28 22:35:49 【问题描述】:

我目前正在构建一个 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?

【问题讨论】:

【参考方案1】:

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

【讨论】:

链接现在是404ing。 谢谢jezmck。我已经更新了链接。这篇文章现在已经很老了,并且有像 Passport 这样的重大发展,使这更容易。【参考方案2】:

请注意,client idclient secret 不是您必须强制最终用户传递的参数。它们是静态的,并且在您的客户端应用程序(在本例中为 Angular 应用程序)中/为您定义。

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

事实上就是这样。

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

如果您仍想使用密码流,另一种方法是创建用于刷新令牌的代理。代理可以将您的刷新令牌隐藏在加密的 http-only cookie 中,并且您的 js-app 不会向您的 api 询问新令牌,而是向代理询问。代理从加密的 cookie 中读取刷新令牌,向 api 请求新令牌并返回它。所以刷新令牌永远不会暴露。如果您将令牌 ttl 设置为一个小时,那么在正常应用程序的情况下窃取令牌将是“毫无意义*”,而窃取刷新令牌将是“不可能*”。

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

是的,我知道这一切看起来有点 hacky - 用于登录、代理等的模式窗口。但在搜索这个主题时,我找不到任何更好、更优雅的方法。如果您想要基于令牌的身份验证,我认为所有 js-apps 都必须处理这一点。

【讨论】:

【参考方案3】:

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

例如,假设您有自己的 API、2 个移动应用程序和另一个使用您的 API 执行某些任务的服务器。您将创建 3 个具有自己的 client_idclient_secret 的客户端。如果您的应用程序具有各种访问级别(在 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

【讨论】:

以上是关于使用 Laravel API 实现 OAuth 2.0 身份验证的主要内容,如果未能解决你的问题,请参考以下文章

将 OAuth 2.0 与自定义 API 集成的概述(用 Laravel 编写)

Laravel 5.1:如何使用 oauth2-server-laravel?

LARAVEL WEB API 中的 JWT 或 OAuth 或两者

Oauth2-server-laravel 自定义消息响应

如何注销并撤销 laravel 8 api 中的所有 oauth 令牌?

Laravel 5.4建站06--API 认证系统 Passport