التفويض والتكامل

عند إنشاء أي تطبيق موجه للجمهور، من المهم جدًا حماية البيانات المخزّنة في نظامك. في ما يتعلّق بالنماذج اللغوية الكبيرة، يجب توخي الحذر الشديد لضمان أنّ النموذج لا يصل إلا إلى البيانات التي يجب الوصول إليها، وأنّ طلبات أداة الربط تُحدَّد نطاقها بشكلٍ صحيح للمستخدم الذي يستدعي النموذج اللغوي الكبير، وأنّ عملية الاستدعاء تتم فقط من خلال تطبيقات العملاء التي تم التحقّق منها.

يوفّر Firebase Genkit آليات لإدارة سياسات التفويض و السياقات. بالنسبة إلى عمليات الربط التي تعمل على "وظائف السحابة الإلكترونية لبرنامج Firebase"، على المطوّرين تقديم سياسة مصادقة أو الاعتراف صراحةً بعدم توفّر سياسة. بالنسبة إلى عمليات المعالجة التي لا تستخدم Functions، يمكن أيضًا إدارة المصادقة وإعدادها، ولكن يتطلب ذلك مزيدًا من الدمج اليدوي.

تفويض المسار الأساسي

يمكن لجميع مسارات الإحالة الناجحة تحديد authPolicy في إعداداتها. سياسة المصادقة هي دالة تختبر ما إذا تم استيفاء معايير معيّنة (تحدّدها أنت)، وتُرسِل استثناءً في حال تعذّر إجراء أي اختبار. في حال ضبط هذا الحقل، يتم تنفيذه قبل استدعاء العملية:

import { genkit, z } from 'genkit';

const ai = genkit({ ... });

export const selfSummaryFlow = ai.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) => {
    // Flow logic here...
  }
);

عند تنفيذ هذه العملية، يجب تقديم عنصر مصادقة باستخدام withLocalAuthContext وإلا ستتلقّى رسالة خطأ:

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

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

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

عند التشغيل باستخدام واجهة مستخدم تطوير Genkit، يمكنك تمرير عنصر Auth من خلال إدخال ملف JSON في علامة التبويب "Auth JSON": {"uid": "abc-def"}.

يمكنك أيضًا استرداد سياق المصادقة للمسار في أي وقت ضمن المسار من خلال استدعاء getFlowAuth()، بما في ذلك الدوال التي يستدعيها المسار:

import { genkit, z } from 'genkit';

const ai = genkit({ ... });;

async function readDatabase(uid: string) {
  const auth = ai.getAuthContext();
  if (auth?.admin) {
    // Do something special if the user is an admin
  } else {
    // Otherwise, use the `uid` variable to retrieve the relevant document
  }
}

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

عند اختبار عمليات التنقّل باستخدام أدوات المطوّرين في Genkit، يمكنك تحديد عنصر auth هذا في واجهة المستخدم أو في سطر الأوامر باستخدام العلامة --auth:

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

دمج وظائف السحابة الإلكترونية لبرنامج Firebase

يقدّم المكوّن الإضافي لـ Firebase عملية دمج ملائمة مع "مصادقة Firebase" أو Google Cloud Identity Platform، بالإضافة إلى إتاحة ميزة "فحص التطبيقات من Firebase" المضمّنة.

التفويض

يعمل الغلاف onFlow() الذي يوفّره المكوّن الإضافي Firebase بشكلٍ أصلي مع حِزم تطوير البرامج (SDK) الخاصة بالعملاء في Cloud Functions لمنصّة Firebase. عند استخدام حزمة تطوير البرامج (SDK)، سيتم تلقائيًا تضمين عنوان Firebase Auth ما دام حزمة تطوير البرامج (SDK) لـ Firebase Auth قيد الاستخدام أيضًا في برنامج تشغيل تطبيقك. يمكنك استخدام Firebase Auth لحماية مسارات المستخدمين المحدّدة باستخدام onFlow():

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

