使用第三方 OAuth 令牌

本页面适用于 ApigeeApigee Hybrid

查看 Apigee Edge 文档。

在本主题中,我们将讨论如何将外部生成的访问令牌、刷新令牌或授权代码导入 Apigee 令牌存储区。如果要配置 Apigee 来验证在 Apigee 之外生成的令牌,您可以使用此方法。

一般情况下,Apigee 将生成和存储 OAuth 令牌,并将其返回给调用应用。然后,调用应用会在请求服务时将该令牌传回 Apigee,Apigee 将通过 Operation = VerifyAccessToken 的 OAuthV2 政策验证该令牌是否有效。本主题介绍如何配置 Apigee 以存储在其他位置生成的 OAuth 令牌,同时保留令牌验证部分,就像该令牌由 Apigee 生成的一样。

示例

如需查看可演示本主题中介绍的技术的有效示例,请参阅 Apigee 委托令牌管理示例

查看解释

假设您已有授权系统,并且您希望使用由该系统生成的令牌或代码值(而不是 Apigee 生成的 OAuth2 令牌或代码值)。则您可以使用替换的令牌或代码发出安全的 API 代理请求,Apigee 会对其进行验证,就像它们是 Apigee 生成的一样。

背景信息

通常情况下,Apigee 会生成一组随机的字母和数字作为令牌。Apigee 将其他数据该令牌与关联,例如令牌颁发时间、到期时间、令牌对其有效的 API 产品的列表以及范围。所有这些信息都可以在由配置了 Operation = GenerateAccessToken 的 OAuthV2 政策自动生成的响应中返回。响应如下所示:

{
  "issued_at": "1469735625687",
  "application_name": "06947a86-919e-4ca3-ac72-036723b18231",
  "scope": "urn://example.com/read",
  "status": "approved",
  "api_product_list": "[implicit-test]",
  "api_product_list_json": ["implicit-test"],
  "expires_in": "1799", //--in seconds
  "developer.email": "joe@weathersample.com",
  "token_type": "BearerToken",
  "client_id": "U9AC66e9YFyI1yqaXgUF8H6b9wUN1TLk",
  "access_token": "zBC90HhCGmGlaMBWeZAai2s3za5j",
  "organization_name": "myorg",
  "refresh_token_expires_in": "0", //--in seconds
  "refresh_count": "0"
}

Apigee 使用 access_token 值检索令牌元数据。 例如,假设 API 代理请求包含不记名令牌 zBC90HhCGmGlaMBWeZAai2s3za5j。Apigee 使用令牌值检索令牌元数据以确定令牌是否有效。

按照本文所述的步骤,您可以将 Apigee 配置为存储其 access_token 值由外部服务生成的令牌。例如,假设您有一个 Apigee 外部的系统,它可以生成形式为“TOKEN-<16 位随机数字>”的令牌。此时,Apigee 存储的完整令牌元数据可能是:

{
  "issued_at": "1469735625687",
  "application_name": "06947a86-919e-4ca3-ac72-036723b18231",
  "scope": "urn://example.com/read",
  "status": "approved",
  "api_product_list": "[implicit-test]",
  "api_product_list_json": ["implicit-test"],
  "expires_in": "1799", //--in seconds
  "developer.email": "joe@weathersample.com",
  "token_type": "BearerToken",
  "client_id": "U9AC66e9YFyI1yqaXgUF8H6b9wUN1TLk",
  "access_token": "TOKEN-1092837373654221",
  "organization_name": "myorg",
  "refresh_token_expires_in": "0", //--in seconds
  "refresh_count": "0"
}

在这种情况下,应用可以向 API 代理发出包含不记名令牌 TOKEN-1092837373654221 的请求,Apigee 将能够对其进行验证。您可以将类似的导入模式应用于授权代码和刷新令牌。

验证客户端凭据

生成令牌的前提条件是验证请求客户端。默认情况下,Apigee 中的 OAuthV2/GenerateAccessToken 政策会隐式验证客户端凭据。通常,在请求 OAuthV2 令牌的请求中,client_idclient_secret 在授权标头中传递,通过 HTTP 基本授权进行编码(以冒号连接,然后进行 base64 编码)。Apigee 中的 OAuthV2/GenerateAccessToken 政策会解码该标头并查找 client_id,然后验证传入的 client_secret 是否对该 client_id 有效。此机制有效的前提是 Apigee 知道这些凭据则,换言之,在 Apigee 内存储的开发者应用包含一个凭据,该凭据本身包含给定的 client_idclient_secret

如果客户端凭据不是由 Apigee 验证,则您必须设计 API 代理,以在生成令牌之前通过其他方法明确验证客户端。这通常通过连接到您网络中的远程端点的 ServiceCallout 政策实现。

无论是哪种情况,显式或是隐式,您都需要确保生成令牌的 API 代理首先验证客户端凭据。请注意,验证客户端与生成访问令牌是相互独立的。您可以对 Apigee 进行配置,使其同时执行两者,或执行其中之一,或两者都不执行。

