Secure Your Chat API
Recipe for adding authentication with JWT tokens, handling 401 errors, and validating requests server-side.
This recipe shows how to secure your chat API with authentication. You'll learn how to pass tokens from the client, handle unauthorized errors, and validate requests on the server.
Problem
You need to:
- Authenticate users before allowing chat access
- Pass tokens securely from React to your API
- Handle token expiration and refresh
- Validate tokens on the server
Solution Overview
Use the headers option in useStreamChat to send authentication tokens. Handle 401 errors with onError. Validate tokens server-side before processing requests.
Bearer Token
The most common pattern is sending a JWT or API key via the Authorization header:
import { useStreamChat } from "@deltakit/react";
function Chat({ token }: { token: string }) {
const { messages, sendMessage } = useStreamChat({
api: "/api/chat",
headers: {
Authorization: `Bearer ${token}`,
},
});
return (/* render messages */);
}Token from Auth Context
If you use a React auth provider (Auth0, Clerk, Supabase, custom), pull the token from context:
import { useStreamChat } from "@deltakit/react";
import { useAuth } from "./auth-context";
function Chat() {
const { token } = useAuth();
const { messages, sendMessage } = useStreamChat({
api: "/api/chat",
headers: {
Authorization: `Bearer ${token}`,
},
});
return (/* render messages */);
}The hook reads headers on each sendMessage call, so token refreshes are picked up automatically.
Handling 401 Errors
Use onError to detect unauthorized responses and redirect or refresh:
import { useStreamChat } from "@deltakit/react";
import { useAuth } from "./auth-context";
function Chat() {
const { token, refreshToken, logout } = useAuth();
const { messages, sendMessage, error } = useStreamChat({
api: "/api/chat",
headers: {
Authorization: `Bearer ${token}`,
},
onError: (error) => {
if (error.message.includes("401")) {
// Try refreshing the token, or redirect to login
refreshToken().catch(() => logout());
}
},
});
return (/* render messages */);
}API Key Authentication
For simpler setups with API keys:
useStreamChat({
api: "/api/chat",
headers: {
"X-API-Key": import.meta.env.VITE_API_KEY,
},
});Server-Side Verification
Your backend should validate the token on every request:
# FastAPI example
from fastapi import Request, HTTPException
@app.post("/api/chat")
async def chat(request: Request):
auth = request.headers.get("Authorization")
if not auth or not auth.startswith("Bearer "):
raise HTTPException(status_code=401, detail="Unauthorized")
token = auth.split(" ")[1]
user = verify_token(token) # Your verification logic
# ... proceed with chat