这都是出于安全考虑。
OAuth 2.0希望满足以下两个标准:
您希望允许开发人员使用非https重定向URI,因为不是所有开发人员都有启用SSL的服务器,如果他们这样做,它并不总是正确配置(非自签名,受信任的SSL证书,同步的服务器时钟……)。
您不希望黑客能够通过拦截请求来窃取访问/刷新令牌。
细节如下:
由于安全原因,隐式流只能在浏览器环境中使用:
在隐式流中,访问令牌直接作为散列片段传递(而不是作为URL参数)。关于哈希片段的一个重要的事情是,一旦你跟随一个包含哈希片段的链接,只有浏览器知道这个哈希片段。浏览器会将散列片段直接传递到目标网页(重定向URI /客户端的网页)。哈希片段具有以下属性:
它们不是HTTP请求的一部分,因此它们不能被服务器读取,因此它们不能被中间服务器/路由器拦截(这很重要)。
它们只存在于浏览器(客户端)上,因此读取散列片段的唯一方法是使用运行在页面上的JavaScript。
这使得直接将访问令牌传递给客户端成为可能,而不会有被中间服务器拦截的风险。这只是可能的客户端,需要javascript运行客户端来使用访问令牌。
隐式流也有安全问题,需要进一步的逻辑来解决/避免,例如:
An attacker could get an access token from a user on a different website/app (let's say if he is the owner of the other website/app), log the token on their website, and then pass it as a URL param on your website therefore impersonating the user on your website. To avoid this you need to check the Client ID associated with the access token (for instance for Google you can use the tokeninfo endpoint) to make sure the token was issued with your own client ID (i.e by your own app) or check the signature if you are using an IDToken (but that requires your client secret).
If the auth request did not originate from your own property (called Session Fixation attacks), to avoid this you'll want to generate a random hash from your website, save it in a cookie and pass that same hash in the state URL param of the auth request, when the user comes back you check the state param with the cookie and it must match.
在授权代码流中,直接在URL参数中传递访问令牌是不可能的,因为URL参数是HTTP请求的一部分,因此,如果您没有使用加密连接(HTTPS),允许所谓的中间人攻击,您的请求将通过的任何中间服务器/路由器(可能有数百个)都能够读取访问令牌。
Passing the access token directly in a URL param could in theory be possible but the auth sever would have to make sure the redirect URI is using HTTPS with TLS encryption and a 'trusted' SSL certificate (typically from a Certificate Authority that is not free) to be sure that the destination server is legitimate and that the HTTP request is fully encrypted. Having all developers purchase an SSL certificate and properly configure SSL on their domain would be a huge pain and would slow adoption down tremendously. This is why an intermediary one-time-use "authorization code" is provided that only the legitimate receiver will be able to exchange (because you need the client secret) and that the code will be useless to potential hackers intercepting the requests over unencrypted transactions (because they don't know the client secret).
您也可以认为隐式流不太安全,存在潜在的攻击向量,如重定向时欺骗域-例如通过劫持客户端网站的IP地址。这就是隐式流只授予访问令牌(应该有有限的时间使用)而从不刷新令牌(时间是无限的)的原因之一。为了解决这个问题,我建议你尽可能将你的网页托管在一个支持http的服务器上。