1
1
import type { FirebaseError , FirebaseApp } from 'firebase/app'
2
- import { getAuth , onIdTokenChanged } from 'firebase/auth'
2
+ import {
3
+ getAuth ,
4
+ onIdTokenChanged ,
5
+ beforeAuthStateChanged ,
6
+ User ,
7
+ } from 'firebase/auth'
3
8
import { VueFireAuth } from 'vuefire'
4
9
import { defineNuxtPlugin , showError } from '#app'
5
10
@@ -13,15 +18,27 @@ export default defineNuxtPlugin((nuxtApp) => {
13
18
VueFireAuth ( nuxtApp . payload . vuefireUser ) ( firebaseApp , nuxtApp . vueApp )
14
19
const auth = getAuth ( firebaseApp )
15
20
// send a post request to the server when auth state changes to mint a cookie
16
- onIdTokenChanged ( auth , async ( user ) => {
17
- const jwtToken = await user ?. getIdToken ( )
18
- $fetch ( '/api/_vuefire/auth' , {
19
- method : 'POST' ,
20
- // if the token is undefined, the server will delete the cookie
21
- body : { token : jwtToken } ,
22
- } ) . catch ( ( reason : FirebaseError ) => {
23
- // there is no need to return a rejected error as `onIdTokenChanged` won't use it
24
- showError ( reason )
25
- } )
21
+ beforeAuthStateChanged ( auth , mintCookie , ( ) => {
22
+ // rollback the auth state
23
+ mintCookie ( auth . currentUser )
26
24
} )
25
+
26
+ // we need both callback to avoid some race conditions
27
+ onIdTokenChanged ( auth , mintCookie )
27
28
} )
29
+
30
+ /**
31
+ * Sends a post request to the server to mint a cookie based auth session. The name of the cookie is defined in the
32
+ * api.session.ts file.
33
+ *
34
+ * @param user - the user to mint a cookie for
35
+ */
36
+ async function mintCookie ( user : User | null ) {
37
+ const jwtToken = await user ?. getIdToken ( )
38
+ // throws if the server returns an error so that beforeAuthStateChanged can catch it to cancel
39
+ await $fetch ( '/api/_vuefire/auth' , {
40
+ method : 'POST' ,
41
+ // if the token is undefined, the server will delete the cookie
42
+ body : { token : jwtToken } ,
43
+ } )
44
+ }
0 commit comments