Oauth 2.0 如何使用资源所有者凭据授权验证公用客户端的作用域

Oauth 2.0 如何使用资源所有者凭据授权验证公用客户端的作用域,oauth-2.0,openid-connect,Oauth 2.0,Openid Connect,给定公共Javascript客户端希望使用资源所有者密码凭据授予类型访问API端点的情况 典型的请求如下所示: username = "john.doe@mail.com" password = "MyP@assw0rd!" grant_type = "password" scope = "openid offline_access" 由于客户端无法存储client\u secret,因此未传递任何client\u id,并且根据规范,可能会忽略它 授权服务器必须: 要求对机密客户或任何

给定公共Javascript客户端希望使用资源所有者密码凭据授予类型访问API端点的情况

典型的请求如下所示:

username = "john.doe@mail.com"
password = "MyP@assw0rd!"
grant_type = "password"
scope = "openid offline_access" 
由于客户端无法存储
client\u secret
,因此未传递任何
client\u id
,并且根据规范,可能会忽略它

授权服务器必须:

  • 要求对机密客户或任何 已颁发客户端凭据(或具有其他凭据)的客户端 认证要求)
问题在于,如果客户端未知,则无法验证
scope=“openid offline\u access”
参数。据我所知,作用域是用来描述应用程序权限的

一个问题马上就出现了

客户机id
被省略时(故意和按规范),如何验证客户机范围? 一些理由:

  • 省略
    client\u id
    的原因是任何人都可以轻松地从JS客户端检索并利用它

  • 在这种情况下,CORS验证增加了几乎为零的值,因为可以手动创建主机头


  • TL;DR跳到下面的结论部分


    的确,存储在Javascript上的
    客户机id
    可以很容易地检索,但是这个标识符不是秘密,规范明确提到了这一点

    客户端标识符不是秘密;它向资源所有者公开,不能单独用于客户端身份验证

    (来源:)

    这意味着可以接受在公共客户机上提供
    客户机id
    ,因此现在让我们关注第二个问题。。。客户端身份验证

    您引用的部分指出,对于机密客户机或任何获得凭据的客户机,必须进行客户机身份验证。您的应用程序不属于这两种情况中的任何一种,因此客户端身份验证要求不适用

    好的,所以您的客户端不需要(实际上也不能执行)客户端身份验证。这会给您的场景带来问题,因为您希望验证请求的作用域,所以让我们尝试找到一个兼容的解决方案

    第一件事是找到一种将
    客户机id
    传递给服务器的方法,因为这是必要的。如果客户机是机密的,则会在
    授权
    标题中与其机密一起传递,但我们不在该场景中。但是,该规范允许省略
    client\u secret
    ,因此让我们仍然使用该HTTP头来传递客户端标识符

    客户端\u机密:必需。客户的秘密。如果客户机机密是空字符串,则客户机可能会忽略该参数

    (来源:)

    现在,我们在服务器端有
    client\u id
    ,但我们不能信任它,因为正如我们已经提到的,我们不能单独使用此标识符进行客户端身份验证,即使我们尝试了一些聪明的(也就是很容易在不知道的情况下出错)身份验证机制,也有:

    授权服务器可以建立客户端认证方法 与公众客户合作。但是,授权服务器不能依赖于 关于公共客户端身份验证以识别 客户

    (来源:)

    妈的,这是行不通的我无法进行身份验证,因此无法信任客户端身份因此无法验证作用域

    我听到了,但还是有希望的。现在让我们关注规范的另一部分

    当无法进行客户端身份验证时,授权服务器应采用其他方法验证客户端的身份,例如,要求注册客户端重定向URI或登记资源所有者以确认身份。

    (来源:)

    中大奖您确实在客户机身份确认过程中登记了资源所有者,他给了客户机用户名和密码,这样就解决了问题


    结论 您似乎确实有办法完成手头的任务,并且仍然声称符合规范(至少从OAuth 2.0方面)。剩下要做的唯一一件事是,这只是我的观点,所以我还想给您一个示例,其中包含一个资源所有者端点的实际实现

    如果你去,你会发现一个具体的实现。看到别人如何处理这个问题总是好的。我已经注意到,这个实现选择在请求主体本身上允许
    client\u id
    ,并有一些其他自定义参数作为选项,但这很好,因为OAuth 2.0没有定义严格的协议,只是定义了基础


    最后一件事,我想提醒您注意的是,OpenID Connect中使用了
    offline_access
    作用域来表示您需要一个刷新令牌,但您不应该对公共客户端这样做。存储刷新令牌(通常是一个长期凭证)几乎与存储实际密码一样糟糕。有关这些类型的令牌的一些一般性指导,请参阅。

    关于在这样的流中每个客户端都可以验证作用域的建议是不正确的。由于
    客户机\u id
    是一个非机密标识符,因此不增加任何值。任何人都可以从您的Javascript实现中获取它,并模拟客户端,对用户凭据进行钓鱼。因此,请求的作用域只能以通用的、非客户端特定的方式处理,而且:

    OAuth 2.0规范建议在这种情况下不要使用资源所有者密码凭据流:

    仅当存在hig时才应使用凭据