目录
a. 授权码模式(Authorization Code Grant)
c. 密码模式(Resource Owner Password Credentials Grant)
d. 客户端凭证模式(Client Credentials Grant)
一、OAuth2.0概述
OAuth是一种广泛使用的授权框架,允许第三方应用程序在用户授权的情况下访问用户在某个服务上的资源,而无需共享用户的凭据(如用户名和密码)。
比如有一个应用“美食分享”,想要使用用户在微信中的好友名单信息,以便向他们分享美食作品,但问题是,只有得到用户的亲自授权,微信官方才会同意"美食分享"读取这些好友名单。
那么,"美食分享"怎样获得用户的授权呢?有一种方法方法是把自己的微信账号和密码告诉“美食分享”,这样“美食分享”就可以读取用户的微信好友清单了(这里假设有相关接口支持这样操作),但这样做,微信官方肯定不同意,微信用户自己大概也不同意。
OAuth就是为了解决这类问题而产生的。
OAuth 2.0 是 OAuth 协议的第二个版本,由 Internet Engineering Task Force (IETF) 制定。与 OAuth 1.0 相比,OAuth 2.0 更加注重简化和灵活性,提供了多种授权模式以适应不同的应用场景,成为现代 Web 和移动应用程序中实现身份验证和授权的标准实践。
OAuth 2.0 广泛应用于各种场景,如社交登录(使用 Google、Facebook 等账号登录第三方应用)、API 访问授权以及移动应用的资源访问等。其核心思想是通过令牌(Token)交换机制,实现资源的受控访问,而无需暴露用户的敏感凭据。
本文将详细介绍 OAuth 2.0 的各个方面,包括概述、角色、概念、授权模式、安全性、使用场景、扩展以及总结。
附:OAuth2.0规范官方文档
- 文档名称 :The OAuth 2.0 Authorization Framework
- RFC 编号 :RFC 6749
- 发布日期 :2012年10月
二、OAuth2.0中的四个角色
OAuth 2.0 涉及四个主要角色,每个角色在授权流程中扮演不同的职责:
资源所有者(Resource Owner):
- 定义:资源所有者通常是最终用户,拥有被保护的资源(如照片、联系人、个人资料等)。
- 职责:决定是否授权第三方应用程序访问其资源。
客户端(Client):
- 定义:客户端是需要访问用户资源的第三方应用程序,如 Web 应用、移动应用或桌面应用。注意:这里客户端指的不是用户的浏览器。
- 职责:发起授权请求,获取访问令牌,并使用令牌访问资源服务器上的资源。
授权服务器(Authorization Server):
- 定义:授权服务器负责验证用户身份,处理授权请求,并颁发访问令牌和刷新令牌。
- 职责:确保只有经过授权的客户端才能获取访问令牌,并管理令牌的生命周期。
资源服务器(Resource Server):
- 定义:资源服务器托管被保护的资源,并处理客户端使用访问令牌发起的资源请求。
- 职责:验证访问令牌的有效性,并根据令牌的权限返回相应的资源。
三、核心概念
在深入理解 OAuth 2.0 的授权流程之前,需要了解一些关键概念:
第三方应用(客户端):
- 独立于资源拥有平台之外,需要获取用户在该平台资源访问权限的应用程序。如 “美食分享” 应用,希望获取用户在微信上的部分资源,以增强自身应用的功能。
服务提供商(授权服务器):
- 拥有用户资源,并负责对第三方应用的授权请求进行处理和验证的平台。比如微信,不仅存储用户的各类信息(如好友列表、个人资料等),还决定第三方应用是否能够访问以及在何种程度上访问这些资源。
客户端标识(Client ID):
- 服务提供商分配给第三方应用的唯一标识符,用于在授权流程中识别第三方应用的身份。类似于个人的身份证号,是服务提供商识别第三方应用的关键信息。例如,在 “美食分享” 应用与微信的交互中,微信通过 Client ID 识别 “美食分享” 应用。
客户端密钥(Client Secret):
- 与客户端标识配套使用的安全密钥,用于验证第三方应用的身份。只有持有正确客户端密钥的第三方应用才能被服务提供商确认其合法性,从而继续授权流程,提供额外的安全保障。
授权码(Authorization Code):
- 在授权码模式下,授权服务器在用户授权后返回一个授权码,客户端使用该授权码向授权服务器请求访问令牌。
访问令牌(Access Token):
- 由授权服务器颁发的令牌,客户端使用它来访问资源服务器上的受保护资源。访问令牌通常具有有限的有效期和权限范围。
刷新令牌(Refresh Token):
- 一种长期有效的令牌,用于在访问令牌过期后获取新的访问令牌,而无需用户重新授权。刷新令牌通常与访问令牌一起颁发。
作用域(Scope):
- 定义客户端可以访问的资源范围和操作权限。作用域用于限制访问令牌的权限,确保客户端只能访问用户授权的资源。
重定向 URI(Redirect URI):
- 在授权请求中指定的 URI,授权服务器在用户授权后将用户重定向回客户端,并附带授权码或其他响应参数。
客户端凭证(Client Credentials):
- 客户端的唯一标识符和密钥,用于客户端向授权服务器进行身份验证。
四、OAuth2.0的四种授权模式简介与流程
客户端必须得到用户的授权(authorization grant),才能获得令牌(access token)以访问用户在其他平台上存储的资源。
OAuth 2.0 定义了以下四种授权模式:
- 授权码模式(authorization code)
- 简化模式(implicit)
- 密码模式(resource owner password credentials)
- 客户端模式(client credentials)
以适应不同的应用场景和客户端类型。
====================================================
a. 授权码模式(Authorization Code Grant)
适用场景:
适用于有后端服务器的 Web 应用程序,安全性较高。
流程概述:
- 授权请求:客户端将用户重定向到授权服务器,请求授权。
- 用户授权:用户在授权服务器上登录并同意授权。
- 授权码返回:授权服务器将用户重定向回客户端,并附带授权码。
- 令牌请求:客户端使用授权码向授权服务器请求访问令牌。
- 令牌颁发:授权服务器验证授权码并返回访问令牌。
- 资源访问:客户端使用访问令牌向资源服务器请求受保护资源。
优点:
- 安全性高,授权码不直接暴露给用户。
- 支持刷新令牌机制,延长访问权限。
====================================================
b. 隐式模式(Implicit Grant)
适用场景:
适用于单页应用(SPA)等没有后端服务器的客户端。
流程概述:
- 授权请求:客户端将用户重定向到授权服务器,请求授权。
- 用户授权:用户在授权服务器上登录并同意授权。
- 访问令牌返回:授权服务器将用户重定向回客户端,并直接返回访问令牌。
- 令牌使用:客户端(通常是网页中的脚本)从重定向后的 URI 片段中提取访问令牌,并使用该令牌访问受保护的资源。
优点:
- 流程简单,无需客户端处理授权码。
缺点:
- 访问令牌直接暴露给客户端,安全性较低。
- 不支持刷新令牌,需重新授权。
====================================================
c. 密码模式(Resource Owner Password Credentials Grant)
适用场景:
适用于高度信任的客户端,如第一方应用。
流程概述:
- 凭证请求:客户端直接收集用户的用户名和密码。
- 令牌请求:客户端使用用户名和密码向授权服务器请求访问令牌。
- 令牌颁发:授权服务器验证凭据并返回访问令牌。
优点:
- 流程简单,无需重定向。
缺点:
- 客户端需要处理用户凭据,安全性较低。
- 不适用于第三方应用。
====================================================
d. 客户端凭证模式(Client Credentials Grant)
适用场景:
适用于客户端访问自己的资源,而不是用户的资源。
流程概述:
- 凭证请求:客户端使用其客户端 ID 和客户端密钥向授权服务器请求访问令牌。
- 令牌颁发:授权服务器验证客户端凭据并返回访问令牌。
优点:
- 流程简单,适用于客户端自身的资源访问。
缺点:
- 不适用于访问用户资源。
五、授权码模式举例说明
背景说明
假设有一款名为 “美食分享” 的应用,用户可以在该应用中分享自己制作美食的过程、发布美食心得以及上传美食图片等。为了丰富社交功能,让用户能与更多朋友分享美食体验,“美食分享” 应用希望能够获取用户在微信上的好友列表,这样用户就可以方便地邀请微信好友关注自己在 “美食分享” 应用上的美食动态。但直接让用户在 “美食分享” 应用中输入微信账号密码来获取好友列表,存在极大的安全风险,可能导致用户微信账号信息泄露。因此,OAuth 第三方应用授权机制应运而生,它能在保障用户账号安全和隐私的前提下,实现 “美食分享” 应用合法获取用户在微信上的相关资源。
说明:本例中所述微信相关功能接口均为虚构,此处只是为了说明OAuth2.0相关原理。真实的微信网页授权官方文档,请参考:
https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html#1
流程详解
1. 客户端注册:“美食分享”应用在微信开放平台注册,获取唯一的客户端标识(client_id)和客户端密钥(client_secret),以此作为在微信体系中的身份识别信息。说明:在微信的实现中,客户端表示和秘钥分别用参数appID和secret来表示,后面的示例,采用微信的命名风格。
2. 重定向请求授权:应用内用户点击“通过微信邀请好友”等相关授权功能按钮,“美食分享”应用会构建包含:
- grant_type:表示使用的授权模式,必选项,此处的值固定为"authorization_code"。
- appID:表示客户端ID,必选项。
- scope:表示申请的权限范围,该示例中为(获取微信好友列表),可选项。
- state:表示客户端的当前状态,可以指定任意值,认证服务器会原封不动地返回这个值。
- redirect_uri:表示重定向URI,可选项。
等参数的 URL,引导用户浏览器重定向至微信的授权端点(即:https://open.weixin.qq.com/connect/oauth2/authorize)。
URL示例:
https://open.weixin.qq.com/connect/oauth2/authorize?appID=1234567890&redirect_uri=https%3A%2F%2Fmeishishare.example.com%2Fwx_callback&scope=snsapi_friend_list&response_type=code |
3. 同意授权:用户在微信授权页面看到“美食分享”应用获取好友列表的权限请求说明,根据自身意愿决定是否授权。若同意,微信将用户重定向回“美食分享”应用指定的重定向 URI,并在 URL 中附带授权码,例如:https://meishishare.example.com/wx_callback?code=abcdef123456
4. 获取授权码:“美食分享” 应用监测到用户从微信重定向回来的请求,从请求的 URL 中提取出授权码 “abcdef123456”。此授权码是临时的,且只能使用一次,并且有一定的有效时长限制,一般为几分钟,例如 5 分钟。这极大地降低了授权码被窃取滥用的风险。
5. 换取访问令牌:“美食分享”应用向微信的令牌端点发起 HTTP POST 请求,换取访问令牌。请求中需携带授权码、客户端标识(AppID)、客户端密钥(AppSecret)以及重定向 URI 等关键信息。假设微信的令牌端点为https://api.weixin.qq.com/sns/oauth2/access_token ,请求的URL可能如下:
https://api.weixin.qq.com/sns/oauth2/access_token?appID=1234567890&secret=abx123xxddkowenoefser3&code=abcdef123456&grant_type=authorization_code&&redirect_uri=https%3A%2F%2Fmeishishare.example.com%2Fwx_callback |
需要注意的是,由于请求参数的安全级别比较高,为避免泄露,应通过客户端后台服务发送Post请求,而不是通过前端浏览器发送。
微信接收到请求后,会严格验证请求的合法性以及授权码的有效性。若验证通过,微信会生成一个访问令牌,并将其连同其他相关信息,如令牌过期时间、刷新令牌等,返回给 “美食分享” 应用。返回的数据格式类似:
{ "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c", "expires_in": 3600, "refresh_token": "abcdefghijklmnopqrstuvwxyz123456", "openid": "o6_bmjrPTlm6_2sgVt7hMZOPfL2M", "scope": "snsapi_friend_list" } |
6. 使用令牌访问资源:“美食分享” 应用成功获取访问令牌后,便可以利用该令牌向微信的资源端点发送请求,以获取用户的微信好友列表资源。例如,“美食分享” 应用向微信的好友列表资源端点https://api.weixin.qq.com/sns/user_friends 发起 GET 请求,请求的URL可能为:
https://api.weixin.qq.com/sns/userinfo?access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c&openid=o6_bmjrPTlm6_2sgVt7hMZOPfL2M&lang=zh_CN |
微信的资源端点接收到请求后,会根据访问令牌验证请求的合法性以及用户的权限范围。若一切合规,微信将返回用户的好友列表数据给 “美食分享” 应用,“美食分享” 应用即可在自身应用内展示相关功能,方便用户邀请微信好友。
7 刷新访问令牌(可选):随着时间推移,访问令牌会过期失效。当 “美食分享” 应用检测到访问令牌过期后,可利用之前获取的刷新令牌来获取新的访问令牌,而无需用户再次在微信上进行授权操作。“美食分享” 应用向微信的令牌端点发送包含刷新令牌的请求,请求的URL可能为:
https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=1234567890&grant_type=refresh_token&refresh_token=abcdefghijklmnopqrstuvwxyz123456 |
微信验证刷新令牌的有效性后,若通过验证,会生成新的访问令牌并返回给 “美食分享” 应用。这样,“美食分享” 应用就能在不打扰用户的情况下,持续访问用户在微信上的授权资源,只要刷新令牌未过期。
六、隐式模式举例说明
背景说明
假设有一款名为 “美食分享” 的应用,用户可以在该应用中分享自己制作美食的过程、发布美食心得以及上传美食图片等。为了丰富社交功能,让用户能与更多朋友分享美食体验,“美食分享” 应用希望能够获取用户在微信上的好友列表,这样用户就可以方便地邀请微信好友关注自己在 “美食分享” 应用上的美食动态。但直接让用户在 “美食分享” 应用中输入微信账号密码来获取好友列表,存在极大的安全风险,可能导致用户微信账号信息泄露。因此,OAuth 第三方应用授权机制应运而生,它能在保障用户账号安全和隐私的前提下,实现 “美食分享” 应用合法获取用户在微信上的相关资源。
说明:本例中所述微信相关功能接口均为虚构,此处只是为了说明OAuth2.0相关原理。真实的微信网页授权官方文档,请参考:
https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html#1
流程详解
1. 客户端注册:“美食分享”应用在微信开放平台注册,获取唯一的客户端标识(client_id)和客户端密钥(client_secret),以此作为在微信体系中的身份识别信息。说明:在微信的实现中,客户端表示和秘钥分别用参数appID和secret来表示,后面的示例,采用微信的命名风格。
2. 重定向请求授权:应用内用户点击“通过微信邀请好友”等相关授权功能按钮,“美食分享”应用会构建包含:
- grant_type:表示使用的授权模式,必选项,此处的值固定为"authorization_code"。
- appID:表示客户端ID,必选项。
- scope:表示申请的权限范围,该示例中为(获取微信好友列表),可选项。
- state:表示客户端的当前状态,可以指定任意值,认证服务器会原封不动地返回这个值。
- redirect_uri:表示重定向URI,可选项。
等参数的 URL,引导用户浏览器重定向至微信的授权端点(即:https://open.weixin.qq.com/connect/oauth2/authorize)。
URL示例:
https://open.weixin.qq.com/connect/oauth2/authorize?appID=1234567890&redirect_uri=https%3A%2F%2Fmeishishare.example.com%2Fwx_callback&scope=snsapi_friend_list&response_type=code |
3. 同意授权:用户在微信授权页面看到“美食分享”应用获取好友列表的权限请求说明,根据自身意愿决定是否授权。若同意,微信将用户重定向回 “美食分享” 应用指定的重定向 URI,并在 URL 的哈希(#)部分附带访问令牌及相关信息,例如:
https://meishishare.example.com/wx_callback?access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c&expires_in=3600&scope=snsapi_friend_list&state=abcdefg |
4. 获取访问令牌:“美食分享” 应用(前端)监测到用户从微信重定向回来的请求,通过前端代码(如 JavaScript)从 URL 的哈希部分提取访问令牌。与授权码模式不同,隐式模式没有中间的授权码环节,直接获取到可用于访问资源的令牌。
5. 使用令牌访问资源:“美食分享” 应用成功获取访问令牌后,便可以利用该令牌向微信的资源端点发送请求,以获取用户的微信好友列表资源。例如,“美食分享” 应用向微信的好友列表资源端点https://api.weixin.qq.com/sns/user_friends 发起 GET 请求,请求的URL可能为:
https://api.weixin.qq.com/sns/userinfo?access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c&openid=o6_bmjrPTlm6_2sgVt7hMZOPfL2M&lang=zh_CN |
微信的资源端点接收到请求后,会根据访问令牌验证请求的合法性以及用户的权限范围。若一切合规,微信将返回用户的好友列表数据给 “美食分享” 应用,“美食分享” 应用即可在自身应用内展示相关功能,方便用户邀请微信好友。
6. 无访问令牌刷新机制:隐式模式不支持刷新令牌功能。当访问令牌过期后,“美食分享” 应用若还需访问用户资源,需引导用户重新进行授权操作,再次重复上述流程获取新的访问令牌。
七、 OAuth2.0的安全性考虑
在使用 OAuth 2.0 时,安全性是至关重要的。以下是一些关键的安全性考虑:
使用 HTTPS:
- 所有通信必须通过 HTTPS 进行,以防止中间人攻击和令牌泄露。
保护客户端凭证:
- 客户端密钥应妥善保管,避免在客户端代码(如前端 JavaScript)中暴露。
验证重定向 URI:
- 授权服务器应验证重定向 URI 的合法性,防止开放重定向攻击。
作用域限制:
- 明确指定客户端可以访问的资源范围和操作权限,遵循最小权限原则。
令牌管理:
- 访问令牌和刷新令牌应安全存储,避免泄露。使用短期有效的访问令牌,并通过刷新令牌机制续期。
防止 CSRF 攻击:
- 在授权请求中使用 state 参数,防止跨站请求伪造攻击。
监控与审计:
- 实施日志记录和监控,及时发现和响应异常活动。
八、 OAuth2.0的使用场景
OAuth 2.0 在现代应用开发中有着广泛的应用,以下是其主要应用场景:
社交登录
- 用户能够利用 Google、Facebook、GitHub 等社交账号登录第三方应用,极大地简化了注册和登录流程。
API 访问授权
- 第三方应用程序可以通过 OAuth 2.0 获取访问令牌,以此来调用受保护的 API 接口,例如获取用户数据或发布内容。
移动应用授权
- 移动应用程序可以使用 OAuth 2.0 来访问用户在其他服务上的资源,如同步联系人信息、照片等。
单点登录(SSO)
- 在企业环境中,多个内部应用可通过 OAuth 2.0 实现单点登录(SSO),提高用户体验并增强安全性。
微服务架构中的认证与授权
- 在微服务架构中,OAuth 2.0 被用于实现服务间的安全通信及资源访问控制,确保系统各部分之间的交互既安全又高效。
九、OAuth2.0的扩展
OAuth 2.0 是一个基础框架,许多扩展和增强功能可以在此基础上实现,以满足特定需求。常见的扩展包括:
OpenID Connect(OIDC)
- 在 OAuth 2.0 的基础上增加了身份验证功能,允许客户端验证用户的身份并获取用户的基本信息。OIDC 通常用于实现单点登录(SSO)。
JSON Web Token(JWT)
- 一种轻量级的令牌格式,常用于 OAuth 2.0 的访问令牌和 ID 令牌。JWT 提供了自包含的声明信息,便于验证和传递。
设备码授权(Device Code Grant)
- 适用于没有浏览器或输入受限的设备,如智能电视、物联网设备。用户通过其他设备完成授权,设备通过轮询获取访问令牌。
PKCE(Proof Key for Code Exchange)
- 增强授权码模式的安全性,特别适用于公共客户端(如移动应用和单页应用),防止授权码拦截攻击。
令牌撤销与黑名单
- 实现机制以在必要时撤销访问令牌,增强系统的灵活性和安全性。
十、 总结
OAuth 2.0 作为一种广泛采用的授权框架,通过简化协议和增强功能,为现代应用程序提供了安全且灵活的身份验证和授权机制。其多种授权模式适应了不同类型的应用场景,结合 HTTPS 加密、作用域限制、令牌管理等安全措施,确保了资源访问的安全性。此外,OAuth 2.0 的扩展如 OpenID Connect 和 JWT 等,进一步增强了其功能和适用性。
在实际开发中,正确实现和配置 OAuth 2.0 是确保应用安全的关键。开发者应深入理解 OAuth 2.0 的各个角色、概念和流程,遵循最佳实践,以构建安全可靠的应用程序。同时,随着技术的发展和安全需求的提升,持续关注 OAuth 2.0 的扩展和演进,将有助于保持应用的安全性和竞争力。
通过掌握 OAuth 2.0,开发者不仅能够实现用户资源的受控访问,还能提升用户体验,构建现代化、安全的 Web 和移动应用。
十一、 相关资料
微信网页授权
彻底理解 OAuth2 协议
Oauth2四种授权流程一口气讲完
Oauth2四种授权流程一口气讲完_哔哩哔哩_bilibili
阮一峰 理解OAuth2.0
理解OAuth 2.0——阮一峰_oauth2.0认证原理 阮一峰-优快云博客
八分钟搞懂Oauth2
阿里二面:什么是SSO、与OAuth2.0有什么关系?问麻了。。。
阿里二面:什么是SSO、与OAuth2.0有什么关系?问麻了。。。_哔哩哔哩_bilibili
ASP.NET没有魔法——ASP.NET MVC使用Oauth2.0实…
ASP.NET MVC使用Oauth2.0实现身份验证 - 冰碟 - 博客园