diff --git a/auth4genai/how-tos/get-github-issues-python.mdx b/auth4genai/how-tos/get-github-issues-python.mdx index aef765890..f97ac43ce 100644 --- a/auth4genai/how-tos/get-github-issues-python.mdx +++ b/auth4genai/how-tos/get-github-issues-python.mdx @@ -39,7 +39,7 @@ Create a function that will return the access token for Github. ```python wrap lines async def get_token_from_token_vault(): - return await auth0.get_access_token_for_connection( + return await auth0.get_access_token_from_token_vault( options = { "connection" : "github", "scope" : "openid profile email offline_access"}) diff --git a/auth4genai/integrations/github.mdx b/auth4genai/integrations/github.mdx index 40c97fbe5..d44e9198d 100644 --- a/auth4genai/integrations/github.mdx +++ b/auth4genai/integrations/github.mdx @@ -83,7 +83,7 @@ To configure the Token Vault for your GitHub connection, you can use the followi ```tsx wrap lines const auth0AI = new Auth0AI(); - export const withGitHubConnection = auth0AI.withTokenForConnection({ + export const withGitHubConnection = auth0AI.withTokenVault({ connection: "github", // scopes are not supported for GitHub yet. Set required scopes when creating the accompanying GitHub app scopes: [], @@ -96,7 +96,7 @@ To configure the Token Vault for your GitHub connection, you can use the followi ```python wrap lines auth0_ai = Auth0AI() - with_github_connection = auth0_ai.with_federated_connection( + with_github_connection = auth0_ai.with_token_vault( connection="github", # scopes are not supported for GitHub yet. Set required scopes when creating the accompanying GitHub app scopes=[], diff --git a/auth4genai/integrations/google.mdx b/auth4genai/integrations/google.mdx index 57e0250aa..1cf4aadcf 100644 --- a/auth4genai/integrations/google.mdx +++ b/auth4genai/integrations/google.mdx @@ -150,7 +150,7 @@ To configure the Token Vault for your Google connection, you can use the followi ```tsx wrap lines const auth0AI = new Auth0AI(); - export const withGoogleConnection = auth0AI.withTokenForConnection({ + export const withGoogleConnection = auth0AI.withTokenVault({ connection: "google-oauth2", scopes: ["https://www.googleapis.com/auth/calendar.freebusy", ...], refreshToken: getAuth0RefreshToken(), @@ -162,7 +162,7 @@ To configure the Token Vault for your Google connection, you can use the followi ```python wrap lines auth0_ai = Auth0AI() - with_google_connection = auth0_ai.with_federated_connection( + with_google_connection = auth0_ai.with_token_vault( connection="google-oauth2", scopes=["https://www.googleapis.com/auth/calendar.freebusy", ...], refresh_token=get_auth0_refresh_token, diff --git a/auth4genai/integrations/slack.mdx b/auth4genai/integrations/slack.mdx index d775c87ef..b7693d8f8 100644 --- a/auth4genai/integrations/slack.mdx +++ b/auth4genai/integrations/slack.mdx @@ -84,7 +84,7 @@ To configure the Token Vault for your GitHub connection, you can use the followi ```tsx wrap lines const auth0AI = new Auth0AI(); - export const withSlackConnection = auth0AI.withTokenForConnection({ + export const withSlackConnection = auth0AI.withTokenVault({ connection: "sign-in-with-slack", scopes: ["channels:read", ...], refreshToken: getAuth0RefreshToken(), @@ -96,7 +96,7 @@ To configure the Token Vault for your GitHub connection, you can use the followi ```python wrap lines auth0_ai = Auth0AI() - with_slack_connection = auth0_ai.with_federated_connection( + with_slack_connection = auth0_ai.with_token_vault( connection="sign-in-with-slack", scopes=["channels:read", ...], refresh_token=get_auth0_refresh_token, diff --git a/auth4genai/intro/call-others-apis-on-users-behalf.mdx b/auth4genai/intro/call-others-apis-on-users-behalf.mdx index 35e5f17c7..946dba761 100644 --- a/auth4genai/intro/call-others-apis-on-users-behalf.mdx +++ b/auth4genai/intro/call-others-apis-on-users-behalf.mdx @@ -1,6 +1,6 @@ --- title: Call Other's APIs on User's Behalf -description: "[Token Vault](/intro/token-vault) lets your AI agent call external APIs on the user's behalf. We provide SDKs for Python, JavaScript, and popular AI frameworks like LangChain, LlamaIndex, Genkit, and Vercel AI, making it easy and straightforward to get access tokens for your federated connections." +description: "[Token Vault](/intro/token-vault) lets your AI agent call external APIs on the user's behalf. We provide SDKs for Python, JavaScript, and popular AI frameworks like LangChain, LlamaIndex, Genkit, and Vercel AI, making it easy and straightforward to get access tokens for your third-party connections." --- ## Web applications with backend for frontend @@ -135,4 +135,4 @@ To begin using Auth0 Token Vault with your AI agents, refer to the following res icon="key" horizontal /> - \ No newline at end of file + diff --git a/auth4genai/intro/token-vault.mdx b/auth4genai/intro/token-vault.mdx index bd7836e85..7abe1d396 100644 --- a/auth4genai/intro/token-vault.mdx +++ b/auth4genai/intro/token-vault.mdx @@ -47,9 +47,9 @@ By using Token Vault, you can: The process of using Token Vault involves the following key steps: 1. **User authentication and consent:** The [user links](/intro/account-linking) and authenticates with an external Identity Provider (e.g., Google) and grants your application permission to access their data by approving the requested OAuth scopes. -2. **Secure token storage:** Auth0 receives the federated access and refresh tokens from the external provider and stores them securely within Token Vault. -3. **Token exchange:** Your application can then exchange a valid Auth0 refresh token for a federated access token from Token Vault. This allows your application to obtain the necessary credentials to call the third-party API without the user having to re-authenticate. It also means your application does not need to store or manage any credentials. -4. **API call:** With the federated access token, your AI agent can make authorized calls to the third-party API on the user's behalf. +2. **Secure token storage:** Auth0 receives access and refresh tokens from the external provider and stores them securely within Token Vault. +3. **Token exchange:** Your application can then exchange a valid Auth0 refresh token for a third-party access token from Token Vault. This allows your application to obtain the necessary credentials to call the third-party API without the user having to re-authenticate. It also means your application does not need to store or manage any credentials. +4. **API call:** With the third-party access token, your AI agent can make authorized calls to the third-party API on the user's behalf. ## Supported integrations diff --git a/auth4genai/sdks/javascript-sdk.mdx b/auth4genai/sdks/javascript-sdk.mdx index 28b3cf792..163ca1bb4 100644 --- a/auth4genai/sdks/javascript-sdk.mdx +++ b/auth4genai/sdks/javascript-sdk.mdx @@ -63,7 +63,7 @@ This library helps to set up the React components that can be used in AI applica - Tools for getting access tokens for supported social and enterprise identity providers ```bash wrap lines -npx @auth0/ai-components add FederatedConnections +npx @auth0/ai-components add TokenVault ``` ### [Redis Store for Auth0 AI](https://github.com/auth0-lab/auth0-ai-js/tree/main/packages/ai-redis) diff --git a/auth4genai/snippets/get-started/langchain-fastapi-py/async-auth.mdx b/auth4genai/snippets/get-started/langchain-fastapi-py/async-auth.mdx index 2fa869a07..57ba5c776 100644 --- a/auth4genai/snippets/get-started/langchain-fastapi-py/async-auth.mdx +++ b/auth4genai/snippets/get-started/langchain-fastapi-py/async-auth.mdx @@ -34,7 +34,7 @@ Make sure you have [uv](https://docs.astral.sh/uv/) installed and run the follow ```bash wrap lines cd backend uv sync -uv add "auth0-ai-langchain>=1.0.0b3" "langgraph>=0.5.4" langchain-openai "langgraph-cli[inmem]" --prerelease=allow +uv add "auth0-ai-langchain>=TODO_NEW_VERSION_HERE" "langgraph>=0.5.4" langchain-openai "langgraph-cli[inmem]>=0.3.6" --prerelease=allow ``` ### Update the environment file @@ -47,7 +47,7 @@ Integrate the Auth0 AI SDK into your application to secure your async AI agent w #### Configure the Auth0 AI SDK -To require asynchronous authorization for your tool, the tool needs to be wrapped with the Async authorizer, `with_async_user_confirmation()`. Let's create a helper function to wrap the tool with the Async authorizer. +To require asynchronous authorization for your tool, the tool needs to be wrapped with the Async authorizer, `with_async_authorization()`. Let's create a helper function to wrap the tool with the Async authorizer. Create a file at `app/core/auth0_ai.py` and instantiate a new Auth0 AI SDK client: @@ -68,8 +68,9 @@ auth0_ai = Auth0AI( ) ) -with_async_user_confirmation = auth0_ai.with_async_user_confirmation( +with_async_authorization = auth0_ai.with_async_authorization( audience=settings.SHOP_API_AUDIENCE, + # param: scopes # add any scopes you want to use with your API scopes=["openid", "product:buy"], binding_message=lambda product, quantity: f"Do you want to buy {quantity} {product}", @@ -78,6 +79,12 @@ with_async_user_confirmation = auth0_ai.with_async_user_confirmation( .get("_credentials") .get("user") .get("sub"), + # param: requested_expiry + # Note: Setting a requested expiry greater than 300 (seconds) will force email verification + # instead of using the push notification flow. + # requested_expiry=301, + + # param: on_authorization_request # When this flag is set to `block`, the execution of the tool awaits # until the user approves or rejects the request. # @@ -87,12 +94,13 @@ with_async_user_confirmation = auth0_ai.with_async_user_confirmation( # In practice, the process that is awaiting the user confirmation # could crash or timeout before the user approves the request. on_authorization_request="block", + ) ``` -This will intercept the tool call to initiate a CIBA request: +This will intercept the tool call to initiate an Async Authorization request: -- The CIBA request includes the user ID that will approve the request. +- The Async Authorization request includes the user ID that will approve the request. - Auth0 sends the user a mobile push notification. The AI agent polls the `/token` endpoint for a user response. - The mobile application retrieves the `bindingMessage` containing the consent details, in this case, the details of the product to purchase. - The user responds to the request: @@ -139,17 +147,17 @@ async def api_route( #### Create a tool to call your API -In this example, we use a tool that buys products on the user's behalf. When the user approves the transaction, the Auth0 AI SDK retrieves an access token to call the shop's API. Upon completing the CIBA flow, the AI agent responds with a message confirming the purchase. The Auth0 AI SDK returns an error response if the user denies the transaction. +In this example, we use a tool that buys products on the user's behalf. When the user approves the transaction, the Auth0 AI SDK retrieves an access token to call the shop's API. Upon completing the Async Authorization flow, the AI agent responds with a message confirming the purchase. The Auth0 AI SDK returns an error response if the user denies the transaction. Now, create a file `app/agents/tools/shop_online.py` and add the following code: ```python app/agents/tools/shop_online.py wrap lines import httpx from langchain_core.tools import StructuredTool -from auth0_ai_langchain.ciba import get_ciba_credentials +from auth0_ai_langchain.async_authorization import get_async_authorization_credentials from pydantic import BaseModel -from app.core.auth0_ai import with_async_user_confirmation +from app.core.auth0_ai import with_async_authorization from app.core.config import settings @@ -167,10 +175,10 @@ async def shop_online_fn(product: str, quantity: int): # No API set, mock a response return f"Ordered {quantity} {product}" - credentials = get_ciba_credentials() + credentials = get_async_authorization_credentials() if not credentials: - raise ValueError("CIBA credentials not found") + raise ValueError("Async Authorization credentials not found") headers = { "Authorization": f"Bearer {credentials['access_token']}", @@ -202,7 +210,7 @@ async def shop_online_fn(product: str, quantity: int): } -shop_online = with_async_user_confirmation( +shop_online = with_async_authorization( StructuredTool( name="shop_online", description="Tool to buy products online.", diff --git a/auth4genai/snippets/get-started/langchain-fastapi-py/auth-for-rag.mdx b/auth4genai/snippets/get-started/langchain-fastapi-py/auth-for-rag.mdx index 6cb426973..e79fab047 100644 --- a/auth4genai/snippets/get-started/langchain-fastapi-py/auth-for-rag.mdx +++ b/auth4genai/snippets/get-started/langchain-fastapi-py/auth-for-rag.mdx @@ -35,7 +35,7 @@ Make sure you have [uv](https://docs.astral.sh/uv/) installed and run the follow ```bash wrap lines cd backend uv sync -uv add "auth0-ai-langchain>=1.0.0b3" openfga-sdk langgraph langchain-openai "langgraph-cli[inmem]" --prerelease=allow +uv add "auth0-ai-langchain>=TODO_NEW_VERSION_HERE" openfga-sdk langgraph langchain-openai "langgraph-cli[inmem]" --prerelease=allow ``` ### Update the environment file diff --git a/auth4genai/snippets/get-started/langchain-fastapi-py/call-others-api.mdx b/auth4genai/snippets/get-started/langchain-fastapi-py/call-others-api.mdx index 931bcad2b..7daf796fb 100644 --- a/auth4genai/snippets/get-started/langchain-fastapi-py/call-others-api.mdx +++ b/auth4genai/snippets/get-started/langchain-fastapi-py/call-others-api.mdx @@ -13,7 +13,7 @@ import { AccountAndAppSteps } from "/snippets/get-started/prerequisites/account- - + ### Clone sample app Clone this sample app from the [Auth0 AI samples](https://github.com/auth0-samples/auth0-ai-samples) repository: @@ -134,7 +134,7 @@ Make sure you have [uv](https://docs.astral.sh/uv/) installed and run the follow ```bash wrap lines cd backend uv sync -uv add "auth0-ai-langchain>=1.0.0b3" "langgraph>=0.5.4" langchain-openai "langgraph-cli[inmem]" google-api-python-client --prerelease=allow +uv add "auth0-ai-langchain>=TODO_NEW_VERSION_HERE" "langgraph>=0.5.4" langchain-openai "langgraph-cli[inmem]>=0.3.6" google-api-python-client --prerelease=allow ``` ### Update your environment file @@ -191,7 +191,7 @@ auth0_ai = Auth0AI( ) ) -with_calendar_access = auth0_ai.with_federated_connection( +with_calendar_access = auth0_ai.with_token_vault( connection="google-oauth2", scopes=["https://www.googleapis.com/auth/calendar.events"], ) @@ -243,8 +243,8 @@ from langchain_core.tools import StructuredTool from google.oauth2.credentials import Credentials from googleapiclient.discovery import build from pydantic import BaseModel -from auth0_ai_langchain.federated_connections import ( - get_access_token_for_connection, +from auth0_ai_langchain.token_vault import ( + get_access_token_from_token_vault, ) import datetime import json @@ -253,10 +253,10 @@ from app.core.auth0_ai import with_calendar_access async def list_upcoming_events_fn(): """List upcoming events from the user's Google Calendar""" - google_access_token = get_access_token_for_connection() + google_access_token = get_access_token_from_token_vault() if not google_access_token: raise ValueError( - "Authorization required to access the Federated Connection API" + "Authorization required to access the Token Vault connection API" ) calendar_service = build( @@ -328,18 +328,18 @@ To implement, install the Auth0 AI Components for React SDK to get the required ```bash wrap lines cd frontend npm install @auth0/ai @langchain/langgraph-sdk -npx @auth0/ai-components add FederatedConnections +npx @auth0/ai-components add TokenVault ``` -Add a new file, `src/components/auth0-ai/FederatedConnections/FederatedConnectionInterruptHandler.tsx`, with the following code: +Add a new file, `src/components/auth0-ai/TokenVault/TokenVaultInterruptHandler.tsx`, with the following code: -```tsx src/components/auth0-ai/FederatedConnections/FederatedConnectionInterruptHandler.tsx wrap lines -import { FederatedConnectionInterrupt } from "@auth0/ai/interrupts"; +```tsx src/components/auth0-ai/TokenVault/TokenVaultInterruptHandler.tsx wrap lines +import { TokenVaultInterrupt } from "@auth0/ai/interrupts"; import type { Interrupt } from "@langchain/langgraph-sdk"; -import { EnsureAPIAccess } from "@/components/auth0-ai/FederatedConnections"; +import { TokenVaultConsent } from "@/components/auth0-ai/TokenVault"; -interface FederatedConnectionInterruptHandlerProps { +interface TokenVaultInterruptHandlerProps { interrupt: Interrupt | undefined | null; onFinish: () => void; auth?: { @@ -348,21 +348,21 @@ interface FederatedConnectionInterruptHandlerProps { }; } -export function FederatedConnectionInterruptHandler({ +export function TokenVaultInterruptHandler({ interrupt, onFinish, auth, -}: FederatedConnectionInterruptHandlerProps) { +}: TokenVaultInterruptHandlerProps) { if ( !interrupt || - !FederatedConnectionInterrupt.isInterrupt(interrupt.value) + !TokenVaultInterrupt.isInterrupt(interrupt.value) ) { return null; } return (
-
{!!chat.interrupt?.value && ( - - \ No newline at end of file + diff --git a/auth4genai/snippets/get-started/langchain-next-js/async-auth.mdx b/auth4genai/snippets/get-started/langchain-next-js/async-auth.mdx index 968cc3f8d..fc6fbc152 100644 --- a/auth4genai/snippets/get-started/langchain-next-js/async-auth.mdx +++ b/auth4genai/snippets/get-started/langchain-next-js/async-auth.mdx @@ -36,7 +36,7 @@ Integrate the Auth0 AI SDK into your application to secure your async AI agent w #### Configure the Auth0 AI SDK -To require asynchronous authorization for your tool, the tool needs to be wrapped with the Async authorizer, `withAsyncUserConfirmation()`. Let's create a helper function to wrap the tool with the Async authorizer. +To require asynchronous authorization for your tool, the tool needs to be wrapped with the Async authorizer, `withAsyncAuthorization()`. Let's create a helper function to wrap the tool with the Async authorizer. Create a file at `src/lib/auth0-ai.ts` and instantiate a new Auth0 AI SDK client: @@ -46,8 +46,8 @@ import { AccessDeniedInterrupt } from "@auth0/ai/interrupts"; const auth0AI = new Auth0AI(); -// CIBA flow for user confirmation -export const withAsyncAuthorization = auth0AI.withAsyncUserConfirmation({ +// Async Authorization flow for user confirmation +export const withAsyncAuthorization = auth0AI.withAsyncAuthorization({ userID: async (_params, config) => { return config.configurable?.langgraph_auth_user?.sub; }, @@ -76,9 +76,9 @@ export const withAsyncAuthorization = auth0AI.withAsyncUserConfirmation({ }); ``` -This will intercept the tool call to initiate a CIBA request: +This will intercept the tool call to initiate a Async Authorization request: -- The CIBA request includes the user ID that will approve the request. +- The Async Authorization request includes the user ID that will approve the request. - Auth0 sends the user a mobile push notification. The AI agent polls the `/token` endpoint for a user response. - The mobile application retrieves the `bindingMessage` containing the consent details, in this case, the details of the product to purchase. - The user responds to the request: @@ -241,7 +241,7 @@ export { auth as authHandler }; #### Create a tool to call your API -In this example, we use a tool that buys products on the user's behalf. When the user approves the transaction, the Auth0 AI SDK retrieves an access token to call the shop's API. Upon completing the CIBA flow, the AI agent responds with a message confirming the purchase. The Auth0 AI SDK returns an error response if the user denies the transaction. +In this example, we use a tool that buys products on the user's behalf. When the user approves the transaction, the Auth0 AI SDK retrieves an access token to call the shop's API. Upon completing the Async Authorization flow, the AI agent responds with a message confirming the purchase. The Auth0 AI SDK returns an error response if the user denies the transaction. Now, create a file `src/lib/tools/shop-online.ts` and add the following code: @@ -249,7 +249,7 @@ Now, create a file `src/lib/tools/shop-online.ts` and add the following code: import { tool } from "@langchain/core/tools"; import { z } from "zod"; -import { getCIBACredentials } from "@auth0/ai-langchain"; +import { getAsyncAuthorizationCredentials } from "@auth0/ai-langchain"; export const shopOnlineTool = tool( async ({ product, qty, priceLimit }) => { @@ -272,7 +272,7 @@ export const shopOnlineTool = tool( priceLimit, }; - const credentials = getCIBACredentials(); + const credentials = getAsyncAuthorizationCredentials(); const accessToken = credentials?.accessToken; if (accessToken) { diff --git a/auth4genai/snippets/get-started/langchain-next-js/call-others-api.mdx b/auth4genai/snippets/get-started/langchain-next-js/call-others-api.mdx index ac2d84f82..6975ddc7d 100644 --- a/auth4genai/snippets/get-started/langchain-next-js/call-others-api.mdx +++ b/auth4genai/snippets/get-started/langchain-next-js/call-others-api.mdx @@ -149,7 +149,7 @@ const auth0AI = new Auth0AI({ }); const withAccessTokenForConnection = (connection: string, scopes: string[]) => - auth0AI.withTokenForConnection({ + auth0AI.withTokenVault({ connection, scopes, accessToken: async (_, config) => { @@ -321,7 +321,7 @@ This example uses `GmailSearch` from the `@langchain/community` tools. This tool ```ts src/lib/tools/gmail-seatch.ts wrap lines highlight={10} //... -import { getAccessTokenForConnection } from "@auth0/ai-langchain"; +import { getAccessTokenFromTokenVault } from "@auth0/ai-langchain"; import { GmailSearch } from "@langchain/community/tools/gmail"; import { withGmailSearch } from "../../lib/auth0-ai"; @@ -329,7 +329,7 @@ import { withGmailSearch } from "../../lib/auth0-ai"; export const gmailSearchTool = withGmailSearch( new GmailSearch({ credentials: { - accessToken: async () => getAccessTokenForConnection(), + accessToken: async () => getAccessTokenFromTokenVault(), }, }) ); @@ -365,36 +365,36 @@ When you try to use the tool, the application requests any additional Google sco To implement, install the Auth0 AI Components for Next.js SDK to get the required UI components: ```bash wrap lines -npx @auth0/ai-components add FederatedConnections +npx @auth0/ai-components add TokenVault ``` -Add a new file, `src/components/auth0-ai/FederatedConnections/FederatedConnectionInterruptHandler.tsx`, with the following code: +Add a new file, `src/components/auth0-ai/TokenVault/TokenVaultInterruptHandler.tsx`, with the following code: -```tsx src/components/auth0-ai/FederatedConnections/FederatedConnectionInterruptHandler.tsx wrap lines -import { FederatedConnectionInterrupt } from "@auth0/ai/interrupts"; +```tsx src/components/auth0-ai/TokenVault/TokenVaultInterruptHandler.tsx wrap lines +import { TokenVaultInterrupt } from "@auth0/ai/interrupts"; import type { Interrupt } from "@langchain/langgraph-sdk"; -import { EnsureAPIAccess } from "@/components/auth0-ai/FederatedConnections"; +import { TokenVaultConsent } from "@/components/auth0-ai/TokenVault"; -interface FederatedConnectionInterruptHandlerProps { +interface TokenVaultInterruptHandlerProps { interrupt: Interrupt | undefined | null; onFinish: () => void; } -export function FederatedConnectionInterruptHandler({ +export function TokenVaultInterruptHandler({ interrupt, onFinish, -}: FederatedConnectionInterruptHandlerProps) { +}: TokenVaultInterruptHandlerProps) { if ( !interrupt || - !FederatedConnectionInterrupt.isInterrupt(interrupt.value) + !TokenVaultInterrupt.isInterrupt(interrupt.value) ) { return null; } return (
-
- chat.submit(null)} /> + chat.submit(null)} />
) diff --git a/auth4genai/snippets/get-started/langchain-react-spa-js/call-others-api.mdx b/auth4genai/snippets/get-started/langchain-react-spa-js/call-others-api.mdx new file mode 100644 index 000000000..c2e1542e0 --- /dev/null +++ b/auth4genai/snippets/get-started/langchain-react-spa-js/call-others-api.mdx @@ -0,0 +1,791 @@ +import { Prerequisites } from "/snippets/get-started/prerequisites/call-others-api.jsx"; +import { AccountAndAppSteps } from "/snippets/get-started/prerequisites/account-app-steps.jsx"; + + + +### Key features of this React SPA + LangGraph.js example + +This integration provides a robust, secure foundation for authenticating users and enabling AI agents to act on their behalf using third-party APIs. Here are some key features of this example: + +1. **Modern Toolset**: Uses a modern stack with React, Vite, LangGraph.js, and the Auth0 AI SDK to create an interactive chat interface that integrates with Google Calendar and the [LangGraph.js ReAct Memory Agent](https://github.com/langchain-ai/memory-agent-js). +2. **Client-Side Authorization**: Client login and step-up authorization are handled client-side using `@auth0/auth0-spa-js`. No backend proxy required, and client streaming calls are made directly to the LangGraph API. +3. **Token Vault**: Token Vault performs token exchanges and securely manages tokens, allowing seamless, user-approved third-party API access to AI agents and finely scoped authorization for each API. +4. **Interrupt Handling**: The React client manages tool access errors and step-up authorization using interrupts that trigger a pop-up for re-authorization. +5. **LangGraph Custom Auth**: The auth integration with LangGraph.js leverages LangGraph's [custom auth support](https://docs.langchain.com/langgraph-platform/custom-auth), ensuring secure and authenticated API calls both with the LangGraph Platform and self-hosted deployments. + + + + +### Clone sample app +Clone this sample app from the [Auth0 AI samples](https://github.com/auth0-samples/auth0-ai-samples.git) repository: + +```bash wrap lines +git clone https://github.com/auth0-samples/auth0-ai-samples.git +cd auth0-ai-samples/calling-apis-on-users-behalf/others-api/langchain-react-spa-js +``` + +The project is divided into two parts: +- `apps/agents`: contains the backend LangGraph API server using LangGraph CLI, LangGraph SDKs, and Auth0 AI SDKs. +- `apps/web`: contains the frontend code for the web app, written in React as a Vite SPA. + +### Install dependencies + +To install all the frontend and backend dependencies, navigate to the root directory of the project and run the following command: +```bash wrap lines +# Install all frontend & backend dependencies from the root directory of the project. +npm install +``` + +### Create the environment files + +Add separate `.env` files with environment variables for the backend LangGraph API server and the frontend. + +#### Backend LangGraph API Server (apps/agents/.env) + +Copy `apps/agents/.env.example` to `apps/agents/.env` and update the values: +```bash .env wrap lines +# OpenAI API Key or any provider supported by the LangGraph SDK +OPENAI_API_KEY=your-openai-key + +# Auth0 Configuration +AUTH0_DOMAIN=your-auth0-domain.auth0.com +AUTH0_AUDIENCE=your-api-identifier +AUTH0_CUSTOM_API_CLIENT_ID=your-custom-api-client-id +AUTH0_CUSTOM_API_CLIENT_SECRET=your-custom-api-client-secret +``` +To get your Auth0 Custom API Client's `AUTH0_DOMAIN`, `AUTH0_CUSTOM_API_CLIENT_ID`, and `AUTH0_CUSTOM_API_CLIENT_SECRET`, navigate to the **Applications** section in the Auth0 Dashboard and select your Custom API Client application from the list. Then, navigate to the **Settings** tab. You'll find these values in the **Basic Information** section at the top. +Copy each value to the matching setting. + +To get the `AUTH0_AUDIENCE`, next hit the **Configure API** button in the top right to navigate to your Custom API Client's **API**. The Identifier will be listed in the **Settings** tab and should be provided as the `AUTH0_AUDIENCE`. + +Lastly, set your OpenAI API key or use any provider supported by the LangGraph SDK: +```bash .env.local wrap lines +OPENAI_API_KEY="YOUR_API_KEY" +``` + +#### Frontend (apps/web/.env) + +Copy `apps/web/.env.example` to `apps/web/.env` and update the values: +```bash .env wrap lines +VITE_AUTH0_DOMAIN=your-auth0-domain.auth0.com +VITE_AUTH0_CLIENT_ID=your-spa-client-id +VITE_AUTH0_AUDIENCE=your-api-identifier +VITE_LANGGRAPH_API_URL=http://localhost:2024 +``` +To get your Auth0 SPA's `VITE_AUTH0_DOMAIN`, and `VITE_AUTH0_CLIENT_ID`, navigate to the **Applications** section in the Auth0 Dashboard and select your Single Page application from the list. Then, navigate to the **Settings** tab. You'll find these values in the **Basic Information** section at the top. +Copy each value to the matching setting. + +The `VITE_AUTH0_AUDIENCE` should match the `AUTH0_AUDIENCE`, and the Identifier of the Custom API client's API you created above. + +Lastly, `VITE_LANGGRAPH_API_URL` set your LangGraph API URL, depending on where you are running the LangGraph API server. If you are running it locally, use `http://localhost:2024`. If you are using a LangGraph Platform deployment, use your deployment's Resource URL (e.g. `https://your.domain.us.langgraph.app`). +```bash .env.local wrap lines +VITE_LANGGRAPH_API_URL=http://localhost:2024 +``` + +### Run your application + +1. Start the Vite frontend and LangGraph API server using Turbo: `npm run dev`. +2. Navigate to `http://localhost:5173`. +3. Hit the **Sign In with Auth0** button and log in to your application with Google credentials on the Universal Login screen. +4. Enter the Agent Chat form options for the `Deployment URL` (e.g., `http://localhost:2024` or your LangGraph Platform Deployment's Resource URL), and the `Graph ID` of the agent to use (e.g., `memory_agent`), and hit the **Continue** button. +5. Ask your AI agent about your calendar with a prompt, such as "Can you check my calendar for availability tomorrow at 3pm?". + +The application will automatically prompt for additional calendar permissions when needed using Auth0's step-up authorization flow. + +That's it! You've successfully set up and run the React SPA + LangGraph API sample app. + + + + +### Install packages + +Ensure you have installed the following client and server dependencies in your project: + +**Frontend client dependencies:** + +- `@auth0/auth0-spa-js`: Auth0 SPA SDK for client-side authentication +- `@auth0/ai`: [Auth0 AI SDK](https://github.com/auth0-lab/auth0-ai-js/tree/main/packages/ai) built for GenAI applications +- `@langchain/core`: contains the core LangChain abstractions and schemas for LangChain.js +- `@langchain/langgraph`, `@langchain/langgraph-api`, `@langchain/langgraph-sdk`: Core [LangGraph.js SDK](https://github.com/langchain-ai/langgraphjs/tree/main) for interacting with LangGraph APIs + +**Backend LangGraph API Server dependencies:** + +- `@langchain/core`: contains the core LangChain abstractions and schemas for LangChain.js +- `@langchain/langgraph`, `@langchain/langgraph-sdk`: Core [LangGraph.js SDK](https://github.com/langchain-ai/langgraphjs/tree/main) libraries for constructing a State Graph and defining LangGraph tools. +- `@langchain/openai`: used when interfacing with the OpenAI series of models from LangGraph agents (alternatively, you can use `@langchain/anthropic` for accessing Anthropic models). +- `@langchain/langgraph-cli`: the [LangGraph CLI](https://docs.langchain.com/langgraph-platform/cli) is used for self-hosted LangGraph API server deployments or commonly as a local LangGraph API server during development +- `@auth0/ai`, `@auth0/ai-langchain`: [Auth0 AI SDK](https://github.com/auth0-lab/auth0-ai-js/tree/main/packages/ai)'s built for interfacing with Token Vault and your LangGraph API tools. +- `googleapis`: Node.js client for Google APIs +- `jose`: JavaScript Object Signing and Encryption library for JWT verification + + +### Update the environment files + +Add separate `.env` files with environment variables for the client and the LangGraph API server. + +#### Backend LangGraph API Server (server/.env) + +In the backend directory of your project, add the following variables to your environment file: +```bash .env wrap lines +# OpenAI API Key or any provider supported by the LangGraph SDK +OPENAI_API_KEY=your-openai-key + +# Auth0 Configuration +AUTH0_DOMAIN=your-auth0-domain.auth0.com +AUTH0_AUDIENCE=your-api-identifier +AUTH0_CUSTOM_API_CLIENT_ID=your-custom-api-client-id +AUTH0_CUSTOM_API_CLIENT_SECRET=your-custom-api-client-secret +``` +To get your Auth0 Custom API Client's `AUTH0_DOMAIN`, `AUTH0_CUSTOM_API_CLIENT_ID`, and `AUTH0_CUSTOM_API_CLIENT_SECRET`, navigate to the **Applications** section in the Auth0 Dashboard and select your Custom API Client application from the list. Then, navigate to the **Settings** tab. You'll find these values in the **Basic Information** section at the top. +Copy each value to the matching setting. + +To get the `AUTH0_AUDIENCE`, next hit the **Configure API** button in the top right to navigate to your Custom API Client's **API**. The Identifier will be listed in the **Settings** tab and should be provided as the `AUTH0_AUDIENCE`. + +Lastly, set your OpenAI API key or use any provider supported by the LangGraph SDK: +```bash .env.local wrap lines +OPENAI_API_KEY="YOUR_API_KEY" +``` + +#### Frontend (apps/web/.env) + +In the frontend directory of your project, add the following variables to your environment file: + +Copy `apps/web/.env.example` to `apps/web/.env` and update the values: +```bash .env wrap lines +VITE_AUTH0_DOMAIN=your-auth0-domain.auth0.com +VITE_AUTH0_CLIENT_ID=your-spa-client-id +VITE_AUTH0_AUDIENCE=your-api-identifier +VITE_LANGGRAPH_API_URL=http://localhost:2024 +``` +To get your Auth0 SPA's `VITE_AUTH0_DOMAIN`, and `VITE_AUTH0_CLIENT_ID`, navigate to the **Applications** section in the Auth0 Dashboard and select your Single Page application from the list. Then, navigate to the **Settings** tab. You'll find these values in the **Basic Information** section at the top. +Copy each value to the matching setting. + +The `VITE_AUTH0_AUDIENCE` should match the `AUTH0_AUDIENCE`, and the Identifier of the Custom API client's API you created above. + +Lastly, `VITE_LANGGRAPH_API_URL` set your LangGraph API URL, depending on where you are running the LangGraph API server. If you are running it locally, use `http://localhost:2024`. If you are using a LangGraph Platform deployment, use your deployment's Resource URL (e.g. `https://your.domain.us.langgraph.app`). +```bash .env.local wrap lines +VITE_LANGGRAPH_API_URL=http://localhost:2024 +``` + +### Frontend React SPA with Vite Auth0 Implementation + +#### Auth0 Client Configuration + +Create the `src/lib/auth0.ts` file to set up the Auth0 SPA JS client: + +```tsx src/lib/auth0.ts wrap lines +import { Auth0Client, createAuth0Client, User } from "@auth0/auth0-spa-js"; + +// Auth0 configuration +const AUTH0_DOMAIN = import.meta.env.VITE_AUTH0_DOMAIN; +const AUTH0_CLIENT_ID = import.meta.env.VITE_AUTH0_CLIENT_ID; +const AUTH0_AUDIENCE = import.meta.env.VITE_AUTH0_AUDIENCE; + +if (!AUTH0_DOMAIN || !AUTH0_CLIENT_ID) { + throw new Error( + "Missing Auth0 configuration. Please check your environment variables.", + ); +} + +let auth0Client: Auth0Client | null = null; + +export const initAuth0 = async (): Promise => { + if (auth0Client) { + return auth0Client; + } + + auth0Client = await createAuth0Client({ + domain: AUTH0_DOMAIN, + clientId: AUTH0_CLIENT_ID, + authorizationParams: { + redirect_uri: window.location.origin, + audience: AUTH0_AUDIENCE, + scope: "openid profile email", // Basic scopes + }, + }); + + return auth0Client; +}; + +export const getAuth0Client = (): Auth0Client => { + if (!auth0Client) { + throw new Error("Auth0 client not initialized. Call initAuth0() first."); + } + return auth0Client; +}; + +export const login = async (targetUrl?: string) => { + const client = getAuth0Client(); + await client.loginWithRedirect({ + authorizationParams: { + redirect_uri: window.location.origin, + }, + appState: targetUrl ? { targetUrl } : undefined, + }); +}; + +export const logout = async () => { + const client = getAuth0Client(); + await client.logout({ + logoutParams: { + returnTo: window.location.origin, + }, + }); +}; + +export const getToken = async (): Promise => { + const client = getAuth0Client(); + return await client.getTokenSilently(); +}; + +export const isAuthenticated = async (): Promise => { + const client = getAuth0Client(); + return await client.isAuthenticated(); +}; + +export const getUser = async (): Promise => { + const client = getAuth0Client(); + return await client.getUser(); +}; +``` + +#### React Context Provider Setup + +Create the `src/providers/Auth0.tsx` file to configure the React context provider for Auth0: +```tsx src/providers/Auth0.tsx wrap lines +import React, { ReactNode, useEffect, useRef, useState } from "react"; +import { Auth0Context, Auth0ContextType } from "@/contexts/auth0-context"; +import { + getToken, + getUser, + initAuth0, + isAuthenticated, + login, + logout, +} from "@/lib/auth0"; +import { User } from "@auth0/auth0-spa-js"; + +interface Auth0ProviderProps { + children: ReactNode; +} + +export const Auth0Provider: React.FC = ({ children }) => { + const [isLoading, setIsLoading] = useState(true); + const [isAuthenticatedState, setIsAuthenticatedState] = useState(false); + const [user, setUser] = useState(null); + const [error, setError] = useState(null); + const initRef = useRef(false); + + useEffect(() => { + // Prevent double execution in React Strict Mode + if (initRef.current) return; + initRef.current = true; + + const initializeAuth0 = async () => { + try { + setIsLoading(true); + await initAuth0(); + + // Handle redirect callback + if ( + window.location.search.includes("code=") && + window.location.search.includes("state=") + ) { + const client = await initAuth0(); + await client.handleRedirectCallback(); + window.history.replaceState( + {}, + document.title, + window.location.pathname, + ); + } + + const authenticated = await isAuthenticated(); + setIsAuthenticatedState(authenticated); + + if (authenticated) { + const userData = await getUser(); + setUser(userData as User); + } + } catch (err) { + console.error("Auth0 initialization error:", err); + setError(err instanceof Error ? err.message : "Authentication error"); + } finally { + setIsLoading(false); + } + }; + + initializeAuth0(); + }, []); + + const contextValue: Auth0ContextType = { + isLoading, + isAuthenticated: isAuthenticatedState, + user, + error, + login: async (targetUrl?: string) => { + try { + setError(null); + await login(targetUrl); + } catch (err) { + console.error("Login error:", err); + setError(err instanceof Error ? err.message : "Login failed"); + } + }, + logout: async () => { + try { + setError(null); + await logout(); + setIsAuthenticatedState(false); + setUser(null); + } catch (err) { + console.error("Logout error:", err); + setError(err instanceof Error ? err.message : "Logout failed"); + } + }, + getToken, + }; + + return ( + + {children} + + ); +}; +``` + +#### Wrap the React Application with the Auth0 Provider + +In `src/main.tsx`, wrap your application with the `Auth0Provider`: + +```tsx src/main.tsx wrap lines +import "./index.css"; +import { NuqsAdapter } from "nuqs/adapters/react-router/v6"; +import { createRoot } from "react-dom/client"; +import { BrowserRouter } from "react-router-dom"; +import { Toaster } from "@/components/ui/sonner"; +import App from "./App.tsx"; +import { Auth0Provider } from "./providers/Auth0.tsx"; +import { StreamProvider } from "./providers/Stream.tsx"; +import { ThreadProvider } from "./providers/Thread.tsx"; + +createRoot(document.getElementById("root")!).render( + + + + + + + + + + + + , +); +``` + +#### Client-Side Chat Component Integration + +Use the Auth0 context with the LangGraph's streaming capabilities in your Chat components: + +```tsx src/components/Chat.tsx wrap lines +import { useAuth0 } from "@/hooks/useAuth0"; +import { useStream } from "@langchain/langgraph-sdk/react"; + +export default function ChatInterface() { + const { user, isLoading, isAuthenticated, login, logout, getToken } = useAuth0(); + const [accessToken, setAccessToken] = useState(null); + const apiUrl = import.meta.env.VITE_LANGGRAPH_API_URL || "http://localhost:2024"; + + // Get access token when authenticated + useEffect(() => { + if (isAuthenticated) { + getToken().then(setAccessToken).catch(console.error); + } + }, [isAuthenticated, getToken]); + + // Initialize LangGraph stream with Auth0 token + const stream = useStream({ + apiUrl, + assistantId: "memory_agent", + defaultHeaders: accessToken + ? { Authorization: `Bearer ${accessToken}` } + : undefined, + }); + + const sendMessage = (content: string) => { + if (!isAuthenticated || !content.trim()) return; + + stream.submit({ + messages: [{ + type: "human", + content, + // User context available in agent workflows + metadata: { userId: user?.sub } + }] + }); + }; + + if (isLoading) return
Loading...
; + + if (!isAuthenticated) { + return ( +
+

Welcome to LangGraph Chat

+ +
+ ); + } + + return ( +
+
+ Welcome, {user?.name} + +
+ +
+ {stream.messages?.map((msg, i) => ( +
{msg.content}
+ ))} +
+ +
{ + e.preventDefault(); + const input = new FormData(e.target).get('message'); + sendMessage(input as string); + e.target.reset(); + }}> + + +
+
+ ); +} +``` + +#### Step-up Authorization with Auth0 Interrupts + +The Auth0 AI and Auth0 SPA JS SDKs include sophisticated interrupt handling for step-up authorization scenarios, particularly when accessing third-party APIs through Auth0's Token Vault. This enables agents to request additional permissions dynamically during conversations. + +##### Implementing Interrupts + +When an agent tool requires access to a third-party service (like Google Calendar) that the user hasn't previously authorized, LangGraph can raise a `TokenVaultInterrupt`. The frontend handles these interrupts by displaying an authorization pop-up. + +1. Interrupt Detection in Chat Interface + +In your chat message rendering logic, check for Auth0 interrupts: +```tsx src/components/Chat.tsx wrap lines +// In your chat message component +{threadInterrupt && + Auth0Interrupt.isInterrupt(threadInterrupt.value) && + isLastMessage ? ( + thread.submit(null)} + /> + ) : null} +``` + +2. Auth0 Interrupt Handler Component + +Create `src/components/Auth0InterruptHandler.tsx` to manage the interrupt UI: + +```tsx src/components/Auth0InterruptHandler.tsx wrap lines +import { Auth0Interrupt } from "@auth0/ai/interrupts"; +import { TokenVaultInterrupt } from "@auth0/ai/interrupts"; +import { TokenVaultConsentPopup } from "./TokenVaultConsentPopup"; + +interface Auth0InterruptHandlerProps { + interrupt: Auth0Interrupt; + onResume: () => void; +} + +export function Auth0InterruptHandler({ + interrupt, + onResume, +}: Auth0InterruptHandlerProps) { + // Handle TokenVaultInterrupt + if (TokenVaultInterrupt.isInterrupt(interrupt)) { + return ( + + ); + } + + return null; +} +``` + +3. Token Vault Consent Popup + +The `TokenVaultConsentPopup` component handles the OAuth flow for third-party connections. + +Create `src/components/TokenVaultConsentPopup.tsx` to display the authorization prompt: + +```tsx src/components/TokenVaultConsentPopup.tsx wrap lines +// apps/web/src/components/auth0/TokenVaultConsentPopup.tsx +import { useState } from "react"; +import { TokenVaultInterrupt } from "@auth0/ai/interrupts"; +import { useAuth0 } from "@/hooks/useAuth0"; + +interface TokenVaultConsentPopupProps { + interrupt: TokenVaultInterrupt; + onResume: () => void; +} + +export function TokenVaultConsentPopup({ + interrupt, + onResume, +}: TokenVaultConsentPopupProps) { + const [isConnecting, setIsConnecting] = useState(false); + const { getToken } = useAuth0(); + + const handleConnect = async () => { + try { + setIsConnecting(true); + + // Get the current access token + const accessToken = await getToken(); + + // Construct Auth0 authorization URL with additional scopes + const authUrl = new URL(`https://${process.env.VITE_AUTH0_DOMAIN}/authorize`); + authUrl.searchParams.set('client_id', process.env.VITE_AUTH0_CLIENT_ID!); + authUrl.searchParams.set('response_type', 'code'); + authUrl.searchParams.set('redirect_uri', window.location.origin); + authUrl.searchParams.set('scope', interrupt.scopes.join(' ')); + authUrl.searchParams.set('connection', interrupt.connection); + authUrl.searchParams.set('state', 'step-up-auth'); + + // Open popup window for authorization + const popup = window.open( + authUrl.toString(), + 'auth-popup', + 'width=500,height=600,scrollbars=yes' + ); + + // Listen for popup completion + const checkClosed = setInterval(() => { + if (popup?.closed) { + clearInterval(checkClosed); + setIsConnecting(false); + // Resume the conversation after authorization + onResume(); + } + }, 1000); + + } catch (error) { + console.error('Connection error:', error); + setIsConnecting(false); + } + }; + + return ( +
+

Additional Permission Required

+

+ To continue, this agent needs access to your {interrupt.connection} account. +

+
+ + +
+
+ ); +} +``` + +You've now implemented step-up authorization handling in your React SPA using Auth0 interrupts! + +Now when step-up authorization is required, the user will see a prompt in the chat window asking them to authorize. + +### Backend LangGraph API Implementation with Auth0 AI SDK Integration + +Next, set up the backend LangGraph API server to define the agent and tools, integrating Auth0 AI SDKs for secure third-party API access. + +#### LangGraph Custom Authentication + +LangGraph supports custom authentication to validate incoming tokens and extract user context. This enables user-specific authorization and auditing within your LangGraph applications. + +Configure your LangGraph deployment to accept Auth0 tokens by setting up custom authentication. See the [LangGraph Custom Auth documentation](https://docs.langchain.com/langgraph-platform/custom-auth) for detailed setup. + +Example Custom Auth Handler: +```ts src/auth.ts wrap lines +import { createRemoteJWKSet, jwtVerify } from "jose"; +const { Auth, HTTPException } = require("@langchain/langgraph-sdk/auth"); + +const AUTH0_DOMAIN = process.env.AUTH0_DOMAIN; +const AUTH0_AUDIENCE = process.env.AUTH0_AUDIENCE; + +// JWKS endpoint for Auth0 +const JWKS = createRemoteJWKSet( + new URL(`https://${AUTH0_DOMAIN}/.well-known/jwks.json`) +); + +const auth = new Auth(); + +auth.authenticate(async (request: Request) => { + const authHeader = request.headers.get("Authorization"); + const xApiKeyHeader = request.headers.get("x-api-key"); + + // LangGraph Platform converts Authorization to x-api-key automatically + let token = xApiKeyHeader ?? authHeader; + + if (token && token.startsWith("Bearer ")) { + token = token.substring(7); + } + + const { payload } = await jwtVerify(token, JWKS, { + issuer: `https://${AUTH0_DOMAIN}/`, + audience: AUTH0_AUDIENCE, + }); + + return { + identity: payload.sub!, + email: payload.email as string, + permissions: typeof payload.scope === "string" ? payload.scope.split(" ") : [], + auth_type: "auth0", + getRawAccessToken: () => token, + ...payload, + }; +}); + +export { auth as authHandler }; +``` + +Then you can reference the custom auth handler in your `langgraph.json` file: + +```json langgraph.json wrap lines +{ + "node_version": "20", + "dependencies": ["."], + "graphs": { + "memory_agent": "./src/memory-agent/graph.ts:graph" + }, + "auth": { + "path": "./src/auth.ts:authHandler" + }, + "env": ".env" +} +``` + +#### Token Vault Integration with Agent Tools + +Create the Auth0 AI `withTokenVault` wrapper to securely fetch access tokens from Token Vault for your tools: + +```ts src/auth0-ai.ts wrap lines +import { SUBJECT_TOKEN_TYPES } from "@auth0/ai"; +import { Auth0AI } from "@auth0/ai-langchain"; + +const auth0AI = new Auth0AI({ + auth0: { + domain: process.env.AUTH0_DOMAIN!, + clientId: process.env.AUTH0_CUSTOM_API_CLIENT_ID!, + clientSecret: process.env.AUTH0_CUSTOM_API_CLIENT_SECRET!, + }, +}); + +export const withGoogleCalendar = auth0AI.withTokenVault({ + connection: "google-oauth2", + scopes: ["https://www.googleapis.com/auth/calendar.freebusy"], + accessToken: async (_, config) => { + return config.configurable?.langgraph_auth_user?.getRawAccessToken(); + }, + subjectTokenType: SUBJECT_TOKEN_TYPES.SUBJECT_TYPE_ACCESS_TOKEN, +}); +``` + +Then reference the Auth0 Token Vault wrapper above in the tool's definition: + +```ts src/tools/google-calendar.ts wrap lines +import { addHours, formatISO } from "date-fns"; +import { GaxiosError } from "gaxios"; +import { google } from "googleapis"; + +import { getAccessTokenFromTokenVault } from "@auth0/ai-langchain"; +import { TokenVaultError } from "@auth0/ai/interrupts"; +import { tool } from "@langchain/core/tools"; + +import { withGoogleCalendar } from "../../auth0-ai"; + +export const checkUsersCalendar = withGoogleCalendar( + tool( + async ({ date }) => { + try { + const accessToken = getAccessTokenFromTokenVault(); + + const calendar = google.calendar("v3"); + const auth = new google.auth.OAuth2(); + + auth.setCredentials({ + access_token: accessToken, + }); + + const response = await calendar.freebusy.query({ + auth, + requestBody: { + timeMin: formatISO(date), + timeMax: addHours(date, 1).toISOString(), + timeZone: "UTC", + items: [{ id: "primary" }], + }, + }); + + return { + available: response.data?.calendars?.primary?.busy?.length === 0, + }; + } catch (err) { + if (err instanceof GaxiosError && err.status === 401) { + throw new TokenVaultError( + `Authorization required to access the Token Vault connection` + ); + } + throw err; + } + }, + ) +); +``` + +Great job! You've now set up the backend LangGraph API server with Auth0 AI SDK integration for secure third-party API access with your LangGraph tools. + +### Test your application +Start your application. If you are already logged in, make sure to log out and log back in using Google. Then, ask your AI agent to list the upcoming events in your Google Calendar! + +That's it! You successfully integrated third-party API access using Token Vault into your React SPA + LangGraph.js project. + +### View a complete example +Want to see how it all comes together? Explore or clone the fully implemented sample application on [GitHub](https://github.com/auth0-samples/auth0-ai-samples/tree/main/calling-apis-on-users-behalf/others-api/langchain-react-spa-js). +
+
diff --git a/auth4genai/snippets/get-started/react-spa-vercel-ai/call-others-api.mdx b/auth4genai/snippets/get-started/react-spa-vercel-ai/call-others-api.mdx new file mode 100644 index 000000000..6fc8582e2 --- /dev/null +++ b/auth4genai/snippets/get-started/react-spa-vercel-ai/call-others-api.mdx @@ -0,0 +1,567 @@ +import { Prerequisites } from "/snippets/get-started/prerequisites/call-others-api.jsx"; + + + +### Key differences from Next.js approach + +This React SPA implementation differs from the Next.js example in a few important ways: + +1. **Token Vault Access Token Exchange**: Instead of using refresh tokens, the React SPA implementation exchanges the SPA's access token for a third-party access token. +2. **Client-Side Authorization**: Client login and step-up authorization are handled client-side using `@auth0/auth0-spa-js`. +3. **Resource Server Client**: Requires a special Resource Server Client configured for token exchange with Token Vault. +4. **Interrupt Handling**: The React client manages tool access errors and step-up authorization using interrupts that trigger a pop-up for re-authorization. + +### Prepare React SPA + Hono API + +**Recommended**: To use this example, clone the [Auth0 AI JS](https://github.com/auth0-lab/auth0-ai-js.git) repository: + +```bash wrap lines +git clone https://github.com/auth0-lab/auth0-ai-js.git +cd auth0-ai-js/examples/calling-apis/spa-with-backend-api/react-hono-ai-sdk +``` + +### Install dependencies + +In the root directory of your project, you have the following client and server dependencies: + +**Client dependencies:** + +- `@auth0/auth0-spa-js`: Auth0 SPA SDK for client-side authentication +- `@auth0/ai-vercel`: [Auth0 AI SDK for Vercel AI](https://github.com/auth0-lab/auth0-ai-js/tree/main/packages/ai-vercel) built for GenAI applications +- `ai`: Core [Vercel AI SDK](https://sdk.vercel.ai/docs) module + +**Server dependencies:** + +- `@hono/node-server`: Node.js server adapter for Hono +- `hono`: Lightweight web framework +- `ai`: Core [Vercel AI SDK](https://sdk.vercel.ai/docs) module +- `@ai-sdk/openai`: [OpenAI](https://sdk.vercel.ai/providers/ai-sdk-providers/openai) provider +- `googleapis`: Node.js client for Google APIs +- `jose`: JavaScript Object Signing and Encryption library for JWT verification +To install all the client and server dependencies, navigate to the root directory of your project and run the following command: +```bash wrap lines +# Install all client & server dependencies from the root directory of the project. +npm install +``` + +### Update the environment files + +Add separate `.env` files with environment variables for the client and server. + +#### Client (client/.env) + +```bash .env wrap lines +VITE_AUTH0_DOMAIN=your-auth0-domain +VITE_AUTH0_CLIENT_ID=your-spa-client-id +VITE_AUTH0_AUDIENCE=your-api-identifier +VITE_API_URL=http://localhost:3001 +``` + +#### Server (server/.env) + +```bash .env wrap lines +AUTH0_DOMAIN=your-auth0-domain +AUTH0_AUDIENCE=your-api-identifier +AUTH0_CLIENT_ID=your-resource-server-client-id +AUTH0_CLIENT_SECRET=your-resource-server-client-secret +OPENAI_API_KEY=your-openai-api-key +PORT=3001 +``` + +### Configure the SPA for step-up authorization + +Unlike the Next.js example, which uses refresh tokens, this React SPA approach uses **access tokens** for token exchange with Token Vault. The SPA handles step-up authorization using Auth0 SPA SDK's `loginWithPopup()` method to display the consent screen and allow the user to grant additional permissions. + +Create `client/src/components/TokenVaultConsentPopup.tsx`: + +```tsx client/src/components/TokenVaultConsentPopup.tsx wrap lines +import { getAuth0Client } from "../lib/auth0"; +import { Button } from "./ui/button"; +import { Card, CardContent, CardHeader, CardTitle } from "./ui/card"; + +import type { Auth0InterruptionUI } from "@auth0/ai-vercel/react"; +interface TokenVaultConsentPopupProps { + interrupt: Auth0InterruptionUI; +} + +export function TokenVaultConsentPopup({ + interrupt, +}: TokenVaultConsentPopupProps) { + const [isLoading, setIsLoading] = useState(false); + + const { connection, requiredScopes, resume } = interrupt; + + // Use Auth0 SPA SDK to request additional connection/scopes + const startFederatedLogin = useCallback(async () => { + try { + setIsLoading(true); + + // Filter out empty scopes + const validScopes = requiredScopes.filter( + (scope: string) => scope && scope.trim() !== "" + ); + + const auth0Client = getAuth0Client(); + + // Use getTokenWithPopup for step-up authorization to request additional scopes + await auth0Client.getTokenWithPopup({ + authorizationParams: { + prompt: "consent", // Required for Google Calendar scopes + connection: connection, // e.g., "google-oauth2" + connection_scope: validScopes.join(" "), // Google-specific scopes + access_type: "offline", + }, + }); + + // The Auth0 client should automatically use the new token, but we should trigger + // a refresh to ensure the latest token is cached. + await auth0Client.getTokenSilently(); + + setIsLoading(false); + + // Resume the interrupted tool after successful authorization + if (typeof resume === "function") { + resume(); + } + } catch (error) { + setIsLoading(false); + + if (typeof resume === "function") { + resume(); + } + } + }, [connection, requiredScopes, resume]); + + if (isLoading) { + return ( + + +
+
+

