When building solutions with Umbraco, there is regularly a need to surface information or functionality above and beyond the content managed in the CMS. Oftentimes this comes from an external service that you need to integrate into the website.
Currently, we could consider there being two extremes as to how you might go about it. On the one hand, of course, you can just do this yourselves with custom integration code. We have the full power of .NET under the hood of Umbraco, so armed with an HttpClient, a serialization library, and an API or client library provided by the service, you are off to the races. You have full control over the implementation, but you do have to do all the work yourselves.
At the other extreme, you might make use of a package that exists to provide the functionality you need, perhaps one that we've built at HQ. If you can find one that matches both the service you need to work with and the use case you have, you'll likely be able to save quite a bit of time by using one of these. Even if either the service or use case differs, most of these integrations, including all the HQ ones, are open source, so you at least have something to start from if you want to take advantage of it. This allows us to reduce the effort somewhat from having to do all the work yourselves.
Making authentication and authorization simpler
One thing we've discovered in building integrations is that many services require a similar, but not identical, process for authentication and authorization - using some form of OAuth flow. How to code up these flows is reasonably established, but they do take some effort and usually from a relatively senior developer.
Â
You have to consider and implement quite a few things, including, but not limited to:
- Redirecting to an authentication endpoint.
- Handling the response including an authentication code and exchanging it for an access token.
- Securely storing the token.
- Including the token in API requests.
- Serializing requests and deserializing the API responses.
- Handling cases where the token has expired and obtaining a new one via a refresh token.
So we thought, what if we could create a package that can handle all this, for multiple services, with the subtle differences between how services implement their auth process handled by providing custom configuration? Maybe that way we can help with something in the middle of these two extremes - we take care of the plumbing, and you focus on implementing the specific business functionality you need from the external service.
And that's what I'm pleased to announce today, a new open-source package called Umbraco Authorized Services that you can use to help with building your own integrations.
How to use the package
To use it, you will need to create your own application with the third-party service. This will provide you with a client Id and secret that are necessary for the authorization flow.
The package is of course available on the Umbraco Marketplace and can be installed into your Umbraco application from NuGet.
<ItemGroup>
<PackageReference Include="Umbraco.AuthorizedServices" Version="0.1.0" />
</ItemGroup>
It's compatible with Umbraco CMS 10+.
You then need to provide configuration for the provider you want to integrate with. This will look something like the example below, which is a configuration we've been testing for working with the HubSpot contacts API. As you see, we need to configure not only things like the client ID and secret but also various hosts, paths, and options that define how the HubSpot authorization flow works as compared to other service providers. You also provide the permissions you need (in the form of scopes) and a sample GET request that can be used to verify the service is correctly set up.
"Umbraco": {
"AuthorizedServices": {
"TokenEncryptionKey": "",
"Services": [
{
"Alias": "hubspot",
"DisplayName": "HubSpot",
"ApiHost": "https://api.hubapi.com",
"IdentityHost": "https://app-eu1.hubspot.com",
"TokenHost": "https://api.hubapi.com",
"RequestIdentityPath": "/oauth/authorize",
"AuthorizationRequestsRequireRedirectUri": true,
"RequestTokenPath": "/oauth/v1/token",
"RequestTokenFormat": "FormUrlEncoded",
"JsonSerializer": "SystemTextJson",
"ClientId": "",
"ClientSecret": "",
"Scopes": "crm.objects.contacts.read crm.objects.contacts.write",
"SampleRequest": "/crm/v3/objects/contacts?limit=10&archived=false"
},
Via the backoffice, you'll find a new tree in the Settings section where the authorized services you have configured are shown.
Â