forked from canada-ca/tracker
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathauthenticate.js
More file actions
108 lines (97 loc) · 3.21 KB
/
authenticate.js
File metadata and controls
108 lines (97 loc) · 3.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
const { GraphQLNonNull, GraphQLString, GraphQLInt } = require('graphql')
const { mutationWithClientMutationId } = require('graphql-relay')
const { t } = require('@lingui/macro')
const { authResultType } = require('../../types')
const { SIGN_IN_KEY } = process.env
const authenticate = new mutationWithClientMutationId({
name: 'Authenticate',
description:
'This mutation allows users to give their credentials and retrieve a token that gives them access to restricted content.',
inputFields: () => ({
authenticationCode: {
type: GraphQLNonNull(GraphQLInt),
description: 'Security code found in text msg, or email inbox.',
},
authenticateToken: {
type: GraphQLNonNull(GraphQLString),
description: 'The JWT that is retrieved from the sign in mutation.',
},
}),
outputFields: () => ({
authResult: {
type: authResultType,
description: 'The authenticated users information, and JWT.',
resolve: async (payload) => {
return payload.authResult
},
},
}),
mutateAndGetPayload: async (
args,
{
i18n,
query,
auth: { tokenize, verifyToken },
loaders: { userLoaderByKey },
validators: { cleanseInput },
},
) => {
// Cleanse Inputs
const authenticationCode = args.authenticationCode
const authenticationToken = cleanseInput(args.authenticateToken)
// Gather token parameters
const tokenParameters = verifyToken({
token: authenticationToken,
secret: String(SIGN_IN_KEY),
})
if (
tokenParameters.userId === 'undefined' ||
typeof tokenParameters.userId === 'undefined'
) {
console.warn(`Authentication token does not contain the userId`)
throw new Error(i18n._(t`Unable to authenticate. Please try again.`))
}
// Gather sign in user
const user = await userLoaderByKey.load(tokenParameters.userId)
if (typeof user === 'undefined') {
console.warn(
`User: ${tokenParameters.userId} attempted to authenticate, no account is associated with this id.`,
)
throw new Error(i18n._(t`Unable to authenticate. Please try again.`))
}
// Check to see if security token matches the user submitted one
if (authenticationCode === user.tfaCode) {
const token = tokenize({ parameters: { userId: user._key } })
// Reset Failed Login attempts
try {
await query`
FOR u IN users
UPDATE ${user._key} WITH { tfaCode: null } IN users
`
} catch (err) {
console.error(
`Database error ocurred when resetting failed attempts for user: ${user._key} during authentication: ${err}`,
)
throw new Error(i18n._(t`Unable to authenticate. Please try again.`))
}
console.info(
`User: ${user._key} successfully authenticated their account.`,
)
user.id = user._key
return {
authResult: {
token,
user,
},
}
} else {
console.warn(
`User: ${user._key} attempted to authenticate their account, however the tfaCodes did not match.`,
)
throw new Error(i18n._(t`Unable to authenticate. Please try again.`))
}
},
})
module.exports = {
authenticate,
}