Migrate users with passwords hashed using Microsoft.AspNet.Identity.Core, Version=

Ready to post? :mag: 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=
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)
         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"

     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;