关于 OAuth 你又了解哪些?

news2024/11/27 18:31:18

作者罗锦华,API7.ai 技术专家/技术工程师,开源项目 pgcat,lua-resty-ffi,lua-resty-inspect 的作者。

OAuth 的背景

OAuth,O 是 Open,Auth 是授权,也就是开放授权的意思。OAuth 始于 2006 年,其设计初衷正是委托授权,就是让最终用户也就是资源拥有者,将他们在受保护资源服务器上的部分权限(例如查询当天订单)委托给第三方应用,使得第三方应用能够代表最终用户执行操作(查询当天订单)。

OAuth 1.0 协议于 2010 年 4 月作为 RFC 5849 发布,这是一份信息性的评论请求。OAuth 2.0 框架的发布考虑了从更广泛的 IETF 社区收集的其他用例和可扩展性要求。尽管基于 OAuth 1.0 部署体验构建,OAuth 2.0 并不向后兼容 OAuth 1.0。OAuth 2.0 于 2012 年 10 月作为 RFC 6749 发布,承载令牌使用作为 RFC 6750 发布。

在 OAuth 协议中,通过为每个第三方软件和每个用户的组合分别生成对受保护资源具有受限的访问权限的凭据,也就是访问令牌,来代替之前的用户名和密码。而生成访问令牌之前的登录操作,又是在用户跟平台之间进行的,第三方软件根本无从得知用户的任何信息。

这样第三方软件的逻辑处理就大大简化了,它今后的动作就变成了请求访问令牌、使用访问令牌、访问受保护资源,同时在第三方软件调用大量 API 的时候,不再传输用户名和密码,从而减少了网络安全的攻击面。

说白了就是集中授权。

值得注意的是,OAuth 并非身份验证,这里的 Auth 是 Authorization,OAuth 是发生在用户做了身份验证后的事情,系统授权用户能做什么操作。互联网中所有的受保护资源,几乎都是以 Web API 的形式来提供访问的。不同的用户能做的事情不同,例如一个 GitHub 项目,有些用户只有读取和提交 PR(pull request)的权限,而管理员用户则能合并 PR。将用户权限在 API 层面细分,是 OAuth 要做的事情。

OAuth的授权流程

角色

在 OAuth 2.0 的体系里面有四种角色:

  • 第三方应用:一般分为前端浏览器、APP 和后端应用服务器。
  • 资源拥有者:使用第三方应用的用户,并在授权服务器上有账号。
  • 授权服务:提供授权的开发平台,例如微博、GitHub、微信。
  • 受保护资源:用户的各类信息,例如用户名、头像、昵称、邮箱等信息。

流程

图片

步骤A:第三方应用向用户(其实是通过授权服务器)申请授权码

步骤B:授权服务器返回授权码给第三方应用

步骤C:第三方应用将授权码发给资源服务器,申请访问口令

步骤D:授权服务器返回访问口令给第三方应用

步骤E:第三方应用使用访问口令向资源服务器请求用户信息

步骤F:资源服务器返回用户信息,第三方应用提供业务逻辑给用户

授权码和访问口令

获取访问口令的方式在标准里有四种,这里只谈论授权码方式,这也是最常见最安全的方式:

图片

步骤 A:第三方应用让用户选择授权方式,例如 GitHub,然后携带client_idredirect_uri等参数将用户重定向到授权服务器

请求示例:

    GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz
        &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.13    Host: server.example.com

步骤 B:用户登录和授权 步骤 C:授权服务器根据redirect_uri将用户重定向回到第三方应用的后端,提供授权码

响应示例:

1     HTTP/1.1 302 Found
2     Location: https://client.example.com/cb?code=SplxlOBeZQQYbYS6WxSbIA
3               &state=xyz

步骤 D:第三方应用的后端访问授权服务器,用授权码去换访问口令 请求示例:

1     POST /token HTTP/1.1
2     Host: server.example.com
3     Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
4     Content-Type: application/x-www-form-urlencoded
5
6     grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA
7     &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb

步骤 E:授权服务器返回访问口令,第三方应用的后端渲染功能页面(对应步骤C)给浏览器,为用户提供功能 授权服务器的响应示例:

     HTTP/1.1 200 OK
     Content-Type: application/json;charset=UTF-8
     Cache-Control: no-store
     Pragma: no-cache

     {
       "access_token":"2YotnFZFEjr1zCsicMWpAA",
       "token_type":"example",
       "expires_in":3600,
       "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
       "example_parameter":"example_value"
     }

实际场景示例

