Back to home

OrderCloud Catalyst Library’s OrderCloudUserAuthHandler – How to use it and an issue I faced

In the previous post, we have seen how to build a login functionality with OrderCloud using React Contexts. With the same application, to build the product grid for the buyer user, I needed to use the OrderCloudUserAuth attribute to my middleware controller function to authenticate the user. Let us see in detail how to use this handler and some issues I had faced during this journey which left me foggy, and also how did I overcome them to proceed further.

Let us see some details about the OrderCloudUserAuth handler.

About the OrderCloudUserAuth Handler

This OrderCloud’s custom authentication handler is inherited from aspnet core AuthenticationHandler with some AuthenticationScheme options.

This handler is having an overridden HandlerAuthenticateAsync method that returns the AuthenticateResult ( Success, Fail or NoResult). In case of any exceptions within this method, it throws UnAuthorizedException that eventually results to authentication failure.

This method receives the Authentication token from the request header ( as BearerToken), typically send from our front end application and it validates it.

As mentioned early, we can also configure some authentication options with this handler using the OrderCloud Catalyst’s OrderCloudUserAuthOptions class. This class is inherited from aspnet core AuthenticationSchemeOptions and it looks like below,

This allows us to specify the valid list of ClientIDs using the AddValidClientIds method while we register this handler in our Startup.cs class. So any token from the front end application will be validated against this configured list of ClientIDs. We will see how to do this shortly.

Let us see how to use this OrderCloudUserAuth in our Middleware

As a first step, we need to register this handler in our Startup.cs class. This looks like below,

As mentioned earlier, we can also configure the valid client IDs.

And finally, the middleware controller has to be decorated it with this custom authentication attribute.

In my middleware, I have a controller of type CatalystController that lists all the products that are available to this user. We can also mention the list of ApiRoles that this particular controller is expected. So to access this method from the front end application, a token should be generated with these roles. In our case the roles are Shopper and FullAccess.

To do:- For now I am returning the response OrderCloud object as it is. But this will be changed with some level of abstraction around it as I do not want to expose them fully to my front end application.

Now I have the middleware setup done with a custom controller to be accessed from my front end application.

Not everything went well

So far with this setup the custom middlecontroller is expected to serve its purpose. But for me, everything did not go as expected, when I tried to access this controller from my buyer react front end application. So I would like to explain what was the issue I faced and how I managed to overcome that.

So for now to better understand it, let us try to access this custom middleware controller with POSTMAN.

First I generated an access token from OrderCloud with the buyer credentials and with the expected ApiRoles like below.

And with this generated buyer token, I am trying to access our custom middleware controller method like below.

But everything did not go well. As you are seeing above, it results me with the ‘Access Token is invalid or expired’ error. Though we have followed the correct steps with expected ApiRoles, Client Credentials etc., still it did not work for me. This has left me clueless about the cause of the issue.

Any idea why it is not working ?????

Narrowing down to the issue

So, to narrow down and to find the root cause of the issue, I needed to debug the OrderCloudCatalyst library’s authentication custom handler locally.

For this I added the below set of classes from the Catalyst library locally into my middleware application.

As these required classes are in our middleware solution, the handlers to be registered in the Startup.cs class with appropriate namespaces. It looks like below,

The previous authentication handler registration can be commented out for now as you are seeing above.

Now our middleware is ready with custom authentication handler registered and we can debug it to see what is going wrong and where. The HandleAuthenticateAsync() method in the OrderCloudUserAuth.cs is the one which you would probably to start the debugging with.

And finally you will be end up reaching the below function where the given token is processed for validity. This function decodes the token passed in the request and it checks the presence of the KeyID (not sure what is this one and I did not find any proper documentation on it )

So based on the presence of this KeyID, two types of validation seems to happen.

  • VerifyTokenWithMeGet – This is successfully validating the token
  • VerifyTokenWithKeyID – Not this

In our case, the KeyID is always there, so its calling the later method to validate the token based on this KeyID. But it is always failing though 😦

So I tried to further see what is happening inside this VerifyTokenWithKeyID and this function looks like this,

It is calling another method from the OrderCloudSDK with the decoded token KeyIDs and its fetching a PublicKey. And the received PublicKey is used to validate the Token. In our case, the .GetPublicKeyAsync is always returning ‘null’.

This is the reason why in my case, the Authentication is failing always.

Are there any docs on this ?

Unfortunately No…..!!!!

From the OrderCloud portal, this is the only one document, I found on this cert topic. And this has only one end point to retrive a Key and not to generate any.

I think the above method is using this end point ‘oauth/certs/{certID} to get the publich key and the token is validated with it.

So this left me foggy on the authentication issue I faced.

How did I workaround this ?

I would to like to continue my journey on this and do not want to get blocked by this. So I had to ignore the VerifyTokenWithKeyID for now. So I needed to use the VerifyTokenWithMeGet(). The updated function would look like this,

With this changes done in my middleware, I was able to call the custom middleware controller from my front end application and I got the list of products as expected.

I have also posted this clarification in the #order-cloud slack channel and waiting for some reply. I will keep this posts updated according to the reply if I get any.

I yet to finalize some code before I push them to my github repo.

Stay tuned for more stuffs…..!!!!