Yetkilendirme ve bütünlük

Herkese açık bir uygulama oluştururken sisteminizde depolanan verileri korumak 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ı kapsamına uygun şekilde ayarlandığından ve akışın yalnızca doğrulanmış istemci uygulamaları tarafından çağrıldığından emin olmak için ekstra özen gerekir.

Firebase Genkit, yetkilendirme politikalarını ve bağlamları yönetmek için kullanılan mekanizmalar sunar. Cloud Functions for Firebase'de çalışan akışlarda geliştiricilerin yetkilendirme politikası sağlaması veya yetkilendirme politikası olmadığını açıkça kabul etmesi gerekir. Fonksiyon dışı akışlar için kimlik doğrulama da yönetilebilir ve ayarlanabilir ancak biraz daha fazla manuel entegrasyon gerektirir.

Temel akış yetkilendirmesi

Tüm akışlar, yapılandırmalarında authPolicy tanımlayabilir. Yetkilendirme politikası, belirli ölçütlerin (sizin tarafınızdan tanımlanan) karşılanıp karşılanmadığını test eden ve herhangi bir test başarısız olursa istisna yapan 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 kullanarak 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 Geliştirme kullanıcı arayüzüyle çalışırken, "Auth JSON" sekmesine JSON yazarak Auth nesnesini aktarabilirsiniz: {"uid": "abc-def"}.

Ayrıca, akış tarafından çağrılan işlevler de dahil olmak üzere getFlowAuth() yöntemini çağırarak akışla ilgili kimlik doğrulama bağlamını istediğiniz zaman 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ştirici araçlarıyla test akışı yapılırken 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"}'

Firebase için Cloud Functions entegrasyonu

Firebase eklentisi, Firebase Auth / Google Cloud Identity Platform ile kolay entegrasyon ve yerleşik Firebase Uygulama Kontrolü desteği sağlar.

Yetkilendirme

Firebase eklentisi tarafından sağlanan onFlow() sarmalayıcı, Cloud Functions for Firebase istemci SDK'ları ile yerel olarak çalışır. SDK kullanılırken, uygulama istemciniz Firebase Auth SDK'yı kullandığı sürece Firebase Auth başlığı otomatik olarak eklenir. 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, bir 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 iletirsiniz:

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

Firebase Auth eklentisi varsayılan olarak istemci tarafından kimlik doğrulama başlığının gönderilmesini gerektirir. Ancak kimliği doğrulanmış kullanıcılar için özel işleme ile kimliği doğrulanmamış erişime izin vermek istediğinizde (ör. upsell özellikleri) politikayı aşağıdaki gibi 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ı internette kullanıma sunduğunuzda, verilerinizi ve müşterilerinizin verilerini korumak için bir tür yetkilendirme mekanizması kullanmanız son derece önemlidir. Bununla birlikte, bir Cloud Functions işlevini kod tabanlı yetkilendirme kontrolü olmadan dağıtmanız gereken durumlar da olabilir (örneğin, İşleviniz herkes tarafından çağrılabilir ancak Cloud IAM tarafından korunur). onFlow() kullanılırken authPolicy alanı her zaman zorunludur ancak noAuth() işlevini kullanarak yetkilendirme kontrollerinden vazgeçtiğinizi kitaplığa 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 tek başına uygulamanızı korumak için oldukça faydalıdır. Ancak işlevlerinizi yalnızca istemci uygulamalarınızın çağırdığından emin olmak da önemlidir. Genkit için Firebase eklentisinde Firebase Uygulama Kontrolü için birinci sınıf destek sunulur. onFlow() cihazınıza aşağıdaki yapılandırma seçeneklerini 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ında kendi yetkilendirme kontrollerinizi oluşturabileceğiniz bir yönteme sahip olmanız 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() üzerinden 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 kullanımı 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 yoksayılacağını lütfen unutmayın.