Scratch org with Salesforce Event Monitoring

Note to self – scratch org definition file to create a scratch org with Event Monitoring enabled. This is a super easy way to quickly spin up an org with Event Monitoring for testing or development. As always the trick is to know the feature and the settings to avoid the manual setup.

{
  "orgName": "foo",
  "edition": "Developer",
  "country": "US",
  "features": ["EventLogFile", "PersonAccounts"],
  "settings": {
    "lightningExperienceSettings": {
      "enableS1DesktopEnabled": true
    },
    "mobileSettings": {
      "enableS1EncryptedStoragePref2": false
    },
    "eventSettings": {
      "enableEventLogGeneration": true,
      "enableTransactionSecurityPolicies": true,
      "enableDeleteMonitoringData": true,
      "enableLoginForensics": true,
      "enableStreamingApi": true,
      "enableTerminateOldestSession": true,
      "enableDynamicStreamingChannel": false,
      "bypassMeteringBlock" :false
    }
  }
}

Scratch org with Salesforce Order Management

Note to self – scratch org definition file to create a scratch org with B2B Commerce and Order Management. The trick was to ensure Enhanced Orders was enabled as well.

{
  "orgName": "foo",
  "edition": "Enterprise",
  "release": "preview",
  "features": ["PersonAccounts", "B2BCommerce", "OrderManagement", "Communities", "EnableSetPasswordInApi", "SalesforceIdentityForCommunities", "Sites", "ExternalIdentityLogin"],
  "language": "en_US",
  "country": "US",
  "settings": {
    "lightningExperienceSettings": {
      "enableS1DesktopEnabled": true
    },
    "mobileSettings": {
      "enableS1EncryptedStoragePref2": false
    },
    "communitiesSettings": {
      "enableNetworksEnabled": true
    },
    "languageSettings":{
      "enableTranslationWorkbench": true
    },
    "commerceSettings": {
      "commerceEnabled": true
    },
    "orderManagementSettings": {
        "enableOrderManagement": true
    },
    "orderSettings": {
        "enableEnhancedCommerceOrders": true,
        "enableOrders": true
    }
  }
}

Salesforce Identity Video – PoC on Preventing Sign-in / Sign-up Page Reload

This video shows a proof-of-concept implementation using the Experience Id to customize the login experience to make login pages and sign-up pages single use. This could be used to prevent users from sending links to sign up pages to one another if consent screens needs to be shown prior to the login experience.

Salesforce Identity videos

Over the last few weeks I’ve spent a fair amount of time working with Salesforce Identity. Salesforce Identity is a very capable offering and offers a fully functional and very configurable identity provider (IdP) at a very competitive price compared to other identity providers on the market. Part of this work has been show casing a number of elements of Salesforce Identity from setting it up as a developer, to working with email templates and translations. To scale it I’ve recorded it as videos and wanted to share them on the blog in case someone could learn from it.

I’ll be posting the videos over the next couple of days. I’ve recorded videos on the following topics:

  • Working with Salesforce, including setting up and org, Salesforce CLI, configuring Salesforce Identity
  • PoC on Preventing Sign-in / Sign-up Page Reload
  • Internationalization (i18n) / Localization (l12n)
  • Email Templates including translation
  • MFA Enablement

The videos use two repositories I’ve created for the demos:

Single Sign On to Salesforce with Azure Active Directory B2C as the IdP through OpenID Connect

A customer reached out the other day as they were unable to make Azure Active Directory B2C work with Salesforce for single-sign-on using OpenID Connect (OIDC). They were seeing a No_Oauth_Token error and couldn’t make it work so they asked if I would look into it.

After spending a bit of time I was able to make it work. First step was to add the Application ID of the app in Azure as a scope in the Auth. Provider configuration in Salesforce. That removed the No_Oauth_Token error but the authentication to Salesforce still failed. The reason was that Salesforce was attempting to reach our the userinfo-endpoint which wasn’t specified as a userinfo-endpoint is not provided by Azure Active Directory B2C when using a standard policy (a policy is how the authentication flow is configured on the Azure side). As no userinfo-endpoint was provided the solution I came up with was to build a small simple web application that could be a stand-in for that missing endpoint.

The stand-in userinfo endpoint of the web app is called from Salesforce after the user has been authenticated through Azure Active Directory B2C but before the user is let into Salesforce. Salesforce will provide a Bearer token in the Authorization header. The Bearer token is the signed JWT from Azure Active Directory B2C.

The endpoint will do the following:

  1. Verify the signature of the JWT by getting the key ID (kid) from the JWT header, then attempt to find the key among the keys loaded from the .wellknown endpoint in Azure when the app started, extract the public key if found and verify the JWT signature
  2. Once the signature has been verified it returns a JSON response with a single claim being the subject identifier (sub)
  3. The Registration Handler on the Salesforce side can then use this subject identifier to lookup the User record in Salesforce and return it to complete the authentication

The web app is available in a repo on Github (https://github.com/lekkimworld/userinfo-endpoint-for-salesforce-with-azure-ad-b2c). The repo also contains a sample Registration Handler.

YMMV.

Salesforce Privacy Center custom metadata

I was looking for a way to move Privacy Center policies between Salesforce environments so I started looking at custom objects but nothing there really so it couldn’t be data. Next I looked at the installed packages in the org and there were 3 pieces of custom metadata listed. Maybe policies are custom metadata?

Next I created a SalesforceDX project and did a sfdx force:source:retrieve from the Privacy Center org and boy was there a lot of custom metadata records. So my best guess is that the policies are actually custom metadata meaning it could be deployed from org to org with the metadata API. Yay!

The records are split across 3 custom metadata types:

  • privacycenter_Data_Object
  • privacycenter_Data_Field
  • privacycenter_Data_Policy