How do I validate access token was issued to the client

Not applicable

Hi,

I have defined a token endpoint for OAuth 2 access token. Before issuing the token I validate the client. The access token returned to the client has a number of sensitive information, like the client_id, which I am removing using a JS callout, before sending back the response to the client.

Here is an example of the token the client receives:

{
  "issued_at": "1459976650698",
  "scope": "password",
  "refresh_token_issued_at": "1459976650698",
  "expires_in": "1799",
  "customerId": "xxx",
  "token_type": "BearerToken",
  "refresh_token": "xxxx",
  "access_token": "Xxxx",
  "refresh_token_expires_in": "0",
  "refresh_count": "0"
}

Q#1: When the client presents the token on a subsequent API call, how do I validate that the token was issued to the client who is presenting the token?

I did notice that Apigee edge captures a client_id and an apigee.client_id. These seems to be auto-populated.

Q#2: How does Apigee populate these variables?

Solved Solved
1 7 11.9K
1 ACCEPTED SOLUTION

akoo
Participant V

Hi @Ritwik Chatterjee,

The access token is provided to the client app that originally requested the token after proper authN/authZ. Importantly, this includes validation of client_id/secret. And so by being a bearer of an access token, no additional check that you are the original client is required. When designing your API flows, it is important that the access token and secret are passed confidentially (e.g., HTTPS). In addition, client_id can be publicly available, and so even if you did send in the client_id along with the access token, it would not prove anything meaningful.

As for how Apigee populates client_id and apigee.client_id (they should be the same), they are populated after using VerfyAccessToken to validate the token. These are also auto-populated using VerifyAPIKey or GetOAuthv2Info. But again, I'd like to reiterate that you shouldn't need to do any client_id validation. This is per IETF OAuth 2.0 spec.

View solution in original post

7 REPLIES 7

An access token is always associated to a client_id

so which means, it can also be linked to

client_id -> app -> developer,

client_id -> app -> api_product -> api_proxy

Apigee manages this data, so when you a client presents a token - it knows all its associated links - thats the reason for your observation, these are auto-populated

Hope it answers both your questions

akoo
Participant V

Hi @Ritwik Chatterjee,

The access token is provided to the client app that originally requested the token after proper authN/authZ. Importantly, this includes validation of client_id/secret. And so by being a bearer of an access token, no additional check that you are the original client is required. When designing your API flows, it is important that the access token and secret are passed confidentially (e.g., HTTPS). In addition, client_id can be publicly available, and so even if you did send in the client_id along with the access token, it would not prove anything meaningful.

As for how Apigee populates client_id and apigee.client_id (they should be the same), they are populated after using VerfyAccessToken to validate the token. These are also auto-populated using VerifyAPIKey or GetOAuthv2Info. But again, I'd like to reiterate that you shouldn't need to do any client_id validation. This is per IETF OAuth 2.0 spec.

@Alex Koo, thanks for your answer. Need a little clarification, as I am still not sure I understood all of it.

When a client (ClientA) reaches out to the token end-point to fetch the token, it is providing its client_id/Client secret as basic authentication (or some other means) credentials. So when issuing the token, the Auth Server can check the client credentials and issue a token.

For the subsequent calls, I have configured the proxy such that the consumer will just need a valid access token. No additional credentials are necessary.

Now does this mean, any other client (ClientB), who has access to that API, will be able to use the token issued to ClientA, to access the API?

If client_id and apigee.client_id are both populated from the token (in our case ClientA), where is the check happening as to who is presenting the token (in our case ClientB)?

>Now does this mean, any other client (ClientB), who has access to that API, will be able to use the token issued to ClientA, to access the API?

Yes, for the TTL of the token. You could put in additional safety, but it isn't required. More importantly, additional safety at the resource API level calls is not a substitute for appropriate access token TTL (keep it short if you can) and proper security protocols when validating client credentials.

>If client_id and apigee.client_id are both populated from the token (in our case ClientA), where is the check happening as to who is presenting the token (in our case ClientB)?

By default, there isn't a check to see that the client presenting the token is the one that requested to mint the token in the first place. This is following IETF OAuth2.0 spec where you can see that only access token is required to access a resource.

You can certainly add in additional checks like client_ID validation or even IP validation, but those are outside of the scope of the IETF OAuth2.0 spec. Even client_id and IP are unreliable (e.g., how is your client_id going to be sent in? Are you sure someone can't get the client_id?), so you may not gain much additional security with those in place.

Yes, Bearer tokens are intended to be secret. the BEARER of the token - the party that holds the token, is expected to be the owner of the token. Upon presenting that token, the party that presents the token is expected to be granted authorization based on the status of the presented token.

Former Community Member
Not applicable

Hi @Ritwik Chatterjee you do have the ability to only send only some of the data attributes back to the client vs sending back everything (as you mention above) by default. One way of doing that is to use a Assign Message policy (sample below) as one of the last steps before the response is returned to the client:

<AssignMessage async="false" continueOnError="false" enabled="true" name="AccessTokenResponseCC">
    <DisplayName>AccessTokenResponseCC</DisplayName>
    <FaultRules/>
    <Properties/>
    <Set>
        <Payload contentType="application/json" variablePrefix="%" variableSuffix="#">{"access_token":"%oauthv2accesstoken.AccessTokenRequest.access_token#","expires_in":"%oauthv2accesstoken.AccessTokenRequest.expires_in#","scope":"%oauthv2accesstoken.AccessTokenRequest.scope#"}</Payload>
    </Set>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    <AssignTo type="response" transport="http" createNew="true"/>
</AssignMessage>

Hope this helps. Let us know if you have additional questions.

Not applicable

Hi @Ritwik Chatterjee, the access token is opaque, Apigee looks up the properties from its data store and sets the variables.