请问 OAuth 中的 access_token 为什么需要过期 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
cc959798
V2EX    Java

请问 OAuth 中的 access_token 为什么需要过期

  •  
  •   cc959798 2018-06-12 16:08:00 +08:00 10395 次点击
    这是一个创建于 2683 天前的主题,其中的信息可能已经有所发展或是发生改变。

    为什么需要设置国企 refresh_token 来刷新 access_token,有些人说是因为 Access_token 会过期,refresh_token 也会过期,为什么不设计成 access_token 和 refresh_token 一样长的过期时间,然后 refresh_token 就不需要了,反正 refresh_token 也会过期

    52 条回复    2020-05-29 18:14:54 +08:00
    Rekkles
        1
    Rekkles  
       2018-06-12 17:08:34 +08:00
    refresh_token 过期时间比 access_token 要长,这样 access_token 即使过期了,也可以用 refresh_token 去重新刷新 token,既为了安全考虑,也为用户体验着想
    U7Q5tLAex2FI0o0g
        2
    U7Q5tLAex2FI0o0g  
       2018-06-12 17:12:41 +08:00
    如果只是 access_token 过期了,可以继续用 refresh_token 来换取 access_token,换取的过程直接调接口,用户感觉不出来。
    一旦 refresh_token 过期,就需要用户重新登录、授权等流程了。

    所以 refresh_token 的作用可以理解成,不需要每次 token 过期就需要用户登录授权。
    你说的“ refresh_token 就不需要了”完全是不对的
    march1993
        3
    march1993  
       2018-06-12 17:20:23 +08:00 via iPhone
    我和你有同样的疑问,我觉得 access_token 也没有意义。从安全角度讲,拿到 access_token 离拿到 refresh_token 也只有一步之遥了
    cc959798
        4
    cc959798  
    OP
       2018-06-12 18:08:11 +08:00
    @march1993 网上的那些资料只讲了怎么做,但是至于为什么没说清楚哦,我相信很多人是有疑问的
    cc959798
        5
    cc959798  
    OP
       2018-06-12 18:10:30 +08:00
    @littleylv 你好,refresh_token 作作用我清楚,不需要重新登录就可以再次拿到授权,但是如果把 access_token 的过期时间和 refresh_token 一样长的话感觉就不需要 了,毕竟如果一样长的话,access_token 过期了 refresh_token 也过期了,然后重新登录不就行了

    至于安全方面我不太明白 refresh_token 的存在的意义
    zhouyou457
        6
    zhouyou457  
       2018-06-12 18:21:46 +08:00
    refresh_token 是一次性的,同时还需要校验客户端的有效性,比如客户端 secret_key 之类的
    zhouyou457
        7
    zhouyo457  
       2018-06-12 18:23:53 +08:00
    在我做的系统中 access_token 过期时间是 1 天,而 refresh_token 过期时间是一个月...如果按你说两者同时过期,让用户输入密码的话,使用体验是很差的....至少我不愿意在一个应用中反复输入密码
    U7Q5tLAex2FI0o0g
        8
    U7Q5tLAex2FI0o0g  
       2018-06-12 18:41:24 +08:00   1
    @zhouyou457 #7
    也许楼主的意思是:如果他不需要 refresh,然后把 access 设置成很久(比如和你的 refresh 一样一个月),那是不是也是一个月后再让用户登录授权,跟你的系统没两样(看起来没两样)。

    但是为了防止 access token 的泄露,一般会把他设置很短时间比如一天。


    @march1993 #3
    拿到 access 不等于可以拿到 refresh,因为 access 会经常在 api 调用中传输,会有安全隐患,但即使被人拿到了,别人根本不知道 refresh,所以只要几个小时后 access 失效,别人也就没辙了。

    这就是为什么需要两者并用,切 access 时间很短的原因了把
    lurenw
        9
    lurenw  
       2018-06-12 18:57:49 +08:00   1
    access_token 暴露在外面的时间越久越危险,需要不断变化来防止泄露。

    refresh_token 用专门的接口和单独的服务器,达到相对的 safer。

    ps. oauth 和 jwt 那套标准和流程真的嗦。
    mooncakejs
        10
    mooncakejs  
       2018-06-12 18:59:10 +08:00
    refresh_token 的获得和更换 access token 只有 2 个接口,这两个接口需要严格的安全措施( https 等),但是对于 access_token 的使用,没有这个限制,所以泄露风险大大增加。
    maichael
        11
    maichael  
       2018-06-12 19:07:46 +08:00   1
    There is a security reason, the refresh_token is only ever exchanged with authorization server whereas the access_token is exchanged with resource servers. This mitigates the risk of a long-lived access_token leaking in the "an access token good for an hour, with a refresh token good for a year or good-till-revoked" vs "an access token good-till-revoked without a refresh token."
    maichael
        12
    maichael  
       2018-06-12 19:10:16 +08:00
    上面忘记加引用了。

    大体意思和 #9 差不多。
    march1993
        13
    march1993  
       2018-06-12 19:51:58 +08:00 via iPhone
    @littleylv 那完全可以授权多个 access_token,独立审计,也比这种短时 access_token 好啊
    Foolt
        14
    Foolt  
       2018-06-12 20:13:41 +08:00
    @march1993 你觉得拿到 access_token 离拿到 refresh_token 也只有一步之遥,是因为你的业务场景比较简单,access_token 和 refresh_token 保存在同一个地方。

    有的场景并不是这样。比如说你要开发个 Javascript 版微博,用户授权后,你直接在浏览器用 JS 获取微博内容,那么 access_token 就会暴露在浏览器之中,但 refresh_token 只在你的服务器里,当用户退出网页后你可以通过刷新令已经暴露的令牌失效。
    sidgwick
        15
    sidgwick  
       2018-06-12 20:19:03 +08:00 via iPhone
    @littleylv 我也觉得是这样,access token 需要经常在网络上传输。这传来穿去的就不安全了
    march1993
        16
    march1993  
       2018-06-12 21:40:50 +08:00   1
    @Foolt 这个客户端应该是个第三方 JS 微博客户端对吧?这个短时 access_token 在用户每次登陆时都需要去刷新吧,存不存 refresh_token 一样啊,要 revoke 也可以直接用这个 access_token。所以存这个 refresh_token 的意义在哪里…要安全完全可以隔离不同的 token。客户端如果不安全,拿到了 access_token,那离拿鉴权也不远啊… 所以我不能信服你这个说法
    march1993
        17
    march1993  
       2018-06-12 21:44:07 +08:00
    当然我觉得拿鉴权还是有点过了,不过如果可以拿到 access_token 一次,就说明可以不断地拿了吧,只要用户经常使用的话?
    chinvo
        18
    chinvo  
       2018-06-12 21:46:03 +08:00 via iPhone
    @march1993 #16 此言差矣

    refresh token 必须和 client secret 一起用才有效

    而且在权限限制严格的情况下,refresh token 必须在满足特定条件下才会被发放给 oauth client

    而 access token 是经常暴露出来的,并且可以先送给第三方 resource provuder,但 refresh token 只能在 oauth client 和 authentication provider 之间传递并且必须被保密存放
    chinvo
        19
    chinvo  
       2018-06-12 21:51:29 +08:00
    @march1993 #16

    另外 agent 不等同于 client,agent 是暴露给用户的部分,包括浏览器、app,而 client 是指包含 agent 和执行 code 换 token 或者 refresh token 换 token 的服务器端两部分,单纯的 agent 形式的 client 又叫 public client,是不能使用 client secret 和 refresh token 的

    #17 但是非法的 agent 能偷到一次 access token 不代表可以偷到第二次,而如果能偷到 refresh token 并使 refresh token 有效,就是非常严重的安全事故了
    march1993
        20
    march1993  
       2018-06-12 21:51:47 +08:00
    @chinvo 我觉得这种做法看似加强了安全,实则让审计成了一个黑箱。在若干第三方 resource provider 中,设有一个被入侵污染了,如何发现并清除呢?由于 access_token 是公用的,我任务这种情况下就很麻烦。
    chinvo
        21
    chinvo  
       2018-06-12 21:52:41 +08:00
    feng huang 的 V2EX iOS app 里面误点感谢突然不能取消感谢好尴尬……
    chinvo
        22
    chinvo  
       2018-06-12 21:54:15 +08:00
    @march1993 #20 所以 access token 有效期是短暂的,即使泄露不会造成太大危害,但是如果按你的思路设置为长期,就是很危险的了,尤其是有一些 authentication provider 不支持 revoke access token 的情况下
    march1993
        23
    march1993  
       2018-06-12 21:56:49 +08:00
    @chinvo 不啊,按照我的思路,我的 token 是独立的,也就是这个 token 能做的事情也是有限的,所以危害是可以控制的。在被污染的 provider 被发现之前,它也可以一直请求更新 token,所以我觉得这个危险可能更严重。
    march1993
        24
    march1993  
       2018-06-12 21:57:48 +08:00
    @chinvo 即便如此,像我们这种下游开发者也只能跟着 access_token 走了
    chinvo
        25
    chinvo  
       2018-06-12 21:58:57 +08:00
    @march1993 #20 抱歉认错了,误认为你是楼主……

    access token 被泄漏的时候的安全性保障,来自于短期有效。

    另外为了避免 public 的 client (单纯 agent 的 client,包括网页、手机 app )所取得的 access token 泄漏造成麻烦,还引入了 PKCE
    chinvo
        26
    chinvo  
       2018-06-12 21:59:50 +08:00
    @march1993 #23 resource provider 并不能更新 token,他只能使用 token 去进行认证或者访问 api,只有 client 能更新 token
    march1993
        27
    march1993  
       2018-06-12 22:05:32 +08:00
    @chinvo 我理解的短时对于入侵者来说用 access_token 配合预先编写的程序可以干一堆事情了,所以可能我理解上有偏差
    chinvo
        28
    chinvo  
       2018-06-12 22:16:15 +08:00   1
    @march1993 #27 resource provider 的接入一般是受 authentication provider 管理方的严格限制的,所以这个角度不容易泄漏。

    大部分只在服务器上调用 RP 接口的 client 也不会泄漏 token。

    那么就只剩下 agent 了,而 agent 是不允许持有 client secret 和 refresh token 的。

    此时 access token 若泄漏,只会造成短时间的风险(一般是 3600 秒),虽然可以做一堆事,但远比直接泄漏用户密码或者长期令牌要安全的多。

    更严格的策略要求 agent 也不可以持有 access token,必须通过后端服务器与 IdP/RP 交互。

    在最严格策略下,可能的泄漏风险是换取 access token 之前,authentication provider 返回的 code,引入 PKCE 对 agent 进行 challenge,code 与 PKCE 的 code_verifier 绑定,只有此 agent 的后端服务器可以用 client_secret, code_verifier 和 code 换到 access token。
    SingeeKing
        29
    SingeeKing  
    PRO
       2018-06-12 22:17:51 +08:00
    假设 access token 一天过期一次

    那么 refresh token 换取 access token 每 24h 只要一次就好了,也就是说每天只有这一次的机会会泄漏 refresh token
    而 access token 则会在每一次调用中都可能泄漏,泄漏几率远大于 refresh token


    ---------------

    其实问题来了,如果服务器是 https 的话,那么如果不考虑中间人应该都不会泄漏,而如果被中间人了那么很大几率 refresh token 也保不住(毕竟被中间人攻击的话手机或电脑应该已经被安装了第三方根证书)
    chinvo
        30
    chinvo  
       2018-06-12 22:22:32 +08:00   1
    @march1993 另外你 #24 说的没错,通常情况下,token 泄漏,client 的开发者是除用户之外最大的受害者。

    所以理论上 client 的开发者有权利和义务选择最严格的流程并且完整实践 OAuth 2.0/OpenId Connect 所有对于安全性的要求和建议。

    而对于敏感数据的提供方,作为 RP 应当要求 client 和 IdP 使用严格的 token 交换机制。
    作为 IdP,因其本身不提供敏感数据( OAuth 中只作为用户身份认证令牌的提供方,OpenId Connect 中还要提供一个 Userinfo Endpoint ),则应当为 RP 和 client 的安全性考虑,为他们实作标准中提出的安全机制。
    chinvo
        31
    chinvo  
       2018-06-12 22:24:17 +08:00
    @SingeeKing #29 按照 IETF 和 OpenId 的要求,refresh token 和 client secret 是不可以放在 agent 上的,也就是说,其实目前大部分将 refresh token 和 client secret 保存在用户手机或者其他设备的 agent 是不合规且有隐患的。
    SingeeKing
        32
    SingeeKing  
    PRO
       2018-06-12 22:25:27 +08:00
    @chinvo #31 What。。Refresh token 不放在客户端怎么刷新。。
    chinvo
        33
    chinvo  
       2018-06-12 22:26:45 +08:00
    @SingeeKing #32 由客户端的服务器刷新。

    如果你真的在客户端能成功刷新 access token,那么你的 client secret 已经至少漏给用户了
    choury
        34
    choury  
       2018-06-12 22:26:47 +08:00
    @SingeeKing #29 access token 可以放在 url 里面的,能拿到这个的可能太多了,而 refresh token 只存在自己服务器上,除了和 auth server 交互之外不会被传送
    说白了这套流程防的是不怀好意的第三方,并不是用来防开发者的
    choury
        35
    choury  
       2018-06-12 22:28:20 +08:00
    @SingeeKing #32 放在客户端,那客户就可以伪造你了……
    ooh
        36
    ooh  
       2018-06-12 22:30:49 +08:00
    cookie 为什么需要过期?
    q397064399
        37
    q397064399  
       2018-06-12 22:56:52 +08:00
    本身并没有什么卵用,

    通信层面上保证安全的是 https 跟非对称加密协议,
    客户端层面上是开发者 保证内存不被恶意 dump,token 不被恶意获取

    客户端如果保护不了 token 那也同样保护不了 refresh_token
    非对称加密要是 证书被恶意篡改 遭受中间人攻击 同样是被脱了裤子,
    你捂住了下面,就捂不住上面,也是没有什么卵用

    另外 md5 挑战认证,了解一下?
    chinvo
        38
    chinvo  
       2018-06-12 22:59:22 +08:00
    @q397064399 #37 所以 refresh token 是禁止放在 agent 的
    q397064399
        39
    q397064399  
       2018-06-12 23:02:23 +08:00
    @chinvo #38

    不解,如果 refresh_token 不放在客户端,客户端如何刷新 token,
    需要借助服务器来刷新么? 那服务器 与 客户端 怎么确认 认证身份?
    chinvo
        40
    chinvo  
       2018-06-12 23:05:01 +08:00
    @q397064399 对的,要用服务器来刷新,客户端和服务器之间没有具体规定,你可以用 access token (由 IdP 颁发而非自行颁发)、cookie、session、或者自行颁发 access token
    q397064399
        41
    q397064399  
       2018-06-12 23:10:30 +08:00
    @chinvo #40

    如果刷新 token,还要另外再弄一套认证鉴权机制
    我觉得意义就不是很大了,token 跟 refresh_token 的存在
    本身就是因为穿了加密协议这条内裤, 假如客户端自己不能保护好 token 跟 refresh_token
    那其它的鉴权机制 也无法保证 用户的认证信息


    之前 Linus 邮件里面 就批评了那些安全专家, 我觉得 Linus 的观点很正确,
    安全的重点从来是人,而不是程序机制,任何机制都无法避免 看守金库的老大爷喝醉之后被小姐骗走钥匙
    march1993
        42
    march1993  
       2018-06-12 23:27:35 +08:00
    @chinvo 我觉得如果你提 IdP 和 SP 的话属于另外一个范畴了,IdP 和 access_token、refresh_token 解决的是两个不同的问题吧?
    chinvo
        43
    chinvo  
       2018-06-12 23:28:44 +08:00
    @march1993 呃,access_token 和 refresh_token 就是 IdP 发给你( client )的啊
    Foolt
        44
    Foolt  
       2018-06-13 00:29:24 +08:00 via Android
    @march1993

    如果只有访问令牌,刷新直接用访问令牌,这意味着用户的访问令牌一旦泄露,黑客可以立即用访问令牌刷新令牌,令你服务器的访问令牌失效,你再想刷新你都刷新不了。这时黑客就可以一直使用访问令牌,直到用户取消授权或者刷新授权。

    刷新令牌就是解决这个问题的,刷新令牌长期有效,访问令牌短期有效,就算用户泄露了访问令牌,你服务器也可以通过刷新令其失效,退一步讲,即使没刷新,最多几个小时(一般是一两个小时)就失效了。不会出现用访问令牌刷新,一旦泄露黑客就取代你的情况。
    icz
        45
    icz  
       2018-06-13 08:12:05 +08:00 via iPhone
    @chinvo 这么说我怎么觉得 refresh token 放在 agent 上更安全? refresh token 只要不配合 client secret 就是无效的,而 refresh token 相当于是一个临时的用户密码,这样不就相当于在客户端的服务器上明文存用户密码了..?客户端服务器如果被攻破 client secret 和 refresh token 就会一起泄漏。如果 refresh token 放在 agent 上,client 接收 agent 的刷新请求(并用自己的手段认证 agent )再向 oauth 认证服务器请求会不会更好一些?
    catinred
        46
    catinred  
       2018-06-13 11:13:59 +08:00
    要分两种情况来讨论,不要混淆在一起。1.通讯线路被黑,例如 MITM。2.客户端被破解。
    CoderGeek
        47
    CoderGeek  
       2018-06-13 16:03:51 +08:00
    refresh_token 未过期 直接申请新的 access_token
    refresh_token 过期 重新登录获取授权的 access_token 和 refresh_token
    CoderGeek
        48
    CoderGeek  
       2018-06-13 16:06:57 +08:00
    你要是觉得 OAuth 麻烦 可以用 JWT 简单 或者看看 Apache OAuth2.0 的介绍上面有流程
    https://tools.ietf.org/html/rfc6749#section-1.5
    CoderGeek
        49
    CoderGeek  
       2018-06-13 16:09:03 +08:00
    如果你自己做个开放平台 类似微博 微信 百度 豆瓣 他们都是这样的流程 = = 看他们 授权介绍 ...虽然有的实现很乱
    但基本都是按照 OAuth2.0 来的
    mingyun
        50
    mingyun  
       2018-12-18 22:10:44 +08:00
    JacobAngle
        51
    JacobAngle  
       2019-12-03 14:20:37 +08:00
    我还是不理解 refresh_token 怎么用才会安全? refresh 请求另一个接口来获取 access_token,那么别人知道 refresh_token 了也就很容易获取到 access_token 了呀?难道是以为别人不知道 refresh_token 的接口?通过分析是很明显就会知道的呀。所以 refresh_token 到底是怎么个安全呢?只是避免在网络传输中被截获?那直接 https 是不是就不会被截获了?那还要 refresh_token 有何用?很迷惑~!
    lubberland666
        52
    lubberland666  
       2020-05-29 18:14:54 +08:00
    fuck 深感同意 @JacobAngle 上面有同学说 refresh_token 放在服务端 刷新的时候 需要另外一套鉴权机制来保证刷新过程, 如果一套鉴权机制 需要另外一套鉴权机制来保证安全,那感觉没啥太大意义了
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5084 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 09:21 PVG 17:21 LAX 02:21 JFK 05:21
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86