Skip to content

Commit

Permalink
refactor(app-check): split client and server
Browse files Browse the repository at this point in the history
  • Loading branch information
posva committed Dec 13, 2022
1 parent 9e43384 commit a8546c8
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 33 deletions.
23 changes: 2 additions & 21 deletions packages/nuxt/src/runtime/app-check/plugin.server.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import type { App as FirebaseAdminApp } from 'firebase-admin/app'
import type { FirebaseApp } from 'firebase/app'
import { CustomProvider } from 'firebase/app-check'
import { VueFireAppCheck } from 'vuefire'
import { VueFireAppCheckServer } from 'vuefire/server'
import { defineNuxtPlugin, useAppConfig } from '#app'
import { defineNuxtPlugin } from '#app'

/**
* Makes AppCheck work on the server. This requires SSR and the admin SDK to be available
Expand All @@ -19,22 +17,5 @@ export default defineNuxtPlugin((nuxtApp) => {
)
}

const appConfig = useAppConfig()
const options = appConfig.vuefireOptions.appCheck!

VueFireAppCheckServer(adminApp, firebaseApp)

// This will fail if used in the server
const provider = new CustomProvider({
getToken: () =>
Promise.reject(
new Error("[VueFire]: This shouldn't be called on server.")
),
})

// injects the empty token symbol
VueFireAppCheck({
...options,
provider,
})(firebaseApp, nuxtApp.vueApp)
VueFireAppCheckServer(nuxtApp.vueApp, adminApp, firebaseApp)
})
12 changes: 5 additions & 7 deletions src/app-check/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export interface VueFireAppCheckOptions extends AppCheckOptions {
}

/**
* VueFire AppCheck Module to be added to the `VueFire` Vue plugin options.
* VueFire AppCheck Module to be added to the `VueFire` Vue plugin options. This module **is client only** and shouldn't be added on server.
*
* @example
*
Expand All @@ -47,14 +47,13 @@ export interface VueFireAppCheckOptions extends AppCheckOptions {
*/
export function VueFireAppCheck(options: VueFireAppCheckOptions) {
return (firebaseApp: FirebaseApp, app: App) => {
// TODO: copy this bit to the server and remove the isClient check
// AppCheck requires special treatment on the server
if (!isClient) return

// provide this even on the server for simplicity of usage
const token = getGlobalScope(firebaseApp, app).run(() => ref<string>())!
app.provide(AppCheckTokenInjectSymbol, token)

// AppCheck requires special treatment on the server
if (!isClient) return

if (options.debug) {
// @ts-expect-error: local override
self.FIREBASE_APPCHECK_DEBUG_TOKEN = options.debug
Expand All @@ -68,14 +67,13 @@ export function VueFireAppCheck(options: VueFireAppCheckOptions) {
}
}

// TODO: split the function above into two, one that provides the token and is used in both server and client and another one that is only used on the client

/**
* To retrieve the current app check
* @internal
*/
export const AppCheckMap = new WeakMap<FirebaseApp, AppCheck>()

// TODO: this should be available on the server too
/**
* Retrieves the Firebase App Check instance. Note this is only available on the client and will be `undefined` on the
* server.
Expand Down
18 changes: 13 additions & 5 deletions src/server/app-check.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import type { App as FirebaseAdminApp } from 'firebase-admin/app'
import { getAppCheck } from 'firebase-admin/app-check'
import { getAppCheck as getAdminAppCheck } from 'firebase-admin/app-check'
import type { FirebaseApp } from 'firebase/app'
import { CustomProvider, initializeAppCheck } from 'firebase/app-check'
import { App, ref } from 'vue-demi'
import { AppCheckMap, AppCheckTokenInjectSymbol } from '../app-check'
import { getGlobalScope } from '../globals'

/**
* Adds AppCheck using the Firebase Admin SDK. This is necessary on the Server if you have configured AppCheck on the
Expand All @@ -12,6 +15,7 @@ import { CustomProvider, initializeAppCheck } from 'firebase/app-check'
* @param param2 options
*/
export function VueFireAppCheckServer(
app: App,
adminApp: FirebaseAdminApp,
firebaseApp: FirebaseApp,
{
Expand All @@ -21,12 +25,15 @@ export function VueFireAppCheckServer(
ttlMillis?: number
} = {}
) {
const appCheck = getAppCheck(adminApp)
initializeAppCheck(firebaseApp, {
// Inject an empty token ref so the same code works on the client and server
const token = getGlobalScope(firebaseApp, app).run(() => ref<string>())!
app.provide(AppCheckTokenInjectSymbol, token)

const appCheck = initializeAppCheck(firebaseApp, {
provider: new CustomProvider({
getToken: () =>
appCheck
// NOTE: appId is checked on the server plugin
getAdminAppCheck(adminApp)
// NOTE: appId is checked on the module
.createToken(firebaseApp.options.appId!, { ttlMillis })
.then(({ token, ttlMillis: expireTimeMillis }) => ({
token,
Expand All @@ -35,4 +42,5 @@ export function VueFireAppCheckServer(
}),
isTokenAutoRefreshEnabled: false,
})
AppCheckMap.set(firebaseApp, appCheck)
}

0 comments on commit a8546c8

Please sign in to comment.