授權和完整性

建構任何公開的應用程式時,保護儲存在系統中的資料至關重要。針對 LLM,您必須進行額外調查,確保模型只會存取應存取的資料、工具呼叫的範疇是將 LLM 的適當範圍限定於叫用 LLM 的使用者,且只能透過通過驗證的用戶端應用程式叫用流程。

Firebase Genkit 提供管理授權政策和背景資訊的機制。針對在 Cloud Functions for Firebase 上執行的流程,開發人員必須提供驗證政策,或是明確確認缺少政策。針對非函式流程,您也能管理及設定驗證作業,但需要進行更多手動整合。

基本流程授權

所有流程都能在其設定中定義 authPolicy。驗證政策是一種函式,用來測試是否符合特定條件 (由您定義),如果任何測試失敗,就會擲回例外狀況。 如果設定了這個欄位,該欄位會在叫用流程前執行:

import { defineFlow, runFlow } from '@genkit-ai/flow';

export const selfSummaryFlow = defineFlow(
  {
    name: 'selfSummaryFlow',
    inputSchema: z.object({uid: z.string()}),
    outputSchema: z.string(),
    authPolicy: (auth, input) => {
      if (!auth) {
        throw new Error('Authorization required.');
      }
      if (input.uid !== auth.uid) {
        throw new Error('You may only summarize your own profile data.');
      }
    }
  },
  async (input) => { ... });

執行這個流程時,您必須使用 withLocalAuthContext 提供驗證物件,否則會收到錯誤訊息:

// Error: Authorization required.
await runFlow(selfSummaryFlow, { uid: 'abc-def' });

// Error: You may only summarize your own profile data.
await runFlow(
  selfSummaryFlow,
  { uid: 'abc-def' },
  {
    withLocalAuthContext: { uid: 'hij-klm' },
  }
);

// Success
await runFlow(
  selfSummaryFlow,
  { uid: 'abc-def' },
  {
    withLocalAuthContext: { uid: 'abc-def' },
  }
);

以 Genkit Development UI 執行時,您可以在「Auth JSON」分頁中輸入 JSON 來傳送驗證物件:{"uid": "abc-def"}

您也可以在流程內隨時呼叫 getFlowAuth() 來擷取流程的驗證內容,包括在資料流叫用的函式中:

import { getFlowAuth, defineFlow } from '@genkit-ai/flow';

async function readDatabase(uid: string) {
  if (getFlowAuth().admin) {
    // Do something special if the user is an admin:
    ...
  } else {
    // Otherwise, use the `uid` variable to retrieve the relevant document
    ...
  }
}

export const selfSummaryFlow = defineFlow(
  {
    name: 'selfSummaryFlow',
    inputSchema: z.object({uid: z.string()}),
    outputSchema: z.string(),
    authPolicy: ...
  },
  async (input) => {
    ...
    await readDatabase(input.uid);
  });

使用 Genkit 開發人員工具測試流程時,您可以在 UI 或指令列中加上 --auth 旗標,來指定這個驗證物件:

genkit flow:run selfSummaryFlow '{"uid": "abc-def"}' --auth '{"uid": "abc-def"}'

Cloud Functions for Firebase 整合

Firebase 外掛程式能夠與 Firebase Auth / Google Cloud Identity Platform 輕鬆整合,並且內建 Firebase App Check 支援。

授權

Firebase 外掛程式提供的 onFlow() 包裝函式會與 Cloud Functions for Firebase 用戶端 SDK 原生搭配運作。使用 SDK 時,只要應用程式用戶端也使用 Firebase 驗證 SDK,系統就會自動納入 Firebase 驗證標頭。您可以利用 Firebase 驗證來保護以 onFlow() 定義的流程:

import {firebaseAuth} from "@genkit-ai/firebase/auth";
import {onFlow} from "@genkit-ai/firebase/functions";

