Pārlūkot izejas kodu

:pencil2: Lots of notes on where to go next

tags/0.0.3^2
tomit4 3 gadus atpakaļ
vecāks
revīzija
3e96a6f364

+ 6
- 0
backend/lib/auth/strategies/jwt.js Parādīt failu

@@ -13,6 +13,12 @@ module.exports = options => {
13 13
         },
14 14
         validate: (artifacts, request, h) => {
15 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 22
                 return {
17 23
                     isValid: true,
18 24
                     credentials: { user: artifacts.decoded.payload.user },

+ 2
- 0
backend/lib/routes/user/generatejwt.js Parādīt failu

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

+ 2
- 0
backend/lib/routes/user/validatejwt.js Parādīt failu

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

+ 4
- 0
backend/lib/routes/user/verifyemail.js Parādīt failu

@@ -25,6 +25,10 @@ module.exports = {
25 25
             const hash = request.params.hashedEmail
26 26
 
27 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 32
                 const hashToMatch = Object.keys(userService.hashedEmails).find(
29 33
                     email => {
30 34
                         return email === hash

+ 102
- 5
backend/lib/services/user.js Parādīt failu

@@ -64,10 +64,24 @@ module.exports = class UserService extends Schmervice.Service {
64 64
         const pwd = new SecurePassword()
65 65
         // TODO: Invalidate this cache somehow after a certain time period has
66 66
         // passed
67
+        // TODO: Remove hashedEmails in preference of activeSessions
67 68
         this.hashedEmails = {
68 69
             // NOTE: key is email hash and value is timestamp in ms
69 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 85
         this.pwd = {
72 86
             hash: Util.promisify(pwd.hash.bind(pwd)),
73 87
             verify: Util.promisify(pwd.verify.bind(pwd)),
@@ -210,17 +224,22 @@ module.exports = class UserService extends Schmervice.Service {
210 224
      * @param {User} user
211 225
      * @returns {Token}
212 226
      */
213
-
227
+    // TODO: Put this logic in the routes, NOT here
228
+    // createSessionToken(user, payload)
229
+    // createAccessToken()
230
+    //
214 231
     createToken(user) {
215 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 236
                 aud: 'urn:audience:test',
220 237
                 iss: 'urn:issuer:test',
238
+                // ...payload,
221 239
                 email: user.email,
222 240
                 name: user.name,
223 241
                 seeking: user.seeking,
242
+                salt: 'a;ldfkjas;l/dfkafnml;/cjkf',
224 243
                 // profile_id: user.profile_id,
225 244
             },
226 245
             {
@@ -228,14 +247,91 @@ module.exports = class UserService extends Schmervice.Service {
228 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 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 336
      * Validates whether a token has expired or not
241 337
      * @param {User} user
@@ -290,6 +386,7 @@ module.exports = class UserService extends Schmervice.Service {
290 386
     async checkEmailCache(userEmail) {
291 387
         const hashedEmail = await hashEmail(userEmail)
292 388
         const now = Date.now()
389
+        // hashedEmail needs to be derived by email, salt
293 390
         const expiration = this.hashedEmails[hashedEmail]
294 391
         console.log('this.hashedEmails :=>', this.hashedEmails)
295 392
         const emailIsInCache = Object.keys(this.hashedEmails).includes(

+ 2
- 1
frontend/src/components/onboarding/Auth.vue Parādīt failu

@@ -51,12 +51,13 @@ export default {
51 51
             })
52 52
             const newUserId = newUser.user_id
53 53
             await createProfileForUserId(newUserId, this.responses)
54
+            // TODO: rename getJwt
54 55
             const jwt = await this.authenticator.generateJwt({
55 56
                 ...this.answered,
56 57
                 expiration: 60 * 10,
57 58
             })
58 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 61
             await this.authenticator.sendAuthEmail(this.answered)
61 62
         } else {
62 63
             console.error('ERROR :=>')

+ 8
- 3
frontend/src/services/auth.service.js Parādīt failu

@@ -16,10 +16,15 @@ class Authenticator {
16 16
         const isVerified = await db.get(`/user/verify/${hashedEmail}`)
17 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 28
     async validateJwt(jwt) {
24 29
         const validateJwt = await db.get(`/user/validatejwt/${jwt}`)
25 30
         return validateJwt

+ 18
- 6
frontend/src/views/OnboardingView.vue Parādīt failu

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

+ 29
- 6
frontend/src/views/VerifyView.vue Parādīt failu

@@ -17,13 +17,33 @@ export default {
17 17
         const hashEmail = this.$route.params.email
18 18
 
19 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 47
                 this.$router.push('/onboarding')
28 48
             }
29 49
         } else {
@@ -50,6 +70,9 @@ export default {
50 70
             })
51 71
             return accessJwt
52 72
         },
73
+        // async doesEmailMatch() {},
74
+        // async doesTokenExist() {},
75
+        // async isTokenValid() {},
53 76
     },
54 77
 }
55 78
 </script>

Notiek ielāde…
Atcelt
Saglabāt