Configure ADXStudio Portals and CRM portals with Azure AD B2C

Azure Active Directory B2C is a new Azure service that is targeted at helping your organization utilize consumer based identities within your sites and applications. This is a guide covering setting up ADXStudio Portals version 7 and CRM portals v8.1 with Azure AD B2C as an identity provider through configuration.  As well discuss some of the additional customizations that can be made to the ADXStudio Portal v7 MasterPortal code base to further enhance the user experience.

A recent update to Azure AD B2C policies has allowed ADXStudio Portals and CRM portals to work with Azure AD B2C via configuration.  To learn more about the technical change please view Azure AD B2C Now Supports ADXStudio Portal v7.

CRM portals v8.x customization is limited and therefore the user experience that the customizations below outline with Azure AD B2C cannot be completely implemented.  CRM portals v8.2 is expected to support Azure AD B2C natively in the Fall release or in a future monthly update.  All configuration based settings mentioned apply for ADXStudio and CRM portals interchangeably.

Note that while you can configure B2C with CRM portals it is completely unsupported and not recommended by Microsoft. The concern is that when support is added to CRM portals if you were previously using B2C that the implementation might not be compatible with your existing users. Therefore it is advised that you do not configure B2C with CRM portal until it is released directly as a feature of the product. The date for this has also moved to unknown, there was discussion on this coming shortly in 8.2, but that has not be committed to. If you wish to implement Azure AD B2C then you should use the latest version of ADXStudio Portals.

The benefit of using Azure AD B2C is moving the authentication of your users to a common secure global service that be consumed be various different application platforms because of its standard based implementation of OpenID Connect. This allows your users to have a single identity with a common user experience across your portfolio of applications. ADXStudio Portals and CRM portals with its implementation of ASP.NET Identity built on the OWIN Framework supports OpenID Connect since version 7.0.0020 with providers like Azure AD B2C.

To get started you will need to create an Azure AD B2C directory which is completely free up to 50,000 authentications per month. Once you have your Azure AD B2C directory you have the ability to enable various social identity providers like Facebook, Google, LinkedIn, Amazon and Microsoft Account for you users to use. You can also enable users without a social identity account to create local users via email address or username. To learn more about creating a directory and setting up social providers via the guide here.

One of the unique functions of Azure AD B2C is that it has the concept of policies. The policies allow you to segment configurations of your identity service, providing flexibility per application, process or however you decide to use policies.  Policies allow you to customize the branding, as to what might be collected during sign up or the claims that are returned to an application. Based on how the ADXStudio Portal and CRM portals function with identity providers through configuration it is best implemented with a “Sign Up and Sign In” policy instead of separate policies for “Sign In” and “Sign Up”.

For the ADXStudio Portal or CRM portals to consume B2C we will need to list it as an application in the B2C settings.

  1. Navigate to Azure AD B2C tenant and then the settings for the directory in the Azure Portal and select Applications, then Add.
  2. Add your application name, enable Web App / Web API, and enter your reply URL (this must be HTTPS and it only needs to be your ADX portal root URL).
  3. Click the Create button.
  4. Once the application is created, select it and you should see an Application ID. Copy this value and save it.

To configure OpenID Connect for ADXStudio Portal or CRM portals we need to map the functionality of the CreateOptionsFromPolicy method in the GitHub sample for .NET Web App Startup.Auth.cs to the portal site settings documented here for ADXStudio Portals and here for CRM portals.

Adding a new identity provider with ADXStudio Portal or CRM portal is must be done via the CRM GUI, outlined below are the necessary site settings for Azure AD B2C.

The settings all follow the format of Authentication/OpenIdConnect/AzureADB2C/[setting_name]. The text AzureADB2C can be replaced with your desired provider name, the label seen on the portal is configured through the caption setting.

The value is the name of your B2C policy for Sign Up and Sign In.
Sample Value: B2C_1_SuSi

You can obtain this value by selecting your policy and copying the metadata endpoint address at the top of the panel.
Sample Value:


You can obtain this value by navigating to your Metadata Address and copying the value of issuer
Sample Value:


The value is the Application ID that you saved when setting up the application in the previous steps.
Sample Value: e48b78ef-e274-4480-a3d5-621138ae1b47

