How does one use an alternative hashing algorithm to `bcrypt`, such as `Argon2id`, for hashing credentials?

I am developing a system which requires three pieces of data for creation of an account; a username; an email address; and a password.

Instead of bcrypt, I am planning to use Argon2 for hashing both user passwords and email addresses. This poses a problem, because – if I am thinking correctly – integrating Argon2 hashing and verification would potentially require me to make two queries instead of one; the first one to fetch the hashed email address or password; and the second one to update the document with the updated piece of data.

Furthermore, a credentials document does not allow me to store data other than metadata and a password, which is not ideal for my use case. I am aware that I could solve this by creating two credentials documents and saving references to them in the user document, but this would force me to use bcrypt as well as prevent me from using the built-in Login() function for verifying hashes.

Why would you need to make two queries if you use Argon2? Since Argon2 isn’t built into Fauna, all hashing would happen in your client. So, you could:

client.query(
  q.Create(
    q.Collection("Users"),
    {
      data: {
        username: "some_user",
        password: await argon2.hash("the user password"),
        // ...
      }
    }
  )
)

Argon2 hashes are not reversible, so if you plan to send emails to the collected email addresses, you’ll need to use some other encryption/obfuscation technique, or store the email addresses in the clear.

A Credentials document is created when a document is created or updated with a credentials field. It is automatically connected to the original document via the instance field.

You are correct: if you use Argon2 hashing for passwords, you cannot use the Login function. However, if you hash a password and then lookup a document that contains that hash (using an appropriate index), you’ll have a comparable workflow. Once your “login” flow is complete, you can directly create a key or token to pass back to the user for direct querying.