Multiple authentication mechanisms in API proxy

Hi,

How can we provide two security options to consumers in API Proxy -

Option 1 - API Key & Secret validation

Option 2 - OAuth 2.0

Based on what client can support, they should be able to use any one of the security option.

Solved Solved
1 2 1,001
2 ACCEPTED SOLUTIONS

I would want to hear more about "why" you want to implement security that way, but just to answer your question, there are a lot of ways to accomplish this task.

One option is, for each proxy, create multiple proxy endpoints and add the type of security you want on each proxy endpoint. For instance, one could support bearer token and the other could support apikey verification.

Another option could be to check the authorization header, and if the header is present, verify the token. Otherwise, if the auth header token isn't present, skip verify token but instead verify the api key on a header named apiKey. If neither header is present, reject the call. I would actually add that last part to the beginning of your logic.

View solution in original post

I think what you're talking about is a little unusual, but not unprecedented.

Most companies or API Publishers evaluate their requirements for API exposure and settle on a single specific kind of authentication - whether it's API Key, or OAuth Token, or some other mechanism.

What you're suggesting is that you'd like to support both.

That's technically no problem doing what you like.

Here's what I imagine:

  • create different Apps (clients) with distinct client ID's.
  • Configure each Client ID with a custom attribute maybe called "required_credential" which takes one of the following two values: { apikey, token }
  • Define the API Proxy to accept either a standard Authorization header with an OAuth token, or a custom header called "APIKey".
  • In the API Proxy
    • check for the APIKey header, and if found, validate that API Key
    • if the APIKey header is not found, then look for the Authorization header and validate that token.
    • If neither credential is found, throw a fault
  • Regardless of which credential is provided, the API Proxy now has knowledge of the client, and the custom attribute that is *required* for that client. In the proxy insert a condition that checks the credential type that *was* used against the credential type that is *Expected* to be used. Throw a fault if there is a mismatch.

That's how you could structure it in the API Proxy logic. As to specifically what that looks like in Conditions, I guess it would be something like the following:

  <Step>
    <Name>VerifyAPIKey</Name> 
    <Condition>request.header.apikey != null</Condition>
  </Step> 
  <Step>
     <Name>OAuthV2-VerifyAccessToken</Name>
    <Condition>request.header.authorization != null</Condition>
  </Step>
  <Step>
     <Name>RaiseFault-MissingCredential</Name>
    <Condition>(request.header.authorization = null) AND (request.header.apikey = null)</Condition>
  </Step>
  <Step>
     <Name>RaiseFault-IncorrectCredentialType</Name>
    <Condition>...condition to check credential type here ...</Condition>
  </Step>



I left the final condition as a placeholder, because ... typing it out would not clarify anything. You could do it all in the Condition logic of the API Proxy or you explicitly factor it out into a JS step to make it more readable. but in the end the condition returns "true" or "false" indicating whether the credential was unacceptable or acceptable, and the API Proxy throws a fault based on that condition.

View solution in original post

2 REPLIES 2

I would want to hear more about "why" you want to implement security that way, but just to answer your question, there are a lot of ways to accomplish this task.

One option is, for each proxy, create multiple proxy endpoints and add the type of security you want on each proxy endpoint. For instance, one could support bearer token and the other could support apikey verification.

Another option could be to check the authorization header, and if the header is present, verify the token. Otherwise, if the auth header token isn't present, skip verify token but instead verify the api key on a header named apiKey. If neither header is present, reject the call. I would actually add that last part to the beginning of your logic.

I think what you're talking about is a little unusual, but not unprecedented.

Most companies or API Publishers evaluate their requirements for API exposure and settle on a single specific kind of authentication - whether it's API Key, or OAuth Token, or some other mechanism.

What you're suggesting is that you'd like to support both.

That's technically no problem doing what you like.

Here's what I imagine:

  • create different Apps (clients) with distinct client ID's.
  • Configure each Client ID with a custom attribute maybe called "required_credential" which takes one of the following two values: { apikey, token }
  • Define the API Proxy to accept either a standard Authorization header with an OAuth token, or a custom header called "APIKey".
  • In the API Proxy
    • check for the APIKey header, and if found, validate that API Key
    • if the APIKey header is not found, then look for the Authorization header and validate that token.
    • If neither credential is found, throw a fault
  • Regardless of which credential is provided, the API Proxy now has knowledge of the client, and the custom attribute that is *required* for that client. In the proxy insert a condition that checks the credential type that *was* used against the credential type that is *Expected* to be used. Throw a fault if there is a mismatch.

That's how you could structure it in the API Proxy logic. As to specifically what that looks like in Conditions, I guess it would be something like the following:

  <Step>
    <Name>VerifyAPIKey</Name> 
    <Condition>request.header.apikey != null</Condition>
  </Step> 
  <Step>
     <Name>OAuthV2-VerifyAccessToken</Name>
    <Condition>request.header.authorization != null</Condition>
  </Step>
  <Step>
     <Name>RaiseFault-MissingCredential</Name>
    <Condition>(request.header.authorization = null) AND (request.header.apikey = null)</Condition>
  </Step>
  <Step>
     <Name>RaiseFault-IncorrectCredentialType</Name>
    <Condition>...condition to check credential type here ...</Condition>
  </Step>



I left the final condition as a placeholder, because ... typing it out would not clarify anything. You could do it all in the Condition logic of the API Proxy or you explicitly factor it out into a JS step to make it more readable. but in the end the condition returns "true" or "false" indicating whether the credential was unacceptable or acceptable, and the API Proxy throws a fault based on that condition.