使用第三方 OAuth 令牌

您正在查看的是 Apigee Edge 文档。
转到 Apigee X 文档
信息

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

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

示例

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

查看解释

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

背景信息

通常情况下,Apigee Edge 会生成一组随机的字母和数字作为令牌。Apigee Edge 将其他数据该令牌与关联,例如令牌颁发时间、到期时间、令牌对其有效的 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": "wwitman",
  "refresh_token_expires_in": "0", //--in seconds
  "refresh_count": "0"
}

access_token 属性的值实际上是响应数据的查找键。应用可以向 Edge 中托管的 API 代理(包含不记名令牌 zBC90HhCGmGlaMBWeZAai2s3za5j)发出请求,而 Edge(使用操作为 = VerifyAccessToken 的 OAuthV2 政策)将为所请求的 API 代理查找令牌,检索所有信息,并使用该信息确定令牌是否有效。 这称为令牌验证。上述所有信息都包含令牌。access_token 值只是查找该信息的方式。

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

{
  "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": "wwitman",
  "refresh_token_expires_in": "0", //--in seconds
  "refresh_count": "0"
}

在这种情况下,应用可以向 OAuth 中托管的 API 代理发出包含不记名令牌 TOKEN-1092837373654221 的请求,Edge 可以通过 Edge = VerifyAccessToken 的 OAuthV2 政策对其进行验证。您可以将类似的导入模式应用于授权代码和刷新令牌。

验证客户端凭据

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

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

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

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

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

Apigee 上第三方 OAuth 的政策流

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

客户端凭据的外部验证

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

客户端凭据的内部验证

  • ServiceCallout,获取外部令牌。
  • ExtractVariablesJavaScript 步骤,从响应中提取外部生成的令牌。
  • 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 Edge 不会尝试验证客户端凭据。如果未设置该变量或值不是 true,则 Apigee Edge 将尝试验证客户端凭据。

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

    例如,OAuthV2 政策中的以下配置指示 Edge 在名为 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 政策示例

如果 Edge 在流变量 external_access_token 中找到了令牌值,以下 OAuthV2 政策会生成一个 Apigee Edge 访问令牌。

<OAuthV2 name="OAuth-v20-Store-External-Token">
    <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 授权服务应用此模式。