From e849c869cc9c72431f236a450c69c5980a57968c Mon Sep 17 00:00:00 2001 From: William Fu-Hinthorn <13333726+hinthornw@users.noreply.github.com> Date: Thu, 19 Dec 2024 08:52:31 -0800 Subject: [PATCH 1/4] [Docs] Add example payloads to code --- docs/docs/concepts/auth.md | 36 +++++++------- docs/docs/tutorials/auth/resource_auth.md | 58 ++++++++++++++++++++++- 2 files changed, 75 insertions(+), 19 deletions(-) diff --git a/docs/docs/concepts/auth.md b/docs/docs/concepts/auth.md index 142c64124..ae7a1eb17 100644 --- a/docs/docs/concepts/auth.md +++ b/docs/docs/concepts/auth.md @@ -383,24 +383,24 @@ If a more specific handler is registered, the more general handler will not be c Here are all the supported action handlers: -| Resource | Handler | Description | -|----------|---------|-------------| -| **Threads** | `@auth.on.threads.create` | Thread creation | -| | `@auth.on.threads.read` | Thread retrieval | -| | `@auth.on.threads.update` | Thread updates | -| | `@auth.on.threads.delete` | Thread deletion | -| | `@auth.on.threads.search` | Listing threads | -| | `@auth.on.threads.create_run` | Creating or updating a run | -| **Assistants** | `@auth.on.assistants.create` | Assistant creation | -| | `@auth.on.assistants.read` | Assistant retrieval | -| | `@auth.on.assistants.update` | Assistant updates | -| | `@auth.on.assistants.delete` | Assistant deletion | -| | `@auth.on.assistants.search` | Listing assistants | -| **Crons** | `@auth.on.crons.create` | Cron job creation | -| | `@auth.on.crons.read` | Cron job retrieval | -| | `@auth.on.crons.update` | Cron job updates | -| | `@auth.on.crons.delete` | Cron job deletion | -| | `@auth.on.crons.search` | Listing cron jobs | +| Resource | Handler | Description | Value Type | +|----------|---------|-------------|------------| +| **Threads** | `@auth.on.threads.create` | Thread creation | [`ThreadsCreate`](../cloud/reference/sdk/python_sdk_ref.md#langgraph_sdk.auth.types.ThreadsCreate) | +| | `@auth.on.threads.read` | Thread retrieval | [`ThreadsRead`](../cloud/reference/sdk/python_sdk_ref.md#langgraph_sdk.auth.types.ThreadsRead) | +| | `@auth.on.threads.update` | Thread updates | [`ThreadsUpdate`](../cloud/reference/sdk/python_sdk_ref.md#langgraph_sdk.auth.types.ThreadsUpdate) | +| | `@auth.on.threads.delete` | Thread deletion | [`ThreadsDelete`](../cloud/reference/sdk/python_sdk_ref.md#langgraph_sdk.auth.types.ThreadsDelete) | +| | `@auth.on.threads.search` | Listing threads | [`ThreadsSearch`](../cloud/reference/sdk/python_sdk_ref.md#langgraph_sdk.auth.types.ThreadsSearch) | +| | `@auth.on.threads.create_run` | Creating or updating a run | [`RunsCreate`](../cloud/reference/sdk/python_sdk_ref.md#langgraph_sdk.auth.types.RunsCreate) | +| **Assistants** | `@auth.on.assistants.create` | Assistant creation | [`AssistantsCreate`](../cloud/reference/sdk/python_sdk_ref.md#langgraph_sdk.auth.types.AssistantsCreate) | +| | `@auth.on.assistants.read` | Assistant retrieval | [`AssistantsRead`](../cloud/reference/sdk/python_sdk_ref.md#langgraph_sdk.auth.types.AssistantsRead) | +| | `@auth.on.assistants.update` | Assistant updates | [`AssistantsUpdate`](../cloud/reference/sdk/python_sdk_ref.md#langgraph_sdk.auth.types.AssistantsUpdate) | +| | `@auth.on.assistants.delete` | Assistant deletion | [`AssistantsDelete`](../cloud/reference/sdk/python_sdk_ref.md#langgraph_sdk.auth.types.AssistantsDelete) | +| | `@auth.on.assistants.search` | Listing assistants | [`AssistantsSearch`](../cloud/reference/sdk/python_sdk_ref.md#langgraph_sdk.auth.types.AssistantsSearch) | +| **Crons** | `@auth.on.crons.create` | Cron job creation | [`CronsCreate`](../cloud/reference/sdk/python_sdk_ref.md#langgraph_sdk.auth.types.CronsCreate) | +| | `@auth.on.crons.read` | Cron job retrieval | [`CronsRead`](../cloud/reference/sdk/python_sdk_ref.md#langgraph_sdk.auth.types.CronsRead) | +| | `@auth.on.crons.update` | Cron job updates | [`CronsUpdate`](../cloud/reference/sdk/python_sdk_ref.md#langgraph_sdk.auth.types.CronsUpdate) | +| | `@auth.on.crons.delete` | Cron job deletion | [`CronsDelete`](../cloud/reference/sdk/python_sdk_ref.md#langgraph_sdk.auth.types.CronsDelete) | +| | `@auth.on.crons.search` | Listing cron jobs | [`CronsSearch`](../cloud/reference/sdk/python_sdk_ref.md#langgraph_sdk.auth.types.CronsSearch) | ???+ note "About Runs" Runs are scoped to their parent thread for access control. This means permissions are typically inherited from the thread, reflecting the conversational nature of the data model. All run operations (reading, listing) except creation are controlled by the thread's handlers. diff --git a/docs/docs/tutorials/auth/resource_auth.md b/docs/docs/tutorials/auth/resource_auth.md index e62b88f60..ae1d08da4 100644 --- a/docs/docs/tutorials/auth/resource_auth.md +++ b/docs/docs/tutorials/auth/resource_auth.md @@ -68,7 +68,51 @@ async def add_owner( value: dict, # The resource being created/accessed ): """Make resources private to their creator.""" - # Add owner when creating resources + # Examples: + # ctx: AuthContext( + # permissions=[], + # user=ProxyUser( + # identity='user1', + # is_authenticated=True, + # display_name='user1' + # ), + # resource='threads', + # action='create_run' + # ) + # value: + # { + # 'thread_id': UUID('1e1b2733-303f-4dcd-9620-02d370287d72'), + # 'assistant_id': UUID('fe096781-5601-53d2-b2f6-0d3403f7e9ca'), + # 'run_id': UUID('1efbe268-1627-66d4-aa8d-b956b0f02a41'), + # 'status': 'pending', + # 'metadata': {}, + # 'prevent_insert_if_inflight': True, + # 'multitask_strategy': 'reject', + # 'if_not_exists': 'reject', + # 'after_seconds': 0, + # 'kwargs': { + # 'input': {'messages': [{'role': 'user', 'content': 'Hello!'}]}, + # 'command': None, + # 'config': { + # 'configurable': { + # 'langgraph_auth_user': ... Your user object... + # 'langgraph_auth_user_id': 'user1' + # } + # }, + # 'stream_mode': ['values'], + # 'interrupt_before': None, + # 'interrupt_after': None, + # 'webhook': None, + # 'feedback_keys': None, + # 'temporary': False, + # 'subgraphs': False + # } + # } + + # Do 2 things: + # 1. Add the user's ID to the resource's metadata. Each LangGraph resource has a `metadata` dict that persists with the resource. + # this metadata is useful for filtering in read and update operations + # 2. Return a filter that lets users only see their own resources filters = {"owner": ctx.user.identity} metadata = value.setdefault("metadata", {}) metadata.update(filters) @@ -182,11 +226,15 @@ async def on_thread_create( 1. Sets metadata on the thread being created to track ownership 2. Returns a filter that ensures only the creator can access it """ + # Example value: + # {'thread_id': UUID('99b045bc-b90b-41a8-b882-dabc541cf740'), 'metadata': {}, 'if_exists': 'raise'} + # Add owner metadata to the thread being created # This metadata is stored with the thread and persists metadata = value.setdefault("metadata", {}) metadata["owner"] = ctx.user.identity + # Return filter to restrict access to just the creator return {"owner": ctx.user.identity} @@ -210,6 +258,14 @@ async def on_assistants( ): # For illustration purposes, we will deny all requests # that touch the assistants resource + # Example value: + # { + # 'assistant_id': UUID('63ba56c3-b074-4212-96e2-cc333bbc4eb4'), + # 'graph_id': 'agent', + # 'config': {}, + # 'metadata': {}, + # 'name': 'Untitled' + # } raise Auth.exceptions.HTTPException( status_code=403, detail="User lacks the required permissions.", From 931419909b8a3ed4c52e1928e69ff657a9c12598 Mon Sep 17 00:00:00 2001 From: William Fu-Hinthorn <13333726+hinthornw@users.noreply.github.com> Date: Thu, 19 Dec 2024 08:59:11 -0800 Subject: [PATCH 2/4] rm --- docs/docs/concepts/auth.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/docs/docs/concepts/auth.md b/docs/docs/concepts/auth.md index ae7a1eb17..993cf8a92 100644 --- a/docs/docs/concepts/auth.md +++ b/docs/docs/concepts/auth.md @@ -342,10 +342,6 @@ async def rbac_create(ctx: Auth.types.AuthContext, value: dict): ## Supported Resources -LangGraph provides authorization handlers for the following resource types: - -## Supported Resources - LangGraph provides three levels of authorization handlers, from most general to most specific: 1. **Global Handler** (`@auth.on`): Matches all resources and actions From 62b35277ec6a6c1fb5523ba1e935607afa5b2ada Mon Sep 17 00:00:00 2001 From: William Fu-Hinthorn <13333726+hinthornw@users.noreply.github.com> Date: Thu, 19 Dec 2024 09:01:50 -0800 Subject: [PATCH 3/4] Warning more obvious --- docs/docs/concepts/auth.md | 31 +++++++++++---------- docs/docs/tutorials/auth/getting_started.md | 9 ++++-- docs/docs/tutorials/auth/resource_auth.md | 5 ++++ 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/docs/docs/concepts/auth.md b/docs/docs/concepts/auth.md index 993cf8a92..eae18ba01 100644 --- a/docs/docs/concepts/auth.md +++ b/docs/docs/concepts/auth.md @@ -17,6 +17,22 @@ While often used interchangeably, these terms represent distinct security concep In LangGraph Platform, authentication is handled by your [`@auth.authenticate`](../cloud/reference/sdk/python_sdk_ref.md#langgraph_sdk.auth.Auth.authenticate) handler, and authorization is handled by your [`@auth.on`](../cloud/reference/sdk/python_sdk_ref.md#langgraph_sdk.auth.Auth.on) handlers. +## Default Security Models + +LangGraph Platform provides different security defaults: + +### LangGraph Cloud + +- Uses LangSmith API keys by default +- Requires valid API key in `x-api-key` header +- Can be customized with your auth handler + +### Self-Hosted + +- No default authentication +- Complete flexibility to implement your security model +- You control all aspects of authentication and authorization + ## System Architecture A typical authentication setup involves three main components: @@ -402,21 +418,6 @@ Here are all the supported action handlers: Runs are scoped to their parent thread for access control. This means permissions are typically inherited from the thread, reflecting the conversational nature of the data model. All run operations (reading, listing) except creation are controlled by the thread's handlers. There is a specific `create_run` handler for creating new runs because it had more arguments that you can view in the handler. -## Default Security Models - -LangGraph Platform provides different security defaults: - -### LangGraph Cloud - -- Uses LangSmith API keys by default -- Requires valid API key in `x-api-key` header -- Can be customized with your auth handler - -### Self-Hosted - -- No default authentication -- Complete flexibility to implement your security model -- You control all aspects of authentication and authorization ## Next Steps diff --git a/docs/docs/tutorials/auth/getting_started.md b/docs/docs/tutorials/auth/getting_started.md index 0f8a79bae..02fce1c58 100644 --- a/docs/docs/tutorials/auth/getting_started.md +++ b/docs/docs/tutorials/auth/getting_started.md @@ -5,6 +5,7 @@ 1. Basic Authentication (you are here) - Control who can access your bot 2. [Resource Authorization](resource_auth.md) - Let users have private conversations 3. [Production Auth](add_auth_server.md) - Add real user accounts and validate using OAuth2 + !!! tip "Prerequisites" This guide assumes basic familiarity with the following concepts: @@ -46,8 +47,12 @@ The graph should run, and if you were to self-host this on the public internet, ![No auth](./img/no_auth.png) -Now that we've seen the base LangGraph app, let's add authentication to it! In part 1, we will start with a hard-coded token for illustration purposes. -We will get to a "production-ready" authentication scheme in part 3, after mastering the basics. +Now that we've seen the base LangGraph app, let's add authentication to it! + +???+ tip "Placeholder token" + + In part 1, we will start with a hard-coded token for illustration purposes. + We will get to a "production-ready" authentication scheme in part 3, after mastering the basics. ## Adding Authentication diff --git a/docs/docs/tutorials/auth/resource_auth.md b/docs/docs/tutorials/auth/resource_auth.md index ae1d08da4..46494e4ff 100644 --- a/docs/docs/tutorials/auth/resource_auth.md +++ b/docs/docs/tutorials/auth/resource_auth.md @@ -10,6 +10,11 @@ In this tutorial, we will extend our chatbot to give each user their own private ![Authorization handlers](./img/authorization.png) +???+ tip "Placeholder token" + + As we did in [part 1](getting_started.md), for this section, we will use a hard-coded token for illustration purposes. + We will get to a "production-ready" authentication scheme in part 3, after mastering the basics. + ## Understanding Resource Authorization In the last tutorial, we controlled who could access our bot. But right now, any authenticated user can see everyone else's conversations! Let's fix that by adding [resource authorization](../../concepts/auth.md#resource-authorization). From 9e767afad7eb831cafc457c178720d6a6170f323 Mon Sep 17 00:00:00 2001 From: William Fu-Hinthorn <13333726+hinthornw@users.noreply.github.com> Date: Thu, 19 Dec 2024 09:09:36 -0800 Subject: [PATCH 4/4] Link --- docs/docs/concepts/auth.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/docs/concepts/auth.md b/docs/docs/concepts/auth.md index eae18ba01..d5119e9e4 100644 --- a/docs/docs/concepts/auth.md +++ b/docs/docs/concepts/auth.md @@ -139,7 +139,7 @@ The returned user information is available: After authentication, LangGraph calls your [`@auth.on`](../cloud/reference/sdk/python_sdk_ref.md#langgraph_sdk.auth.Auth.on) handlers to control access to specific resources (e.g., threads, assistants, crons). These handlers can: -1. Add metadata to be saved during resource creation by mutating the `value["metadata"]` dictionary directly. +1. Add metadata to be saved during resource creation by mutating the `value["metadata"]` dictionary directly. See the [supported actions table](##supported-actions) for the list of types the value can take for each action. 2. Filter resources by metadata during search/list or read operations by returning a [filter dictionary](#filter-operations). 3. Raise an HTTP exception if access is denied. @@ -393,6 +393,7 @@ If a more specific handler is registered, the more general handler will not be c ``` More specific handlers provide better type hints since they handle fewer action types. +#### Supported actions and types {#supported-actions} Here are all the supported action handlers: | Resource | Handler | Description | Value Type |