转载

在 IBM WebSphere DataPower 设备上实现 OAuth,第 10 部分: 更多扩展点的自定义场景

简介

在固件版本 6.0 中,WebSphere® DataPower 提供了扩展点来自定义 OAuth 协议阶段的标准处理。在本教程中,我们将介绍如何扩展或自定义这些操作。您可以为 Additional OAuth Process 字段选择一个样式表值来启用此特性,如图 1 所示。此字段显示在 OAuth 客户端配置文件对象的 Advanced 选项卡上。

图 1. OAuth 扩展点字段

在 IBM WebSphere DataPower 设备上实现 OAuth,第 10 部分: 更多扩展点的自定义场景

要使用 DataPower 作为授权服务器,它需要提供以下功能:

  • 发出和验证一个授权代码。
  • 发出和验证一个访问令牌。
  • 发出和验证一个更新令牌(固件 6.0.0 中新增)。
  • 通过 OAuth 客户端或资源所有者撤销支持。
  • 支持令牌自省。

通过填充 Additional OAuth Process 字段,您可以提供一个样式表来支持您希望覆盖的操作。如果该操作未在样式表中指定,DataPower 将使用它的标准行为。

支持的操作包括:

  • authorization_request :此操作在成功生成授权代码后调用(像授权代码授予类型中一样)。它允许将更多信息与授权代码一起返回给 OAuth 客户端。
  • access_request :此操作在成功生成访问令牌后调用。它允许在包含访问令牌的 JSON 对象中包含更多要返回给 OAuth 客户端的自定义名称-值对。
  • resource_request :此操作在成功验证访问令牌后调用。它允许向后端资源服务器发送更多信息供进一步处理。此操作很可能使用更多的 HTTP 标头值来完成。例如,资源所有者身份可发送给后端。
  • authorization_form (6.0.0 版固件):此操作在将针对 OAuth 授予类型 “Authorization Code” 或 “Implicit” 的授权表返回给设备后调用。这使客户能够处理资源所有者授予对 OAuth 客户端请求的部分范围的访问权的情形。
  • preapproved_check (6.0.0 版固件):此操作提供了一种方式来绕过向资源所有者的授权权限请求。当您有一个框架,可允许资源所有者在您定义的某些条件下预先授权或预先拒绝一个给定 OAuth 客户端的请求时,此操作对 “Authorization Code” 和 “Implicit Grant” 类型很有用。
  • validate_request (6.0.0 版固件):此操作在成功验证访问令牌后调用。可选操作:用户可以添加属性或执行额外的处理。这类似于前面提及的 access_request 扩展点。它的用途仅限于下面的validate_request部分中讨论的 DataPower 验证授予类型。
  • miscinfo_request (7.0.0 版固件):这允许在授权代码、访问令牌中添加更多其他信息(也用作更新令牌)。可添加的字符数不得超过 512 个字符。

以下两个操作仅在 “OAuth Client Profile” 中的 “Caching” 设置为 “Custom” 时使用。这表明您希望提供一个自定义进程来处理撤销。

  • revoke_request (6.0.0 版固件):这允许客户在设备收到一个撤销请求时提供一个自定义插件。
  • check_revocation_request (6.0.0 版固件):此操作在验证一个令牌来确定它是否被调用时调用。它与前一个 revoke_request 操作相反。

回页首

authorization_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>

预期输出:不适用

回页首

authorization_form 操作

对于授权代码和隐式授予类型,资源所有者将获得一个授权表,资源所有者可在其中授予 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>

各个选择具有以下含义:

  • yes :请求已预先批准,将不呈现授权表。
  • no :请求已预先拒绝,将不呈现授权表。
  • unknown :将呈现授权表。

回页首

validate_request 操作

从固件版本 6.0.0 开始,DataPower 为 OAuth 客户端提供了一种验证其拥有的访问令牌的方式。添加了一种新授予类型 urn:ibm:datapower:validate 来支持此验证请求。请参阅下面的示例 curl 命令,了解使用这种自定义授予类型调用 DataPower 的详细信息。

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-codeaccess-token 。但是,如果需要的话,您可以在 @type=az-code@type=access-token 期间忽略该信息。

如果在 az-code 期间添加了其他信息,DataPower 会自动将该值传递给 access_tokenrefresh_token ,除非它在以后的 @type=access-token 期间被覆盖。

输入:

<input>   <operation @type='dp-state|az-code|access_token'>     validate_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。该撤销分解为 3 个不同的操作。在这一节中,我们将介绍如何将撤销信息从 DataPower 持久保存到永久存储中,以便您可以在高可用性 (HA) 环境中提供撤销支持。对于任何文件访问,网络访问都是应用程序最耗时的任务之一。DataPower 仅在绝对必要时触发以下操作。

在大多数情况下,撤销的访问只是不同资源所有者向许多应用程序授予的所有访问权的一小部分。没有必要存储来自 OAuth 的所有授权令牌,将它们用于此用途。通过提供跟踪撤销的选项,DataPower 在撤销的处理上提高了灵活性(不是一个 “一体适用” 的解决方案)。

  • 处理撤销请求 ( revoke_request )
  • 确定一个客户端或令牌是否已撤销 ( check_revocation_request )
  • 记录正常 OAuth 协议处理过程中的撤销 ( access_request )

为了提供最佳性能和在集群环境中实现 HA 灵活性,DataPower 在使用任何上述操作执行撤销检查之前,首先应利用它的运行时缓存,如图 2 中所示。

图 2. 撤销检查

在 IBM WebSphere DataPower 设备上实现 OAuth,第 10 部分: 更多扩展点的自定义场景

回页首

revoke_request 操作

此操作处理撤销的记录。有两种类型的撤销:客户端/应用程序撤销它收到的令牌,以及资源所有者撤销一个客户端/应用程序。此操作在 DataPower 确认令牌有效而且没有过期之后触发。由于此设计,对于基于文件和基于网络的高成本且耗时的操作,仅在认为该令牌值得此开销时才会发生。您可以利用此行为让您的实现更加健全。例如,对于资源所有者撤销,可以考虑存储资源所有者撤销权限时的时间戳。检查一个令牌是否撤销(在操作 check_revocation_request 中)时,使用此信息拒绝在上述时间戳之前发放的所有令牌。这允许拥有新权限的应用程序访问资源。

客户端用于撤销其令牌的输入:

点击查看代码清单

关闭 [x]

<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>

资源所有者要撤销一个客户端的权限:

点击查看代码清单

关闭 [x]

<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 对本文的审阅。

回页首

下载

描述 名字 大小
代码示例 code_sample.zip 7KB
正文到此结束
Loading...