小明想通过小兔软件打印他在京东上的订单。

资源拥有者 -> 小明

第三方软件 -> 小兔软件

授权服务 -> 京东商家开放平台的授权服务

受保护资源 -> 小明店铺在京东上面的订单

图片

为什么授权码和访问口令要分开获取呢?

OAuth2 协议中,用户登录成功后,OAuth2 认证服务器会将用户的浏览器回调到一个回调地址,并携带一个授权码 code。这个授权码 code 一般有效期十分钟且一次有效,用后作废。这避免了在前端暴露 access_token 或者用户信息的风险,access_token 的有效期都比较长,一般为 1~2 个小时。如果泄露会对用户造成一定影响。后端收到这个 code 之后,需要使用 Client Id + Client Secret + Code 去授权服务器换取用户的 access_token

在这一步,实际上授权服务器对第三方应用进行了认证,能够确保来授权服务器获取 access_token 的机器是可信任的,而不是任何一个人拿到 code 之后都能来授权服务器进行 code 换 token。如果 code 被黑客获取到,如果他没有 Client Id + Client Secret 也无法使用,就算有,也要和真正的应用服务器竞争,因为 code 一次有效,用后作废,加大了攻击难度。相反,如果不经过 code 直接返回 access_token 或用户信息,那么一旦泄露就会对用户造成影响。

简单说就是,client secret 不能暴露给前端(验证 client),用户授权(获取 code)又只能前端做,因此需要分两步。

OIDC(OpenID Connect)

既然 OAuth 本身就隐含了身份验证,那么为什么不以标准化的形式将身份验证的结果导出,使得第三方应用可以使用呢?这就是 OIDC 要做的事情了。那身份验证的结果是什么?很简单,它就是用户的各种信息。

OIDC 怎么做?简单来说,就是在 OAuth 返回 access token 的时候顺带返回 id tokenid token 的格式是 JWT,第三方应用可使用非对称公钥或者对称密码验证 id token 的合法性和有效性,而 id token 本身也包含了基本用户信息。另外,OIDC 提供了 UserInfo endpoint,第三方应用可携带 access token 访问该 endpoint 以获取额外的用户信息。

OIDC 还有一个好处,就是单点登录(SSO,Single Sign On)和单点注销(SLO,Single LogOut)。跟 OAuth 类似,OIDC 提供的集中化身份验证,它可以对应多个应用。只要用户成功登录了一个应用,那么当他登录其他应用的时候,就无需再进行一次身份验证了(例如输入用户名密码),那是因为授权服务器在用户的浏览器里面存下了 cookie。而单点注销则是用户注销了一个应用,其他应用也顺便注销了,注销既可以借由浏览器来做,也可以由第三方应用的后端与授权服务器之间来做。注销的时候指定的参数就是 id token 里面的 session 字段。

注意:OIDC 并没有指定身份验证的具体方式,例如传统的密码或者刷脸,而是指定了如何将身份验证委托给一个集中化的身份验证提供者,在身份验证通过后得到什么凭证(id token),这个凭证如何被校验(JWT 格式),这个凭证包含了哪些用户信息。这样第三方应用就无需重造轮子了。OAuth 提供了集中化的授权,而 OIDC 则是在此基础上进一步提供了集中化的身份验证。

APISIX 对 OAuth/OIDC 的支持

Apache APISIX 是一个开源的云原生 API 网关,作为 API 网关,它兼具动态、实时、高性能等特点,提供了负载均衡、动态上游、灰度发布、服务熔断、身份认证、可观测性等丰富的流量管理功能。你可以使用 APISIX 来处理传统的南北向流量,以及服务间的东西向流量,也可以当做 K8s Ingress controller 来使用。

APISIX 既然是 API 网关,为多个上游应用服务器做代理,那么集中授权、集中身份认证,放在 API 网关是最自然不过的事情了。

APISIX 的 openid-connect 插件支持 OpenID Connect 协议,用户可以使用该插件让 APISIX 对接众多认证鉴权软件,如 Okta、Keycloak、Ory Hydra、Authing 等,作为集中式认证网关部署于企业中。OIDC是OAuth的超集,所以这个插件也隐含了对OAuth的支持。

部署图如下所示:

图片

配置实例:使用 Keycloak 与 API 网关保护你的 API配置 Keycloak

