认证授权那点事儿 —— OAuth 2.0

OAuth 2.0 —— 开放授权协议,对应的规范文件RFC-6749早在2012年便成形,所以这并不是一个新的技术(你问我为啥研究这个,我也想吟一首诗啊。。。组织上就是这样决定的),但由于其必不可少的价值,在今天的网络上已经得到了广泛的应用。

OAuth2.0认证是要在不同的应用之间打通互信,互信的目的是为了实现一定程度上的用户数据分享,没数据的一方到有数据的一方拿数据,并且在时间尺度上,数据的分享是受控的。

比如你在微信上打开小程序,小程序会向微信索要你的基本信息;比如你用马克飞象作为印象笔记的客户端,马克飞象会向印象笔记索要你的账户信息,以及阅读、创建、删除、修改笔记等的权限;比如你用github账号登录leetcode,后者会去前者索要你的账户信息 ……

在这些场景里都涉及三方:用户、没数据的应用、有数据的应用(授权、资源)。OAuth2.0规范就规定了三方如何交互,完成权限的授予,获取数据的过程。整体逻辑过程如下图

整个授权框架中包含了4种授权模式:

  • 授权码模式
  • 隐式许可模式
  • 密码模式
  • 客户端模式

在详述4种模式之前,首先需要注意,第三方应用需要先到资源持有应用处注册身份,提交回调URI,注册成功后,得到标识身份的 Client ID 和 Client Secret。资源持有者也可以趁这个阶段对第三方应用进行安全审核。

Client Type, 根据客户端与授权服务器进行安全认证的能力,分为 Confidential(机密客户端)和 Public(公开客户端)。
Client IDClient Secret,应用的身份标识。
Registered Redirect URIs,回调地址,后面会用到。

授权码模式

授权码模式是四种模式中最严密的,主要用于web应用,我们来看看整体逻辑图

下面我按图上的顺序一步步说明。

  1. 我在浏览器上打开了LeetCode网页,并且发现可以用github账户来登录,于是,我点击了章鱼标志。这个时候,就被LeetCode导向了github的认证页面,并且携带了几个必要参数。

    Client ID,表明第三方应用自己的身份,即这个请求是从LeetCode过来的。
    Scope,表明要请求哪些用户信息,用户名、密码、邮箱、头像……
    Redirect URI,应用注册时填入的回调URI之一,授权服务器会检查,必须严格匹配。
    State,一个不容意被猜到的随机数,用于第3步确认收到的code是自己请求的,避免 CSRF 攻击。

  2. 现在打开了github的认证页面(如果没有事先登录,github会要求我先登录github账号),github页面提示是否授权给LeetCode,点击是,则进入下一步;否则,流程结束。
  3. github调用回调URI(这个URI就是最初注册时提交的URI之一),传回授权码,把state也传回。这时,授权码就到了第三方应用的后台服务器。这一步之后的交互,在浏览器上就看不到了,由两个应用的后台服务器完成。

    Authorization Code,授权码,一个临时的随机串。
    State,第1步传过来的state。

  4. 拿到code,并比对了state后,LeetCode服务器就拿着这个code去换访问令牌。

    Client ID & Client Secret,表明自己的身份。
    Redirect URI,获取授权码时提交的回调地址,授权服务器会检查是不是一致。
    Authorization Code,前面拿到的授权码。

  5. 授权服务器认证了客户端身份,并检查回调地址通过后,调用回调URI回传访问令牌。

    Token Type,值为 Bearer Token。
    Access Token,访问令牌,访问资源的凭据。
    Scope,权限范围。
    Expires In,令牌有效时间,单位秒。
    Refresh Token,可选参数,用户更新访问令牌。

  6. 现在LeetCode可以拿着令牌去github获取我的账户信息了,从浏览器上看,我顺利登入了LeetCode。

回过头来看一下,为什么先发一个授权码,不直接发访问令牌?

因为直接发令牌,那么到达用户浏览器的就是令牌。而拿着令牌去访问资源是不需要认证的(别问为什么,就是这样的设计和用法)。如果本地环境不可信,那么让第三方应用服务器和资源服务器去交互,完成code到token的转换是更安全的选择。

