Skip to content

Commit

Permalink
[Docs] Show example payloads (#2839)
Browse files Browse the repository at this point in the history
  • Loading branch information
hinthornw authored Dec 19, 2024
2 parents 5a580ae + 9e767af commit e3050b3
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 41 deletions.
74 changes: 36 additions & 38 deletions docs/docs/concepts/auth.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -123,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.

Expand Down Expand Up @@ -342,10 +358,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
Expand Down Expand Up @@ -381,46 +393,32 @@ 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 |
|----------|---------|-------------|
| **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.
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

Expand Down
9 changes: 7 additions & 2 deletions docs/docs/tutorials/auth/getting_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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
Expand Down
63 changes: 62 additions & 1 deletion docs/docs/tutorials/auth/resource_auth.md
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down Expand Up @@ -68,7 +73,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)
Expand Down Expand Up @@ -182,11 +231,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}

Expand All @@ -210,6 +263,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.",
Expand Down

0 comments on commit e3050b3

Please sign in to comment.