Testing out the new API Connectors feature of Azure AD External Identities

External Identities just got a hell of a lot closer to B2C, with the API Connectors feature, allowing external API calls to happen before user creation and after signing in with an identity provider. As in my last post about the new External Identities feature, this post will be me exploring the new feature, simply blogging about my experience with it, and which awesome and not so awesome stuff I find.

One thing the Identity product group has really started to become good at, is documentation from the start. This time, a blog post with use cases, a great overview / introduction, a super detailed post about the approval use case and a full github repo with an example API. Not bad when comparing to the launch of Azure AD B2C (which is now swimming in doc, but once upon a time…).

The example of the approval use case is a bit too time consuming for the first blog post on this topic, but I will just try out some customer asks that I have seem before.

First, let’s try to figure out if we can essentially call an API whenever any guest tries to access an application. My preferred method for these kinds of APIs is Azure Logic Apps, so I’ll create a simple HTTP request triggered LogicApp, with random number returned, just to check out the feature first.

Quick creation, and let’s just start with a simple 1-step template:

Based on this example, I just paste the following as my request sample:

{
 "email_address": "johnsmith@fabrikam.onmicrosoft.com",
 "identities": [
     {
     "signInType":"federated",
     "issuer":"facebook.com",
     "issuerAssignedId":"0123456789"
     }
 ],
 "displayName": "John Smith",
 "ui_locales":"en-US"
}

Since I am not currently planning on using the input for anything useful, I could have easily not put anything in the schema. Next, we add a response step like this:

This is the body I used to respond with a random integer between 1000 and 9999:

{
    "jobTitle": "@{rand(1000,9999)}"
}

Please note that the keys (attributes) must reflect a supported Azure AD attribute, and cannot be completely random). After saving, you’ll find the url of the Logic App here:

A quick PowerShell verifies that it works as expected:

Now, we register an application in our tenant like the following. This will be the app that our users are signing into:

Noting down our tenant id and client id for later:

We need to make sure the following feature is enabled, in order to create user flows:

We are now ready to add our API connector, under the External Identities tab:

First we define a name for the API, our URL (which contains a secret, so this is already authenticated) and a dummy username and password (Basic auth only for now – Microsoft, please add bearer token support just like SCIM, as well as the ability to provide a static authorization header):

Next, I first used department as the attribute, but found that it was not on the list of supported attributes. So jobTitle is what I ended up using. (Microsoft Product Group, please add support for all attributes, I want to put random integers into attributes):

This looks very promissing:

Now we create a new user flow:

Just give it a name and click create, and you will end up here:

Now we can assign our API connector to this flow:

And the last thing is to assign our application to the user flow as follows:

Now we are ready to test it out! We can do this without any listening endpoints and stuff, simply use a url like the following:

https://login.microsoftonline.com/<TENANTID>/oauth2/authorize?client_id=<CLIENTID>&response_type=code&redirect_uri=<VALID_REDIRECT_URI>&response_mode=query

https://login.microsoftonline.com/937a3b05-1264-406f-ade1-3f4a42d4e26f/oauth2/authorize?client_id=f2138bf5-3fc3-4eea-86f3-62fab4304e3a&response_type=code&redirect_uri=http://localhost:8000&response_mode=query

Going to my sign in url, I can see that I get the “Create one!” user flow experience:

Since I not yet a guest in the tenant, I can type the email address for my work account (as I have not configured social IDPs in this tenant, please see my previous post), and sign in with that.

Unfortunately Microsoft has not yet fixed the issue with signing up with a work account:

But hey, let’s invite it and see what happens then.

New-AzureADMSInvitation -InvitedUserEmailAddress x.y@contoso.com -InviteRedirectUrl https://myapps.microsoft.com

But, trying again with a succesfull sign-in, still does not trigger my API (these three times are my own PowerShell testing):

My guess here is that it is not called, because we invited the user, rather than the user using the signup feature, which apparently is bugged for Azure AD users. Let’s try out a social IDP instead:

The steps are already documented here, and I end up with a clientid and secret:

Then we enable Facebook auth for our user flow:

Then we try to sign up again with our url – https://login.microsoftonline.com/937a3b05-1264-406f-ade1-3f4a42d4e26f/oauth2/authorize?client_id=f2138bf5-3fc3-4eea-86f3-62fab4304e3a&response_type=code&redirect_uri=http://localhost:8000&response_mode=query

We now find “Sign in with Facebook” as a new option:

Ok, sign-up successful, and? Nothing…

Now what? Well guest what, remember that it only supports basic auth, right? Turns out Logic Apps is not all that happy about getting that authorization header:

Crap, well, that ruins Logic Apps apparently, as I see no way of ignoring the authorization header. Let’s try an Azure Function with PowerShell then:

Let’s try authorization level “Function” first, which again, is a secret in the url or a header:

Here is a sample code that I am using, doing the same thing as my Logic App:

using namespace System.Net

# Input bindings are passed in via param block.
param($Request, $TriggerMetadata)

$body = @{
    jobTitle = [String] (Get-random -min 1000 -max 9999)
} | Convertto-json

# Associate values to output bindings by calling 'Push-OutputBinding'.
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
    StatusCode = [HttpStatusCode]::OK
    Body = $body
})

Tested sending with dummy authorization header!

Ok, now we just reconfigure the url for our API, and try to sign in again with Facebook! I will now try deleting the user first, just to be sure.

And finally my function was called!

But my jobTitle was not populated, as I expected:

What do we do now? Well of course we read the freakin’ documentation that I have already given credit to, and see that there are a few other things that we need to add to our response! Modifying our function:

using namespace System.Net

# Input bindings are passed in via param block.
param($Request, $TriggerMetadata)

$body = @{
    jobTitle = [String] (Get-random -min 1000 -max 9999)
    version = "1.0.0"
    action = "Continue"
} | Convertto-json

# Associate values to output bindings by calling 'Push-OutputBinding'.
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
    StatusCode = [HttpStatusCode]::OK
    Body = $body
})

Again, deleting the user and trying to do a sign UP, and jobTitle is STIL NOT POPULATED… Wonder if this is because I did not state “Before creating the user”, and that after signing in does not support receiving attributes?

Well, let’s try that then! Deleting user, signing up – STILL NO JOB TITLE….. And I do see that my function is being called properly. But again, good documentation that I did not read:

So, let’s select it as a user attribute on our flow then!

That changes things!

Now it seems it autocompleted the user attribute collection page with my value, though without saying what the content should be to the user. Not really an optimal experience currently, I would really like for an option to keep attributes “silent” 🙂

Well, this took a little longer than expected, so I’ll make a more advanced post soon.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s