Firebase 云函数 Appcheck for https.onRequest

dee*_*k n 8 firebase google-cloud-functions firebase-app-check

根据文档,我们可以添加 appcheck,如下所示,

exports.yourCallableFunction = functions.https.onCall((data, context) => {
  // context.app will be undefined if the request doesn't include a valid
  // App Check token.
  if (context.app == undefined) {
    throw new functions.https.HttpsError(
        'failed-precondition',
        'The function must be called from an App Check verified app.')
  }
});
Run Code Online (Sandbox Code Playgroud)

我现在的问题是如何为以下场景添加应用程序检查?

exports.date = functions.https.onRequest((req, res) => {

});
Run Code Online (Sandbox Code Playgroud)

use*_*025 7

在客户端中,从 Firebase 获取 appCheck 令牌。将其在标头中发送到您的函数。从 req 对象的标头获取令牌。使用 firebase-admin 验证令牌。我将在下面包含客户端的文档,然后是我如何使用 Apollo 客户端 graphql 在客户端实现它的要点。然后我将包含后端的文档,然后是我如何实现后端的要点,再次使用 Apollo。

客户端(来自文档):

const { initializeAppCheck, getToken } = require('firebase/app-check');

const appCheck = initializeAppCheck(
    app,
    { provider: provider } // ReCaptchaV3Provider or CustomProvider
);

const callApiWithAppCheckExample = async () => {
  let appCheckTokenResponse;
  try {
      appCheckTokenResponse = await getToken(appCheck, /* forceRefresh= */ false);
  } catch (err) {
      // Handle any errors if the token was not retrieved.
      return;
  }

  // Include the App Check token with requests to your server.
  const apiResponse = await fetch('https://yourbackend.example.com/yourApiEndpoint', {
      headers: {
          'X-Firebase-AppCheck': appCheckTokenResponse.token,
      }
  });

  // Handle response from your backend.
}; 
Run Code Online (Sandbox Code Playgroud)

客户端(我的实现要点)

import { setContext } from "@apollo/client/link/context";
import { app } from '../firebase/setup';
import { initializeAppCheck, ReCaptchaV3Provider, getToken } from "firebase/app-check"

let appCheck
let appCheckTokenResponse

const getAppCheckToken = async () => {
  const appCheckTokenResponsePromise = await getToken(appCheck, /* forceRefresh= */ false)
  appCheckTokenResponse = appCheckTokenResponsePromise
}

const authLink = setContext(async (_, { headers }) => {
  if (typeof window !== "undefined" && process.env.NEXT_PUBLIC_ENV === 'production') {
    appCheck = initializeAppCheck(app, {
      provider: new ReCaptchaV3Provider('my_public_key_from_recaptcha_V3'),
      isTokenAutoRefreshEnabled: true
    })
    await getAppCheckToken()
  }

  return {
    headers: {
      ...headers,
      'X-Firebase-AppCheck': appCheckTokenResponse?.token,
    },
  }
})
Run Code Online (Sandbox Code Playgroud)

后端/服务器(来自文档)

const express = require('express');
const app = express();

const firebaseAdmin = require('firebase-admin');
const firebaseApp = firebaseAdmin.initializeApp();

const appCheckVerification = async (req, res, next) => {
    const appCheckToken = req.header('X-Firebase-AppCheck');

    if (!appCheckToken) {
        res.status(401);
        return next('Unauthorized');
    }

    try {
        const appCheckClaims = await firebaseAdmin.appCheck().verifyToken(appCheckToken);

        // If verifyToken() succeeds, continue with the next middleware
        // function in the stack.
        return next();
    } catch (err) {
        res.status(401);
        return next('Unauthorized');
    }
}

app.get('/yourApiEndpoint', [appCheckVerification], (req, res) => {
    // Handle request.
});
Run Code Online (Sandbox Code Playgroud)

后端/服务器(我的实现要点)

import { https } from 'firebase-functions'
import gqlServer from './graphql/server'
const functions = require('firebase-functions')

const env = process.env.ENV || functions.config().config.env

const server = gqlServer()

const api = https.onRequest((req, res) => {
    server(req, res)
})

export { api }

. . .


import * as admin from 'firebase-admin';
const functions = require('firebase-functions');

const env = process.env.ENV || functions.config().config.env

admin.initializeApp()


appCheckVerification = async (req: any, res: any) => {
  const appCheckToken = req.header('X-Firebase-AppCheck')
  if (!appCheckToken) {
    return false
  }

  try {
    const appCheckClaims = await admin.appCheck().verifyToken(appCheckToken);
    return true
  } catch (error) {
    console.error(error)
    return false
  }
 }

. . .


const apolloServer = new ApolloServer({
  introspection: isDevelopment,
  typeDefs: schema,
  resolvers,
  context: async ({ req, res }) => {
            
    if (!isDevelopment && !isTest) {
      const appCheckVerification = await appCheckVerification(req, res)
        if (!appCheckVerification) throw Error('Something went wrong with verification')
 }
return { req, res, }
}
Run Code Online (Sandbox Code Playgroud)


Fra*_*len 0

如果您在 Cloud Functions 中强制执行应用程序检查,它将仅允许来自项目中注册的应用程序的调用。

不过,我不确定这是否足以满足您的用例,因为我怀疑您可以提供网络挂钩的大多数应用程序都将实现应用程序证明 - 这就是应用程序检查识别有效请求的方式。

  • 拒接电话也需要付费吗? (2认同)