Skip to content
This repository was archived by the owner on Apr 3, 2019. It is now read-only.

Commit a866e8f

Browse files
committed
feat(devices): added fxa-deviceId to the signed certificate
1 parent 571f2d8 commit a866e8f

File tree

7 files changed

+86
-30
lines changed

7 files changed

+86
-30
lines changed

lib/db.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,31 @@ module.exports = function (
453453
)
454454
}
455455

456+
DB.prototype.sessionWithDevice = function (id) {
457+
log.trace({ op: 'DB.sessionWithDevice', id: id })
458+
return this.pool.get('/sessionToken/' + id.toString('hex') + '/device')
459+
.then(
460+
function (body) {
461+
var data = bufferize(body, {
462+
ignore: [
463+
'uaBrowser',
464+
'uaBrowserVersion',
465+
'uaOS',
466+
'uaOSVersion',
467+
'uaDeviceType'
468+
]
469+
})
470+
return SessionToken.fromHex(data.tokenData, data)
471+
},
472+
function (err) {
473+
if (isNotFoundError(err)) {
474+
err = error.invalidToken()
475+
}
476+
throw err
477+
}
478+
)
479+
}
480+
456481
// UPDATE
457482

458483
DB.prototype.updatePasswordForgotToken = function (token) {

lib/routes/sign.js

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ module.exports = function (log, isA, error, signer, db, domain) {
1212
path: '/certificate/sign',
1313
config: {
1414
auth: {
15-
strategy: 'sessionToken',
15+
strategy: 'sessionTokenWithDevice',
1616
payload: 'required'
1717
},
1818
validate: {
@@ -88,23 +88,36 @@ module.exports = function (log, isA, error, signer, db, domain) {
8888
}
8989
}
9090
var uid = sessionToken.uid.toString('hex')
91-
signer.sign(
91+
var deviceId = sessionToken.deviceId ?
92+
sessionToken.deviceId.toString('hex') : null
93+
94+
return signer.sign(
9295
{
9396
email: uid + '@' + domain,
9497
publicKey: publicKey,
9598
domain: domain,
9699
duration: duration,
97100
generation: sessionToken.verifierSetAt,
98101
lastAuthAt: sessionToken.lastAuthAt(),
99-
verifiedEmail: sessionToken.email
102+
verifiedEmail: sessionToken.email,
103+
deviceId: deviceId
100104
}
101-
).then(function(certResult) {
102-
log.activityEvent('account.signed', request, {
103-
uid: uid,
104-
account_created_at: sessionToken.accountCreatedAt
105-
})
106-
reply(certResult)
107-
}, reply)
105+
)
106+
.then(
107+
function(certResult) {
108+
log.activityEvent(
109+
'account.signed',
110+
request,
111+
{
112+
uid: uid,
113+
account_created_at: sessionToken.accountCreatedAt,
114+
device_id: deviceId
115+
}
116+
)
117+
reply(certResult)
118+
},
119+
reply
120+
)
108121
}
109122
}
110123
]

