Oauth 我们真的需要客户端密钥来获取PKCE流上的访问令牌吗?

Oauth 我们真的需要客户端密钥来获取PKCE流上的访问令牌吗?,oauth,oauth-2.0,rails-api,doorkeeper,pkce,Oauth,Oauth 2.0,Rails Api,Doorkeeper,Pkce,我正在构建2个应用程序;一个前端,一个后端 后端将使用Rails API+Doorkeeper Gem(oauth2提供程序)构建,而前端将使用React Native构建 目前,我使用的是“客户端凭据授权流”,目前运行良好。但是在研究了一段时间之后,这个流不应该用在仅客户端的应用程序中,因为如果有人对应用程序进行反编译,它会暴露客户端的秘密 我也读过关于“隐式赠款流动”的书,它只需要客户id。但这种流动现在似乎已经过时了 根据这一点: 建议使用“PKCE授权码授权”而不是“隐式授权流”。我可以

我正在构建2个应用程序;一个前端,一个后端

后端将使用Rails API+Doorkeeper Gem(oauth2提供程序)构建,而前端将使用React Native构建

目前,我使用的是“客户端凭据授权流”,目前运行良好。但是在研究了一段时间之后,这个流不应该用在仅客户端的应用程序中,因为如果有人对应用程序进行反编译,它会暴露
客户端的秘密

我也读过关于“隐式赠款流动”的书,它只需要
客户id
。但这种流动现在似乎已经过时了

根据这一点:

建议使用“PKCE授权码授权”而不是“隐式授权流”。我可以让它工作,但问题是它仍然需要
客户机\u secret
才能获得
访问\u令牌
,应该这样吗

以下是我正在进行的样本流:

curl -X POST 'http://localhost:3000/oauth/authorize?client_id=xxxx&redirect_uri=urn:ietf:wg:oauth:2.0:oob&response_type=code&scope=public&code_challenge=testchallenge&code_challenge_method=plain'
这将给我以下答复:

{
    "status": "redirect",
    "redirect_uri": {
        "action": "show",
        "code": "8quZ-EAiKKG2EKnQiSYs3xeFRCgsIwcTbaWNdjnpyFg"
    }
}
{
    "error": "invalid_client",
    "error_description": "Client authentication failed due to unknown client, no client authentication included, or unsupported authentication method."
}
然后我将使用上面的代码通过下面的请求获取访问令牌:

curl -i http://localhost:3000/oauth/token \
  -F grant_type="authorization_code" \
  -F client_id="xxxx" \
  -F client_secret="xxxx" \
  -F code="8quZ-EAiKKG2EKnQiSYs3xeFRCgsIwcTbaWNdjnpyFg" \
  -F redirect_uri="urn:ietf:wg:oauth:2.0:oob" \
  -F code_verifier="testchallenge"
现在,问题是,为了将
code>交换到
access\u令牌
I仍然需要
client\u secret
。如果两者都只是公开我的
客户机密
,那么它与“客户凭证授权流”有何不同

上述命令将返回以下内容:

{
    "access_token": "nQoorBqLxQH4qFpmlx3mGG6Cd_TfX4d3L3gAGOTwrFs",
    "token_type": "Bearer",
    "expires_in": 7200,
    "scope": "public",
    "created_at": 1595517643
}
如果我没有在请求中包含
客户机密
,则响应如下:

{
    "status": "redirect",
    "redirect_uri": {
        "action": "show",
        "code": "8quZ-EAiKKG2EKnQiSYs3xeFRCgsIwcTbaWNdjnpyFg"
    }
}
{
    "error": "invalid_client",
    "error_description": "Client authentication failed due to unknown client, no client authentication included, or unsupported authentication method."
}
下面是我的问题:

  • 我们真的需要
    client\u secret
    才能在PKCE流上获取
    access\u token
  • 如果“PKCE流”只会暴露
    客户机的秘密,为什么建议使用它
  • 它与“客户端凭据授予流”有什么不同?后者还公开了
    客户端\u机密
  • 门卫PKCE文件:

  • 我们真的需要客户端密钥来获取PKCE流上的访问令牌吗
  • 视情况而定。最初引入PKCE是为了保护公共客户机(无法保护机密的客户机)。但最近,通过实践,PKCE成为授权代码授予的建议()

    2.1.1。授权代码授予

    客户端必须防止将授权代码注入(重播)到
    攻击者的授权响应。PKCE[RFC7636]的使用
    为此目的,建议采取行动。OpenID Connect“nonce”参数和 也可以使用ID令牌声明[OpenID]。PKCE挑战或
    OpenID连接“nonce”必须是特定于事务且安全的
    绑定到交易所在的客户端和用户代理
    开始

    注:尽管迄今为止PKCE被设计为一种保护机制
    本机应用程序,此建议适用于所有类型的OAuth客户端,
    包括web应用程序

  • 如果“PKCE流”只会暴露客户端的秘密,为什么建议使用它
  • 简而言之,为了避免授权代码重播攻击()。这发生在终端用户的设备中,而不是在数据传输中。对于OAuth 2.0令牌请求,TLS是必需的

  • 它与“客户端凭据授予流”有什么不同,后者也会公开客户端的机密
  • 由于令牌请求是通过TLS完成的,因此没有授权将公开凭据


    我认为在你的情况下,客户是一个机密客户()。因此,我建议在授权服务器中检查这一方面。

    我正在Rails控制台中创建一个类似这样的
    Doorkeeper::应用程序

    Doorkeeper::Application.create :name => 'Test App', :uid => 'xxxx', :secret => 'xxxx', :redirect_uri => 'urn:ietf:wg:oauth:2.0:oob'
    
    似乎我需要将
    Doorkeeper::Application
    机密字段设置为
    false
    ,以便能够在不使用
    客户机密的情况下获取
    访问令牌

    因此,上述代码将变为:

    Doorkeeper::Application.create :name => 'Test App', :uid => 'xxxx', :secret => 'xxxx', :redirect_uri => 'urn:ietf:wg:oauth:2.0:oob', :confidential => false
    
    我在以下方面找到了解决方案: PKCE授权码流是为客户端无法安全保护机密的设置而发明的。因此,在PKCE中使用授权码流时,您不需要密码,或者更准确地说,客户端密码没有任何意义

    似乎您正在经历的是一个看门人bug(请参阅)。所以我担心,在他们修复之前,你必须使用一些虚假的客户秘密

    但只要Doorkeeper正确地实现了PKCE流的其余部分,这就不应该成为问题,因为此流不依赖于任何静态客户端机密,而是使用动态创建的代码验证器,正如您已经指出的那样

    我不确定我是否正确理解您正在使用的处理登录的客户端类型。如果是SPA或移动应用程序,您应该使用PKCE的授权码流,但如果您正在实施一个“经典”web应用程序,其中登录在某个后端服务中处理,您应该使用正常的授权码流,使用客户端密码,因为后端可以信任以保护密码

    顺便说一句,我刚刚检查了我正在进行的一个项目中的代码,我在其中构建了一些Angular SPA,它通过Auth0作为身份提供者进行身份验证。我在PKCE中使用授权代码流,我绝对不会向Auth0发送任何客户机机密,因为很明显,该流是按预期实现的。所以这真的是看门人的问题


    还有一件事:我不知道您提供的请求是否只是示例,但我宁愿使用安全方法,如S256,而不是您在问题中引用的RFC中推荐的方法。PKCE不需要客户端secret@Evert做这意味着看门人出了问题?当使用
    access\u token
    交换
    code
    时,必须存在
    client\u secret
    。我的理解是,这对于此流程的意图没有多大意义<代码>客户端