Skip to content

Commit a5045f4

Browse files
fix: updated quick-start examples with updated langgraph-nextjs-api-passthrough usage
1 parent 4b87a2b commit a5045f4

File tree

4 files changed

+545
-104
lines changed

4 files changed

+545
-104
lines changed

auth4genai/snippets/get-started/langchain-next-js/async-auth.mdx

Lines changed: 123 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ In the root directory of your project, install the following dependencies:
2424
- `langgraph-nextjs-api-passthrough`: API passthrough for LangGraph.
2525

2626
```bash wrap lines
27-
npm install @auth0/ai-langchain@3 @langchain/core@0.3 @langchain/langgraph@0.3 @langchain/openai@0.6 langchain@0.3 langgraph-nextjs-api-passthrough@0.1
27+
npm install @auth0/ai-langchain@3.5.0 @langchain/core@0.3.77 @langchain/langgraph@0.4.4 @langchain/openai@0.6.13 langchain@0.3.12 langgraph-nextjs-api-passthrough@0.1.4
2828
```
2929
### Update the environment file
3030

@@ -49,7 +49,7 @@ const auth0AI = new Auth0AI();
4949
// CIBA flow for user confirmation
5050
export const withAsyncAuthorization = auth0AI.withAsyncUserConfirmation({
5151
userID: async (_params, config) => {
52-
return config?.configurable?._credentials?.user?.sub;
52+
return config.configurable?.langgraph_auth_user?.sub;
5353
},
5454
bindingMessage: async ({ product, qty }) =>
5555
`Do you want to buy ${qty} ${product}`,
@@ -95,43 +95,142 @@ Next, add the following code to `src/lib/auth0.ts`:
9595

9696
```tsx src/lib/auth0.ts wrap lines highlight={2-5}
9797
//... existing code
98-
export const getUser = async () => {
99-
const session = await auth0.getSession();
100-
return session?.user;
98+
export const auth0 = new Auth0Client({
99+
authorizationParameters: {
100+
// In v4, the AUTH0_SCOPE and AUTH0_AUDIENCE environment variables are no longer automatically picked up by the SDK.
101+
// Instead, we need to provide the values explicitly.
102+
scope: process.env.AUTH0_SCOPE,
103+
audience: process.env.AUTH0_AUDIENCE,
104+
},
105+
});
106+
107+
// Get the Access token from Auth0 session
108+
export const getAccessToken = async () => {
109+
const tokenResult = await auth0.getAccessToken();
110+
111+
if(!tokenResult || !tokenResult.token) {
112+
throw new Error("No access token found in Auth0 session");
113+
}
114+
115+
return tokenResult.token;
101116
};
102117
```
103118

104-
Update the `/src/app/api/chat/[..._path]/route.ts` file with the following code. The `user` will be passed to your LangGraph agent so we can use it from the Auth0 AI SDK to get the current user.
119+
Update the `/src/app/api/chat/[..._path]/route.ts` file with the following code. AccessToken will be passed to your LangGraph agent so we can use it from the Auth0 AI SDK to get the current user.
105120

106-
```ts src/app/api/chat/[..._path]/route.ts wrap lines highlight={3,19}
121+
```ts src/app/api/chat/[..._path]/route.ts wrap lines highlight={3,10}
107122
import { initApiPassthrough } from "langgraph-nextjs-api-passthrough";
108123

109-
import { getUser } from "@/lib/auth0";
124+
import { getAccessToken } from "@/lib/auth0";
110125

111126
export const { GET, POST, PUT, PATCH, DELETE, OPTIONS, runtime } =
112127
initApiPassthrough({
113128
apiUrl: process.env.LANGGRAPH_API_URL,
114129
baseRoute: "chat/",
115-
bodyParameters: async (req, body) => {
116-
if (
117-
req.nextUrl.pathname.endsWith("/runs/stream") &&
118-
req.method === "POST"
119-
) {
130+
headers: async () => {
131+
const accessToken = await getAccessToken();
132+
return {
133+
Authorization: `Bearer ${accessToken}`,
134+
};
135+
});
136+
```
137+
138+
### Add Custom Authentication
139+
<Info>
140+
For more information on how to add custom authentication for your LangGraph Platform application, see the [Custom Auth](https://langchain-ai.github.io/langgraphjs/how-tos/auth/custom_auth/) guide.
141+
</Info>
142+
In your langgraph.json, add the path to your auth file:
143+
```typescript langgraph.json wrap lines highlight={8}
144+
{
145+
"node_version": "20",
146+
"graphs": {
147+
"agent": "./agent.mts:graph"
148+
},
149+
"env": ".env",
150+
"auth": {
151+
"path": "./auth.mts:authHandler"
152+
}
153+
}
154+
```
155+
Then, in your auth.mts file, add your auth logic:
156+
```typescript ./auth.mts wrap lines
157+
import { createRemoteJWKSet, jwtVerify } from "jose";
158+
159+
const { Auth, HTTPException } = require("@langchain/langgraph-sdk/auth");
160+
161+
const AUTH0_DOMAIN = process.env.AUTH0_DOMAIN;
162+
const AUTH0_AUDIENCE = process.env.AUTH0_AUDIENCE;
163+
164+
// JWKS endpoint for Auth0
165+
const JWKS = createRemoteJWKSet(
166+
new URL(`https://${AUTH0_DOMAIN}/.well-known/jwks.json`)
167+
);
168+
169+
// Create the Auth instance
170+
const auth = new Auth();
171+
// Register the authentication handler
172+
auth.authenticate(async (request: Request) => {
173+
const authHeader = request.headers.get("Authorization");
174+
const xApiKeyHeader = request.headers.get("x-api-key");
175+
/**
176+
* LangGraph Platform will convert the `Authorization` header from the client to an `x-api-key` header automatically
177+
* as of now: https://docs.langchain.com/langgraph-platform/custom-auth
178+
*
179+
* We can still leverage the `Authorization` header when served in other infrastructure w/ langgraph-cli
180+
* or when running locally.
181+
*/
182+
// This header is required in Langgraph Cloud.
183+
if (!authHeader && !xApiKeyHeader) {
184+
throw new HTTPException(401, {
185+
message: "Invalid auth header provided.",
186+
});
187+
}
188+
189+
// prefer the xApiKeyHeader first
190+
let token = xApiKeyHeader || authHeader;
191+
192+
// Remove "Bearer " prefix if present
193+
if (token && token.startsWith("Bearer ")) {
194+
token = token.substring(7);
195+
}
196+
197+
// Validate Auth0 Access Token using common JWKS endpoint
198+
if (!token) {
199+
throw new HTTPException(401, {
200+
message:
201+
"Authorization header format must be of the form: Bearer <token>",
202+
});
203+
}
204+
205+
if (token) {
206+
try {
207+
// Verify the JWT using Auth0 JWKS
208+
const { payload } = await jwtVerify(token, JWKS, {
209+
issuer: `https://${AUTH0_DOMAIN}/`,
210+
audience: AUTH0_AUDIENCE,
211+
});
212+
213+
console.log("✅ Auth0 JWT payload resolved!", payload);
214+
215+
// Return the verified payload - this becomes available in graph nodes
120216
return {
121-
...body,
122-
config: {
123-
configurable: {
124-
_credentials: {
125-
user: await getUser(),
126-
},
127-
},
128-
},
217+
identity: payload.sub!,
218+
email: payload.email as string,
219+
permissions:
220+
typeof payload.scope === "string" ? payload.scope.split(" ") : [],
221+
auth_type: "auth0",
222+
// include the access token for use with Auth0 Token Vault exchanges by tools
223+
getRawAccessToken: () => token,
224+
// Add any other claims you need
225+
...payload,
129226
};
227+
} catch (jwtError) {
228+
...
130229
}
230+
}
231+
});
131232

132-
return body;
133-
},
134-
});
233+
export { auth as authHandler };
135234
```
136235
137236
#### Create a tool to call your API

auth4genai/snippets/get-started/langchain-next-js/auth-for-rag.mdx

Lines changed: 130 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ In the root directory of your project, install the following dependencies:
2525
- `langgraph-nextjs-api-passthrough`: API passthrough for LangGraph.
2626

2727
```bash wrap lines
28-
npm install @auth0/ai-langchain@3 @langchain/core@0.3 @langchain/langgraph@0.3 @langchain/openai@0.6 langchain@0.3 langgraph-nextjs-api-passthrough@0.1
28+
npm install @auth0/ai-langchain@3.5.0 @langchain/core@0.3.77 @langchain/langgraph@0.4.4 @langchain/openai@0.6.13 langchain@0.3.12 langgraph-nextjs-api-passthrough@0.1.4
2929
```
3030

3131
### Update the environment file
@@ -112,10 +112,10 @@ export const getContextDocumentsTool = tool(
112112

113113
Call the tool from your AI agent to get data from documents. First, update the `/src/app/api/chat/[..._path]/route.ts` file with the following code to pass the user credentials to your agent:
114114

115-
```ts src/app/api/chat/[..._path]/route.ts wrap lines highlight={3,19}
115+
```ts src/app/api/chat/[..._path]/route.ts wrap lines highlight={3,19,31}
116116
import { initApiPassthrough } from "langgraph-nextjs-api-passthrough";
117117

118-
import { getUser } from "@/lib/auth0";
118+
import { getUser, getAccessToken } from "@/lib/auth0";
119119

120120
export const { GET, POST, PUT, PATCH, DELETE, OPTIONS, runtime } =
121121
initApiPassthrough({
@@ -140,19 +140,144 @@ export const { GET, POST, PUT, PATCH, DELETE, OPTIONS, runtime } =
140140

141141
return body;
142142
},
143+
headers: async () => {
144+
const accessToken = await getAccessToken();
145+
return {
146+
Authorization: `Bearer ${accessToken}`,
147+
};
148+
},
143149
});
144150
```
145151

146152
Next, add the following code to `src/lib/auth0.ts`:
147153

148-
```tsx src/lib/auth0.ts wrap lines highlight={2-5}
149-
//... existing code
154+
```tsx src/lib/auth0.ts wrap lines highlight={14,25}
155+
import { Auth0Client } from '@auth0/nextjs-auth0/server';
156+
157+
export const auth0 = new Auth0Client({
158+
authorizationParameters: {
159+
// In v4, the AUTH0_SCOPE and AUTH0_AUDIENCE environment variables are no longer automatically picked up by the SDK.
160+
// Instead, we need to provide the values explicitly.
161+
scope: process.env.AUTH0_SCOPE,
162+
audience: process.env.AUTH0_AUDIENCE,
163+
},
164+
});
165+
166+
// Get the Access token from Auth0 session
167+
export const getAccessToken = async () => {
168+
const tokenResult = await auth0.getAccessToken();
169+
170+
if(!tokenResult || !tokenResult.token) {
171+
throw new Error("No access token found in Auth0 session");
172+
}
173+
174+
return tokenResult.token;
175+
};
176+
150177
export const getUser = async () => {
151178
const session = await auth0.getSession();
152179
return session?.user;
153180
};
154181
```
155182

183+
### Add Custom Authentication
184+
<Info>
185+
For more information on how to add custom authentication for your LangGraph Platform application, see the [Custom Auth](https://langchain-ai.github.io/langgraphjs/how-tos/auth/custom_auth/) guide.
186+
</Info>
187+
In your langgraph.json, add the path to your auth file:
188+
```typescript langgraph.json wrap lines highlight={8}
189+
{
190+
"node_version": "20",
191+
"graphs": {
192+
"agent": "./agent.mts:graph"
193+
},
194+
"env": ".env",
195+
"auth": {
196+
"path": "./auth.mts:authHandler"
197+
}
198+
}
199+
```
200+
Then, in your auth.mts file, add your auth logic:
201+
```typescript ./auth.mts wrap lines
202+
import { createRemoteJWKSet, jwtVerify } from "jose";
203+
204+
const { Auth, HTTPException } = require("@langchain/langgraph-sdk/auth");
205+
206+
const AUTH0_DOMAIN = process.env.AUTH0_DOMAIN;
207+
const AUTH0_AUDIENCE = process.env.AUTH0_AUDIENCE;
208+
209+
// JWKS endpoint for Auth0
210+
const JWKS = createRemoteJWKSet(
211+
new URL(`https://${AUTH0_DOMAIN}/.well-known/jwks.json`)
212+
);
213+
214+
// Create the Auth instance
215+
const auth = new Auth();
216+
// Register the authentication handler
217+
auth.authenticate(async (request: Request) => {
218+
const authHeader = request.headers.get("Authorization");
219+
const xApiKeyHeader = request.headers.get("x-api-key");
220+
/**
221+
* LangGraph Platform will convert the `Authorization` header from the client to an `x-api-key` header automatically
222+
* as of now: https://docs.langchain.com/langgraph-platform/custom-auth
223+
*
224+
* We can still leverage the `Authorization` header when served in other infrastructure w/ langgraph-cli
225+
* or when running locally.
226+
*/
227+
// This header is required in Langgraph Cloud.
228+
if (!authHeader && !xApiKeyHeader) {
229+
throw new HTTPException(401, {
230+
message: "Invalid auth header provided.",
231+
});
232+
}
233+
234+
// prefer the xApiKeyHeader first
235+
let token = xApiKeyHeader || authHeader;
236+
237+
// Remove "Bearer " prefix if present
238+
if (token && token.startsWith("Bearer ")) {
239+
token = token.substring(7);
240+
}
241+
242+
// Validate Auth0 Access Token using common JWKS endpoint
243+
if (!token) {
244+
throw new HTTPException(401, {
245+
message:
246+
"Authorization header format must be of the form: Bearer <token>",
247+
});
248+
}
249+
250+
if (token) {
251+
try {
252+
// Verify the JWT using Auth0 JWKS
253+
const { payload } = await jwtVerify(token, JWKS, {
254+
issuer: `https://${AUTH0_DOMAIN}/`,
255+
audience: AUTH0_AUDIENCE,
256+
});
257+
258+
console.log("✅ Auth0 JWT payload resolved!", payload);
259+
260+
// Return the verified payload - this becomes available in graph nodes
261+
return {
262+
identity: payload.sub!,
263+
email: payload.email as string,
264+
permissions:
265+
typeof payload.scope === "string" ? payload.scope.split(" ") : [],
266+
auth_type: "auth0",
267+
// include the access token for use with Auth0 Token Vault exchanges by tools
268+
getRawAccessToken: () => token,
269+
// Add any other claims you need
270+
...payload,
271+
};
272+
} catch (jwtError) {
273+
...
274+
}
275+
}
276+
});
277+
278+
export { auth as authHandler };
279+
```
280+
156281
Now, update the `/src/lib/agent.ts` file with the following code to add the tool to your agent:
157282

158283
```ts src/lib/agent.ts wrap lines highlight={1,7}

0 commit comments

Comments
 (0)