Skip to content

Commit 1552964

Browse files
committed
refactor: move admin app initialization to vuefire
1 parent 807b4eb commit 1552964

File tree

15 files changed

+643
-641
lines changed

15 files changed

+643
-641
lines changed

build.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export default defineBuildConfig({
2626
'firebase-admin',
2727
'firebase-admin/app',
2828
'firebase-admin/app-check',
29+
'firebase-admin/auth',
2930
'firebase-functions',
3031
'firebase-functions/params',
3132
],

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,8 @@
8080
"conventional-changelog-cli": "^2.0.34",
8181
"enquirer": "^2.3.6",
8282
"execa": "^7.0.0",
83-
"firebase": "^9.15.0",
84-
"firebase-admin": "^11.4.0",
83+
"firebase": "^9.19.1",
84+
"firebase-admin": "^11.5.0",
8585
"focus-visible": "^5.2.0",
8686
"globby": "^13.1.2",
8787
"happy-dom": "^8.9.0",

packages/nuxt/package.json

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,16 @@
66
"type": "module",
77
"exports": {
88
".": {
9+
"types": "./dist/module.d.ts",
910
"import": "./dist/module.mjs",
1011
"require": "./dist/module.cjs"
1112
},
12-
"./templates/*": "./templates/*"
13+
"./templates/*": "./templates/*",
14+
"./runtime": {
15+
"types": "./dist/runtime/index.d.ts",
16+
"import": "./dist/runtime/index.mjs",
17+
"require": "./dist/runtime/index.mjs"
18+
}
1319
},
1420
"main": "./dist/module.cjs",
1521
"module": "./dist/module.mjs",
@@ -58,9 +64,9 @@
5864
"@nuxt/schema": "^3.0.0",
5965
"@nuxtjs/eslint-config-typescript": "^12.0.0",
6066
"eslint": "^8.35.0",
61-
"firebase": "^9.15.0",
62-
"firebase-admin": "^11.4.0",
63-
"firebase-functions": "^4.1.1",
67+
"firebase": "^9.19.1",
68+
"firebase-admin": "^11.5.0",
69+
"firebase-functions": "^4.2.1",
6470
"nuxt": "^3.0.0",
6571
"vuefire": "workspace:*"
6672
}

packages/nuxt/playground/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
},
1313
"dependencies": {
1414
"@firebase/app-types": "^0.8.1",
15-
"firebase": "^9.14.0",
15+
"firebase": "^9.19.1",
1616
"nuxt-vuefire": "workspace:*",
1717
"vuefire": "workspace:*"
1818
}

packages/nuxt/src/runtime/admin/plugin-auth-user.server.ts

Lines changed: 17 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,34 @@
11
import type { App as AdminApp } from 'firebase-admin/app'
22
import { getAuth as getAdminAuth, UserRecord } from 'firebase-admin/auth'
3-
import { createServerUser } from 'vuefire/server'
3+
import {
4+
createServerUser,
5+
decodeUserToken,
6+
AUTH_COOKIE_NAME,
7+
} from 'vuefire/server'
48
import { getCookie } from 'h3'
5-
import { log } from '../logging'
6-
import { AUTH_COOKIE_NAME, UserSymbol } from '../constants'
7-
import { isFirebaseError } from '../utils'
9+
import { UserSymbol } from '../constants'
810
import { defineNuxtPlugin, useRequestEvent } from '#app'
911

