博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Auth2.0拿code换token,拿token换用户信息
阅读量:3950 次
发布时间:2019-05-24

本文共 3783 字,大约阅读时间需要 12 分钟。

先post一篇介绍Auth2.0的文章:, 链接失效的话,看本地PDF文件。

来源于WeChat公众号:低并发编程


之前做过oidc的权限登陆,原理基本上就是Auth2.0。

auth2.0有好几种认证模式,一般大家用的也都是授权码模式(也就是多一步返回code的操作)。

下面先引用作知乎用户回答:

链接:https://www.zhihu.com/question/27446826/answer/127367856

先确认一下 oauth2 code 认证的角色

1,client——通常是我们开发的 app
2,owner——使用我们 app 的用户
3,auth server——在 owner 授权后,为 client 提供接口来访问资源
认证过程
1,client 获取code时,auth server是不能确认client的身份的,因为这时auth server只有一个app id,但没有任何手段来确认 client 使用的是自己的 app id
2,owner 在 auth server 上认证身份,并同意授权给 client
3,auth server 向 client 发送一个 code,按 oauth2 的协议约定,该 code 通过浏览器的 302 重定向发送给 client
4,client 拿 code 换取 token,首先,这个过程是 client 后台对 auth server 后台的,其次,client 需要提供自己的 app secret,这样就为 auth server 提供了一种验证 client 的机制

那么为什么要这个code?

关键还是第三步:auth server 把 code 发送给 client 这一步不安全,

因为 client 可能会用一个 http 协议的接口来接收 code,那么 code 就会被截取如果在这一步把 token 返回去,

有 2 个问题

1)必须在第一步就提供 app secret,使 auth server 能够验证 client 的身份,这对于 client 的 app secret 来说是不安全的
2)如果 client 指定的 redirect_url 是 http 协议,token 可以在传输过程中被截取导致泄漏

再延伸一下:

拿到 token 后,client 在后续的请求里,token 还是直接发送给 auth server (这个时候其实已经是 resource server 了)的,这个时候就不能截取了吗?

答案是 https——虽然 oauth2.0 协议没有明文要求 auth server 使用 https,但实际上 auth server 提供的接口都是 https 的,作为 app 开发者可以留意一下,看看有哪个提供 oauth 认证服务的厂家不用 https 的。


结合最上面例子:

先说为什么用户在第三方(上面例子中的qq验证服务器)点击授权之后,不直接返回登陆的用户信息,而是返回code?
因为:第三方也需要对客户端(例子中的豆瓣)进行验证。(PS:为什么当时做云课项目的时候,需要拿云课的域名去netease的oidc服务器去申请client_id和client_secret)
在豆瓣发给qq验证服务器的请求中,带了一个重定向的url,表明在验证身份成功之后,需要重定向到这个url(要不然那么多网站都需要qq给验证授权,qq也不知道验证成功之后该跳转到哪),
既然是重定向,那么参数都是在url里的,所以是对浏览器可见的,当然不安全。
所以,不能直接返回token,而是先返回一个code(授权码),这个code有效期很短,
(1)然后服务端把这个code和当时域名注册的client_secret传给qq验证服务器
(2)qq验证服务器拿这个code和client_secret进行验证,验证成功,把access_token返回给豆瓣。(中间还有JWT加密的操作)
(3)豆瓣拿到这个token,再去请求qq服务器,拿到用户信息。

注意,上面1,2,3步骤都是服务端之间自动完成的,浏览器只能到收到code的那一步,剩下的对浏览器都不可见了。

简单来说:

很简单,client是怎么拿到code的?
code 是通过浏览器重定向获取的,你在浏览器地址栏就可以看到,
如果这一步不返回code而是直接返回access token,
那么这个token其实已经暴露了而client拿到code以后换取access token是client后台对认证服务器的访问,不依赖浏览器,access token不会暴露出去。

答案2:

因为整个oauth2的流程,不只要资源拥有者同意,还需要验证客户端的身份。

整个OAuth2中的授权码模式分为两大步骤:
假设 你 是一个客户端, 你首先需要取得
资源拥有者的同意:你需要提供app_id给授权认证服务器,当资源拥有者在授权认证服务器提供的表单登录成功且同意后,你会取得一个code,这个code跟你提供的app_id所绑定。
你然后需要取得
授权认证服务器的同意:你提供code,授权认证服务器知道资源拥有者同意了你获取资源,但是授权认证服务器需要你证明 你是你的 问题,所以你需要提供app_secret,当code和app_secret同时存在,且app_secret对应你的code所绑定的app_id时,整个授权成功结束。

答案3:

