Friday, 26 July 2024

Add an API connector to a sign-up user flow

 

Create an API connector

To use an API connector, you first create the API connector and then enable it in a user flow.

  1. Sign in to the Azure portal.

  2. Under Azure services, select Azure AD B2C.

  3. Select API connectors, and then select New API connector.

    Screenshot of basic configuration for an API connector

  4. Provide a display name for the call. For example, Validate user information.

  5. Provide the Endpoint URL for the API call.

  6. Choose the Authentication type and configure the authentication information for calling your API. Learn how to Secure your API Connector.

    Screenshot of authentication configuration for an API connector

  7. Select Save.

The request sent to your API

An API connector materializes as an HTTP POST request, sending user attributes ('claims') as key-value pairs in a JSON body. Attributes are serialized similarly to Microsoft Graph user properties.

Example request

HTTP
POST <API-endpoint>
Content-type: application/json

{
 "email": "johnsmith@fabrikam.onmicrosoft.com",
 "identities": [
     {
     "signInType":"federated",
     "issuer":"facebook.com",
     "issuerAssignedId":"0123456789"
     }
 ],
 "displayName": "John Smith",
 "objectId": "11111111-0000-0000-0000-000000000000",
 "givenName":"John",
 "surname":"Smith",
 "jobTitle":"Supplier",
 "streetAddress":"1000 Microsoft Way",
 "city":"Seattle",
 "postalCode": "12345",
 "state":"Washington",
 "country":"United States",
 "extension_<extensions-app-id>_CustomAttribute1": "custom attribute value",
 "extension_<extensions-app-id>_CustomAttribute2": "custom attribute value",
 "step": "<step-name>",
 "client_id":"93fd07aa-333c-409d-955d-96008fd08dd9",
 "ui_locales":"en-US"
}

Only user properties and custom attributes listed in the Azure AD B2C > User attributes experience are available to be sent in the request.

Custom attributes exist in the extension_<extensions-app-id>_CustomAttribute format in the directory. Your API should expect to receive claims in this same serialized format. For more information on custom attributes, see Define custom attributes in Azure AD B2C.

Additionally, these claims are typically sent in all requests:

  • UI Locales ('ui_locales') - An end-user's locale(s) as configured on their device. This can be used by your API to return internationalized responses.
  • Step ('step') - The step or point on the user flow that the API connector was invoked for. Values include:
    • PostFederationSignup - corresponds to "After federating with an identity provider during sign-up"
    • PostAttributeCollection - corresponds to "Before creating the user"
    • PreTokenIssuance - corresponds to "Before sending the token (preview)". Learn more about this step
  • Client ID ('client_id') - The appId value of the application that an end-user is authenticating to in a user flow. This is not the resource application's appId in access tokens.
  • Email Address ('email') or identities ('identities') - these claims can be used by your API to identify the end-user that is authenticating to the application.

 Important

If a claim does not have a value at the time the API endpoint is called, the claim will not be sent to the API. Your API should be designed to explicitly check and handle the case in which a claim is not in the request.

Enable the API connector in a user flow

Follow these steps to add an API connector to a sign-up user flow.

  1. Sign in to the Azure portal.

  2. Under Azure services, select Azure AD B2C.

  3. Select User flows, and then select the user flow you want to add the API connector to.

  4. Select API connectors, and then select the API endpoints you want to invoke at the following steps in the user flow:

    • After federating with an identity provider during sign-up
    • Before creating the user
    • Before sending the token (preview)

    Selecting an API connector for a step in the user flow

  5. Select Save.

These steps only exist for Sign up and sign in (Recommended) and Sign up (Recommended) but only apply to the sign-up part of the experience.

After federating with an identity provider during sign-up

An API connector at this step in the sign-up process is invoked immediately after the user authenticates with an identity provider (like Google, Facebook, and Microsoft Entra ID). This step precedes the attribute collection page, which is the form presented to the user to collect user attributes. This step is not invoked if a user is registering with a local account.

Example request sent to the API at this step

HTTP
POST <API-endpoint>
Content-type: application/json

