Using third-party OAuth tokens- Implementation

abiram8
Participant IV

When reviewing the documents listed for OAUTH 3rd Party delegation.


http://docs.apigee.com/api-services/content/use-third-party-oauth-system

https://github.com/dzuluaga/apigee-tutorials/tree/master/apiproxies/musicapi-oauth-delegated-authent...

It indicates about the flow in proxy as first OAUTH policy followed by AssignMessage Policy.

Followed all indicated steps

Even Deployed oauth (cloud Apigee proxy to Product) and created App

where do the "Service Call out falls" link in the flow. Do we have reference of fully working model ?? even sample do not indicate about Service call out even though the OAUTH delegation talks about Service Call out Policy .. Please advice

1 4 1,246
4 REPLIES 4

abiram8
Participant IV

looked into the indicated post could not get information.

Does the flow in the Proxy need to be as below ?
Service Callout policy (Verify get the Valid Token) --> Configire OAUTH Policy--> AssignMessage policy

Thank you for your question, Abiram. I can't directly answer it - "does the flow need to be like this .. Verify -> Configure OAuth -> Assign Message?" But maybe I can provide some information that will be helpful anyway.

First, I apologize, but I just don't understand that question. Those three things are not parallel. "Configure OAuth policy" is not a policy, in the same way that "paint the house" is not a house. So you cannot include "Configure OAuthV2 policy" in the same list as "AssignMessage".

There are two lists of things we can discuss here.

  1. The set of steps you must follow to set up Apigee to do what you want.
  2. the policy steps that Apigee must execute at runtime. (We often call this the "flow")

"Configure OAuth policy" fits into the first list. "OAuthV2 policy" and "AssignMessage" fit into the second list. Do you see what I mean? I'm sorry to be so pedantic, but I want to be very clear.

OK, now, please bear with me, because it's a little more complicated that what I have just described because of these factors:

  • Regarding list #1, the set of steps you must follow in order to configure Apigee is not strictly ordered. A reading of this doc page, the one that you referenced, might suggest that the steps you must follow are strictly ordered. But that's not the case. You can do them in a mixed order, if you know what I mean. In particular, you can do the configuration of the AssignMessage policy before you set up the configuration of the OAuthV2 policy to Generate an accesstoken. Or, you could reverse the order, and set up the configuration of the OAuthV2 policy to Generate an accesstoken, and THEN, set up the configuration of the AssignMessage policy. The key point is that you must configure both of them, and the order in which you configure these things is independent of the configured order of execution.
  • Regarding list #2, the steps that occur IN THE FLOW ITSELF, this list of things is strictly ordered. The AssignMessage must execute *before* the OAuthV2 policy that generates the access token. Regardless of the order in which you have performed the configuration of these policies, the order of execution must be as described. Do you see the distinction I'm trying to make?
  • Also regarding list #2, the policy steps that must execute.... there are actually 2 distinct flows worth discussing. ONE flow will generate the access token, the second flow will verify the access token. You mentioned "verify" in your question and comment, and while you may be clear on what's happening, I want to make absolutely sure we're talking about the same thing. The "Verify" that occurs in the first flow - to generate the access token - is the optional step that verifies external client credentials. The "Verify" that occurs in the second flow - when the token is presented back, during a request-for-service, is simply an OAuthV2 policy with Operation=VerifyAccessToken. Because it's so simple, I won't discuss this second flow further in this answer.

OK, so what does the proxy flow need to be, in order to ingest an external access token?

The ordered flow for ingesting an external access token is:

  1. Verify the client credentials - probably via a ServiceCallout policy, plus possibly a step (policy) that examines the response of the ServiceCallout. Maybe ExtractVariables or a JS step that parses JSON.
  2. AssignMessage to set the special well-known-variable called "oauth_external_authorization_status". The value must be true.
  3. OAuthV2/GenerateAccessToken with <ExternalAccessToken>, <ExternalRefreshToken>, or <ExternalAuthorizationCode>.

The reason AssignMessage must execute in the flow before OAuthV2/GenerateAccessToken is that the latter policy reads the variable with the name "oauth_external_authorization_status". If that variable is false, then the OAuthV2/GenerateAccessToken policy will fail to generate an access token, by design.

The thinking is that the AssignMessage might be conditional based on the outcome of the ServiceCallout step. In other words if the remote system responds with "INVALID CREDENTIALS" then the AssignMessage must set "oauth_external_authorization_status" to false. Whereas if the remote system responds with "THOSE CLIENT CREDENTIALS ARE VALID" then the AssignMessage must set "oauth_external_authorization_status" to true.

Now, different remote system indicate validity in different ways. If the HTTP status code in the response from the remote system is enough to determine the valid/invalid status, then you do not need an ExtractVariables or a JS step. a 200 status code implies "good credentials", whereas a 400 or non-200 code indicates "invalid credentials". But in some cases the remote system will respond with a 200 to indicate "ok, I have successfully processed your request to validate credentials" but the result of the validation effort is contained only within the response payload. In this case you need to parse the payload to extract the answer with either ExtractVariable or a JS Step.

