Podczas tworzenia aplikacji publicznych bardzo ważne jest zabezpieczenie danych przechowywanych w systemie. W przypadku LLM należy zachować szczególną ostrożność, aby mieć pewność, że model ma dostęp tylko do danych, do których powinien, że wywołania narzędzi są odpowiednio ograniczone do użytkownika wywołującego LLM, oraz że przepływ jest wywoływany tylko przez zweryfikowane aplikacje klienckie.
Firebase Genkit udostępnia mechanizmy do zarządzania zasadami i kontekstami autoryzacji. W przypadku przepływów działających w Cloud Functions dla Firebase programi muszą podać zasadę uwierzytelniania lub wyraźnie potwierdzić brak takiej zasady. W przypadku procesów innych niż Functions można też zarządzać uwierzytelnianiem i je konfigurować, ale wymaga to nieco więcej ręcznej integracji.
Podstawowy przepływ autoryzacji
Wszystkie przepływy mogą definiować authPolicy
w swojej konfiguracji. Zasady uwierzytelniania to funkcja, która sprawdza, czy są spełnione określone przez Ciebie kryteria, i wyrzuca wyjątek, jeśli którykolwiek z testów zakończy się niepowodzeniem.
Jeśli to pole jest ustawione, jest wykonywane przed wywołaniem przepływu:
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...
}
);
Podczas wykonywania tego procesu musisz podać obiekt uwierzytelniania za pomocą parametru withLocalAuthContext
. W przeciwnym razie wystąpi błąd:
// 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' },
}
);
Podczas uruchamiania za pomocą interfejsu programistycznego Genkit możesz przekazać obiekt Auth, wpisując JSON na karcie „Auth JSON”: {"uid": "abc-def"}
.
Możesz też w dowolnym momencie w ramach przepływu odzyskać kontekst uwierzytelniania, wywołując funkcję getFlowAuth()
, w tym w funkcjach wywoływanych przez przepływ:
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);
}
);
Podczas testowania przepływów za pomocą narzędzi dla programistów Genkit możesz określić ten obiekt autoryzacji w interfejsie lub w wierszu poleceń za pomocą parametru --auth
:
genkit flow:run selfSummaryFlow '{"uid": "abc-def"}' --auth '{"uid": "abc-def"}'
Integracja Cloud Functions z Firebase
Wtyczka Firebase zapewnia wygodną integrację z Firebase Auth / Google Cloud Identity Platform, a także wbudowane wsparcie Sprawdzania aplikacji Firebase.
Autoryzacja
Opakowanie onFlow()
udostępniane przez wtyczkę Firebase działa natywnie z pakietami SDK klienta Cloud Functions dla Firebase.
Gdy używasz pakietu SDK, nagłówek Firebase Auth zostanie automatycznie uwzględniony, o ile klient aplikacji korzysta też z pakietu SDK Firebase Auth.
Użyj Uwierzytelniania Firebase, aby chronić przepływy zdefiniowane za pomocą: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...
}
);
Gdy używasz wtyczki Firebase Auth, user
zostanie zwrócony jako DecodedIdToken.
W każdej chwili możesz pobrać ten obiekt za pomocą funkcji getFlowAuth()
, jak opisano powyżej. Podczas uruchamiania tego procesu w trakcie tworzenia aplikacji obiekt user przekazujesz w taki sam sposób:
genkit flow:run selfSummaryFlow '{"uid": "abc-def"}' --auth '{"admin": true}'
Domyślnie wtyczka Firebase Auth wymaga, aby klient wysyłał nagłówek uwierzytelniania, ale w przypadku, gdy chcesz zezwolić na dostęp bez uwierzytelniania z uwzględnieniem specjalnego przetwarzania w przypadku uwierzytelnionych użytkowników (np. funkcji upsellingu), możesz skonfigurować zasadę w ten sposób:
authPolicy: firebaseAuth((user) => {
if (user && !user.email_verified) {
throw new Error("Logged in users must have verified emails");
}
}, {required: false}),
Gdy udostępniasz funkcję Cloud Function w internecie, musisz zadbać o ochronę swoich danych i danych klientów za pomocą odpowiedniego mechanizmu autoryzacji. Czasami jednak musisz wdrożyć funkcję Cloud Functions bez autoryzacji opartej na kodzie (np. gdy Twoja funkcja nie jest dostępna dla wszystkich, ale jest chroniona przez uprawnienia Cloud IAM). Pole authPolicy
jest zawsze wymagane podczas używania funkcji onFlow()
, ale możesz wskazać bibliotece, że rezygnujesz z sprawdzania autoryzacji, używając funkcji 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...
}
);
Integralność klienta
Uwierzytelnianie samo w sobie zapewnia dużą ochronę aplikacji, ale ważne jest też, aby tylko Twoje aplikacje klienckie wywoływały funkcje. Wtyczka Firebase dla genkit zapewnia pierwszorzędną obsługę Sprawdzania aplikacji Firebase. Wystarczy, że dodasz do onFlow()
te opcje konfiguracji:
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...
}
);
Autoryzacja HTTP spoza Firebase
Podczas wdrażania przepływów w kontekście serwera poza Cloud Functions w Firebase musisz mieć możliwość konfigurowania własnych kontroli autoryzacji obok wbudowanych przepływów. Dostępne są dwie opcje:
Użyj dowolnej ramki serwera i przekaż kontekst uwierzytelniania za pomocą wywołania przepływu, jak opisano powyżej.
Użyj wbudowanego
startFlowsServer()
i podaj oprogramowanie pośredniczące Express w konfiguracji przepływu: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
Więcej informacji o używaniu Expressa znajdziesz w instrukcji Cloud Run.
Jeśli wybierzesz opcję 1, opcja konfiguracji middleware
zostanie zignorowana, gdy przepływ zostanie wywołany bezpośrednio.