Azure AD B2C自定义用户属性

时间:2018-08-02 15:43:56

标签: azure azure-ad-b2c azure-ad-graph-api

我是Azure B2C世界的新手。我试图创建一个“自定义用户”属性来存储我们应用程序的数据。我已经在Azure门户中创建了它,并将其分配给我的“注册/登录”策略。但是,我希望能够以编程方式更新/读取此值。我一直在使用Graph API和注册Extensions。有两个问题:

1)扩展名/自定义属性是否相同? 2)我尝试过此代码,返回的扩展名始终为空:

 public void RegisterExtension()
    {
        string myRegisteredAppObjectId = "<>";
        string json = @"{
                        ""name"": ""My Custom Attribute"",
                        ""dataType"": ""String"",
                        ""targetObjects"": [
                            ""User""
                        ]
                        }";

        B2CGraphClient b2CGraphClient = new B2CGraphClient();
        b2CGraphClient.RegisterExtension(myRegisteredAppObjectId, json);
        var extensions = JsonConvert.DeserializeObject(b2CGraphClient.GetExtensions(myRegisteredAppObjectId).Result);

    }

B2CGraphClient.cs

 public class B2CGraphClient
{
    private string clientId { get; set; }
    private string clientSecret { get; set; }
    private string tenant { get; set; }

    private AuthenticationContext authContext;
    private ClientCredential credential;

    public B2CGraphClient(string clientId, string clientSecret, string tenant)
    {
        // The client_id, client_secret, and tenant are pulled in from the App.config file
        this.clientId = clientId;
        this.clientSecret = clientSecret;
        this.tenant = tenant;

        // The AuthenticationContext is ADAL's primary class, in which you indicate the direcotry to use.
        this.authContext = new AuthenticationContext("https://login.microsoftonline.com/" + tenant);

        // The ClientCredential is where you pass in your client_id and client_secret, which are 
        // provided to Azure AD in order to receive an access_token using the app's identity.
        this.credential = new ClientCredential(clientId, clientSecret);
    }


    public async Task<string> DeleteUser(string objectId)
    {
        return await SendGraphDeleteRequest("/users/" + objectId);
    }

    public async Task<string> RegisterExtension(string objectId, string body)
    {
        return await SendGraphPostRequest("/applications/" + objectId + "/extensionProperties", body);
    }


    public async Task<string> GetExtensions(string appObjectId)
    {
        return await SendGraphGetRequest("/applications/" + appObjectId + "/extensionProperties", null);
    }


    private async Task<string> SendGraphPostRequest(string api, string json)
    {
        // NOTE: This client uses ADAL v2, not ADAL v4
        AuthenticationResult result = authContext.AcquireToken(Globals.aadGraphResourceId, credential);
        HttpClient http = new HttpClient();
        string url = Globals.aadGraphEndpoint + tenant + api + "?" + Globals.aadGraphVersion;

        Console.ForegroundColor = ConsoleColor.Cyan;
        Console.WriteLine("POST " + url);
        Console.WriteLine("Authorization: Bearer " + result.AccessToken.Substring(0, 80) + "...");
        Console.WriteLine("Content-Type: application/json");
        Console.WriteLine("");
        Console.WriteLine(json);
        Console.WriteLine("");

        HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, url);
        request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
        request.Content = new StringContent(json, Encoding.UTF8, "application/json");
        HttpResponseMessage response = await http.SendAsync(request);

        if (!response.IsSuccessStatusCode)
        {
            string error = await response.Content.ReadAsStringAsync();
            object formatted = JsonConvert.DeserializeObject(error);
            throw new WebException("Error Calling the Graph API: \n" + JsonConvert.SerializeObject(formatted, Formatting.Indented));
        }

        Console.ForegroundColor = ConsoleColor.Green;
        Console.WriteLine((int)response.StatusCode + ": " + response.ReasonPhrase);
        Console.WriteLine("");

        return await response.Content.ReadAsStringAsync();
    }

    public async Task<string> SendGraphGetRequest(string api, string query)
    {
        // First, use ADAL to acquire a token using the app's identity (the credential)
        // The first parameter is the resource we want an access_token for; in this case, the Graph API.
        AuthenticationResult result = authContext.AcquireToken("https://graph.windows.net", credential);

        // For B2C user managment, be sure to use the 1.6 Graph API version.
        HttpClient http = new HttpClient();
        string url = "https://graph.windows.net/" + tenant + api + "?" + Globals.aadGraphVersion;
        if (!string.IsNullOrEmpty(query))
        {
            url += "&" + query;
        } 

        Console.ForegroundColor = ConsoleColor.Cyan;
        Console.WriteLine("GET " + url);
        Console.WriteLine("Authorization: Bearer " + result.AccessToken.Substring(0, 80) + "...");
        Console.WriteLine("");

        // Append the access token for the Graph API to the Authorization header of the request, using the Bearer scheme.
        HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, url);
        request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
        HttpResponseMessage response = await http.SendAsync(request);

        if (!response.IsSuccessStatusCode)
        {
            string error = await response.Content.ReadAsStringAsync();
            object formatted = JsonConvert.DeserializeObject(error);
            throw new WebException("Error Calling the Graph API: \n" + JsonConvert.SerializeObject(formatted, Formatting.Indented));
        }

        Console.ForegroundColor = ConsoleColor.Green;
        Console.WriteLine((int)response.StatusCode + ": " + response.ReasonPhrase);
        Console.WriteLine("");

        return await response.Content.ReadAsStringAsync();
    } 
}

当然,myRegisteredAppObjectId中有一个有效的GUID。

谢谢

1 个答案:

答案 0 :(得分:2)

  

扩展程序/自定义属性是否相同?

根据我的测试,扩展名与自定义属性相同。

  

我已经尝试过此代码,并且返回的扩展名始终为空:

我在此tutorialuse a custom attribute in my policy之后添加自定义属性MyCustomAttribute。您可以参考我的测试步骤。

我从Github下载B2C-GraphAPI-DotNet项目。将以下代码用于自定义属性

var applications = client.GetApplications("$filter=startswith(displayName, 'b2c-extensions-app')").Result

var extension = client.GetExtensions(objectId).Result //objectId from the applications result.

然后,我们可以从扩展名中获取自定义属性。

enter image description here

然后,您可以像对待用户对象上的其他任何属性一样对待该属性

例如创建用户:

var jsonObject = new JObject
            {
                {"accountEnabled", true},
                {"country", "US"},
                {"creationType", "LocalAccount"},
                {"displayName", "Tomsun"},
                {"passwordPolicies", "DisablePasswordExpiration,DisableStrongPassword"},
                { "extension_42ba0de8530a4b5bbe6dad21fe6ef092_MyCustomAttribute","test2"},  //custom propery
                {"passwordProfile", new JObject
                {
                    {"password", "!QAZ1234wer"},
                    {"forceChangePasswordNextLogin", true}
                } },
                {"signInNames", new JArray
                    {
                        new JObject
                        {
                            {"value","tom1@example.com"},
                            {"type", "emailAddress"}
                        }
                    }
                }
            };

string user = client.CreateUser(jsonObject.ToString()).Result;

查询用户

var user = client.GetUserByObjectId(objectId).Result; //user objectId

enter image description here

更新用户

var jsonUpdate = new JObject
            {  
                { "extension_42ba0de8530a4b5bbe6dad21fe6ef092_MyCustomAttribute","testx"}

            };
var updateuser = client.UpdateUser("objectId", jsonObject2.ToString()).Result; //UserObject Id