Argon2id password checking

Sometimes I need to ask the user to renter a password just to verify they are the legitimate user before they perform critical actions such as changing passwords.
With SHA encryption this is easy as i simply hash the password and compare the sting to the stored string.
However, due to the nature of Argon, i believe this is not a valid method of confirmation

To date all i have been able to come up with is to perform an additional login step as a way of validating the password but I would prefer not to do this.
Is there a way of checking that a password entered matches an Argon encrypted password without a login step?

Also is there any documentation on Password Verify (is that the solution?) and Password Needs Rehash as i cant find any and I have no idea what they do.

Looks like so. Haven’t used it though.
The inputs seems straightforward - plain text password, and the hash stored in the DB.

Yes, but the argon encryption has many facets, not just a salt?
i.e. $argon2id$v=19$m=4096,t=3,p=1$P8nHqMwe3ymOkPyOo2ub9w$M0uy5aOBDp0Cao0zwKfAwOvKX2zBvbxJNQz5d4c8qDQ

There is no simple salt to select, so string manipulation would be required i guess, a bit messy

Indeed, if:
v = version?
m=memory
t=iterations
p=parallelism
P=password
I am not even sure what the salt is?

Hi Brian,
In order to do this you need to use the password verify indeed. You just need to give the plain password and the hash stored in the database and it will return a boolean true if the password is correct.

So just query the hashed passwords in the database then use the password verify to check if the password is correct.

3 Likes

No… no need to supply any of those values. Just bind the hashed string stored in the DB.

2 Likes

Thanks Teodor BUT

I start with:

It returns (as i would expect)

I then add Password verify

and get

I have also tried hard coding the password like this with same result:

Any ideas what is wrong?

What is the server action code generated for this step, maybe it’s wrong?

{
  "exec": {
    "steps": [
      {
        "name": "PWD",
        "module": "core",
        "action": "setvalue",
        "options": {
          "value": 11111111
        },
        "meta": [],
        "output": true,
        "outputType": "text"
      },
      {
        "name": "query",
        "module": "dbconnector",
        "action": "single",
        "options": {
          "connection": "db",
          "sql": {
            "type": "SELECT",
            "columns": [
              {
                "table": "user",
                "column": "*"
              }
            ],
            "table": {
              "name": "user"
            },
            "primary": "user_id",
            "joins": [],
            "wheres": {
              "condition": "AND",
              "rules": [
                {
                  "id": "user.user_id",
                  "field": "user.user_id",
                  "type": "double",
                  "operator": "equal",
                  "value": 14,
                  "data": {
                    "table": "user",
                    "column": "user_id",
                    "type": "number",
                    "columnObj": {
                      "type": "increments",
                      "primary": true,
                      "unique": false,
                      "nullable": false,
                      "name": "user_id"
                    }
                  },
                  "operation": "="
                }
              ],
              "conditional": null,
              "valid": true
            },
            "query": "SELECT *\nFROM user\nWHERE user_id = 14",
            "params": []
          }
        },
        "output": true,
        "meta": [
          {
            "type": "number",
            "name": "user_id"
          },
          {
            "type": "text",
            "name": "first_name"
          },
          {
            "type": "text",
            "name": "last_name"
          },
          {
            "type": "text",
            "name": "email"
          },
          {
            "type": "text",
            "name": "password"
          },
          {
            "type": "datetime",
            "name": "date_signup"
          },
          {
            "type": "text",
            "name": "authcode"
          },
          {
            "type": "datetime",
            "name": "validated"
          }
        ],
        "outputType": "object"
      },
      {
        "name": "verify",
        "module": "crypto",
        "action": "passwordVerify",
        "options": {
          "password": "{{PWD}}",
          "hash": "{{query.password}}"
        },
        "outputType": "boolean",
        "output": true
      }
    ]
  },
  "usedModules": {
    "argon2": "^0.28.3"
  }
}

Can i assume from the code

exports.passwordVerify = async function(options) {
  const password = this.parseRequired(options.password, 'string', 'crypto.passwordVerify: password is required.')
  const hash = this.parseRequired(options.hash, 'string', 'crypto.passwordVerify: hash is required.')
  const argon2 = require('argon2')
  return argon2.verify(hash, password)

That the password option is not being sent to the module correctly?

The password must be of the type string, you are using a number.

So obvious when you point it out. This is some demo data and I used the passord “11111111” for demo purposed but of course you are correct, in this context it will be evaluated as a number
Sorry for being so stupid :exploding_head:

Working perfectly

2 Likes

I was following this. Glad to hear the info.

Just double-checking, because I was thinking of moving a site from SHA256 to Argon2ID…
…Argon2ID needs no salt or anything. Just select it in the Wappler Data Formats tool, right?

1 Like

Yes