lib/server.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,14 @@ function create(log, error, config, routes, db) {
106106
server.connection(connectionOptions)
107107

108108
server.register(require('hapi-auth-hawk'), function (err) {
109+
server.auth.strategy(
110+
'sessionTokenWithDevice',
111+
'hawk',
112+
{
113+
getCredentialsFunc: makeCredentialFn(db.sessionWithDevice.bind(db)),
114+
hawk: hawkOptions
115+
}
116+
)
109117
server.auth.strategy(
110118
'sessionToken',
111119
'hawk',

lib/signer.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ module.exports = function (secretKeyFile, domain) {
2121
exp: now + data.duration,
2222
'fxa-generation': data.generation,
2323
'fxa-lastAuthAt': data.lastAuthAt,
24-
'fxa-verifiedEmail': data.verifiedEmail
24+
'fxa-verifiedEmail': data.verifiedEmail,
25+
'fxa-deviceId': data.deviceId
2526
}
2627
)
2728
.then(

lib/tokens/session_token.js

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ module.exports = function (log, inherits, Token) {
1414

1515
function SessionToken(keys, details) {
1616
Token.call(this, keys, details)
17-
this.forceUpdate(details)
17+
this.setUserAgentInfo(details)
18+
this.setDeviceInfo(details)
1819
this.email = details.email || null
1920
this.emailCode = details.emailCode || null
2021
this.emailVerified = !!details.emailVerified
@@ -60,7 +61,7 @@ module.exports = function (log, inherits, Token) {
6061
return false
6162
}
6263

63-
this.forceUpdate(freshData)
64+
this.setUserAgentInfo(freshData)
6465

6566
return true
6667
}
@@ -83,7 +84,7 @@ module.exports = function (log, inherits, Token) {
8384
return result
8485
}
8586

86-
SessionToken.prototype.forceUpdate = function (data) {
87+
SessionToken.prototype.setUserAgentInfo = function (data) {
8788
this.uaBrowser = data.uaBrowser
8889
this.uaBrowserVersion = data.uaBrowserVersion
8990
this.uaOS = data.uaOS
@@ -92,6 +93,15 @@ module.exports = function (log, inherits, Token) {
9293
this.lastAccessTime = data.lastAccessTime
9394
}
9495

96+
SessionToken.prototype.setDeviceInfo = function (data) {
97+
this.deviceId = data.deviceId
98+
this.deviceName = data.deviceName
99+
this.deviceType = data.deviceType
100+
this.deviceCreatedAt = data.deviceCreatedAt
101+
this.callbackURL = data.callbackURL
102+
this.callbackPublicKey = data.callbackPublicKey
103+
}
104+
95105
return SessionToken
96106
}
97107

npm-shrinkwrap.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/local/session_token_tests.js

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ test(
2626
t.equal(typeof token.lastAuthAt, 'function', 'lastAuthAt method is defined')
2727
t.equal(typeof token.update, 'function', 'update method is defined')
2828
t.equal(typeof token.isFresh, 'function', 'isFresh method is defined')
29-
t.equal(typeof token.forceUpdate, 'function', 'forceUpdate method is defined')
29+
t.equal(typeof token.setUserAgentInfo, 'function', 'setUserAgentInfo method is defined')
3030
})
3131
}
3232
)
@@ -81,11 +81,11 @@ test(
8181
)
8282

8383
test(
84-
'SessionToken.forceUpdate',
84+
'SessionToken.setUserAgentInfo',
8585
function (t) {
8686
return SessionToken.create(ACCOUNT)
8787
.then(function (token) {
88-
token.forceUpdate({
88+
token.setUserAgentInfo({
8989
data: 'foo',
9090
tokenId: 'foo',
9191
authKey: 'foo',
@@ -217,7 +217,7 @@ test(
217217
sinon.stub(SessionToken.prototype, 'isFresh', function () {
218218
return true
219219
})
220-
sinon.spy(SessionToken.prototype, 'forceUpdate')
220+
sinon.spy(SessionToken.prototype, 'setUserAgentInfo')
221221

222222
t.equal(
223223
token.update(
@@ -240,11 +240,11 @@ test(
240240
t.ok(isFreshData.lastAccessTime > Date.now() - 10000, 'lastAccessTime was greater than 10 seconds ago')
241241
t.ok(isFreshData.lastAccessTime < Date.now(), 'lastAccessTime was less then Date.now()')
242242

243-
t.equal(SessionToken.prototype.forceUpdate.callCount, 0, 'forceUpdate was not called')
243+
t.equal(SessionToken.prototype.setUserAgentInfo.callCount, 0, 'setUserAgentInfo was not called')
244244
})
245245
.finally(function () {
246246
SessionToken.prototype.isFresh.restore()
247-
SessionToken.prototype.forceUpdate.restore()
247+
SessionToken.prototype.setUserAgentInfo.restore()
248248
})
249249
}
250250
)
@@ -257,7 +257,7 @@ test(
257257
sinon.stub(SessionToken.prototype, 'isFresh', function () {
258258
return false
259259
})
260-
sinon.spy(SessionToken.prototype, 'forceUpdate')
260+
sinon.spy(SessionToken.prototype, 'setUserAgentInfo')
261261

262262
t.equal(
263263
token.update(
@@ -266,19 +266,18 @@ test(
266266
)
267267

268268
t.equal(SessionToken.prototype.isFresh.callCount, 1, 'isFresh was called once')
269-
var isFreshArgs = SessionToken.prototype.forceUpdate.args[0]
269+
var isFreshArgs = SessionToken.prototype.setUserAgentInfo.args[0]
270270
t.equal(isFreshArgs.length, 1, 'isFresh was passed one argument')
271271

272-
t.equal(SessionToken.prototype.forceUpdate.callCount, 1, 'forceUpdate called once')
273-
t.equal(SessionToken.prototype.forceUpdate.thisValues[0], token, 'forceUpdate context was token')
274-
var forceUpdateArgs = SessionToken.prototype.forceUpdate.args[0]
275-
t.equal(forceUpdateArgs.length, 1, 'forceUpdate was passed one argument')
276-
t.deepEqual(forceUpdateArgs[0], isFreshArgs[0], 'forceUpdate was passed correct argument')
272+
t.equal(SessionToken.prototype.setUserAgentInfo.callCount, 1, 'setUserAgentInfo called once')
273+
t.equal(SessionToken.prototype.setUserAgentInfo.thisValues[0], token, 'setUserAgentInfo context was token')
274+
var setUserAgentInfoArgs = SessionToken.prototype.setUserAgentInfo.args[0]
275+
t.equal(setUserAgentInfoArgs.length, 1, 'setUserAgentInfo was passed one argument')
276+
t.deepEqual(setUserAgentInfoArgs[0], isFreshArgs[0], 'setUserAgentInfo was passed correct argument')
277277
})
278278
.finally(function () {
279279
SessionToken.prototype.isFresh.restore()
280-
SessionToken.prototype.forceUpdate.restore()
280+
SessionToken.prototype.setUserAgentInfo.restore()
281281
})
282282
}
283283
)
284-

0 commit comments

Comments
 (0)