Verify API Key - Query parameter or Form Parameter

nickolsen
Participant I

Is there a way to setup the Verify API Key policy to have it look for either a query parameter OR a form parameter? We would like the calling part to be able to provide it in either place.

Solved Solved
0 10 1,471
1 ACCEPTED SOLUTION

sidd-harth
Participant V

I guess we can use the ref attribute and reference variable value coming in query or form param,

<VerifyAPIKey async="false" continueOnError="false" enabled="true" name="Verify-API-Key-1">
    <DisplayName>Custom label used in UI</DisplayName>
    <APIKey ref="variable_containing_api_key"/>
</VerifyAPIKey>

Before this policy maybe use a JS to get key from either query/form param and set it to a variable. You can also use a couple of extract variable policies with appropiate conditions to set a variable.

It's a good practice to pass the API key in a header or form parameter rather than in a query parameter. The reason is that query parameters can show up in browser histories and network logs, which could present a possible security risk.

View solution in original post

10 REPLIES 10

sidd-harth
Participant V

I guess we can use the ref attribute and reference variable value coming in query or form param,

<VerifyAPIKey async="false" continueOnError="false" enabled="true" name="Verify-API-Key-1">
    <DisplayName>Custom label used in UI</DisplayName>
    <APIKey ref="variable_containing_api_key"/>
</VerifyAPIKey>

Before this policy maybe use a JS to get key from either query/form param and set it to a variable. You can also use a couple of extract variable policies with appropiate conditions to set a variable.

It's a good practice to pass the API key in a header or form parameter rather than in a query parameter. The reason is that query parameters can show up in browser histories and network logs, which could present a possible security risk.

I assume in this case some other policy needs to set variable_containing_api_key? What would that look like?

Before this policy maybe use a JS to get key from either query/form param and set it to a variable. You can also use a couple of extract variable policies with appropiate conditions to set a variable.

Do you have an example of what that javascript would look like? From my research it looks like there is the ability to iterate over request.queryparam, is there also a request.formparam?

Also, once you find the apikey, do you just set it to a global javascript variable and that will be accessible from the VerifyAPIKey policy as long as I provide the same name?

sidd-harth
Participant V

I don't have a JS example right now, use the below logic for the time being,

For both cases users need to send x-api-key in below policies,

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ExtractVariables async="false" continueOnError="false" enabled="true" name="Extract-Query">
    <DisplayName>Extract-Query</DisplayName> <!-- Query parameter -->
    <Properties/>
    <URIPath name="name"/>
    <QueryParam name="x-api-key">
        <Pattern ignoreCase="true">{apikey}</Pattern>
    </QueryParam>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    <Source clearPayload="false">request</Source>
    <VariablePrefix>apigee</VariablePrefix>
</ExtractVariables>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ExtractVariables async="false" continueOnError="false" enabled="true" name="Extract-Form">
    <DisplayName>Extract-Form</DisplayName> <!-- form parameter -->
    <Properties/>
    <FormParam name="x-api-key">
        <Pattern ignoreCase="true">{apikey}</Pattern>
    </FormParam>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    <Source clearPayload="false">request</Source>
    <VariablePrefix>apigee</VariablePrefix>
</ExtractVariables>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<VerifyAPIKey async="false" continueOnError="false" enabled="true" name="Verify-API-Key-1">
    <DisplayName>Verify API Key-1</DisplayName>
    <Properties/>
    <APIKey ref="apigee.apikey"/>
</VerifyAPIKey>
<PreFlow name="PreFlow">
        <Request>
            <Step>
                <Name>Extract-Query</Name>
                <Condition>request.queryparam.x-api-key != null</Condition>
            </Step>
            <Step>
                <Name>Extract-Form</Name>
                <Condition>request.formparam.x-api-key != null</Condition>
            </Step>
            <Step>
                <Name>Verify-API-Key-1</Name>
            </Step>
        </Request>
        <Response/>
    </PreFlow>

Really appreciate the examples and I was able to get these working. Related but not part of this exact original question; is there a way to allow the form parameter to be case insensitive? Meaning, if I pass in x-api-key or x-API-key, either would work. Or in this case, would the javascript scenario be better?

Yes, I guess we need to use JS for case-insensitive paramters. Let me check and give a example. BTW I am posting different answers for easy readability.

Hi @Nick Olsen, I hope you got the answer to this question. I guess this thread is not a good place to discuss case-insensitive form params query. Kindly accept this answer and post a new question.

sidd-harth
Participant V

Instead of using Extract Variable policy, use Javascript,

var queryParam = context.getVariable("request.queryparam.x-api-key");
var formParam = context.getVariable("request.formparam.x-api-key");


if (queryParam !== null){
    context.setVariable("apigee.apikey",queryParam);
}else{
    context.setVariable("apigee.apikey",formParam);
}

Use a Raise Fault before JS policy to check missing query/form params,

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<RaiseFault async="false" continueOnError="false" enabled="true" name="Raise-Fault-1">
    <DisplayName>Raise Fault-1</DisplayName>
    <Properties/>
    <FaultResponse>
        <Set>
            <Headers/>
            <Payload contentType="application/json">
                {
                    "error":"Missing x-api-key in query/form param"
                }
            </Payload>
            <StatusCode>404</StatusCode>
            <ReasonPhrase>Missing Key</ReasonPhrase>
        </Set>
    </FaultResponse>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</RaiseFault>
<PreFlow name="PreFlow">
        <Request>
            <Step>
                <Name>Raise-Fault-1</Name>
                <Condition>(request.queryparam.x-api-key = null) and (request.formparam.x-api-key = null) </Condition>
            </Step>
            <Step>
                <Name>JavaScript-1</Name>
            </Step>
            <Step>
                <Name>Verify-API-Key-1</Name>
            </Step>
        </Request>
        <Response/>
    </PreFlow>