我是堆栈溢出的常客,但这是我的第一个问题。
我正在使用OAuth2规范开发授权服务器。我只是在使用密码流时如何确保第一方客户端的真实性。我读了很多论坛,这就是我得到的:
Javascript单页客户端
Alex Bilbie撰写的这篇博客文章指出,要避免client_secret问题,我们应该:
这很简单;通过瘦服务器端组件代理所有API调用。这个组件(我们从这里开始称之为代理) 将验证来自用户会话的ajax请求。访问 并且刷新令牌可以以加密形式存储在cookie中 只有代理可以解密。应用程序客户端凭据 也将被硬编码到代理中,因此它们不是公开的 也可以访问。
但现在这个代理人可以被冒充我的人访问 角应用。然后我从安迪那里看到了这篇博客文章 守场员:How Secure is the OAuth2 Resourc Owner Password Flow for Single Page Apps。他基本上说要依靠CORS来 避免模仿JS客户端。
使用这两种方法保护我的JS应用程序是个好主意吗?
原生应用(桌面和移动设备)
就移动应用而言,我只找到了授权案例 代码和隐式流程。这不是我想要的,重定向 会损害用户体验。所以我对此的想法是:
我将使用ROP流程,然后使用a注册客户端
为此特定安装生成client_id
并附加它
到用户帐户,收到access_token
和a
client_secret
作为回应。由此产生的任何其他令牌请求
客户端必须携带此凭据(因为client_id
是特定的
对于安装,我将能够检查此客户端是否
已经过身份验证)。这样,如果有人使用任何凭证
冒充客户,甚至注册虚假客户,我可以
用于撤销用户和客户端访问的消息。
我知道这可能是过度思考,而且我也知道其中一些事情并不能避免任何事情。我觉得尽我所能来保护我的API是我的工作。
我非常感谢您对此事的看法!我是否真的过度思考?我应该只使用“公共客户”的概念并继续吗?
谢谢大家,编码愉快!
答案 0 :(得分:3)
首先,这个问题不是一个常见的优先级,因为大多数应用程序首先使用网站开发,然后使用API开发。这可能是原因,因为没有人知道如何使用oauth2处理第一个客户端,因为每个人都已经开发了其他方法来执行此操作,仅需要oauth2授予用户访问第三方应用程序的权限。
即使您只为第一个客户端应用程序开发oauth2授权服务器(考虑单个身份验证机制而不是开发许多),您应该尝试开发授权代码或隐式授权类型。您将意识到您需要一种方法来检查用户实际登录的内容。
两种常用方法是:
无论哪种方式,您都需要检查应用程序安全性,用户会话容易受到CSRF的攻击,localStorage很容易受到XSS攻击。有很多文章关于如何保护你的网站,所以我不会在这里提出任何建议,你只需要知道它们存在。
现在您选择了身份验证方法,我们可以开始考虑以下事项:
代理
在我看来,拥有一个过滤所有请求的代理就像是有一扇门,钥匙总是被插入。即使建造门也没用。
但是,对于基于会话的身份验证,它是唯一的方法。允许对Rest API进行会话身份验证将导致CSRF安全问题,因此您需要拥有一个代理层来获取用户会话,从会话中检索访问令牌并向Rest API发出请求,添加Authorization
头。
CORS
使用此方法,您需要将用户访问令牌存储在localStorage中,因为该令牌是直接从Js客户端检索的。
使用CORS,您确定其他网站无法通过浏览器向您的Rest API发出请求。但是你的第一个客户需要公开(即:它没有client_secret
)。
在我的第一个应用程序中,我尝试使用您建议的相同机制来保护身份验证流程。但是,这种类型的机制要求您以独特的方式识别每个用户客户端。这在privacy reasons的iOS中是不可能的,并且有可能在未来的Android版本中会被拒绝。因此,您应该依赖公共客户端,并在本机应用程序代码中仅添加client_id
。
这意味着您的原生应用客户端/您的js客户端可以进行非人格化?
是,并且无法使用oAuth2资源所有者密码凭据授予类型来阻止此情况。
这样做的主要原因是因为oAuth2不用于身份验证,仅用于第三方授权,并且该授权类型仅针对特定的第三方应用程序添加,直接使用用户密码。您可以阅读有关此参数here和here的更多信息。
你仍然需要一种方法来篡改你的用户,我认为使用oAuth2可以达到的最好是Auth0所做的。 从本质上讲,这个Saas使用oAuth2服务器+ OpenID连接来管理您的用户,因此您总是管理您的用户,就像它的第三方应用程序一样,一切正常。
实际上,您可以在this page上看到,对于移动应用程序,他们建议使用基于浏览器的登录表单,因为本机可以通过反编译应用程序的每个人进行非个性化,但是如果将其包装到授权中代码流程工作正常。