信息取值
keycloak地址http://127.0.0.1:8080/
Realmmyrealm
Client TypeOpenID Connect
Client IDmyclient
Client Secrete91CKZQwhxyDqpkP0YFUJBxiXJ0ikJhq
Redirect URIhttp://127.0.0.1:9080/anything/callback
Discoveryhttp://127.0.0.1:8080/realms/myrealm/.well-known/openid-configuration
Logout URI/anything/logout
Usernamemyuser
Passwordmyrealm
Realmmypassword

场景示例

curl -XPUT 127.0.0.1:9080/apisix/admin/routes/1 -H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" -d '{
    "uri":"/anything/*",
    "plugins": {
        "openid-connect": {
            "client_id": "myclient",
            "client_secret": "e91CKZQwhxyDqpkP0YFUJBxiXJ0ikJhq",
            "discovery": "http://127.0.0.1:8080/realms/myrealm/.well-known/openid-configuration",
            "scope": "openid profile",
            "bearer_only": false,
            "realm": "myrealm",
            "redirect_uri": "http://127.0.0.1:9080/anything/callback",
            "logout_path": "/anything/logout"
        }
    },
    "upstream":{
        "type":"roundrobin",
        "nodes":{
            "httpbin.org:80":1
        }
    }
}'

创建 API 成功后访问 http://127.0.0.1:9080/anything/test 时,由于未进行登录,因此将被引导到 Keycloak 的登录页面:

图片

输入账号(myuser)、密码(mypassword)完成登录后,成功跳转到 http://127.0.0.1:9080/anything/test 页面:

图片

访问 http://127.0.0.1:9080/anything/logout 退出登录:

图片

总结

本文介绍了 OAuth 协议由来和授权流程,引入更上一层的身份层协议 OIDC 并提供了详细的配置示例。 作为最流行的鉴权方式,OAuth/OIDC 通过 APISIX 的鉴权插件在 API 网关层面进行集中化鉴权管理,使得客户端和上游服务器之间免去重复繁琐的鉴权部署和维护。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/335919.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

error when starting dev server:Error: Failed to resolve vue/compiler-sfc.

对于node 的包管理工具,我一般习惯用 yarn,但是最近使用 yarn 创建前端项目的时候出了一些问题。yarn create vite vite-project报错如下:error when starting dev server:Error: Failed to resolve vue/compiler-sfc.vitejs/plugin-vue requ…

[Arxiv 2022] A Novel Plug-in Module for Fine-Grained Visual Classification

Contents MethodPlug-in ModuleLoss functionExperimentsReferencesMethod Plug-in Module Backbone:为了帮助模型抽取出不同尺度的特征,作者在 backbone 里加入了 FPNWeakly Supervised Selector:假设 backbone 的 i i

LayUI渲染数据失败之Ajax异步交互

案例 在layui中调用jquery的ajxa,返回数据,赋值给全局变量,通过DOM渲染到页面。 //定义变量 let sale;//定义请求 $.ajax({type: "GET",url: "http://localhost:8080/product/sale",data: null,dataType: "json&q…

离散数学 课时一 命题逻辑的基本概念

1 命题 1、命题:可以判断其真值的陈述句 2、真值:真或者假(1或者0) 3、真命题:真值为真的命题 4、假命题:真值为假的命题 5、原子命题:不可以再被分解成更简单的命题 6、复合命题:由原子命题通过联结词联结…

12 Day:内存管理

前言:今天我们要完成我们操作系统的内存管理,以及一些数据结构和小组件的实现,在此之前大家需要了解我们前几天一些重要文件的内存地址存放在哪,以便我们更好的去编写内存管理模块 一,实现ASSERT断言 不知道大家有没有…

< Linux >:Linux 进程概念 (4)

