Loading

OAuth1.0介绍

背景

为什么需要OAuth授权呢?

最典型的应用场景就是第三方登录了, 我们开发了一个网站希望用户可以QQ登录, 但是怎么能拿到用户的 QQ 信息呢? 用户将 账号密码告诉我们当然可以, 但是这样有如下隐患:

  • 我们拿到了用户的密码, 这样很不安全. 而且任意一个应用被黑, 所有相关站点均受影响
  • QQ 需要支持密码登录, 但是单纯密码登录并不安全. 因此进而影响 QQ 的安全问题
  • 我们拿到密码之后, 就相当于拥有了用户的所有信息, 这样无法进行权限限制
    • 可能只是希望授权用户名和头像, 但是连着好友列表一起交代出去了
  • 用户一旦修改密码, 所有之前授权过的应用全部失效

基于以上原因, 就需要有这样一套机制:

  • 不基于密码的授权
  • 授权存在时间限制, 并且随时可以收回权限
  • 收回单个应用的权限, 不会对其他已授权的应用造成任何影响
  • 可以仅授予个别权限, 而不是所有

没错, OAuth就是为了解决这个问题而提出来的.

介绍

OAuth是什么呢? 在RFC 文档中是这样介绍的.

OAuth provides a method for clients to access server resources on behalf of a resource owner (such as a different client or an end- user). It also provides a process for end-users to authorize third- party access to their server resources without sharing their credentials (typically, a username and password pair), using user- agent redirections.

写的比较官方哈, 简单说, 就是授权他人以拥有临时访问资源的权限.

那么, OAuth1.0是如何实现这样的机制呢?

实现

在介绍其实现之前, 需要先来了解OAuth中的几个概念.

  • 角色
    • Consumer 消费者, 既需要访问资源的应用
    • ServiceProvider 服务提供者, 既提供资源的服务器
    • User 用户

依旧使用我们上面的例子, 我们的博客网站需要接入 QQ 登录. 在这里, 博客网站就是其中的Consumer, 而 QQ 服务器就是ServiceProvider了. 为了方便立即, 下面均称为 博客网站 QQ服务器. 我们获取授权的流程大致如下图:

image-20220218204953974

对其中的各个流程进行介绍

流程

在请求之前, 博客网站需要到 QQ 服务器 进行注册, 并获得如下标识:

  • consumer_key: 网站标识符
  • consumer_secret: 网站使用的私钥

1. 获取 request_token

网站向QQ 服务器申请一个临时凭据, 用来在本次授权过程中进行校验.

携带参数

  • oauth_consumer_key
  • oauth_signature_method: 签名使用的生成方法
  • oauth_signature: 本次请求的签名, 使用consumer_secret生成
  • oauth_timestamp 时间戳, 用于对本次请求进行校验
  • oauth_callback 回调链接, 用于在用户授权之后回调通知消费者
  • oauth_nonce 随机字符串
    • 此参数用来防止重放攻击, 即别人拿到请求链接再次请求
    • 因此, 服务提供者会对其进行验证是否处理过

返回数据

  • request_token: 此 token 仅用作后面授权中校验使用, 以及对本次授权进行标识
  • request_secret: 用于本次授权的后续请求进行加密, 使用在第5步

2. 重定向到服务器授权页面

将页面重定向到 QQ 服务器 的授权页面.

携带参数

  • request_token: 用来向 QQ 服务器标识本次授权

3. 用户在 QQ 服务器完成授权操作

用户在 QQ 服务器的授权页面进行登录并授权

4. 回调函数通知授权成功

用户授权成功后, QQ 服务器将链接重定向到 第一步指定的 回调链接. 并在回调链接上附带结果:

  • request_token: 用来对本次授权进行标识. 毕竟博客网站收到回调时, 需要知道是哪个用户授权成功了.
  • verifier: 在下一步获取 access_token 中检验使用. 具体作用在下一步说明.

5. 授权成功后获取 access_token + access_secret

此时用户已经同意了权限的授予, 博客网站可以到 QQ 服务器获取用户的授权码了.

返回数据

  • access_token
  • access_token_secret

用户后续就使用这两个授权信息到 QQ 服务器请求资源.

access_token_secret作用

这里有个小疑问, 既然有了access_token, 又为什么需要access_token_secret呢?

因为访问数据使用HTTP协议, 对数据的传输过程没有安全保障. 在后续访问资源时, 若仅使用consumer_secret对请求进行签名, 若consumer_secret泄露了, 那么攻击者只要获得用户的access_token就拥有了其权限. 而access_token又需要在访问是携带在参数中对权限进行标识. 故而十分危险.

在生成签名时, 额外加上access_token_secret进行签名, 而access_token_secret不会在后续访问中传递, 每个用户又都是不同的, 因此即使consumer_secret泄露了, 攻击者也无法获得所有用户的权限.

携带参数

  • consumer_key
  • request_token
  • signature_method
  • timestamp
  • nonce
  • verifier
  • signature

verifier作用

那么, 这里的oauth_verifier有必要么? 其实它是为了防止 session固话攻击, 感兴趣的可以搜索"OAuth Session Fixation Attack"查看具体内容. 这里简单介绍一下.

假设, 有一个攻击者监控了你的网络请求, 因为使用了HTTP协议, 明文信息也没什么秘密. 那么攻击者就可以在第一步时获得本次授权的request_token. 同时攻击者又通过暴力破解或其他方法, 获得了consumer_secret.

此时, 若没有verifier参数, 本次请求的所有参数攻击者均可以构造. 若攻击者频繁访问本次请求, 又恰好在用户授权完成和网站回调的间隙发起了合法访问, 就会成功获得用户的access_token.

通过添加随机的verifier可以使得本次请求不可预测.

问题

对于OAuth1.0实现的一些问题:

  • 使用了HTTP协议, 安全性较低
  • 使用HTTP协议, 没有对服务提供者的真实性进行校验
  • 对非web应用(如安卓)支持很不友好. (也有通过 PIN 码实现的, 这里不展开介绍了)
  • 签名过程复杂. 需要同时使用consumer_secret+access_token_secret进行签名. (也是因为使用HTTP协议)

这些问题在OAuth2.0得到了解决, 详情查看下一篇文章: OAuth2.0介绍

posted @ 2022-02-19 20:53  烟草的香味  阅读(141)  评论(0编辑  收藏  举报