This value applies to both RedirectUri and PostLogoutRedirectUri. It should be the root URL to your ADX portal.
Sample Value:

This value applies to both RedirectUri and PostLogoutRedirectUri. It should be the root URL to your ADX portal.
Sample Value:

Value: openid

Value: id_token

Value: name

Authentication/OpenIdConnect/AzureADB2C/Caption Optional
This can be set to whatever you would like the button text to read on the Sign In and Register pages of the portal. This value is optional.
Sample Value: Azure AD B2C

Once you have completed all the site settings outlined above associated to your ADX portal website then you should be able to restart the portal application and see the new provider listed under external account.

ADXStudio Portals Sign In:

CRM portals Sign In:

You can now test your registration and sign in flows. The nice thing about the Sign Up and Sign In policy and the portal is it will handle that detection as part of its out of the box configuration. All of the other ADXStudio Portals or CRM portal authentication settings can be used and applied to the site as normal.

The following customizations only applies to ADXStudio Portals.

With the out of box code in ADXStudio Portals login controller the logoff or sign out function will only sign you out from the ADX Portal. To modify this functionality you just need to update the Logoff HTTP GET and POST methods in LoginController.cs. This controller can be found in the MasterPortal code base Areas\Account\Controllers folder.

// GET: /Login/LogOff
public ActionResult LogOff(string returnUrl)
	if (HttpContext.Request.Url != null && !returnUrl.Contains(HttpContext.Request.Url.Authority))
		returnUrl = $"{HttpContext.Request.Url.Scheme}://{HttpContext.Request.Url.Authority}{returnUrl}";

	var authTypes = AuthenticationManager.GetAuthenticationTypes();

	AuthenticationManager.SignOut(new AuthenticationProperties { RedirectUri = returnUrl }, authTypes.Select(t => t.AuthenticationType).ToArray());
	return Redirect(!string.IsNullOrEmpty(returnUrl) && Url.IsLocalUrl(returnUrl) ? returnUrl : "~/");

The changes here are to ensure that the return URL passed to Azure B2C is a includes the full site URL and not just the relative path. Azure B2C checks this return URL against what was configured in the application settings to ensure it includes the same root URL.   Additional the code to tell ASP.NET Identity OWIN to sign out not only of the portal but also Azure B2C is to modify the SignOut method of the AuthenticationManager to include the authentication types as a parameter. This causes OWIN to process not only the ADX applicaiton cookie but call the associated Azure B2C logoff method which will remove the Azure B2C cookie as well.

Note – you may also modify the ReturnUrl methods in Helpers\UrlHelper.cs to output a full qualified URL as the return URL instead of modifying the URL in the LogOff HTTP GET method.

The following is the change to the HTTP POST method, no return URL is needed, just the Authentication Types added to the SignOut parameters.

// POST: /Login/LogOff
public ActionResult LogOff()
	var authTypes = AuthenticationManager.GetAuthenticationTypes();

	AuthenticationManager.SignOut(authTypes.Select(t => t.AuthenticationType).ToArray());
	return Redirect("~/");

The other changes you would be able to make in the code is mapping claims to CRM properties so that the profile is auto populated. Though you may need to consider a more complex implementation so that all CRM modifications of certain attributes are sync’d back to the Azure AD B2C attribute store. If you are interested then check out the Graph API documentation. For a less complex implementation that does not require complex attribute mapping, you could leave contact profile data collection just to CRM/portal and not collect any additional claims on the Azure B2C side.

If you want to at least ensure the email from Azure B2C is mapped to the CRM Contact email address then you can modify the ExternalLoginCallback method in the LoginController.cs and add lines 8 – 11 highlighted in the following code:

var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();

if (loginInfo == null)
	return RedirectToAction("Login");

if (string.IsNullOrEmpty(loginInfo.Email))
	loginInfo.Email = loginInfo.ExternalIdentity.Claims.FirstOrDefault(a => a.Type == "emails")?.Value;

This is necessary due to the AuthenticationManager.GetExternalLoginInfoAsync() method only looking for as the claim type name it would get for email.  Note B2C has been modifying the email claim name recently so you may need to update the Type condition to match what is current.

