其他分享
首页 > 其他分享> > 理解OAuth2.0协议和授权机制

理解OAuth2.0协议和授权机制

作者:互联网

无论是自然资源还是互联网上的资源,需要控制使用权与被使用权,以保护资源的安全、合理的使用和有效的管控。

项目中,我们需要控制的是用户资源,既要保证有效用户的合理使用,又要防范非法用户的攻击。如此,如何区分有效和非法就是我们需要考虑的问题,简单点,通过账号密码来区分,能够通过检测的便是有效用户。

图片

可当项目越来越复杂,用户还想使用第三方应用,那么不能将账号密码交给第三方吧,同时,尽管通过账号密码检测了是有效用户,那么是否就能够访问资源、使用资源呢,这也未必。

图片

种种因素下,OAuth(Open Authorization)作为一个安全、开放且简易的标准,方便我们在项目中协调资源、控制授权,以在用户、第三方应用和用户资源三者间形成一个有效的控制机制,而无需将用户的账号密码提供给第三方应用,且还能控制第三方应用对资源的访问与使用。

An open protocol to allow secure authorizationin a simple and standard method from web, mobile and desktop applications.

认证与授权

对于第三方应用想要访问被保护的资源,应当是使用授权访问,而这前提是要经过认证环节,毕竟认证成功,但不代表就有权限访问资源。OAuth更多的是侧重于如何实现授权来控制第三方应用能够访问资源。认证协议是基于其上的Open ID Connect。尽管OAuth的流程中存在认证部分内容,但不能说OAuth就是认证协议。

OAuth历史

OAuth 的历史版本中有 OAuth 1.0 和 OAuth 2.0,其中 OAuth 1.0 在 2010 年发表为 RFC5849,OAuth 2.0 为 RFC6749,并且 OAuth 2.0 不向下兼容 OAuth 1.0,目前 OAuth 2.0 被广泛使用,因此这里不再对 OAuth 1.0 进行更多的描述。

OAuth的几种角色

图片

OAuth的工作流程

图片

获取授权过程:

(A) 用户(Resource Owner)访问第三方应用(Client),第三方应用(Client)向授权服务器(Authorization Server)发起请求,即第三方应用(Client)向用户(Resource Owner)请求授权。

(B)用户(Resource Owner)输入账号密码,勾选允许的资源范围,提交表单,授权服务器验证后返回授权许可给第三方应用(Client)。

(C) 第三方应用(Client)再带着授权许可请求授权服务器(Authorization Server)换取访问令牌(Access_token)。

(D) 授权服务器(Authorization Server)验证第三方应用(Client)的身份和授权许可,然后给第三方应用(Client)返回访问令牌(Access_token)。

获取资源过程:

(E) 第三方应用(Client)拿访问令牌(Access_token)去请求资源服务器(Resource Server)获取资源。

(F) 资源服务器(Resource Server)返回允许范围内的资源给第三方应用(Client)。

OAuth的几种授权方式

在增加了一个Authorization Server角色后,存在几种常用获取授权许可(资源所有者授权能够访问资源服务器内有效范围资源的凭据,供第三方应用来访问资源服务器)的方式。

如上四种模式有一个前提是第三方应用需要在授权服务器中有过登记注册过程。不应该让随便一个第三方应用需要请求资源,就跳转到授权服务器,然后让资源所有者完成授权,然后便可去访问资源。而应该是有效的第三方应用,何为有效,在授权服务器中有过登记,并返回给第三方客户端一对识别码,客户端Id和客户端密钥,由第三方应用私有保存,这个很是常见。

授权码

授权码是目前 OAuth 2.0 中最常用的。通过去授权端获取授权码,利用授权码换取 token,通过使用 token 去资源服务器获取受保护资源。

图片

核心部分在于红色部分,细讲这几部分

1、当前访问的客户端的URL地址重定向到授权服务器的授权地址(2.0~2.1)

https://authorization-server.com/auth
 ?response_type=code
 &client_id=29352915982374239857
 &redirect_uri=https%3A%2F%2Fexample-app.com%2Fcallback
 &scope=create+delete
 &state=xcoiv98y2kd22vusuye3kch

参数说明:

2、授权页中同意授权,重定向回Client提供的重定向地址(3.0~3.3)

https://example-app.com/redirect
 ?code=g0ZGZmNjVmOWIjNTk2NTk4ZTYyZGI3
 &state=xcoiv98y2kd22vusuye3kch

参数说明:

重定向回到Client后,Client获取到授权码,向授权服务器发送Post请求,以换取访问令牌。

POST 
https://authorization-server.com/auth/token
Content-Type: application/x-www-form-urlencoded

参数:
  grant_type=code
  &code=Yzk5ZDczMzRlNDEwY
  &redirect_uri=https://example-app.com/cb
  &client_id=mRkZGFjM
  &client_secret=xRsjfkgfgfdfvxsfg

参数说明:

{
    "access_token": "MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3",
    "token_type": "bearer",
    "expires_in": 3600,
    "refresh_token": "IwOGYzYTlmM2YxOTQ5MGE3YmNmMDFkNTVk",
    "scope": "create delete"
}

核心部分授权码流程结束,后续便是拿着访问令牌获取资源。

问题解惑

虽然整个流程算是清晰了,但还是存在一些疑惑,如下所示,也随着更多的了解也有了答案。纯属自问自答了。

