【问题标题】:Create a new user in Azure Active Directory (B2C) with Graph API, using http post request使用 Graph API 在 Azure Active Directory (B2C) 中创建一个新用户,使用 http post 请求
【发布时间】:2016-09-11 19:24:54
【问题描述】:

我之前一直使用 Active Directory 身份验证库 (ADAL) 以编程方式添加用户,但现在我需要定义“signInNames”(= 用户电子邮件),而这似乎不适用于 ADAL(请告诉我是否我错了)。

现在我正在尝试使用 HTTP POST 以编程方式添加一个新用户(本地帐户),遵循the documentation on MSDN

//Get access token (using ADAL)
var authenticationContext = new AuthenticationContext(AuthString, false);
var clientCred = new ClientCredential(ClientId, ClientSecret);
var authenticationResult = authenticationContext.AcquireTokenAsync(ResourceUrl, clientCred);
var token = authenticationResult.Result.AccessToken;


//HTTP POST CODE
const string mail = "new@email.com";
// Create a new user object.
var user = new CustomUser
{
    accountEnabled = true,
    country = "MS",
    creationType = "LocalAccount",
    displayName = mail,
    passwordPolicies = "DisablePasswordExpiration,DisableStrongPassword",
    passwordProfile = new passwordProfile { password = "jVPmEm)6Bh", forceChangePasswordNextLogin = true },
    signInNames = new signInNames { type = "emailAddress", value = mail }
};

var url = "https://graph.windows.net/" + TenantId + "/users?api-version=1.6";

var jsonObject = JsonConvert.SerializeObject(user);

using (var client = new HttpClient())
{
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

    var response = client.PostAsync(url,
        new StringContent(JsonConvert.SerializeObject(user).ToString(),
            Encoding.UTF8, "application/json"))
            .Result;

    if (response.IsSuccessStatusCode)
    {
        dynamic content = JsonConvert.DeserializeObject(
            response.Content.ReadAsStringAsync()
            .Result);

        // Access variables from the returned JSON object
        var appHref = content.links.applications.href;
    }
}

但我没有成功,得到这个回复:

{StatusCode: 400, ReasonPhrase: 'Bad Request', Version: 1.1, Content:....}

任何想法我应该做什么?我成功使用了 Powershell 脚本,但我需要在我的 C# 应用程序中执行此操作。

【问题讨论】:

    标签: c# adal azure-ad-graph-api


    【解决方案1】:

    您是否授予应用足够的权限来操作用户?对于 B2C 租户,创建用户 REST API 非常适合我。

    以下是我测试的步骤:

    1.通过下面的PowerShell创建应用

    PowerShell:
    
    $bytes = New-Object Byte[] 32
    $rand = [System.Security.Cryptography.RandomNumberGenerator]::Create()
    $rand.GetBytes($bytes)
    $rand.Dispose()
    $newClientSecret = [System.Convert]::ToBase64String($bytes)
    
    New-MsolServicePrincipal -DisplayName "My New B2C Graph API App" -Type password -Value 
    

    2.将应用授予用户帐户管理员角色。

    Add-MsolRoleMember -RoleObjectId fe930be7-5e62-47db-91af-98c3a49a38b1 -RoleMemberObjectId 7311370c-dac3-4f34-b2ce-b22c2a5a811e -RoleMemberType servicePrincipal
    

    3.通过客户端凭证流获取应用的令牌

    POST: https://login.microsoftonline.com/adb2cfei.onmicrosoft.com/oauth2/token
    grant_type=client_credentials&client_id={AppPrincipalId return by PowerShell}&client_secret={client_secret}&resource=https%3A%2F%2Fgraph.windows.net
    

    4.使用下面的REST创建用户:

    POST: https://graph.windows.net/adb2cfei.onmicrosoft.com/users?api-version=1.6
    authorization: bearer {token}
    content-type: application/json
    
    {
      "accountEnabled": true,
      "creationType": "LocalAccount",
      "displayName": "Alex Wu",
      "passwordProfile": {
        "password": "Test1234",
        "forceChangePasswordNextLogin": false
      },
      "signInNames": [
        {
          "type": "userName",
          "value": "AlexW"
        },
        {
          "type": "emailAddress",
          "value": "AlexW@example.com"
        }
      ]
    }
    

    【讨论】:

      【解决方案2】:

      感谢飞雪的回复,我相信我有正确的权限。我做了什么来解决我的问题。

      首先我删除了我自己的自定义类“NewUser”,然后我下载了这个示例项目:https://github.com/AzureADQuickStarts/B2C-GraphAPI-DotNet/blob/master/B2CGraphClient/B2CGraphClient.cs 以消除我的代码错误的风险。我对其进行了修改以满足我的需要,然后我创建了一个简单的 JObject:

      var jsonObject = new JObject
                              {
                                  {"accountEnabled", true},
                                  {"country", customer.CustomerBase.Company},
                                  {"creationType", "LocalAccount"},
                                  {"displayName", pendingCustomer.Email.Trim()},
                                  {"passwordPolicies", "DisablePasswordExpiration,DisableStrongPassword"},
                                  {"passwordProfile", new JObject
                                  {
                                      {"password", pwd},
                                      {"forceChangePasswordNextLogin", true}
                                  } },
                                  {"signInNames", new JArray
                                      {
                                          new JObject
                                          {
                                              {"value", pendingCustomer.Email.Trim()},
                                              {"type", "emailAddress"}
                                          }
                                      }
                                  }
                              };
      
      client = new B2CGraphClient(ClientId, ClientSecret, TenantId);
      var response = await client.CreateUser(jsonObject.ToString());
      var newUser = JsonConvert.DeserializeObject<User>(response);
      

      来自 B2CGraphClient.cs

              private async Task<string> SendGraphPostRequest(string api, string json)
          {
              // NOTE: This client uses ADAL v2, not ADAL v4
              var result = authContext.AcquireToken(Globals.aadGraphResourceId, credential);
              var http = new HttpClient();
              var url = Globals.aadGraphEndpoint + tenant + api + "?" + Globals.aadGraphVersion;
      
              var request = new HttpRequestMessage(HttpMethod.Post, url);
              request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
              request.Content = new StringContent(json, Encoding.UTF8, "application/json");
              var response = await http.SendAsync(request);
      
              if (!response.IsSuccessStatusCode)
              {
                  var error = await response.Content.ReadAsStringAsync();
                  var formatted = JsonConvert.DeserializeObject(error);
                  //Console.WriteLine("Error Calling the Graph API: \n" + JsonConvert.SerializeObject(formatted, Formatting.Indented));
                  Logger.Error("Error Calling the Graph API: \n" + JsonConvert.SerializeObject(formatted, Formatting.Indented));
              }
              Logger.Info((int)response.StatusCode + ": " + response.ReasonPhrase);
      
              return await response.Content.ReadAsStringAsync();
          }
      

      这终于解决了我所有的问题,可能是我的 NewCustomer 类的序列化中的格式错误,然后被 API 拒绝了。

      【讨论】:

      • @melberg 您是如何在通过和失败的情况下将响应返回给 C# 对象的?您提到的成功案例是“var newUser = JsonConvert.DeserializeObject(response);”。那么User对象的定义是什么,以及如何在C#对象中获取错误响应结果。
      猜你喜欢
      • 2019-08-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-17
      • 2016-04-17
      • 1970-01-01
      • 1970-01-01
      • 2017-12-09
      相关资源
      最近更新 更多