Customizing Key Validation flow

Since we have already covered how WSO2 API Manager 1.9.0, allows you creating OAuth clients on your desired OAuth Provider, let’s move on and see how we can delegate token validating part to the OAuth provider.

As part of the OAuth Provider Extension Framework, the capability was provided to extend Key Validation flow. This was done by introducing a handler which executes when APIKeyValidation service is called. Before explaining about the new handler, it would be good to have a clear idea on, how KeyValidation works.

How keys are validated

Once you call an API providing an Access Token, the execution flows through five handlers,specified in the API. ( For the curious, you can take a look at these handlers by opening an xml, located at ./repository/deployment/server/synapse-configs/default/api )

It is the second handler APIAuthenticationHandler that captures our attention. This is the handler that extracts the Token out from the Header and call APIKeyValidationService ( running on the KeyValidator node) to get the Token validated. Upon validating the Token, Gateway would receive an APIKeyValidationInfoDTO as the response , only using which the rest of the operations would be performed. Before decoupling was done, the entire Key Validation process happened  inside one single method ( validateKey). ValidateKey operation performed all the following operations running a single query,

  1. Checking token validity.
  2. Checking if the application  to which token was issued has subscribed to the API being invoked,
  3. Checking whether the token has necessary permission to access the resource being accessed ( if resource is protected with a user token, then token has to be of type APPLICATION_USER)

If the query evaluates token as a valid one, then somewhere down inthe validatekey operation, we check if the token has a valid scope required to access the resource.

What is changed

What has been done with the new framework is, breaking down this one big code block into smaller parts and providing a way to extend each step. With the new change, we have introduced a handler KeyValidationHandler, which runs inside validateKey operation, which has four operations representing each smaller task previously done inside validateKey.

1.validateToken
2.validateSubscription
3.validateScopes
4.generateConsumerToken

Now, APIKeyValidationService  will instantiate the handler implementing KeyValidationHandler, ( the class name of the implementation can be provided in api-manager.xml) once the server starts up, and would call each method specified in the handler in the order specified above.

Default implementation shipped with the product does following things.

Inside validate token method it would call getTokenMetaData in KeyManager interface, which would call introspect endpoint in OAuth Provider would return;

  1. Validity Status
  2. Consumer key
  3. Issued time &  validity period
  4. Scopes issued for the token
  5. EndUserName

associated with the token.

Returning last two attributes is optional.

If a developer wishes to use any additional fields for validation, the framework supports using such. If token validation failed and the developer would like to propogate the particular error associated with the failure,error code can be set in AccessTokenInfo – but please remeber that error code can only take values defined in APIConstants.KeyValidationStatus

Within the same validateToken method, a new APIKeyValidationInfoDTO will be created, and populated with details returned by getTokenMetadata method.

After executing each method mentioned above, APIKeyValidationInfoDTO will have following details populated.

KeyValidatioFlow (1)

Only those fields getting changed at each step are mentioned in the diagram above for clarity.

After going through this chain, APIKeyValidationInfoDTO is sent back to Gateway as  the response. Gateway would perform all subsequent operations only using values populated in this DTO. In the case KeyValidationHandler is extended, it’s crucial that proper values are set for above fields, since all the functionalities (Throttling, Statistics, picking the correct endpoint) depend upon them.

Do we really need to extend KeyValidationHandler?

For most cases no. The default implementation was written in such a way, that by only extending getTokenMetadata method (in KeyManager interface), you should be able to complete entire keyValidation flow.

So when do we really need to extend KeyValidationHandler?

Suppose that you need to skip some functionalities provided in API Manager. For example domain validation ( When a creating a key via Store, Subscribers can specify which domains are allowed to make calls using a token generated against a particular   consumer key). If this validation doesn’t add any value, then such trivial steps can be ignored and skipped by extending KeyValidationHandler.

There can be instances where, default scope validation doesn’t suite perfectly well for certain usecases. In default scope validation, we first get the scope assigned for the resource being accessed. And then we check whether the issued token has the scope assigned to that resource. Invocation is only allowed, if those two are matching. Suppose that someone doesn’t need to go into the level of detail if  a scope is assigned to a resource, but only need to verify if the token used to access has at least one of the scopes defined for that API. Extending validateScope method would be a good option to cater such requirements.

As a method of passing details of an API invocation to the backend, a JWT is used. If someone needs to send a different type of token, then generateConsumerToken method can be extended.

Advertisements

One thought on “Customizing Key Validation flow

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s