const ai = genkit({ ... });;

export const selfSummaryFlow = onFlow(
  ai,
  {
    name: 'selfSummaryFlow',
    inputSchema: z.string(),
    outputSchema: z.string(),
    authPolicy: firebaseAuth((user) => {
      if (!user.email_verified && !user.admin) {
        throw new Error('Email not verified');
      }
    }),
  },
  async (input) => {
        // Flow logic here...
  }
);

عند استخدام المكوّن الإضافي Firebase Auth، سيتم عرض user على أنّه DecodedIdToken. يمكنك استرداد هذا العنصر في أي وقت من خلال getFlowAuth() كما هو موضّح أعلاه. عند تنفيذ هذا المسار أثناء التطوير، عليك تمرير عنصر المستخدم بالطريقة نفسها:

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

يتطلّب المكوّن الإضافي Firebase Auth تلقائيًا أن يُرسِل العميل عنوان المصادقة، ولكن في الحالات التي تريد فيها السماح بالوصول غير المعتمَد من خلال معالجة خاصة للمستخدمين المعتمَدين (مثل ميزات البيع الإضافي)، يمكنك ضبط السياسة على النحو التالي:

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

عند إتاحة إحدى وظائف Cloud على الإنترنت بشكل عام، من المهم جدًا استخدام نوع من آلية التفويض لحماية بياناتك وبيانات عملائك. ومع ذلك، هناك أوقات تحتاج فيها إلى نشر دالة Cloud بدون عمليات تحقّق من التفويض المستندة إلى الرموز البرمجية (على سبيل المثال، دالتك غير قابلة للاتّصال من جميع المستخدمين، بل محمية بدلاً من ذلك من خلال إدارة الهوية وإمكانية الوصول في Cloud). يكون الحقل authPolicy مطلوبًا دائمًا عند استخدام onFlow()، ولكن يمكنك إعلام المكتبة بأنّك ستتجاهل عمليات التحقّق من التفويض باستخدام الدالة noAuth():

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

export const selfSummaryFlow = onFlow(
  ai,
  {
    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(),
  },
  async (input) => {
        // Flow logic here...
  }
);

سلامة العميل

تساهم المصادقة وحدها في حماية تطبيقك، ولكن من المهم أيضًا ضمان أن تطبيقات العملاء فقط هي التي تستدعي وظائفك. يتضمّن المكوّن الإضافي Firebase لـ genkit دعمًا من الدرجة الأولى لميزة فحص التطبيقات من Firebase. ما عليك سوى إضافة خيارات الإعداد التالية إلى onFlow():

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

export const selfSummaryFlow = onFlow(
  ai,
  {
    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: ...,
  },
  async (input) => {
        // Flow logic here...
  }
);

تفويض HTTP غير التابع لخدمة Firebase

عند نشر عمليات سير العمل في سياق خادم خارج Cloud Functions لأجل Firebase، ستحتاج إلى طريقة لإعداد عمليات التحقّق من التفويض الخاصة بك إلى جانب عمليات سير العمل الأصلية. ويكون أمامك خياران:

  1. استخدِم إطار عمل الخادم الذي تريده، واضبط سياق المصادقة من خلال طلب مسار المعالجة كما هو موضّح أعلاه.

  2. استخدِم startFlowsServer() المضمّن وقدِّم الوسيط Express في إعدادات flow:

    import { genkit, z } from 'genkit';
    
    const ai = genkit({ ... });;
    
    export const selfSummaryFlow = ai.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);
    
            // Pass auth information to the flow
            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) => {
        // Flow logic here...
      }
    );
    
    ai.startFlowServer({
      flows: [selfSummaryFlow],
    });  // Registers the middleware
    

    لمزيد من المعلومات عن استخدام Express، اطّلِع على تعليمات Cloud Run.

يُرجى العلم أنّه في حال اختيار (1)، سيتم تجاهل خيار الضبط middleware عند استدعاء العملية مباشرةً.