This repository has been archived by the owner on May 17, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 68
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #4 from LockTar/f/manage-custom-attributes
F/manage custom attributes
- Loading branch information
Showing
8 changed files
with
208 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
namespace b2c_ms_graph.Helpers | ||
{ | ||
internal class B2cCustomAttributeHelper | ||
{ | ||
internal readonly string _b2cExtensionAppClientId; | ||
|
||
internal B2cCustomAttributeHelper(string b2cExtensionAppClientId) | ||
{ | ||
_b2cExtensionAppClientId = b2cExtensionAppClientId.Replace("-", ""); | ||
} | ||
|
||
internal string GetCompleteAttributeName(string attributeName) | ||
{ | ||
if (string.IsNullOrWhiteSpace(attributeName)) | ||
{ | ||
throw new System.ArgumentException("Parameter cannot be null", nameof(attributeName)); | ||
} | ||
|
||
return $"extension_{_b2cExtensionAppClientId}_{attributeName}"; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
using System; | ||
|
||
namespace b2c_ms_graph.Helpers | ||
{ | ||
public static class PasswordHelper | ||
{ | ||
public static string GenerateNewPassword(int lowercase, int uppercase, int numerics) | ||
{ | ||
string lowers = "abcdefghijklmnopqrstuvwxyz"; | ||
string uppers = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; | ||
string number = "0123456789"; | ||
|
||
Random random = new Random(); | ||
|
||
string generated = "!"; | ||
for (int i = 1; i <= lowercase; i++) | ||
generated = generated.Insert( | ||
random.Next(generated.Length), | ||
lowers[random.Next(lowers.Length - 1)].ToString() | ||
); | ||
|
||
for (int i = 1; i <= uppercase; i++) | ||
generated = generated.Insert( | ||
random.Next(generated.Length), | ||
uppers[random.Next(uppers.Length - 1)].ToString() | ||
); | ||
|
||
for (int i = 1; i <= numerics; i++) | ||
generated = generated.Insert( | ||
random.Next(generated.Length), | ||
number[random.Next(number.Length - 1)].ToString() | ||
); | ||
|
||
return generated.Replace("!", string.Empty); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ | |
// Licensed under the MIT License. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Threading.Tasks; | ||
using Microsoft.Graph; | ||
|
@@ -32,6 +33,40 @@ public static async Task ListUsers(GraphServiceClient graphClient) | |
} | ||
} | ||
|
||
public static async Task ListUsersWithCustomAttribute(GraphServiceClient graphClient, string b2cExtensionAppClientId) | ||
{ | ||
if (string.IsNullOrWhiteSpace(b2cExtensionAppClientId)) | ||
{ | ||
throw new ArgumentException("B2cExtensionAppClientId (its Application ID) is missing from appsettings.json. Find it in the App registrations pane in the Azure portal. The app registration has the name 'b2c-extensions-app. Do not modify. Used by AADB2C for storing user data.'.", nameof(b2cExtensionAppClientId)); | ||
} | ||
|
||
// Declare the names of the custom attributes | ||
const string customAttributeName1 = "FavouriteSeason"; | ||
const string customAttributeName2 = "LovesPets"; | ||
|
||
// Get the complete name of the custom attribute (Azure AD extension) | ||
Helpers.B2cCustomAttributeHelper helper = new Helpers.B2cCustomAttributeHelper(b2cExtensionAppClientId); | ||
string favouriteSeasonAttributeName = helper.GetCompleteAttributeName(customAttributeName1); | ||
string lovesPetsAttributeName = helper.GetCompleteAttributeName(customAttributeName2); | ||
|
||
Console.WriteLine($"Getting list of users with the custom attributes '{customAttributeName1}' (string) and '{customAttributeName2}' (boolean)"); | ||
Console.WriteLine(); | ||
|
||
// Get all users (one page) | ||
var result = await graphClient.Users | ||
.Request() | ||
.Select($"id,displayName,identities,{favouriteSeasonAttributeName},{lovesPetsAttributeName}") | ||
.GetAsync(); | ||
|
||
foreach (var user in result.CurrentPage) | ||
{ | ||
Console.WriteLine(JsonConvert.SerializeObject(user)); | ||
|
||
// Only output the custom attributes... | ||
//Console.WriteLine(JsonConvert.SerializeObject(user.AdditionalData)); | ||
} | ||
} | ||
|
||
public static async Task GetUserById(GraphServiceClient graphClient) | ||
{ | ||
Console.Write("Enter user object ID: "); | ||
|
@@ -135,7 +170,7 @@ public static async Task SetPasswordByUserId(GraphServiceClient graphClient) | |
|
||
var user = new User | ||
{ | ||
PasswordPolicies = "DisablePasswordExpiration,DisableStrongPassword", | ||
PasswordPolicies = "DisablePasswordExpiration,DisableStrongPassword", | ||
PasswordProfile = new PasswordProfile | ||
{ | ||
ForceChangePasswordNextSignIn = false, | ||
|
@@ -202,5 +237,95 @@ public static async Task BulkCreate(AppSettings config, GraphServiceClient graph | |
} | ||
} | ||
} | ||
|
||
public static async Task CreateUserWithCustomAttribute(GraphServiceClient graphClient, string b2cExtensionAppClientId, string tenantId) | ||
{ | ||
if (string.IsNullOrWhiteSpace(b2cExtensionAppClientId)) | ||
{ | ||
throw new ArgumentException("B2C Extension App ClientId (ApplicationId) is missing in the appsettings.json. Get it from the App Registrations blade in the Azure portal. The app registration has the name 'b2c-extensions-app. Do not modify. Used by AADB2C for storing user data.'.", nameof(b2cExtensionAppClientId)); | ||
} | ||
|
||
// Declare the names of the custom attributes | ||
const string customAttributeName1 = "FavouriteSeason"; | ||
const string customAttributeName2 = "LovesPets"; | ||
|
||
// Get the complete name of the custom attribute (Azure AD extension) | ||
Helpers.B2cCustomAttributeHelper helper = new Helpers.B2cCustomAttributeHelper(b2cExtensionAppClientId); | ||
string favouriteSeasonAttributeName = helper.GetCompleteAttributeName(customAttributeName1); | ||
string lovesPetsAttributeName = helper.GetCompleteAttributeName(customAttributeName2); | ||
|
||
Console.WriteLine($"Create a user with the custom attributes '{customAttributeName1}' (string) and '{customAttributeName2}' (boolean)"); | ||
|
||
// Fill custom attributes | ||
IDictionary<string, object> extensionInstance = new Dictionary<string, object>(); | ||
extensionInstance.Add(favouriteSeasonAttributeName, "summer"); | ||
extensionInstance.Add(lovesPetsAttributeName, true); | ||
|
||
try | ||
{ | ||
// Create user | ||
var result = await graphClient.Users | ||
.Request() | ||
.AddAsync(new User | ||
{ | ||
GivenName = "Casey", | ||
Surname = "Jensen", | ||
DisplayName = "Casey Jensen", | ||
Identities = new List<ObjectIdentity> | ||
{ | ||
new ObjectIdentity() | ||
{ | ||
SignInType = "emailAddress", | ||
Issuer = tenantId, | ||
IssuerAssignedId = "[email protected]" | ||
} | ||
}, | ||
PasswordProfile = new PasswordProfile() | ||
{ | ||
Password = Helpers.PasswordHelper.GenerateNewPassword(4, 8, 4) | ||
}, | ||
PasswordPolicies = "DisablePasswordExpiration", | ||
AdditionalData = extensionInstance | ||
}); | ||
|
||
string userId = result.Id; | ||
|
||
Console.WriteLine($"Created the new user. Now get the created user with object ID '{userId}'..."); | ||
|
||
// Get created user by object ID | ||
result = await graphClient.Users[userId] | ||
.Request() | ||
.Select($"id,givenName,surName,displayName,identities,{favouriteSeasonAttributeName},{lovesPetsAttributeName}") | ||
.GetAsync(); | ||
|
||
if (result != null) | ||
{ | ||
Console.ForegroundColor = ConsoleColor.Blue; | ||
Console.WriteLine($"DisplayName: {result.DisplayName}"); | ||
Console.WriteLine($"{customAttributeName1}: {result.AdditionalData[favouriteSeasonAttributeName].ToString()}"); | ||
Console.WriteLine($"{customAttributeName2}: {result.AdditionalData[lovesPetsAttributeName].ToString()}"); | ||
Console.WriteLine(); | ||
Console.ResetColor(); | ||
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented)); | ||
} | ||
} | ||
catch (ServiceException ex) | ||
{ | ||
if (ex.StatusCode == System.Net.HttpStatusCode.BadRequest) | ||
{ | ||
Console.ForegroundColor = ConsoleColor.Red; | ||
Console.WriteLine($"Have you created the custom attributes '{customAttributeName1}' (string) and '{customAttributeName2}' (boolean) in your tenant?"); | ||
Console.WriteLine(); | ||
Console.WriteLine(ex.Message); | ||
Console.ResetColor(); | ||
} | ||
} | ||
catch (Exception ex) | ||
{ | ||
Console.ForegroundColor = ConsoleColor.Red; | ||
Console.WriteLine(ex.Message); | ||
Console.ResetColor(); | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters