OAuth2.0和OIDC协议概述
XAuth对接应用程序的方法是基于OAuth2.0和OIDC协议来实现的,因此在对接应用之前首先需要了解OAuth2.0和OIDC协议的流程特点以及与XAuth对接应用的方法。
认证API vs OAuth2.0 vs OIDC
在XAuth中我们主要提供了以下2种认证方式:
- OAuth2.0 :OAuth2.0协议用于授权访问受保护的资源,如Web 应用、Native 应用以及API服务。
- OIDC:OIDC协议(Open ID Connect)建立在OAuth2.0基础之上,除对用户进行认证和授权之外还提供了id token以传递用户的身份信息。而且,OIDC还比OAuth2.0提供了更多的灵活性,如可以按需求自定义的scopes。
如果你的需求是希望通过XAuth提供的身份认证、授权服务来控制对应用程序的访问,请使用 OAuth 2.0 或 OIDC协议的方式进行对接。
OAuth 2.0 协议通过颁发access token来确保 API的 安全性,通过OAuth 2.0 协议能够对应用进行委托授权;而通过 OIDC协议,应用可以取得用户的身份验证信息并保存。OIDC协议是对OAuth 2.0的重要扩展升级,通过OIDC协议可以对用户进行身份认证提供单点登录。
OAuth2.0
OAuth2.0协议提供了一整套授权访问受保护资源的方法,它允许用户通过颁发access token作为凭证委托/授权第三方应用访问该用户托管在其它服务中的资源。
OAuth2.0有四个主要参与角色:
- 资源所有者(RO,Resource Owner):通常是最终用户,由他来决定是否允许给应用(客户端client)颁发access token
- 客户端 Client:希望代表数据资源所有者RO访问的服务,通常是应用程序、网站等,
- 授权服务器(AS,Authorization Server):颁发授权凭证access token的服务方,在当前的场景中XAuth是授权服务器
- 资源服务器(RS,Resource Server):access token的消费者,资源服务器鉴别access token有效后返回客户端所请求的资源
其他重要术语:
- grant:是用户授予客户端的一种委托。委托的方式(grant type)包括是
authorization_code
和client_credentials
。不同的委托方式都有各不相同的流程,后面会进行详细的介绍 - access token:是访问资源使用的授权凭证,由授权服务器 (XAuth) 颁发
- refresh token:为可选的token类型,如果access token 过期,则将使用refresh token向授权服务器请求新的access token
关于上述token的生命周期的配置和管理问题,请阅读文档Token生命周期
通常的 OAuth 2.0 授权流程如下所示:
- 客户端向资源所有者(通常是用户)请求授权。
- 如果用户同意授权,客户端将用户的委托发送给授权服务器(在本例中为 XAuth)。
- 如果客户端提供的委托凭证有效,授权服务器返回access token(还可能包括refresh token)。
- 客户端使用access token来访问资源服务器。
如果需要深入了解OAuth2.0协议,请阅读Oauth2.0协议标准
OAuth 2.0 以及OIDC的核心是授权服务器。授权服务器是用于签发token的引擎,每个授权服务器都有一个唯一的issuer URI和用于对token签名的密钥。
在OIDC协议中授权服务器也称之为OP(OpenID Provider),身份提供商、身份源或认证源),因此,除了向授权服务器的 endpoint请求access token外,还可以请求id token。
有关授权服务器本身及其原理和使用的问题,请阅读文档授权服务器
OIDC协议
OIDC协议(OpenID Connect)在Oauth2.0之上提供了一个身份服务层,旨在允许授权服务器对应用程序的用户进行身份验证,并以标准的方式返回结果。在OIDC在Oauth2.0的基础之上提供了id token以传递用户的身份信息。而且,在OIDC标准中还升级扩展了更多的scopes和claims。
尽管OIDC建立在OAuth2.0的基础之上,但OIDC中对几个角色的描述略有不同:
- OpenID Provider(OP):OP是OIDC协议中的授权服务器实,用于验证用户身份、签发access token 、id token和 refresh token。
- End User :最终用户是要验证的主体。 (即授权服务器签发的 id token 所描述的人。)
- relaying Provider(RP):向XAuth授权服务请求access token 和 id token的应用。
- id token:id token是由OP签发的,在id token中通过一组claims描述用户的身份信息。
- claim:每一条claim对应着用户的一个属性信息。
如何选择OIDC协议模式
控制台的协议如何配置
XAuth 的创建应用提供了协议向导,但是如何选择,以及选择的原理是什么?本节将详细的介绍,如何根据你的需求,选择不同的协议模式和配置。
下表将应用程序类型与相应的协议模式进行了一对一的展示,简单的说根据你需要的 token 类型、客户端应用程序类型来决定选择哪一种协议模式。
按应用类型
应用类型 | OAuth 2.0 flow |
---|---|
有服务端的应用 | 授权码模式 Authorization Code |
单页面应用 | Authorization Code + PKCE (推荐), Implicit flow |
Native 应用 | Authorization Code + PKCE |
Trusted | 密码模式 Resource Owner Password |
服务 | 客户端凭证模式 Client Credentials |
应用是否需要 id token
所有的协议模式都可以签发 access token,然而他们不都支持 id token
协议模式 Grant Type | access token | id token |
---|---|---|
Authorization Code | ✅ | ✅ |
Authorization Code with PKCE | ✅ | ✅ |
Implicit | ✅ | ✅ |
Resource Owner Password | ✅ | ✅ |
Client Credentials | ✅ | ❌ |
按客户端类型
通过下图可以根据你的需求快速匹配到合适的协议模式:
应用是否是公共客户端
当最终用户可能查看和修改代码时,客户端应用程序被视为公共应用程序。这包括单页应用 (SPA,Single-Page App) 或任何移动 app 或 PC 应用程序。在这两种情况下,应用程序都无法对恶意用户保密。
应用是 SPA 还是 Native 类型的应用程序?
如果应用是运行于能够支持 PKCE 所需的 Web Crypto 的浏览器的 SPA 应用,那么可以使用 Authorization Code + PKCE 的认证模式;
如果应用要在无法支持 PKCE 所需的 Web Crypto 的浏览器中运行中,需要使用 Implicit 认证模式。由于在 Implicit 模式下,无法保证 client secret 的保密性,所以除非其它的认证模式都不可用时不推荐使用 Implicit 模式。
如果是 Native 应用,则推荐使用 Authorization Code + PKCE 的认证模式。
应用是否有终端用户
当应用程序运行于终端用户无法直接访问的服务器时,我们认为该应用是安全可信的,因此在这种情况下应用可以保存 secret 作为认证的凭证。
如果应用只进行机器与机器之间(machine-to-machine)的交互,则需要使用 client Credentials 的认证模式。
应用客户端是否可信且其它模式不可用
当你同时拥有客户端应用程序和它所请求访问的资源时,应用程序是可信的,所以应用程序可以用来保存终端用户的用户名和密码。因此,当其它的认证模式都不可用时,可以使用这种需要高度信任关系的的认证模式:密码模式(resource owner password flow)
不同类型的流程
授权码模式 Authorization Code flow
授权码模式(authorization code flow)指的是第三方应用先和向 authorize endpoint 申请一个授权码,然后再用该授权码向 token endpoint 请求 token。
这种方式是最常用的流程,安全性也最高,它适用于那些有后端的 Web 应用。授权码通过前端传送,token 则是储存在服务端,而且所有与资源服务器的通信都在服务端之间完成。这样的前后端分离,可以避免 token 泄漏。
Authorization Code + PKCE
在 SPA 应用以及 PC 客户端程序、移动 APP 程序等公共客户端应用中,固定的 client secret 保存在客户端中极易泄漏无法保证安全性。因此通过 PKCE(Proof Key for Code Exchange)方式用随机的 code_challenge 和 code_verifier 取代固定的 client secret 加强授权码模式的安全性。
PKCE 是对常规授权码模式的扩展,除了各个步骤中的 PKCE 的元素,整体流程上与常规的授权码模式基本一致。
注:SPA 等基于浏览器的应用使用授权码+PKCE 模式时,不支持 refresh token。
在基于 PKCE 的授权码模式中,应用客户端需要生成一个随机的认证码(code verifier) ,并通过认证码生成挑战码(code challenge)。然后应用客户端按照授权码的流程向 authorize endpoint 请求授权码时将 code challenge 附加到请求中。
当使用授权码向 token endpoint 请求 token 时,需要将认证码附加到请求中。授权服务器使用约定好的哈希算法对认证码进行哈希计算,并比对计算结果是否与挑战码一致,如果一致则证明 authorize endpoint 和 token endpoint 接收到的两个请求来源同同一个应用客户端。
另外,建议整个通信过程使用 Https 协议,使恶意程序将无法窃取 code_challenge 和 code_verifier。
简易模式 Impicit flow
当客户端是公共应用程序时,由于安全问题在客户端中不能保存 client secret ,在这种情况下推荐使用简易模式(或称为隐藏模式,Implicit flow),允许客户端直接向授权服务器的 authorize endpoint 请求 token,省去了授权码的中间步骤。
注 1:由于公共应用程序不能保证所存储的数据的私密性,所以简易模式下不支持 refresh token
注 2:出于安全上的考虑,仅在浏览器不支持 Web Crypto 时建议使用简易模式;对运行于支持 Web Crypto 的浏览器中的 SPA 类型应用,强烈建议使用授权码+PKCE 模式。
密码模式 Resource Owner Password flow
当高度信任应用客户端时,可以采用密码模式(Resource Owner Password flow)。用户向客户端提供自己的用户名和密码,客户端使用用户名密码向 token endpoint 请求 token
密码模式适用于客户端应用程序和受保护资源都高度受控可信的情况。
密码模式下客户端直接向 token endpoint 发起请求,而不需要像授权码模式和简易模式那样进行重定向。
客户端凭证模式 Client Credentials
客户端凭证模式用于没有最终端用户的服务器端应用程序,该模式通常是用于机器到机器的通信。 由于在客户端凭证模式下使用的是固定的 client secret 进行认证,所以该模式下应用必须是服务端的(也就是没有前端的应用),由应用使用 client secret 直接向 token endpoint 请求 access token 。