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 przetwarzanie jest wywoływane tylko przez zweryfikowane aplikacje klienckie.
Firebase Genkit udostępnia mechanizmy zarządzania zasadami autoryzacji i kontekstami. Procesy działające w Firebase mogą używać wywołania zwrotnego (lub pomocnika) zasad uwierzytelniania. Firebase może też przekazywać kontekst uwierzytelniania do procesu, w którym może przeprowadzać własne kontrole. W przypadku przepływów innych niż Functions uwierzytelnianie można zarządzać i konfigurować za pomocą oprogramowania pośredniczącego.
Autoryzowanie w ramach przepływu
Procesy mogą sprawdzać autoryzację na 2 sposoby: albo mechanizm wiązania żądań (np. onCallGenkit
w przypadku Cloud Functions for Firebase lub express
) może wymuszać autoryzację, albo te platformy mogą przekazywać zasady autoryzacji do samego procesu, który ma dostęp do informacji o autoryzacji zarządzanych w ramach procesu.
import { genkit, z, UserFacingError } from 'genkit';
const ai = genkit({ ... });
export const selfSummaryFlow = ai.defineFlow( {
name: 'selfSummaryFlow',
inputSchema: z.object({ uid: z.string() }),
outputSchema: z.string(),
}, async (input, { context }) => {
if (!context.auth) {
throw new UserFacingErrorError('UNAUTHENTICATED', 'Unauthenticated');
}
if (input.uid !== context.auth.uid) {
throw new UserFacingError('PERMISSION_DENIED', 'You may only summarize your own profile data.');
}
// Flow logic here...
});
W tym przypadku wypełnienie parametru context.auth
zależy od powiązania żądania. Na przykład onCallGenkit
automatycznie wypełnia pola context.auth
(Uwierzytelnianie Firebase), context.app
(Sprawdzanie aplikacji Firebase) i context.instanceIdToken
(Komunikacja w chmurze Firebase). Gdy wywołujesz przepływ ręcznie, możesz ręcznie dodać własny kontekst uwierzytelniania.
// Error: Authorization required.
await selfSummaryFlow({ uid: 'abc-def' });
// Error: You may only summarize your own profile data.
await selfSummaryFlow.run(
{ uid: 'abc-def' },
{
context: { auth: { uid: 'hij-klm' } },
}
);
// Success
await selfSummaryFlow(
{ uid: 'abc-def' },
{
context: { auth: { uid: 'abc-def' } },
}
);
Gdy używasz 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ę ai.currentContext()
, 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.currentContext()?.auth;
// Note: the shape of context.auth depends on the provider. onCallGenkit puts
// claims information in auth.token
if (auth?.token?.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 --context
:
genkit flow:run selfSummaryFlow '{"uid": "abc-def"}' --context '{"auth": {"email_verified": true}}'
Autoryzowanie za pomocą Cloud Functions dla Firebase
Pakiety SDK Cloud Functions for Firebase obsługują Genkit, w tym integrację z Firebase Auth / Google Cloud Identity Platform, a także wbudowane sprawdzanie aplikacji Firebase.
Uwierzytelnianie użytkowników
Opakowanie onCallGenkit()
udostępniane przez bibliotekę Firebase Functions ma wbudowane wsparcie dla pakietów SDK klienta Cloud Functions dla Firebase.
Gdy używasz tych pakietów SDK, nagłówek Firebase Auth jest dołączany automatycznie, o ile klient aplikacji korzysta też z pakietu SDK Firebase Auth.
Użyj Uwierzytelniania Firebase, aby chronić przepływy zdefiniowane za pomocą:onCallGenkit()
import { genkit } from 'genkit';
import { onCallGenkit } from 'firebase-functions/https';
const ai = genkit({ ... });;
const selfSummaryFlow = ai.defineFlow({
name: 'selfSummaryFlow',
inputSchema: z.string(),
outputSchema: z.string(),
}, async (input) => {
// Flow logic here...
});
export const selfSummary = onCallGenkit({
authPolicy: (auth) => auth?.token?.['email_verified'] && auth?.token?.['admin'],
}, selfSummaryFlow);
Gdy używasz onCallGenkit
, context.auth
jest zwracany jako obiekt z uid
jako identyfikatorem użytkownika i token
jako rozszyfrowanym identyfikatorem użytkownika.
W każdej chwili możesz pobrać ten obiekt, używając wcześniej wspomnianego polecenia ai.currentContext()
. Podczas uruchamiania tego procesu na etapie programowania obiekt użytkownika jest przekazywany w taki sam sposób:
genkit flow:run selfSummaryFlow '{"uid": "abc-def"}' --context '{"auth": {"admin": true}}'
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 weryfikacji autoryzacji opartej na kodzie (np. gdy Twoja funkcja nie jest dostępna dla wszystkich, ale jest chroniona przez uprawnienia Cloud IAM).
Cloud Functions dla Firebase umożliwia to za pomocą właściwości invoker
, która kontroluje dostęp w usługach Identity and Access Management. Wartość specjalna 'private'
pozostawia ustawienie funkcji w domyślnym ustawieniu IAM, co oznacza, że tylko wywołujący z rolą wywołującego Cloud Run mogą ją wykonać. Zamiast tego możesz podać adres e-mail użytkownika lub konta usługi, któremu chcesz przyznać uprawnienia do wywołania tej funkcji.
import { onCallGenkit } from 'firebase-functions/https'
const selfSummaryFlow = ai.defineFlow({
name: 'selfSummaryFlow',
inputSchema: z.string(),
outputSchema: z.string(),
}, async (input) => {
// Flow logic here...
});
export const selfSummary = onCallGenkit({
invoker: 'private',
}, selfSummaryFlow);
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 obsługuje Sprawdzanie aplikacji Firebase. Aby to zrobić, dodaj do onCallGenkit()
te opcje konfiguracji:
import { onCallGenkit } from 'firebase-functions/https';
const selfSummaryFlow = ai.defineFlow({
name: 'selfSummaryFlow',
inputSchema: z.string(),
outputSchema: z.string(),
}, async (input) => {
// Flow logic here...
});
export const selfSummary = onCallGenkit({
// 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: ...,
}, selfSummaryFlow);
Autoryzacja HTTP spoza Firebase
Podczas wdrażania przepływów w kontekście serwera poza Cloud Functions for Firebase musisz mieć możliwość konfigurowania własnych kontroli autoryzacji obok wbudowanych przepływów.
Użyj elementu ContextProvider
, aby wypełnić wartości kontekstu, takie jak auth
, oraz podać deklaratywną zasadę lub wywołanie zwrotne zasady. Pakiet SDK Genkit udostępnia ContextProvider
, takie jak apiKey
. Wtyczki mogą też je udostępniać. Na przykład wtyczka @genkit-ai/firebase/context
udostępnia dostawcę kontekstu do weryfikowania danych logowania Firebase Auth i ich wypełniania w kontekście.
za pomocą kodu podobnego do tego, który może występować w różnych aplikacjach:
// Express app with a simple API key
import { genkit, z } from 'genkit';
const ai = genkit({ ... });;
export const selfSummaryFlow = ai.defineFlow(
{
name: 'selfSummaryFlow',
inputSchema: z.object({ uid: z.string() }),
outputSchema: z.string(),
},
async (input) => {
// Flow logic here...
}
);
Aby zabezpieczyć prostą aplikację typu „flow server”, możesz napisać:
import { apiKey } from "genkit";
import { startFlowServer, withContext } from "@genkit-ai/express";
startFlowServer({
flows: [
withContext(selfSummaryFlow, apiKey(process.env.REQUIRED_API_KEY))
],
});
Możesz też utworzyć niestandardową aplikację ekspresową, korzystając z tych samych narzędzi:
import { apiKey } from "genkit";
import * as express from "express";
import { expressHandler } from "@genkit-ai/express;
const app = express();
// Capture but don't validate the API key (or its absence)
app.post('/summary', expressHandler(selfSummaryFlow, { contextProvider: apiKey()}))
app.listen(process.env.PORT, () => {
console.log(`Listening on port ${process.env.PORT}`);
})
ContextProvider
s abstrakcyjnie obsługuje platformę internetową, dzięki czemu te narzędzia działają też w innych platformach, takich jak Next.js. Oto przykład aplikacji Firebase utworzonej w Next.js.
import { appRoute } from "@genkit-ai/express";
import { firebaseContext } from "@genkit-ai/firebase";
export const POST = appRoute(selfSummaryFlow, { contextProvider: firebaseContext })
Więcej informacji o używaniu Express znajdziesz w instrukcji Cloud Run.