Arnav Garg
Arnav Garg

Reputation: 41

Is there any way possible to create or delete Users in bulk using GRAPH API in Azure AD B2C

I am trying to make a console app in C# through which I want to migrate more than 100000 users to Azure AD B2C.

We are using Graph API for this purpose.

My current approach creates a single user account per API call and it takes more than 12 hours to migrate around 50000 users.

To reduce the overall time I want to send data in bulk instead of one by one using the API. But, I am unable to find any solution for it.

Is there an API endpoint available for creating users in batch. Please help.

Also, If I want to delete these users in batch. Is it possible to do that?

Here are some Microsoft docs references which I have used for implementing my solution.

https://learn.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-user-migration?tabs=applications https://learn.microsoft.com/en-us/previous-versions/azure/ad/graph/api/users-operations#CreateLocalAccountUser

Upvotes: 2

Views: 3865

Answers (3)

zetawars
zetawars

Reputation: 1081

Just to add onto the Allen Wu Answer. This is how you would use it in c# for example.

string json = @"
{
    ""requests"": [{
            ""id"": ""1"",
            ""method"": ""POST"",
            ""url"": ""/users"",
            ""body"": {
                ""accountEnabled"": true,
                ""displayName"": ""zetawarsTest01"",
                ""mailNickname"": ""zetawarstest01"",
                ""userPrincipalName"": ""[email protected]"",
                ""passwordProfile"": {
                    ""forceChangePasswordNextSignIn"": false,
                    ""password"": ""zetawars123!@#""
                }
            },
            ""headers"": {
                ""Content-Type"": ""application/json""
            }
        }, {
            ""id"": ""2"",
            ""method"": ""POST"",
            ""url"": ""/users"",
            ""body"": {
                ""accountEnabled"": true,
                ""displayName"": ""zetawarsTest02"",
                ""mailNickname"": ""zetawarsTest02"",
                ""userPrincipalName"": ""[email protected]"",
                ""passwordProfile"": {
                    ""forceChangePasswordNextSignIn"": false,
                    ""password"": ""zetawars123!@#""
                }
            },
            ""headers"": {
                ""Content-Type"": ""application/json""
            }
        }
        ]
    }
";
            //Credentials
            var tenantId = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
            var clientId = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
            var clientSecret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";

            var scopes = new string[] { "https://graph.microsoft.com/.default" };

            //This to get the Access Token
            var confidentialClient = ConfidentialClientApplicationBuilder
                .Create(clientId)
                .WithAuthority($"https://login.microsoftonline.com/{tenantId}/v2.0")
                .WithClientSecret(clientSecret)
                .Build();

            IConfidentialClientApplication confidentialClientApplication = ConfidentialClientApplicationBuilder
                .Create(clientId)
                .WithTenantId(tenantId)
                .WithClientSecret(clientSecret)
                .Build();

            var result = await confidentialClientApplication
                .AcquireTokenForClient(new string[] { "https://graph.microsoft.com/.default" })
                .ExecuteAsync(); ;

             // This is to send Json Request using Client
            using (HttpClient http = new HttpClient())
            using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "https://graph.microsoft.com/v1.0/$batch"))
            {

                request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);


                if (!string.IsNullOrEmpty(json))
                {
                    request.Content = new StringContent(json, Encoding.UTF8, "application/json");
                }


                using (HttpResponseMessage response = await http.SendAsync(request))
                {
                    string error = await response.Content.ReadAsStringAsync();

                    if (!response.IsSuccessStatusCode)
                    {
                        if (response.StatusCode == (HttpStatusCode)429)
                        {
                            // TBD: Add you error handling here
                        }

                        throw new Exception(error);
                    }
                    await response.Content.ReadAsStringAsync();
                }
            }

I have read that there is limit of 20 users/request in batch. But i haven't tested that out yet.

Upvotes: 2

AdeelNasir
AdeelNasir

Reputation: 33

The approach of using JSON batching seems more reasonable but last time we had imported 160,000 users to Azure AD B2C via Graph API using Parallel.ForEach loop with MaxDegreeOfParallelism to 10. We were providing a batch of 40,000 users per run. It took 30 minutes to migrate 40,000 users batch.

Upvotes: 0

Allen Wu
Allen Wu

Reputation: 16458

You can use JSON batching to combine multiple requests in one HTTP call.

Here is an example:

POST https://graph.microsoft.com/v1.0/$batch

{
    "requests": [{
            "id": "1",
            "method": "POST",
            "url": "/users",
            "body": {
                "accountEnabled": true,
                "displayName": "allentest01",
                "mailNickname": "allentest01",
                "userPrincipalName": "allentest01@{tenant}.onmicrosoft.com",
                "passwordProfile": {
                    "forceChangePasswordNextSignIn": true,
                    "password": "{password-value}"
                }
            },
            "headers": {
                "Content-Type": "application/json"
            }
        }, {
            "id": "2",
            "method": "POST",
            "url": "/users",
            "body": {
                "accountEnabled": true,
                "displayName": "allentest02",
                "mailNickname": "allentest02",
                "userPrincipalName": "allentest02@{tenant}.onmicrosoft.com",
                "passwordProfile": {
                    "forceChangePasswordNextSignIn": true,
                    "password": "{password-value}"
                }
            },
            "headers": {
                "Content-Type": "application/json"
            }
        }
    ]
}

You can also delete user with it. (use DELETE method)

Upvotes: 5

Related Questions