V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
Newyorkcity
V2EX  ›  问与答

OAuth2(第三方登录)里,为什么 Authorization Access Token 前要先有个 Authorization Code?

  •  
  •   Newyorkcity · 2021-12-25 15:42:15 +08:00 · 2211 次点击
    这是一个创建于 1058 天前的主题,其中的信息可能已经有所发展或是发生改变。
    我个人理解,以用 Google 账号登录应用程序 Foobar 为例,不论是 token 还是 code ,主要都是为了 Foobar 和 google 间的交流。绝大多数场景下,应用程序 Foobar 会把自己和 google 交流的 access token 也给客户,让客户每次请求带上,是因为现在流行服务端不保持状态,所以不缓存这个 token 。


    然后我现在迷惑为啥要先给 foobar 一个 code ,foobar 用这个 code 再去拿 token ?不能直接一开始就给 Token 吗?

    那我这里能想到的一个好处是,code 一般比 token 要短。foobar 拿到一个 code,然后向 google 验证,这个是一个有效 code ,再得到 token ,比 foobar 拿到一个 token ,然后带着 token 向 google 验证这个 token 有效花的空间少。。

    但我觉得这个优点好无力啊

    请注意!
    我是知道 Foobar 第一次拿到 code 后要回头向 Google 验证的。
    我不是说 Foobar 一拿到 token 就信任这是个有效 token ,不向 google 验证。
    我问的是,foobar 第一次就拿到 google 给的 token ,而不是 code ,它带着这个 token 向 google 验证不成吗?

    谢谢
    18 条回复    2021-12-26 22:12:30 +08:00
    eason1874
        1
    eason1874  
       2021-12-25 16:07:33 +08:00
    OAuth2 有两种模式。一种适合客户端,直接与开放网站连接,这就是你想要的无 Code 版本,直接就给 Token

    另一种适合 Web 页面,用户授权回调跳转给 Code ,你的服务器再拿 Code 去拿 Token 。因为网页跳转的网址可能会被浏览器、代理、安全软件等多种软件记录,直接给 Token 会增加泄露风险,所以给一次性 Code ,你服务器拿到了再去换。Code 有效期很短而且只能用一次,不怕泄露
    wdssmq
        2
    wdssmq  
       2021-12-25 17:46:10 +08:00
    除了支付接口外,大部分都是,你向 API 发起一个请求,API 返回对应信息,API 不会主动向外发起请求,一些非 web 端的也没法主动通知;

    登录验证后,只能由用户通过浏览器跳转将鉴权信息带回 app 端,虽然请求的 access token 属于用户,用户自身可信,但是用户环境不可信。

    不管 code 还是 token ,app 信不信并没人在乎,你拿着 code 或 token 去请求时对面认不认才是关键,甚至已经发了正确的 token ,但是中间发现该应用违规,直接 ban appid ,关联该应用的全部 token 都失效;
    oott123
        3
    oott123  
       2021-12-25 18:20:06 +08:00 via Android   ❤️ 1
    因为你的前提:

    > 绝大多数场景下,应用程序 Foobar 会把自己和 google 交流的 access token 也给客户,让客户每次请求带上,是因为现在流行服务端不保持状态,所以不缓存这个 token 。

    是错误的。使用 code 流程授权,应用不应该把 token 提供给用户端。
    Newyorkcity
        4
    Newyorkcity  
    OP
       2021-12-25 18:48:07 +08:00
    @eason1874 啊?那拿到 code 后用 code 去拿 token 的那次请求的 request 和 response ,难道就不会被浏览器、代理、安全软件等多种软件记录吗?


    @wdssmq 额。。。你这么一说不就更显得 code 这个阶段没必要存在了吗?
    @oott123 应用不把 token 提供给用户让用户每次请求带着,那难道应用自身保存下来 token ?
    eason1874
        5
    eason1874  
       2021-12-25 18:57:47 +08:00
    @Newyorkcity #4 不会,因为正确的流程是用户授权回调得到 Code 之后,在服务端换取 Token ,不在客户端
    kejialiu
        6
    kejialiu  
       2021-12-25 19:58:21 +08:00 via Android
    code 是经过客户端转发给 Foobar ,而不是 Google 直接发给 Foobar 的,Foobar 无法直接验证真伪,得自己去找 Google 问一下(通过 https ,可以验明 Google 正身)。

    但如果用 SAML 这样的协议,可以不用回 Google 二次验证,因为认证结果(Assertion)是带签名的,签名用的公钥在前期配置过程中就已经同步给 Foobar 了
    Newyorkcity
        7
    Newyorkcity  
    OP
       2021-12-25 20:50:32 +08:00
    @kejialiu 我知道要二次验证,因为 foobar 被动接收的地址不知道到底是什么妖魔鬼怪再向它发消息。。。我的疑惑是,干嘛不第一次就发 token ,非得先发个 code ,然后你来验证了我才给你 token 。。。。。。。难道是强迫应用程序必须进行验证,强迫应用程序提高安全性?
    wdssmq
        8
    wdssmq  
       2021-12-25 21:36:18 +08:00
    ![QQ 截图 20211225212310.png]( https://s2.loli.net/2021/12/25/AenbjgR5mt4PcDv.png)

    v 站的谷歌登录,code 在浏览器控制台就能看到;
    ysc3839
        9
    ysc3839  
       2021-12-25 21:41:00 +08:00 via Android   ❤️ 1
    有 code 的是用户授权第三方服务的情况吧?此时要确保只有被授权的服务能拿到实际的 access token ,所以先返回一个 code 给客户端,客户端把 code 提交给服务器,服务器拿着 code 和 app secret 去请求才能拿到 access token ,任何中间方拿到了 code 都不能拿到 access token
    wyx119911
        10
    wyx119911  
       2021-12-26 02:42:38 +08:00
    就是为了防止拦截到 access token 呀,这样可以保证 token 始终在服务器不外泄出去
    Newyorkcity
        11
    Newyorkcity  
    OP
       2021-12-26 08:16:34 +08:00
    @ysc3839 emmmm 中间方是指什么?是不是想说其它应用?你的意思是 access token 是不带应用程序的信息的吗?


    @wyx119911 不外泄出去?可是授权服务器至少要发一次 token 给应用啊,那这一次会不会外泄?如果这一次不会外泄,那为什么不能做到次次不外泄?
    kejialiu
        12
    kejialiu  
       2021-12-26 09:44:36 +08:00 via Android   ❤️ 1
    服务器之间的通信,不会经过浏览器,https 保证了没有中间人(除非 Google 脑抽泄露了私钥或者把私钥共享给了不靠谱的第三方 cdn 之类)
    oneisall8955
        13
    oneisall8955  
       2021-12-26 10:03:18 +08:00 via Android   ❤️ 1
    楼主是不是觉得用 code 请求获取 token 是多余的,那就是这种 password 模式?

    https://www.oauth.com/oauth2-servers/access-tokens/password-grant/

    相比较 code 模式如下:

    https://www.oauth.com/oauth2-servers/server-side-apps/authorization-code/
    Newyorkcity
        14
    Newyorkcity  
    OP
       2021-12-26 10:33:17 +08:00
    @kejialiu 『不会经过浏览器』 -> 言下之意是数据经过浏览器的话在这一步可能会有风险。why ?什么风险呢?


    @oneisall8955 谢谢。我粗看了 password 模式,里面说

    as there is no way to add multifactor authorization to this flow, and your options for detecting brute force attacks are more limited. This flow should not be used in practice.

    emmm ,但为什么不用 code 直接发 token 会导致 no way to add multifactor authorization 和 options for detecting brute force attacks are more limited 呢?(直接拿到 token 不要 code 并不意味着应用不做第二步——向授权服务器验证 token 有效——在有 code 的流程里,这一步是应用拿着 code 去验证并拿回 token——我是想问为什么不一开始就让应用程序拿到 token ,然后这一步让应用拿着 token 去验证)
    wyx119911
        15
    wyx119911  
       2021-12-26 12:08:43 +08:00   ❤️ 1
    @Newyorkcity “至少要发一次 token 给应用”,给的是应用服务器,而不是应用前端。保证 token 只在服务器间流转就 能保证次次不外泄。只要 token 带给前端,就无法避免外泄。
    horsley
        16
    horsley  
       2021-12-26 14:22:45 +08:00
    可以从票据特性的角度重新理解下:
    按你的例子,第一方 Google 有自己的身份票据,要授权给 Foobar ,授权后 Foobar 最终会得到 access_token ,长期有效,可刷新,可用于请求各种资源,因此 access_token 暴露在浏览器跳转等过程就不安全,可能被中间人获取,可以被重放使用。

    而通过使用 code 做转换依据则好得多,code 的设计为短时间单次有效,用完即弃,正常浏览器跳转时间很短,无法被重放使用。
    ysc3839
        17
    ysc3839  
       2021-12-26 16:06:03 +08:00 via Android
    @Newyorkcity 中间方指的是除了被授权应用,其他能获得 code 的人
    kejialiu
        18
    kejialiu  
       2021-12-26 22:12:30 +08:00 via Android
    @Newyorkcity 尽量减少不必要的暴露。客户端不能完全信任,浏览器也有正经的和不正经的,正经浏览器也可能装了恶意插件。当然,真出问题的可能性不大,但你要做的事情足够敏感时就不得不防
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2647 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 10:53 · PVG 18:53 · LAX 02:53 · JFK 05:53
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.