如果您希望 Apigee 中的 OAuthV2/GenerateAccessToken 政策为 Apigee 存储区验证客户端凭据,请在政策配置中将 <ExternalAuthorization> 元素设置为 false,或完全省略它。如果您想使用外部授权服务来明确验证客户端凭据,请将 <ExternalAuthorization> 设置为 true

虽然 Apigee 可能不验证客户端凭据,但 Apigee 仍需知道和管理 client_id。Apigee 中的每个 access_token(无论是由 Apigee 生成还是由外部系统生成并导入 Apigee)都必须与客户端应用关联(由 client_id 指示)。因此,即使 Apigee 中的 OAuthV2/GenerateAccessToken 政策不验证 client_idclient_secret 是否匹配,该政策也会验证 client_id 是否有效、存在以及未被撤消。因此,作为前提条件设置步骤,您可能需要通过 Apigee 管理 API 导入 client_id

Apigee 上第三方 OAuth 的政策流

要在 Apigee 中使用来自第三方 OAuth 系统的令牌,则生成访问令牌的流程应遵循以下模式之一。

客户端凭据的外部验证

  1. ServiceCallout,验证入站客户端凭据,并获取外部令牌。
  2. ExtractVariableJavaScript 步骤,从响应中提取外部生成的令牌。
  3. AssignMessage,设置名为 oauth_external_authorization_status 的特殊已知变量。要表明客户端凭据有效,该值必须为 true。
  4. OAuthV2/GenerateAccessToken,<ExternalAuthorization> 元素设置为 true,并且至少包含 <ExternalAccessToken><ExternalRefreshToken><ExternalAuthorizationCode> 中的一个。

客户端凭据的内部验证

  • ServiceCallout,获取外部令牌。
  • ExtractVariableJavaScript 步骤,从响应中提取外部生成的令牌。
  • OAuthV2/GenerateAccessToken,<ExternalAuthorization> 元素设置为 false,并且至少包含 <ExternalAccessToken><ExternalRefreshToken><ExternalAuthorizationCode> 中的一个。

关于流和政策配置的说明

  • 如果您想使用外部系统验证客户端凭据,那么您需要负责开发相应的政策流。通常,您可以使用 ServiceCallout 政策将外部识别的凭据发送到外部身份验证服务。外部身份验证服务通常会返回响应;如果凭据有效,还会提供访问令牌。

  • ServiceCallout 之后,API 代理需要解析响应以提取有效状态,以及外部生成的 access_token 和可能的 refresh_token。

  • 在 OAuthV2/GenerateAccessToken 政策中,将 <StoreToken> 元素设置为 true,并根据情况将 <ExternalAuthorization> 元素设置为 truefalse

    当 OAuthV2/GenerateAccessToken 政策执行时,它会读取变量 oauth_external_authorization_status。如果设置了此变量且值为 true,则 Apigee 不会尝试验证客户端凭据。如果未设置该变量或值不是 true,则 Apigee 将尝试验证客户端凭据。

  • OAuthV2 政策有三个元素,可供您指定要导入的外部数据:<ExternalAccessToken><ExternalRefreshToken><ExternalAuthorizationCode>。每个元素都接受一个流变量。Apigee 政策将读取该变量,以找出外部生成的访问令牌、刷新令牌或授权代码。您需要自行实现相关政策和逻辑,以将外部令牌或代码放入相应的变量中。

    例如,OAuthV2 政策中的以下配置指示 Apigee 在名为 external_token 的上下文变量中查找令牌。

    <ExternalAccessToken>external_token</ExternalAccessToken>
    

    您还需要执行设置该变量的前一个步骤。

  • 设置 oauth_external_authorization_status 变量的一个常用方法是使用具有 AssignVariable 元素的 AssignMessage 政策,如下所示:

    <AssignMessage name="AssignMessage-SetVariable">
        <DisplayName>Assign Message - Set Variable</DisplayName>
        <AssignVariable>
            <Name>oauth_external_authorization_status</Name>
            <Value>true</Value>
        </AssignVariable>
        <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    </AssignMessage>
    

    请记住,此政策必须在 Operation = GenerateAccessToken 的 OAuthV2 政策之前。

OAuthV2 政策示例

以下 OAuthV2 政策会生成访问令牌(假设 Apigee 在流变量 external_access_token 中找到令牌值)。

<OAuthV2 name="OAuth-v20-Store-External-Token">
    <DisplayName>OAuth v2.0 1</DisplayName>
    <Attributes/>
    <ExternalAccessToken>external_access_token</ExternalAccessToken>
    <ExternalAuthorization>true</ExternalAuthorization>
    <Operation>GenerateAccessToken</Operation>
    <GenerateResponse enabled="true">
        <Format>FORM_PARAM</Format>
    </GenerateResponse>
    <ReuseRefreshToken>false</ReuseRefreshToken>
    <StoreToken>true</StoreToken>
    <SupportedGrantTypes>
        <GrantType>client_credentials</GrantType>
    </SupportedGrantTypes>
    <ExpiresIn ref='flow.variable'>2400000</ExpiresIn>
</OAuthV2>

从理论上讲,您可以对任何第三方 OAuth2 授权服务应用此模式。