我尽力保持这个答案简短(但我被迫添加很多上下文来理解答案)
机密与公共客户
客户端(代表您请求访问的应用程序 - MVC 应用程序、SPA 等)根据它们与授权服务器(在我们的例子中是身份服务器)进行安全身份验证的能力被分类为机密和公共客户端。
例如,Web 应用程序(MVC 应用程序)被认为是机密客户端,因为它是在安全服务器上实现的,并且能够与授权服务器进行安全客户端身份验证(通过反向通道 - 无需用户代理或公共通道的参与)。此外,它可以维护秘密令牌(主要是客户端凭据、access_token 和刷新令牌),这些令牌被保护免受公共访问(例如,由用户代理/资源所有者)
而基于用户代理的应用程序 (SPA) 和本机应用程序(移动应用程序)被视为公共客户端。这是因为资源所有者可以轻松访问协议数据和客户端凭据。
授权码授予
Oauth2 规范将授权代码授予定义为:
“授权码授权类型用于获取访问令牌和刷新令牌,并针对机密客户端进行了优化。由于这是一个基于重定向的流程,客户端必须能够与资源所有者的用户代理(通常是 Web 浏览器)进行交互,并且能够接收来自授权服务器的传入请求(通过重定向)。”</p>
简而言之,授权代码流程针对机密客户端通过用户代理(浏览器)与资源所有者交互进行了优化,该用户代理(浏览器)能够接收和重定向来自身份验证服务器(身份服务器)的传入请求。
抽象地说——授权码流程有以下顺序,
- Resource-owner 向授权服务器进行身份验证(通过-user agent)并获得一个authorization_code
- 资源所有者向客户端提供 Authorization_code(从授权服务器重定向后通过用户代理)
- 客户端向授权服务器进行身份验证(通过反向通道请求)并交换 Authorization_code 以获取 access_token
- access_token 存储在客户端中,资源所有者被重定向到适当的资源
- 由于客户端(MVC 应用程序)具有 access_token,它可以从授权服务器(如果需要)请求刷新令牌。
- 但重要的一点 - 在授权代码流中,资源所有者永远不会看到(或有权访问)Access_token。客户端安全地存储它。
隐式授权
Oauth2 规范将隐式授权定义为:
“隐式授权类型用于获取访问令牌(它不支持发布刷新令牌),并针对已知操作特定重定向 URI 的公共客户端进行了优化。这些客户端通常使用 JavaScript 等脚本语言在浏览器中实现。
由于这是一个基于重定向的流程,客户端必须能够与资源所有者的用户代理(通常是 Web 浏览器)进行交互,并且能够接收来自授权服务器的传入请求(通过重定向)。
与授权码授予类型不同,在这种授权类型中,客户端分别发出授权请求和访问令牌请求,客户端接收访问令牌作为授权请求的结果。
隐式授权类型不包括客户端身份验证,并且依赖于资源所有者的存在和重定向 URI 的注册。因为访问令牌被编码到重定向 URI 中,它可能会暴露给资源所有者和驻留在同一设备上的其他应用程序”</p>
授权码和隐式的区别?
所以主要的区别是:
这是否意味着应该使用隐式,例如 javascript 代码?
是的。由于上面讨论的细节和作为一种常见做法,大多数 JS/SPA 使用 Oauth2 隐式流来保护应用程序。
(为避免混淆,请跳过此部分 - 此隐式流程有多种变体。总体而言,Oauth2 规范本质上是流动的,这导致我们根据 Oauth2 建议构建了几种混合/自定义实现。OpenID-Connect 解决了一些关注点,并且是建立在 Oauth2 之上的相对较新(和成熟)的规范)
ASP.NET MVC 应用程序的密码授权 –</p>
密码授予旨在用于资源所有者与客户端(例如本机应用程序)具有强信任关系的场景。对于这个用例,推荐的授权类型是授权代码流。
Web API 的客户端凭据 –</p>
你说的对。当应用程序本身也是资源所有者时,使用客户端凭据授予类型
windows服务的授权码?
由于规范中的上述原因(用户代理重定向要求等)授权代码流不适合此处。根据 Windows 服务的类型,我会使用 Client Credentials 或 Password grant type
两种类型可以结合吗?如何使用身份服务器实现 apiKey?
我不是 100% 确定您的要求。但是,如果您可以在此处发布有关您想要实现的目标的更多详细信息和背景。我很确定 Brock / Dominick 应该能够确认。