A last tip, if you plan to only use Azure B2C then it might make sense for your users to skip the portal sign in page and go directly to Azure B2C. This can be done using an out of box site setting Authentication/Registration/LoginButtonAuthenticationType. Simply set this site setting to same value as the site setting Authentication/OpenIdConnect/AzureADB2C/AuthenticationType and the sign in button in headers that utilize the UrlHelper method (default out of box non-liquid based) will forward directly to Azure B2C.

Azure AD B2C Now Supports ADXStudio Portals v7

Azure Active Directory B2C is a new Azure service that is targeted at helping your organization utilize consumer based identities within your sites and applications.  Until recently ADXStudio Portals version 7 required custom code modification to properly support Azure B2C as a login provider but now with a recent change by the Azure AD B2C team it can be configured directly through site settings.

ADXStudio Portals implementation of ASP.NET Identity is perhaps one of the best identity implementations in a CMS.  It supports such a wide array of protocols and token formats making it easy to integrate with various identity platforms and supports a single profile with many identities.  Previously ADXStudio Portal integrated with Azure ACS (Access Control Service) which provided a way to integrate with social identity providers like Google, Facebook or Microsoft Windows Live ID (at the time) if you wanted a common STS that managed all your consumer identity providers.  The ADXStudio Community site actually still uses Azure ACS for its authentication.  Azure ACS is being retired and replaced by various new Azure services (creating new ACS directories has been blocked, but existing directories continue to function), for the consumer identity side that replacement is Azure AD B2C which comes with a wealth of new features that many have been long asking for in Azure ACS.

With ADXStudio Portals implementation of standards based protocols like OpenID Connect and the same standards based protocols implemented in Azure AD B2C you would think it was an easy match.  Unfortunately ADXStudio Portals v7 ASP.NET Identity OWIN implementation expected a certain claim to be populated and Azure AD B2C was not supporting that claim…until recently.

The claim required by ADXStudio Portals ASP.NET Identity:

And until recently Azure AD B2C would populate that claim with “Not supported currently. Use oid claim.”.  Since ASP.NET Identity mapped the nameidentifier claim to the login key and ADXStudio Portal the login key to the username field in CRM, no matter who you logged in as on the Azure AD B2C side you would always be the same contact in ADX/CRM.  The error in the nameidentifier claim from Azure AD B2C was directing the application to instead use the OID claim:

And to use this claim value as the username, but this required some custom code to override the existing ASP.NET Identity logic within the ADXStudio Portal login controller callback method.

Now new Azure AD B2C policies are populating nameidentifier with the same value as objectidentifier which allows ADXStudio Portal to be configured with a Sign Up and Sign In policy just through portal site settings.  There is still some functionality that will required to you modify the ADX code base, sign out that including signing out of Azure AD B2C, if you want to incorporate profile edits that sync with CRM attributes, and if you wanted to use separate policies from registration and sign in.

Note, if you have existing Azure AD B2C tenant with existing policies, the nameidentifier claim may still not show in those policies.  Re-creating your policies should enable the nameidentifier claim.

To learn more about configuring ADXStudio Portals with Azure AD B2C I will follow this up with a guide shortly showing the configuration end to end.

Microsoft Ignite Dynamics CRM Highlights

