Otorisasi dan integritas

Saat membangun aplikasi yang dapat diakses oleh publik, Anda harus melindungi data yang disimpan di sistem Anda. Jika menyangkut LLM, ketekunan ekstra untuk memastikan bahwa model hanya mengakses data yang seharusnya, alat memanggil tercakup dengan benar ke pengguna yang memanggil LLM, dan alur dipanggil hanya oleh aplikasi klien terverifikasi.

Firebase Genkit menyediakan mekanisme untuk mengelola kebijakan otorisasi dan konteks tambahan. Untuk alur yang berjalan di Cloud Functions for Firebase, developer menyediakan kebijakan autentikasi atau secara eksplisit mengakui kurangnya satu. Untuk alur non-Fungsi, autentikasi juga dapat dikelola dan ditetapkan, tetapi memerlukan sedikit lebih banyak integrasi manual.

Otorisasi alur dasar

Semua flow dapat menentukan authPolicy dalam konfigurasinya. Kebijakan autentikasi adalah fungsi yang menguji apakah kriteria tertentu (ditentukan oleh Anda) terpenuhi, dan menampilkan pengecualian jika ada pengujian yang gagal. Jika kolom ini disetel, kolom ini akan dieksekusi sebelum flow dipanggil:

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

Saat menjalankan alur ini, Anda harus menyediakan objek autentikasi menggunakan withLocalAuthContext atau Anda akan menerima 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' },
  }
);

Saat menjalankan Genkit Development UI, Anda dapat meneruskan objek Auth dengan memasukkan JSON di "Auth JSON" tab: {"uid": "abc-def"}.

Anda juga dapat mengambil konteks autentikasi untuk flow kapan saja di dalam flow dengan memanggil getFlowAuth(), termasuk dalam fungsi yang dipanggil oleh flow:

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

Saat menguji alur dengan alat dev Genkit, Anda dapat menentukan autentikasi ini di UI, atau di command line dengan tanda --auth:

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

Integrasi Cloud Functions for Firebase

Plugin Firebase menyediakan integrasi yang mudah dengan Firebase Auth / Google Cloud Identity Platform serta dukungan Firebase App Check bawaan.

Otorisasi

Wrapper onFlow() yang disediakan oleh plugin Firebase berfungsi secara native dengan Cloud Functions for Firebase SDK klien. Saat menggunakan SDK, header Firebase Auth akan otomatis disertakan sebagai selama klien aplikasi Anda juga menggunakan Firebase Auth SDK. Anda dapat menggunakan Firebase Auth untuk melindungi alur yang ditentukan dengan 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) => {...})

Saat menggunakan plugin Firebase Auth, user akan ditampilkan sebagai DecodeIdToken. Anda selalu dapat mengambil objek ini kapan saja melalui getFlowAuth() sebagaimana disebutkan di atas. Saat menjalankan alur ini selama pengembangan, Anda akan meneruskan objek pengguna dengan cara yang sama:

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

Secara default, plugin Firebase Auth mengharuskan header autentikasi dikirim oleh tetapi jika Anda ingin mengizinkan akses yang tidak terotentikasi dengan untuk pengguna yang diautentikasi (misalnya, fitur upselling), maka Anda dapat konfigurasikan kebijakan seperti berikut:

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

Setiap kali Anda mengekspos Cloud Function ke internet yang lebih luas, sangat penting penting bahwa Anda menggunakan semacam mekanisme otorisasi untuk melindungi data Anda dan data pelanggan Anda. Meskipun demikian, ada kalanya Anda perlu men-deploy Cloud Function tanpa pemeriksaan otorisasi berbasis kode (misalnya, Function Anda tidak dapat dipanggil secara global, tetapi dilindungi oleh Cloud IAM). Tujuan Kolom authPolicy selalu wajib ada saat menggunakan onFlow(), tetapi Anda dapat menunjukkan ke perpustakaan bahwa Anda tidak melakukan pemeriksaan otorisasi dengan menggunakan Fungsi 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) => {...})

Integritas klien

Autentikasi sendiri sangat bermanfaat untuk melindungi aplikasi Anda. Tapi itu juga penting untuk memastikan bahwa hanya aplikasi klien yang memanggil fungsi Anda. Tujuan Plugin Firebase untuk genkit menyertakan dukungan terbaik untuk Firebase App Check. Cukup tambahkan opsi konfigurasi berikut ke onFlow() Anda:

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

Otorisasi HTTP non-Firebase

Saat men-deploy flow ke konteks server di luar Cloud Functions untuk Firebase, Anda mungkin ingin memiliki cara untuk menyiapkan pemeriksaan otorisasi Anda sendiri di sepanjang alur native. Anda memiliki dua opsi:

  1. Gunakan kerangka kerja server apa pun yang Anda suka, dan teruskan konteks auth melalui runFlow() seperti yang disebutkan di atas.

  2. Gunakan startFlowsServer() bawaan dan sediakan middleware Express di flow config:

    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
    

    Untuk informasi selengkapnya tentang penggunaan Express, lihat Cloud Run petunjuk.

Perhatikan, jika Anda menggunakan (1), opsi konfigurasi middleware akan diabaikan oleh runFlow().