{
 "email": "johnsmith@fabrikam.onmicrosoft.com",
 "identities": [ 
     {
     "signInType":"federated",
     "issuer":"facebook.com",
     "issuerAssignedId":"0123456789"
     }
 ],
 "displayName": "John Smith",
 "givenName":"John",
 "surname":"Smith",
 "step": "PostFederationSignup",
 "client_id":"<guid>",
 "ui_locales":"en-US"
}

The exact claims sent to the API depend on the information is provided by the identity provider. 'email' is always sent.

Expected response types from the web API at this step

When the web API receives an HTTP request from Microsoft Entra ID during a user flow, it can return these responses:

  • Continuation response
  • Blocking response

Continuation response

A continuation response indicates that the user flow should continue to the next step: the attribute collection page.

In a continuation response, the API can return claims. If a claim is returned by the API, the claim does the following:

  • Pre-fills the input field in the attribute collection page.

See an example of a continuation response.

Blocking Response

A blocking response exits the user flow. It can be purposely issued by the API to stop the continuation of the user flow by displaying a block page to the user. The block page displays the userMessage provided by the API.

See an example of a blocking response.

Before creating the user

An API connector at this step in the sign-up process is invoked after the attribute collection page, if one is included. This step is always invoked before a user account is created.

Example request sent to the API at this step

HTTP
POST <API-endpoint>
Content-type: application/json

{
 "email": "johnsmith@fabrikam.onmicrosoft.com",
 "identities": [
     {
     "signInType":"federated",
     "issuer":"facebook.com",
     "issuerAssignedId":"0123456789"
     }
 ],
 "displayName": "John Smith",
 "givenName":"John",
 "surname":"Smith",
 "jobTitle":"Supplier",
 "streetAddress":"1000 Microsoft Way",
 "city":"Seattle",
 "postalCode": "12345",
 "state":"Washington",
 "country":"United States",
 "extension_<extensions-app-id>_CustomAttribute1": "custom attribute value",
 "extension_<extensions-app-id>_CustomAttribute2": "custom attribute value",
 "step": "PostAttributeCollection",
 "client_id":"93fd07aa-333c-409d-955d-96008fd08dd9",
 "ui_locales":"en-US"
}

The claims that are sent to the API depend on the information is collected from the user or is provided by the identity provider.

Expected response types from the web API at this step

When the web API receives an HTTP request from Microsoft Entra ID during a user flow, it can return these responses:

  • Continuation response
  • Blocking response
  • Validation response

Continuation response

A continuation response indicates that the user flow should continue to the next step: create the user in the directory.

In a continuation response, the API can return claims. If a claim is returned by the API, the claim does the following:

  • Overrides any value that has already been provided by a user in the attribute collection page.

To write claims to the directory on sign-up that shouldn't be collected from the user, you should still select the claims under User attributes of the user flow, which will by default ask the user for values, but you can use custom JavaScript or CSS to hide the input fields from an end user.

See an example of a continuation response.

Blocking Response

A blocking response exits the user flow. It can be purposely issued by the API to stop the continuation of the user flow by displaying a block page to the user. The block page displays the userMessage provided by the API.

See an example of a blocking response.

Validation-error response

When the API responds with a validation-error response, the user flow stays on the attribute collection page and a userMessage is displayed to the user. The user can then edit and resubmit the form. This type of response can be used for input validation.

See an example of a validation-error response.

Before sending the token (preview)

 Important

API connectors used in this step are in preview. For more information about previews, see Product Terms for Online Services.

An API connector at this step is invoked when a token is about to be issued during sign-ins and sign-ups. An API connector for this step can be used to enrich the token with claim values from external sources.

Example request sent to the API at this step

HTTP
POST <API-endpoint>
Content-type: application/json

{
 "clientId": "231c70e8-8424-48ac-9b5d-5623b9e4ccf3",
 "step": "PreTokenApplicationClaims",
 "ui_locales":"en-US",
 "email": "johnsmith@fabrikam.onmicrosoft.com",
 "identities": [
     {
     "signInType":"federated",
     "issuer":"facebook.com",
     "issuerAssignedId":"0123456789"
     }
 ],
 "displayName": "John Smith",
 "extension_<extensions-app-id>_CustomAttribute1": "custom attribute value",
 "extension_<extensions-app-id>_CustomAttribute2": "custom attribute value",
}

