How Tambo AI Handles Authentication and API Communication in the React SDK
Tambo AI's React SDK implements a layered authentication architecture that supports both static API keys and dynamic OAuth token exchanges, ensuring secure API communication through a discriminated union auth state pattern that prevents unauthorized requests.
The Tambo AI React SDK provides a robust authentication and API communication system designed for React applications requiring secure interactions with the Tambo API. This architecture separates concerns between client configuration, session token management, and authentication state derivation to ensure every API request carries valid credentials. Whether using a static userKey for server-side scenarios or a dynamic userToken for client-side OAuth flows, the SDK guarantees type-safe authentication state management throughout the component tree.
Layered Authentication Architecture
The SDK organizes authentication into distinct layers, each with specific responsibilities and implementation files.
Configuration Layer: TamboClientProvider
The TamboClientProvider component in src/providers/tambo-client-provider.tsx constructs the ClientOptions object passed to the underlying @tambo-ai/typescript-sdk client. It creates a tamboConfig object containing the API key, optional tamboUrl, environment settings, default headers, and the userKey query parameter for static authentication scenarios.
// Conceptual implementation based on source analysis
const tamboConfig = {
apiKey: props.apiKey,
environment: props.environment,
defaultHeaders: { ... },
// userKey is injected as a default query parameter
};
Session Token Handling with useTamboSessionToken
For OAuth-based authentication, the useTamboSessionToken hook in src/providers/hooks/use-tambo-session-token.tsx manages the exchange of third-party OAuth tokens (userToken) for short-lived Tambo session tokens. This React Query-powered hook performs the token exchange via client.beta.auth.getToken, automatically refreshes the token using refetchInterval, and updates client.bearer with the new access token.
// Token exchange implementation
const { data } = useQuery({
queryKey: ['tambo-session-token', userToken],
queryFn: async () => {
const response = await client.beta.auth.getToken({ userToken });
return response.access_token;
},
refetchInterval: (data) => {
// Refresh before expiration
return data ? (expiresIn * 1000) - buffer : false;
}
});
Auth State Derivation via useTamboAuthState
The useTamboAuthState hook in src/v1/hooks/use-tambo-v1-auth-state.ts computes the current authentication status by inspecting the client context, configuration context, and token exchange results. It returns a discriminated union (TamboAuthState defined in src/v1/types/auth.ts) with one of five statuses: identified, exchanging, error, invalid, or unauthenticated.
// TamboAuthState discriminated union
type TamboAuthState =
| { status: "identified"; source: "userKey" | "tokenExchange" }
| { status: "exchanging" }
| { status: "error"; error: Error }
| { status: "invalid" }
| { status: "unauthenticated" };
Authentication Flow Step-by-Step
Understanding the exact sequence of operations helps debug authentication issues and implement custom flows.
-
Provider Mounting – The application renders
<TamboProvider>with either auserKey(static) oruserToken(OAuth). -
Client Initialization –
TamboClientProviderconstructs thetamboConfigobject and instantiatesnew TamboAI(tamboConfig), establishing the base HTTP client with default headers and query parameters. -
Token Exchange – If
userTokenis provided,useTamboSessionTokenexecutes:- POSTs a token-exchange request to
client.beta.auth.getToken - Receives
access_tokenandexpires_in - Sets
client.bearer = access_token - Configures automatic refresh via React Query's
refetchInterval
- POSTs a token-exchange request to
-
State Computation –
useTamboAuthStateevaluates the combined configuration and token status, returning the appropriateTamboAuthStatevariant. -
Warning Generation –
TamboAuthWarnings(rendered withinTamboProvider) logs console messages forunauthenticated,invalid, orerrorstates to aid development debugging. -
API Request Guarding – All data-fetching hooks (such as
useTamboV1ThreadanduseTamboV1SendMessage) checkuseTamboAuthStatebefore executing, ensuring no API call proceeds without valid authentication.
Preventing Unauthorized API Calls
The SDK implements defense-in-depth to prevent unauthenticated requests. The discriminated union pattern in src/v1/types/auth.ts forces exhaustive handling of all authentication states. Downstream hooks import useTamboClient to access the configured client, but rely on useTamboAuthState to gate execution.
When the status is identified, hooks proceed with API calls using the client instance that already contains the correct bearer token (for OAuth) or userKey query parameter (for static auth). For all other states (exchanging, error, invalid, unauthenticated), hooks either return loading states or throw errors, preventing any network request to Tambo AI endpoints.
Implementation Examples
Basic Provider Setup
Configure the SDK with either static or OAuth authentication:
import { TamboProvider } from "@tambo-ai/react";
function App() {
return (
<TamboProvider
apiKey={process.env.NEXT_PUBLIC_TAMBO_API_KEY!}
// Choose one authentication method:
userKey="user-12345" // Static server-side key
// userToken={oauthAccessToken} // Client-side OAuth token
>
<ChatInterface />
</TamboProvider>
);
}
Monitoring Authentication State
Use the discriminated union to handle all auth states exhaustively:
import { useTamboAuthState } from "@tambo-ai/react/v1/hooks/use-tambo-v1-auth-state";
function AuthStatus() {
const auth = useTamboAuthState();
switch (auth.status) {
case "identified":
return <p>Authenticated via {auth.source}</p>;
case "exchanging":
return <p>Signing you in...</p>;
case "error":
return <p>Authentication failed: {auth.error.message}</p>;
case "invalid":
return <p>Error: Cannot use both userKey and userToken</p>;
case "unauthenticated":
return <p>Please configure authentication</p>;
}
}
Making Authenticated API Calls
Access the client and guard requests based on auth state:
import { useTamboClient } from "@tambo-ai/react";
import { useTamboAuthState } from "@tambo-ai/react/v1/hooks/use-tambo-v1-auth-state";
import { useQuery } from "@tanstack/react-query";
function ThreadList() {
const client = useTamboClient();
const auth = useTamboAuthState();
const { data, isLoading } = useQuery({
queryKey: ["threads"],
queryFn: async () => {
const result = await client.beta.threads.list();
return result.threads;
},
// Only execute when authenticated
enabled: auth.status === "identified",
});
if (auth.status !== "identified") {
return <div>Waiting for authentication...</div>;
}
return (
<ul>
{data?.map(thread => (
<li key={thread.id}>{thread.id}</li>
))}
</ul>
);
}
Manual Session Token Refresh
Force a token refresh in rare edge cases:
import { useTamboClient, useTamboSessionToken } from "@tambo-ai/react";
function ForceRefresh() {
const client = useTamboClient();
const { refetch } = useTamboSessionToken(
client,
client.queryClient,
"oauth-token"
);
return (
<button onClick={() => refetch()}>
Refresh session token
</button>
);
}
Key Source Files
Understanding the implementation requires familiarity with these specific files in the tambo-ai/tambo repository:
-
src/v1/types/auth.ts– Defines theTamboAuthStatediscriminated union with statusesidentified,exchanging,error,invalid, andunauthenticated. -
src/v1/hooks/use-tambo-v1-auth-state.ts– Computes the current auth state by inspecting configuration context, client context, and token exchange results. -
src/providers/tambo-client-provider.tsx– Initializes theTamboAIclient withtamboConfig, sets up default headers, and injects theuserKeyquery parameter for static authentication. -
src/providers/hooks/use-tambo-session-token.tsx– Handles OAuth token exchange viaclient.beta.auth.getToken, automatic refresh via React Query'srefetchInterval, and updatesclient.bearer. -
src/v1/providers/tambo-v1-provider.tsx– High-level provider composing all sub-providers and renderingTamboAuthWarningsfor development debugging.
Summary
- Tambo AI React SDK authentication operates through a layered architecture separating configuration, token exchange, and state management.
- The
TamboClientProviderinsrc/providers/tambo-client-provider.tsxinitializes the HTTP client with API keys and optionaluserKeyparameters. - OAuth flows use
useTamboSessionTokeninsrc/providers/hooks/use-tambo-session-token.tsxto exchange third-party tokens for short-lived bearer tokens with automatic refresh. useTamboAuthStateinsrc/v1/hooks/use-tambo-v1-auth-state.tsexposes a discriminated union (TamboAuthState) that forces exhaustive handling of all authentication states.- All API calls are gated by authentication state checks, ensuring no requests proceed without valid credentials via
userKeyor bearer token.
Frequently Asked Questions
What is the difference between userKey and userToken in Tambo AI React SDK?
The userKey is a static identifier passed directly to the TamboProvider that gets attached as a query parameter to all API requests, suitable for server-side or trusted client scenarios. In contrast, userToken is a third-party OAuth access token that the SDK exchanges for a short-lived Tambo session token via client.beta.auth.getToken, storing the result as a bearer token for authenticated requests.
How does Tambo AI React SDK prevent API calls without authentication?
The SDK implements a discriminated union pattern through TamboAuthState (defined in src/v1/types/auth.ts) that requires downstream hooks to handle every possible authentication status. Hooks such as useTamboV1Thread check useTamboAuthState before executing API calls, only proceeding when the status is "identified", effectively blocking all network requests when authentication is missing, invalid, or in an error state.
What happens when the Tambo session token expires?
The useTamboSessionToken hook in src/providers/hooks/use-tambo-session-token.tsx utilizes React Query's refetchInterval option to automatically refresh the token before it expires. When the token exchange response includes expires_in, the hook calculates a refresh interval that triggers a new call to client.beta.auth.getToken, updating client.bearer with the new access token seamlessly without requiring manual intervention.
Can I use both userKey and userToken simultaneously?
No, the SDK explicitly treats this configuration as invalid. The useTamboAuthState hook returns a status of "invalid" when both userKey and userToken are present simultaneously, and the TamboAuthWarnings component logs a console error to alert developers of the misconfiguration. You must choose either the static userKey approach or the dynamic OAuth userToken flow, but never both at the same time.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →