diff --git a/docs/docs/how-tos/auth/custom_auth.md b/docs/docs/how-tos/auth/custom_auth.md index 872c3c216..e49c23091 100644 --- a/docs/docs/how-tos/auth/custom_auth.md +++ b/docs/docs/how-tos/auth/custom_auth.md @@ -76,47 +76,47 @@ threads = await client.threads.list() === "Python RemoteGraph" -```python -from langgraph.pregel.remote import RemoteGraph -# generate token with your auth provider -my_token = "your-token" -remote_graph = RemoteGraph( - "agent", - url="http://localhost:2024", - headers={"Authorization": f"Bearer {my_token}"} -) -threads = await remote_graph.threads.list() -``` + ```python + from langgraph.pregel.remote import RemoteGraph + # generate token with your auth provider + my_token = "your-token" + remote_graph = RemoteGraph( + "agent", + url="http://localhost:2024", + headers={"Authorization": f"Bearer {my_token}"} + ) + threads = await remote_graph.threads.list() + ``` === "JavaScript Client" -```javascript -import { Client } from "@langchain/langgraph-sdk"; -// generate token with your auth provider -const my_token = "your-token"; -const client = new Client({ - apiUrl: "http://localhost:2024", - headers: { Authorization: `Bearer ${my_token}` }, -}); -const threads = await client.threads.list(); -``` + ```javascript + import { Client } from "@langchain/langgraph-sdk"; + // generate token with your auth provider + const my_token = "your-token"; + const client = new Client({ + apiUrl: "http://localhost:2024", + headers: { Authorization: `Bearer ${my_token}` }, + }); + const threads = await client.threads.list(); + ``` === "JavaScript RemoteGraph" -```javascript -import { RemoteGraph } from "@langchain/langgraph/remote"; -// generate token with your auth provider -const my_token = "your-token"; -const remoteGraph = new RemoteGraph({ - graphId: "agent", - url: "http://localhost:2024", - headers: { Authorization: `Bearer ${my_token}` }, -}); -const threads = await remoteGraph.threads.list(); -``` + ```javascript + import { RemoteGraph } from "@langchain/langgraph/remote"; + // generate token with your auth provider + const my_token = "your-token"; + const remoteGraph = new RemoteGraph({ + graphId: "agent", + url: "http://localhost:2024", + headers: { Authorization: `Bearer ${my_token}` }, + }); + const threads = await remoteGraph.threads.list(); + ``` === "CURL" -```bash -curl -H "Authorization: Bearer your-token" http://localhost:2024/threads -``` + ```bash + curl -H "Authorization: Bearer your-token" http://localhost:2024/threads + ``` diff --git a/docs/docs/how-tos/index.md b/docs/docs/how-tos/index.md index 6cad576ad..0f836fe57 100644 --- a/docs/docs/how-tos/index.md +++ b/docs/docs/how-tos/index.md @@ -181,8 +181,8 @@ LangGraph applications can be deployed using LangGraph Cloud, which provides a r ### Authentication & Access Control -- [How to add custom authentication](./auth/custom_auth_new.md) -- [How to update the security schema of your OpenAPI spec](./auth/openapi_security_new.md) +- [How to add custom authentication](./auth/custom_auth.md) +- [How to update the security schema of your OpenAPI spec](./auth/openapi_security.md) ### Assistants diff --git a/docs/docs/tutorials/auth/getting_started.md b/docs/docs/tutorials/auth/getting_started.md index ffea05cda..783cf29cc 100644 --- a/docs/docs/tutorials/auth/getting_started.md +++ b/docs/docs/tutorials/auth/getting_started.md @@ -1,9 +1,9 @@ # Setting up custom authentication -Let's learn how to add custom authentication to a LangGraph Platform deployment. We'll cover the core concepts of token-based authentication and show how to integrate with an authentication server. +Let's add custom authentication to a LangGraph template. This lets users interact with our bot making their conversations accessible to other users. This tutorial covers the core concepts of token-based authentication and show how to integrate with an authentication server. ??? note "Default authentication" - When deploying to LangGraph Cloud, requests are authenticated using LangSmith API keys by default. This gates access to the server but doesn't provide fine-grained access control over threads. Self-hosted LangGraph platform has no default authentication. This guide shows how to add custom authentication handlers that work in both cases, to provide fine-grained access control over threads, runs, and other resources. +When deploying to LangGraph Cloud, requests are authenticated using LangSmith API keys by default. This gates access to the server but doesn't provide fine-grained access control over threads. Self-hosted LangGraph platform has no default authentication. This guide shows how to add custom authentication handlers that work in both cases, to provide fine-grained access control over threads, runs, and other resources. !!! note "Prerequisites" @@ -21,58 +21,35 @@ The key components in a token-based authentication system are: 2. **Client**: gets tokens from auth server and includes them in requests. This is typically the user's browser or mobile app. 3. **LangGraph backend**: validates tokens and enforces access control to control access to your agents and data. -After implementing the following steps, when a user's client application (such as their web browser or mobile app) wants to access resources in LangGraph, the following steps occur: - -```mermaid -sequenceDiagram - participant User - participant AuthServer as Auth Server - participant LangGraph - User->>AuthServer: 1. Authenticate (username/password) - AuthServer-->>User: 2. Return signed JWT token - User->>LangGraph: 3. Request with JWT in header - LangGraph->>AuthServer: 4a. Validate token - AuthServer-->>LangGraph: 4b. Confirm token validity - Note over LangGraph: 4c. Apply access filters - LangGraph-->>User: Return authorized resources -``` +Here's how it typically works: 1. User authenticates with the auth server (username/password, OAuth, "Sign in with Google", etc.) 2. Auth server returns a signed JWT token attesting "I am user X with claims/roles Y" 3. User includes this token in request headers to LangGraph 4. LangGraph validates token signature and checks claims against the auth server. If valid, it allows the request, using custom filters to restrict access only to the user's resources. -In this tutorial, we'll implement password-based authentication using Supabase as our auth server. +## 1. Clone the template -## Project Structure - -After cloning, you'll see these key files: +Clone the [LangGraph template](https://github.com/langchain-ai/new-langgraph-project) to get started. ```shell -custom-auth/ -├── src/ -│ └── security/ -│ └── auth.py # We'll create this -├── langgraph.json # We'll update this -└── .env.example # Environment variables template +pip install -U "langgraph-cli[inmem]" +langgraph new --template=new-langgraph-project-python custom-auth +cd custom-auth ``` -## Setting up authentication +### 2. Create the auth handler -### 1. Create the auth handler - -First, let's create our authentication handler. Create a new file at `src/security/auth.py`: +Next, let's create our authentication handler. Create a new file at `src/security/auth.py`: ```python import os import httpx -import jwt from langgraph_sdk import Auth # Load from your .env file SUPABASE_URL = os.environ["SUPABASE_URL"] SUPABASE_SERVICE_KEY = os.environ["SUPABASE_SERVICE_KEY"] -SUPABASE_JWT_SECRET = os.environ["SUPABASE_JWT_SECRET"] # Create the auth object we'll use to protect our endpoints auth = Auth() @@ -90,20 +67,14 @@ async def get_current_user( ) try: - # Extract and verify JWT token - token = authorization.split(" ", 1)[1] - payload = jwt.decode( - token, - SUPABASE_JWT_SECRET, - algorithms=["HS256"], - audience="authenticated", - ) - - # Double-check with Supabase that token is still valid + # Fetch the user info from Supabase async with httpx.AsyncClient() as client: response = await client.get( f"{SUPABASE_URL}/auth/v1/user", - headers={"Authorization": f"Bearer {token}"}, + headers={ + "Authorization": authorization, + "apiKey": SUPABASE_SERVICE_KEY, + }, ) if response.status_code != 200: raise Auth.exceptions.HTTPException( @@ -112,7 +83,7 @@ async def get_current_user( ) user_data = response.json() - return [], { + return { "identity": user_data["id"], "display_name": user_data.get("name"), "is_authenticated": True, @@ -147,9 +118,9 @@ Next, tell LangGraph about our auth handler. Open `langgraph.json` and add: ```json { - "auth": { - "path": "src/security/auth.py:auth" - } + "auth": { + "path": "src/security/auth.py:auth" + } } ``` @@ -168,21 +139,21 @@ cp .env.example .env ``` Add to your `.env`: + ```bash SUPABASE_URL=https://your-project.supabase.co SUPABASE_SERVICE_KEY=your-service-key # aka the service_role secret -SUPABASE_JWT_SECRET=your-jwt-secret ANTHROPIC_API_KEY=your-anthropic-key # For the LLM in our chatbot ``` -Also note down your project's "anon public" key - we'll use this for client authentication. +Also note down your project's "anon public" key - we'll use this for client authentication below. ### 4. Start the server Install dependencies and start LangGraph: ```bash -pip install -U "langgraph-cli[inmem]" && pip install -e . +pip install -e . langgraph dev --no-browser ``` diff --git a/docs/docs/tutorials/index.md b/docs/docs/tutorials/index.md index 02a7983d2..ffd11fd1c 100644 --- a/docs/docs/tutorials/index.md +++ b/docs/docs/tutorials/index.md @@ -8,14 +8,15 @@ title: Tutorials New to LangGraph or LLM app development? Read this material to get up and running building your first applications. -## Get Started +## Get Started 🚀 {#quick-start} - [LangGraph Quickstart](introduction.ipynb): Build a chatbot that can use tools and keep track of conversation history. Add human-in-the-loop capabilities and explore how time-travel works. - [LangGraph Server Quickstart](langgraph-platform/local-server.md): Launch a LangGraph server locally and interact with it using REST API and LangGraph Studio Web UI. - [LangGraph Template Quickstart](../concepts/template_applications.md): Start building with LangGraph Platform using a template application. - [Deploy with LangGraph Cloud Quickstart](../cloud/quick_start.md): Deploy a LangGraph app using LangGraph Cloud. -## Use cases +## Use cases 🛠️ {#use-cases} + Explore practical implementations tailored for specific scenarios: @@ -72,10 +73,10 @@ Explore practical implementations tailored for specific scenarios: - [Competitive Programming](usaco/usaco.ipynb): Build an agent with few-shot "episodic memory" and human-in-the-loop collaboration to solve problems from the USA Computing Olympiad; adapted from the ["Can Language Models Solve Olympiad Programming?"](https://arxiv.org/abs/2404.10952v1) paper by Shi, Tang, Narasimhan, and Yao. - [Complex data extraction](extraction/retries.ipynb): Build an agent that can use function calling to do complex extraction tasks -## LangGraph Platform +## LangGraph Platform 🧱 {#platform} ### Authentication & Access Control -Learn how to secure your LangGraph applications: +Add custom authentication and authorization to your LangGraph Platform deployment. - [Setting Up Custom Authentication](./auth/getting_started.md): Implement OAuth2 authentication to authorize users on your deployment \ No newline at end of file diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 1fb71d807..b661ebe14 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -141,7 +141,8 @@ nav: - tutorials/web-navigation/web_voyager.ipynb - tutorials/usaco/usaco.ipynb - tutorials/extraction/retries.ipynb - - LangGarph Platform: + - LangGraph Platform: + - LangGraph Platform: concepts#langgraph-platform - docs/docs/tutorials/auth/getting_started.md - How-to Guides: @@ -241,6 +242,10 @@ nav: - cloud/deployment/cloud.md - how-tos/deploy-self-hosted.md - how-tos/use-remote-graph.md + - Authentication & Access Control: + - Authentication & Access Control: how-tos#authentication-access-control + - cloud/how-tos/auth/custom_auth_new.md + - cloud/how-tos/auth/openapi_security_new.md - Assistants: - Assistants: how-tos#assistants - cloud/how-tos/configuration_cloud.md