If the HTTP status indicate valid/invalid, then your proxy flow will look something like this:

    <Flow name='example-1'>
      <Step>
        <Name>ServiceCallout-VerifyClientCredentials</Name>
      </Step>
      <Step>
        <!-- the HTTP status code from the remote system indicates valid/invalid -->
        <Condition>serviceCallout.status = 200</Condition>
        <Name>AssignMessage-SetExternalAuthorizationStatus</Name>
      </Step>
      <Step>
        <Name>OAuthV2-GenerateAccessToken-WithExternalToken</Name>
      </Step>
      
      <Condition>(proxy.pathsuffix MatchesPath "/token") and (request.verb = "POST")</Condition>
    </Flow>

If the HTTP response payload indicates the valid/invalid result, then your flow will look something like this:

    <Flow name='example-2'>
      <Step>
        <Name>ServiceCallout-VerifyClientCredentials</Name>
      </Step>
      <Step>
        <!-- the HTTP response payload from the ServiceCallout indicates valid/invalid -->
        <Condition>serviceCallout.status = 200</Condition>
        <Name>ExtractVariables-ExtractPayloadItem</Name>
      </Step>
      <Step>
        <!-- the HTTP response payload from the ServiceCallout valid/invalid -->
        <Condition>(serviceCallout.status = 200) AND (payload_item = "success")</Condition>
        <Name>AssignMessage-SetExternalAuthorizationStatus</Name>
      </Step>
      <Step>
        <Name>OAuthV2-GenerateAccessToken-WithExternalToken</Name>
      </Step>
      
      <Condition>(proxy.pathsuffix MatchesPath "/token") and (request.verb = "POST")</Condition>
    </Flow>

I hope this clarifies things for you. If not, please ask followup questions here in the comments.

Looking at the doc page you referenced, I agree with you that it could be clarified. I will work to make those changes to help future readers. (EDIT: done.)

@Dino Thanks for updating the write up on "Using Third-Party OAuth Tokens" and giving the details about the Steps which Apiee should follow and Policy steps for run time (flow) to break the thoughts and make things clear.

To iterate Verify Client credentials I have indicated following information.

.

I am indicating what kind of validation I am referring to hence will give better insight…

As per latest updates to the link

http://docs.apigee.com/api-services/content/use-third-party-oauth-system

which indicates

“If you want the OAuthV2/GenerateAccessToken policy in Apigee Edge to validate the client credentials against the Edge store, set the <ExternalAuthorization> element to false inside the policy configuration, or omit it entirely. If you want to use an external authorization service to explicitly validate the client credentials, set <ExternalAuthorization> to true.”

As per context above, have a situation where the Client key and Secret will be validated by OAUTH Policy and will have to use Token from 3rd party retaining the authentication of Client Key and secret to OAUTH only.

Step 1: OAUTH Policy which validates Key and secret (from User)

Hence in that case, will have to set <ExternalAuthorization> to false... And this will still enable me to get the external token from Third party but I would expect OAUTH2 Policy to validate the Key and secret (Client Credentials initially)....

My situation is Internal validation of client credentials with OAUTH Policy but use the Externally generated Token ..

FYI..I am not using the Service call out because the OAUTH Policy can just validate the Client credentials (Key and secret) and Token is only required from 3rd party….

Step 2: As per write up I will also require Assign Message.

"AssignMessage to set the special well-known-variable called oauth_external_authorization_status. The value must be true to indicate the client credentials are valid."

Step 3: If Step 1 is successful (OAUTH2 Policy is successful) . A Service Callout policy to invoke the external API (To get just a Token) with other required information (per my requirements)...else OAUTH 2 Policy responds with required error to user about Client authentication failure (of Key and secret validation error response)

Step 4: User to fire the request with 3rd Party Token (instead of OAUTH2 token).

Note: The same write up have indicated

“External Validation of Client Credentials

ServiceCallout to Verify the inbound client credentials, and acquire an external token. “

As per

http://docs.apigee.com/api-services/reference/service-callout-policy

“The Service Callout policy lets you call to an another service from your API proxy flow. You can make callouts to either an external service (such as an external RESTful service endpoint) or internal services (such as an API proxy in the same organization and environment).”

Hence as per write up the second part "and acquire an external token." is fine but Service Callout is just to call service but not to validate the inbound client in my case rather OAUTH2 will validate the Client credentials.

Hence OAUTH 2 Policy will be used to authenticate Client credentials hence its Policy configuration will be

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

<OAuthV2 name="OAuth-v20-1">

<DisplayName>OAuth v2.0-1Validate-ExternalToken</DisplayName>

<ExternalAccessToken>external_access_token</ExternalAccessToken>

<ExternalAuthorization>false</ExternalAuthorization>

<Operation>GenerateAccessToken</Operation>

<SupportedGrantTypes>

<GrantType>client_credentials</GrantType>

</SupportedGrantTypes>

<GrantType>request.queryparam.grant_type</GrantType>

<GenerateResponse enabled="false"/>

<Tokens/>

</OAuthV2>

In my case Token is generate by external party hence as per write up I need to store such token, hence set to true above..

Looks like as per your write up I will have to maintain Assign message to as below

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