OAuth2中的“资源所有者密码凭证”安全吗?

因此,我正在使用slim/slimleague/oauth2-server开发 API 来管理 OAuth2 连接。 OAuth2很有用,因为我将需要在服务之间使用 Client Credentials授予

然后,我还正在使用 React Native 开发一个混合应用程序。此应用程序将要求用户使用电子邮件和密码或与其他服务(例如Facebook,Google,Twitter等)连接来登录。

对于这种情况下要使用的OAuth2流,我感到困惑。网上有很多文章说资源所有者密码凭据不再安全,我们应该改用带有PKCE的身份验证代码

但是我无法发现或理解如何在第一方应用程序中通过PKCE应用身份验证代码,因为所有有关您的文档都需要使用浏览器在redirect_uri中获取身份验证代码。

我想象中的流程是这样的:

  1. 用户打开应用,然后插入您的凭据usernamepassword
  2. 此屏幕将连接到发送/request_token的API { 'grant_type': 'password','username': username,'password': password,'client_id': CLIENT_ID } URI,认为它是我们无法发送client_secret的公共应用;
  3. API会验证凭据并返回诸如{ "access_token": access_token,"token_type": "JWT","expires_in": LIFE_SPAN }之类的数据,这里我们将使用 JWT 来基于access_token来使public/private key脱颖而出;
  4. 身份验证完成后,应用将在access_token处于活动状态时对其进行存储,并且当其到期时,将流向refresh_token

我的问题:安全吗? Scott Brady did some "aggressive" article talking it's NEVER safe

这些应用如何进行?例如,当我使用Instagram应用程序时,他们拥有该应用程序和API,因此我不需要用户体验流程中的浏览器。现代应用程序是否使用“资源所有者密码凭据”或“带有PKCE的身份验证代码”?可以避免在使用“带有PKCE的身份验证代码”时在流程中插入浏览器吗?

[EDIT] 可能的解决方案

正如Gary Archer所说:“建议使用PKCE进行身份验证代码流-以及通过系统浏览器登录”,但我们并不是在谈论授予访问用户数据或第三方应用程序的权限。

作为设计师,我不同意由同一API所有者拥有的第一方应用程序中的登录要求使用浏览器,这不是我们想要的用户体验。还有我们看到的所有应用程序,例如Instagram,Facebook,Uber ...我们只需输入您的用户名和密码,即可访问您的帐户。

我要做的是使用PKCE创建一个自定义版本的身份验证代码,并删除了required_uri

[EDIT:2] 新流程

经过大量搜索,我发现了一些我认为很有趣的答案。如上所述,我从流程中删除了redirect_url。看:

  1. 流程在用户提供您的凭据时从登录屏幕开始;
  2. 客户端生成一个code_verifier,然后将code_verifier散列到code_challenge,并使用以下参数将其发送到授权服务器:

    • response_type=code:表示您的服务器希望接收授权码。
    • client_id=xxxx:客户端ID。
    • client_integrity=xxxx:第一方应用的应用完整性检查。
    • code_challenge=xxxx:如上所述生成的代码质询。
    • code_challenge_method=S256:纯文本或S256,具体取决于质询是纯验证符字符串还是字符串的SHA256哈希。如果省略此参数,则服务器将采用普通格式。
    • username=xxxx:要验证的用户名。
    • password=xxxx:密码的哈希版本。
    • state=xxxx:由您的应用程序生成的随机字符串(CSRF保护)。
  3. 授权服务器将验证用户身份验证,存储code_challenge并返回带有authorization_code的{​​{1}};

  4. 客户端收到client_tokenaauthorization_code后,将保存client_token,并立即使用以下参数将client_token发送回授权服务器:

    • authorization_code:指定此令牌请求的授予类型。
    • grant_type=authorization_code:客户端将发送它获得的授权代码。
    • code=xxxx:客户端ID。
    • client_id=xxxx:客户端最初在授权请求之前生成的PKCE请求的代码验证程序。
  5. 授权服务器将验证所有数据,如果一切正确,将返回code_verifier=xxxx;

  6. 客户端将使用access_token设置授权标头,并始终向每个请求发送access_token,只有两个值都正确时,才会接受它;
  7. 如果client_token过期,则客户端将请求刷新access_token并获取一个新请求。

现在,我将把这种逻辑重现为PHP语言。如果一切顺利,我希望一切顺利,我将以明确的答案回来。

[编辑] 说明

我正在使用 OAuth2 来连接您的第三方帐户(Google,Facebook等)。但是用户也可以登录到我的数据库中的本地帐户。在这种情况下,用户根本不需要授予任何权限。因此,将用户发送到浏览器对他进行登录没有任何意义。