1、授权码是一个临时的,用来令Client向Authorization Server换取访问令牌(Access token),那么这一次获取到访问令牌,并获取到了资源后。User再次访问同样的资源,这个授权码换取访问令牌的过程没有了,那么如何从哪里获取访问令牌以去访问资源呢?

答:除了返回Access_token还返回了一个Refresh_token。Access_token有短暂的生命周期,如果过期了就用Refresh_token去刷新或是获取一个新的Access_token。Refresh_token的生命周期更长。

2、当一次访问资源的流程结束后,下一次再访问时,如何可以不要再登录了,也就是这个流程中并没返回标识信息到User,如何判断User有效并可以不用重定向到用户登录页?

答:该部分标识用户身份属于OIDC的部分与OAuth无关,OAuth目的是访问受保护的资源。OIDC中有个ID token,一般为JWT格式,用于返回给前端,然后请求时携带着以标识用户身份。又或者是采用Cookie+Session方式来标识用户。具体点就是从AuthServer重定向到Client时已经带上了身份标识信息。

3、Refresh_token是需要Client端存起来吗,如何标识这个Client端对应是哪个User?

答:标识Client端对应的是哪个User,这部分不是OAuth2.0协议所关注的,这部分更多是OIDC协议的事情。至于Refresh_token的存储,如下方式可以。

需要注意

隐式授权

在授权码的环节上做了一些简化,原有返回授权码的过程变成了直接返回访问令牌。这种情况在纯前端Web应用中(如SPA、浏览器插件)常出现,没有后台,在浏览器中需要负责完成所有过程。

图片

相比于授权码形式,少了Client Server与Authorization Server完成交换Access Token过程,而是直接将返回授权码替换成了返回Access Token(这种方式存在着一些安全问题)。除非没得选,不然不会考虑这种方式,因为提出这种方式是十年前,浏览器功能受限,现如今功能更加强大,更多是采用授权码类型加PKCE来代替隐式授权类型。

https://developer.okta.com/blog/2019/05/01/is-the-oauth-implicit-flow-dead

核心部分在于红色部分,细讲这几部分

1、当前访问的客户端的URL地址重定向到授权服务器的授权地址(2.0)

https://authorization-server.com/auth
 ?response_type=token
 &client_id=29352915982374239857
 &redirect_uri=https%3A%2F%2Fexample-app.com%2Fcallback
 &scope=create+delete
 &state=xcoiv98y2kd22vusuye3kch

参数说明:

2、授权页中同意授权,重定向回Client提供的重定向地址(3.0~3.3)

https://example-app.com/redirect
 #access_token=g0ZGZmNjVmOWIjNTk2NTk4ZTYyZGI3
 &state=xcoiv98y2kd22vusuye3kch
 &expires_in=3600
 &token_type=Bearer
 &scope=create

参数说明:

问题解惑

1、这样返回的Access token生命周期很短同时又不会返回Refresh token,如果多次请求,那么就失效了得重新登录了?

答:隐式授予流程不能用于获取刷新令牌,由于基于浏览器的应用基本上都是短时的连接,仅持续加载它们的浏览器的上下文的会话长度,因此,刷新令牌的用途非常有限。与其他授予类型不同,可以假定资源所有者仍处于浏览器中,并在必要的时候可用于重新授权客户端。授权服务器仍能够应用首次使用信任(TOFU)原则从而使重新认证成为无缝的用户体验。

需要注意

重定向返回时的返回参数形式上和授权码模式有所不一样,隐式授权将token信息放在了url的hash部分(#后面),而不是作为查询字符串(?后面)。这样浏览器在访问重定向的Location指定的url时,就不会把这些数据发送到服务器。而Client可以通过读取Location头信息中获取到access_token信息。

客户端凭证授权

有些场景下,资源所有者不能直接参与,即没有与用户的交互这一过程,像后台任务,定时Job等是直接由Client Server去请求Authorization Server,这种即Machine to Machine。

图片

核心部分在于红色部分,细讲这几部分

1、当前客户端发起Post请求授权服务器(4.1)

POST请求
https://authorization-server.com/auth
 
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
scope=create+delete
 
携带请求头,其中Basic对应值xxx为clientid:clientsecret然后经base64编码
Authorization: Basic xxx

客户端提供以下参数请求Authorization Server:

  1. grant_type:必选。值固定为“client_credentials”。
  2. scope:可选。表示授权范围。

2、授权服务器认证Client端信息无误后返回访问令牌(4.2)

参数说明:

资源所有者密码凭证授权

这种方式将资源所有者的身份标识信息(账号密码,提供给Client,然后Client再去授权服务器换取访问令牌),这种安全风险大,更多是完全信任Client才会使用。

图片

核心部分在于红色部分,细讲这几部分

1、当前客户端发起Post请求授权服务器(4.1~4.2)

POST请求
https://authorization-server.com/auth

Content-Type: application/x-www-form-urlencoded
grant_type=password&username=yourname&password=123qwe

请求头,其中Basic对应值xxx为clientid:clientsecret然后经base64编码
Authorization: Basic xxx
  1. grant_type:必选。值固定为“password”。
  2. username:必选。用户登陆名。
  3. passward:必选用户登陆密码。
  4. scope:可选。表示授权范围。

参考

https://developer.okta.com/
https://www.cnblogs.com/linianhui/p/oauth2-authorization.html#auto-id-4

2022-02-26,望技术有成后能回来看见自己的脚步

标签:理解,访问,token,Client,授权,服务器,OAuth2.0,资源
来源: https://www.cnblogs.com/CKExp/p/15938916.html