OrderCloud Fundamentals - Part 2

OrderCloud Catalyst

fevereiro 28, 2022

In the previous part of this series, OrderCloud Fundamentals, we looked at the .NET OrderCloud SDK and learned how you could use that in a .NET based integration with OrderCloud. 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.

Read part 1 here!

The Catalyst library comes with a set of features helping you to build functionalities in your application. These features or helpers include things like:

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

In this post we won't be discussing all features of the library, instead we will be focusing on the two, in my opinion, most important features.

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.
In order 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 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.

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
{
	///
	/// Get the value directly from the cache if it exists. If not, call addItemFactory() and cache the result for future use.
	/// 
	///Unique key pointing to a value in the cache
	///Time before the cache is cleared. Also called "Time to Live"
	///A function to calculate the value fully.
	/// 
	Task GetOrAddAsync(string key, TimeSpan expireAfter, Func<Task> addItemFactory);
	///
	/// Remove the value from the cache. 
	/// 
	///Unique key pointing to a value in the cache
	Task RemoveAsync(string key);
}

In order 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. A 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 the next part of this series we will put this newly gathered knowledge to use and define an example architecture for an OrderCloud based commerce platform.

Contate-nos