在这种情况下,我想知道本地帐户是否可以使用资源所有者密码凭据,或者使用PKCE的身份验证代码更安全(我们已经得出结论,这是更好的选择Approuch)。但是带有PKCE的身份验证代码需要access_token,我是否需要使用此重定向将用户登录到不需要授予访问权限的本地帐户?

zhaopingg 回答:OAuth2中的“资源所有者密码凭证”安全吗?

推荐使用PKCE的

Auth Code流-以及通过系统浏览器登录。另外,建议使用AppAuth模式。 https://curity.io/resources/develop/sso/sso-for-mobile-apps-with-openid-connect/

尽管实现起来很棘手,而且很耗时-所以您需要考虑一下-有时使用便宜的选项就足够了。取决于公开数据的敏感性。

如果有帮助,请参见以下有关我的Android演示应用程序的注意事项,该应用程序还着重于可用性-以及可运行的代码示例的链接: https://authguidance.com/2019/09/13/android-code-sample-overview/

,

首先,不要仅仅因为需要在应用程序中采用OAuth授予就发明它。这会使维护变得复杂。

在您的情况下,您需要提供社交登录名(例如:-通过Google,facebook登录)。当然,这是必须支持的一种理想功能。但这并不限制您通过自定义注册过程获取最终用户凭据。造成这种情况的原因很多,例如,并非所有人都使用社交媒体或Google帐户。与某些人相比,某些人更喜欢注册而不是共享其他服务的用户标识符(是的,这是社交登录的另一端)。

所以,继续,提供社交登录。首次通过外部身份服务器(例如:-Google)登录时,存储用户标识符。而且,还要进行良好的旧注册,并输入密码和电子邮件。

,

那我们走吧。经过大量研究,我发现了一些我将应用并且可能正确工作的方法。因此,首先是挑战:

  • 您绝不能信任在客户端运行的客户端。令人担忧的是,您的应用程序可能会被分解,修改,用户设备可能带有恶意软件或中间人攻击(MITM)可能会造成连接...
  • 即使使用OAuth2,API服务器也只能识别 WHO 正在访问资源,而不能识别 Who 正在访问什么。因此,任何敏感信息都是危险的,任何人都可以窃取并使用它。
  • 资源所有者密码凭证是OAuth2协议的一部分,用于授权资源所有者访问您的资源。因此,它不属于身份验证过程的一部分,如果您将其视为那样,将会毁灭您的生活;
  • 通过使用ROPC授予类型,无法知道资源所有者是否确实在发出该请求,是什么使钓鱼攻击“容易”。提醒您“您知道,而不是什么”。最后,无论假设用户身份如何,这种授予方式都很容易;
  • 此授予类型也与OAuth2提议相反,因为OAuth试图避免使用密码来访问资源。那就是为什么很多人说不使用它的原因;
  • 为加强起见,重要的是要强调ROPC并不对用户进行身份验证,而只是授权用户访问资源服务器。
  • 是的,ROPC允许刷新令牌,但是有两个问题:首先,客户端每次需要获取新令牌时都需要重新提供凭据;其次,如果使用长期访问代码,则事情会变得更加危险。

为防止恶意行为随意使用用户凭据,有访问令牌。它们替换了密码,需要在短时间内刷新。这就是为什么它们比HTTP基本身份验证好得多的原因。

这就是为什么建议在现代应用中使用带有PKCE的身份验证代码的原因,它提供了使用OAuth2协议的所有功能和优势。但是,这是一个漫长的讨论,甚至是开发人员社区面临的问题:

要获取验证码,某些用户需要在浏览器中进行登录,授予访问权限,重定向回客户端,不久,客户端将收到用于交换访问令牌的代码。

此方案很好,并且需要可用于第三方应用。但是,如果它是第一方应用程序怎么办?当您拥有包含用户数据的数据库并且拥有“受信任”应用程序时,重定向用户没有任何意义。对吧?

此刻,我的问题是:如何在没有重定向用户的情况下使用AuthCode(PKCE)流?同样,重要的是要强调,谈论OAuth2协议始终与“授予客户端访问资源服务器”(授权而不是身份验证)相同。

真正的问题是:为什么授权码根本需要重定向?然后,我给出了以下答案:

此流程需要了解客户端凭据和用户共识,以转回授权码。

这就是为什么我的编辑错误。 OAuth2协议不需要任何更改(抱歉,我认为与众不同)。因此,OAuth2所需要的是位于您层上方的授权中介。因此,授权代码不是将返回给客户端,而是返回给最终将返回给客户端的授权中介器。有道理吗?

