Reputation: 41
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
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
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
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