即使Authorization Code被另一个应用窃取,并且该应用在授权服务器上合法,也不能使用这个授权码,因为授权服务器会检查带着授权码过来换token的应用是不是最初申请该授权码的应用。

而且,授权码只能被使用一次,当在本地被窃取了以后,如果你使用一次code,攻击者使用一次code,不管谁先谁后,第二次使用code将导致授权服务器终止该code及已下发的token的有效性。

授权码模式被使用的最多,以上讲解只是列出了规范中的主要参数,编码时具体实现还要看各厂是如何落地规范的,可以搜github、微信、google等的接口文档。

隐式许可模式

隐式许可模式和授权码模式最大的不同就是没有授权码交互这一环节,它主要用于依附于浏览器的驻于用户侧的应用,如JavaScript应用。

还是从图说起

  1. 和授权码模式一样。
  2. 和授权码模式一样。
  3. 用户授权通过后,调用回调URI,直接就传回访问令牌。

    Redirect URI,指向第三方应用的资源服务器。
    Fragment with Access Token, etc.,在URI的fragment部分(即#后的部分)携带访问令牌等参数,只会被留在浏览器本地,里面包含了和授权码模式第5步中相同参数。

  4. 访问第三方应用的资源服务器,请求从fragment参数中提取访问令牌的脚本,由于http规范,请求中不会携带fragment部分。
  5. 返回解析脚本,并提取出访问令牌。
  6. 拿着访问令牌去获取资源。

这里看到4、5的时候,困惑了很久,为什么要特地去第三方应用的服务器上取解析脚本,有什么安全考量。SO上某个5K声望的仁兄的回答是:没看出什么考虑,只是在本地放脚本和去服务器取脚本中选了一种方式。我看,是不是因为反正都会用到 Redirect URI,就顺便取个脚本,不然糟蹋了这一来一回。最后访问令牌留在了驻用户侧的应用里。考虑到这种模式不严瑾,行业最佳实践建议采用授权码模式或PKCE模式。

密码模式

密码模式就是用户把用户名和密码都放心地给到第三方应用(如山一般厚重的信任),第三方应用以用户的名字去认证并获取资源。规范中规定了应用不应该保存用户输入的用户名和密码。此种模式多见于资源服务器自家的应用。

客户端模式

第三方应用证明自己的身份,以自己的身份去获取一些公共的资源。这种模式我就不细解释了,参数用途和前面的一致。

基本就是这样了,下次再讲讲 PKCE、Device Code。

如理解有误,欢迎各位老铁拍砖。

参考:
https://oauth.net/2/
https://tools.ietf.org/html/rfc6749
https://getpocket.com/a/read/2216790858

原文地址:https://www.cnblogs.com/read-the-spring-and-autumn-annals-in-night/p/12041916.html

时间: 2024-10-29 17:53:57

认证授权那点事儿 —— OAuth 2.0的相关文章

OAuth 2.0 认证授权

其实之前自己做的微信服务号的绑定登录也就是个OAuth认证授权 简单看下第三方使用OAuth做认证授权的过程:(取自网络,带图的大家应该都喜欢~) 第一步:用户登录第三方网站,例如使用qq登录. 第二步:点击登录后,会跳到qq平台提示输入用户名和密码. 第三步:如果用户名和密码正确,会提示是否接受授权,如果授权成功,第三方网站就能访问你的资源了,qq头像.用户名等 认证和授权过程(包括三方) 1.服务提供方,用户使用服务提供方来存储受保护的资源,如照片,视频,联系人列表. 2.用户,存放在服务提

OAuth 2.0 认证的原理与实践

摘要: 使用 OAuth 2.0 认证的的好处是显然易见的.你只需要用同一个账号密码,就能在各个网站进行访问,而免去了在每个网站都进行注册的繁琐过程. 本文将介绍 OAuth 2.0 的原理,并基于 Spring Security 和 GitHub 账号,来演示 OAuth 2.0 的认证的过程. 原文同步至https://waylau.com/principle-and-practice-of-oauth2/ 使用 OAuth 2.0 认证的的好处是显然易见的.你只需要用同一个账号密码,就能在

使用Owin中间件搭建OAuth2.0认证授权服务器

前言 这里主要总结下本人最近半个月关于搭建OAuth2.0服务器工作的经验.至于为何需要OAuth2.0.为何是Owin.什么是Owin等问题,不再赘述.我假定读者是使用Asp.Net,并需要搭建OAuth2.0服务器,对于涉及的Asp.Net Identity(Claims Based Authentication).Owin.OAuth2.0等知识点已有基本了解.若不了解,请先参考以下文章: MVC5 - ASP.NET Identity登录原理 - Claims-based认证和OWIN

(转)OAuth 2.0授权协议详解和流程

这篇文章主要介绍了OAuth 2.0授权协议详解,本文对OAuth协议做了详解讲解,对OAuth协议的各个方面做了分解,读完本文你就会知道到底啥是OAuth了,需要的朋友可以参考下 OAuth是一个关于授权(authorization)的开放网络标准,在全世界得到广泛应用,目前的版本是2.0版.本文对OAuth 2.0的设计思路和运行流程,做一个简明通俗的解释,主要参考材料为RFC 6749. 一.应用场景 为了理解OAuth的适用场合,让我举一个假设的例子.有一个"云冲印"的网站,可

谈谈基于OAuth 2.0的第三方认证 [下篇]

从安全的角度来讲,<中篇> 介绍的Implicit类型的Authorization Grant存在这样的两个问题:其一,授权服务器没有对客户端应用进行认证,因为获取Access Token的请求只提供了客户端应用的ClientID而没有提供其ClientSecret:其二,Access Token是授权服务器单独颁发给客户端应用的,照理说对于其他人(包括拥有被访问资源的授权者)应该是不可见的.Authorization Code类型的Authorization Grant很好地解决了这两个问题

Oauth2.0认证---授权码模式

目录: 1.功能描述 2.客户端的授权模式 3.授权模式认证流程 4.代码实现 1.功能描述 OAuth在"客户端"与"服务提供商"之间,设置了一个授权层(authorization layer)."客户端"不能直接登录"服务提供商",只能登录授权层,以此将用户与客户端区分开来. "客户端"登录授权层所用的令牌(token),与用户的密码不同.用户可以在登录的时候,指定授权层令牌的权限范围和有效期. 2.客

谈谈基于OAuth 2.0的第三方认证 [上篇]

对于目前大部分Web应用来说,用户认证基本上都由应用自身来完成.具体来说,Web应用利用自身存储的用户凭证(基本上是用户名/密码)与用户提供的凭证进行比较进而确认其真实身份.但是这种由Web应用全权负责的认证方式会带来如下两个问题: 对于用户来说,他们不得不针对不同的访问Web应用提供不同的用户凭证.如果这些凭证具有完全不同的密码,我们没有多少人能够记得住,所以对于大部分整天畅游Internet的网友来说,我想他们在不同的网站注册的帐号都会采用相同的密码.密码的共享必然带来安全隐患,因为我们不能

谈谈基于OAuth 2.0的第三方认证 [中篇]

虽然我们在<上篇>分别讨论了4种预定义的Authorization Grant类型以及它们各自的适用场景的获取Access Token的方式,我想很多之前没有接触过OAuth 2.0的读者朋友们依然会有“不值所云” 之感,所以在介绍的内容中,我们将采用实例演示的方式对Implicit和Authorization Code这两种常用的Authorization Grant作深入介绍.本章着重介绍Implicit Authorization Grant. Implicit Authorizatio

基于OAuth 2.0的第三方授权

OAuth 2.0 什么是OAuth OAuth是Open Authorization的缩写,为用户资源的授权提供了一个安全的.开放而又简易的标准. 在用户授权的前提下允许第三方网站访问用户在服务商里存储信息. 而这种授权无需将用户提供用户名和密码提供给该第三方网站. 提供一个令牌给第三方网站,一个令牌对应一个特定的第三方网站,同时该令牌只能在特定的时间内访问特定的资源. 值得注意的是OAuth 2.0虽然是OAuth 1.0的下一个版本,但并不向后兼容OAuth 1.0. OAuth 2.0授