Remove all padding in a Salesforce Experience Cloud Site

Note to self. When building non-LWR based Experience Cloud sites there is some padding that needs to be removed to make your site fill the entire display port. Put the following CSS classed in custom CSS for the Site to remove it.

.cCenterPanel {
padding: 0px;
margin: 0px;
}
.contentRegion {
padding: 0 !important;
}

YMMV

Unable to force:source:push ExperienceBundle from API version 50.0 with API version 51.0

Yesterday I was trying to deploy some source including an Experience Cloud Site (using ExperienceBundle) created with API version 50.0 to a scratch org but it failed when I updated the API version to 51.0 in sfdx-project.json . Deploying with API version 50.0 worked just fine. The deploy (w/ API version 51.0) failed with the following message:

Error  force-app/main/default/experiences/Digital_Capability_Assessment_Aura1.site-meta.xml  You seem to be missing the property configurationTags in Digital_Capability_Assessment_Aura1/routes/register.json with component ID: f7c5ea49-0bde-4848-a72f-82ace4ea6760

And the error message was right – that key is not in the file but that’s was also true for some of the other Experience Cloud files. Deploying with API version 50.0 and trying to pull with API version 51.0 didn’t change any source. Clever people told me that this was expected as nothing changed in the org (regardless of a publish or similar).

Solution was to deploy with force:source:push with API version 50.0 and then do a force:source:retrieve specifying API version 51.0 on the command line. Then afterwards toggle the API version in sfdx-project.json.

sfdx force:source:retrieve -u dca_scratch_comm -a 51.0 -m ExperienceBundle

Adding myself back into a Salesforce Community

Playing around with Salesforce Communities I accidentally removed my own profile from the Members of the Community. This in effect locked me out of administering the Community in that I couldn’t access the Builder or the Workspaces. Bummer! What to do? Now this was a test environment and I was the only user in the org so not exactly critical but I wanted to remember the way I got back in.

As I had full administrator rights to the org I could use the NetworkMemberGroup object to add myself (or rather the Profile I was mapped to) back into the Community. Now this cannot be done from Apex so it has to be done using the REST API, Data Loader or similar. I opted for the REST API approach.

To do this simply POST to the object as you would any other object passing in the networkId (the ID of the Community) and the parentId (the ID of the Profile or Permission Set to grant access).

POST https://mydomain.my.salesforce.com/services/data/v49.0/sobjects/NetworkMemberGroup
Content-Type: application/json
Content-Length: <length>
Authorization: Bearer <access_token>

{"networkId": "0DB3V000000blOT","parentId": "00e3V000000OkzG"}

Single-Sign-On between multiple Salesforce Communities with custom domains on same Salesforce org

For a customer I was looking into Single-Sign-On (SSO) between multiple Salesforce Communities using a custom domain for each. Consider a customer with two communities (Community 1 at comm1.example.com and Community 2 at comm2.example.com) – these could be different customer communities, a customer community and a partner community etc. The issue we encountered was that when using custom domains (i.e. comm1.example.com and comm2.example.com) the built in session ID cookie support will not suffice as the cookie will be bound to the exact domain. This means the cookie is not sent along when accessing the second community and hence no SSO.

Now the solution to all this is using SAML with is baked into the Salesforce platform and included in the license. There is a bit more stuff to configure with SAML but once set up you get SSO for non-Salesforce Community properties as well such as a property on Heroku as well.

All in all I think it’s worth the additional configuration.

Before I list what I configured let me say that it may feel a bit convoluted as the Salesforce org is both the Identity Provider (IdP) and the Service Provider (SP) in SAML-speak. Usually Salesforce is either the one or the other but but not both.

Please note: Below I assume a certain level of knowledge about Salesforce Communities around controlling access to communities using Profiles, activating Communities and mapping to custom domains. All is well documented in the documentation but understand you cannot simply do the below steps and be done…

What I ended up configuring was the following:

  1. A community (“SSO”) used for Single-Sign-On and self-service (password reset etc.) where I style and brand the SSO experience at sso.example.com. The community has a CA signed SSL certificate and a custom domain setup via the Domains setup.
  2. A community (“Community 1”) for customers at comm1.example.com. The community has a CA signed SSL certificate and a custom domain setup via the Domains setup.
  3. A community (“Community 2”) for customers at comm2.example.com. The community has a CA signed SSL certificate and a custom domain setup via the Domains setup.
  4. A Customer Community profile with the SSO community as the default community. This profile I use to control access to the communities in Members.
  5. I next configured the Salesforce as an Identity Provider using a self-signed certificate. This will allow the org to act as an IdP in a SAML authentication flow.
  6. Next I created 2 Single-Sign-On configurations (under “Single-Sign-On Settings” in Setup). One for comm1.example.com and one for comm2.example.com with separate, unique, entity IDs and mapping each to the appropriate community as the only login configuration under Workspaces/Administration/Login & Registration. I used “Federation ID” for the SAML Identity Type. Ensure you use the SAML configuration from the SSO community.
  7. Next configure the SSO community to only use “Username & Password” under Workspaces/Administration/Login & Registration. This ensures the customers actually are able to login using their Salesforce credentials.
  8. Under “App Manager” in Setup create a Connected App for each community configuring SAML and using the appropriate entity ID remembering to also set these to use Federation ID.
  9. Allow the community user profile to use the Connected Apps (both of them) and ensure user records have a federation ID set.

The result is that I can access all 3 communities on my custom domains. Accessing sso.example.com simply allows me to logon with username and password and do self-service incl. password reset etc. Accessing either comm1.example.com or comm2.example.com will redirect me to sso.example.com for authentication if not authenticated already. If already authenticated to sso.example.com it will simply bounce me via that and authenticate the user to the community transparently.

YMMV!

Generate own Certificate Authority for testing custom Domains with Salesforce Communities

I had a need to test custom domains with Salesforce Communities and be able to log into those communities. When authenticating to a Salesforce Community an encrypted connection (meaning SSL) is required so I needed an easy and free way to generate certificates for my domains The solution was using openssl for the signing and Firefox for the testing as the latter comes with its own Trust Store. Lately many browsers has become very picky about what root certificates are trusted making this kind of testing harder.

Below are the steps I used:

Generate a private key for the root certificate authority:
openssl genrsa -des3 -out rootCA.key 4096

Selg-sign and create a certificate with the private key:
openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 1024 -out rootCA.crt

Convert the certificate to PEM format for import into the Firefox Trust Store:
openssl x509 -in rootCA.crt -pubkey > rootCA_publickey.pem

Now in Salesforce Setup using “Certificate and Key Management” use “Create CA-Signed Certificate” and fill in the form. Then download the Certificate Signing Request (CSR) to your machine and then sign the CSR:
openssl x509 -req -in my_csr_file.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -out my_csr_file.crt -days 365 -sha256

Back in Salesforce on the key/pair created above use “Upload Signed Certificate” and pick the my_csr_file.crt signed above.

Now the certificate may be mapped to a custom domains (under “Domains”) having Salesforce terminate the SSL connection.