Skip to content

Commit

Permalink
feat(firebase): fallback based on user status, session cookie mode, a…
Browse files Browse the repository at this point in the history
…nd custom cookie key
  • Loading branch information
aiji42 committed Nov 22, 2021
1 parent 22f281f commit 94ba935
Showing 1 changed file with 33 additions and 17 deletions.
50 changes: 33 additions & 17 deletions src/firebase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,48 @@ import { AsyncMiddleware, Fallback } from './types'
import { FIREBASE_COOKIE_KEY } from './constants'
import { NextRequest } from 'next/server'
import { handleFallback } from './handle-fallback'
import { decodeProtectedHeader, jwtVerify, JWK, importJWK } from 'jose'
import { decodeProtectedHeader, jwtVerify, importJWK } from 'jose'
import { toJwk } from 'js-x509-utils'

export const makeFirebaseInspector = (fallback: Fallback): AsyncMiddleware => {
export const makeFirebaseInspector = (
fallback: Fallback,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
customHandler?: (payload: any) => boolean
): AsyncMiddleware => {
return async (request, event) => {
const ok = await verifyFirebaseIdToken(request)
const ok = await verifyFirebaseIdToken(request, customHandler)
if (ok) return
return handleFallback(fallback, request, event)
}
}

const JWK_ENDPOINT =
'https://www.googleapis.com/service_accounts/v1/jwk/[email protected]'

const verifyFirebaseIdToken = async (req: NextRequest): Promise<boolean> => {
const token = req.cookies[FIREBASE_COOKIE_KEY]
const verifyFirebaseIdToken = async (
req: NextRequest,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
customHandler?: (payload: any) => boolean
): Promise<boolean> => {
const cookieKey =
process.env.FORTRESS_FIREBASE_COOKIE_KEY ?? FIREBASE_COOKIE_KEY
const token = req.cookies[cookieKey]
if (!token) return false

const { keys }: { keys: JWK[] } = await fetch(JWK_ENDPOINT).then((res) =>
res.json()
)
const endpoint =
process.env.FORTRESS_FIREBASE_MODE === 'session'
? 'https://www.googleapis.com/identitytoolkit/v3/relyingparty/publicKeys'
: 'https://www.googleapis.com/robot/v1/metadata/x509/[email protected]'

try {
const keys: Record<string, string> = await fetch(endpoint).then((res) =>
res.json()
)

const { kid } = decodeProtectedHeader(token)
const jwk = keys.find((key) => key.kid === kid)
if (!jwk) return false
const { kid = '', alg } = decodeProtectedHeader(token)
const jwk = await toJwk(keys[kid], 'pem')

return jwtVerify(token, await importJWK(jwk))
.then(() => true)
.catch(() => false)
return jwtVerify(token, await importJWK({ ...jwk, alg }))
.then((res) => customHandler?.(res.payload) ?? true)
.catch(() => false)
} catch (_) {
return false
}
}

0 comments on commit 94ba935

Please sign in to comment.