The claims that are sent to the API depend on the information defined for the user.

Expected response types from the web API at this step

When the web API receives an HTTP request from Microsoft Entra ID during a user flow, it can return these responses:

  • Continuation response

Continuation response

A continuation response indicates that the user flow should continue to the next step: issue the token.

In a continuation response, the API can return additional claims. A claim returned by the API that you want to return in the token must be a built-in claim or defined as a custom attribute and must be selected in the Application claims configuration of the user flow.

The claim value in the token will be the value returned by the API, not the value in the directory. Some claim values cannot be overwritten by the API response. Claims that can be returned by the API correspond to the set found under User attributes with the exception of email.

See an example of a continuation response.

 Note

The API is only invoked during an initial authentication. When using refresh tokens to silently get new access or ID tokens, the token will include the values evaluated during the initial authentication.

Example responses

Example of a continuation response

HTTP
HTTP/1.1 200 OK
Content-type: application/json

{
    "version": "1.0.0",
    "action": "Continue",
    "postalCode": "12349", // return claim
    "extension_<extensions-app-id>_CustomAttribute": "value" // return claim
}
ParameterTypeRequiredDescription
versionStringYesThe version of your API.
actionStringYesValue must be Continue.
<builtInUserAttribute><attribute-type>NoReturned values can overwrite values collected from a user.
<extension_{extensions-app-id}_CustomAttribute><attribute-type>NoThe claim does not need to contain _<extensions-app-id>_, it is optional. Returned values can overwrite values collected from a user.

Example of a blocking response

HTTP
HTTP/1.1 200 OK
Content-type: application/json

{
    "version": "1.0.0",
    "action": "ShowBlockPage",
    "userMessage": "There was a problem with your request. You are not able to sign up at this time. Please contact your system administrator",
}

ParameterTypeRequiredDescription
versionStringYesThe version of your API.
actionStringYesValue must be ShowBlockPage
userMessageStringYesMessage to display to the user.

End-user experience with a blocking response

Example of a blocking response

Example of a validation-error response

HTTP
HTTP/1.1 400 Bad Request
Content-type: application/json

{
    "version": "1.0.0",
    "status": 400,
    "action": "ValidationError",
    "userMessage": "Please enter a valid Postal Code."
}
ParameterTypeRequiredDescription
versionStringYesThe version of your API.
actionStringYesValue must be ValidationError.
statusInteger / StringYesMust be value 400, or "400" for a ValidationError response.
userMessageStringYesMessage to display to the user.

 Note

HTTP status code has to be "400" in addition to the "status" value in the body of the response.

End-user experience with a validation-error response

Example of a validation-error response

Best practices and how to troubleshoot

Using serverless cloud functions

Serverless functions, like HTTP triggers in Azure Functions, provide a way create API endpoints to use with the API connector. You can use the serverless cloud function to, for example, perform validation logic and limit sign-ups to specific email domains. The serverless cloud function can also call and invoke other web APIs, data stores, and other cloud services for complex scenarios.

Best practices

Ensure that:

  • Your API is following the API request and response contracts as outlined above.
  • The Endpoint URL of the API connector points to the correct API endpoint.
  • Your API explicitly checks for null values of received claims that it depends on.
  • Your API implements an authentication method outlined in secure your API Connector.
  • Your API responds as quickly as possible to ensure a fluid user experience.
    • Azure AD B2C will wait for a maximum of 20 seconds to receive a response. If none is received, it will make one more attempt (retry) at calling your API.
    • If using a serverless function or scalable web service, use a hosting plan that keeps the API "awake" or "warm" in production. For Azure Functions, it's recommended to use at minimum the Premium plan in production.
  • Ensure high availability of your API.
  • Monitor and optimize performance of downstream APIs, databases, or other dependencies of your API.

 Important

Your endpoints must comply with the Azure AD B2C security requirements. Older TLS versions and ciphers are deprecated. For more information, see Azure AD B2C TLS and cipher suite requirements.

Use logging

