Yetkilendirme ve bütünlük

Herkese açık bir uygulama geliştirirken sisteminizde depolanan verilerin korunması son derece önemlidir. LLM'ler söz konusu olduğunda, modelin yalnızca olması gereken verilere eriştiğinden, araç çağrılarının LLM'yi çağıran kullanıcıya düzgün bir şekilde odaklandığından ve akışın yalnızca doğrulanmış istemci uygulamaları tarafından çağrıldığından emin olmak için daha fazla özen gösterilmesi gerekir.

Firebase Genkit, yetkilendirme politikalarını ve bağlamları yönetmek için mekanizmalar sağlar. Cloud Functions for Firebase'de çalışan akışlar için geliştiricilerin bir kimlik doğrulama politikası sağlaması veya eksik olduğunu açıkça onaylaması gerekir. İşlev dışı akışlarda kimlik doğrulama da yönetilebilir ve ayarlanabilir ancak biraz daha manuel entegrasyon gerektirir.

Temel akış yetkilendirmesi

Tüm akışlar, yapılandırmalarında bir authPolicy tanımlayabilir. Yetkilendirme politikası, belirli ölçütlerin (sizin tarafınızdan tanımlanan) karşılanıp karşılanmadığını test eden ve test başarısız olursa istisna oluşturan bir işlevdir. Bu alan ayarlanırsa akış çağrılmadan önce yürütülür:

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

Bu akışı yürütürken withLocalAuthContext aracılığıyla bir kimlik doğrulama nesnesi sağlamanız gerekir, aksi takdirde hata alırsınız:

// 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 ile çalıştırırken "Auth JSON" sekmesine JSON yazarak Auth nesnesini geçirebilirsiniz: {"uid": "abc-def"}.

Ayrıca akış tarafından çağrılan işlevler dahil olmak üzere getFlowAuth() yöntemini çağırarak akış içinde istediğiniz zaman akış için yetkilendirme bağlamını alabilirsiniz:

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 geliştirme araçlarıyla akışları test ederken bu kimlik doğrulama nesnesini kullanıcı arayüzünde veya komut satırında --auth işaretiyle belirtebilirsiniz:

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

Cloud Functions for Firebase entegrasyonu

Firebase eklentisi, yerleşik Firebase Uygulama Kontrolü desteğinin yanı sıra Firebase Auth / Google Cloud Identity Platform ile kolay entegrasyon sunar.

Yetkilendirme

Firebase eklentisi tarafından sağlanan onFlow() sarmalayıcı, Cloud Functions for Firebase istemci SDK'larıyla yerel olarak çalışır. SDK'yı kullanırken, uygulama istemciniz de Firebase Auth SDK'yı kullandığı sürece Firebase Auth başlığı otomatik olarak dahil edilecektir. onFlow() ile tanımlanan akışlarınızı korumak için Firebase Auth'u kullanabilirsiniz:

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 Auth eklentisi kullanılırken user, DecodedIdToken olarak döndürülür. Bu nesneyi yukarıda belirtildiği gibi getFlowAuth() aracılığıyla istediğiniz zaman alabilirsiniz. Geliştirme sırasında bu akışı çalıştırırken kullanıcı nesnesini aynı şekilde geçirirsiniz:

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

Varsayılan olarak Firebase Auth eklentisi kimlik doğrulama üstbilgisinin istemci tarafından gönderilmesini gerektirir. Ancak kimliği doğrulanmış kullanıcılar için özel işleme (ör. üst satış özellikleri) ile kimlik doğrulamasız erişime izin vermek istediğiniz durumlarda, politikayı aşağıdaki şekilde yapılandırabilirsiniz:

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

Bir Cloud Functions işlevini daha geniş kapsamlı internete sunduğunuzda, hem kendi verilerinizi hem de müşterilerinizin verilerini korumak için bir tür yetkilendirme mekanizması kullanmanız büyük önem taşır. Bununla birlikte, kod tabanlı yetkilendirme kontrolü olmadan bir Cloud Functions işlevini dağıtmanız gereken zamanlar olabilir (örneğin, İşleviniz dünya çapında çağrılmaz ancak Cloud IAM tarafından korunur). onFlow() kullanılırken authPolicy alanı her zaman gereklidir ancak noAuth() işlevini kullanarak kitaplığa yetkilendirme kontrollerinden vazgeçtiğinizi belirtebilirsiniz:

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

İstemci bütünlüğü

Kimlik doğrulama, uygulamanızı korumak için tek başına uzun bir yol kat eder. Ancak işlevlerinizi yalnızca istemci uygulamalarınızın çağırdığından emin olmanız da önemlidir. Genkit için Firebase eklentisi Firebase Uygulama Kontrolü için birinci sınıf destek içerir. Aşağıdaki yapılandırma seçeneklerini onFlow() cihazınıza eklemeniz yeterlidir:

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 dışı HTTP yetkilendirmesi

Akışları Cloud Functions for Firebase dışındaki bir sunucu bağlamına dağıtırken yerel akışların yanı sıra kendi yetkilendirme kontrollerinizi ayarlama yönteminizin olması gerekir. İki seçeneğiniz vardır:

  1. İstediğiniz sunucu çerçevesini kullanın ve kimlik doğrulama bağlamını yukarıda belirtildiği gibi runFlow() aracılığıyla iletin.

  2. Yerleşik startFlowsServer() kullanın ve akış yapılandırmasında Express ara katman yazılımı sağlayın:

    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'i kullanma hakkında daha fazla bilgi için Cloud Run talimatlarına bakın.

(1) ile devam ederseniz middleware yapılandırma seçeneğinin runFlow() tarafından yok sayılacağını lütfen unutmayın.