软件扩展方案
在固件版本6.0中,WebSphere®DataPower提供了扩展点来定制OAuth协议阶段的标准处理。 在本教程中,我们将介绍如何扩展或定制操作。 您可以通过为Additional OAuth Process字段选择样式表值来启用此功能,如图1所示。该字段显示在OAuth客户端配置文件对象的Advanced选项卡上。
图1. OAuth扩展点字段
为了使DataPower充当授权服务器,它必须提供以下功能:
- 发出并验证授权码。
- 颁发并验证访问令牌。
- 发出并验证刷新令牌(固件6.0.0的新功能)。
- 支持由OAuth客户端或资源所有者撤销。
- 支持令牌自省。
通过填充“ 其他OAuth流程”字段,您可以提供支持您要覆盖的操作的自定义样式表。 如果未在样式表中指定操作,则DataPower将使用其标准行为。
支持的操作是:
- Authorization_request :在成功生成授权码之后(与授权码授予类型一样)调用此函数。 它允许将其他信息与授权代码一起返回给OAuth客户端。
- access_request :成功生成访问令牌后调用。 它允许将其他自定义名称/值对作为包含访问令牌的JSON对象的一部分返回给OAuth客户端。
- resource_request :在成功验证访问令牌后调用此方法。 它允许将其他信息发送到后端资源服务器以进行进一步处理。 这很可能是通过其他HTTP标头值完成的。 例如,资源所有者身份可以发送到后端。
- authorization_form (6.0.0固件):在将授权表返回给设备以用于“ Authorization Code”或“ Implicit”的OAuth授予类型后,将调用此方法。 这使客户可以处理以下情况:资源所有者授予从OAuth客户端访问所请求范围的子集的权限。
- preapproved_check (6.0.0固件):这提供了一种与资源所有者绕过授权许可请求的方法。 当您具有允许资源所有者在您定义的某些条件下对给定的OAuth客户端进行预授权或拒绝请求的框架时,它对于“授权代码”和“隐式授予”类型很有用。
- validate_request (6.0.0固件):在成功验证访问令牌后调用此函数。 用户可以选择添加属性或执行其他处理。 这类似于前面提到的access_request扩展点。 它的使用仅限于下面在validate_request部分中讨论的DataPower验证授予类型。
- miscinfo_request (7.0.0固件):这允许在授权码access_token(也作为refresh_token)的一部分中添加其他杂项信息。 最多可以添加512个字符。
仅当在“ OAuth客户端配置文件”中将“缓存”设置为“自定义”时,才使用以下两个操作。 这表明您想提供一个自定义过程来处理撤销。
- revoke_request (6.0.0固件):当设备收到吊销请求时,这允许客户提供自定义插件。
- check_revocation_request (6.0.0固件):在令牌验证期间调用此命令以确定它是否已被撤销。 它是上一个操作revoke_request的对应内容。
授权请求操作
在授权码授予类型的情况下,临时授权码被提供给OAuth客户端以交换访问令牌。
使用以下HTTP 302重定向将授权代码返回给OAuth客户端:
HTTP/1.1 302 Processed
Location: https://<client-hostname-redirect-url>?
code=........&state=........
Authorization_request扩展点允许您将其他信息附加到授权码授予响应中。
输入:
<input>
<operation>authorization_form</operation>
<oauth-id>........</oauth-id>
<OauthSupportedClient>........</OAuthSupportedClient>
</input>
预期产量:
<result>
<name1>text</name1>
...
<name-9>text</name-9>
</result>
使用上面的输出,将增加302重定向,如下所示:
HTTP/1.1 302 Processed
Location: https://<client-hostname-redirect-url>?
code=........&state=........&name1=text&name-9=text
access_request操作
对于所有受支持的授权类型,在成功完成OAuth握手后,将在JSON对象中或作为重定向URI的一部分返回访问令牌:
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token":"........",
"token_type":"bearer",
"expires_in":3600,
"refresh_token":"........"
}
access_request扩展点使您可以向访问令牌响应中添加其他信息,或处理其他处理。 在本教程提供的样式表示例中 ,它向access_token有效负载响应添加了其他信息。
输入 :
<input>
<operation>access_request</operation>
<result>
<access_token>........</access_token>
<expires_in type='json:number'>........</expires_in>
<scope>........</scope>
</result>
…..
</input>
预期产量 :
<result>
<custom1>text</custom1>
...
<custom9 type='json:number'>88</custom9>
</result>
使用上面的输出,访问令牌JSON对象将扩展为以下内容:
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token":"........",
"token_type":"bearer",
"expires_in":3600,
"refresh_token":"........",
"custom1":"text",
…
"custom9":88
}
resource_request操作
在设备成功验证了access_token之后,但在将请求发送到后端应用程序服务器之前,此操作提供了在发送请求之前处理有效负载的机会。 此操作不期望输出,并且DataPower将忽略返回的任何输出。 您可以使用它为后端应用程序服务器设置其他HTTP标头。
输入 :
<input>
<operation>resource_request</operation>
.....
<container>
same input for AAA – PostProcess Custom stylesheet ...
</container>
</input>
预期输出 :N / A
授权表单操作
对于授权代码和隐式授予类型,将向资源所有者提供一个授权表单,其中资源所有者可以通过OAuth客户端授予对所请求资源的访问权限。 默认情况下,DataPower允许资源所有者仅授予客户端所请求范围的一部分。
当授权表单返回到设备时, authorization_form扩展点使您可以微调此选择。
输入 :
<input>
<operation>authorization_form</operation>
<oauth-id type="authorization_request">
<response_type>...</response_type>
........
<authorization-request>
<args src="body">
........
</args>
</authorization-request>
</oauth-id>
<OAuthSupportedClient>….....</OAuthSupportedClient>
</input>
预期产量 :
<result>
<scope>....supported scopes separated by space....</scope>
</result>
预期输出中指定的范围将用作OAuth握手支持的范围。
preapproved_check操作
对于授权代码和隐式授予类型,将向资源所有者提供一个授权表单,以批准客户的请求。 DataPower支持预先批准或预先拒绝此类请求。 通过标记请求是已预先批准还是已预先拒绝,DataPower将跳过向资源所有者显示的授权表单,并继续进行OAuth流程中的下一步。
preapproved_check扩展点使您可以缩短授权授予过程,以便可以批准或拒绝某些请求。 当客户端尝试访问资源时,这些情况将不会显示授权表单。
输入 :
<input>
<operation>preapproved_check</operation>
<container>
... same input for AAA – PostProcess Custom stylesheet ...
</container>
</input>
预期产量 :
<result><approved>yes|no|unknown</approved></result>
这些选择具有以下含义:
- 是 :该请求已被预先批准,不会显示授权表格。
- 否 :该请求已被预先拒绝,不会显示授权表格。
- 未知 :将显示授权表。
validate_request操作
从6.0.0版固件开始,DataPower为OAuth客户端提供了一种验证其所拥有的访问令牌的方式。 添加了新的授权类型urn:ibm:datapower:validate
来支持此验证请求。 有关如何使用此自定义授予类型调用DataPower的详细信息,请参见下面的curl示例命令。
validate_request扩展点使您可以在成功验证访问令牌之后向响应添加其他信息或执行其他处理。
对于以下请求:
curl -k -v https://<dp>:<port>/<uri>?client_id=<client_id>&grant_type=
urn%3Aibm%3Adatapower%3Avalidate&access_token=......
这是输出示例:
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store, no=cache
Pragma: no-cache
{
"valid":true,
"token_type":"bearer",
"client_id":"<client_id>",
"not_after":"178947675",
"not_after_text":"2012-09-02T03:41:15Z",
"not_before":"178944075",
"not_before_text":"2012-09-02T02:41:15Z",
"resource_owner":"spoon",
"scope":"/getAccountInfo"
}
输入 :
<input>
<operation>validate_request</operation>
<container>
.. same input for AAA – PostProcess Custom stylesheet ….....
</container>
</input>
预期产量 :
<result>
<extra1>customerid</extra1>
...
<extra8 type='json:number'>8888</extra8>
</result>
使用上面的输出,响应将增加到以下内容:
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store, no=cache
Pragma: no-cache
{
"valid":true,
"token_type":"bearer",
"client_id":"<client_id>",
"not_after":"178947675",
"not_after_text":"2012-09-02T03:41:15Z",
"not_before":"178944075",
"not_before_text":"2012-09-02T02:41:15Z",
"resource_owner":"spoon",
"scope":"/getAccountInfo"
"extra1":"customerid",
.....
"extra8":8888
}
miscinfo_request操作
从7.0.0固件版本开始,DataPower提供了一种添加其他信息作为加密保护令牌的一部分的方法。 这使您最多可以添加512个字符的数据。 例如,如果某个会话在某个地方的数据库中具有持久性,则可以使用此字段将条目的索引存储到数据库中。
- @type :这指示何时调用此操作的OAuth协议。
- dp-state :这是授权/同意书形式的信息的一部分。 如果在数据库中为资源所有者跟踪了SSO会话,则可以将SSO会话ID添加到其他信息中。
- az-code :这是授权码信息的一部分
- access-token :这是
access_token
信息的一部分,这也会影响refresh_token
。
如果在dp-state
期间添加了其他信息,DataPower将自动将该值转发给az-code
和access-token
。 但是,您可以在@type=az-code
或@type=access-token
期间覆盖该信息(如果需要)。
如果在az-code
期间添加了其他信息,则DataPower将自动将该值传送给access_token
和refresh_token
,除非稍后在@type=access-token
期间将其覆盖。
输入 :
<input>
<operation @type='dp-state|az-code|access_token'>
miscinfo_request
</operation>
<container>
.. same input for AAA – PostProcess Custom stylesheet ….....
</container>
</input>
预期产量 :
<result>
<miscinfo>up to 512 characters long of data</miscinfo>
</result>
要对持久性撤销信息使用定制的撤销支持,可以升级到以下DataPower固件修订包:6.0.0.15、6.0.1.11、7.0.0.8、7.1.0.5。 撤销分为三个不同的操作。 在本节中,我们将介绍如何将撤销信息持久保存在DataPower之外的持久性存储中,以便您可以在高可用性(HA)环境中提供撤销支持。 对于任何文件访问而言,网络访问都是应用程序最耗时的任务之一。 DataPower仅在绝对必要时才触发以下操作。
在大多数情况下,访问的撤消只是不同资源所有者授予许多应用程序的所有访问的一小部分。 为此目的从OAuth存储所有授权令牌是没有意义的。 通过提供跟踪撤消的选项,DataPower在处理撤消方面提供了一定的灵活性(而不是“一刀切”的解决方案)。
- 处理撤销请求(
revoke_request
) - 确定客户端或令牌是否已被撤销(
check_revocation_request
) - 在正常的OAuth协议处理期间记录撤消(
access_request
)
为了提供最佳性能并在集群环境中提供HA灵活性,DataPower将首先使用其运行时缓存,然后再将上述任何操作用于吊销检查,如图2所示。
图2.吊销检查
revoke_request操作
这处理撤销的记录。 撤销有两种类型:针对接收到的令牌的客户端/应用程序,以及针对客户端/应用程序的资源所有者。 在DataPower确认令牌有效且尚未过期之后,将触发此操作。 由于这种设计,昂贵且费时的基于文件和基于网络的操作仅在认为令牌值得此开销后才发生。 您可以利用此行为来使您的实现更可靠。 例如,对于资源所有者吊销,请考虑在资源所有者吊销权限时存储时间戳。 检查要撤销的令牌时(在操作check_revocation_request中),请使用此信息拒绝在上述时间戳之前发出的所有令牌。 这允许具有新权限的应用程序访问资源。
客户端撤销其令牌的输入:
<input>
<operation>revoke_request</operation>
<!—optional access_token and refresh_token, since client can revoke access_token only,
refresh_token only, or both <access_token count="1" src="body">...</access_token> <refresh_token count="1">....</refresh_token>
<client_id src="basic-auth" count="1">client</client_id>
<oauth-id type="client_revoke_request">
<access_token count="1" src="body">...</access_token>
<refresh_token count="1">....</refresh_token>
<grant_type count="1">urn:ibm:datapower:client:revoke</grant_type>
<client_id src="basic-auth" count="1">client</client_id>
<client_secret src="basic-auth" sanitize="true" count="1>..</client_secret>
<original-url count="1" type="request">https://dp:7777/revoke</original-url>
</oauth-id>
<OAuthSupportedClient>....</OAuthSupportedClient>
</input>
对于资源所有者撤消客户的许可:
<input>
<operation>revoke_request</operation> <resource_owner>tonyf</resource_owner> <client_id count="1" src="body">client</client_id>
<entry type="oauth">
<oauth-id type="owner_revoke_request">
<grant_type count="1">urn:ibm:datapower:owner:revoke</grant_type>
<client_id count="1" src="body">client</client_id>
<original-url count="1" type="request">https://dp:7777/revoke</original-url>
</oauth-id>
<OAuthSupportedClient><client-id>..</client-id>......</OAuthSupportedClient>
<oauth-verified state="ok">
<result>
<grant_type count="1">urn:ibm:datapower:owner:revoke</grant_type>
<client_id count="1" src="body">client</client_id>
</result>
</oauth-verified>
</entry>
</input>
预期产量:
<result><status>success|failure</status></result>
check_revocation_request操作
在OAuth或资源访问处理期间,DataPower将需要验证令牌(或访问)是否已被吊销。 该操作为DataPower提供了所需的信息。 仅当DataPower已验证令牌有效且由于在DataPower运行时缓存中重用而尚未吊销令牌时,才调用此操作。
输入:
<input>
<operation token-type="access_token|refresh_token|az-code|dp-state">check_revocation_request</operation>
<token>....</token>
<verified-token>
<client_id>…</client_id>
<not_after>….</not_after>
<not_after_text>….</not_after_text>
<not_before>…</not_before>
<not_before_text>2014-08-08T08:08:08Z</not_before_text>
<resource_owner>xx</resource_owner>
<scope>xx</scope>
<miscinfo>..</miscinfo>
</verified-token>
<oauth-id type="...">.....</oauth-id>
<OAuthSupportedClient>...</OAuthSupportedClient>
</input>
如果令牌被吊销,则输出:
节点<revoked/>
表示令牌已被撤销。
<result><revoked/></result>
如果令牌未被吊销,则无需返回任何节点集。
access_request操作
此操作是可选的。 但是,我们强烈建议您使用它。 当为验证操作生成访问令牌时,将发生此操作。 在两种情况下,您应考虑将信息保存在外部存储中:当将access_token
创建为授权代码授予类型的一部分时,或将refresh_token
授予类型创建。 您可能希望将授权代码或refresh_token
的副本保留在其他令牌的相同撤销存储中。
结论
本系列的最后一部分,第10部分,描述了可以重写以修改标准DataPower OAuth支持的操作。 您可以使用本教程提供的样式表来单独使用扩展点,也可以组合使用不同的扩展点来满足业务需求。
致谢
作者要感谢Paul Glezen审阅本文。
翻译自: https://www.ibm.com/developerworks/websphere/library/techarticles/1505_poon2/1505_poon2.html
软件扩展方案