目录 五、孤儿进程 六、进程优先级 6.1、基本概念 6.2、查看时实系统进程 6.3、PRI and NI 七、其他概念 四、X 状态:死亡状态 所谓进程处于 X 状态(死亡状态)代表的就是该进程已经死亡了,即操作系统可以随时回收它的资源(操作系统也可以…

代码质量与安全 | 开发人员必备的安全编码实践指南

在任何新的软件开发项目开始时,您就应该考虑软件安全。开始一个新项目或许会令人望而生畏,因为有许多的决定要做,有许多想法必须考虑清楚。通常来说,这些决定和想法包括了定义项目需求、选择正确的流程、选择正确的工具以及确保软…

QML- 导入库包语法

QML- 导入库包语法一、概述二、Import语句的语法1. Module (namespace) 模块(命名空间)导入1. 非模块命名空间的导入2. 导入到限定局部命名空间2. 路径 import1. 本地目录导入2. 远程目录3. JavaScript资源导入三、QML导入路径四、调试一、概述 import 语句其实在QML文档里面体…

Springboot扩展点之SmartInstantiationAwareBeanPostProcessor

前言这是Springboot扩展点系列的第5篇了,主要介绍一下SmartInstantiationAwareBeanPostProcessor扩展点的功能特性、和实现方式。SmartInstantiationAwareBeanPostProcessor与其他扩展点最明显的不同,就是在实际的业务开发场景中应用到的机会并不多&…

机器学习框架sklearn之特征降维

目录特征降维概念特征选择过滤式①低方差特征过滤②相关系数③主成分分析特征降维 0维 标量 1维 向量 2维 矩阵 概念 降维是指在某些限定条件下,降低随机变量(特征)个数,得到一组“不相关”主变量的过程 注:正是…

微信小程序 java 医生预约挂号答疑问询系统

生预约答疑系统用户端是基于微信小程序端,医生和管理员是基于网页后端。本系统分为用户,管理员,医生三个角色,用户的主要功能是注册登陆小程序,查看新闻资讯,查看医生列表,预约医生,…

【unity细节】关于资源商店(Package Maneger)无法下载资源问题的解决

👨‍💻个人主页:元宇宙-秩沅 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 本文由 秩沅 原创 收录于专栏:unity细节和bug ⭐关于资源商店为何下载不了的问题⭐ 文章目录⭐关于资源商店为何下载不了的问题…

鸟哥的Linux私房菜读书笔记:文件系统的简单操作

磁盘与目录的容量 现在我们知道磁盘的整体数据实在superblock区块中,但是每个个别文件的容量则在inode当中记载的. 那在命令行下面该如何显示处这几个数据呢? df:列出文件系统的整体磁盘书用量du:评估文件系统的磁盘使用量(常用在推估目录所占容量)df先来说明一下范例一所输…

网络协议(四):网络互联模型、物理层、数据链路层

网络协议系列文章 网络协议(一):基本概念、计算机之间的连接方式 网络协议(二):MAC地址、IP地址、子网掩码、子网和超网 网络协议(三):路由器原理及数据包传输过程 网络协议(四):网络互联模型、物理层、数据链路层 目录一、网…

HER2靶向药物研发进展-销售数据-上市药品前景分析

HER2长期作为肿瘤领域的热门靶点之一,其原因是它在多部位、多种形式的癌症中均有异常的表达,据研究表明HER2除了在胃癌、胆道癌、胆管癌、乳腺癌、卵巢癌、结肠癌、膀胱癌、肺癌、子宫颈癌、子宫浆液性子宫内膜癌、头颈癌、食道癌中的异常表达还存在于多…

从0到0.1学习 maven(三:声明周期、插件、聚合与继承)

该文章为maven系列学习的第三篇,也是最后一篇 第一篇快速入口:从0到0.1学习 maven(一:概述及简单入门) 第二篇快速入口:从0到0.1学习 maven(二:坐标、依赖和仓库) 文章目录啥子叫生命周期生命周期详解clean生命周期def…

统计检验(一)// 方差分析

【应用案例】 检验不同组(即不同收入者)是否存在“品类满意度”显著差异。各组的满足度平均值如下: 【操作步骤】 方差分析的前提条件是各组总体方差没有显著差异。 第一步:方差同质性检验 原假设:没有差异。 结论…

接口测试入门,如何划分接口文档

1.首先最主要的就是要分析接口测试文档,每一个公司的测试文档都是不一样的。具体的就要根据自己公司的接口而定,里面缺少的内容自己需要与开发进行确认。 我认为一针对于测试而言的主要的接口测试文档应该包含的内容分为以下几个方面。 a.具体的一个业…

时间复杂度的计算(2023-02-10)

时间复杂度的计算 时间复杂度的计算分为三大类&#xff1a;一层循环、二层循环和多层循环。 一层循环 1.找出循环趟数t及每轮循环i的变化值 2.确立循环停止的条件 3.得出t与i之间的关系 4.联立两式&#xff0c;得出结果 eg: void fun(int n) {int i0;while (i*i*i<n)i;…

LeetCode刷题模版:292、295、297、299-301、303、304、309、310

目录 简介292. Nim 游戏295. 数据流的中位数297. 二叉树的序列化与反序列化【未理解】299. 猜数字游戏300. 最长递增子序列301. 删除无效的括号【未理解】303. 区域和检索 - 数组不可变304. 二维区域和检索 - 矩阵不可变309. 最佳买卖股票时机含冷冻期310. 最小高度树【未理解】…