OAuth 2.0 定义了 4 种授权方式,涉及到code的只是 authorization code 方式,其它几种方式并不需要 code,而且也相对简单一些。
这样你可以分析一下 authorization code 方式和另外 3 种有什么不同,自然就可以得出为什么需要先拿 code 了。

答案4:

好几个答案没答到点子上,都集中在“就算拿到了code,没有appkey和appsecret也无法获取资源”,那我直接返回access_token不也没有appkey和appsecret。其实主要原因还是加一道防护,code的时效性比access_token短的多,并且只能使用一次,就算拿到了code并且知道appkey和appsecret很有可能也已经过期或者被正主使用过了。

答案5:

好,现在让我们回到问题本身。不知道大家在看授权模式(Authorization Code)时是否曾经跟我有一样的疑惑,简单来说,对于这种模式,既然是授权服务器先给予客户端一个授权码,客户端拿着授权码再回头向授权服务器申请一个访问令牌。那为什么不直接设计成,在用户选择同意授权之后,授权服务器直接将令牌返回给客户端?反而中间需要一个“授权码”来做一次“翻译”?这样做的又是在哪里?多了一次交互的成本。从这方面来看,效果可能还不如同门师兄弟的 客户端模式(Client Credentials) 来的直接。 对于这个问题,如大家所知,OAuth设计出来就是是用于解决授权问题的,那么说到授权,安全自然就是很重要的一个点,很多问题从安全的角度出发去思考也就不难理解了。

Authorization Code Grant

首先,我们贴出这种模式的时序图。

在这里插入图片描述

如果我们按照刚才的思路所说,假设在第一步返回令牌,那么面临着一个问题就是需要把Client ID和Client Secret也在第一步传给授权服务器,不然的话,就无法校验客户端是否用的是自己的Client ID证明 你是你的问题)。那么有同学会说了,如果在第一步就把这两个信息传给授权服务器呢,会有什么问题?那么就是Client Secret面临着泄露的风险。泄露的方式包括请求被拦截,非HTTPS等等,个人的理解是,只要请求是对用户可见的(尤其是还要通过浏览器),就都有可能泄露。 那么像OAuth这样的设计中,在第二步用第一步的授权码去换取令牌,就可以很好的解决这个问题,因为第二步是客户端与授权服务器的独立后台交互,对用户不可见,也不会把行为暴露给浏览器。将授权码和Client ID, Client Secret一并发送,获传取令牌。这样直接避免了网络传输中被窥探,提高了安全性。

至此,我们通过以上所有获取到的信息,串起整个流程,并顺带“推测”一下授权服务器端的动作。(只包括 Happy Path 的主流程)

第一步,第三方客户端将用户导向至授权服务器,用户选择是否授权以及授权范围。 第二步,授权服务器拿到上一步用户侧的输入之后,在后台生成一组信息,包括了授权码,授权范围,用户详情等信息,并以授权码作为Key。 第三步,授权服务器将上一步生成的授权码作为第一步的请求响应返回给浏览器,浏览器再通过302状态附上授权码重定向至第一步客户端指定的回调地址,客户端拿到授权码。 第四步,客户端通过后台发送授权码,Client ID,Client Secret,至授权服务器。 第五步,授权服务器对比Client ID和Client Secret,确认无误之后,再以授权码作为Key,查找到对应第二步生成的那组信息,将这组信息转化成访问令牌(也许还有刷新令牌),返回给客户端。

转载地址:http://kikzi.baihongyu.com/

你可能感兴趣的文章
在Redhat9下静态编译glib库.
查看>>
CImg库编译使用.
查看>>
SQL Server循环执行动态SQL语句.
查看>>
ubuntu10.4网卡名由eth0改为eth4,导致获得不了IP地址.解决方法.
查看>>
CheckPoint关键词做字段名使用.
查看>>
Qt QSplitte分割器使用(用户手动改变窗口大小)
查看>>
Qt动态加载动态库
查看>>
java8新特性
查看>>
git clone时RPC failed; curl 18 transfer closed with outstanding read data remaining
查看>>
Java8内存模型—永久代(PermGen)和元空间(Metaspace)
查看>>
maven中jar、war、pom的区别
查看>>
maven之pom.xml配置文件详解
查看>>
java基础学习之抽象类与接口的区别
查看>>
java基础学习之包、类、方法、属性、常量的命名规则
查看>>
java基础知识学习之匿名内部类
查看>>
SSM框架和SSH框架的区别
查看>>
Elasticsearch-基础介绍及索引原理分析
查看>>
过滤敏感词算法
查看>>
linux学习之shell脚本if判断参数-n,-d,-f等
查看>>
linux学习之windos文件在linux里面乱码解决
查看>>