Bringing Azure and ForgeRock together via OIDC
Microsoft Azure is one of the most popular cloud platforms out there today and we often integrate with it in many different ways. One of them is where Azure provides authentication services and acts like a social identity provider — kind of “Login with Azure” approach.
Let’s see what would it take to realise that scenario using ForgeRock AM 7 (its Intelligent Authentication capability) and OpenID Connect standard. To make things more interesting I’ll be using ForgeRock Identity Cloud as the environment.
Preparing Azure
First let’s setup Azure. The assumption is we already have users configured in Azure, so we’ll skip that part.
We need to configure ForgeRock AM as OIDC client. In Azure Portal (portal.azure.com) we configure an application via “App Registrations” service.
Once here we nee to create a new app registration:
Let’s give it a name eg. “ForgeRock AM”, define who can use our application and configure redirect URI that would instruct Azure where to redirect user when the authentication process is finished (eg. https://[amFQDN]/am or for ForgeRock Identity Cloud https://[amFQDN]/login).
Now, we need to copy Application (client) ID.
What’s definitely missing here is client secret. We can generate it via Security section on the lefthand side menu.
Once generated let’s copy the “Value” — it will be needed shortly.
So far our application (Forgerock AM) does have one privilege assigned (scope) for Azure API — this happens by default. We can review that by going to API Permissions section. Which privileges should be granted depends on what’s needed on the application side. By default there should only be User.Read
permission assigned and that is sufficient for our use case. If you needed to add another permission you can do so by clicking on “Add a permission” button a following the wizard.
Preparing ForgeRock AM
ForgeRock Access Management 7.x makes any OIDC based integration deadly simple.
In our case there are only two steps involved — preparing a “Social Identity Provider Service” and creating a user journey (via Authentication Trees). For better “visual” effect we’ll use administrative UI but the same configuration can be performed in a programatic way using REST API.
Social Identity Provider Service
In AM administrative console we need to configure Azure as one of Social Identity Providers. This is done on a realm level in “Services” section:
We need to make sure the service is enabled:
And then configure microsoft
in the “Secondary Configurations” section filling the details we got when creating an application in Azure:
The only thing we need to change for the default config is Client ID
and Client Secret
. The rest is already there. We can tweak look and feel in “UI Config Properties” :
But for now we can skip that. Important thing to mention here is the “Transformation Script” - in case on Microsoft this is called “Microsoft Profile Normalization”. What the script does is it converts identity data received from a social provider to a “common” object format. The reason why this being done is various social provider might bring information in various claims/attributes. Abstracting normalization part gives us huge flexibility when adding custom identity providers and matching attributes — we can normalize whatever identity provider brings to a common format. By the way — we can extend the script to suit our need. Let’s have a look what the scripts does out-of-the-box by going to the “Scripts” section in AM administrative console:
As you can see this script has a really simple logic and requires minimum effort to adjust (if needed).
ForgeRock Authentication Tree
The next part is configuring authentication journey. As we are using ForgeRock Identity Cloud we a nice new Platform UI at our disposal that allows us to create this journey. If we had a standalone ForgeRock AM deployment we could do exactly the same in the native AM admin UI in “Authentication”->”Trees” section:
Let’s then create a tree in the new Platform UI.
Now lets add nodes (building blocks of a journey) to the canvas:
Here’s what is happening in our tree after user hits it:
- Page Node — this is a “frame” node that allows you bringing several elements together and showing them to the user. It can also have a description assigned so that user can be presented with an informative message. In our case we included just a single element — node called “Select Identity Provider” allowing to serve social providers configured and enabled previously.
2. Social Provider Handler Node — provides actual identity provider login capability. In addition it verifies if the user exists already or not.
3. When exiting “Social Provider Handler Node” we can have to outcomes: user exists or not.
a. If user exists we complete this journey successfully. I also added one more useful node — “Increment Login Count” which in our case stores number of successful user logins. This information can be used later on eg. for triggering progressive profiling journey.
b. User does not exist. If that’s the case we’re first checking if we have all the required attributes present (“Required Attributes Present” node) already (in the token coming back from the IdP, or any other preceding nodes). Please note as we’re using ForgeRock Identity Cloud “Identity Resource” is mapped to managed/alpha_user
.
4. If we do have all the information required, we can create user object and finish the journey with success.
5. If we don’t, “Attribute Collector” node can help us getting additional information from the user.
Then we hit “Create Object” (as above). If for whatever reason object cannot be created we will fail the journey.
Testing the flow
Finally we can test the flow. In the Journey view we have a little helper allowing us to copy the URL which would directly invoke our new AzureOIDC tree.
After going to that url here’s what should happen. More or less … :-)
Step 1 — visiting the URL copied from the step before.
https://[am_instance]/am/XUI/?realm=alpha&authIndexType=service&authIndexValue=AzureOIDC
Step 2 — Sign in to Azure.
Step 3 — Account created (if does not exist) and user logged in.
I hope that was useful. Happy integration!