附录B OAuth2授权类型

    本附录主要内容
    OAuth2密码授权(password grant)
    OAuth2客户端凭据授权(client credentials grant)
    OAuth2鉴权码授权(authorization code grant)
    OAuth2隐式授权(implicit grant)
    OAuth2令牌刷新
 
在阅读第7章时,读者可能会认为OAuth2看起来不太复杂。毕竟有一个验证服务,用于检查用户的凭据并颁发令牌给用户。每次用户想要调用由OAuth2服务器保护的服务时,都可以依次出示令牌。
    遗憾的是,现实世界从来都不是简单的。由于Web应用程序和基于云的应用程序具有相互关联的性质,用户期望可以安全地共享自己的数据,并在不同服务所拥有的不同应用程序之间整合功能。这从安全角度来看,是一个独特的挑战,因为开发人员希望跨不同的应用程序进行整合,而不是强迫用户与他们想要集成的每个应用程序共享他们的凭据。
    幸运的是,OAuth2是一个灵活的授权框架,它为应用程序提供了多种机制来对用户进行验证和授权,而不用强制他们共享凭据。但是,这也是OAuth2被认为是复杂的原因之一。这些验证机制被称为验证授权(authentication grant)。OAuth2有4种模式的验证授权,客户端应用程序可以使用它们来对用户进行验证、接收访问令牌,然后确认该令牌。这些授权分别是:
    密码授权;
    客户端凭据授权;
    授权码授权;
    隐式授权。
    在下面几节中,我将介绍在执行每个OAuth2授权流程期间发生的活动,同时我会谈到何时适合使用何用授权类型。
 
B.1 密码授权
    OAuth2密码授权可能是最容易理解的授权类型。这种授权类型适用于应用程序和服务都明确相互信任的时候。例如,EagleEye Web应用程序和EagleEye Web服务(许可证服务和组织服务)都由ThoughtMechanix拥有,所以它们之间存在着一种天然的信任关系。
    注意
    
    明确地说,当我提到“天然的信任关系”时,我的意思是应用程序和服务完全由同一个组织拥有,并且它们是按照相同的策略和程序来管理的。
    当存在一种天然的信任关系时,几乎不用担心将OAuth2访问令牌暴露给调用应用程序。例如,EagleEye Web应用程序可以使用OAuth2密码授权来捕获用户凭据,并直接针对EagleEye OAuth2服务进行验证。图B-1展示了EagleEye和下游服务之间的密码授权。
 
图B-1 OAuth2服务确定访问服务的用户是否为已通过验证的用户
    在图B-1中,正在发生以下活动。
    (1)在EagleEye应用程序可以使用受保护资源之前,它需要在OAuth2服务中被唯一标识。通常,应用程序的所有者通过OAuth2服务进行注册,并为其应用程序提供唯一的名称。OAuth2服务随后提供一个密钥给正在注册的应用程序。
    应用程序的名称和由OAuth2服务提供的密钥唯一地标识了试图访问任何受保护资源的应用程序。
    (2)用户登录到EagleEye,并将其登录凭据提供给EagleEye应用程序。EagleEye将用户凭据以及应用程序名称、应用程序密钥直接传给EagleEye OAuth2服务。
    (3)EagleEye OAuth2服务对应用程序和用户进行验证,然后向用户提供OAuth2访问令牌。
    (4)每次EagleEye应用程序代表用户调用服务时,它都会传递OAuth2服务器提供的访问令牌。
    (5)当一个受保护的服务(在本例中是许可证服务和组织服务)被调用时,该服务将回调到EagleEye OAuth2服务来确认令牌。如果令牌是有效的,则被调用的服务允许用户继续进行操作。如果令牌无效,OAuth2服务将返回HTTP状态码403,指示该令牌无效。
 
B.2 客户端凭据授权
    当应用程序需要访问受OAuth2保护的资源时,通常会使用客户端凭据授权,但在这个事务中不涉及任何人员。使用客户端凭据授权类型,OAuth2服务器仅根据应用程序名称和资源所有者提供的密钥进行验证。同样,客户端凭据授权经常用于两个应用程序都归同一个公司所有时。密码授权和客户端凭据授权的区别在于,客户端凭据授权仅使用注册的应用程序名称和密钥进行验证。
    例如,假设EagleEye应用程序每隔一小时就会运行一个数据分析作业。作为其工作的一部分,它向EagleEye服务发出调用。但是,EagleEye开发人员仍然希望应用程序在访问这些服务中的数据之前,进行验证和鉴权。这是可以使用客户端凭据授权的场景。图B-2展示了这个流程。
 