Microsoft Ignite the re-envisioning of Microsoft TechEd now includes a lot of the technical components of the old Microsoft Convergence conference, was held just this last week in Atlanta.  This was the first time Microsoft Dynamics was part of this conference and it was great to have it there.  Both myself and a college were down in Atlanta representing Adoxio and were able to learn a lot while networking with a lot of great Microsoft engineers, partners, and vendors.  There was such a wealth of information available at all of the sessions that it is hard to condense it into a single post but I have outlined some of my top highlights below with links to the recorded sessions.

  • CRM Editable Grid – with much fan fair this was publicly announced and coming this fall you will be able to edit your records within a CRM view not having to drill directly into the record allowing you to quickly edit multiple records.  This has been available in the past as an ISV solution from various partners but now it is coming as a native control for both views and sub grids.  The feature was created by the Project and Field Service team (checkout the CRM Field Team blog) out of their own internal need and has been brought into the CRM product.  The configuration options are astounding, and it even comes with an API!  Watch Matt Barbour’s session, Evolve with Microsoft Dynamics CRM platform and online to hear and see the editable grid in action! See time index, 1:00:45.
  • Application Lifecycle Management and Developer Tool Improvements – Visual studio developers rejoice, there are tons of improvements coming that will help you manage your CRM customizations within Visual Studio and with your source control system.  There are also a lot of application platform changes and improvements being made in recent releases and upcoming ones.  Watch Matt Barbour And Brandon Kelly’s session, Learn the essentials of application lifecycle management for Dynamics CRM to get a deep dive and demo of all the latest functionality.  See time index 36:25 for a demo of the developer tools from Brandon.
  • Server to Server Authentication – We have seen it in the new CRM Portal with the fact that records are owned by SYSTEM, no longer will you need to have a service account to interact with Dynamics CRM from an application and have a user license used.  Client ID and Secret functionality will be coming to CRM this Fall, you can see more in  Learn the essentials of application lifecycle management for Dynamics CRM from Matt Barbour and Brandon Kelly.  See time index 29:57 to hear about authentication in CRM from Matt.
  • Azure Service Bus and CRM Service Endpoint – In multiple sessions the Dynamics CRM product team stressed the use of the Service Endpoint functionality.  With the extremely easy to configure Service Endpoint to an Azure Service Bus, be it a Queue, Topic or Event Hub this is a great way to offload processing from the CRM system.  If you want to learn how to use the Service Endpoint with the Azure Service Bus head over my blog post about using it with Azure Event Hubs.  You can also watch Matt Barbour’s session, Evolve with Microsoft Dynamics CRM platform and online where he gives a full demo of configuring a Service Endpoint with an Azure Service Bus Queue; see time index 35:42.
  • Lifecycle Services – This has been a major pillar of Dynamics AX online and now a lot of functionality is coming to Dynamics CRM.  Currently the data loader is available and in private preview is the Metadata migration.  Lifecycle Services will also be making moving to the cloud from your CRM 2011 and above on premise installations a lot less painful.  For those looking to move to the cloud this is a must look.  Watch Simon Matthews’ session, Migrate metadata and data to CRM OL with Lifecycle Services accelerators.
  • CRM Portal – The product continues to evolve and just get more great functionality with new portals for Event Management and Project Service coming in preview after the fall release of Dynamics CRM.  The team also has worked hard to enhance the existing portals with more functionality including conditional entity actions and much more.  Check out the session, Engage external communities with Microsoft Dynamics CRM Portals from Shan McArthur and Dileep Singh.
  • Microsoft Flow and Azure Logic Apps – This is the Microsoft workflow engine of the future and it is only going to get better with Dynamics CRM.  Coming in the future (Spring/Summer 2017) is a real-time connector with Dynamics CRM, meaning you will no longer have to poll at an interval and will be event based making integrations that much better for performance.  Watch Matt Barbour’s session, Evolve with Microsoft Dynamics CRM platform and online for a live demo of both Microsoft Flow; see time index 30:31.

These were just the highlights for Dynamics CRM!   Ignite is such a huge conference now blurring the lines between IT Pro and Developer roles, and covering information available for almost all Microsoft products.

On a side note, also born out of this conference was Alan the Unicorn.  If you haven’t seen the exploits of Alan Unicorn from Microsoft Ignite you can checkout Twitter with the hashtag #alantheunicorn to see all the session knowledge that was gain and fun times that he had.  Look out for Adoxio’s #alantheunicorn at future conferences!

Note: This post also appears on Adoxio Business Solutions Team Blog.

Update: Added details about Project and Field Service team as authors of the CRM Editable Grid.

Using an Azure Service Bus with Dynamics CRM 2016 Spring Update

CRM developers and even end users know of the asynchronous service in CRM; the service is usually associated with workflow processes or plugins. An often forgotten feature is its ability to notify a service endpoint with the data context of the particular CRM message that it is registered on.

The data context contains all of the business data that is processed as part of the CRM message.  So if you were to create a contact with first name and last name, the data context would contain that data as well as any other default data as part of the create itself.  Things like a newly created contact ID, the created by system user ID,  any option sets that had a default value, and a lot more.  It is the same data context that you work with when building a plugin so it also will contain your input parameters, pre and post images, the execution depth, the entity logical name, and what CRM message is being executed (create, update, delete, etc.).  I have posted a sample contact create data context in JSON here so you can get an idea of all the data it contains as well as its format.

