Ready to post? First, try searching for your answer.
I want to share some code i created to create the json needed to do a bulk import for users with a password hash created with Microsoft.AspNet.Identity.Core, Version=2.0.0.0
It was quite a challange to get it right but at the end by adding ToUrlSafeBase64 i got i to work:
public ActionResult Export()
{
var users = _userManager.GetUsers();
List userDataList = new List();
foreach (var user in users.Items)
{
try
{
var passwordComponents = ExtractSaltAndSubkey(user.Password);
var userData = new
{
email = user.WorkEmail,
username = user.LoginName,
given_name = user.FirstName,
family_name = user.LastName,
email_verified = false,
custom_password_hash = new
{
algorithm = "pbkdf2",
hash = new
{
value = $"$pbkdf2-sha1$i={PBKDF2IterCount},l={PBKDF2SubkeyLength}${passwordComponents.Salt}${passwordComponents.Subkey}",
encoding = "utf8"
}
}
};
userDataList.Add(userData);
}
catch (Exception ex)
{
// Log the error or handle it appropriately
Console.WriteLine($"Error processing user {user.LoginName}: {ex.Message}");
}
}
string json = JsonConvert.SerializeObject(userDataList, Formatting.Indented);
return View("Export", (object)json);
}
private const int PBKDF2IterCount = 1000; // Ensure this matches the iterations used when hashing originally
private const int PBKDF2SubkeyLength = 32; // Ensure this matches the byte length of the derived key
private const int SaltSize = 16; // Ensure this matches the byte size of the salt used when hashing
public static (string Salt, string Subkey) ExtractSaltAndSubkey(string hashedPassword)
{
byte hashBytes = Convert.FromBase64String(hashedPassword);
byte salt = new byte[SaltSize];
byte subkey = new byte[PBKDF2SubkeyLength];
Array.Copy(hashBytes, 1, salt, 0, SaltSize);
Array.Copy(hashBytes, 1 + SaltSize, subkey, 0, PBKDF2SubkeyLength);
return (ToUrlSafeBase64(Convert.ToBase64String(salt)), ToUrlSafeBase64(Convert.ToBase64String(subkey)));
}
public static string ToUrlSafeBase64(string base64String)
{
return base64String.Replace(โ+โ, โ-โ).Replace(โ/โ, โ_โ).TrimEnd(โ=โ); // Convert standard base64 to URL-safe base64 and remove padding
}
View content for Export.cshtml:
@model string
@{
Layout = null;
}
@Html.Raw(Model)