In general, it's helpful to use the logging tools enabled by your web API service, like Application insights, to monitor your API for unexpected error codes, exceptions, and poor performance.

  • Monitor for HTTP status codes that aren't HTTP 200 or 400.
  • A 401 or 403 HTTP status code typically indicates there's an issue with your authentication. Double-check your API's authentication layer and the corresponding configuration in the API connector.
  • Use more aggressive levels of logging (for example "trace" or "debug") in development if needed.
  • Monitor your API for long response times.

Additionally, Azure AD B2C logs metadata about the API transactions that happen during user authentications via a user flow. To find these:

  1. Go to Azure AD B2C.
  2. Under Activities, select Audit logs.
  3. Filter the list view: For Date, select the time interval you want, and for Activity, select An API was called as part of a user flow.
  4. Inspect individual logs. Each row represents an API connector attempting to be called during a user flow. If an API call fails and a retry occurs, it's still represented as a single row. The numberOfAttempts indicates the number of times your API was called. This value can be 1or 2. Other information about the API call is detailed in the logs.

Example of an API connector transaction during user authentication

How to create API connection using ARM REST API

 How to create API connection (Logic App consumption) using ARM REST API


thumbnail image 1 of blog post titled 
	
	
	 
	
	
	
				
		
			
				
						
							How to create API connection (Logic App consumption) using ARM REST API

4. Select Register to complete the initial app registration.

5. Once the registration finishes, the Azure portal displays the app registration's Overview pane. The Application (client) ID uniquely identifies your application in the Microsoft identity platform. Please note down the Application (client) ID and Directory (tenant) ID for later use:

thumbnail image 2 of blog post titled 
	
	
	 
	
	
	
				
		
			
				
						
							How to create API connection (Logic App consumption) using ARM REST API

6. In the left panel, select Certificates & secrets > Client secrets > New client secret:

7. Add a description for your client secret and select an expiration for the secret or specify a custom lifetime.

8. Select Add

    Note: Please make sure to record the secret's value for use later. This secret value is never displayed again after you leave this page.     

thumbnail image 3 of blog post titled 
	
	
	 
	
	
	
				
		
			
				
						
							How to create API connection (Logic App consumption) using ARM REST API

9. In the left panel, select API permissions > Add a permission > Microsoft APIs, select Azure Service ManagementSelect Delegated permissions and select the permissions the client app should have on behalf of the signed-in user. Currently, Azure Service Management API has only one permission listed - user_impersonation.

thumbnail image 4 of blog post titled 
	
	
	 
	
	
	
				
		
			
				
						
							How to create API connection (Logic App consumption) using ARM REST API

10. Select Add permissions;

11. Back to the API permissions page, click Grant admin consent:

thumbnail image 5 of blog post titled 
	
	
	 
	
	
	
				
		
			
				
						
							How to create API connection (Logic App consumption) using ARM REST API

12. Please grant the registered application the Logic App Contributor role of the target resource group. Go to the resource group, in the left panel, select Access control (IAM)-> Add role assignment:

thumbnail image 6 of blog post titled 
	
	
	 
	
	
	
				
		
			
				
						
							How to create API connection (Logic App consumption) using ARM REST API

13. Search for Logic App Contributor

thumbnail image 7 of blog post titled 
	
	
	 
	
	
	
				
		
			
				
						
							How to create API connection (Logic App consumption) using ARM REST API

14. Select the registered application to be assigned the role -> Review + assign:thumbnail image 8 of blog post titled 
	
	
	 
	
	
	
				
		
			
				
						
							How to create API connection (Logic App consumption) using ARM REST API
							
						
					
			
		
	
			
	
	
	
	
	
thumbnail image 9 of blog post titled 
	
	
	 
	
	
	
				
		
			
				
						
							How to create API connection (Logic App consumption) using ARM REST API

Note: If the Logic App Contributor role is not assigned, when trying to create the API connection using ARM API, you may encounter the following error:

 

	{
	    "error": {
	        "code": "AuthorizationFailed",
	        "message": "The client 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx' with object id 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx' does not have authorization to perform action 'Microsoft.Web/connections/write' over scope '/subscriptions/<subscriptionid>/resourceGroups/LAtestRG/providers/Microsoft.Web/connections/testconn58' or the scope is invalid. If access was recently granted, please refresh your credentials."
	    }
}

 

 

Acquire an access token