+ Connecting to {connection.replace("-", " ")}... +

+
+
+
+ ); + } + + return ( + + + + Authorization Required + + + +

+ To access your {connection.replace("-", " ")} data, you need to authorize this application. +

+

+ Required permissions:{" "} + {requiredScopes + .filter((scope: string) => scope && scope.trim() !== "") + .join(", ")} +

+ +
+
+ ); +} +``` + +#### Create tools with integrated Token Vault support for retrieving third-party access tokens + +Next, create a tool that accesses Token Vault to fetch a Google access token to list all the Google Calendars a user has access to. + +Create `server/src/lib/tools/listUserCalendars.ts`: + +```ts server/src/lib/tools/listUserCalendars.ts wrap lines +import { tool } from "ai"; +import { google } from "googleapis"; +import { z } from "zod"; + +import { getAccessTokenFromTokenVault } from "@auth0/ai-vercel"; + +import type { ToolWrapper } from "@auth0/ai-vercel"; + +/** + * Tool: listUserCalendars + * Lists all calendars the user has access to. + * Uses the enhanced @auth0/ai SDK for token exchange with Token Vault. + */ +export const createListUserCalendarsTool = ( + googleCalendarWrapper: ToolWrapper +) => + googleCalendarWrapper( + tool({ + description: "List all calendars the user has access to", + parameters: z.object({}), + execute: async () => { + // Get the access token from Token Vault using the enhanced SDK + const token = getAccessTokenFromTokenVault(); + + const calendar = google.calendar("v3"); + const auth = new google.auth.OAuth2(); + auth.setCredentials({ access_token: token }); + + const res = await calendar.calendarList.list({ auth }); + + const calendars = + res.data.items?.map((cal) => ({ + id: cal.id, + name: cal.summary, + accessRole: cal.accessRole, + })) ?? []; + + return calendars; + }, + }) + ); +``` + +#### Configure the API server with Google connection wrapper for calendar tools + +Instantiate an instance of `Auth0AI` with a pre-configured resource client. Then, create a wrapper for the Google Calendar Tool that sets up the token exchange. This allows you to directly exchange an Auth0 access token for a Google access token from Token Vault with the necessary Calendar scopes. + +Create `server/src/lib/auth0.ts`: + +```ts server/src/lib/auth0.ts wrap lines +import { SUBJECT_TOKEN_TYPES } from "@auth0/ai"; +import { Auth0AI } from "@auth0/ai-vercel"; + +import type { Context } from "hono"; + +import type { ToolWrapper } from "@auth0/ai-vercel"; +// Create an Auth0AI instance configured with reserver client credentials +const auth0AI = new Auth0AI({ + auth0: { + domain: process.env.AUTH0_DOMAIN!, + clientId: process.env.RESOURCE_SERVER_CLIENT_ID!, // Resource server client ID for token exchange + clientSecret: process.env.RESOURCE_SERVER_CLIENT_SECRET!, // Resource server client secret + }, +}); + +// Enhanced token exchange with Token Vault, setup with access token support +// This demonstrates the new API pattern where access tokens can be used directly +export const createGoogleCalendarTool = (c: Context): ToolWrapper => { + const accessToken = c.get("auth")?.token; + if (!accessToken) { + throw new Error("Access token not available in auth context"); + } + return auth0AI.withTokenVault({ + accessToken: async () => accessToken, + subjectTokenType: SUBJECT_TOKEN_TYPES.SUBJECT_TYPE_ACCESS_TOKEN, + connection: process.env.GOOGLE_CONNECTION_NAME || "google-oauth2", + scopes: [ + "https://www.googleapis.com/auth/calendar.calendarlist.readonly", // Read-only access to calendar list + "https://www.googleapis.com/auth/calendar.events.readonly", // Read-only access to events + ], + }); +}; +``` + +### Create Hono API Chat API server with interrupt handling + +Create an AI-powered chat server using Hono, the Auth0 AI SDK, and the Vercel AI SDK that allows a user to chat with an AI assistant that can access their Google Calendar. + +The Auth0 AI SDK's `withInterruptions()` function wraps the Vercel AI SDK's `streamText()` function, enabling the Hono server to handle interrupts, which are special responses from Token Vault. An interrupt is sent if a tool call requires a new or updated access token, for example, if a user needs to re-authenticate or a new permission is needed. + +Create `server/src/index.ts`: + +```ts server/src/index.ts wrap lines +import { + createDataStreamResponse, + generateId, + streamText, + ToolExecutionError, +} from "ai"; +import { Hono } from "hono"; +import { cors } from "hono/cors"; +import { decodeJwt } from "jose"; + +import { openai } from "@ai-sdk/openai"; +import { setAIContext } from "@auth0/ai-vercel"; +import { InterruptionPrefix, withInterruptions } from "@auth0/ai-vercel/interrupts"; +import { Auth0Interrupt } from "@auth0/ai/interrupts"; +import { serve } from "@hono/node-server"; + +import { listUserCalendars } from "./lib/tools/listUserCalendars"; +import { jwtAuthMiddleware } from "./middleware/auth"; + +import type { ApiResponse } from "shared/dist"; + +export const app = new Hono().post("/chat", jwtAuthMiddleware(), async (c) => { + // auth middleware adds the auth context to the request + const auth = c.get("auth"); + + const { messages: requestMessages } = await c.req.json(); + + // Generate a thread ID for this conversation + const threadID = generateId(); + + // Set AI context for the tools to access + setAIContext({ threadID }); + + // Create the Google Calendar wrapper with auth context + const googleCalendarWrapper = createGoogleCalendarTool(c); + + // Create tools with the auth context + const listUserCalendars = createListUserCalendarsTool(googleCalendarWrapper); + + // Use the messages from the request directly + const tools = { listUserCalendars }; + + // note: you can see more examples of Hono API consumption with AI SDK here: + // https://ai-sdk.dev/cookbook/api-servers/hono?utm_source=chatgpt.com#hono + + return createDataStreamResponse({ + execute: withInterruptions( + async (dataStream) => { + const result = streamText({ + model: openai("gpt-4o-mini"), + system: + "You are a helpful calendar assistant! You can help users with their calendar events and schedules. Keep your responses concise and helpful.", + messages: requestMessages, + maxSteps: 5, + tools, + }); + + result.mergeIntoDataStream(dataStream, { + sendReasoning: true, + }); + }, + { messages: requestMessages, tools } + ), + onError: (error: any) => { + // Handle Auth0 AI interrupts + if ( + error.cause instanceof Auth0Interrupt || + error.cause instanceof TokenVaultInterrupt + ) { + const serializableError = { + ...error.cause.toJSON(), + toolCall: { + id: error.toolCallId, + args: error.toolArgs, + name: error.toolName, + }, + }; + + return `${InterruptionPrefix}${JSON.stringify(serializableError)}`; + } + + return "Oops! An error occurred."; + }, + }); + }); + +// Start the server for Node.js +const port = Number(process.env.PORT) || 3000; + +console.log(`🚀 Server starting on port ${port}`); +serve({ fetch: app.fetch, port }); + +console.log(`✅ Server running on http://localhost:${port}`); +``` + +### Implement interrupt handling in React + +Update your chat component to handle step-up auth interrupts: + +```tsx client/src/components/Chat.tsx wrap lines highlight={3,5,12,18-33,49-65, 124-126} +import { Loader2, Send, Trash2 } from "lucide-react"; +import { useChat } from "@ai-sdk/react"; +import { useInterruptions } from "@auth0/ai-vercel/react"; +import { useAuth0 } from "../hooks/useAuth0"; +import { TokenVaultConsentPopup } from "./TokenVaultConsentPopup"; +import { Button } from "./ui/button"; +import { Card, CardContent, CardHeader, CardTitle } from "./ui/card"; +import { Input } from "./ui/input"; + +import type { Message } from "ai"; + +const InterruptionPrefix = "AUTH0_AI_INTERRUPTION:"; +const SERVER_URL = import.meta.env.VITE_SERVER_URL; + +export function Chat() { + const { getToken } = useAuth0(); + + const chatHelpers = useInterruptions((errorHandler) => + useChat({ + api: `${SERVER_URL}/chat`, + fetch: async (url: string | URL | Request, init?: RequestInit) => { + const token = await getToken(); + return fetch(url, { + ...init, + headers: { + "Content-Type": "application/json", + ...init?.headers, + Authorization: `Bearer ${token}`, + }, + }); + }, + }) + ); + + const { + messages, + input, + handleInputChange, + handleSubmit, + isLoading, + error, + setMessages, + toolInterrupt, + } = chatHelpers; + + // Filter out interrupted tool calls from messages + let displayMessages = messages; + + if (toolInterrupt) { + displayMessages = messages.map((message) => ({ + ...message, + parts: message.parts?.map((part) => + part.type === "tool-invocation" && + part.toolInvocation.toolCallId === toolInterrupt.toolCall?.id + ? { + ...part, + toolInvocation: { + ...part.toolInvocation, + state: "call", + }, + } + : part + ), + })); + } + + const clearMessages = () => { + setMessages([]); + }; + + return ( + + + + Calendar Assistant + + {messages.length > 0 && ( + + )} + + + {/* Messages */} +
+ {displayMessages.length === 0 ? ( +
+

Ask me about your calendar events!

+

+ Try: "What meetings do I have today?" or "Show me my upcoming + events" +

+
+ ) : ( + displayMessages.map((message) => ( + + )) + )} + {isLoading && ( +
+
+ + + Thinking... + +
+
+ )} +
+ + {/* Error message - hide if it's an Auth0 interrupt (we show the popup instead) */} + {error && !error.message.startsWith(InterruptionPrefix) && ( +
+ Error: {error.message} +
+ )} + + {/* Step-Up Auth Interrupt Handling */} + {toolInterrupt && ( + + )} + + {/* Input form */} +
+ + +
+
+
+ ); +} + +function MessageBubble({ message }: { message: Message }) { + const isUser = message.role === "user"; + + return ( +
+
+

{message.content}

+
+
+ ); +} +``` + +### Test your application + +1. Start the client and server using Turbo: `npm run dev`. +2. Navigate to `http://localhost:5173`. +3. Log in with Google and ask your AI agent about your calendar. + +The application will automatically prompt for additional calendar permissions when needed using Auth0's step-up authorization flow. + +That's it! You've successfully integrated Token Vault with access tokens into your React SPA + Vercel AI application. + +Explore [the example app on GitHub](https://github.com/auth0-lab/auth0-ai-js/tree/main/examples/calling-apis/spa-with-backend-api/react-hono-ai-sdk). diff --git a/auth4genai/snippets/get-started/vercel-ai-next-js/async-auth.mdx b/auth4genai/snippets/get-started/vercel-ai-next-js/async-auth.mdx index 605bc30b6..f675aab60 100644 --- a/auth4genai/snippets/get-started/vercel-ai-next-js/async-auth.mdx +++ b/auth4genai/snippets/get-started/vercel-ai-next-js/async-auth.mdx @@ -36,7 +36,7 @@ Integrate the Auth0 AI SDK into your application to secure your async AI agent w #### Configure the Auth0 AI SDK -To require asynchronous authorization for your tool, the tool needs to be wrapped with the Async authorizer, `withAsyncUserConfirmation()`. Let's create a helper function to wrap the tool with the Async authorizer. +To require asynchronous authorization for your tool, the tool needs to be wrapped with the Async authorizer, `withAsyncAuthorization()`. Let's create a helper function to wrap the tool with the Async authorizer. Create a file at `src/lib/auth0-ai.ts` and instantiate a new Auth0 AI SDK client: @@ -48,8 +48,8 @@ import { getUser } from "./auth0"; const auth0AI = new Auth0AI(); -// CIBA flow for user confirmation -export const withAsyncAuthorization = auth0AI.withAsyncUserConfirmation({ +// Async Authorization flow for user confirmation +export const withAsyncAuthorization = auth0AI.withAsyncAuthorization({ userID: async () => { const user = await getUser(); return user?.sub as string; @@ -114,7 +114,7 @@ Now, create and wrap the tool with the Async authorizer. Create a file `src/lib/ import { tool } from "ai"; import { z } from "zod"; -import { getCIBACredentials } from "@auth0/ai-vercel"; +import { getAsyncAuthorizationCredentials } from "@auth0/ai-vercel"; import { withAsyncAuthorization } from "../auth0-ai"; export const shopOnlineTool = withAsyncAuthorization( @@ -145,7 +145,7 @@ export const shopOnlineTool = withAsyncAuthorization( priceLimit, }; - const credentials = getCIBACredentials(); + const credentials = getAsyncAuthorizationCredentials(); const accessToken = credentials?.accessToken; if (accessToken) { diff --git a/auth4genai/snippets/get-started/vercel-ai-next-js/call-others-api.mdx b/auth4genai/snippets/get-started/vercel-ai-next-js/call-others-api.mdx index 6867b1b42..1198be748 100644 --- a/auth4genai/snippets/get-started/vercel-ai-next-js/call-others-api.mdx +++ b/auth4genai/snippets/get-started/vercel-ai-next-js/call-others-api.mdx @@ -7,7 +7,7 @@ import { AccountAndAppSteps } from "/snippets/get-started/prerequisites/account- - + ### Clone sample app Clone this sample app from the [Auth0 AI samples](https://github.com/auth0-samples/auth0-ai-samples) repository: @@ -119,16 +119,16 @@ Use the [Auth0 AI SDK for Vercel AI](https://github.com/auth0-lab/auth0-ai-js/tr Create a file at `src/lib/auth0-ai.ts` to instantiate the Auth0 AI SDK client: ```tsx src/lib/auth0-ai.ts wrap lines -import { Auth0AI, getAccessTokenForConnection } from "@auth0/ai-vercel"; +import { Auth0AI, getAccessTokenFromTokenVault } from "@auth0/ai-vercel"; import { getRefreshToken } from "./auth0"; // Get the access token for a connection via Auth0 -export const getAccessToken = async () => getAccessTokenForConnection(); +export const getAccessToken = async () => getAccessTokenFromTokenVault(); const auth0AI = new Auth0AI(); // Connection for Google services -export const withGoogleConnection = auth0AI.withTokenForConnection({ +export const withGoogleConnection = auth0AI.withTokenVault({ connection: "google-oauth2", scopes: ["https://www.googleapis.com/auth/calendar.events"], refreshToken: getRefreshToken, @@ -158,7 +158,7 @@ Once the user is authenticated, you can fetch an access token from the Token Vau Once you've obtained the access token for a social connection, you can use it with an AI agent to fetch data during a tool call and provide contextual data in its response. In this example, we define a tool call, `getCalendarEventsTool`, that uses the access token with the Google Calendar API to query for calendar events on a specific date. -Update your tool call to request an access token similar to this example: +Update your tool call to request an access token similar to this example: ```ts src/lib/tools/google-calendar.ts wrap lines import { tool } from 'ai'; @@ -166,7 +166,7 @@ import { endOfDay, formatISO, startOfDay } from 'date-fns'; import { GaxiosError } from 'gaxios'; import { google } from 'googleapis'; import { z } from 'zod'; -import { FederatedConnectionError } from '@auth0/ai/interrupts'; +import { TokenVaultError } from '@auth0/ai/interrupts'; import { getAccessToken, withGoogleConnection } from '../auth0-ai'; @@ -225,7 +225,7 @@ export const getCalendarEventsTool = withGoogleConnection( } catch (error) { if (error instanceof GaxiosError) { if (error.status === 401) { - throw new FederatedConnectionError(`Authorization required to access the Federated Connection`); + throw new TokenVaultError(`Authorization required to access the Token Vault connection`); } } @@ -244,31 +244,31 @@ When you try to use the tool, the application requests any additional Google sco To implement, install the Auth0 AI Components for Next.js SDK to get the required UI components: ```bash wrap lines -npx @auth0/ai-components add FederatedConnections +npx @auth0/ai-components add TokenVault ``` -Add a new file, `src/components/auth0-ai/FederatedConnections/FederatedConnectionInterruptHandler.tsx` with the following code: +Add a new file, `src/components/auth0-ai/TokenVault/TokenVaultInterruptHandler.tsx` with the following code: -```tsx src/components/auth0-ai/FederatedConnections/FederatedConnectionInterruptHandler.tsx wrap lines -import { FederatedConnectionInterrupt } from "@auth0/ai/interrupts"; +```tsx src/components/auth0-ai/TokenVault/TokenVaultInterruptHandler.tsx wrap lines +import { TokenVaultInterrupt } from "@auth0/ai/interrupts"; import type { Auth0InterruptionUI } from "@auth0/ai-vercel/react"; -import { EnsureAPIAccess } from "@/components/auth0-ai/FederatedConnections"; +import { TokenVaultConsent } from "@/components/auth0-ai/TokenVault"; -interface FederatedConnectionInterruptHandlerProps { +interface TokenVaultInterruptHandlerProps { interrupt: Auth0InterruptionUI | null; } -export function FederatedConnectionInterruptHandler({ +export function TokenVaultInterruptHandler({ interrupt, -}: FederatedConnectionInterruptHandlerProps) { - if (!FederatedConnectionInterrupt.isInterrupt(interrupt)) { +}: TokenVaultInterruptHandlerProps) { + if (!TokenVaultInterrupt.isInterrupt(interrupt)) { return null; } return (
-
- +
) @@ -395,4 +395,4 @@ That's it! You successfully integrated third-party API access using Token Vault Want to see how it all comes together? Explore or clone the fully implemented sample application [here on GitHub](https://github.com/auth0-samples/auth0-ai-samples/tree/main/call-apis-on-users-behalf/others-api/vercel-ai-next-js). - \ No newline at end of file + diff --git a/auth4genai/snippets/get-started/vercel-ai-node-js/async-auth.mdx b/auth4genai/snippets/get-started/vercel-ai-node-js/async-auth.mdx index 5b155a86f..4cb58d2f0 100644 --- a/auth4genai/snippets/get-started/vercel-ai-node-js/async-auth.mdx +++ b/auth4genai/snippets/get-started/vercel-ai-node-js/async-auth.mdx @@ -52,11 +52,11 @@ STOCK_API_AUDIENCE=sample-stock-api #### 2. Require async authorization for your tool -To require asynchronous authorization for your tool wrap the tool with the Async authorizer, `withAsyncUserConfirmation()`. +To require asynchronous authorization for your tool wrap the tool with the Async authorizer, `withAsyncAuthorization()`. -Wrap the tool with the Async authorizer in `src/lib/tools/buy.ts`. This will intercept the tool call to initiate a CIBA request: +Wrap the tool with the Async authorizer in `src/lib/tools/buy.ts`. This will intercept the tool call to initiate an Async Authorization request: -- The CIBA request includes the user ID that will approve the request. +- The Async Authorization request includes the user ID that will approve the request. - Auth0 sends the user a mobile push notification. The AI agent polls the `/token` endpoint for a user response. - The mobile application retrieves the `binding_message` containing the consent details, in this case, the quantity of stock to purchase for a stock ticker. - The user responds to the request: @@ -80,7 +80,7 @@ import "dotenv/config"; import { tool } from "ai"; import { z } from "zod"; -import { Auth0AI, getCIBACredentials } from "@auth0/ai-vercel"; +import { Auth0AI, getAsyncAuthorizationCredentials } from "@auth0/ai-vercel"; import { AccessDeniedInterrupt } from "@auth0/ai/interrupts"; export type Context = { userId: string; @@ -90,7 +90,7 @@ const auth0AI = new Auth0AI(); export const buy = (context: Context) => { // highlight-next-line - const withAsyncAuthorization = auth0AI.withAsyncUserConfirmation({ + const withAsyncAuthorization = auth0AI.withAsyncAuthorization({ // highlight-next-line userID: context.userId, // highlight-next-line @@ -135,7 +135,7 @@ export const buy = (context: Context) => { qty: qty, }; // highlight-next-line - const credentials = getCIBACredentials(); + const credentials = getAsyncAuthorizationCredentials(); const accessToken = credentials?.accessToken?.value; if (accessToken) { diff --git a/auth4genai/snippets/get-started/vercel-ai-react-spa-js/call-others-api.mdx b/auth4genai/snippets/get-started/vercel-ai-react-spa-js/call-others-api.mdx index f5f998c49..7dcf629d2 100644 --- a/auth4genai/snippets/get-started/vercel-ai-react-spa-js/call-others-api.mdx +++ b/auth4genai/snippets/get-started/vercel-ai-react-spa-js/call-others-api.mdx @@ -88,21 +88,21 @@ PORT=3001 Unlike the Next.js example, which uses refresh tokens, this React SPA approach uses **access tokens** for token exchange with Token Vault. The SPA handles step-up authorization using Auth0 SPA SDK's `loginWithPopup()` method to display the consent screen and allow the user to grant additional permissions. -Create `client/src/components/FederatedConnectionPopup.tsx`: +Create `client/src/components/TokenVaultConsentPopup.tsx`: -```tsx client/src/components/FederatedConnectionPopup.tsx wrap lines +```tsx client/src/components/TokenVaultConsentPopup.tsx wrap lines import { getAuth0Client } from "../lib/auth0"; import { Button } from "./ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "./ui/card"; import type { Auth0InterruptionUI } from "@auth0/ai-vercel/react"; -interface FederatedConnectionPopupProps { +interface TokenVaultConsentPopupProps { interrupt: Auth0InterruptionUI; } -export function FederatedConnectionPopup({ +export function TokenVaultConsentPopup({ interrupt, -}: FederatedConnectionPopupProps) { +}: TokenVaultConsentPopupProps) { const [isLoading, setIsLoading] = useState(false); const { connection, requiredScopes, resume } = interrupt; @@ -200,7 +200,7 @@ import { tool } from "ai"; import { google } from "googleapis"; import { z } from "zod"; -import { getAccessTokenForConnection } from "@auth0/ai-vercel"; +import { getAccessTokenFromTokenVault } from "@auth0/ai-vercel"; import type { ToolWrapper } from "@auth0/ai-vercel"; @@ -218,7 +218,7 @@ export const createListUserCalendarsTool = ( parameters: z.object({}), execute: async () => { // Get the access token from Token Vault using the enhanced SDK - const token = getAccessTokenForConnection(); + const token = getAccessTokenFromTokenVault(); const calendar = google.calendar("v3"); const auth = new google.auth.OAuth2(); @@ -268,7 +268,7 @@ export const createGoogleCalendarTool = (c: Context): ToolWrapper => { if (!accessToken) { throw new Error("Access token not available in auth context"); } - return auth0AI.withTokenForConnection({ + return auth0AI.withTokenVault({ accessToken: async () => accessToken, subjectTokenType: SUBJECT_TOKEN_TYPES.SUBJECT_TYPE_ACCESS_TOKEN, connection: process.env.GOOGLE_CONNECTION_NAME || "google-oauth2", @@ -356,7 +356,7 @@ export const app = new Hono().post("/chat", jwtAuthMiddleware(), async (c) => { // Handle Auth0 AI interrupts if ( error.cause instanceof Auth0Interrupt || - error.cause instanceof FederatedConnectionInterrupt + error.cause instanceof TokenVaultInterrupt ) { const serializableError = { ...error.cause.toJSON(), @@ -393,7 +393,7 @@ import { Loader2, Send, Trash2 } from "lucide-react"; import { useChat } from "@ai-sdk/react"; import { useInterruptions } from "@auth0/ai-vercel/react"; import { useAuth0 } from "../hooks/useAuth0"; -import { FederatedConnectionPopup } from "./FederatedConnectionPopup"; +import { TokenVaultConsentPopup } from "./TokenVaultConsentPopup"; import { Button } from "./ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "./ui/card"; import { Input } from "./ui/input"; @@ -513,7 +513,7 @@ export function Chat() { {/* Step-Up Auth Interrupt Handling */} {toolInterrupt && ( - + )} {/* Input form */} @@ -563,6 +563,6 @@ function MessageBubble({ message }: { message: Message }) { The application will automatically prompt for additional calendar permissions when needed using Auth0's step-up authorization flow. -That's it! You've successfully integrated federated connections with access tokens into your React SPA + Vercel AI application. +That's it! You've successfully integrated Token Vault with access tokens into your React SPA + Vercel AI application. Explore [the example app on GitHub](https://github.com/auth0-lab/auth0-ai-js/tree/main/examples/calling-apis/spa-with-backend-api/react-hono-ai-sdk). diff --git a/auth4genai/snippets/how-tos/github/ai-sdk.mdx b/auth4genai/snippets/how-tos/github/ai-sdk.mdx index 7e19b69d5..0b17715bb 100644 --- a/auth4genai/snippets/how-tos/github/ai-sdk.mdx +++ b/auth4genai/snippets/how-tos/github/ai-sdk.mdx @@ -14,7 +14,7 @@ import { auth0 } from "@/lib/auth0"; const auth0AI = new Auth0AI(); -export const withGitHub = auth0AI.withTokenForConnection({ +export const withGitHub = auth0AI.withTokenVault({ connection: "github", scopes: ["repo"], refreshToken: async () => { @@ -37,8 +37,8 @@ Wrap your tool using the Auth0 AI SDK to obtain an access token for the GitHub A ```typescript ./src/lib/tools/listRepositories.ts wrap lines highlight={2-4,9,15,19-21,31-33} import { Octokit, RequestError } from "octokit"; -import { getAccessTokenForConnection } from "@auth0/ai-vercel"; -import { FederatedConnectionError } from "@auth0/ai/interrupts"; +import { getAccessTokenFromTokenVault } from "@auth0/ai-vercel"; +import { TokenVaultError } from "@auth0/ai/interrupts"; import { withGitHub } from "@/lib/auth0-ai"; import { tool } from "ai"; import { z } from "zod"; @@ -50,7 +50,7 @@ export const listRepositories = withGitHub( parameters: z.object({}), execute: async () => { // Get the access token from Auth0 AI - const accessToken = getAccessTokenForConnection(); + const accessToken = getAccessTokenFromTokenVault(); // GitHub SDK try { @@ -66,8 +66,8 @@ export const listRepositories = withGitHub( if (error instanceof RequestError) { if (error.status === 401) { - throw new FederatedConnectionError( - `Authorization required to access the Federated Connection` + throw new TokenVaultError( + `Authorization required to access the Token Vault connection` ); } } @@ -126,10 +126,10 @@ export async function POST(request: Request) { #### Client Side -On this example we utilize the `EnsureAPIAccessPopup` component to show a popup that allows the user to authenticate with GitHub and grant access with the requested scopes. You'll first need to install the `@auth0/ai-components` package: +On this example we utilize the `TokenVaultConsentPopup` component to show a popup that allows the user to authenticate with GitHub and grant access with the requested scopes. You'll first need to install the `@auth0/ai-components` package: ```bash wrap lines -npx @auth0/ai-components add FederatedConnections +npx @auth0/ai-components add TokenVault ``` Then, you can integrate the authentication popup in your chat component, using the interruptions helper from the SDK: @@ -139,8 +139,8 @@ Then, you can integrate the authentication popup in your chat component, using t import { useChat } from "@ai-sdk/react"; import { useInterruptions } from "@auth0/ai-vercel/react"; -import { FederatedConnectionInterrupt } from "@auth0/ai/interrupts"; -import { EnsureAPIAccessPopup } from "@/components/auth0-ai/FederatedConnections/popup"; +import { TokenVaultInterrupt } from "@auth0/ai/interrupts"; +import { TokenVaultConsentPopup } from "@/components/auth0-ai/TokenVault/popup"; export default function Chat() { const { messages, handleSubmit, input, setInput, toolInterrupt } = @@ -159,8 +159,8 @@ export default function Chat() {
))} - {FederatedConnectionInterrupt.isInterrupt(toolInterrupt) && ( - ({ threadID: getAgent().name })); const auth0AI = new Auth0AI(); -export const withGitHub = auth0AI.withTokenForConnection({ +export const withGitHub = auth0AI.withTokenVault({ connection: "github", scopes: ["repo"], refreshToken: async () => { @@ -52,8 +52,8 @@ Wrap your tool using the Auth0 AI SDK to obtain an access token for the Github A ```typescript ./src/agent/tools/listRepositories.ts wrap lines highlight={2-4,9,15,19-21,31-33} import { Octokit, RequestError } from "octokit"; -import { getAccessTokenForConnection } from "@auth0/ai-vercel"; -import { FederatedConnectionError } from "@auth0/ai/interrupts"; +import { getAccessTokenFromTokenVault } from "@auth0/ai-vercel"; +import { TokenVaultError } from "@auth0/ai/interrupts"; import { withGitHub } from "@/lib/auth0-ai"; import { tool } from "ai"; import { z } from "zod"; @@ -65,7 +65,7 @@ export const listRepositories = withGitHub( parameters: z.object({}), execute: async () => { // Get the access token from Auth0 AI - const accessToken = getAccessTokenForConnection(); + const accessToken = getAccessTokenFromTokenVault(); // GitHub SDK try { @@ -81,8 +81,8 @@ export const listRepositories = withGitHub( if (error instanceof RequestError) { if (error.status === 401) { - throw new FederatedConnectionError( - `Authorization required to access the Federated Connection` + throw new TokenVaultError( + `Authorization required to access the Token Vault connection` ); } } @@ -180,10 +180,10 @@ The name of the user is ${claims?.name ?? "unknown"}. #### Client Side -On this example we utilize the `EnsureAPIAccessPopup` component to show a popup that allows the user to authenticate with Github and grant access with the requested scopes. You'll first need to install the `@auth0/ai-components` package: +On this example we utilize the `TokenVaultConsentPopup` component to show a popup that allows the user to authenticate with Github and grant access with the requested scopes. You'll first need to install the `@auth0/ai-components` package: ```bash wrap lines -npx @auth0/ai-components add FederatedConnections +npx @auth0/ai-components add TokenVault ``` Then, you can integrate the authentication popup in your chat component, using the interruptions helper from the SDK: @@ -193,8 +193,8 @@ Then, you can integrate the authentication popup in your chat component, using t import { useChat } from "@ai-sdk/react"; import { useAgentChatInterruptions } from "@auth0/ai-cloudflare/react"; -import { FederatedConnectionInterrupt } from "@auth0/ai/interrupts"; -import { EnsureAPIAccessPopup } from "@/components/auth0-ai/FederatedConnections/popup"; +import { TokenVaultInterrupt } from "@auth0/ai/interrupts"; +import { TokenVaultConsentPopup } from "@/components/auth0-ai/TokenVault/popup"; export default function Chat() { @@ -221,8 +221,8 @@ export default function Chat() {
))} - {FederatedConnectionInterrupt.isInterrupt(toolInterrupt) && ( - { @@ -42,8 +42,8 @@ Wrap your tool using the Auth0 AI SDK to obtain an access token for the GitHub A ```typescript ./src/lib/tools/listRepositories.ts wrap lines highlight={3-5,11,19,33-35} import { Octokit, RequestError } from "octokit"; import { z } from "zod"; -import { getAccessTokenForConnection } from "@auth0/ai-genkit"; -import { FederatedConnectionError } from "@auth0/ai/interrupts"; +import { getAccessTokenFromTokenVault } from "@auth0/ai-genkit"; +import { TokenVaultError } from "@auth0/ai/interrupts"; import { withGoogleCalendar } from "@/lib/auth0-ai"; // importing GenKit instance @@ -58,7 +58,7 @@ export const listRepositories = ai.defineTool( }, async () => { // Get the access token from Auth0 AI - const accessToken = getAccessTokenForConnection(); + const accessToken = getAccessTokenFromTokenVault(); try { // GitHub SDK @@ -72,8 +72,8 @@ export const listRepositories = ai.defineTool( } catch (error) { if (error instanceof RequestError) { if (error.status === 401) { - throw new FederatedConnectionError( - `Authorization required to access the Federated Connection` + throw new TokenVaultError( + `Authorization required to access the Token Vault connection` ); } } @@ -174,10 +174,10 @@ export async function GET( #### Client Side -On this example we utilize the `EnsureAPIAccessPopup` component to show a popup that allows the user to authenticate with Google Calendar and grant access with the requested scopes. You'll first need to install the `@auth0/ai-components` package: +On this example we utilize the `TokenVaultConsentPopup` component to show a popup that allows the user to authenticate with Google Calendar and grant access with the requested scopes. You'll first need to install the `@auth0/ai-components` package: ```bash wrap lines -npx @auth0/ai-components add FederatedConnections +npx @auth0/ai-components add TokenVault ``` Then, you can integrate the authentication popup in your chat component, using the interruptions helper from the SDK: @@ -186,8 +186,8 @@ Then, you can integrate the authentication popup in your chat component, using t "use client"; import { useQueryState } from "nuqs"; import { FormEventHandler, useEffect, useRef, useState } from "react"; -import { FederatedConnectionInterrupt } from "@auth0/ai/interrupts"; -import { EnsureAPIAccessPopup } from "@/components/auth0-ai/FederatedConnections/popup"; +import { TokenVaultInterrupt } from "@auth0/ai/interrupts"; +import { TokenVaultConsentPopup } from "@/components/auth0-ai/TokenVault/popup"; import Markdown from "react-markdown"; const useFocus = () => { @@ -304,14 +304,14 @@ export default function Chat() { {!isLoading && message.content[0].metadata?.interrupt && - FederatedConnectionInterrupt.isInterrupt( + TokenVaultInterrupt.isInterrupt( message.content[0].metadata?.interrupt ) ? (() => { const interrupt: any = message.content[0].metadata?.interrupt; return (
- submit({ interruptedToolRequest: message.content[0] })} interrupt={interrupt} connectWidget={{ diff --git a/auth4genai/snippets/how-tos/github/langgraph-python.mdx b/auth4genai/snippets/how-tos/github/langgraph-python.mdx index 3388d5bac..6ed811355 100644 --- a/auth4genai/snippets/how-tos/github/langgraph-python.mdx +++ b/auth4genai/snippets/how-tos/github/langgraph-python.mdx @@ -13,7 +13,7 @@ from auth0_ai_langchain.auth0_ai import Auth0AI auth0_ai = Auth0AI() -with_github = auth0_ai.with_federated_connection( +with_github = auth0_ai.with_token_vault( connection="github", scopes=["repo"] # Optional: By default, the SDK will expect the refresh token from @@ -32,7 +32,7 @@ from github import Github from github.GithubException import BadCredentialsException from pydantic import BaseModel from langchain_core.tools import StructuredTool -from auth0_ai_langchain.federated_connections import get_access_token_for_connection, FederatedConnectionError +from auth0_ai_langchain.token_vault import get_access_token_from_token_vault, TokenVaultError from src.lib.auth0_ai import with_github class EmptySchema(BaseModel): @@ -40,7 +40,7 @@ class EmptySchema(BaseModel): def list_repositories_tool_function(date: datetime): # Get the access token from Auth0 AI - access_token = get_access_token_for_connection() + access_token = get_access_token_from_token_vault() # GitHub SDK try: @@ -50,7 +50,7 @@ def list_repositories_tool_function(date: datetime): repo_names = [repo.name for repo in repos] return repo_names except BadCredentialsException: - raise FederatedConnectionError("Authorization required to access the Federated Connection API") + raise TokenVaultError("Authorization required to access the Token Vault API") list_github_repositories_tool = with_github(StructuredTool( name="list_github_repositories", @@ -98,7 +98,7 @@ workflow = ( "tools", ToolNode( [ - # a tool with federated connection access + # a tool with Token Vault access list_github_repositories_tool, # ... other tools ], @@ -167,18 +167,18 @@ You can check different authentication options for Next.js with Auth0 at the [of #### Client Side -On this example we utilize the `EnsureAPIAccessPopup` component to show a popup that allows the user to authenticate with GitHub and grant access with the requested scopes. You'll first need to install the `@auth0/ai-components` package: +On this example we utilize the `TokenVaultConsentPopup` component to show a popup that allows the user to authenticate with GitHub and grant access with the requested scopes. You'll first need to install the `@auth0/ai-components` package: ```bash wrap lines -npx @auth0/ai-components add FederatedConnections +npx @auth0/ai-components add TokenVault ``` Then, you can integrate the authentication popup in your chat component, using the interruptions helper from the SDK: ```tsx ./src/components/chat.tsx wrap lines highlight={2-3,62-74} import { useStream } from "@langchain/langgraph-sdk/react"; -import { FederatedConnectionInterrupt } from "@auth0/ai/interrupts"; -import { EnsureAPIAccessPopup } from "@/components/auth0-ai/FederatedConnections/popup"; +import { TokenVaultInterrupt } from "@auth0/ai/interrupts"; +import { TokenVaultConsentPopup } from "@/components/auth0-ai/TokenVault/popup"; const useFocus = () => { const htmlElRef = useRef(null); @@ -237,9 +237,9 @@ export default function Chat() {
))} - {thread.interrupt && FederatedConnectionInterrupt.isInterrupt(thread.interrupt.value) ? ( + {thread.interrupt && TokenVaultInterrupt.isInterrupt(thread.interrupt.value) ? (
- thread.submit(null)} connectWidget={{ diff --git a/auth4genai/snippets/how-tos/github/langgraph.mdx b/auth4genai/snippets/how-tos/github/langgraph.mdx index c6adce65c..161d14244 100644 --- a/auth4genai/snippets/how-tos/github/langgraph.mdx +++ b/auth4genai/snippets/how-tos/github/langgraph.mdx @@ -21,7 +21,7 @@ const auth0AI = new Auth0AI({ }); const withAccessTokenForConnection = (connection: string, scopes: string[]) => - auth0AI.withTokenForConnection({ + auth0AI.withTokenVault({ connection, scopes, accessToken: async (_, config) => { @@ -40,8 +40,8 @@ Wrap your tool using the Auth0 AI SDK to obtain an access token for the GitHub A ```typescript ./src/lib/tools/listRepositories.ts wrap lines highlight={3-5,9,12,16-18,28-30} import { Octokit } from "@octokit/rest"; import { RequestError } from "@octokit/request-error"; -import { getAccessTokenForConnection } from "@auth0/ai-langchain"; -import { FederatedConnectionError } from "@auth0/ai/interrupts"; +import { getAccessTokenFromTokenVault } from "@auth0/ai-langchain"; +import { TokenVaultError } from "@auth0/ai/interrupts"; import { withGitHub } from "@/lib/auth0-ai"; import { tool } from "@langchain/core/tools"; import { z } from "zod"; @@ -49,7 +49,7 @@ import { z } from "zod"; export const listRepositories = withGitHub( tool(async () => { // Get the access token from Auth0 AI - const accessToken = getAccessTokenForConnection(); + const accessToken = getAccessTokenFromTokenVault(); // GitHub SDK try { @@ -65,8 +65,8 @@ export const listRepositories = withGitHub( if (error instanceof RequestError) { if (error.status === 401) { - throw new FederatedConnectionError( - `Authorization required to access the Federated Connection` + throw new TokenVaultError( + `Authorization required to access the Token Vault connection` ); } } @@ -116,7 +116,7 @@ const stateGraph = new StateGraph(MessagesAnnotation) "tools", new ToolNode( [ - // A tool with federated connection access + // A tool with Token Vault access listRepositories, // ... other tools ], @@ -297,18 +297,18 @@ export { auth as authHandler }; #### Client Side -On this example we utilize the `EnsureAPIAccessPopup` component to show a popup that allows the user to authenticate with GitHub and grant access with the requested scopes. You'll first need to install the `@auth0/ai-components` package: +On this example we utilize the `TokenVaultConsentPopup` component to show a popup that allows the user to authenticate with GitHub and grant access with the requested scopes. You'll first need to install the `@auth0/ai-components` package: ```bash wrap lines -npx @auth0/ai-components add FederatedConnections +npx @auth0/ai-components add TokenVault ``` Then, you can integrate the authentication popup in your chat component, using the interruptions helper from the SDK: ```tsx ./src/components/chat.tsx wrap lines highlight={2-3,62-74} import { useStream } from "@langchain/langgraph-sdk/react"; -import { FederatedConnectionInterrupt } from "@auth0/ai/interrupts"; -import { EnsureAPIAccessPopup } from "@/components/auth0-ai/FederatedConnections/popup"; +import { TokenVaultInterrupt } from "@auth0/ai/interrupts"; +import { TokenVaultConsentPopup } from "@/components/auth0-ai/TokenVault/popup"; const useFocus = () => { const htmlElRef = useRef(null); @@ -367,9 +367,9 @@ export default function Chat() {
))} - {thread.interrupt && FederatedConnectionInterrupt.isInterrupt(thread.interrupt.value) ? ( + {thread.interrupt && TokenVaultInterrupt.isInterrupt(thread.interrupt.value) ? (
- thread.submit(null)} connectWidget={{ diff --git a/auth4genai/snippets/how-tos/github/llamaindex-python.mdx b/auth4genai/snippets/how-tos/github/llamaindex-python.mdx index d20405916..b0bfc643f 100644 --- a/auth4genai/snippets/how-tos/github/llamaindex-python.mdx +++ b/auth4genai/snippets/how-tos/github/llamaindex-python.mdx @@ -14,7 +14,7 @@ from flask import session auth0_ai = Auth0AI() -with_github = auth0_ai.with_federated_connection( +with_github = auth0_ai.with_token_vault( connection="github", scopes=["repo"], refresh_token=lambda *_args, **_kwargs:session["user"]["refresh_token"], @@ -32,12 +32,12 @@ Wrap your tool using the Auth0 AI SDK to obtain an access token for the GitHub A from github import Github from github.GithubException import BadCredentialsException from llama_index.core.tools import FunctionTool -from auth0_ai_llamaindex.federated_connections import get_access_token_for_connection, FederatedConnectionError +from auth0_ai_llamaindex.token_vault import get_access_token_from_token_vault, TokenVaultError from src.lib.auth0_ai import with_github def list_github_repositories_tool_function(): # Get the access token from Auth0 AI - access_token = get_access_token_for_connection() + access_token = get_access_token_from_token_vault() # GitHub SDK try: @@ -47,7 +47,7 @@ def list_github_repositories_tool_function(): repo_names = [repo.name for repo in repos] return repo_names except BadCredentialsException: - raise FederatedConnectionError("Authorization required to access the Federated Connection") + raise TokenVaultError("Authorization required to access the Token Vault API") list_github_repositories_tool = with_github(FunctionTool.from_defaults( name="list_github_repositories", @@ -70,7 +70,7 @@ system_prompt = f"""You are an assistant designed to answer random user's questi agent = OpenAIAgent.from_tools( tools=[ - # a tool with federated connection access + # a tool with Token Vault access list_github_repositories_tool # ... other tools ], @@ -88,14 +88,14 @@ Interrupts are a way for the system to pause execution and prompt the user to ta On the server side of your Flask application you will need to set up a route to handle the Chat API requests. This route will be responsible for forwarding the requests to the OpenAI API utilizing LlamaIndex's SDK, that has been initialized with Auth0 AI's protection enhancements for tools. -When `FederatedConnectionInterrupt` error ocurrs, the server side will signal the front-end about the level access restrictions, and the front-end should prompt the user to trigger a new authorization (or login) request with the necessary permissions. +When `TokenVaultInterrupt` error ocurrs, the server side will signal the front-end about the level access restrictions, and the front-end should prompt the user to trigger a new authorization (or login) request with the necessary permissions. ```python ./src/app.py wrap lines highlight={3-5,19-20} from dotenv import load_dotenv from flask import Flask, request, jsonify, session from auth0_ai_llamaindex.auth0_ai import Auth0AI -from auth0_ai_llamaindex.federated_connections import FederatedConnectionInterrupt +from auth0_ai_llamaindex.token_vault import TokenVaultInterrupt from src.lib.agent import agent load_dotenv() @@ -110,7 +110,7 @@ async def chat(): message = request.json.get("message") response = agent.achat(message) return jsonify({"response": str(response)}) - except FederatedConnectionInterrupt as e: + except TokenVaultInterrupt as e: return jsonify({"error": str(e.to_json())}), 403 except Exception as e: return jsonify({"error": str(e)}), 500 diff --git a/auth4genai/snippets/how-tos/github/llamaindex.mdx b/auth4genai/snippets/how-tos/github/llamaindex.mdx index f25ebff31..f6e8ef9fb 100644 --- a/auth4genai/snippets/how-tos/github/llamaindex.mdx +++ b/auth4genai/snippets/how-tos/github/llamaindex.mdx @@ -14,7 +14,7 @@ import { auth0 } from "@/lib/auth0"; const auth0AI = new Auth0AI(); -export const withGitHub = auth0AI.withTokenForConnection({ +export const withGitHub = auth0AI.withTokenVault({ connection: "github", scopes: ["repo"], refreshToken: async () => { @@ -38,8 +38,8 @@ Wrap your tool using the Auth0 AI SDK to obtain an access token for the GitHub A import { Octokit, RequestError } from "octokit"; import { z } from "zod"; import { withGitHub } from "@/lib/auth0-ai"; -import { getAccessTokenForConnection } from "@auth0/ai-vercel"; -import { FederatedConnectionError } from "@auth0/ai/interrupts"; +import { getAccessTokenFromTokenVault } from "@auth0/ai-vercel"; +import { TokenVaultError } from "@auth0/ai/interrupts"; import { tool } from "llamaindex"; export const listRepositories = () => @@ -47,7 +47,7 @@ export const listRepositories = () => tool( async () => { // Get the access token from Auth0 AI - const accessToken = getAccessTokenForConnection(); + const accessToken = getAccessTokenFromTokenVault(); // GitHub SDK try { @@ -61,8 +61,8 @@ export const listRepositories = () => } catch (error) { if (error instanceof RequestError) { if (error.status === 401) { - throw new FederatedConnectionError( - `Authorization required to access the Federated Connection` + throw new TokenVaultError( + `Authorization required to access the Token Vault connection` ); } } @@ -132,10 +132,10 @@ export async function POST(request: Request) { #### Client Side -On this example we utilize the `EnsureAPIAccessPopup` component to show a popup that allows the user to authenticate with GitHub and grant access with the requested scopes. You'll first need to install the `@auth0/ai-components` package: +On this example we utilize the `TokenVaultConsentPopup` component to show a popup that allows the user to authenticate with GitHub and grant access with the requested scopes. You'll first need to install the `@auth0/ai-components` package: ```bash wrap lines -npx @auth0/ai-components add FederatedConnections +npx @auth0/ai-components add TokenVault ``` Then, you can integrate the authentication popup in your chat component, using the interruptions helper from the SDK: @@ -144,9 +144,9 @@ Then, you can integrate the authentication popup in your chat component, using t "use client"; import { generateId } from "ai"; -import { EnsureAPIAccessPopup } from "@/components/auth0-ai/FederatedConnections/popup"; +import { TokenVaultConsentPopup } from "@/components/auth0-ai/TokenVault/popup"; import { useInterruptions } from "@auth0/ai-vercel/react"; -import { FederatedConnectionInterrupt } from "@auth0/ai/interrupts"; +import { TokenVaultInterrupt } from "@auth0/ai/interrupts"; import { useChat } from "@ai-sdk/react"; export default function Chat() { @@ -169,8 +169,8 @@ export default function Chat() { {message.parts && message.parts.length > 0 && (
{toolInterrupt?.toolCall.id.includes(message.id) && - FederatedConnectionInterrupt.isInterrupt(toolInterrupt) && ( - { @@ -40,8 +40,8 @@ Wrap your tool using the Auth0 AI SDK to obtain an access token for the Google C import { addHours, formatISO } from "date-fns"; import { GaxiosError } from "gaxios"; import { google } from "googleapis"; -import { getAccessTokenForConnection } from "@auth0/ai-vercel"; -import { FederatedConnectionError } from "@auth0/ai/interrupts"; +import { getAccessTokenFromTokenVault } from "@auth0/ai-vercel"; +import { TokenVaultError } from "@auth0/ai/interrupts"; import { withGoogleCalendar } from "@/lib/auth0-ai"; import { tool } from "ai"; import { z } from "zod"; @@ -55,7 +55,7 @@ export const checkUsersCalendar = withGoogleCalendar( }), execute: async ({ date }) => { // Get the access token from Auth0 AI - const accessToken = getAccessTokenForConnection(); + const accessToken = getAccessTokenFromTokenVault(); // Google SDK try { @@ -82,8 +82,8 @@ export const checkUsersCalendar = withGoogleCalendar( } catch (error) { if (error instanceof GaxiosError) { if (error.status === 401) { - throw new FederatedConnectionError( - `Authorization required to access the Federated Connection` + throw new TokenVaultError( + `Authorization required to access the Token Vault connection` ); } } @@ -142,10 +142,10 @@ export async function POST(request: Request) { #### Client Side -On this example we utilize the `EnsureAPIAccessPopup` component to show a popup that allows the user to authenticate with Google Calendar and grant access with the requested scopes. You'll first need to install the `@auth0/ai-components` package: +On this example we utilize the `TokenVaultConsentPopup` component to show a popup that allows the user to authenticate with Google Calendar and grant access with the requested scopes. You'll first need to install the `@auth0/ai-components` package: ```bash wrap lines -npx @auth0/ai-components add FederatedConnections +npx @auth0/ai-components add TokenVault ``` Then, you can integrate the authentication popup in your chat component, using the interruptions helper from the SDK: @@ -155,8 +155,8 @@ Then, you can integrate the authentication popup in your chat component, using t import { useChat } from "@ai-sdk/react"; import { useInterruptions } from "@auth0/ai-vercel/react"; -import { FederatedConnectionInterrupt } from "@auth0/ai/interrupts"; -import { EnsureAPIAccessPopup } from "@/components/auth0-ai/FederatedConnections/popup"; +import { TokenVaultInterrupt } from "@auth0/ai/interrupts"; +import { TokenVaultConsentPopup } from "@/components/auth0-ai/TokenVault/popup"; export default function Chat() { const { messages, handleSubmit, input, setInput, toolInterrupt } = @@ -175,8 +175,8 @@ export default function Chat() {
))} - {FederatedConnectionInterrupt.isInterrupt(toolInterrupt) && ( - ({ threadID: getAgent().name })); const auth0AI = new Auth0AI(); -export const withGoogleCalendar = auth0AI.withTokenForConnection({ +export const withGoogleCalendar = auth0AI.withTokenVault({ connection: "google-oauth2", scopes: ["https://www.googleapis.com/auth/calendar.freebusy"], refreshToken: async () => { @@ -52,8 +52,8 @@ Wrap your tool using the Auth0 AI SDK to obtain an access token for the Google C import { addHours, formatISO } from "date-fns"; import { GaxiosError } from "gaxios"; import { google } from "googleapis"; -import { getAccessTokenForConnection } from "@auth0/ai-vercel"; -import { FederatedConnectionError } from "@auth0/ai/interrupts"; +import { getAccessTokenFromTokenVault } from "@auth0/ai-vercel"; +import { TokenVaultError } from "@auth0/ai/interrupts"; import { withGoogleCalendar } from "@/lib/auth0-ai"; import { tool } from "ai"; import { z } from "zod"; @@ -67,7 +67,7 @@ export const checkUsersCalendar = withGoogleCalendar( }), execute: async ({ date }) => { // Get the access token from Auth0 AI - const accessToken = getAccessTokenForConnection(); + const accessToken = getAccessTokenFromTokenVault(); // Google SDK try { @@ -94,8 +94,8 @@ export const checkUsersCalendar = withGoogleCalendar( } catch (error) { if (error instanceof GaxiosError) { if (error.status === 401) { - throw new FederatedConnectionError( - `Authorization required to access the Federated Connection` + throw new TokenVaultError( + `Authorization required to access the Token Vault connection` ); } } @@ -193,10 +193,10 @@ The name of the user is ${claims?.name ?? "unknown"}. #### Client Side -On this example we utilize the `EnsureAPIAccessPopup` component to show a popup that allows the user to authenticate with Google Calendar and grant access with the requested scopes. You'll first need to install the `@auth0/ai-components` package: +On this example we utilize the `TokenVaultConsentPopup` component to show a popup that allows the user to authenticate with Google Calendar and grant access with the requested scopes. You'll first need to install the `@auth0/ai-components` package: ```bash wrap lines -npx @auth0/ai-components add FederatedConnections +npx @auth0/ai-components add TokenVault ``` Then, you can integrate the authentication popup in your chat component, using the interruptions helper from the SDK: @@ -206,8 +206,8 @@ Then, you can integrate the authentication popup in your chat component, using t import { useChat } from "@ai-sdk/react"; import { useAgentChatInterruptions } from "@auth0/ai-cloudflare/react"; -import { FederatedConnectionInterrupt } from "@auth0/ai/interrupts"; -import { EnsureAPIAccessPopup } from "@/components/auth0-ai/FederatedConnections/popup"; +import { TokenVaultInterrupt } from "@auth0/ai/interrupts"; +import { TokenVaultConsentPopup } from "@/components/auth0-ai/TokenVault/popup"; export default function Chat() { @@ -234,8 +234,8 @@ export default function Chat() {
))} - {FederatedConnectionInterrupt.isInterrupt(toolInterrupt) && ( - { @@ -41,8 +41,8 @@ Wrap your tool using the Auth0 AI SDK to obtain an access token for the Google C ```typescript ./src/lib/tools/checkUsersCalendar.ts wrap lines highlight={3-5,11,24,31-33,51-53} import { addHours } from "date-fns"; import { z } from "zod"; -import { getAccessTokenForConnection } from "@auth0/ai-genkit"; -import { FederatedConnectionError } from "@auth0/ai/interrupts"; +import { getAccessTokenFromTokenVault } from "@auth0/ai-genkit"; +import { TokenVaultError } from "@auth0/ai/interrupts"; import { withGoogleCalendar } from "@/lib/auth0-ai"; // importing GenKit instance @@ -62,7 +62,7 @@ export const checkUsersCalendar = ai.defineTool( }, async ({ date }) => { // Get the access token from Auth0 AI - const accessToken = getAccessTokenForConnection(); + const accessToken = getAccessTokenFromTokenVault(); // Google SDK try { @@ -89,8 +89,8 @@ export const checkUsersCalendar = ai.defineTool( } catch (error) { if (error instanceof GaxiosError) { if (error.status === 401) { - throw new FederatedConnectionError( - `Authorization required to access the Federated Connection` + throw new TokenVaultError( + `Authorization required to access the Token Vault connection` ); } } @@ -191,10 +191,10 @@ export async function GET( #### Client Side -On this example we utilize the `EnsureAPIAccessPopup` component to show a popup that allows the user to authenticate with Google Calendar and grant access with the requested scopes. You'll first need to install the `@auth0/ai-components` package: +On this example we utilize the `TokenVaultConsentPopup` component to show a popup that allows the user to authenticate with Google Calendar and grant access with the requested scopes. You'll first need to install the `@auth0/ai-components` package: ```bash wrap lines -npx @auth0/ai-components add FederatedConnections +npx @auth0/ai-components add TokenVault ``` Then, you can integrate the authentication popup in your chat component, using the interruptions helper from the SDK: @@ -203,8 +203,8 @@ Then, you can integrate the authentication popup in your chat component, using t "use client"; import { useQueryState } from "nuqs"; import { FormEventHandler, useEffect, useRef, useState } from "react"; -import { FederatedConnectionInterrupt } from "@auth0/ai/interrupts"; -import { EnsureAPIAccessPopup } from "@/components/auth0-ai/FederatedConnections/popup"; +import { TokenVaultInterrupt } from "@auth0/ai/interrupts"; +import { TokenVaultConsentPopup } from "@/components/auth0-ai/TokenVault/popup"; import Markdown from "react-markdown"; const useFocus = () => { @@ -321,14 +321,14 @@ export default function Chat() { {!isLoading && message.content[0].metadata?.interrupt && - FederatedConnectionInterrupt.isInterrupt( + TokenVaultInterrupt.isInterrupt( message.content[0].metadata?.interrupt ) ? (() => { const interrupt: any = message.content[0].metadata?.interrupt; return (
- submit({ interruptedToolRequest: message.content[0] })} interrupt={interrupt} connectWidget={{ @@ -350,4 +350,4 @@ export default function Chat() {
); } -``` \ No newline at end of file +``` diff --git a/auth4genai/snippets/how-tos/google-calendar/langgraph-python.mdx b/auth4genai/snippets/how-tos/google-calendar/langgraph-python.mdx index 26b9cc271..2e806e545 100644 --- a/auth4genai/snippets/how-tos/google-calendar/langgraph-python.mdx +++ b/auth4genai/snippets/how-tos/google-calendar/langgraph-python.mdx @@ -13,7 +13,7 @@ from auth0_ai_langchain.auth0_ai import Auth0AI auth0_ai = Auth0AI() -with_google = auth0_ai.with_federated_connection( +with_google = auth0_ai.with_token_vault( connection="google-oauth2", scopes=["https://www.googleapis.com/auth/calendar.freebusy"] # Optional: By default, the SDK will expect the refresh token from @@ -34,7 +34,7 @@ from googleapiclient.discovery import build from google.oauth2.credentials import Credentials from pydantic import BaseModel from langchain_core.tools import StructuredTool -from auth0_ai_langchain.federated_connections import get_access_token_for_connection, FederatedConnectionError +from auth0_ai_langchain.token_vault import get_access_token_from_token_vault, TokenVaultError from lib.auth0_ai import with_google class CheckUserCalendarSchema(BaseModel): @@ -42,7 +42,7 @@ class CheckUserCalendarSchema(BaseModel): def check_user_calendar_tool_function(date: datetime): # Get the access token from Auth0 AI - access_token = get_access_token_for_connection() + access_token = get_access_token_from_token_vault() # Google SDK try: @@ -61,7 +61,7 @@ def check_user_calendar_tool_function(date: datetime): return {"available": len(busy_times) == 0} except HttpError as e: if e.resp.status == 401: - raise FederatedConnectionError("Authorization required to access the Federated Connection API") + raise TokenVaultError("Authorization required to access the Token Vault API") raise ValueError(f"Invalid response from Google Calendar API: {response.status_code} - {response.text}") @@ -111,7 +111,7 @@ workflow = ( "tools", ToolNode( [ - # a tool with federated connection access + # a tool with Token Vault access check_user_calendar_tool, # ... other tools ], @@ -180,18 +180,18 @@ You can check different authentication options for Next.js with Auth0 at the [of #### Client Side -On this example we utilize the `EnsureAPIAccessPopup` component to show a popup that allows the user to authenticate with Google Calendar and grant access with the requested scopes. You'll first need to install the `@auth0/ai-components` package: +On this example we utilize the `TokenVaultConsentPopup` component to show a popup that allows the user to authenticate with Google Calendar and grant access with the requested scopes. You'll first need to install the `@auth0/ai-components` package: ```bash wrap lines -npx @auth0/ai-components add FederatedConnections +npx @auth0/ai-components add TokenVault ``` Then, you can integrate the authentication popup in your chat component, using the interruptions helper from the SDK: ```tsx ./src/components/chat.tsx wrap lines highlight={2-3,62-74} import { useStream } from "@langchain/langgraph-sdk/react"; -import { FederatedConnectionInterrupt } from "@auth0/ai/interrupts"; -import { EnsureAPIAccessPopup } from "@/components/auth0-ai/FederatedConnections/popup"; +import { TokenVaultInterrupt } from "@auth0/ai/interrupts"; +import { TokenVaultConsentPopup } from "@/components/auth0-ai/TokenVault/popup"; const useFocus = () => { const htmlElRef = useRef(null); @@ -250,9 +250,9 @@ export default function Chat() {
))} - {thread.interrupt && FederatedConnectionInterrupt.isInterrupt(thread.interrupt.value) ? ( + {thread.interrupt && TokenVaultInterrupt.isInterrupt(thread.interrupt.value) ? (
- thread.submit(null)} connectWidget={{ diff --git a/auth4genai/snippets/how-tos/google-calendar/langgraph.mdx b/auth4genai/snippets/how-tos/google-calendar/langgraph.mdx index 828075d88..010f7492f 100644 --- a/auth4genai/snippets/how-tos/google-calendar/langgraph.mdx +++ b/auth4genai/snippets/how-tos/google-calendar/langgraph.mdx @@ -21,7 +21,7 @@ const auth0AI = new Auth0AI({ }); const withAccessTokenForConnection = (connection: string, scopes: string[]) => - auth0AI.withTokenForConnection({ + auth0AI.withTokenVault({ connection, scopes, accessToken: async (_, config) => { @@ -44,8 +44,8 @@ Wrap your tool using the Auth0 AI SDK to obtain an access token for the Google C import { addHours, formatISO } from "date-fns"; import { GaxiosError } from "gaxios"; import { google } from "googleapis"; -import { getAccessTokenForConnection } from "@auth0/ai-langchain"; -import { FederatedConnectionError } from "@auth0/ai/interrupts"; +import { getAccessTokenFromTokenVault } from "@auth0/ai-langchain"; +import { TokenVaultError } from "@auth0/ai/interrupts"; import { withGoogleCalendar } from "@/lib/auth0-ai"; import { tool } from "@langchain/core/tools"; import { z } from "zod"; @@ -53,7 +53,7 @@ import { z } from "zod"; export const checkUsersCalendar = withGoogleCalendar( tool(async ({ date }) => { // Get the access token from Auth0 AI - const accessToken = getAccessTokenForConnection(); + const accessToken = getAccessTokenFromTokenVault(); // Google SDK try { @@ -79,8 +79,8 @@ export const checkUsersCalendar = withGoogleCalendar( }; } catch (err) { if (err instanceof GaxiosError && err.status === 401) { - throw new FederatedConnectionError( - `Authorization required to access the Federated Connection` + throw new TokenVaultError( + `Authorization required to access the Token Vault connection` ); } throw err; @@ -131,7 +131,7 @@ const stateGraph = new StateGraph(MessagesAnnotation) "tools", new ToolNode( [ - // A tool with federated connection access + // A tool with Token Vault access checkUsersCalendar, // ... other tools ], @@ -310,18 +310,18 @@ export { auth as authHandler }; #### Client Side -On this example we utilize the `EnsureAPIAccessPopup` component to show a popup that allows the user to authenticate with Google Calendar and grant access with the requested scopes. You'll first need to install the `@auth0/ai-components` package: +On this example we utilize the `TokenVaultConsentPopup` component to show a popup that allows the user to authenticate with Google Calendar and grant access with the requested scopes. You'll first need to install the `@auth0/ai-components` package: ```bash wrap lines -npx @auth0/ai-components add FederatedConnections +npx @auth0/ai-components add TokenVault ``` Then, you can integrate the authentication popup in your chat component, using the interruptions helper from the SDK: ```tsx ./src/components/chat.tsx wrap lines highlight={2-3,63-73} import { useStream } from "@langchain/langgraph-sdk/react"; -import { FederatedConnectionInterrupt } from "@auth0/ai/interrupts"; -import { EnsureAPIAccessPopup } from "@/components/auth0-ai/FederatedConnections/popup"; +import { TokenVaultInterrupt } from "@auth0/ai/interrupts"; +import { TokenVaultConsentPopup } from "@/components/auth0-ai/TokenVault/popup"; const useFocus = () => { const htmlElRef = useRef(null); @@ -380,9 +380,9 @@ export default function Chat() {
))} - {thread.interrupt && FederatedConnectionInterrupt.isInterrupt(thread.interrupt.value) ? ( + {thread.interrupt && TokenVaultInterrupt.isInterrupt(thread.interrupt.value) ? (
- thread.submit(null)} connectWidget={{ diff --git a/auth4genai/snippets/how-tos/google-calendar/llamaindex-python.mdx b/auth4genai/snippets/how-tos/google-calendar/llamaindex-python.mdx index a4394f9ff..82306d17b 100644 --- a/auth4genai/snippets/how-tos/google-calendar/llamaindex-python.mdx +++ b/auth4genai/snippets/how-tos/google-calendar/llamaindex-python.mdx @@ -14,7 +14,7 @@ from flask import session auth0_ai = Auth0AI() -with_google = auth0_ai.with_federated_connection( +with_google = auth0_ai.with_token_vault( connection="google-oauth2", scopes=["https://www.googleapis.com/auth/calendar.freebusy"], refresh_token=lambda *_args, **_kwargs:session["user"]["refresh_token"], @@ -35,14 +35,14 @@ from googleapiclient.discovery import build from google.oauth2.credentials import Credentials from typing import Annotated from llama_index.core.tools import FunctionTool -from auth0_ai_llamaindex.federated_connections import get_access_token_for_connection, FederatedConnectionError +from auth0_ai_llamaindex.token_vault import get_access_token_from_token_vault, TokenVaultError from src.lib.auth0_ai import with_google def check_user_calendar_tool_function( date: Annotated[str, "Date and time in ISO 8601 format."] ): # Get the access token from Auth0 AI - access_token = get_access_token_for_connection() + access_token = get_access_token_from_token_vault() # Google SDK try: @@ -61,7 +61,7 @@ def check_user_calendar_tool_function( return {"available": len(busy_times) == 0} except HttpError as e: if e.resp.status == 401: - raise FederatedConnectionError("Authorization required to access the Federated Connection API") + raise TokenVaultError("Authorization required to access the Token Vault API") raise ValueError(f"Invalid response from Google Calendar API: {response.status_code} - {response.text}") @@ -86,7 +86,7 @@ system_prompt = f"""You are an assistant designed to answer random user's questi agent = OpenAIAgent.from_tools( tools=[ - # a tool with federated connection access + # a tool with Token Vault access check_user_calendar_tool # ... other tools ], @@ -104,14 +104,14 @@ Interrupts are a way for the system to pause execution and prompt the user to ta On the server side of your Flask application you will need to set up a route to handle the Chat API requests. This route will be responsible for forwarding the requests to the OpenAI API utilizing LlamaIndex's SDK, that has been initialized with Auth0 AI's protection enhancements for tools. -When `FederatedConnectionInterrupt` error ocurrs, the server side will signal the front-end about the level access restrictions, and the front-end should prompt the user to trigger a new authorization (or login) request with the necessary permissions. +When `TokenVaultInterrupt` error ocurrs, the server side will signal the front-end about the level access restrictions, and the front-end should prompt the user to trigger a new authorization (or login) request with the necessary permissions. ```python ./src/app.py wrap lines highlight={3-5,19-20} from dotenv import load_dotenv from flask import Flask, request, jsonify, session from auth0_ai_llamaindex.auth0_ai import Auth0AI -from auth0_ai_llamaindex.federated_connections import FederatedConnectionInterrupt +from auth0_ai_llamaindex.token_vault import TokenVaultInterrupt from src.lib.agent import agent load_dotenv() @@ -126,7 +126,7 @@ async def chat(): message = request.json.get("message") response = agent.achat(message) return jsonify({"response": str(response)}) - except FederatedConnectionInterrupt as e: + except TokenVaultInterrupt as e: return jsonify({"error": str(e.to_json())}), 403 except Exception as e: return jsonify({"error": str(e)}), 500 diff --git a/auth4genai/snippets/how-tos/google-calendar/llamaindex.mdx b/auth4genai/snippets/how-tos/google-calendar/llamaindex.mdx index 6fa468fd6..77c24a8aa 100644 --- a/auth4genai/snippets/how-tos/google-calendar/llamaindex.mdx +++ b/auth4genai/snippets/how-tos/google-calendar/llamaindex.mdx @@ -14,7 +14,7 @@ import { auth0 } from "@/lib/auth0"; const auth0AI = new Auth0AI(); -export const withGoogleCalendar = auth0AI.withTokenForConnection({ +export const withGoogleCalendar = auth0AI.withTokenVault({ connection: "google-oauth2", scopes: ["https://www.googleapis.com/auth/calendar.freebusy"], refreshToken: async () => { @@ -40,8 +40,8 @@ import { GaxiosError } from "gaxios"; import { google } from "googleapis"; import { tool } from "llamaindex"; import { withGoogleCalendar } from "@/lib/auth0-ai"; -import { getAccessTokenForConnection } from "@auth0/ai-llamaindex"; -import { FederatedConnectionError } from "@auth0/ai/interrupts"; +import { getAccessTokenFromTokenVault } from "@auth0/ai-llamaindex"; +import { TokenVaultError } from "@auth0/ai/interrupts"; import { z } from "zod"; export const checkUsersCalendar = () => @@ -49,7 +49,7 @@ export const checkUsersCalendar = () => tool( async ({ date }) => { // Get the access token from Auth0 AI - const accessToken = getAccessTokenForConnection(); + const accessToken = getAccessTokenFromTokenVault(); // Google SDK try { @@ -76,8 +76,8 @@ export const checkUsersCalendar = () => } catch (error) { if (error instanceof GaxiosError) { if (error.status === 401) { - throw new FederatedConnectionError( - `Authorization required to access the Federated Connection` + throw new TokenVaultError( + `Authorization required to access the Token Vault connection` ); } } @@ -150,10 +150,10 @@ export async function POST(request: Request) { #### Client Side -On this example we utilize the `EnsureAPIAccessPopup` component to show a popup that allows the user to authenticate with GitHub and grant access with the requested scopes. You'll first need to install the `@auth0/ai-components` package: +On this example we utilize the `TokenVaultConsentPopup` component to show a popup that allows the user to authenticate with GitHub and grant access with the requested scopes. You'll first need to install the `@auth0/ai-components` package: ```bash wrap lines -npx @auth0/ai-components add FederatedConnections +npx @auth0/ai-components add TokenVault ``` Then, you can integrate the authentication popup in your chat component, using the interruptions helper from the SDK: @@ -162,9 +162,9 @@ Then, you can integrate the authentication popup in your chat component, using t "use client"; import { generateId } from "ai"; -import { EnsureAPIAccessPopup } from "@/components/auth0-ai/FederatedConnections/popup"; +import { TokenVaultConsentPopup } from "@/components/auth0-ai/TokenVault/popup"; import { useInterruptions } from "@auth0/ai-vercel/react"; -import { FederatedConnectionInterrupt } from "@auth0/ai/interrupts"; +import { TokenVaultInterrupt } from "@auth0/ai/interrupts"; import { useChat } from "@ai-sdk/react"; export default function Chat() { @@ -187,8 +187,8 @@ export default function Chat() { {message.parts && message.parts.length > 0 && (
{toolInterrupt?.toolCall.id.includes(message.id) && - FederatedConnectionInterrupt.isInterrupt(toolInterrupt) && ( - { @@ -36,8 +36,8 @@ Wrap your tool using the Auth0 AI SDK to obtain an access token for the Slack AP ```typescript ./src/lib/tools/listChannels.ts wrap lines highlight={2-4,8,14,18,30-32} import { ErrorCode, WebClient } from "@slack/web-api"; -import { getAccessTokenForConnection } from "@auth0/ai-vercel"; -import { FederatedConnectionError } from "@auth0/ai/interrupts"; +import { getAccessTokenFromTokenVault } from "@auth0/ai-vercel"; +import { TokenVaultError } from "@auth0/ai/interrupts"; import { withSlack } from "@/lib/auth0-ai"; import { tool } from "ai"; import { z } from "zod"; @@ -48,7 +48,7 @@ export const listChannels = withSlack( parameters: z.object({}), execute: async () => { // Get the access token from Auth0 AI - const accessToken = getAccessTokenForConnection(); + const accessToken = getAccessTokenFromTokenVault(); // Slack SDK try { @@ -64,8 +64,8 @@ export const listChannels = withSlack( } catch (error) { if (error && typeof error === "object" && "code" in error) { if (error.code === ErrorCode.HTTPError) { - throw new FederatedConnectionError( - `Authorization required to access the Federated Connection` + throw new TokenVaultError( + `Authorization required to access the Token Vault connection` ); } } @@ -124,10 +124,10 @@ export async function POST(request: Request) { #### Client Side -On this example we utilize the `EnsureAPIAccessPopup` component to show a popup that allows the user to authenticate with Slack and grant access with the requested scopes. You'll first need to install the `@auth0/ai-components` package: +On this example we utilize the `TokenVaultConsentPopup` component to show a popup that allows the user to authenticate with Slack and grant access with the requested scopes. You'll first need to install the `@auth0/ai-components` package: ```bash wrap lines -npx @auth0/ai-components add FederatedConnections +npx @auth0/ai-components add TokenVault ``` Then, you can integrate the authentication popup in your chat component, using the interruptions helper from the SDK: @@ -137,8 +137,8 @@ Then, you can integrate the authentication popup in your chat component, using t import { useChat } from "@ai-sdk/react"; import { useInterruptions } from "@auth0/ai-vercel/react"; -import { FederatedConnectionInterrupt } from "@auth0/ai/interrupts"; -import { EnsureAPIAccessPopup } from "@/components/auth0-ai/FederatedConnections/popup"; +import { TokenVaultInterrupt } from "@auth0/ai/interrupts"; +import { TokenVaultConsentPopup } from "@/components/auth0-ai/TokenVault/popup"; export default function Chat() { const { messages, handleSubmit, input, setInput, toolInterrupt } = @@ -157,8 +157,8 @@ export default function Chat() {
))} - {FederatedConnectionInterrupt.isInterrupt(toolInterrupt) && ( - ({ threadID: getAgent().name })); const auth0AI = new Auth0AI(); -export const withSlack = auth0AI.withTokenForConnection({ +export const withSlack = auth0AI.withTokenVault({ connection: "sign-in-with-slack", scopes: ["channels:read", "groups:read"], refreshToken: async () => { @@ -50,8 +50,8 @@ Wrap your tool using the Auth0 AI SDK to obtain an access token for the Slack AP ```typescript ./src/agent/tools/listRepositories.ts wrap lines highlight={2-4,8,14,18,30-32} import { ErrorCode, WebClient } from "@slack/web-api"; -import { getAccessTokenForConnection } from "@auth0/ai-vercel"; -import { FederatedConnectionError } from "@auth0/ai/interrupts"; +import { getAccessTokenFromTokenVault } from "@auth0/ai-vercel"; +import { TokenVaultError } from "@auth0/ai/interrupts"; import { withSlack } from "@/lib/auth0-ai"; import { tool } from "ai"; import { z } from "zod"; @@ -62,7 +62,7 @@ export const listChannels = withSlack( parameters: z.object({}), execute: async () => { // Get the access token from Auth0 AI - const accessToken = getAccessTokenForConnection(); + const accessToken = getAccessTokenFromTokenVault(); // Slack SDK try { @@ -78,8 +78,8 @@ export const listChannels = withSlack( } catch (error) { if (error && typeof error === "object" && "code" in error) { if (error.code === ErrorCode.HTTPError) { - throw new FederatedConnectionError( - `Authorization required to access the Federated Connection` + throw new TokenVaultError( + `Authorization required to access the Token Vault connection` ); } } @@ -177,10 +177,10 @@ The name of the user is ${claims?.name ?? "unknown"}. #### Client Side -On this example we utilize the `EnsureAPIAccessPopup` component to show a popup that allows the user to authenticate with Github and grant access with the requested scopes. You'll first need to install the `@auth0/ai-components` package: +On this example we utilize the `TokenVaultConsentPopup` component to show a popup that allows the user to authenticate with Github and grant access with the requested scopes. You'll first need to install the `@auth0/ai-components` package: ```bash wrap lines -npx @auth0/ai-components add FederatedConnections +npx @auth0/ai-components add TokenVault ``` Then, you can integrate the authentication popup in your chat component, using the interruptions helper from the SDK: @@ -190,8 +190,8 @@ Then, you can integrate the authentication popup in your chat component, using t import { useChat } from "@ai-sdk/react"; import { useAgentChatInterruptions } from "@auth0/ai-cloudflare/react"; -import { FederatedConnectionInterrupt } from "@auth0/ai/interrupts"; -import { EnsureAPIAccessPopup } from "@/components/auth0-ai/FederatedConnections/popup"; +import { TokenVaultInterrupt } from "@auth0/ai/interrupts"; +import { TokenVaultConsentPopup } from "@/components/auth0-ai/TokenVault/popup"; export default function Chat() { @@ -218,8 +218,8 @@ export default function Chat() {
))} - {FederatedConnectionInterrupt.isInterrupt(toolInterrupt) && ( - { @@ -40,8 +40,8 @@ Wrap your tool using the Auth0 AI SDK to obtain an access token for the Slack AP ```typescript ./src/lib/tools/listChannels.ts wrap lines highlight={2-4,11,18,22,34-36} import { z } from "zod"; -import { getAccessTokenForConnection } from "@auth0/ai-genkit"; -import { FederatedConnectionError } from "@auth0/ai/interrupts"; +import { getAccessTokenFromTokenVault } from "@auth0/ai-genkit"; +import { TokenVaultError } from "@auth0/ai/interrupts"; import { withSlack } from "@/lib/auth0-ai"; import { ErrorCode, WebClient } from "@slack/web-api"; @@ -56,7 +56,7 @@ export const listChannels = ai.defineTool( name: "listChannels", }, async () => { - const accessToken = getAccessTokenForConnection(); + const accessToken = getAccessTokenFromTokenVault(); try { // Slack SDK @@ -72,8 +72,8 @@ export const listChannels = ai.defineTool( } catch (error) { if (error && typeof error === "object" && "code" in error) { if (error.code === ErrorCode.HTTPError) { - throw new FederatedConnectionError( - `Authorization required to access the Federated Connection` + throw new TokenVaultError( + `Authorization required to access the Token Vault connection` ); } } @@ -174,10 +174,10 @@ export async function GET( #### Client Side -On this example we utilize the `EnsureAPIAccessPopup` component to show a popup that allows the user to authenticate with Google Calendar and grant access with the requested scopes. You'll first need to install the `@auth0/ai-components` package: +On this example we utilize the `TokenVaultConsentPopup` component to show a popup that allows the user to authenticate with Google Calendar and grant access with the requested scopes. You'll first need to install the `@auth0/ai-components` package: ```bash wrap lines -npx @auth0/ai-components add FederatedConnections +npx @auth0/ai-components add TokenVault ``` Then, you can integrate the authentication popup in your chat component, using the interruptions helper from the SDK: @@ -186,8 +186,8 @@ Then, you can integrate the authentication popup in your chat component, using t "use client"; import { useQueryState } from "nuqs"; import { FormEventHandler, useEffect, useRef, useState } from "react"; -import { FederatedConnectionInterrupt } from "@auth0/ai/interrupts"; -import { EnsureAPIAccessPopup } from "@/components/auth0-ai/FederatedConnections/popup"; +import { TokenVaultInterrupt } from "@auth0/ai/interrupts"; +import { TokenVaultConsentPopup } from "@/components/auth0-ai/TokenVault/popup"; import Markdown from "react-markdown"; const useFocus = () => { @@ -304,14 +304,14 @@ export default function Chat() { {!isLoading && message.content[0].metadata?.interrupt && - FederatedConnectionInterrupt.isInterrupt( + TokenVaultInterrupt.isInterrupt( message.content[0].metadata?.interrupt ) ? (() => { const interrupt: any = message.content[0].metadata?.interrupt; return (
- submit({ interruptedToolRequest: message.content[0] })} interrupt={interrupt} connectWidget={{ diff --git a/auth4genai/snippets/how-tos/slack/langgraph-python.mdx b/auth4genai/snippets/how-tos/slack/langgraph-python.mdx index 92aa3aa12..f7dfcf2a5 100644 --- a/auth4genai/snippets/how-tos/slack/langgraph-python.mdx +++ b/auth4genai/snippets/how-tos/slack/langgraph-python.mdx @@ -13,7 +13,7 @@ from auth0_ai_langchain.auth0_ai import Auth0AI auth0_ai = Auth0AI() -with_slack = auth0_ai.with_federated_connection( +with_slack = auth0_ai.with_token_vault( connection="sign-in-with-slack", scopes=["channels:read groups:read"], # Optional: By default, the SDK will expect the refresh token from @@ -32,7 +32,7 @@ from slack_sdk import WebClient from slack_sdk.errors import SlackApiError from pydantic import BaseModel from langchain_core.tools import StructuredTool -from auth0_ai_langchain.federated_connections import get_access_token_for_connection, FederatedConnectionError +from auth0_ai_langchain.token_vault import get_access_token_from_token_vault, TokenVaultError from lib.auth0_ai import with_slack class EmptySchema(BaseModel): @@ -40,7 +40,7 @@ class EmptySchema(BaseModel): def list_channels_tool_function(date: datetime): # Get the access token from Auth0 AI - access_token = get_access_token_for_connection() + access_token = get_access_token_from_token_vault() # Slack SDK try: @@ -55,7 +55,7 @@ def list_channels_tool_function(date: datetime): return channel_names except SlackApiError as e: if e.response['error'] == 'not_authed': - raise FederatedConnectionError("Authorization required to access the Federated Connection API") + raise TokenVaultError("Authorization required to access the Token Vault API") raise ValueError(f"An error occurred: {e.response['error']}") @@ -105,7 +105,7 @@ workflow = ( "tools", ToolNode( [ - # a tool with federated connection access + # a tool with Token Vault access list_slack_channels_tool, # ... other tools ], @@ -174,18 +174,18 @@ You can check different authentication options for Next.js with Auth0 at the [of #### Client Side -On this example we utilize the `EnsureAPIAccessPopup` component to show a popup that allows the user to authenticate with Slack and grant access with the requested scopes. You'll first need to install the `@auth0/ai-components` package: +On this example we utilize the `TokenVaultConsentPopup` component to show a popup that allows the user to authenticate with Slack and grant access with the requested scopes. You'll first need to install the `@auth0/ai-components` package: ```bash wrap lines -npx @auth0/ai-components add FederatedConnections +npx @auth0/ai-components add TokenVault ``` Then, you can integrate the authentication popup in your chat component, using the interruptions helper from the SDK: ```tsx ./src/components/chat.tsx wrap lines highlight={2-3,62-74} import { useStream } from "@langchain/langgraph-sdk/react"; -import { FederatedConnectionInterrupt } from "@auth0/ai/interrupts"; -import { EnsureAPIAccessPopup } from "@/components/auth0-ai/FederatedConnections/popup"; +import { TokenVaultInterrupt } from "@auth0/ai/interrupts"; +import { TokenVaultConsentPopup } from "@/components/auth0-ai/TokenVault/popup"; const useFocus = () => { const htmlElRef = useRef(null); @@ -244,9 +244,9 @@ export default function Chat() {
))} - {thread.interrupt && FederatedConnectionInterrupt.isInterrupt(thread.interrupt.value) ? ( + {thread.interrupt && TokenVaultInterrupt.isInterrupt(thread.interrupt.value) ? (
- thread.submit(null)} connectWidget={{ diff --git a/auth4genai/snippets/how-tos/slack/langgraph.mdx b/auth4genai/snippets/how-tos/slack/langgraph.mdx index eac31652c..9f40b9c75 100644 --- a/auth4genai/snippets/how-tos/slack/langgraph.mdx +++ b/auth4genai/snippets/how-tos/slack/langgraph.mdx @@ -21,7 +21,7 @@ const auth0AI = new Auth0AI({ }); const withAccessTokenForConnection = (connection: string, scopes: string[]) => - auth0AI.withTokenForConnection({ + auth0AI.withTokenVault({ connection, scopes, accessToken: async (_, config) => { @@ -40,8 +40,8 @@ Wrap your tool using the Auth0 AI SDK to obtain an access token for the Slack AP ```typescript ./src/lib/tools/listChannels.ts wrap lines highlight={2-4,8,11,15,27-29} import { ErrorCode, WebClient } from "@slack/web-api"; -import { getAccessTokenForConnection } from "@auth0/ai-langchain"; -import { FederatedConnectionError } from "@auth0/ai/interrupts"; +import { getAccessTokenFromTokenVault } from "@auth0/ai-langchain"; +import { TokenVaultError } from "@auth0/ai/interrupts"; import { withSlack } from "@/lib/auth0-ai"; import { tool } from "@langchain/core/tools"; import { z } from "zod"; @@ -49,7 +49,7 @@ import { z } from "zod"; export const listChannels = withSlack( tool(async ({ date }) => { // Get the access token from Auth0 AI - const accessToken = getAccessTokenForConnection(); + const accessToken = getAccessTokenFromTokenVault(); // Slack SDK try { @@ -65,8 +65,8 @@ export const listChannels = withSlack( } catch (error) { if (error && typeof error === "object" && "code" in error) { if (error.code === ErrorCode.HTTPError) { - throw new FederatedConnectionError( - `Authorization required to access the Federated Connection` + throw new TokenVaultError( + `Authorization required to access the Token Vault connection` ); } } @@ -118,7 +118,7 @@ const stateGraph = new StateGraph(MessagesAnnotation) "tools", new ToolNode( [ - // A tool with federated connection access + // A tool with Token Vault access listChannels, // ... other tools ], @@ -297,18 +297,18 @@ export { auth as authHandler }; #### Client Side -On this example we utilize the `EnsureAPIAccessPopup` component to show a popup that allows the user to authenticate with Slack and grant access with the requested scopes. You'll first need to install the `@auth0/ai-components` package: +On this example we utilize the `TokenVaultConsentPopup` component to show a popup that allows the user to authenticate with Slack and grant access with the requested scopes. You'll first need to install the `@auth0/ai-components` package: ```bash wrap lines -npx @auth0/ai-components add FederatedConnections +npx @auth0/ai-components add TokenVault ``` Then, you can integrate the authentication popup in your chat component, using the interruptions helper from the SDK: ```tsx ./src/components/chat.tsx wrap lines highlight={2-3,62-74} import { useStream } from "@langchain/langgraph-sdk/react"; -import { FederatedConnectionInterrupt } from "@auth0/ai/interrupts"; -import { EnsureAPIAccessPopup } from "@/components/auth0-ai/FederatedConnections/popup"; +import { TokenVaultInterrupt } from "@auth0/ai/interrupts"; +import { TokenVaultConsentPopup } from "@/components/auth0-ai/TokenVault/popup"; const useFocus = () => { const htmlElRef = useRef(null); @@ -367,9 +367,9 @@ export default function Chat() {
))} - {thread.interrupt && FederatedConnectionInterrupt.isInterrupt(thread.interrupt.value) ? ( + {thread.interrupt && TokenVaultInterrupt.isInterrupt(thread.interrupt.value) ? (
- thread.submit(null)} connectWidget={{ diff --git a/auth4genai/snippets/how-tos/slack/llamaindex-python.mdx b/auth4genai/snippets/how-tos/slack/llamaindex-python.mdx index fe9dd7b82..681ac5a8c 100644 --- a/auth4genai/snippets/how-tos/slack/llamaindex-python.mdx +++ b/auth4genai/snippets/how-tos/slack/llamaindex-python.mdx @@ -14,7 +14,7 @@ from flask import session auth0_ai = Auth0AI() -with_slack = auth0_ai.with_federated_connection( +with_slack = auth0_ai.with_token_vault( connection="sign-in-with-slack", scopes=["channels:read groups:read"], refresh_token=lambda *_args, **_kwargs:session["user"]["refresh_token"], @@ -32,12 +32,12 @@ Wrap your tool using the Auth0 AI SDK to obtain an access token for the Slack AP from slack_sdk import WebClient from slack_sdk.errors import SlackApiError from llama_index.core.tools import FunctionTool -from auth0_ai_llamaindex.federated_connections import get_access_token_for_connection, FederatedConnectionError +from auth0_ai_llamaindex.token_vault import get_access_token_from_token_vault, TokenVaultError from src.lib.auth0_ai import with_slack def list_slack_channels_tool_function(): # Get the access token from Auth0 AI - access_token = get_access_token_for_connection() + access_token = get_access_token_from_token_vault() # Slack SDK try: @@ -52,7 +52,7 @@ def list_slack_channels_tool_function(): return channel_names except SlackApiError as e: if e.response['error'] == 'not_authed': - raise FederatedConnectionError("Authorization required to access the Federated Connection API") + raise TokenVaultError("Authorization required to access the Token Vault API") raise ValueError(f"An error occurred: {e.response['error']}") @@ -77,7 +77,7 @@ system_prompt = f"""You are an assistant designed to answer random user's questi agent = OpenAIAgent.from_tools( tools=[ - # a tool with federated connection access + # a tool with Token Vault access list_slack_channels_tool # ... other tools ], @@ -95,14 +95,14 @@ Interrupts are a way for the system to pause execution and prompt the user to ta On the server side of your Flask application you will need to set up a route to handle the Chat API requests. This route will be responsible for forwarding the requests to the OpenAI API utilizing LlamaIndex's SDK, that has been initialized with Auth0 AI's protection enhancements for tools. -When `FederatedConnectionInterrupt` error ocurrs, the server side will signal the front-end about the level access restrictions, and the front-end should prompt the user to trigger a new authorization (or login) request with the necessary permissions. +When `TokenVaultInterrupt` error ocurrs, the server side will signal the front-end about the level access restrictions, and the front-end should prompt the user to trigger a new authorization (or login) request with the necessary permissions. ```python ./src/app.py wrap lines highlight={3-5,19-20} from dotenv import load_dotenv from flask import Flask, request, jsonify, session from auth0_ai_llamaindex.auth0_ai import Auth0AI -from auth0_ai_llamaindex.federated_connections import FederatedConnectionInterrupt +from auth0_ai_llamaindex.token_vault import TokenVaultInterrupt from src.lib.agent import agent load_dotenv() @@ -117,7 +117,7 @@ async def chat(): message = request.json.get("message") response = agent.achat(message) return jsonify({"response": str(response)}) - except FederatedConnectionInterrupt as e: + except TokenVaultInterrupt as e: return jsonify({"error": str(e.to_json())}), 403 except Exception as e: return jsonify({"error": str(e)}), 500 diff --git a/auth4genai/snippets/how-tos/slack/llamaindex.mdx b/auth4genai/snippets/how-tos/slack/llamaindex.mdx index 65095e0ec..2b602880a 100644 --- a/auth4genai/snippets/how-tos/slack/llamaindex.mdx +++ b/auth4genai/snippets/how-tos/slack/llamaindex.mdx @@ -14,7 +14,7 @@ import { auth0 } from "@/lib/auth0"; const auth0AI = new Auth0AI(); -export const withSlack = auth0AI.withTokenForConnection({ +export const withSlack = auth0AI.withTokenVault({ connection: "sign-in-with-slack", scopes: ["channels:read", "groups:read"], refreshToken: async () => { @@ -38,8 +38,8 @@ Wrap your tool using the Auth0 AI SDK to obtain an access token for the GitHub A import { tool } from "llamaindex"; import { z } from "zod"; import { withSlack } from "@/lib/auth0-ai"; -import { getAccessTokenForConnection } from "@auth0/ai-llamaindex"; -import { FederatedConnectionError } from "@auth0/ai/interrupts"; +import { getAccessTokenFromTokenVault } from "@auth0/ai-llamaindex"; +import { TokenVaultError } from "@auth0/ai/interrupts"; import { ErrorCode, WebClient } from "@slack/web-api"; export const listChannels = () => @@ -47,7 +47,7 @@ export const listChannels = () => tool( async () => { // Get the access token from Auth0 AI - const accessToken = getAccessTokenForConnection(); + const accessToken = getAccessTokenFromTokenVault(); // Slack SDK try { @@ -67,8 +67,8 @@ export const listChannels = () => } catch (error) { if (error && typeof error === "object" && "code" in error) { if (error.code === ErrorCode.HTTPError) { - throw new FederatedConnectionError( - `Authorization required to access the Federated Connection` + throw new TokenVaultError( + `Authorization required to access the Token Vault connection` ); } } @@ -138,10 +138,10 @@ export async function POST(request: Request) { #### Client Side -On this example we utilize the `EnsureAPIAccessPopup` component to show a popup that allows the user to authenticate with GitHub and grant access with the requested scopes. You'll first need to install the `@auth0/ai-components` package: +On this example we utilize the `TokenVaultConsentPopup` component to show a popup that allows the user to authenticate with GitHub and grant access with the requested scopes. You'll first need to install the `@auth0/ai-components` package: ```bash wrap lines -npx @auth0/ai-components add FederatedConnections +npx @auth0/ai-components add TokenVault ``` Then, you can integrate the authentication popup in your chat component, using the interruptions helper from the SDK: @@ -150,9 +150,9 @@ Then, you can integrate the authentication popup in your chat component, using t "use client"; import { generateId } from "ai"; -import { EnsureAPIAccessPopup } from "@/components/auth0-ai/FederatedConnections/popup"; +import { TokenVaultConsentPopup } from "@/components/auth0-ai/TokenVault/popup"; import { useInterruptions } from "@auth0/ai-vercel/react"; -import { FederatedConnectionInterrupt } from "@auth0/ai/interrupts"; +import { TokenVaultInterrupt } from "@auth0/ai/interrupts"; import { useChat } from "@ai-sdk/react"; export default function Chat() { @@ -175,8 +175,8 @@ export default function Chat() { {message.parts && message.parts.length > 0 && (
{toolInterrupt?.toolCall.id.includes(message.id) && - FederatedConnectionInterrupt.isInterrupt(toolInterrupt) && ( - {`const auth0AI = new Auth0AI(); -export const ${jsVariableName} = auth0AI.withTokenForConnection({ +export const ${jsVariableName} = auth0AI.withTokenVault({ connection: "${connectionName}", scopes: [${formatScopes(scopes)}, ...], refreshToken: getAuth0RefreshToken(), @@ -28,7 +28,7 @@ export const ${jsVariableName} = auth0AI.withTokenForConnection({ {`auth0_ai = Auth0AI() -${pythonVariableName} = auth0_ai.with_federated_connection( +${pythonVariableName} = auth0_ai.with_token_vault( connection="${connectionName}", scopes=[${formatScopes(scopes)}, ...], refresh_token=get_auth0_refresh_token, diff --git a/auth4genai/snippets/integrations/learn-more.mdx b/auth4genai/snippets/integrations/learn-more.mdx index c9c65d3ab..949d31a05 100644 --- a/auth4genai/snippets/integrations/learn-more.mdx +++ b/auth4genai/snippets/integrations/learn-more.mdx @@ -4,5 +4,5 @@ If you want to use more than one connection for a user, you can link their accou ## Learn more -- Auth0's [Token Vault](https://auth0.com/docs/secure/tokens/token-vault) organizes the access and refresh tokens of federated connections in secure tokensets. Applications can then access the Token Vault to retrieve access tokens to call third-party APIs. To learn more, read [Configure Token Vault](https://auth0.com/docs/secure/tokens/token-vault/configure-token-vault). +- Auth0's [Token Vault](https://auth0.com/docs/secure/tokens/token-vault) organizes the access and refresh tokens of third-party connections in secure tokensets. Applications can then access the Token Vault to retrieve access tokens to call third-party APIs. To learn more, read [Configure Token Vault](https://auth0.com/docs/secure/tokens/token-vault/configure-token-vault). - Learn how to get an access token to make a tool call by completing the [Call other's APIs on user's behalf quickstart](/get-started/call-others-apis-on-users-behalf). diff --git a/main/secure/tokens/token-vault.mdx b/main/secure/tokens/token-vault.mdx index eb629a228..90b84562f 100644 --- a/main/secure/tokens/token-vault.mdx +++ b/main/secure/tokens/token-vault.mdx @@ -1,5 +1,5 @@ --- -description: Learn how Token Vault securely stores federated access and refresh +description: Learn how Token Vault securely stores third-party access and refresh tokens. 'og:image': https://cdn2.auth0.com/docs/1.14553.0/img/share-image.png 'og:title': Token Vault @@ -7,7 +7,7 @@ description: Learn how Token Vault securely stores federated access and refresh permalink: token-vault sidebarTitle: Overview title: Token Vault -'twitter:description': Learn how Token Vault securely stores federated access and +'twitter:description': Learn how Token Vault securely stores third-party access and refresh tokens. 'twitter:title': Token Vault --- @@ -19,7 +19,7 @@ Token Vault is currently available in Early Access for public cloud tenants. To Token Vault enables your applications to securely access third-party APIs on the user's behalf. There is no need to manage refresh tokens or build custom integrations per provider—Auth0 handles it all for you. You gain access to a wide range of external providers’ APIs and services, all through a single Auth0 integration. -When a user authenticates with a supported external provider and uses OAuth scopes to authorize access, Auth0 stores the access and refresh tokens for that connection in the Token Vault. Token Vault organizes the federated tokens issued by external providers into tokensets, with one tokenset per authorized connection. +When a user authenticates with a supported external provider and uses OAuth scopes to authorize access, Auth0 stores the access and refresh tokens for that connection in the Token Vault. Token Vault organizes the third-party tokens issued by external providers into tokensets, with one tokenset per authorized connection. You can then call the external provider's APIs using these stored credentials via Auth0 to get a user’s Google Calendar events, access GitHub repos, create a Microsoft Word document, and more. @@ -35,12 +35,12 @@ For Early Access, Auth0 supports Token Vault for the following social and enterp ## How it works -When a user authenticates with a supported external provider and authorizes the federated connection: +When a user authenticates with a supported external provider and authorizes the third-party connection: 1. Auth0 obtains access tokens using OAuth 2.0 scopes to control access. Users explicitly approve requested permissions. -2. Auth0 securely stores federated access and refresh tokens in the Token Vault. -3. The application [links user accounts](/manage-users/user-accounts/user-account-linking) with the user's consent. As a result, the user won’t have to create separate accounts for each external provider. -4. Your application calls Auth0 to exchange a valid Auth0 refresh token with an access token for a federated connection. Your application can perform this exchange multiple times while Auth0 manages refreshing the federated access tokens stored in the Token Vault. Using a federated access token, your application can call third-party APIs on the user’s behalf. +2. Auth0 securely stores third-party access and refresh tokens in the Token Vault. +3. The application [links user accounts](/docs/manage-users/user-accounts/user-account-linking) with the user's consent. As a result, the user won’t have to create separate accounts for each external provider. +4. Your application calls Auth0 to exchange a valid Auth0 refresh token with an access token for a third-party connection. Your application can perform this exchange multiple times while Auth0 manages refreshing the third-party access tokens stored in the Token Vault. Using a third-party access token, your application can call third-party APIs on the user’s behalf. Token Vault allows for seamless federated identity and simplifies integration across multiple external providers via a single Auth0 interface. diff --git a/main/secure/tokens/token-vault/call-apis-with-token-vault.mdx b/main/secure/tokens/token-vault/call-apis-with-token-vault.mdx index fd807a72d..4c3f2eb4f 100644 --- a/main/secure/tokens/token-vault/call-apis-with-token-vault.mdx +++ b/main/secure/tokens/token-vault/call-apis-with-token-vault.mdx @@ -16,7 +16,7 @@ Token Vault is currently available in Early Access for public cloud tenants. To -Token Vault organizes federated access and refresh tokens issued by external providers into tokensets, with one tokenset per authorized connection. Applications can access the Token Vault when they exchange a valid Auth0 refresh token for a federated access token stored in the tokenset. This enables applications to request federated access tokens without the user having to re-authorize the connection. Using the federated access token, the application can call third-party APIs on the user’s behalf. +Token Vault organizes third-party access and refresh tokens issued by external providers into tokensets, with one tokenset per authorized connection. Applications can access the Token Vault when they exchange a valid Auth0 refresh token for a third-party access token stored in the tokenset. This enables applications to request third-party access tokens without the user having to re-authorize the connection. Using the third-party access token, the application can call third-party APIs on the user’s behalf. Let’s walk through a real-world example: A user wants to schedule a meeting in their Google Calendar using a productivity app. @@ -66,7 +66,7 @@ When the user logs into a new Google social connection: ## Call third-party API -To schedule the meeting, the application needs to call the Google Calendar API. The application can use a valid Auth0 refresh token to request a Google access token with the scopes granted in the login flow without the user having to re-authorize the connection. To learn more, read [Manage federated refresh tokens](#manage-federated-refresh-tokens). +To schedule the meeting, the application needs to call the Google Calendar API. The application can use a valid Auth0 refresh token to request a Google access token with the scopes granted in the login flow without the user having to re-authorize the connection. To learn more, read [Manage Token Vault refresh tokens](#manage-token-vault-refresh-tokens). To call the Google Calendar API: @@ -128,7 +128,7 @@ Request: client_secret -Client secret. Note: You can use any client authentication method to get a federated access token. +Client secret. Note: You can use any client authentication method to get a third-party access token. subject_token_type @@ -159,7 +159,7 @@ The Auth0 Authorization Server validates and loads the user profile associated w 2. If the authorization request contains `login_hint`, Auth0 looks for an identity matching both the connection name and the `login_hint`. 3. If Auth0 can’t find the user, it returns a `401` status code with an error message. -Once the Auth0 Authorization Server validates the user, it locates the federated access token within the Token Vault. If it is still valid, Auth0 returns the federated access token with its scopes and expiry time: +Once the Auth0 Authorization Server validates the user, it locates the third-party access token within the Token Vault. If it is still valid, Auth0 returns the third-party access token with its scopes and expiry time: ```json lines { @@ -176,16 +176,16 @@ Once the Auth0 Authorization Server validates the user, it locates the federated -If the federated access token has expired, Auth0 uses the federated refresh token stored in the Token Vault to get a new federated access token with the same scopes. Auth0 then stores it in the corresponding tokenset and returns it to the application. To learn more about how Auth0 manages federated refresh tokens, read [Manage federated refresh tokens](#manage-federated-refresh-tokens). +If the third-party access token has expired, Auth0 uses the refresh token stored in the Token Vault to get a new third-party access token with the same scopes. Auth0 then stores it in the corresponding tokenset and returns it to the application. To learn more about how Auth0 manages refresh tokens, read [Manage Token Vault refresh tokens](#manage-token-vault-refresh-tokens). -Using the federated access token, the application calls the Google Calendar API on the user’s behalf. +Using the Token Vault access token, the application calls the Google Calendar API on the user’s behalf. -## Manage federated refresh tokens +## Manage Token Vault refresh tokens -Auth0 securely stores the federated refresh and access tokens of external providers in a tokenset within the Token Vault, with one tokenset per authorized connection. Auth0 manages federated refresh tokens on the server, so your application only has to handle storing and exchanging Auth0 refresh tokens for federated access tokens. +Auth0 securely stores refresh and access tokens for external providers in a tokenset within the Token Vault, with one tokenset per authorized connection. Auth0 manages refresh tokens on the server, so your application only has to handle storing and exchanging Auth0 refresh tokens for third-party access tokens. To learn more about how Auth0 manages Auth0 refresh tokens for different types of applications, read [Refresh tokens](/secure/tokens/refresh-tokens). -### Federated refresh token expiration policy +### Token Vault refresh token expiration policy -Auth0 deletes federated refresh tokens from tokensets when they expire based on the expiration date set by the external provider or if they have not been exchanged for a federated access token for 1+ years. \ No newline at end of file +Auth0 deletes refresh tokens from tokensets when they expire based on the expiration date set by the external provider or if they have not been exchanged for a third-party access token for 1+ years. \ No newline at end of file diff --git a/main/secure/tokens/token-vault/configure-token-vault.mdx b/main/secure/tokens/token-vault/configure-token-vault.mdx index 1c17d830d..dfb74212e 100644 --- a/main/secure/tokens/token-vault/configure-token-vault.mdx +++ b/main/secure/tokens/token-vault/configure-token-vault.mdx @@ -24,13 +24,13 @@ Auth0 supports Token Vault for the following social and enterprise OpenID Connect * Custom social connection -Once a user authenticates with a supported external provider and authorizes the federated connection, you can get an access token to call third-party APIs on the user’s behalf. To learn more, read [Call APIs with Token Vault](/secure/tokens/token-vault/call-apis-with-token-vault). +Once a user authenticates with a supported external provider and authorizes the third-party connection, you can get an access token to call third-party APIs on the user’s behalf. To learn more, read [Call APIs with Token Vault](/secure/tokens/token-vault/call-apis-with-token-vault). To configure Token Vault, you need to: -1. Configure your application with the Token Exchange (Federated Connection) grant type. -2. Enable Token Vault for a federated connection. -3. Manage tokensets within the Token Vault for your federated connection. +1. Configure your application with the Token Vault grant type. +2. Enable Token Vault for a third-party connection. +3. Manage tokensets within the Token Vault for your third-party connection. @@ -42,9 +42,9 @@ If you need to trigger MFA challenges for interactive flows, enable **Customize ## Configure application -Configure your application with the Token Exchange (Federated Connection) grant type using the Auth0 Dashboard or Management API. +Configure your application with the Token Vault grant type using the Auth0 Dashboard or Management API. -Only certain types of clients can use the Token Exchange (Federated Connection) grant type: +Only certain types of clients can use the Token Vault grant type: 1. The client must be a first-party client, i.e. the `is_first_party` property is `true`. 2. The client must be a confidential client with a valid authentication mechanism, i.e. the `token_endpoint_auth_method` property must not be set to `none`. @@ -54,7 +54,7 @@ Only certain types of clients can use the Token Exchange (Federated Connection) 1. Navigate to **Applications > Applications**. 2. Select the application you want to configure. -3. Under **Advanced Settings > Grant Types**, select the **Token Exchange (Federated Connection)** grant type. +3. Under **Advanced Settings > Grant Types**, select the **Token Vault** grant type. 4. Select **Save Changes**. ![](/images/cdy7uua7fh8z/4pDrKjLpUISfhhGAfc0EaU/28517676a42ec418c75a7034a0cad343/configure_federated_connection_token_exchange.png) @@ -83,9 +83,9 @@ curl --location --request PATCH 'https://{tenantDomain}/api/v2/clients/{clientId -## Configure federated connection +## Configure Third-Party Connection -Use the Auth0 Dashboard or Management API to configure a federated connection to retrieve and store access tokens for third-party APIs in the Token Vault. +Use the Auth0 Dashboard or Management API to configure a third-party connection to retrieve and store access tokens for third-party APIs in the Token Vault. Once you enable Token Vault for your connection, access and refresh tokens will no longer be stored in the user’s `identities` array. Instead, they will be stored in a secure tokenset within the Token Vault. To learn more, read [Manage tokensets](#manage-tokensets).