-
Notifications
You must be signed in to change notification settings - Fork 26
feat(totp): Add initial totp session verification logic #309
Conversation
ebfb75f
to
848838c
Compare
@@ -125,6 +126,7 @@ function createServer(db) { | |||
|
|||
api.get('/keyFetchToken/:id/verified', withIdAndBody(db.keyFetchTokenWithVerificationStatus)) | |||
api.post('/tokens/:id/verify', withIdAndBody(db.verifyTokens)) | |||
api.post('/tokens/:id/verifyWith', withIdAndBody(db.verifyTokensWithMethod)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated this endpoint name to /tokens/:id/verifyWith
and db to verifyTokensWithMethod
over verifySessionWithMethod
. This made sense because it verifies more than session tokens. Open to other names as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yea maybe verifyWith
--> verifyWithMethod
to make it verbose
@@ -1524,8 +1524,8 @@ module.exports = function(cfg, makeServer) { | |||
.spread((sessionTokenResp, keyFetchTokenResp) => { | |||
respOk(sessionTokenResp) | |||
respOk(keyFetchTokenResp) | |||
const sessionToken = sessionTokenResp | |||
const keyFetchToken = keyFetchTokenResp | |||
const sessionToken = sessionTokenResp.obj |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unrelated, but noticed that this wasn't testing against the correct response object.
@@ -38,7 +38,7 @@ var DEVICE_FIELDS = [ | |||
'callbackIsExpired' | |||
] | |||
|
|||
var SESSION_FIELDS = [ | |||
const SESSION_DEVICE_FIELDS = [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is unrelated change that confused me while working on this PR. These are session device fields that are returned when updating/retrieving devices.
SELECT @updateCount; | ||
END; | ||
|
||
CREATE PROCEDURE `sessionWithDevice_12` ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The procedures below have been updated to return the mustVerify
property of session tokens from either the session table or unverified tokens table.
@mozilla/fxa-devs r? |
lib/db/mem.js
Outdated
item.mustVerify = sessionTokens[id].mustVerify | ||
} else { | ||
item.mustVerify = unverifiedTokens[id].mustVerify | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code confused me initially. Given that item.mustVerify
is already initialised to sessionTokens[id].mustVerify || null
on line 546, could it be simplified to a simple single if (! item.mustVerify) {
condition?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/simple/single/
@@ -1761,7 +1761,7 @@ module.exports = function (config, DB) { | |||
}) | |||
.then((session) => { | |||
// Returns verified session | |||
assert.equal(session.mustVerify, null, 'mustVerify is not set') | |||
assert.equal(!! session.mustVerify, false, 'mustVerify is false') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Purely out of curiousity, do we actually need to keep using !!
every time we test these properties?
assert.equal
already uses ==
under the hood, so presumably null
coerces to false
anyway. And true
is always true
. Do any of them fail without the !!
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately, this would break some tests because the mysql column is using TINYINT(1)
instead of BOOLEAN
. I don't believe there is any harm in using the boolean variable since it will return true/false instead of 0,1 which needed to be coerced. Will update!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately, this would break some tests because the mysql column is using TINYINT(1) instead of BOOLEAN
Turns that that was not correct and tests do pass. The only other explanation I have is that it was needed when we were using TAP. In either case, they have been updated.
lib/db/schema/patch-072-073.sql
Outdated
) | ||
BEGIN | ||
|
||
UPDATE `totp` SET verified = verifiedArg, enable = enableArg WHERE uid = uidArg; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pedantry: Looks like 2-space indentation elsewhere...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
docs/DB_API.md
Outdated
The uid of the owning account | ||
* `tokenData` | ||
* `verified`: Boolean whether TOTP token has been verified | ||
* `enable`: Boolean whether TOTP token is enabled |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This only occurred to me while reviewing the auth server PR. Should it be enabled
rather than enable
? That way sounds more like a boolean state and less like an instruction to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yikes, looks I am not consistent with these fields/docs. I will update to use enabled
.
// Currently, users can only update the verified and enable flags. | ||
// Updating shared secret and epoch will break clients. | ||
totpToken.verified = token.verified | ||
totpToken.enabled = token.enabled |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
...oh and here you are setting enabled
, not enable
. Is one of them wrong?
lib/db/schema/patch-072-073.sql
Outdated
-- Add columns `verified` and `enable` to help manage TOTP token state | ||
ALTER TABLE `totp` | ||
ADD COLUMN `verified` TINYINT(1) DEFAULT FALSE, | ||
ADD COLUMN `enable` TINYINT(1) DEFAULT TRUE, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
...yeah (he said, continuing the conversation with himself), I think enabled
would be better actually, it seems more consistent with other column names.
848838c
to
c22e19d
Compare
@philbooth Thank you! |
@@ -97,6 +97,7 @@ function createServer(db) { | |||
return db.deleteEmail(req.params.id, req.params.email) | |||
}) | |||
) | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
side note in this file, above we have db.deleteEmail(req.params.id, req.params.email)
but all methods below use Buffer(
on the email. might be worth filing a clean up issue, I'm not sure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting, looks like this might have been missed on the original secondary email implementation. Opened issue #311.
@@ -91,13 +91,15 @@ The following datatypes are used throughout this document: | |||
* forgotPasswordVerified : `POST /passwordForgotToken/:id/verified` | |||
* Unverified tokens: | |||
* verifyTokens : `POST /tokens/:tokenVerificationId/verify` | |||
* verifyTokensWithMethod : `POST /tokens/:tokenId/verifyWith` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this new doc uses tokenId
, but above it is tokenVerificationId
, both are {:id}
in the route definition. Intentional ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea this was intentional. The store procedure will look up the tokenVerificationId
directly from the tokenId
. I used id
since it allowed me to reuse the helper function withIdAndBody
. I don't mind updating if it makes it more clear.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool 👍
@@ -125,6 +126,7 @@ function createServer(db) { | |||
|
|||
api.get('/keyFetchToken/:id/verified', withIdAndBody(db.keyFetchTokenWithVerificationStatus)) | |||
api.post('/tokens/:id/verify', withIdAndBody(db.verifyTokens)) | |||
api.post('/tokens/:id/verifyWith', withIdAndBody(db.verifyTokensWithMethod)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yea maybe verifyWith
--> verifyWithMethod
to make it verbose
This PR is the next stage for TOTP tokens. It adds the ability to verify TOTP tokens and sessions.
verified, enabled
property to TOTP tokens.verificationMethod, verifiedAt
property to session tokens.mustVerify
property to the session table. This property is in sync with the property on the unverified tokens table, ref: TOTP Session Verification API #301 (comment).Fixes #301