After we have a valid client registration, we can use the OAuth 2.0 client credentials grant (non-interactive clients) to acquire an access token:

 

In the Postman, create a request like below:

1. From Method dropdown list, select POST method;

2. For URI, enter "https://login.microsoftonline.com/<Your tenant id>/oauth2/v2.0/token", please check step 5 above for your tenant id;

3. Add header with key: Content-Type, value: application/x-www-form-urlencoded:

thumbnail image 10 of blog post titled 
	
	
	 
	
	
	
				
		
			
				
						
							How to create API connection (Logic App consumption) using ARM REST API

4. In Body, select x-www-form-urlencoded and enter keys:

client_id= <your Application ID> (refer step 5 above)

scope=https://management.azure.com/.default

client_secret=<your secret value> (refer step 8 above)

grant_type=client_credentials

 

After sending the request, you should get the response like below and the access_token will be Bearer token used for the next call to create the API connection.

 

	{
	    "token_type": "Bearer",
	    "expires_in": 3599,
	    "ext_expires_in": 3599,
	    "access_token": "<encoded bearer-token>"
}

 

 

Call the ARM REST API to create the API connection

After we have a valid bearer token, we can send an HTTPS PUT request method for an Azure Resource Manager provider to create the API connection:

 

In the Postman, create a request like below:

1. From Method dropdown list, select PUT method;

2. For URI, enter "https://management.azure.com/subscriptions/<Your subscription id>/resourceGroups/<Your Resource Group Name>/providers/Microsoft.Web/connections/<API connection name>?api-version=2018-07-01-preview", for example: https://management.azure.com/subscriptions/11111111-1111-1111-1111-111111111111/resourceGroups/LAtes...

3. Add header with keys: 

Content-Type: application/json

Authorization: Bearer <bearer-token> (it's the access_token in the above step)

4. In Body, select raw and enter ARM template body of the API connection resource, for example:

 

{
        "properties": {
            "api": {
               "id": "/subscriptions/11111111-1111-1111-1111-111111111111/providers/Microsoft.Web/locations/australiaeast/managedApis/servicebus"
            },
            "parameterValueSet": {
            "name":"connectionstringauth",
            "values":{
               "connectionString":{
                    "value":"Endpoint=sb://<sbnamespace>.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=<Access key>"
                    }
                }
            },
            "displayName":"sbtest03"
        },
        "kind": "V1",
        "location": "australiaeast"
}

 

 

5. Then the successful response should be like below:

 

{
	    "kind": "V1",
	    "properties": {
	        "displayName": "sbtest03",
	        "authenticatedUser": {},
	        "overallStatus": "Connected",
	        "statuses": [
	            {
	                "status": "Connected"
	            }
	        ],
	        "parameterValueSet": {
	            "name": "connectionstringauth",
	            "values": {}
	        },
	        "customParameterValues": {},
	        "createdTime": "2022-07-06T03:39:23.9337935Z",
	        "changedTime": "2022-07-06T03:39:24.340078Z",
	        "api": {
	            "name": "servicebus",
	            "displayName": "Service Bus",
	            "description": "Connect to Azure Service Bus to send and receive messages. You can perform actions such as send to queue, send to topic, receive from queue, receive from subscription, etc.",
	            "iconUri": "https://connectoricons-prod.azureedge.net/releases/v1.0.1568/1.0.1568.2757/servicebus/icon.png",
	            "brandColor": "#c4d5ff",
	            "category": "Standard",
	            "id": "/subscriptions/711111111-1111-1111-1111-111111111111/providers/Microsoft.Web/locations/australiaeast/managedApis/servicebus",
	            "type": "Microsoft.Web/locations/managedApis"
	        },
	        "testLinks": [],
	        "testRequests": []
	    },
	    "id": "/subscriptions/11111111-1111-1111-1111-111111111111/resourceGroups/LAtestRG/providers/Microsoft.Web/connections/testconn61",
	    "name": "testconn61",
	    "type": "Microsoft.Web/connections",
	    "location": "australiaeast"
}

 

 

6. And in the target resource group, the API connection should be created:

thumbnail image 11 of blog post titled 
	
	
	 
	
	
	
				
		
			
				
						
							How to create API connection (Logic App consumption) using ARM REST API