Integridad y autorización

Cuando compilas una aplicación pública, es muy importante proteger los datos almacenados en tu sistema. Cuando se trata de los LLM, es importante necesarias para garantizar que el modelo solo acceda a los datos que debería, la herramienta llama Tienen un alcance adecuado para el usuario que invoca el LLM, y se invoca el flujo. solo por aplicaciones cliente verificadas.

Firebase Genkit proporciona mecanismos para administrar las políticas de autorización y diferentes. En el caso de los flujos que se ejecutan en Cloud Functions para Firebase, para proporcionar una política de autenticación o reconocer explícitamente la falta de uno. En los flujos que no son Functions, también se puede administrar y configurar la autenticación, pero requiere una integración un poco más manual.

Autorización básica de flujo

Todos los flujos pueden definir un authPolicy en su configuración. Una política de autenticación es una función que prueba si se cumplen ciertos criterios (definidos por ti) y arroja una excepción si falla alguna prueba. Si se configura este campo, se ejecuta antes de que se invoque el flujo:

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) => { ... });

Cuando ejecutes este flujo, debes proporcionar un objeto auth usando withLocalAuthContext; de lo contrario, deberás si recibes un mensaje de error:

// 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' },
  }
);

Cuando se ejecuta con la IU de Genkit Development, puedes pasar el objeto Auth mediante ingresando JSON en el “JSON de autenticación” pestaña: {"uid": "abc-def"}.

También puedes recuperar el contexto de Auth para el flujo en cualquier momento dentro del flujo. llamando a getFlowAuth(), incluso en las funciones que invoca el flujo:

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);
  });

Cuando pruebas los flujos con las herramientas para desarrolladores de Genkit, puedes especificar esta autenticación en la IU o en la línea de comandos con la marca --auth:

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

Integración de Cloud Functions para Firebase

El complemento de Firebase proporciona una integración conveniente en Firebase Auth / Google Cloud Identity Platform, así como la compatibilidad integrada de la Verificación de aplicaciones de Firebase.

Autorización

El wrapper onFlow() que proporciona el complemento de Firebase funciona de forma nativa con el Cloud Functions para Firebase SDKs de clientes. Cuando uses el SDK, el encabezado de Firebase Auth se incluirá automáticamente como siempre que tu cliente de la app también use SDK de Firebase Auth. Puedes usar Firebase Auth para proteger los flujos definidos con 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) => {...})

Cuando uses el complemento de Firebase Auth, se mostrará user como un DecodedIdToken. Puedes recuperar este objeto en cualquier momento mediante getFlowAuth(), como se indica arriba. Cuando ejecutes este flujo durante el desarrollo, deberías pasar el objeto de la misma manera:

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

Según la configuración predeterminada, el complemento de Firebase Auth requiere que el encabezado de autenticación envíe el encabezado de autenticación pero, en los casos en que desees permitir el acceso no autenticado con para usuarios autenticados (por ejemplo, la venta de funciones), puedes configura la política de la siguiente manera:

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

Cuando expongas una Cloud Function a la Internet en general, importante que uses algún tipo de mecanismo de autorización para proteger tus datos y los datos de tus clientes. Dicho esto, hay momentos en los que necesitas para implementar una Cloud Function sin verificaciones de autorización basadas en código (por ejemplo, tu función no admite llamadas en todo el mundo, sino que está protegida por Cloud IAM). El El campo authPolicy siempre es obligatorio cuando se usa onFlow(), pero puedes le indicará a la biblioteca que renunciará a las verificaciones de autorización mediante el Función 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) => {...})

Integridad del cliente

La autenticación por sí sola ayuda a proteger tu app. Pero también importante que te asegures de que solo tus apps cliente llamen a tus funciones. El El complemento de Firebase para genkit incluye compatibilidad de primera clase con Verificación de aplicaciones de Firebase Simplemente agrega las siguientes opciones de configuración a tu 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) => {...})

Autorización HTTP que no es de Firebase

Cuando se implementan flujos en el contexto de un servidor fuera de Cloud Functions Firebase, te recomendamos tener una forma de configurar tus propias verificaciones de autorización junto con los flujos nativos. Tienes estas dos opciones:

  1. Usa el framework del servidor que desees y pasa el contexto de Auth a través de runFlow(), como se indica más arriba.

  2. Usa el startFlowsServer() integrado y proporciona middleware Express en el configuración de flujo:

    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
    

    Para obtener más información sobre cómo usar Express, consulta la documentación de Cloud Run instrucciones.

Ten en cuenta que, si eliges (1), la opción de configuración middleware runFlow() las ignorará.