希望应用程序在访问这些服务中的数据之前,进行验证和鉴权。这是可以使用客户端凭据授权的场景。图B-2展示了这个流程。
 
图B-2 客户端凭据授权适用于“无用户参与”的应用程序验证和授权
    (1)资源所有者通过OAuth2服务注册了EagleEye数据分析应用程序。资源所有者将提供应用程序的名称并接收一个密钥。
    (2)当EagleEye数据分析作业运行时,它将出示应用程序名称和资源所有者提供的密钥。
    (3)EagleEye OAuth2服务将使用提供的应用程序名称和密钥对应用程序进行验证,然后返回一个OAuth2访问令牌。
    (4)每当应用程序调用EagleEye服务时,它就会出示它在OAuth2服务调用中接收到的OAuth2访问令牌。
 
B.3 鉴权码授权
    授权码授权是迄今为止最复杂的OAuth2授权,但它也是最常用的流程,因为它允许来自不同供应商的不同应用程序共享数据和服务,而无须在多个应用程序间暴露用户凭据。鉴权码授权不会让调用应用程序立即获得OAuth2访问令牌,而是使用一个“预访问”授权码的方式来执行额外的检查。
    理解授权码授权的简单方法就是看一个例子。假设有一个EagleEye用户,它也使用Salesforce.com。EagleEye客户的IT部门已经构建了一个Salesforce应用程序,它需要EagleEye服务(组织服务)的数据。来看一下图B-3,看看授权码授权是如何使Salesforce从EagleEye的组织服务中访问数据而无须EagleEye客户向Salesforce公开他们的EagleEye凭据的。
图B-3 授权码授权可以让应用程序在不暴露用户凭据的情况下共享数据
    (1)EagleEye用户登录到EagleEye,并为其Salesforce应用程序生成应用程序名称和应用程序密钥。作为注册过程的一部分,还将提供一个回调URL,以返回到基于Salesforce的应用程序。此回调URL是一个Salesforce的URL,将在EagleEye OAuth2服务器验证了用户的EagleEye凭据后被调用。
 
(2)用户使用以下信息配置Salesforce应用程序:
    为Salesforce创建的应用程序名称;
    为Salesforce生成的密钥;
    指向EagleEye OAuth2登录页面的URL。
    现在,当用户尝试使用Salesforce应用程序并通过组织服务访问EagleEye数据时,根据上述要点中描述的URL,用户将被重定向到EagleEye登录页面。用户将提供他们的EagleEye凭据。如果提供的EagleEye凭据有效,则EagleEye OAuth2服务器将生成一个授权码,并通过步骤1中提供的URL将用户重定向到Salesforce。授权码将作为回调URL的一个查询参数被发送。
    (3)自定义的Salesforce应用程序将对授权码进行持久化。注意,此授权码不是OAuth2访问令牌。
    (4)一旦存储了授权码,自定义的Salesforce应用程序就可以向Salesforce应用程序出示在注册过程中生成的密钥,并将授权码返回给EagleEye OAuth2服务器。EagleEye OAuth2服务器将确认授权码是否有效,然后将OAuth2令牌返回给自定义的Salesforce应用程序。每次自定义的Salesforce应用程序需要对用户进行验证并获取OAuth2访问令牌时,都会使用此授权码。
(5)Salesforce应用程序将在HTTP首部中传递OAuth2令牌以调用EagleEye组织服务。
    (6)组织服务将通过EagleEye OAuth2服务来确认传入EagleEye服务调用的OAuth2访问令牌。如果令牌有效,组织服务将处理用户的请求。
    这真的太令人激动了!应用程序到应用程序的集成是错综复杂的。这整个流程中要注意的是,即使用户登录到Salesforce并且正在访问EagleEye数据,用户的EagleEye凭据也不会直接暴露给Salesforce。在EagleEye OAuth2服务生成并提供初始授权码之后,用户就再也不用向EagleEye服务提供他们的凭据了。
    B.4 隐式授权
    授权码模式可以在通过传统的服务器端Web编程环境(如Java或.NET)运行Web应用程序时使用。如果客户端应用程序是纯JavaScript应用程序或完全在Web浏览器中运行的移动应用程序,并且不依靠服务器端调用来调用第三方服务,那么会发生什么呢?
    这就是最后一种授权类型,即隐式授权,能够发挥作用的地方。图B-4展示了在隐式授权中发生的一般流程。
 
