التفويض والنزاهة

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

توفّر Firebase Genkit آليات لإدارة سياسات التفويض والسياقات. بالنسبة إلى التدفقات التي تعمل على Cloud Functions for Firebase، على المطوّرين تقديم سياسة مصادقة أو الإقرار صراحةً بعدم توفُّر واحدة. بالنسبة إلى التدفقات غير الدوال، يمكن إدارة المصادقة وضبطها أيضًا، ولكن تتطلب المزيد من الدمج اليدوي.

تفويض التدفّق الأساسي

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

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

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

// 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، يمكنك تمرير كائن Auth من خلال إدخال JSON في علامة التبويب "Auth JSON": {"uid": "abc-def"}.

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

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، يمكنك تحديد كائن المصادقة هذا في واجهة المستخدم أو في سطر الأوامر باستخدام العلامة --auth:

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

الدوال السحابية لتكامل Firebase

يوفّر مكوّن Firebase الإضافي تكاملاً ملائمًا مع مصادقة Firebase وGoogle Cloud Identity Platform، بالإضافة إلى إمكانية الدمج مع أداة Firebase App Check.

التفويض

يعمل برنامج تضمين onFlow() الذي يوفّره المكوّن الإضافي لمنصة Firebase بشكل مضمّن مع حِزم تطوير البرامج (SDK) لعملاء Firebase من خلال وظائف السحابة الإلكترونية. عند استخدام حزمة SDK، سيتم تضمين عنوان مصادقة Firebase تلقائيًا ما دام عميل التطبيق يستخدم حزمة SDK لمصادقة Firebase أيضًا. يمكنك استخدام مصادقة Firebase لحماية المسارات المحدَّدة باستخدام 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) => {...})

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

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

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

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

عندما تعرض دالة Cloud على نطاق واسع على الإنترنت، من المهم جدًا أن تستخدم نوعًا من آليات التفويض لحماية بياناتك وبيانات عملائك. ومع ذلك، قد تحتاج في بعض الأحيان إلى نشر دالة Cloud بدون عمليات فحص تفويض مستندة إلى الرمز (على سبيل المثال، لا يمكن تسمية دالتك على الإطلاق، ولكنها تحميها خدمة Cloud IAM). يكون الحقل authPolicy مطلوبًا دائمًا عند استخدام "onFlow()"، ولكن يمكنك إعلام المكتبة بأنّك ستتخلّى عن عمليات التحقق من التفويض باستخدام الدالة 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) => {...})

نزاهة العميل

تساهم المصادقة في حد ذاتها في حماية تطبيقك بشكل كبير، ولكن من المهم أيضًا التأكد من أنّ تطبيقات العميل فقط هي التي تستدعي وظائفك. يتضمّن مكوّن Firebase الإضافي لبرنامج genkit دعمًا من الدرجة الأولى لميزة فحص التطبيقات من Firebase. ما عليك سوى إضافة خيارات الضبط التالية إلى 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) => {...})

تفويض HTTP من غير Firebase

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

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

  2. يمكنك استخدام startFlowsServer() المضمَّنة وتوفير البرمجيات الوسيطة لـ Express في إعدادات التدفق:

    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
    

    لمزيد من المعلومات حول استخدام النسخ الاحتياطي السريع، راجع تعليمات التشغيل السحابي.

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