Validating both client id and secret

As per this exercise in academy certification,it says

2.Ensure that both the app key and secret is validated before validating the user credentials.

Kindly help me how to do both appkey and secret validation before user credentials in password grant oauth type.

Should I use verify api key to validate first client id and subsequently use another policy to validate client key alone?

And then I use Service callout to Baas user store to validate user credentials.

And finally Generate Access token OAuth2 policy.

Please suggest.

Solved Solved
0 18 5,961
1 ACCEPTED SOLUTION

Not applicable

I figured I better chime in on this because there is a good pattern to use in this particular case.

First thing lets outline the problem.

I have an token API that has a third leg and i want to validate that the client credentials are A.)Valid and B.)Have access to this endpoint, before calling my IDP to verify the use credentials.

Now for the solution

Request Flow

You have two options here, I think someone mentioned using API Key Validation, then using a RaiseFault policy afterwards if the client_secrets don't match. This works!!

but if your not wanting the extra policy (i.e. raisefault) there is another way

Using the oathv2 policy there is a little known feature called StoreToken

When set to false you tell your oauth policy to not store the token your generating in TokenStore.

So in the request flow you can have your normal oauth policy with this StoreToken tag set to false and what will happen is that the oauth policy will generate an accessToken and refreshToken that you can use later, it also verifies the validity and accessibility of the credentials and will throw the same errors as you would with any other grant type. (life made easy)

In this configuration your target Url would point to your idp...

on a successful response ...

You would add another oauthV2 policy this one would use the ExternalAccessToken and ExternalRefreshToken tags. These tags allow you to use variables to set the accessToken and RefreshToken, the variables you would use are the ones generated in the first oauthv2 policy. You also have a chance to store any metadata from the idp with the token at this point.

View solution in original post

18 REPLIES 18

Former Community Member
Not applicable

The OAuth 2 policy (Generate Access token mode), will automatically validate app key and secret. You must however implement policies to authenticate the user (for a password grant flow) - this must be done before the OAuth 2 policy. A service callout to BaaS is one way to store and validate user's credentials.

+1 This is the best (and easiest) way if you don't need to validate user credentials first. The app key and secret should go in a header as such: "Authorization: Basic <Base64(appKey:secret)>" . I think the key here is whether you need to validate the app before validating user credentials. With proper security (policies,network,etc.), you may be able to bypass app credential checks until time of minting the token.

Right, that's part of generating a token for sure, point is tho, that we only want valid clients hitting the IDP with un/pw before requesting a token, so need to verify at least API Key before making the callout to authenticate.

Hi @Subbu R, We recently added an excellent video to the password grant type documentation that explains how to implement the password grant type on Edge. I hope it helps answer your questions.

@wwitman I watched the video.But my question is how to do client credentials validation before User credentials validation.As per this exercise in academy certification,it says

2.Ensure that both the app key and secret is validated before validating the user credentials.

So,I cannot use GenerateAccesstoken before user credentials validation to validate client credentials in Password grant.I want to know solution for this exercise 2nd point.

@Subbu R, I'm afraid I don't understand Step 2 either. I think the usual pattern is to authenticate the user's name/password first against a backend user store, then generate the token if that succeeds using the client id/secret, just as @Srinandan Sridhar said and as demonstrated in the video.

However, there is a trick you can try, and it's documented in this Community Post !

Not applicable

Dear Subbu,

To validate both apikey and secret, first you have validate the apikey. During validation of apikey, api-secret will be populated in the flow variables. Then you can compare the secret from request to the secret in the flow variable to also validate the secret.

Please click on accept if you accept the answer.

Thanks

Not applicable

@wwitman While you are correct in say "the user's id/password should be verified before generating the token", there is another step before that. It is about validating the request itself to make sure it is coming from a valid source. This is your first line of verification before you want to verify the id/password (through a external idp), so that if the request is not coming from a valid source (valid registered app), you avoid having to validate the userid and password. This verification is done by validating the apikey and secret.

Hope this helps.

Thanks @Pradeep -- Now I understand the broader use case. This has been a great community thread pointing out and clarifying several different techniques to tackle it.

@Pradeep Totally agree, I want to make sure I have a valid client before hitting my backend IDP. I used the approach @Dino suggested in this Community Post and it worked great.

Caveat is that your OAuth proxy /oauth/token endpoint has to be in your API Product for the verify API key to work in the /oauth/token flow otherwise you will get an "Invalid ApiKey for given resource".

2301-screen-shot-2016-03-31-at-32049-pm.png

Raise Faults skipped for APIKey and Secret and valid user credentials.

Not applicable

There could be many variations to this. It is possible that the idp is also a token generation authority in which case, ipd will verify the userid/password and return a token. Apigee at this point will either return the token to client or generate a new token and map this external token to a internal token. In this case as well, you will first need to validate the apikey to make sure it is a valid request.

So in this case, Apigee is exposing a token endpoint as a proxy to a token end point from idp. And there could be many combinations of impl here.

In this particulate case, the question is about apigee exposing a token endpiont and is also a token generation authority.

Not applicable

I figured I better chime in on this because there is a good pattern to use in this particular case.

First thing lets outline the problem.

I have an token API that has a third leg and i want to validate that the client credentials are A.)Valid and B.)Have access to this endpoint, before calling my IDP to verify the use credentials.

