A first look at the OrderCloud Catalyst library

In this part we will be discussing the OrderCloud Catalyst library. This Catalyst library can be very helpful when creating a middleware application which acts as the gateway between your frontend application (like a shop) and OrderCloud itself.

In this blog post I will be sharing some of the things I learned about the OrderCloud Catalyst library. This is, next to the .NET SDK which I explained in my previous post, another .NET based NuGet library going by the name of “ordercloud-dotnet-catalyst”.
The Catalyst library comes with a set of features helping you to build functionalities in your application. This library is especially useful when building a middleware type of application.
These features or helpers include things like:

  • Authentication and Authorization helpers
  • Result listing helpers
  • Caching
  • Throttling requests
  • Error Handling

In this post I won’t be showing all those features as I have not tried all of them yet. Instead, we will be focusing on the two, in my opinion, most important features, Authorization and Caching.

Authorization

OrderCloud especially excels in the flexibility you have around creating organizational structures of users and their roles. By default, the product knows quite some roles which you can assign to any user, but you also don’t want any unwanted API calls being made by users who should not have access to certain functionalities.
To make it easier for us to manage security checks, Catalyst provides some Authentication and Authorization helpers which we can use in our MVC based APIs.

You can make use of these helpers as part of your MVC Controller. For this to work, your Controller needs to be based on the OrderCloud.Catalyst.CatalystController.
When a request is made to a CatalystController, the provided Bearer token is decoded and stored as a variable on the Controller.

public override void OnActionExecuting(ActionExecutingContext context)
{
    string text = base.User.Claims.FirstOrDefault((Claim claim) => claim.Type == "AccessToken")?.Value;
    if (text != null)
    {
        UserContext = new DecodedToken(text);
    }
 
    base.OnActionExecuting(context);
}

This DecodedToken object stored as UserContext contains some helpful properties about the user making the request, like:

  • AccessToken; This token can be used in the API calls to OrderCloud through the SDK to impersonate this user.
  • Username
  • Roles

Once you have the Controller, you can create methods for your API. Those methods can be annotated using attributes. You can use the Microsoft.AspNetCore.Authorization.AuthorizeAttribute attribute for example to specify any authorization rules for the given request.
OrderCloud has extended this attribute, as OrderCloud.Catalyst.OrderCloudUserAuth, so that you can specify which OrderCloud roles have access to this request. The roles of the context user making the request (UserContext.Roles) are then validated against the list of roles specified in this attribute.

[HttpGet(Name = "GetAllCatalogs"), OrderCloudUserAuth(ApiRole.Shopper)]
public async Task<IActionResult> Get()
{
    var result = await _catalogService.GetAllCatalogs(UserContext.AccessToken);
    return !result.Ok ? Api.BadRequest(result) : Api.Ok(result);
}

This way your application will do the validation before making any subsequent request to OrderCloud instead of OrderCloud returning an error. But you can also just use it for any custom-built functionalities which don’t use OrderCloud at all.

When you are building APIs which function as a proxy to OrderCloud rather than offering custom built functionalities, you will probably want to specify this OrderCloudUserAuth attribute using the roles which we know have access to the OrderCloud API. You can find these roles in the API reference documentation on ordercloud.io where each request shows which roles have access to that API. https://ordercloud.io/api-reference

Caching

The second functionality I want to cover is caching. Catalyst offers a very simple caching mechanism which by default is setup using LazyCache, which is a 3rd party library requiring no configuration but is only caching locally using memory.

To use this caching mechanism, we can use the ISimpleCache service. This service only has two methods and by default is implemented using LazyCache.

public interface ISimpleCache
{
 /// <summary>
 /// Get the value directly from the cache if it exists. If not, call addItemFactory() and cache the result for future use.
 /// </summary>
 /// <param name="key">Unique key pointing to a value in the cache</param>
 /// <param name="expireAfter">Time before the cache is cleared. Also called "Time to Live"</param>
 /// <param name="addItemFactory">A function to calculate the value fully.</param>
 /// <returns></returns>
 Task<T> GetOrAddAsync<T>(string key, TimeSpan expireAfter, Func<Task<T>> addItemFactory);
 /// <summary>
 /// Remove the value from the cache.
 /// </summary>
 /// <param name="key">Unique key pointing to a value in the cache</param>
 Task RemoveAsync(string key);
}

To use a different caching implementation, we could overwrite the service registration with our own implementation for ISimpleCache.

public static void AddCustomCache(this IServiceCollection services) {
 services.AddSingleton<ISimpleCache, MyCacheService>();
}

This caching functionality might not seem like a lot, but a good reason to use it is because Catalyst uses this feature itself.
The OrderCloudUserAuth attribute, as mentioned earlier, uses this ISimpleCache service to cache the token validation requests it makes to OrderCloud APIs. This way, when a user performs multiple actions in a short period of time, the token is only verified once every hour instead of it having to be verified on each request.

Overall, the Catalyst library seems like a very neat set of functionalities which you could use in any Middleware implementation around OrderCloud. It is both easy to setup as well as use.
In a next post I will be sharing some insights about the OrderCloud Headstart demo application as well as my unsalted thoughts about it.