@Drake @D5
there we go
it successfully works for the generation part
and it successfully gives me a key but
I can never get them to be the same
Are you supposed to be generating a new secret every time? 🧐
Technically yes
it's time based authentication
Never mind... misunderstood part of the code
Do you have an extra fromBase32 in the verification part?
maybe you can try setting the window to 2?
so it's this part of the code
log("MFA Setup -- Verify Code");
const userId = req.body.userId;
if (!req.body.mfacode && req.body.mfacode && req.body.mfacode.length != 6) {
return res.status(500).json("Error!");
}
const user = await users.get(userId);
const member = await db.getDocument("maindb", "member", userId);
let status = 0;
if (!user) {
return res.status(500).json("Error!");
}
let secret = OTPAuth.Secret.fromBase32(member.mfaCode);
let totp = new OTPAuth.TOTP({
issuer: encodeURIComponent('PVA.ai'),
label: encodeURIComponent(user.email),
algorithm: 'SHA1',
digits: 6,
period: 30,
secret: secret,
}); //<----- here specifically
let token = totp.generate();
let tokenSame = totp.validate({ token: req.body.mfacode });
log(`mfaToken: ${token} -- req.body.mfacode: ${req.body.mfacode} -- tokenSame: ${tokenSame}`);
log(`Timestamp right now: ${Date.now().toFixed(4)} -- Timestamp sent: ${timestamp} -- Difference: ${Date.now().toFixed(4) - timestamp}`);
if (tokenSame) {
let data = {
mfaSetup: true,
};
await db.updateDocument("maindb", "member", userId, data);
status = 1;
try {
return res.json({
type: "success",
status: status,
});
} catch (error) {
log(error);
return res.json({ type: "error", message: error });
}
} else {
return res.json({
type: "error",
message: "Token Mismatch",
status: status,
})
}
the validate doesn't work, and I've tried setting window to 2, I've tried a lot of different things and for some reason it doesn't work
Do you have an extra fromBase32 in the verification part?
I meant a few lines up when you're creating the secret from the member.mfaCode.
What you stored in mfaCode is already a result of Secret.fromBase32() but then you're running it through that again
what do you mean? Can you be more specific? I set up the totp as the instance to generate the token
but the token vs the code
the code is the users secret code, the token is the 6 digit token, so I'm generating the secret for that user and then storing the result and using it to generate the 6 digit code that it stores
that it returns"
-let secret = OTPAuth.Secret.fromBase32(member.mfaCode);
+let secret = member.mfaCode;
or something. i think there's mishandling of the secret
I also think this is incorrect:
let secret = OTPAuth.Secret.fromBase32(crypto.randomBytes(20));
the input of that is supposed to be a base32 string, but you're passing in a buffer
When initializing, you should probably be doing:
let secret = new OTPAuth.Secret({buffer: crypto.randomBytes(20)});
and then store secret.base32 in the document.
Then, you can do:
let secret = OTPAuth.Secret.fromBase32(member.mfaCode);
hmm okay, gotcha, thank you, that makes sense that that could be it
Recommended threads
- Unable to create Sites or Functions with...
Heya, I was looking at the appwrite documentation for Sites API with the server api: https://appwrite.io/docs/references/cloud/server-nodejs/sites I can’t fin...
- Triggers and call function in function p...
Hello, Today we are experiencing several issues with Appwrite Cloud. Functions triggered by events, or functions called from another function, are taking an e...
- Functions executed by events does not ap...
Hello, Running self-hosted Appwrite version 1.9.0 (with console 7.8.26). When functions are triggered by an event (eg. databases.\*tables.\*.rows.\*.create) doe...