1012
/**
1113
* Check if there is a cookie and if it is valid, extracts the user from it. This only requires the admin app.
1214
*/
1315
export default defineNuxtPlugin(async (nuxtApp) => {
1416
const event = useRequestEvent()
15-
const token = getCookie(event, AUTH_COOKIE_NAME)
16-
let user: UserRecord | undefined | null
17-
// ensure the property is set
18-
event.context.user = null
17+
const adminApp = nuxtApp.$firebaseAdminApp as AdminApp
18+
const adminAuth = getAdminAuth(adminApp)
1919

20-
// log('debug', `Getting user from "${AUTH_COOKIE_NAME}"`, token)
21-
22-
if (token) {
23-
const adminApp = nuxtApp.$firebaseAdminApp as AdminApp
24-
const adminAuth = getAdminAuth(adminApp)
25-
26-
try {
27-
// TODO: should we check for the revoked status of the token here?
28-
const decodedToken = await adminAuth.verifyIdToken(token)
29-
user = await adminAuth.getUser(decodedToken.uid)
30-
event.context.user = user
31-
} catch (err) {
32-
// TODO: some errors should probably go higher
33-
// ignore the error and consider the user as not logged in
34-
if (isFirebaseError(err) && err.code === 'auth/id-token-expired') {
35-
// Other errors to be handled: auth/argument-error
36-
// the error is fine, the user is not logged in
37-
log('info', 'Token expired -', err)
38-
// TODO: this error should be accessible somewhere to instruct the user to renew their access token
39-
} else {
40-
// ignore the error and consider the user as not logged in
41-
log('error', 'Unknown Error -', err)
42-
}
43-
}
44-
}
20+
const decodedToken = await decodeUserToken(
21+
getCookie(event, AUTH_COOKIE_NAME),
22+
adminApp
23+
)
24+
const user = await (decodedToken && adminAuth.getUser(decodedToken.uid))
4525

26+
// expose the user to code
27+
event.context.user = user
28+
// for SSR
4629
nuxtApp.payload.vuefireUser = user?.toJSON()
4730

31+
// user that has a similar shape for client and server code
4832
nuxtApp[
4933
// we cannot use symbol to index
5034
UserSymbol as unknown as string

packages/nuxt/src/runtime/admin/plugin.server.ts

Lines changed: 6 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,87 +1,14 @@
1-
import {
2-
initializeApp,
3-
cert,
4-
getApp,
5-
getApps,
6-
applicationDefault,
7-
// renamed because there seems to be a global Credential type in vscode
8-
Credential as FirebaseAdminCredential,
9-
App as AdminApp,
10-
} from 'firebase-admin/app'
11-
import { log } from '../logging'
1+
import { App as AdminApp } from 'firebase-admin/app'
2+
import { getAdminApp } from 'vuefire/server'
123
import { defineNuxtPlugin, useAppConfig, useRequestEvent } from '#app'
134

14-
export default defineNuxtPlugin((nuxtApp) => {
5+
export default defineNuxtPlugin(() => {
156
const event = useRequestEvent()
16-
// only initialize the admin sdk once
17-
if (!getApps().length) {
18-
const { firebaseAdmin } = useAppConfig()
19-
const {
20-
// these can be set by the user on other platforms
21-
FIREBASE_PROJECT_ID,
22-
FIREBASE_CLIENT_EMAIL,
23-
FIREBASE_PRIVATE_KEY,
24-
// set on firebase cloud functions
25-
FIREBASE_CONFIG,
26-
// in cloud functions, we can auto initialize
27-
FUNCTION_NAME,
28-
GOOGLE_APPLICATION_CREDENTIALS,
29-
} = process.env
7+
const { firebaseAdmin } = useAppConfig()
308

31-
if (FIREBASE_CONFIG || FUNCTION_NAME) {
32-
log('debug', 'using FIREBASE_CONFIG env variable')
33-
initializeApp()
34-
} else {
35-
let credential: FirebaseAdminCredential
36-
// This version should work in Firebase Functions and other providers while applicationDefault() only works on
37-
// Firebase deployments
38-
if (FIREBASE_PRIVATE_KEY) {
39-
log('debug', 'using FIREBASE_PRIVATE_KEY env variable')
40-
credential = cert({
41-
projectId: FIREBASE_PROJECT_ID,
42-
clientEmail: FIREBASE_CLIENT_EMAIL,
43-
// replace `\` and `n` character pairs w/ single `\n` character
44-
privateKey: FIREBASE_PRIVATE_KEY.replace(/\\n/g, '\n'),
45-
})
46-
} else if (process.env.GOOGLE_APPLICATION_CREDENTIALS) {
47-
if (
48-
typeof GOOGLE_APPLICATION_CREDENTIALS === 'string' &&
49-
// ensure it's an object
50-
GOOGLE_APPLICATION_CREDENTIALS[0] === '{'
51-
) {
52-
log(
53-
'debug',
54-
'Parsing GOOGLE_APPLICATION_CREDENTIALS env variable as JSON'
55-
)
56-
credential = cert(JSON.parse(GOOGLE_APPLICATION_CREDENTIALS))
57-
} else {
58-
// automatically picks up the service account file path from the env variable
59-
log('debug', 'using applicationDefault()')
60-
credential = applicationDefault()
61-
}
62-
} else {
63-
// No credentials were provided, this will fail so we throw an explicit error
64-
// TODO: add link to vuefire docs
65-
log(
66-
'warn',
67-
`\
68-
You must provide an "admin.serviceAccount" path to your json so it's picked up during development. See https://firebase.google.com/docs/admin/setup#initialize-sdk for more information. Note that you can also set the GOOGLE_APPLICATION_CREDENTIALS env variable to a full resolved path or a JSON string.
69-
You can also set the FIREBASE_CLIENT_EMAIL, FIREBASE_PRIVATE_KEY and FIREBASE_PROJECT_ID env variables in production if you are deploying to something else than Firebase Cloud Functions.
70-
`
71-
)
72-
throw new Error('admin-app/missing-credentials')
73-
}
9+
const firebaseAdminApp = getAdminApp(firebaseAdmin?.options)
7410

75-
initializeApp({
76-
// TODO: is this really going to be used?
77-
...firebaseAdmin?.options,
78-
credential,
79-
})
80-
}
81-
}
82-
83-
const firebaseAdminApp = getApp()
84-
// TODO: Is this accessible within middlewares and api routes? or should be use a middleware to add it
11+
// TODO: Is this accessible within middlewares and api routes? or should we use a middleware to add it
8512
event.context.firebaseApp = firebaseAdminApp
8613

8714
return {

packages/nuxt/src/runtime/auth/plugin.server.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { FirebaseApp } from 'firebase/app'
22
import type { User } from 'firebase/auth'
33
import { VueFireAuthServer } from 'vuefire/server'
4-
import { log } from '../logging'
4+
import type { App } from 'vue'
55
import { UserSymbol } from '../constants'
66
import { defineNuxtPlugin } from '#app'
77

@@ -18,5 +18,5 @@ export default defineNuxtPlugin((nuxtApp) => {
1818
// log('debug', 'setting up user for app', firebaseApp.name, user?.uid)
1919

2020
// provide the user data to the app during ssr
21-
VueFireAuthServer(firebaseApp, nuxtApp.vueApp, user)
21+
VueFireAuthServer(firebaseApp, nuxtApp.vueApp as App, user)
2222
})

packages/nuxt/src/runtime/constants.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,3 @@
22
* @internal Gets access to the user within the application. This is a symbol to keep it private for the moment.
33
*/
44
export const UserSymbol = Symbol('user')
5-
6-
// MUST be named `__session` to be kept in Firebase context, therefore this name is hardcoded
7-
// https://firebase.google.com/docs/hosting/manage-cache#using_cookies
8-
export const AUTH_COOKIE_NAME = '__session'

playground/functions/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
},
1616
"main": "lib/index.js",
1717
"dependencies": {
18-
"firebase-admin": "^11.3.0",
19-
"firebase-functions": "^4.1.0"
18+
"firebase-admin": "^11.5.0",
19+
"firebase-functions": "^4.2.1"
2020
},
2121
"devDependencies": {
2222
"@typescript-eslint/eslint-plugin": "^5.53.0",

0 commit comments

Comments
 (0)