一、前言
本篇将讨论剩余的授权类型以及使用刷新令牌重新获得令牌等内容,仍然以概念为主。下一节我们将通过一个SSO实例让大家对授权码授权类型更加熟悉。
二、实现密码授权类型
此授权类型也被称为资源所有者凭据授权类型。使用此流程的应用程序会假定客户端收集用户凭据,并使用这些凭据进行身份验证,然后从授权服务器获得访问令牌。
如上图,密码授权类型会假设用户与客户端共享其凭据。客户端使用这些凭据从授权服务器获取令牌。然后,它会以用户名义从资源服务器访问资源。
不知道你还记不记得之前动手过的实践,只是我们没有实现JWT而已,但是思想架构和这个非常相似。当然在后面的学习中,我们会搭建一个真正的OAuth2的密码授权类型架构。
对于密码授权类型,我们应该期望应用程序向用户提供一个登陆表单,并让客户端负责向服务器发送用户凭据以进行身份验证。用户不需要知道我们如何在应用程序中设计身份验证职责。让我们看看使用密码授权类型时会发生什么。涉及的两项任务如下:
(1)请求一个访问令牌
(2)使用该访问令牌调用资源
步骤1:使用密码授权类型时请求访问令牌
使用密码授权类型,流程会简单很多。客户端会收集用户凭据并调用授权服务器来获取访问令牌。当请求访问令牌时,客户端还会在请求中发送以下详细信息:
- 具有password值的grant_type。
- client_id和client_secret,它们是客户端用于对其自身进行身份验证的凭据。
- scope:可以将其理解为已授权权限。
- username和password,它们是用户凭据。会以纯文本的形式将其作为请求头的值来发送。
客户端在响应中接收回一个访问令牌。接下来客户端就可以使用该访问令牌调用资源服务器的端点。
步骤2:使用密码授权类型时,需要使用访问令牌调用资源
一旦客户端有了访问令牌,它就可以使用该令牌调用资源服务器上的端点,这与授权码授权类型完全相同。客户端要在授权请求头中将访问令牌添加到请求。
ps:密码授权类型比授权码授权类型更不安全,主要是因为其前提是要与客户端应用程序共享用户凭据。虽然它确实比授权码授权类型更简单,但是我们仍需尽量不把它放到实际开发中,而是将它放在理论示例当中去。
三、实现客户端凭据授权类型
这是OAuth2所描述的最简单的授权类型。可以在用户不参与的情况下使用它:也就是说,在两个应用程序之间实现身份验证时不需要用户参与。可以将客户端凭据授权类型看作密码授权类型和API密钥身份验证流程的组合。假设有一个使用OAuth2实现身份验证的系统。现在需要允许外部服务器进行身份验证并调用服务器暴露的特定资源。
客户端凭据授权类型的步骤与密码授权类型类似。唯一的例外是对访问令牌的请求不需要任何用户凭据。以下是实现这一授权类型的步骤:
步骤1:使用客户端凭据授权类型请求访问令牌
为了获得访问令牌,客户端要向授权服务器发送一个包含以下详细信息的请求。
- 具有client_credentials值的grant_type;
- client_id和client_secret,它们代表了客户端凭据;
- scope,它表示已授权的权限。
作为响应,客户端将接收到一个访问令牌。接下来客户端可以使用该访问令牌调用资源服务器的端点。
步骤2:使用客户端凭据授权类型时,可访问令牌调用资源
一旦客户端有了访问令牌,它就可以使用该令牌调用资源服务器上的端点,这与授权码授权类型和密码授权类型完全相同。客户端要在授权请求头中将访问令牌添加到请求。
四、使用刷新令牌获得新的访问令牌
本节将讨论刷新令牌。到目前为止,本节已经介绍了OAuth2流程(也称为授权)的结果是一个访问令牌。但其中并没有过多谈论这个令牌本身。归根结底,OAuth2并没有为令牌预设一个特定的实现。接下来将会介绍,无论如何实现,令牌都可鞥过期。这并不是强制的——可以创建具有无限生命周期的令牌——但是,一般来说,都应该使其生命周期尽可能短。而本节将讨论的刷新令牌代表了使用凭据获取新访问令牌的另一种选择。这里将展示在OAuth2中刷新令牌是如何工作的,后面我们再讲具体实现。
假设在应用程序中实现了永不过期的令牌。这意味着客户端可以一次又一次地使用相同的令牌调用资源服务器上的资源。那么如果令牌被偷了,该怎么办?最后,不要忘记令牌作为一个简单的HTTP头信息被附加在每个请求上。如果令牌没有过期,得到令牌的人就可以使用它访问资源。不会过期的令牌太强大了。它变得几乎和用户凭据一样强大。应该避免这种情况,并缩短令牌的生命周期。这样,过期的令牌就不能再使用了。客户端必须获得另一个访问令牌。
要获得新的访问令牌,客户端可以根据所使用的的授权类型重新运行流程。例如,如果授权类型是身份验证授权码,则客户端会将用户重定向到授权服务器登录端点,用户必须再次填写他们的用户名和密码。这对用户不太友好,是吗?假设这个令牌的生命周期只有20分钟,而用户在这个在线应用程序上工作了两个小时。那么在这段时间里,这个应用程序会将用户重定向回去6次,以便再次登录。为了避免重新进行身份验证,授权服务器可以发出刷新令牌,它的值和用途与访问令牌不同。应用程序使用刷新令牌获得一个新的访问令牌,而不必重新进行身份验证。
如何使用刷新令牌,从哪里获得刷新令牌,当使用授权码或密码授权类型等流程时,授权服务器将返回一个刷新令牌和一个访问令牌。对于客户端凭据授权,则不存在刷新令牌,因为此流程不需要用户凭据。一旦客户端有了一个刷新令牌,那么当访问令牌过期时,客户端应该发出一个包含以下详细信息的请求:
- 具有refresh_token值得grant_type;
- 具有刷新令牌值的refresh_token;
- 具有客户端凭据的client_id和client_secret;
- scope,它定义了相同或更少的授权权限。如果需要授权更多已授权的权限,则需要进行重新身份验证。
为了响应此请求,授权服务器会发出一个新的访问令牌和一个新的刷新令牌。
五、OAuth2的弱点
OAuth2并不是无懈可击的。它有其弱点,我们必须意识到这些弱点,并且在构建应用程序时必须考虑这些弱点,这里列举一些最常见的:
- 在客户端上使用跨站请求伪造(CSRF)——用户已登录时,如果应用程序没有应用任何CSRF防护机制,则可能会遇到CSRF
- 窃取客户端凭据——存储或传输未受保护的凭据会造成损失,使攻击者得以窃取和使用他们。
- 重放令牌——这个后面会介绍,令牌时OAuth2身份验证和授权架构中用来访问资源的密钥。这些信息是通过网络发送的,但有时候,它们可能会被拦截。如果被截获,它们就被窃取了,并且可能再次使用。想象一下,如果你把你家大门钥匙弄丢了,会发生什么呢?其他人可以用它打开门,想打开多少次都可以(也就是所谓的令牌重放)
- 令牌劫持——意味着有人入侵身份验证过程并窃取可以用来访问资源的令牌。这也是使用刷新令牌的一个潜在漏洞,因为这些令牌也可以被拦截并用于获取新的访问令牌.这里推荐一片有用的文章
http://blog.intothesymmetry.com/2015/06/on-oauth-token-hijacks-for-fun-and.html