IdentityServer, OpenID Connect and Microsoft CRM Portals
Posted by Dylan Beattie on 14 November 2016 • permalinkAs readers of this blog will know, here at Spotlight we’re in the process of moving nine decades’ worth of legacy business process onto Microsoft Dynamics CRM, aka CRM Online, which I gather is now called Dynamics 365 (because hey, it’s not like naming things was hard enough already, right?)
We’re also investigating a couple of options for building customer-facing systems that integrate with Dynamics. Until last year, there were really three options for this – a product called Adxstudio, a free Microsoft component called the CRM Portal Accelerator, or rolling your own solution using the CRM SDK. Around this time last year, Microsoft quietly retired the Portal Accelerator component and acquired Adxstudio, and since then, they’ve been in the process of assimilating it into the Dynamics product family – which has meant it’s been something of a moving target, both in terms of the supported features and in terms of the quality of documentation and examples.
I’ve previously blogged about one way to integrate Adxstudio with your existing authentication system, but that approach relied completely on running Adxstudio on-premise so you could run your own code as part of the request lifecycle – and as you may have noticed, there’s a bit of a trend in IT at the moment away from running your own servers and towards using hosted managed services, so that patching and backups are somebody else’s problem. Since Microsoft acquired Adxstudio, there’s been a lot of churn around what’s supported and what’s not – I’m guessing that behind the scenes they’re going through the Adxstudio codebase feature-by-feature and making sure it lines up with their plans for the Dynamics 365 platform, but that’s just guesswork on my part.
One of the main integration points I’ve been waiting for is the ability for a Microsoft-hosted Portal solution to use a third-party OpenID Connect endpoint to authenticate users, and it appears in the latest update this is finally supported – albeit with a couple of bumps along the way. Here’s what I’ve had to do to get a proof-of-concept up and running.
Setting up Dynamics CRM Portals
First, you’ll need to set up a Dynamics Portal trial. You can get a 30-day hosted trial of Dynamics CRM Online by signing up here – this actually gives you a full Office 365 organization including things like hosted Active Directory, as well as the Dynamics CRM Online instance we’re using in this example. Next, you’ll need to ask nicely for a trial of the portal add-on – which you can do by filling out the form at crmmanagedtrials.dynamics.com.
Setting up IdentityServer and configuring an ngrok tunnel
Whilst you’re waiting for the nice Microsoft people to send you your trial license, get up and running with IdentityServer. For this prototype, I’m using the MVC Authentication example from the IdentityServer3.Samples project – clone it to your workstation, open the MVC Authentication solution, hit F5, verify you can get up and running on localhost.
Next – in order for Dynamics CRM Online to talk to your IdentityServer instance, you’ll need to make your IdentityServer endpoints visible to the internet. You could do this by deploying your IdentityServer sample to Azure or AWS, but for experiments like this, I like to use a tool called ngrok, which will create temporary, secure tunnels from the internet to your workstation. Download ngrok, unzip it somewhere sensible.
Pick a tunnel name. I’m using authdemo in this example but any valid DNS host name will do. Next, create a local IIS application pointing to the EmbeddedMvc folder in your samples directory, and set the host name to <your tunnel name>.ngrok.io
Now run ngrok.exe to create a tunnel from the internet to your new IIS application:
C:\tools\ngrok> ngrok.exe http –subdomain=authdemo 80
ngrok by @inconshreveable
Session Status online
Version 2.1.18
Region United States (us)
Web Interface http://127.0.0.1:4040
Forwarding http://authdemo.ngrok.io -> localhost:80
Forwarding https://authdemo.ngrok.io -> localhost:80Connections ttl opn rt1 rt5 p50 p90
0 0 0.00 0.00 0.00 0.00All being
If that’s worked, you should be able to fire up a browser, go to http://authdemo.ngrok.io/ – replacing ‘authdemo’ with your own tunnel name - and see the IdentityServer3 sample landing page:
Configuring IdentityServer
Right. Next thing we need to do is to make a couple of changes to the IdentityServer configuration, so that it’ll run happily on authdemo.ngrok.io instead of on localhost
First, enable logging. Just do it. Use the package manager console to install the Serilog.Sinks.Trace package. Then add this to the top of your Configuration() method inside Startup:
Log.Logger = new LoggerConfiguration() .MinimumLevel.Debug() .WriteTo.Trace() .CreateLogger();
and add this to your web.config, specifying a path that’s writable by the application pool:
<system.diagnostics>
<trace autoflush="true"
indentsize="4">
<listeners>
<add name="myListener"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="C:\logfiles\identityserver.log" />
<remove name="Default" />
</listeners>
</trace>
</system.diagnostics>
Next, do a global search and replace, replacing any occurrence of localhost:44319 with authdemo.ngrok.io – again, substituting your own tunnel name as required.
Next, add a new client to the static EmbeddedMvc.IdentityServer.Clients class the IdentityServer sample project – changing the highlighted values to your own client ID, client secret, and portal instance URL:
new Client {
ClientName = "Dynamics CRM Online",
ClientId = "crm",
Flow = Flows.Hybrid,
ClientSecrets = new List() { new Secret("secret01".Sha256()) },
RedirectUris = new List {
"https://my-portal-instance.microsoftcrmportals.com"
},
PostLogoutRedirectUris = new List {
"https://my-portal-instance.microsoftcrmportals.com"
},
AllowedScopes = new List { "openid" }
},
Adding IdentityServer as an endpoint in CRM Portals
Finally, you need to add your new IdentityServer as an identity provider. CRM Portals uses the Dynamics CRM platform for all its configuration and data storage, so to add new settings you’ll need to log into your Dynamics CRM Online instance, go into Portals > Site Settings, and add the following values:
Name |
Value |
Website |
Authentication/OpenIdConnect/AuthDemo/Authority |
http://authdemo.ngrok.io/identity/ |
Customer Self-Service |
Authentication/OpenIdConnect/AuthDemo/Caption |
IdentityServer OpenID Connect Demo |
Customer Self-Service |
Authentication/OpenIdConnect/AuthDemo/ClientId |
crm |
Customer Self-Service |
Authentication/OpenIdConnect/AuthDemo/ClientSecret |
secret01 |
Customer Self-Service |
Authentication/OpenIdConnect/AuthDemo/MetadataAddress |
http://authdemo.ngrok.io/identity/.well-known/openid-configuration |
Customer Self-Service |
Finally, it looks like you’ll need to restart the portal instance to get it to pick up the updated values – which you can do by logging into the Office 365 Admin Center, Admin Centers, CRM, Applications, Portal Add-On, clicking ‘MANAGE’, and pressing the nice big RESTART button on the Portal Actions page:
And – assuming everything lines up exactly right – you should now see an additional login button on your CRM Portals instance:
Clicking on it will bounce you across to your ngrok-tunnelled IdentityServer MVC app running on localhost:
Log in as bob / secret, and you’ll get the OpenID permissions check:
…and when you hit ‘Yes, Allow’, you’ll be redirected back to the CRM Portals instance, which will create a new CRM Contact linked to your OpenID Connect identity, and log you in to the portal.
Conclusions
Of course, in the real world there’s a lot more to it than this – there is a huge difference between a proof of concept like this and a production system. These sorts of user journeys form such a key part of delivering great user experience, and integrating multiple systems into your login and authentication/authorization journeys only makes this harder. But it did work, and it wasn’t actually all that complicated to get it up and running. It’s also interesting to see how something like OpenID Connect can be used to integrate a powerful open-source solution like IdentityServer with a heavyweight hosted platform service like CRM Portals.
Whether we end up adopting a hosted solution like CRM Portals – as opposed to just building our own apps that connect to CRM via the SDK or the new OData API – remains to be seen, but it’s nice to see solutions from two radically different sources playing nicely together thanks to the joy of open protocols like OpenID Connect. Long may it continue.