tl; dr:这都是出于安全原因。
OAuth 2.0希望满足以下两个条件:
- 您希望允许开发人员使用非HTTPS重定向URI,因为并非所有开发人员都具有启用SSL的服务器,并且如果这样做的话,并非总是正确配置的(非自签名,受信任的SSL证书,同步的服务器时钟...)。
- 您不希望黑客能够通过拦截请求来窃取访问/刷新令牌。
详情如下:
由于安全原因,隐式流仅在浏览器环境中才可能:
在隐式流中,访问令牌作为散列片段(而不作为URL参数)直接传递。关于哈希片段的重要一件事是,一旦您跟随包含哈希片段的链接,只有浏览器才知道哈希片段。浏览器会将散列片段直接传递到目标网页(重定向URI /客户端网页)。哈希片段具有以下属性:
- 它们不是HTTP请求的一部分,因此它们不能被服务器读取,因此,它们不能被中间服务器/路由器拦截(这很重要)。
- 它们仅存在于浏览器(客户端)上,因此读取哈希片段的唯一方法是使用页面上运行的JavaScript。
这样就可以将访问令牌直接传递给客户端,而没有被中间服务器拦截的风险。这仅是可能的客户端的警告,并且需要运行JavaScript的javascript客户端才能使用访问令牌。
隐式流还具有安全性问题,例如,需要进一步的逻辑来解决/避免这种情况:
- 攻击者可以从其他网站/应用程序上的用户那里获得访问令牌(假设他是其他网站/应用程序的所有者),将令牌登录到他们的网站上,然后将其作为URL参数传递到您的网站上因此冒充用户在您的网站上。为了避免这种情况,您需要检查与访问令牌关联的客户端ID(例如,对于Google,您可以使用tokeninfo端点)以确保令牌是使用您自己的客户端ID发行的(即通过您自己的应用程序)或检查签名如果您使用的是IDToken(但这需要您的客户机密)。
- 如果auth请求不是来自您自己的属性(称为会话固定攻击),为避免这种情况,您需要从您的网站生成一个随机哈希,将其保存在Cookie中并在状态URL参数中传递相同的哈希auth请求,当用户回来时,您需要使用cookie检查状态参数,并且该参数必须匹配。
在授权码流程中,由于URL参数是HTTP请求的一部分,因此无法直接在URL参数中传递访问令牌,因此,您的请求可以通过的任何中间服务器/路由器(可能是数百个)都可以如果您未使用en-encrypted connection(HTTPS)(即所谓的中间人攻击),请读取访问令牌。
从理论上讲,可以直接在URL参数中传递访问令牌,但是身份验证服务器必须确保重定向URI使用具有TLS加密和“受信任” SSL证书的HTTPS(通常来自不免费的证书颁发机构)确保目标服务器是合法的,并且HTTP请求已完全加密。让所有开发人员购买SSL证书并在其域上正确配置SSL将是一个巨大的痛苦,并且会大大降低其采用速度。这就是为什么要提供一个中间的一次性使用“授权码”的原因,即只有合法的接收者才能进行交换(因为您需要客户机密),并且该代码对于潜在的黑客在未经加密的交易中拦截请求没有用处(因为他们没有
您还可以辩称,隐式流的安全性较低,存在潜在的攻击媒介,例如在重定向时欺骗域-例如通过劫持客户网站的IP地址。这就是为什么隐式流仅授予访问令牌(应该使用有限的时间)而从不刷新令牌(时间不受限制)的原因之一。为解决此问题,我建议您尽可能将网页托管在启用HTTPS的服务器上。