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

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

توفّر Firebase Genkit آليات لإدارة سياسات التفويض وسياقاته. بالنسبة إلى التدفقات التي تعمل على وظائف السحابة الإلكترونية لبرنامج 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 dev، يمكنك تحديد كائن المصادقة هذا في واجهة المستخدم، أو في سطر الأوامر باستخدام علامة --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 for 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 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 Functions في 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
    

    لمزيد من المعلومات حول استخدام Express، يُرجى الاطّلاع على تعليمات تشغيل Cloud.

يُرجى ملاحظة أنّه في حال استخدام القيمة (1)، سيتم تجاهل خيار الإعداد middleware من قِبل runFlow().