大家都知道OAuth 2.0 有四种不同的grant type,分不同的业务场景来使用,我在前面的一篇文章也有粗略讲过 微服务架构学习笔记之一认证和授权 - 大概怎么去按照不同业务场景来使用OAuth 2.0的不同grant type, 比如下面这张图
但是很多时候还是不能很好的理解为什么要这么划分,关键点在哪里?这又回退到我们要清楚的知道OAuth 2.0 四种不同的grant type的区别是什么。
首先我们先罗列4种的OAuth 2.0的grant type
Authorization Code Flow
Implicit Flow
Resource Owner Password Credential Flow
Client Credential Flow
要回答这四种不同的grant type的区别是什么,需要考虑以下维度:
- 需不需要用户输入用户名密码?
- Client Application是第三方应用还是第一方应用?
- 用户输入用户名和密码的界面是谁来提供的?Authorization Server还是第三方应用?
- Client Application(需要访问你的资源的应用)能否感知和存储authorization code和access token?
对于第一个问题,4种grant type中只有client credential flow是不需要用户输入用户名和密码,这也就不难解释为什么在只有机器执行的场景下,那么就需要采用client credential flow这种OAuth 2.0的方式,只需要约定好client id和client secret就可以去换取access token来进行resource的访问。这种业务场景一般发生在有些服务器需要定时执行一些job的情况。
对于第二个问题,Client Application是第三方应用还是第一方应用?一般来讲,如果是第一方应用(自己开发的应用)一般我们都认为要安全一些,因为不会故意的去泄露访问resource的access token, 所以一般第一方应用我们可以使用简单的resource owner password credential flow, 这种OAuth 2.0 grant type 节省了通过code去交换access token这一步骤(实际上就是节省了一次网络请求来回),直接通过用户名,密码去获取access token。而第三方应用我们需要采用更加安全的OAuth 2.0 flow, 比如authorization code flow 或者 implicit flow. 至于究竟是选择authorization code flow 还是 implicit flow, 那么可以参见下面第四个问题的回答。
对于第三个问题, 这个也是出于安全性的考虑,我们可以看到,authorization code flow 和 implicit flow 的用户输入credential的界面都是由authorization server提供的H5 page,而resource owner password credential flow则是由client application提供的page (可以是Native App Page, 也可以是H5 Page), 由authorization server提供的H5 page会更加安全一点。
对于第四个问题,Client Application(需要访问你的资源的应用)能否感知和存储authorization code和access token? 我们都知道最常用的是authorization code flow,它是最安全的,它需要先通过用户的身份验证,然后获得一个code,再拿这个code去authorization server交换access token和refresh token。而我们都知道access token本身是有时效性的,如果有人很容易的拿到code 或 refresh token,那么就基本上可以随意随时的去访问你的resource了,因为他可以不断的通过refresh token 去刷新access token。 而为什么第三方的SPA使用的是implicit flow 而第三方的Native App却使用的是authorization code flow? 理论上第三方应用都应该使用authorization code flow,但是如果你仔细看下,implicit flow中是没有code 和 refresh token的,而SPA应用(本质上是web,需要通过浏览器的)更加容易去暴露code 和 refresh token, 所以才在第三方的SPA应用中使用了implicit flow,而只给了access token, 一旦过期,则需要重新用户名密码验证。