Просмотр исходного кода

:pencil2: Lots of notes on where to go next

tags/0.0.3^2
tomit4 3 лет назад
Родитель
Сommit
3e96a6f364

+ 6
- 0
backend/lib/auth/strategies/jwt.js Просмотреть файл

13
         },
13
         },
14
         validate: (artifacts, request, h) => {
14
         validate: (artifacts, request, h) => {
15
             try {
15
             try {
16
+                // Check if the Access Token is Valid
17
+                // if (!accessTokenIsValid) {
18
+                // Look up if the Session is Active
19
+                // } else {
20
+                // isValid: true
21
+                // }
16
                 return {
22
                 return {
17
                     isValid: true,
23
                     isValid: true,
18
                     credentials: { user: artifacts.decoded.payload.user },
24
                     credentials: { user: artifacts.decoded.payload.user },

+ 2
- 0
backend/lib/routes/user/generatejwt.js Просмотреть файл

24
             const { userService } = request.server.services()
24
             const { userService } = request.server.services()
25
             const res = request.payload
25
             const res = request.payload
26
             const token = await userService.createToken(res)
26
             const token = await userService.createToken(res)
27
+            // TODO: Move logic adding initial three responses to here
27
             try {
28
             try {
29
+                // return h.state(token)
28
                 return {
30
                 return {
29
                     ok: true,
31
                     ok: true,
30
                     handler: pluginConfig.handlerType,
32
                     handler: pluginConfig.handlerType,

+ 2
- 0
backend/lib/routes/user/validatejwt.js Просмотреть файл

15
 module.exports = {
15
 module.exports = {
16
     method: 'GET',
16
     method: 'GET',
17
     path: '/validatejwt/{jwt}',
17
     path: '/validatejwt/{jwt}',
18
+    // method: 'GET' sessionToken in header ?
19
+    // path: '/validatesession/{sessionToken}'
18
     options: {
20
     options: {
19
         ...pluginConfig.docs.get,
21
         ...pluginConfig.docs.get,
20
         tags: ['api'],
22
         tags: ['api'],

+ 4
- 0
backend/lib/routes/user/verifyemail.js Просмотреть файл

25
             const hash = request.params.hashedEmail
25
             const hash = request.params.hashedEmail
26
 
26
 
27
             try {
27
             try {
28
+                // Is there an userService.activeSession?
29
+                // If there is, issue a new access token
30
+                // We need the session token from the frontend
31
+                // If NOT, throw error (kicks back to login)
28
                 const hashToMatch = Object.keys(userService.hashedEmails).find(
32
                 const hashToMatch = Object.keys(userService.hashedEmails).find(
29
                     email => {
33
                     email => {
30
                         return email === hash
34
                         return email === hash

+ 102
- 5
backend/lib/services/user.js Просмотреть файл

64
         const pwd = new SecurePassword()
64
         const pwd = new SecurePassword()
65
         // TODO: Invalidate this cache somehow after a certain time period has
65
         // TODO: Invalidate this cache somehow after a certain time period has
66
         // passed
66
         // passed
67
+        // TODO: Remove hashedEmails in preference of activeSessions
67
         this.hashedEmails = {
68
         this.hashedEmails = {
68
             // NOTE: key is email hash and value is timestamp in ms
69
             // NOTE: key is email hash and value is timestamp in ms
69
             // abc123456: '123456689',
70
             // abc123456: '123456689',
70
         }
71
         }
72
+
73
+        // this.activeSessions = [
74
+        // {
75
+        // user: {
76
+        // useremail: email,
77
+        // hashedEmail: hashedEmail,
78
+        // username: name,
79
+        // },
80
+        // expiration: 1203984710234
81
+        // },
82
+        // token: 'tokenString + expirationDate + salt'
83
+        // ]
84
+
71
         this.pwd = {
85
         this.pwd = {
72
             hash: Util.promisify(pwd.hash.bind(pwd)),
86
             hash: Util.promisify(pwd.hash.bind(pwd)),
73
             verify: Util.promisify(pwd.verify.bind(pwd)),
87
             verify: Util.promisify(pwd.verify.bind(pwd)),
210
      * @param {User} user
224
      * @param {User} user
211
      * @returns {Token}
225
      * @returns {Token}
212
      */
226
      */
213
-
227
+    // TODO: Put this logic in the routes, NOT here
228
+    // createSessionToken(user, payload)
229
+    // createAccessToken()
230
+    //
214
     createToken(user) {
231
     createToken(user) {
215
         const key = this.server.registrations['main-app-plugin'].options.jwtKey
232
         const key = this.server.registrations['main-app-plugin'].options.jwtKey
216
 
233
 
217
-        const token = Jwt.token.generate(
234
+        let token = Jwt.token.generate(
218
             {
235
             {
219
                 aud: 'urn:audience:test',
236
                 aud: 'urn:audience:test',
220
                 iss: 'urn:issuer:test',
237
                 iss: 'urn:issuer:test',
238
+                // ...payload,
221
                 email: user.email,
239
                 email: user.email,
222
                 name: user.name,
240
                 name: user.name,
223
                 seeking: user.seeking,
241
                 seeking: user.seeking,
242
+                salt: 'a;ldfkjas;l/dfkafnml;/cjkf',
224
                 // profile_id: user.profile_id,
243
                 // profile_id: user.profile_id,
225
             },
244
             },
226
             {
245
             {
228
                 algorithm: 'HS256',
247
                 algorithm: 'HS256',
229
             },
248
             },
230
             {
249
             {
231
-                // ttlSec: 4 * 60 * 60, // 7 days
232
-                // ttlSec: 60 * 3, // 3 minutes
233
-                ttlSec: user.expiration,
250
+                ttlSec: 4 * 60 * 60, // 7 days
234
             },
251
             },
235
         )
252
         )
253
+        console.log('token :=>', token)
254
+        token = Jwt.token.generate(
255
+            {
256
+                aud: 'urn:audience:test',
257
+                iss: 'urn:issuer:test',
258
+                // ...payload,
259
+                email: user.email,
260
+                name: user.name,
261
+                seeking: user.seeking,
262
+                salt: 'qpowieurpqowytqpoieryu',
263
+                // profile_id: user.profile_id,
264
+            },
265
+            {
266
+                key: key,
267
+                algorithm: 'HS256',
268
+            },
269
+            {
270
+                ttlSec: 4 * 60 * 60, // 7 days
271
+            },
272
+        )
273
+        console.log('\n')
274
+        console.log('token :=>', token)
275
+        token = Jwt.token.generate(
276
+            {
277
+                aud: 'urn:audience:test',
278
+                iss: 'urn:issuer:test',
279
+                // ...payload,
280
+                email: user.email,
281
+                name: user.name,
282
+                seeking: user.seeking,
283
+                salt: 'a;ldfkjas;l/dfkafnml;/cjkf',
284
+                // profile_id: user.profile_id,
285
+            },
286
+            {
287
+                key: key,
288
+                algorithm: 'HS256',
289
+            },
290
+            {
291
+                ttlSec: 6 * 60 * 60, // 7 days
292
+            },
293
+        )
294
+        console.log('token :=>', token)
295
+        token = Jwt.token.generate(
296
+            {
297
+                aud: 'urn:audience:test',
298
+                iss: 'urn:issuer:test',
299
+                // ...payload,
300
+                email: user.email,
301
+                name: user.name,
302
+                seeking: user.seeking,
303
+                salt: 'a;ldfkjas;l/dfkafnml;/cjkf',
304
+                // profile_id: user.profile_id,
305
+            },
306
+            {
307
+                key: key,
308
+                algorithm: 'HS256',
309
+            },
310
+            {
311
+                ttlSec: 7 * 60 * 60, // 7 days
312
+            },
313
+        )
314
+        console.log('token :=>', token)
315
+
316
+        // TODO: keep userinfo and it's association with the sessionToken in state/memory
317
+        // registerSession(user, sessionToken) // useremail, token
318
+        // this.registerSession(user, token)
236
         return token
319
         return token
237
     }
320
     }
238
 
321
 
322
+    async registerSession(user, hashedEmail, token) {
323
+        const sessionRequester = {
324
+            user: user,
325
+            hashedEmail: hashedEmail,
326
+            token: token,
327
+        }
328
+        const alreadyExists = this.activeSessions.find(
329
+            sessionRequester => sessionRequester.hashedEmail === hashedEmail,
330
+        )
331
+        if (!alreadyExists) {
332
+            this.activeSessions.push(sessionRequester)
333
+        }
334
+    }
239
     /**
335
     /**
240
      * Validates whether a token has expired or not
336
      * Validates whether a token has expired or not
241
      * @param {User} user
337
      * @param {User} user
290
     async checkEmailCache(userEmail) {
386
     async checkEmailCache(userEmail) {
291
         const hashedEmail = await hashEmail(userEmail)
387
         const hashedEmail = await hashEmail(userEmail)
292
         const now = Date.now()
388
         const now = Date.now()
389
+        // hashedEmail needs to be derived by email, salt
293
         const expiration = this.hashedEmails[hashedEmail]
390
         const expiration = this.hashedEmails[hashedEmail]
294
         console.log('this.hashedEmails :=>', this.hashedEmails)
391
         console.log('this.hashedEmails :=>', this.hashedEmails)
295
         const emailIsInCache = Object.keys(this.hashedEmails).includes(
392
         const emailIsInCache = Object.keys(this.hashedEmails).includes(

+ 2
- 1
frontend/src/components/onboarding/Auth.vue Просмотреть файл

51
             })
51
             })
52
             const newUserId = newUser.user_id
52
             const newUserId = newUser.user_id
53
             await createProfileForUserId(newUserId, this.responses)
53
             await createProfileForUserId(newUserId, this.responses)
54
+            // TODO: rename getJwt
54
             const jwt = await this.authenticator.generateJwt({
55
             const jwt = await this.authenticator.generateJwt({
55
                 ...this.answered,
56
                 ...this.answered,
56
                 expiration: 60 * 10,
57
                 expiration: 60 * 10,
57
             })
58
             })
58
             console.log('jwt :=>', jwt)
59
             console.log('jwt :=>', jwt)
59
-            document.cookie = `siimee_session_verify=${jwt}; max-age=600; path=/verify; secure`
60
+            document.cookie = `siimee_session=${jwt}; max-age=600; path=/; secure`
60
             await this.authenticator.sendAuthEmail(this.answered)
61
             await this.authenticator.sendAuthEmail(this.answered)
61
         } else {
62
         } else {
62
             console.error('ERROR :=>')
63
             console.error('ERROR :=>')

+ 8
- 3
frontend/src/services/auth.service.js Просмотреть файл

16
         const isVerified = await db.get(`/user/verify/${hashedEmail}`)
16
         const isVerified = await db.get(`/user/verify/${hashedEmail}`)
17
         return isVerified.hashesMatch
17
         return isVerified.hashesMatch
18
     }
18
     }
19
-    async generateJwt(res) {
20
-        const token = await db.post('/user/generatejwt', res)
21
-        return token.jwt
19
+    // TODO: rename getJwt()
20
+    async generateJwt(req) {
21
+        const response = await db.post('/user/generatejwt', req)
22
+        // TODO: Move token into repsonse.headers
23
+        // return response.headers ?
24
+        return response.jwt
22
     }
25
     }
26
+
27
+    // validateSession(sessionToken)
23
     async validateJwt(jwt) {
28
     async validateJwt(jwt) {
24
         const validateJwt = await db.get(`/user/validatejwt/${jwt}`)
29
         const validateJwt = await db.get(`/user/validatejwt/${jwt}`)
25
         return validateJwt
30
         return validateJwt

+ 18
- 6
frontend/src/views/OnboardingView.vue Просмотреть файл

43
 import { surveyFactory } from '@/utils'
43
 import { surveyFactory } from '@/utils'
44
 import stepViews from '@/components/onboarding'
44
 import stepViews from '@/components/onboarding'
45
 import SurveyCompleteView from './SurveyCompleteView.vue'
45
 import SurveyCompleteView from './SurveyCompleteView.vue'
46
-
46
+let sessionToken = null
47
+let accessToken = null
47
 // import savesurveybyprofileid - call it on submit
48
 // import savesurveybyprofileid - call it on submit
48
 // paginate to save every steps answers
49
 // paginate to save every steps answers
49
 export default {
50
 export default {
62
         invalidResponse: false,
63
         invalidResponse: false,
63
         userEmail: null,
64
         userEmail: null,
64
         emailIsInCache: false,
65
         emailIsInCache: false,
65
-        sessionToken: null, // need this?
66
-        accessToken: null,
67
         authenticator: {},
66
         authenticator: {},
68
     }),
67
     }),
69
     async created() {
68
     async created() {
70
         this.survey = await surveyFactory.createSurvey()
69
         this.survey = await surveyFactory.createSurvey()
71
         this.authenticator = new Authenticator()
70
         this.authenticator = new Authenticator()
72
-        const sessionToken = this.grabCookie('siimee_session_onboarding')
71
+        // TODO: Consider switch/case() depending on what tokens exist/are valid...
72
+        sessionToken = this.grabCookie('siimee_session_onboarding')
73
+        // if (!sessionToken) {
74
+        //     //
75
+        // }
76
+        accessToken = this.grabCookie('siimee_access_onboarding')
77
+        // if (!accessToken) {
78
+        //     // blow up
79
+        // }
73
         const sessionData = await this.authenticator.validateJwt(sessionToken)
80
         const sessionData = await this.authenticator.validateJwt(sessionToken)
74
-
75
-        const accessToken = this.grabCookie('siimee_access_onboarding')
76
         // NOTE: Left off here, INCOMPLETE, no ACCESS TOKEN yet, crazy amount of logic here...
81
         // NOTE: Left off here, INCOMPLETE, no ACCESS TOKEN yet, crazy amount of logic here...
77
         if (sessionData.isValid && !accessToken) {
82
         if (sessionData.isValid && !accessToken) {
78
             this.userEmail = sessionData.payload.email
83
             this.userEmail = sessionData.payload.email
84
+            // this.emailIsRegistered
79
             this.emailIsInCache = await this.authenticator.checkEmailCache(
85
             this.emailIsInCache = await this.authenticator.checkEmailCache(
80
                 this.userEmail,
86
                 this.userEmail,
81
             )
87
             )
82
         }
88
         }
89
+        // TODO: EVERY ROUTE WE HIT AFTER THIS HAS TO BE AUTHENTICATED
90
+        // ACCESS TOKEN WORKS
83
         if (this.emailIsInCache) {
91
         if (this.emailIsInCache) {
84
             const user = await fetchUserByEmail(this.userEmail)
92
             const user = await fetchUserByEmail(this.userEmail)
85
             const userId = user.user_id
93
             const userId = user.user_id
98
             })
106
             })
99
             this.currentStep = this.responses.length + 3
107
             this.currentStep = this.responses.length + 3
100
             this.goToStep(this.currentStep)
108
             this.goToStep(this.currentStep)
109
+        } else {
110
+            // TODO: CHECK SESSION
101
         }
111
         }
102
     },
112
     },
103
     methods: {
113
     methods: {
107
         async goToStep(num) {
117
         async goToStep(num) {
108
             this.currentStep = num
118
             this.currentStep = num
109
         },
119
         },
120
+        // TODO: Rename this method, grab cookie from where?
121
+        // grabStoredCookie(cookieKey)
110
         grabCookie(cookieKey) {
122
         grabCookie(cookieKey) {
111
             const cookies = document.cookie
123
             const cookies = document.cookie
112
                 .split('; ')
124
                 .split('; ')

+ 29
- 6
frontend/src/views/VerifyView.vue Просмотреть файл

17
         const hashEmail = this.$route.params.email
17
         const hashEmail = this.$route.params.email
18
 
18
 
19
         const hashesMatch = await this.authenticator.verifyAuthEmail(hashEmail)
19
         const hashesMatch = await this.authenticator.verifyAuthEmail(hashEmail)
20
-        const siimeeToken = this.grabCookie('siimee_session_verify')
20
+        // TODO: Refactor, see methods below
21
+        // if (!hashesMatch) {
22
+        //     throw new Error('no record of hashed email in cache')
23
+        //     this.$router.push('/onboarding')
24
+        // }
25
+        // TODO: THIS NEEDS TO BE SENT OVER TO verifyAuthEmail(hashEmail) in the headers
26
+        const sessionToken = this.grabCookie('siimee_session')
27
+        // TODO: Refactor, see methods below
28
+        // if (!sessionToken) {
29
+        //     throw new Error('token doesn't exist)
30
+        //     this.$router.push('/onboarding')
31
+        // } else {}
21
 
32
 
22
-        if (siimeeToken) {
23
-            const jwt = await this.authenticator.validateJwt(siimeeToken)
24
-            if (jwt.isValid && hashesMatch) {
25
-                document.cookie = `siimee_session_onboarding=${siimeeToken}; max-age=600; path=/onboarding; secure`
26
-                document.cookie = 'siimee_session_verify='
33
+        // TODO: Refactor to not nest, use try/catch/throw
34
+        if (sessionToken) {
35
+            // TODO: rename
36
+            // const accessToken = await this.authenticator.validateSession(sessionToken)
37
+            // hits backend route and the backend route has to be /validateSession/
38
+            // if backend route succeeds, gives you access token
39
+            const accessToken = await this.authenticator.validateJwt(
40
+                sessionToken,
41
+            )
42
+            // TODO: isValid logic needs to live on back end
43
+            if (accessToken.isValid && hashesMatch) {
44
+                // server needs to issue an ACCESS token here ( getToken() )
45
+                // const accessToken = await this.authenticator.getToken()
46
+                document.cookie = `siimee_access=${accessToken}; max-age=600; path=/; secure`
27
                 this.$router.push('/onboarding')
47
                 this.$router.push('/onboarding')
28
             }
48
             }
29
         } else {
49
         } else {
50
             })
70
             })
51
             return accessJwt
71
             return accessJwt
52
         },
72
         },
73
+        // async doesEmailMatch() {},
74
+        // async doesTokenExist() {},
75
+        // async isTokenValid() {},
53
     },
76
     },
54
 }
77
 }
55
 </script>
78
 </script>

Загрузка…
Отмена
Сохранить