Sitecore and Salesforce custom integration – Salesforce JWT bearer token generation

In this post I will explain my approach to the Salesforce – Sitecore integration. In fact code that is going to be described here can be used in almost every .net application.

Available Sitecore – Salesforce integration

Sitecore provides an integration to everyone who needs to synchronize the data between the Sitecore and Salesforce – the “Salesforce Connect” extension.

You can download it here: https://dev.sitecore.net/Downloads/Salesforce_Connect.aspx

If you do not know which version you should install, check it here (comatibility table): https://support.sitecore.com/kb?id=kb_article_view&sysparm_article=KB1000576

The natural question that probably comes to your mind right now is ‘why did not I use it when I had a need to connect to salesforce’ – this is a really good question.

The answer is – because available extension is focused on the syncing contacts between Salesforce and Sitecore, when in our case we just wanted to send some data to Salesforce and the synchronization was being made on the different level.

In other words, available extension did not meet our needs.

Few general words about the integration

Integration with Salesforce is not in any kind special – it is just an API that is managed by the Salesforce developers. An endpoints and parameters can differ but the common thing is token generation that I decided to describe in this post because it took me a while to understand how to generate the correct JWT bearer token that will be honored by the Salesforce endpoint.

Documentation about it is available on the Salesforce help portal : https://help.salesforce.com/s/articleView?id=sf.remoteaccess_oauth_jwt_flow.htm&type=5

Documentation contains the Java code that I had to transform into .NET one what sometimes was not so obvious.

What do you need to generate OAuth 2.0 JWT bearer token

To make communication possible you must have generated certificate that is going to be used by Salesforce and your Sitecore instance. When certificate will be installed on the Salesforce side you can continute configuration on your side.

To generate the JWT token you need to gather the following information:

  • iss – this is OAuth client_id (provided by Salesforce)
  • aud – this is authorization server’s url (login.salesfroce.com for production and test.salesforce.com for test environments – provided by Salesforce)
  • sub – the username of account used to connect to salesforce (usually email – provided by Salesforce)
  • exp – timestamp of the expiration (provided by Salesforce)

Generation process

All of that data need to be later encoded to base64 string:

private string GenerateClaimsString()
{
var iss = this._salesforceConfigurationService.GetJwtClaimsIss();
var sub = this._salesforceConfigurationService.GetJwtClaimsSub();
var aud = this._salesforceConfigurationService.GetJwtClaimsAud();
var exp = this._salesforceConfigurationService.GetJwtClaimsExp();
var claims = $"{{\"iss\": \"{iss}\", \"sub\": \"{sub}\", \"aud\": \"{aud}\", \"exp\": \"{exp}\"}}";
return this.Base64Encoder(claims);
}

But it is not only encoding by the standard Convert.ToBase64String method. We must also remove some of the chars from the generated string:

private string Base64Encoder(string valueToEncode)
{
byte[] valueToEncodeAsBytes = System.Text.Encoding.UTF8.GetBytes(valueToEncode);
return Convert.ToBase64String(valueToEncodeAsBytes).TrimEnd('=').Replace('+', '-').Replace('/', '_');
}

When the values are encoded and unwanted chars are removed from the encoded string we need to add to it predefined JWT header. Header has a very similar structure to the claims and can be hardcoded with value:

"{\"alg\":\"RS256\"}"

Here is the code that can do that:

private string GenerateJwtHeaderString()
{
var headerValue = SalesforceConstants.Api.Values.Header;
return this.Base64Encoder(headerValue);
}

After all operations we have two strings that we can use to build the assertion used later in the authorization request.

var assertion = this.GenerateJwtHeaderString();
assertion += ".";
assertion += this.GenerateClaimsString();

As you can see two strings are again connected with the dot sign.

But this is not the end – now we are going to use our certificate to sign the assertion. Full code of assertion generation will look like this:

var assertion = this.GenerateJwtHeaderString();
assertion += ".";
assertion += this.GenerateClaimsString();
this._assertion = assertion + "." + this.SignAndGeneratePayloadString(assertion);

Where SignAndGeneratePayloadString method looks like this:

