OAuth 2.0是一个关于授权的开放网络协议,允许用户授权第三方应用访问其在服务提供商上存储的资源(如照片、视频、联系人列表),而无需将用户名和密码提供给第三方应用。OAuth 2.0在第三方应用与服务提供商之间设置了一个授权层,将用户与客户端区分开来,使得第三方应用不能直接登录服务提供商,只能登录授权层。服务提供商根据令牌的权限范围和有效期,向第三方应用开放用户资源。
与OAuth 1.0相比,OAuth 2.0不向后兼容,且更加关注客户端开发者的简易性。同时,OAuth 2.0为Web应用、桌面应用、手机和起居室设备提供了专门的认证流程。在认证和授权的过程中涉及的三方包括:服务提供方(用户使用服务提供方来存储受保护的资源,如照片、视频、联系人列表)、用户(存放在服务提供方的受保护的资源的拥有者)和客户端(即第三方应用)。
- 用户不再需要注册大量账号。在以前,每使用一个新的网站或者APP都需要注册一个账号,建立一套新的账户体系才能使用网站或APP提供的服务。而OAuth2.0简化了这个过程,用户只需要授权给第三方应用,就可以让第三方应用访问特定的资源。
- OAuth2.0可以实现单点登录。如果一个公司有很多个需要用户登录才能提供服务的子产品(比如:官网、APP、微信公众号等),这种情况下为每个产品都开发一个登录、授权模块显然是不太优雅。使用OAuth2.0可以让所有需要登录的产品都请求同一个登录授权中心,进行统一登录授权处理。
- OAuth2.0可以用于分布式系统的权限控制。因为基于OAuth2.0协议获得的令牌(Access Token)同时关联了接入的第三方应用、授权用户、权限范围等信息。因此,在第三方应用拿着Token请求资源的时候,资源服务应用就可以很容易根据其访问权限返回相应的数据。
- OAuth 2.0关注客户端开发者的简易性。它为Web应用、桌面应用和手机,以及智能家居设备提供专门的认证流程。
OAuth 2.0协议的主要作用是授权,它允许用户授权第三方应用访问其在服务提供商上存储的资源(如照片、视频、联系人列表),而无需将用户名和密码提供给第三方应用。这个协议关注客户端开发者的简易性,为Web应用、桌面应用和手机,以及智能家居设备提供专门的认证流程。
在OAuth 2.0中,用户通过客户端向服务提供方请求一个临时令牌,该令牌授权第三方应用在特定的时段内访问特定的资源。用户只需授权一次,就可以让第三方应用访问其存储在服务提供者上的信息,而不需要每次都分享他们的访问许可或他们数据的所有内容。
对于第三方应用来说,无需存储用户相关账号密码等信息;对于用户访问来说,省去注册用户等繁琐步骤。因此,OAuth 2.0广泛应用于一些知名网站(如QQ、微信、微博等)授权第三方应用(比如:自己搭建的应用),以获取知名网站用户的个人信息,如昵称、性别、头像等。
在手机上扫描二维码进行授权,将重定向到客户端应用提供的URL。
客户端使用上一步获取的授权码,向官方授权服务器申请令牌(Token);
官方授权服务器对客户端进行认证以后,确认无误,同意发放令牌;
客户端使用令牌向资源服务器(微信)申请获取资源;
资源服务器(微信)确认令牌无误后,同意向客户端开放资源;
Third-party application:第三方应用程序,又称"客户端"(client),即例子中的"Gitee"。
HTTP service:HTTP服务提供商,简称"服务提供商",即例子中的微信。
Resource Owner:资源所有者,又称"用户",也就是你(user)。
User Agent:用户代理,比如浏览器。
Authorization server:授权服务器,即服务提供商专门用来处理认证授权的服务器。
Resource server:资源服务器,即服务提供商存放用户生成的资源的服务器。它与授权服务器,可以是同一台服务器,也可以是不同的服务器。
OAuth的作用就是让"客户端"安全可控地获取"用户"的授权,与"服务提供商"进行交互。
主要角色
- 资源拥有者(Resource Owner):通常是用户,拥有并授权访问其个人资源。
- 客户端(Client):负责发起资源请求的应用或服务,比如第三方应用。
- 资源服务(Resource Server):存储并处理用户资源的服务器。
- 认证服务器(Authorization Server):负责处理用户的授权请求,颁发访问令牌。
- 客户端向用户请求授权,并出示自己的身份。
- 用户在客户端的网页上输入用户名和密码,然后授权该客户端访问所请求的资源。
- 授权成功后,服务提供方引导用户返回客户端的网页。
- 客户端根据临时令牌从服务提供方那里获取访问令牌。
- 服务提供方根据临时令牌和用户的授权情况授予客户端访问令牌。
- 客户端使用获取的访问令牌访问存放在服务提供方上的受保护的资源。
(A)用户打开客户端以后,客户端要求用户给予授权。
(B)用户同意给予客户端授权。
(C)客户端使用上一步获得的授权,向认证服务器申请令牌。
(D)认证服务器对客户端进行认证以后,确认无误,同意发放令牌。
(E)客户端使用令牌,向资源服务器申请获取资源。
(F)资源服务器确认令牌无误,同意向客户端开放资源。
令牌又时效性,一般是短期的,且不能修改,密码一般是长期有效的
令牌可以由颁发者撤销,且即时生效,密码一般可以不用修改而长期有效
令牌可以设定权限的范围,且使用者无法修改
在使用令牌时需要保证令牌的保密,令牌验证有效即可进入系统,不会再做其他的验证。
- 授权码模式(Authorization Code):这是最常用且安全级别最高的授权模式。在授权码模式下,客户端首先通过用户在授权服务器上获取授权码(Authorization Code)。然后,客户端使用这个授权码向授权服务器换取访问令牌。
- 隐式模式(Implicit):这种模式适用于纯前端应用,没有后端服务。客户端直接请求授权服务器获得访问令牌,并将其存储在前端应用中以供以后使用。
- 密码模式(Resource Owner Password Credentials):在这种模式下,客户端直接从用户那里获取用户名和密码,然后使用这些凭据直接向授权服务器请求访问令牌。
- 客户端凭证模式(Client Credentials):在这种模式下,客户端提供自己的凭证(通常是一些证书或者API密钥)来获取访问令牌。这种模式通常用于机器对机器的通信,例如,一个服务器向另一个服务器请求访问某个资源。
授权码模式是最常用且安全级别最高的授权模式。在这种模式下,客户端首先通过用户在授权服务器上获取授权码。然后,客户端使用这个授权码向授权服务器换取访问令牌。具体流程包括用户访问页面时,重定向到认证服务器,认证服务器给用户一个认证页面,等待用户授权,用户在认证页面上做出决定,认证服务器接收用户的决定并返回授权码给客户端,客户端在后台向授权服务器请求令牌,并使用授权码换取访问令牌。
适用场景:目前主流的第三方验证都是采用这种模式
(A)用户访问客户端,后者将前者导向授权服务器。
https://www.example.com/v1/oauth/authorize? response_type=code& client_id=CLIENT_ID& redirect_uri=CALLBACK_URL& scope=read& state=xxx
参数说明
参数类型 | 说明 |
---|---|
response_type | 授权类型,必选项,此处的值固定为"code" |
client_id | 客户端的ID,必选项 |
redirect_uri | 重定向URI,认证服务器接受请求之后的调转连接,可以根据这个连接将生成的授权码回传,必选项 |
scope | code发送给资源服务器申请的权限范围,可选项 |
state | 任意值,认证服务器会原样返回,用于抵制CSRF(跨站请求伪造)攻击。 |
(B)用户选择是否给予客户端授权。
(C)用户给予授权,授权服务器将用户导向客户端事先指定的"重定向URI"(redirection URI),同时附上一个授权码。
https://client.example.com/cb? code=SplxlOBeZQQYbYS6WxSbIA& state=xxx
参数说明
参数类型 | 说明 |
---|---|
code | 授权码,必选项。授权码有效期通常设为10分钟,一次性使用。该码与客户端ID、重定向URI以及用户,是一一对应关系。 |
state | 原样返回客户端传的该参数的值 |
(D)客户端收到授权码,附上早先的"重定向URI",向授权服务器申请令牌。这一步是在客户端的后台的服务器上完成的,对用户不可见。
https://www.example.com/v1/oauth/token? client_id=CLIENT_ID& client_secret=CLIENT_SECRET& grant_type=authorization_code& code=AUTHORIZATION_CODE& redirect_uri=CALLBACK_URL
参数说明
参数类型 | 说明 |
---|---|
client_id | 表示客户端ID,必选项 |
client_secret | 表示安全参数,只能在后端发请求 |
grant_type | 表示使用的授权模式,必选项,此处的值固定为"authorization_code" |
code | 表示上一步获得的授权码,必选项 |
redirect_uri | 表示重定向URI,必选项,且必须与A步骤中的该参数值保持一致 |
(E)授权服务器核对了授权码和重定向URI,确认无误后,向客户端发送访问令牌(access token)和更新令牌(refresh token)。
{
"access_token":访问令牌,
"token_type":"bearer",
"expires_in":过期时间,
"refresh_token":"REFRESH_TOKEN",
"scope":"read",
"uid":用户ID,
"info":{...}
}
参数说明
参数类型 | 说明 |
---|---|
access_token | 访问令牌,必选项 |
token_type | 令牌类型,该值大小写不敏感,必选项 |
expires_in | 过期时间,单位为秒。如果省略该参数,必须其他方式设置过期时间 |
refresh_token | 更新令牌,用来获取下一次的访问令牌,可选项 |
scope | 权限范围,如果与客户端申请的范围一致,此项可省略 |
隐式授权模式适用于纯前端应用,没有后端服务。在这种模式下,客户端直接请求授权服务器获得访问令牌,并将其存储在前端应用中以供以后使用。由于访问令牌是在客户端的浏览器中存储的,因此存在一定的安全风险。
在这种模式下,客户端直接从用户那里获取用户名和密码,然后使用这些凭据直接向授权服务器请求访问令牌。这种模式的优点是简单易用,但存在安全风险,因为用户密码可能会被泄露。
适用场景:公司搭建的授权服务器
在这种模式下,客户端提供自己的凭证(通常是一些证书或者API密钥)来获取访问令牌。这种模式通常用于机器对机器的通信,例如,一个服务器向另一个服务器请求访问某个资源。这种模式的优点是可以减少对用户的依赖,但需要确保客户端凭证的安全性。