Skip to main content

Auth0 AI for Genkit

This SDK provides building blocks for using Auth0 for AI Agents with Genkit. Includes a RAG Retriever for using OpenFGA, tools for implementing asynchronous user authentication, tools for getting access tokens for third-party connections, and OpenFGA-based tool authorizers. It supports:
  • A RAG Retriever for using OpenFGA
  • OpenFGA-based tool authorizer and re-ranker
npm install @auth0/ai-genkit
Below are examples that demonstrate how to integrate Auth0’s token vault and authorization flows with AI tools. You’ll see how to:
  • Use a token vault to call third-party APIs on behalf of the user
  • Use Client-Initiated Backchannel Authentication (CIBA) for consent flows
  • Apply Okta FGA authorization in Retrieval-Augmented Generation (RAG) scenarios
For more examples, click here.
Token Vault allows you to exchange refresh tokens for access tokens for third-party APIs. This is useful when you want to use a token vault (like Google, Facebook, etc.) to authenticate users and then use the access token to call the API on behalf of the user.First initialize the Token Vault Authorizer as follows:
const withGoogleAccess = auth0AI.withTokenVault({
  //this is the defaults:
  refreshToken: async (params) => {
    return context.refreshToken;
  },
  // The connection name:
  connection: "google-oauth2",
  // The scopes to request:
  scopes: ["https://www.googleapis.com/auth/calendar.freebusy"],
});
Then use the withGoogleAccess to wrap the tool and use getAccessTokenFromTokenVault from the SDK to get the access token.
import { getAccessTokenFromTokenVault } from "@auth0/ai-genkit";
import { TokenVaultError } from "@auth0/ai/interrupts";
import { addHours } from "date-fns";
import { z } from "zod";

export const checkCalendarTool = ai.defineTool(
  ...withGoogleAccess({
    name: "check_user_calendar",
    description:
      "Check user availability on a given date time on their calendar",
    inputSchema: z.object({
      date: z.coerce.date(),
    }),
    outputSchema: z.object({
      available: z.boolean(),
    }),
  },
  async ({ date }) => {
    const accessToken = getAccessTokenFromTokenVault();
    const body = JSON.stringify({
      timeMin: date,
      timeMax: addHours(date, 1),
      timeZone: "UTC",
      items: [{ id: "primary" }],
    });

    const response = await fetch(url, {
      method: "POST",
      headers: {
        Authorization: `Bearer ${accessToken}`,
        "Content-Type": "application/json",
      },
      body,
    });

    if (!response.ok) {
      if (response.status === 401) {
        throw new TokenVaultError(
          `Authorization required to access the Token Vault`
        );
      }
      throw new Error(
        `Invalid response from Google Calendar API: ${
          response.status
        } - ${await response.text()}`
      );
    }
    const busyResp = await response.json();
    return { available: busyResp.calendars.primary.busy.length === 0 };
  }
));
CIBA (Client-Initiated Backchannel Authentication) enables secure, user-in-the-loop authentication for sensitive operations. This flow allows you to request user authorization asynchronously and resume execution once authorization is granted.
const buyStockAuthorizer = auth0AI.withAsyncAuthorization({
  // A callback to retrieve the userID from tool context.
  userID: (_params, config) => {
    return config.configurable?.user_id;
  },
  // The message the user will see on the notification
  bindingMessage: async ({ qty , ticker }) => {
    return `Confirm the purchase of ${qty} ${ticker}`;
  },
  // Expiration for this request in seconds (default=300s)
  requestedExpiry: 300,
  // The scopes and audience to request
  audience: process.env["AUDIENCE"],
  scopes: ["stock:trade"]
});
Then wrap the tool as follows:
import { z } from "zod";
import { getAsyncAuthorizationCredentials } from "@auth0/ai-genkit";

export const buyTool = ai.defineTool(
  ...buyStockAuthorizer({
    name: "buy_stock",
    description: "Execute a stock purchase given stock ticker and quantity",
    inputSchema: z.object({
      tradeID: z
        .string()
        .uuid()
        .describe("The unique identifier for the trade provided by the user"),
      userID: z
        .string()
        .describe("The user ID of the user who created the conditional trade"),
      ticker: z.string().describe("The stock ticker to trade"),
      qty: z
        .number()
        .int()
        .positive()
        .describe("The quantity of shares to trade"),
    }),
    outputSchema: z.string(),
  },
  async ({ ticker, qty }) => {
    const { accessToken } = getAsyncAuthorizationCredentials();
    fetch("http://yourapi.com/buy", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: `Bearer ${accessToken}`,
      },
      body: JSON.stringify({ ticker, qty }),
    });
    return `Purchased ${qty} shares of ${ticker}`;
  })
);
Auth0AI can leverage OpenFGA to authorize RAG applications. The FGARetriever can be used to filter documents based on access control checks defined in Okta FGA. This retriever performs batch checks on retrieved documents, returning only the ones that pass the specified access criteria.Create a Retriever instance using the FGARetriever.create method.
import { FGARetriever } from "@auth0/ai-genkit/RAG";
import { MemoryStore, RetrievalChain } from "./helpers/memory-store";
import { readDocuments } from "./helpers/read-documents";

async function main() {
  // UserID
  const user = "user1";
  const documents = await readDocuments();
  // 1. Call helper function to load LangChain MemoryStore
  const vectorStore = await MemoryStore.fromDocuments(documents);
  // 2. Call helper function to create a LangChain retrieval chain.
  const retrievalChain = await RetrievalChain.create({
    // 3. Decorate the retriever with the FGARetriever to check permissions.
    retriever: FGARetriever.create({
      retriever: vectorStore.asRetriever(),
      buildQuery: (doc) => ({
        user: `user:${user}`,
        object: `doc:${doc.metadata.id}`,
        relation: "viewer",
      }),
    }),
  });

  // 4. Execute the query
  const { answer } = await retrievalChain.query({
    query: "Show me forecast for ZEKO?",
  });

  console.log(answer);
}

main().catch(console.error);