Now for the solution

Request Flow

You have two options here, I think someone mentioned using API Key Validation, then using a RaiseFault policy afterwards if the client_secrets don't match. This works!!

but if your not wanting the extra policy (i.e. raisefault) there is another way

Using the oathv2 policy there is a little known feature called StoreToken

When set to false you tell your oauth policy to not store the token your generating in TokenStore.

So in the request flow you can have your normal oauth policy with this StoreToken tag set to false and what will happen is that the oauth policy will generate an accessToken and refreshToken that you can use later, it also verifies the validity and accessibility of the credentials and will throw the same errors as you would with any other grant type. (life made easy)

In this configuration your target Url would point to your idp...

on a successful response ...

You would add another oauthV2 policy this one would use the ExternalAccessToken and ExternalRefreshToken tags. These tags allow you to use variables to set the accessToken and RefreshToken, the variables you would use are the ones generated in the first oauthv2 policy. You also have a chance to store any metadata from the idp with the token at this point.

@srichardson I like this approach, its cleaner and allows me to use one OAuth policy instead of three policies (Basic Auth, OAuth and RaiseFault).

I got this working by using an OAuth policy to verify api key and secret using

<Operation>GenerateAccessToken</Operation>

<StoreToken>false</StoreToken>

<GenerateResponse enabled="false"/> to prevent it from returning a token.

In my second OAuth policy to generate the token and refresh token, I used

<ExternalAccessToken>apigee.access_token</ExternalAccessToken>

which is the variable populated in the first OAuth policy. I couldn't find the refresh token from the first OAuth policy but it gets generated in the second one.

That works!!

I verified by looking at the access_token generated in the first OAuth flow and comparing to the one used in the second.

However I noticed a few things that deviate from the documentation @wwitman.

1. Flow variables are not populated in the trace as documented here: http://docs.apigee.com/api-services/content/oauthv2-policy#flowvariables-generateaccesstoken. I only see apigee.access_token, apigee.developer.app.name and a few others, not the complete set and they are not scoped by OAuth policy name.

2. The first OAuth policy does not generate a refresh token, or at least I don't know where it is.

3. ExternalRefreshToken is not documented in the Docs, I see it in the Schema though. But I couldn't use it because I don't have the refresh token from the first OAuth.

Here are my policies

<OAuthV2 async="false" continueOnError="false" enabled="true" name="OA-VerifyAPIKey-and-Secret">
    <DisplayName>OA-VerifyAPIKey and Secret</DisplayName>
    <ExternalAuthorization>false</ExternalAuthorization>
    <StoreToken>false</StoreToken>
    <Operation>GenerateAccessToken</Operation>
    <ExpiresIn>36000000</ExpiresIn>
    <SupportedGrantTypes>
        <GrantType>password</GrantType>
    </SupportedGrantTypes>
    <GrantType>request.formparam.grant_type</GrantType>
    <UserName>request.formparam.username</UserName>
    <PassWord>request.formparam.password</PassWord>
    <GenerateResponse enabled="false"/>
    <GenerateErrorResponse enabled="true"/>
    <Tokens/>
</OAuthV2>
<OAuthV2 async="false" continueOnError="false" enabled="true" name="OA-GenerateAccessToken-Password">
    <DisplayName>OA-GenerateAccessToken Password</DisplayName>
    <Operation>GenerateAccessToken</Operation>
<!-- removed
    <ExternalAccessToken>apigee.access_token</ExternalAccessToken>
-->
<!-- updated to use the following -->
<ExternalAccessToken>oauthv2accesstoken.OA-VerifyAPIKey-and-Secret.access_token</ExternalAccessToken>
    <ExternalRefreshToken>oauthv2accesstoken.OA-VerifyAPIKey-and-Secret.refresh_token</ExternalRefreshToken>

    <ExpiresIn>36000000</ExpiresIn>
    <SupportedGrantTypes>
        <GrantType>password</GrantType>
    </SupportedGrantTypes>
    <GrantType>request.formparam.grant_type</GrantType>
    <UserName>request.formparam.username</UserName>
    <PassWord>request.formparam.password</PassWord>
    <GenerateResponse enabled="true"/>
    <GenerateErrorResponse enabled="true"/>
</OAuthV2>

You can find the refresh token here oauthv2accesstoken.OA-VerifyAPIKey-and-Secret.refresh_token

@Kurt Kanaskie Thanks for pointing out the doc issues, Kurt. I'll try out your policies and make sure the doc matches what the product is doing.

Thankyou @srichardson...

I have seen your videos in certification page.They are very good 🙂 Thankyou..

Thanks everyone for a great thread on this use case! The key takeaway for me is that it's a best practice to authenticate the calling app before making a callout to the IDP. This prevents unauthorized apps from hitting the IDP.

In the StreetCarts project, we used password grant and we use an API Key policy at the beginning of the auth flow, which some pointed out is a reasonable pattern. In the above use case from the academy, the user is asked to validate both the ID and Secret, and that requirement threw me a bit. However, now we have multiple ideas and approaches outlined here for that use case.

hi There,

Good day.

we would not be able to use the key+ secret verification without mentioning a Grant type for validate.

if we dont mention the same, then it throws a oauth V2 failure.

Is there a way to validate the key + secret without passing the grant_type parameter ??

Regards,

Sreenivas S P