So why would you want to send this to a service endpoint like the Azure Service Bus?  Often the CRM asynchronous service is over taxed; it is responsible for so much in the CRM system now.  If we can offload some of that logic processing elsewhere then we can improve the overall performance of the CRM system.  You need to have the right use case for using the service endpoint though, and choosing which type of Azure Service Bus to send it to will also depend on what your use case is.  Over the next few blog posts I will explore some of the use cases I have and are looking to use the service bus with, items like near real-time integrations, ADXStudio cache invalidations, search indexes, and more.

Previously using the Azure Service Bus was more complex as the integration relied on the old (now deprecated) Azure ACS functionality.  You had to weave through a number of steps to get it all setup and it was prone to errors.  With Dynamics CRM 2016 Spring Update this process has become extremely easy with the support for the modern authentication, Shared Access Signatures (SAS).  Also with this release support has now been added for all of the Azure Service Bus types; Queues, Topics and now Event Hubs.  Another improvement is you can have the message format of the data context sent in XML and also now JSON.  Using JSON will cut the message size in nearly half from the same XML message.

MSDN has provided a walkthrough with the classic Azure portal using a queue.  Below I have outlined the process in using the new Azure portal as Service Bus management has recently launched in preview to create an Event Hubs Namespace, Event Hub, then Register it with CRM and validate everything works with Service Bus Explorer.

Setup Azure Event Hub Namespace and Event Hub in the New Azure Portal

  1. Navigate to the new Azure portal and sign in with your subscription administrator account.
  2. From the side navigation, select New and search for “Event Hubs”.
  3. Select the Event Hub result and create a new Event Hub Namespace.
    For just testing you can select the basic pricing tier but for production use it would be suggested to go with the standard tier.  It would also be advised that you try and locate your Event Hub in the same data center region as the your CRM online organization.  If you are an on premise user then likely the closest physical region to your CRM.
    Azure Portal Create Event Hub Namespace
  4. Once the Event Hub Namespace is created and deployed, we still need to create the actual Event Hub.  To do so Open The Event Hub Namespace and select Event Hubs from the settings blade.
  5. From the new blade that lists all the Event Hubs in the namespace at the top click “Add New Event Hub”.
  6. Give it a name, and for the purposes of the demo leave all the other defaults.  See the Event Hub Overview documentation for more information about the settings.  You will use the name you assign it when registering the Event Hub.
  7. Now we need a key and connection string for the namespace.  From the settings blade select Shared Access Policies.
    Event Hub Settings
  8. Here you can either select the existing root key, or better yet create a new CRM key.  When creating a new key ensure you select the Send and Listen claims to be enabled.
  9. In the policy settings blade copy and save the “Connection String Primary Key” as we will then use this to register the service endpoint.

Register the out of box CRM-Azure Plugin with an Event Hub Service Endpoint.

Note: The out of box CRM-Azure plugin is preferred if you want to just send entire messages to the service bus.  This plugin executes in full trust mode vs. custom CRM-Azure plugins which executes in partial trust mode.  To learn more see Write a custom Azure-aware plugin.

  1. If you do not have the 8.1 (2016 Spring Update) SDK then download it here.
  2. Within the extracted SDK browse to “Tools\Plugin Registration” and run PluginRegistration.exe.
  3. Create a new connection to your CRM organization.
  4. Once connected, to register your Event Hub select Register, Register New Service Endpoint.
    Register New Service Endpoint
  5. In the dialog select the “Let’s start with the connection string…” and paste in the “Connection String Primary Key” we saved from the Azure Portal Event Hub Shared Access Policies. Select Next.
  6. On the Service Endpoint Registration, select the Designation Type as Event Hub and enter the Event Hub name you created previously. Setting User Information Sent to UserId will include additional claims in the message. Select Save.
    Endpoint Details
  7. You should now have your new Service Endpoint listed.  From here you can start registering steps on different entities and messages of what you want sent to the Event Hub.  Let’s setup a demo contact create one.  Right click on it and select Register New Step.
  8. On the Register New Step dialog enter “Create” as the message and “contact” for Primary Entity.
  9. Change the execution mode to Asynchronous and check the Delete AsyncOperation if StatusCode = Successful.  For developments purposes you might leave this cleared so you can see when messages are sent properly.  We will be using another tool to listen to the event hub and see successful messages posted.
    Register New Step