private string SignAndGeneratePayloadString(string payload)
{
            X509Certificate2 certificate = new X509Certificate2(this._salesforceConfigurationService.GetCertPath(), this._salesforceConfigurationService.GetCertPass(), X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);
            using (var privateKey = certificate.GetRSAPrivateKey())
            {
                var signedData = privateKey.SignData(System.Text.Encoding.UTF8.GetBytes(payload), HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
                return Convert.ToBase64String(signedData).TrimEnd('=').Replace('+', '-').Replace('/', '_');
            }
}

As you may noticed SignAndGeneratePayloadString method uses certificate to ‘sign’ the assertion data – to make it work you need to load the certificate from the disk (it must be p12 certificate file) and have certificate password to read it.

The result of signing is again concatenated with the dot and original assertion data.

When the assertion is finally ready, you can authenticate with Salesforce API and Request Access Token for further Salesforce communication.

Summary

If you compare implementation from this blog post with implementation from the Salesforce’s help page you will notice few major differences like:

  • usage of p12 certificate file instead of jks
  • additional string operations on the generated/encoded string values

If you want you can check the full implementation here: https://github.com/lskowronski/SitecoreSalesforce/blob/main/SalesforceJwtService.cs

Because transition from JKS file to p12 file can be also tricky, I will describe it in the another blog post that is going to be published soon – stay tuned!

What to use to write Unit Tests for Sitecore?

In this post, I would like to share with you some experiences I had in my last project and give you advice on what you can use to write Unit Tests and why sometimes some of the libraries are not a good way to go.

In the most cases when the team is thinking to start writing unit tests there is an discussion about different approaches and available libraries – been there done that.

Let me tell you my story

In our case, we had the following libraries taken into consideration:

  • NUnit vs XUnit
  • NSubstitute vs Moq
  • Asserts vs FluentAssertions
  • FakeDB

We totally forgot about AutoFixture and that was our mistake!

After couple of meetings (we had several teams that had to agree something) we decided to vote and the winners were:

  • NUnit
  • Moq
  • FluentAssertions
  • FakeDB

Of course, you may ask “why” … the answer is usually simple because team members knew these three or just liked to write unit tests with the support of these libraries than others.

Is this logical – in some way yes. Is it professional – some people may say ‘no’ but this is how real-world works. Software developers tend to use libraries that they know – especially when it comes to writing unit tests – even when there are better solutions out there.

Everything was fine at the beginning…

We started to write tests, we had around 100 test cases and then we realized that we need something to generate fake Sitecore items automatically.

We started to play we AutoFixture library and then we realized that we made a mistake …

AutoFixture was working really good with all of the libraries instead of FakeDB. We were able to generate simple types like strings etc. but no items were added to the FakeDB.

After some digging in google I found out that many people had that issue and there are two repeated solutions:

  • switch into XUnit
  • get rid of FakeDB and prepare your own fake objects

For us was too late – we decided to stay with our setup.

What to use – the answer

Based on my experience I would not start writing unit tests for Sitecore with NUnit in the future.

The rest of the listed libraries seem to be pretty safe and good from my point of view.

So the answer is:

Use XUnit and whatever else you want – but not NUnit because it can block you at some point as blocked me.

Sitecore Helix Training-do you need it?

I wrote an article about my experiences from Sitecore Helix Workshop held in Copenhagen this month (March 2019).  This time as a test I decided to wrote that on LinkedIn as it is not strictly programming related post.

In the article, I am describing topics from the training and my opinion about the target group for this workshop.

Please check this article here: https://www.linkedin.com/pulse/sitecore-helix-training-do-you-need-lukasz-skowronski/

Sitecore Symposium 2018 – All discounts in one place!

Warning: This is an old post – check a new one here: sitecore symposium 2019 all discounts in one place

EDIT: early-bird price has been removed – 01-08-2018
EDIT: it seems that early-bird is still available – 20-08-2018
EDIT: Sitecore Trial contest has been finished and the winner has been announced – 21-08-2018
EDIT: added information about visa invite letter – 21-08-2018
EDIT: added detailed information about hotel rooms discount
EDIT: removed early-bird price
EDIT: removed MVP code – 14-09-2018
EDIT: removed hotel discounts – 20-09-2018

Are you going to attend on Sitecore Symposium 2018 in Orlando and you still do not have tickets and accommodation? Great, this is post for you!

These days everyone complains for lack of time so I built a list of discounts which Sitecore has prepared for you this year – maybe it will let you to get tickets in better price.

I will try to continuously update that list to share with you all up to date information which I found.

Buy tickets sooner

It is nothing new – if you will buy tickets sooner you will get a better price. This year Sitecore has prepared three price levels:

  • Early-bird: 1295$
  • Advanced: 1495$
  • Regular: 1595$

It means that if you will buy tickets now (July) you will get
100$ discount
.

Use referral links from MVPs

Every MVP can prepare a special link with code which lets you to by tickets 100$ cheaper than price at the moment is. Code expires Friday, September 14, 2018.

So currently it means – 200$ off.

Click image or this link https://sitecoresymposium2018.smarteventscloud.com/portal/registration/MVPLSKOWRONSKI to use my code.

Remember, in case of any problems you can use also code directly: MVPLSKOWRONSKI

Code expires: 14 September 2018

Share your experience and get ticket
for free!

On July Sitecore has announced new trial license for developers. If you have not heard about that – check details here: https://community.sitecore.net/technical_blogs/b/technical-marketing/posts/announcing-the-global-availability-of-the-sitecore-developer-trial.

Everyone who have tried that and will share what achieved with Sitecore during 60 days of tests, have a chance to win free ticket (regular price – 1595$).

Contest closes on August 03, 2018 so you do not have too much time. Check details here: https://community.sitecore.net/technical_blogs/b/technical-marketing/posts/developer-trial-symposium-ticket-contest

The winner of this contest has been announced. The winner is Mohammad Abujaffal – congrats! Check his story here: My Sitecore story.

If you want to check Sitecore’s announcement – visit this page.

Buy tickets in group

If you are coming with the team or you just want to organize with friends you can get discounts for groups.

Currently two levels of discount are prepared:

  • 5-9 people = 75$ off
  • 10 people and more = 100$ off

Tickets must be purchased together and cannot be combined with additional discounts.

Discounted rate in Walt Disney World Swan and Dolphin Resort

As always also this year Sitecore has organized better hotel prices for all Symposium attendees.

Use that link: https://www.swandolphin.com/groupres/site18/ to start booking process.

Worth to know that this year tracks will be split between Swan and Dolphin hotels, so if you would like to see:

  • non-technical tracks – make booking in Dolphin
  • technical tracks – make booking in Swan

Cost of a hotel room starts from USD $259 + $25 daily resort fee/night plus tax, currently 12.5% – offer expires on Friday, September 7, 2018.

Save time with Disney Resorts benefits

If you are going to stay in Swan or Dolphin you can enjoy special deals which will save your time – if you will decide to visit Walt Disney Wolrd.

On the list of benefits you will find:

  • FastPass++ reservation up to 60 days in advance
  • Extra hours benefit – Walt Disney World will be open for you before and after normal working hours
  • Possibility to order Disney tickets in advance
  • and more….

Check all benefits here: https://www.swandolphin.com/aboutus/benefits.html

Save time on US border

It is possible to get visa invite letter from Sitecore. With this letter will be easier to get visa. If you want to have it – write an email with following details to SitecoreSymposium@sitecore.com :

  • invoice number (you have to buy symposium ticket first)
  • job title
  • company name
  • company street
  • company city & postcode
  • country

 

Hopefully gathered information from this post will let you to save some bucks to spend them in Orlando!

Lifecycle of services and support

From time to time we all hear some rumors about Sitecore plans. People say interesting or sometimes strange things about incoming changes. Until today I was trying to filter what is true and what is just a gossip – but you know what? – we do not have to think about those things too much! At least in topics like cloud services and support.

I was not aware about fact that Sitecore provides clear information about their plans in terms of cloud services and support. Read on to know more about that publications.

Sitecore Cloud Services Lifecycle

In article about Sitecore Cloud Services Lifecycle you will find information about:

  • Sitecore Managed Cloud
  • Sitecore Email Cloud
  • IP Geolocation Service
  • Device Detection

And many others. What is interesting? Sitecore prepared new version of Device Detection service which replaced old one. It is not longer available for Sitecore 8 so if you want to use it you should upgrade your Sitecore to version 9. Google Apps and  Page Preview cloud services are not longer available.

More about that you will find here.

If you want to check extended information about changes in Device Detection you should check article here.

Sitecore Product Support Lifecycle

This part for some of you can be even more interesting than previous one. Why? Because partially it answers for question “when upgrade Sitecore to version 9?”.

Of course everyone who has bigger experience with Sitecore would answer:

  • “now”
  • “as fast as it is possible”

But if you need more time then in table “Support Phases For Specific Products” you will find the date when Sitecore will stop providing support for Sitecore 8.  I will not give you here the answer – you have got some time, but check particular dates here.

Summary

Both articles from links where updated week or two weeks ago. I believe they will be updated after every Sitecore update or even more often. That means that it would be good idea to add them to yours favorite links – I did that and recommend the same for you.