它将如何工作?好吧,将需要4个不同的“核心”:

  1. 身份验证服务器:将负责验证用户凭据和客户端身份。主要目的是证明“ 是用户,并且连接要获取身份验证”;
  2. 授权中介器(位于OAuth2上方一层):将验证客户端的唯一身份,以确保客户端/用户“知道”并可以获得访问令牌;
  3. 授权服务器:是OAuth2实现的一部分,没有任何变化。将授权客户端获取您的授权码,访问令牌刷新令牌;
  4. 资源服务器:将允许通过访问令牌访问资源。

然后,我们可以考虑使用安全技术:

  1. API密钥:每个应用程序(客户端)将拥有自己的API密钥,并具有与这些密钥关联的权限范围。通过使用它,您可以收集有关API使用情况的基本统计信息。大多数API服务都使用统计信息来对每个应用程序实施速率限制,以提供不同的服务层或拒绝可疑的高频调用模式;
  2. 相互SSL身份验证:通过使用这种技术,客户端和服务器交换并验证彼此的公钥。一旦密钥被验证,客户端和服务器就协商共享密钥,消息认证码(MAC)和加密算法;
  3. HMAC :API密钥将分为ID和共享密钥。然后,和以前一样,ID与每个HTTP请求一起传递,但是共享机密用于对传输中的信息进行签名,验证和/或加密。客户端和服务器将使用诸如HMAC SHA-256之类的算法交换共享密钥;
  4. 保护代码应用程序:使用代码混淆器将使从应用程序定位和提取敏感数据变得更加困难,例如秘密共享,api密钥,公共密钥...
  5. 处理用户凭据:提供一种简单的方法来登录用户并证明您的身份。插入有效凭据后,服务器可以返回用户令牌(JWT)并以此模拟用户会话。

让我们看看流程:

  • 第一部分:验证用户和客户端;

    1. 在客户端将用户凭据(例如{ email,mobile_number,hash ( password ),verification_method })发送到Authentication Server路由/login之后,用户将键入您的凭据,并被要求使用您的电子邮件或手机号码来证明您的身份;
    2. Authentication Server将验证用户凭据并发送一次密码,以确认您的身份(用户选择的电子邮件或手机号码);
    3. 然后,用户将插入收到的OTP,客户端将发送回包括验证方法(例如/login-otp)的Authentication Server路由{ otp,verification_method }
    4. 最后,身份验证服务器将返回一个{ hash ( shared_secret ) }以便很快使用。
  • 第二部分:授权API访问;

    1. 当收到shared_secret客户端将安全存储在移动应用程序中时,它将使用PKCE与/auth调用{ response_type,client_id,scope,state,code_challenge,code_challenge_method }来请求授权码,授权服务器将验证凭据并返回授权没有重定向的代码;
    2. 稍后,客户端会将接收到的代码交换为访问/token的访问令牌,但是它将需要发送一些额外的数据:{ payload: { grant_type,code,code_verifier },timestamp,hash ( some_user_data + timestamp + shared_secret ) };
    3. 授权中介者将收到此请求并验证尝试生成用户生成的相同哈希值。并将所有数据重定向到授权服务器,该服务器将验证client_idcodecode_verifier并使用访问令牌进行响应;
    4. 这个新的access_token将返回到授权中介器,然后再返回给客户端以授予对API资源的访问权限。
  • 第三部分:访问资源服务器;

    1. 客户端每次需要发送对API /api的调用,其中包含Authorization标头和带有{ timestamp,hash ( some_user_data + timestamp + shared_secret ) }的一些额外数据;
    2. 授权中介器将验证shared_secret哈希,调用资源服务器验证access_token并返回数据。
  • 第四部分:刷新访问令牌;

    1. 访问令牌过期后,客户端将向包含/refresh-token标头和Authorization的一些额外数据的{ payload: { grant_type,refresh_token,scope },hash ( some_user_data + timestamp + shared_secret ) }发送呼叫;
    2. 授权中介器将验证shared_secret哈希,调用授权服务器并返回新的新令牌访问权限。

此流程的视觉图像:

User App Login Flow

我认为这不是一个完美的策略,但是它用PKCE代替了身份验证代码的资源所有者密码凭证,并提供了一些额外的安全性技术。这比单一且简单的身份验证方法更好,它保留了OAuth2协议,并且使操作变得更难于破坏用户数据。

一些参考和支持:

How do popular apps authenticate user requests from their mobile app to their server?

Why does your mobile app need an API key?

Mobile API Security Techniques

Secure Yet Simple Authentication System for Mobile Applications: Shared Secret Based Hash Authentication

本文链接:https://www.f2er.com/3168673.html

大家都在问