At this point we have successfully configured the Event Hub using the Azure portal, registered the Event Hub with CRM as a Service Endpoint, and registered a step for on create of contacts.  To help us validate if this is working successfully we need to view the Event Hub to see what messages are posted.  An open source tool from an Microsoft engineer, Paulo Salvatori, Service Bus Explorer provides this function and can downloaded from GitHub (best if you want to modify and contribute), you can also get it from MSDN Code Gallery (best if you just want to run it) which includes a debug version already compiled.

Validate CRM Service Endpoint to Event Hub with Service Bus Explorer

  1. After you have downloaded and extracted Service Bus Explorer, browse to “C#\bin\Debug” and run ServiceBusExplorer.exe if using the MSDN Code Gallery download, otherwise you will need to compile and run the solution.
  2. Select File, Connect.  Under Service Bus Namespaces select “Enter connection string…”.  For this connection you will need the claim Manage on the policy used.  So navigate back to the Azure Portal and select the root key or create a new key with Manage claim.  Select OK once you have entered your connection string.  Any errors in the connection will be shown in the log panel on the bottom.
  3. Once successfully connected, the left navigation should populate with your Event Hub.  Expand the Event Hub, and Consumer Groups to expose the default consumer group called, “$Default”.  Right click on this consumer group and select Create Consumer Group Listener.
    Service Bus Explorer Consumer Groups
  4. In the new window for the listener select the Start button.  In the log you should see it open a connection to the 2 Event Hub partitions.
    Service Bus Explorer Listener Log
  5. Now navigate to the CRM and create a new contact.  Once you have created the contact look back at the Service Bus Explorer listener window.  If you have successfully set it up you should see a new log item appear with the message “Event received…”.
  6. You can view the entire message by navigating to the Events tab at the top of the window, then select the message from the list and the Event Text is the body of the message with your JSON formatted data context object.
    Service Bus Explorer Listener Event Details

If you did not see your message on the Event Hub then you will want to go in CRM and view the System Jobs log under Settings.  From there you should see the failed or cancelled System Event, open it and expand the details to see any error messages.
CRM System Jobs Cancelled System Event

Hopefully this guide has been helpful.  I will be using this as a step in future posts to implement a number of different functionalities.

Welcome :)

Hello, welcome, I am Colin Vermander and thought it might be good to introduce myself as my first blog post.  I am a solution architect and full stack developer who has been working in IT for over 15 years now.  Over those years I have had a chance to do a wide variety of projects working with many different talented individuals and interesting organizations.  I started my professional career in the infrastructure world, my first big project was moving a company off their ISP hosted email service to their own Microsoft Exchange Server!  From there I embedded myself deeply in the Microsoft server world and was always trying the latest and greatest out on the users I worked with.

Software development has always been a hobby of mine and I have managed to turn it into a great career.  The point I really remember it starting was the summer I broke my arm and couldn’t go to a sailing camp :(.  So my parents put me in computer camp…web site 101 basically.  I loved it, completely hooked.  So hooked that my next birthday I asked for, not the latest remote controlled car, or whatever else was cool that year, but software so I could make web sites.  Numerous years later and I have had the chance to build tons of sites and use many different platforms to power them.

The last 5 years I have spent deep in the Dynamics CRM world.  First introduced to CRM 3.0 by having to install it for someone moving from Goldmine.  To then starting with ADXStudio as a developer after the launch of CRM 2011 to build web sites or portals using CRM as a backend.  You might know ADXStudio as Microsoft acquired the portal product and brand in October 2015 that is now part of the Dynamics CRM family known as CRM portals.  Since then the members of ADXStudio formed Adoxio Business Solutions and within 8 months we won Microsoft Dynamics Partner of the Year for Canada in 2016!

Throughout all this time the value of the IT communities; Dynamics CRM, ASP.NET, and all types of software development, has always blown me away.  The moments where I am stumped on a problem, and I find that 1 post where they have had the exact same issue and were kind enough to share their knowledge with everyone else always have delighted me.  So thank you to all those that share their challenges and solutions.  I hope I can help start contribute to that sharing with my challenges, solutions and fun discoveries on this blog.