export const selfSummaryFlow = onFlow({
    name: "selfSummaryFlow",
    inputSchema: z.string(),
    outputSchema: z.string(),
    authPolicy: firebaseAuth((user) => {
      if (!user.email_verified && !user.admin) {
        throw new Error("Email not verified");
      }
    }),
  }, (subject) => {...})

使用 Firebase 驗證外掛程式時,系統會以 DecodedIdToken 傳回 user,您隨時可以透過 getFlowAuth() 擷取這個物件,如上所述。在開發期間執行這個流程時,您必須以相同方式傳遞使用者物件:

genkit flow:run selfSummaryFlow '{"uid": "abc-def"}' --auth '{"admin": true}'

根據預設,Firebase 驗證外掛程式會要求用戶端傳送驗證標頭,但如果您想允許以特殊方式對已驗證使用者進行未經驗證的存取權 (例如向上銷售功能),則可設定如下的政策:

authPolicy: firebaseAuth((user) => {
  if (user && !user.email_verified) {
    throw new Error("Logged in users must have verified emails");
  }
}, {required: false}),

每當您向更廣泛的網際網路公開 Cloud 函式時,請務必使用特定授權機制來保護您的資料和客戶資料。即便如此,有時您還需要部署 Cloud 函式,而不進行以程式碼為基礎的授權檢查 (例如,您的函式無法呼叫世界呼叫,而是受到 Cloud IAM 保護)。使用 onFlow() 時,一律必須使用 authPolicy 欄位,但您可以使用 noAuth() 函式,指出您要進行授權檢查的程式庫:

import {onFlow, noAuth} from "@genkit-ai/firebase/functions";

export const selfSummaryFlow = onFlow({
    name: "selfSummaryFlow",
    inputSchema: z.string(),
    outputSchema: z.string(),
    // WARNING: Only do this if you have some other gatekeeping in place, like
    // Cloud IAM!
    authPolicy: noAuth(),
  }, (subject) => {...})

用戶端完整性

自行進行驗證是保護應用程式的絕佳方式,但也請務必確保只有用戶端應用程式會呼叫您的函式。Genkit 的 Firebase 外掛程式提供對 Firebase App Check 的一流支援。只要將下列設定選項新增至 onFlow() 即可:

import {onFlow} from "@genkit-ai/firebase/functions";

export const selfSummaryFlow = onFlow({
    name: "selfSummaryFlow",
    inputSchema: z.string(),
    outputSchema: z.string(),

    // These two fields for app check. The consumeAppCheckToken option is for
    // replay protection, and requires additional client configuration. See the
    // App Check docs.
    enforceAppCheck: true,
    consumeAppCheckToken: true,

    authPolicy: ...,
  }, (subject) => {...})

非 Firebase HTTP 授權

將流程部署至 Cloud Functions for Firebase 以外的伺服器結構定義時,您需要在原生流程之外自行設定授權檢查。您可以採用兩種方法:

  1. 請使用您偏好的伺服器架構,並如上所述,透過 runFlow() 傳遞驗證內容。

  2. 使用內建 startFlowsServer(),並在流程設定中提供 Express 中介軟體:

    export const selfSummaryFlow = defineFlow(
    {
      name: 'selfSummaryFlow',
      inputSchema: z.object({uid: z.string()}),
      outputSchema: z.string(),
      middleware: [
        (req, res, next) => {
          const token = req.headers['authorization'];
          const user = yourVerificationLibrary(token);
    
          // This is what will get passed to your authPolicy
          req.auth = user;
          next();
        }
      ],
      authPolicy: (auth, input) => {
        if (!auth) {
          throw new Error('Authorization required.');
        }
        if (input.uid !== auth.uid) {
          throw new Error('You may only summarize your own profile data.');
        }
      }
    },
    async (input) => { ... });
    
    startFlowsServer();  // This will register the middleware
    

    如要進一步瞭解如何使用 Express,請參閱 Cloud Run 操作說明。

請注意,如果選擇 (1),runFlow() 就會忽略 middleware 設定選項。