图B-4 隐式授权用于基于浏览器的单页面应用程序(Single-Page Application,SPA) JavaScript应用程序
    
隐式授权通常用于处理完全在浏览器内运行的纯JavaScript应用程序。在其他授权流程中,客户端与执行用户请求的应用程序服务器(客户端应用程序-已经注册了)进行通信,然后应用程序服务器与下游服务进行交互。使用隐式授权类型,所有的服务交互都直接从用户的客户端(通常是Web浏览器)发生。在图B-4中,正在进行以下活动:
 
    (1)JavaScript应用程序的所有者已经通过EagleEye OAuth2服务器注册了应用程序。他们提供了一个应用程序名称以及一个回调URL,该URL将被重定向并带有用户的OAuth2访问令牌。
    (2)JavaScript应用程序将调用OAuth2服务。JavaScript应用程序必须出示预注册的应用程序名称。OAuth2服务器将强制用户进行验证。
    (3)如果用户成功进行了验证,那么EagleEye OAuth2服务将不会返回一个令牌,而是将用户重定向回一个页面,该页面是JavaScript应用程序所有者在第一步中注册的页面。在重定向回的URL中,OAuth2访问令牌将被OAuth2验证服务作为查询参数传递。
    (4)应用程序将接收传入的请求并运行JavaScript脚本,该脚本将解析OAuth2访问令牌并将其存储(通常作为Cookie)。
    (5)每次调用受保护资源时,就会将OAuth2访问令牌出示给调用服务。
    (6)调用服务将确认OAuth2令牌,并检查用户是否被授权执行他们正在尝试的活动。
    关于OAuth2隐式授权,记住下面几点。
    隐式授权是唯一一种OAuth2访问令牌直接暴露给公共客户端(Web浏览器)的授权类型。在授权码授权中,客户端应用程序获得一个返回到托管应用程序的应用程序服务器的授权码。通过授权码授权,用户可以通过出示授权码来获得OAuth2访问权限。返回的OAuth2令牌不会直接暴露给用户的浏览器。在客户端凭据授权中,授权发生在两个基于服务器的应用程序之间。在密码授权中,向服务发出请求的应用程序和这个服务都是可信的,并且属于同一个组织。
    由隐式授权生成的 OAuth2 令牌更容易受到攻击和滥用,因为令牌可供浏览器使用。在浏览器中运行的任何恶意JavaScript都可以访问OAuth2访问令牌,并以他人的名义调用他人为了调用服务而检索到的OAuth2令牌,实质上是在模拟他人。
    隐式授权类型的OAuth2令牌应该是短暂的(1~2小时)。因为OAuth2访问令牌存储在浏览器中,所以OAuth2规范(和Spring Cloud Security)不支持可以自动更新令牌的刷新令牌的概念。
 
B.5 如何刷新令牌
    当OAuth2访问令牌被颁发时,其有效时间是有限的,它最终会过期。当令牌到期时,调用应用程序(和用户)将需要使用OAuth2服务重新进行验证。但是,在大多数OAuth2授权流程中,OAuth2服务器将同时颁发访问令牌和刷新令牌。客户端可以将刷新令牌出示给OAuth2验证服务,该服务将确认刷新令牌,然后发出新的OAuth2访问令牌。来看看图B-5,查看一下刷新令牌流程。
 
图B-5 刷新令牌可以让应用程序获取新的访问令牌而不强制用户重新进行验证
    (1)用户已经登录了EagleEye,并且早已通过EagleEye OAuth2服务进行了验证。用户正在愉快地工作,但是,他们的令牌已经过期了。
    (2)用户下一次尝试调用服务(如组织服务)时,EagleEye应用程序将把过期的令牌传递给组织服务。
    (3)组织服务将尝试使用OAuth2服务确认令牌,OAuth2服务返回HTTP状态码401(未经授权)和一个JSON净荷,指示该令牌不再有效。组织服务将把HTTP状态码401返回给调用服务。
    (4)EagleEye应用程序收到HTTP状态码401和JSON净荷,指出调用从组织服务失败的原因。EagleEye应用程序将使用刷新令牌调用OAuth2验证服务。OAuth2验证服务将确认刷新令牌,然后发回新的访问令牌。
 
 
posted @ 2019-12-03 11:13  mongotea  阅读(401)  评论(0编辑  收藏  举报