OIDC - 基于 JWT 的认证
使用 JWT 认证管理员/用户/项目访问代理。
用法
步骤 1. 设置代理
JWT_PUBLIC_KEY_URL
: 这是您的 OpenID 提供商的公钥端点。通常是{openid-provider-base-url}/.well-known/openid-configuration/jwks
。对于 Keycloak 来说,它是{keycloak_base_url}/realms/{your-realm}/protocol/openid-connect/certs
。JWT_AUDIENCE
: 这是用于解码 JWT 的目标受众(audience)。如果未设置,解码步骤将不会验证目标受众。
export JWT_PUBLIC_KEY_URL="" # "https://demo.duendesoftware.com/.well-known/openid-configuration/jwks"
- 在您的配置中设置
enable_jwt_auth
。这将指示代理检查令牌是否为 JWT 令牌。
general_settings:
master_key: sk-1234
enable_jwt_auth: True
model_list:
- model_name: azure-gpt-3.5
litellm_params:
model: azure/<your-deployment-name>
api_base: os.environ/AZURE_API_BASE
api_key: os.environ/AZURE_API_KEY
api_version: "2023-07-01-preview"
步骤 2. 创建带有作用域的 JWT
- 管理员
- 项目
在您的 OpenID 提供商(例如 Keycloak)中创建一个名为 litellm_proxy_admin
的客户端作用域。
生成 JWT 时,为您的用户授予 litellm_proxy_admin
作用域。
curl --location ' 'https://demo.duendesoftware.com/connect/token'' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id={CLIENT_ID}' \
--data-urlencode 'client_secret={CLIENT_SECRET}' \
--data-urlencode 'username=test-{USERNAME}' \
--data-urlencode 'password={USER_PASSWORD}' \
--data-urlencode 'grant_type=password' \
--data-urlencode 'scope=litellm_proxy_admin' # 👈 grant this scope
在您的 OpenID 提供商(例如 Keycloak)上为您的项目创建一个 JWT。
curl --location ' 'https://demo.duendesoftware.com/connect/token'' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id={CLIENT_ID}' \ # 👈 project id
--data-urlencode 'client_secret={CLIENT_SECRET}' \
--data-urlencode 'grant_type=client_credential' \
步骤 3. 测试您的 JWT
- /key/generate
- /chat/completions
curl --location '{proxy_base_url}/key/generate' \
--header 'Authorization: Bearer eyJhbGciOiJSUzI1NiI...' \
--header 'Content-Type: application/json' \
--data '{}'
curl --location 'http://0.0.0.0:4000/v1/chat/completions' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer eyJhbGciOiJSUzI1...' \
--data '{"model": "azure-gpt-3.5", "messages": [ { "role": "user", "content": "What's the weather like in Boston today?" } ]}'
高级
多个 OIDC 提供商
如果您希望 LiteLLM 根据多个 OIDC 提供商(例如 Google Cloud、GitHub Auth)验证您的 JWT,请使用此项。
在您的环境中将 JWT_PUBLIC_KEY_URL
设置为您的 OIDC 提供商 URL 的逗号分隔列表。
export JWT_PUBLIC_KEY_URL="https://demo.duendesoftware.com/.well-known/openid-configuration/jwks,https://#/.well-known/openid-configuration/jwks"
设置接受的 JWT 作用域名称
更改 JWT 'scopes' 中的字符串,LiteLLM 会评估该字符串以查看用户是否具有管理员访问权限。
general_settings:
master_key: sk-1234
enable_jwt_auth: True
litellm_jwtauth:
admin_jwt_scope: "litellm-proxy-admin"
跟踪终端用户 / 内部用户 / 团队 / 组织
设置 JWT 令牌中对应 LiteLLM 用户 / 团队 / 组织的字段。
general_settings:
master_key: sk-1234
enable_jwt_auth: True
litellm_jwtauth:
admin_jwt_scope: "litellm-proxy-admin"
team_id_jwt_field: "client_id" # 👈 CAN BE ANY FIELD
user_id_jwt_field: "sub" # 👈 CAN BE ANY FIELD
org_id_jwt_field: "org_id" # 👈 CAN BE ANY FIELD
end_user_id_jwt_field: "customer_id" # 👈 CAN BE ANY FIELD
预期的 JWT
{
"client_id": "my-unique-team",
"sub": "my-unique-user",
"org_id": "my-unique-org",
}
现在,LiteLLM 将为每次调用自动更新数据库中用户/团队/组织的消费。
JWT 作用域
以下是 JWT 认证令牌上的作用域示例
可以是列表
scope: ["litellm-proxy-admin",...]
可以是空格分隔的字符串
scope: "litellm-proxy-admin ..."
通过团队控制模型访问
- 指定包含用户所属团队 ID 的 JWT 字段。
general_settings:
enable_jwt_auth: True
litellm_jwtauth:
user_id_jwt_field: "sub"
team_ids_jwt_field: "groups"
user_id_upsert: true # add user_id to the db if they don't exist
enforce_team_based_model_access: true # don't allow users to access models unless the team has access
假设您的令牌如下所示
{
...,
"sub": "my-unique-user",
"groups": ["team_id_1", "team_id_2"]
}
- 在 LiteLLM 上创建团队
curl -X POST '<PROXY_BASE_URL>/team/new' \
-H 'Authorization: Bearer <PROXY_MASTER_KEY>' \
-H 'Content-Type: application/json' \
-D '{
"team_alias": "team_1",
"team_id": "team_id_1" # 👈 MUST BE THE SAME AS THE SSO GROUP ID
}'
- 测试流程
UI 的 SSO: 查看演练
API 的 OIDC 认证: 查看演练
流程
- 验证用户 ID 是否在数据库中 (LiteLLM_UserTable)
- 验证任何组是否在数据库中 (LiteLLM_TeamTable)
- 验证任何组是否具有模型访问权限
- 如果所有检查通过,则允许请求
自定义 JWT 验证
如果您需要额外的验证方法来检查令牌是否对 LiteLLM 代理有效,可以使用自定义逻辑验证 JWT 令牌。
1. 设置自定义验证函数
from typing import Literal
def my_custom_validate(token: str) -> Literal[True]:
"""
Only allow tokens with tenant-id == "my-unique-tenant", and claims == ["proxy-admin"]
"""
allowed_tenants = ["my-unique-tenant"]
allowed_claims = ["proxy-admin"]
if token["tenant_id"] not in allowed_tenants:
raise Exception("Invalid JWT token")
if token["claims"] not in allowed_claims:
raise Exception("Invalid JWT token")
return True
2. 设置 config.yaml
general_settings:
master_key: sk-1234
enable_jwt_auth: True
litellm_jwtauth:
user_id_jwt_field: "sub"
team_id_jwt_field: "tenant_id"
user_id_upsert: True
custom_validate: custom_validate.my_custom_validate # 👈 custom validate function
3. 测试流程
预期的 JWT
{
"sub": "my-unique-user",
"tenant_id": "INVALID_TENANT",
"claims": ["proxy-admin"]
}
预期响应
{
"error": "Invalid JWT token"
}
允许的路由
通过配置,配置 JWT 可以访问哪些路由。
默认情况下
- 管理员:只能访问管理路由 (
/team/*
,/key/*
,/user/*
) - 团队:只能访问 openai 路由 (
/chat/completions
等) + 信息路由 (/*/info
)
管理路由
general_settings:
master_key: sk-1234
enable_jwt_auth: True
litellm_jwtauth:
admin_jwt_scope: "litellm-proxy-admin"
admin_allowed_routes: ["/v1/embeddings"]
团队路由
general_settings:
master_key: sk-1234
enable_jwt_auth: True
litellm_jwtauth:
...
team_id_jwt_field: "litellm-team" # 👈 Set field in the JWT token that stores the team ID
team_allowed_routes: ["/v1/chat/completions"] # 👈 Set accepted routes
缓存公钥
控制公钥的缓存时长(以秒为单位)。
general_settings:
master_key: sk-1234
enable_jwt_auth: True
litellm_jwtauth:
admin_jwt_scope: "litellm-proxy-admin"
admin_allowed_routes: ["/v1/embeddings"]
public_key_ttl: 600 # 👈 KEY CHANGE
自定义 JWT 字段
设置包含 team_id 的自定义字段。默认情况下,会检查 'client_id' 字段。
general_settings:
master_key: sk-1234
enable_jwt_auth: True
litellm_jwtauth:
team_id_jwt_field: "client_id" # 👈 KEY CHANGE
阻止团队
要阻止某个团队 ID 的所有请求,请使用 /team/block
阻止团队
curl --location 'http://0.0.0.0:4000/team/block' \
--header 'Authorization: Bearer <admin-token>' \
--header 'Content-Type: application/json' \
--data '{
"team_id": "litellm-test-client-id-new" # 👈 set team id
}'
解除阻止团队
curl --location 'http://0.0.0.0:4000/team/unblock' \
--header 'Authorization: Bearer <admin-token>' \
--header 'Content-Type: application/json' \
--data '{
"team_id": "litellm-test-client-id-new" # 👈 set team id
}'
Upsert 用户 + 允许的电子邮件域
允许属于特定电子邮件域的用户自动访问代理。
general_settings:
master_key: sk-1234
enable_jwt_auth: True
litellm_jwtauth:
user_email_jwt_field: "email" # 👈 checks 'email' field in jwt payload
user_allowed_email_domain: "my-co.com" # allows user@my-co.com to call proxy
user_id_upsert: true # 👈 upserts the user to db, if valid email but not in db
[测试版]使用 OIDC 角色控制访问
允许带有支持角色的 JWT 令牌访问代理。
允许用户和团队访问代理,无需将其添加到数据库中。
非常重要,设置 enforce_rbac: true
以确保 RBAC 系统已启用。
注意:这是测试版功能,可能会意外更改。
general_settings:
enable_jwt_auth: True
litellm_jwtauth:
object_id_jwt_field: "oid" # can be either user / team, inferred from the role mapping
roles_jwt_field: "roles"
role_mappings:
- role: litellm.api.consumer
internal_role: "team"
enforce_rbac: true # 👈 VERY IMPORTANT
role_permissions: # default model + endpoint permissions for a role.
- role: team
models: ["anthropic-claude"]
routes: ["/v1/chat/completions"]
environment_variables:
JWT_AUDIENCE: "api://LiteLLM_Proxy" # ensures audience is validated
object_id_jwt_field
: JWT 令牌中包含对象 ID 的字段。此 ID 可以是用户 ID,也可以是团队 ID。如果同一字段可能同时是两者,请使用此字段代替user_id_jwt_field
和team_id_jwt_field
。roles_jwt_field
: JWT 令牌中包含角色的字段。此字段是用户拥有的角色列表。要索引嵌套字段,请使用点表示法 - 例如resource_access.litellm-test-client-id.roles
。role_mappings
: 角色映射列表。将 JWT 令牌中收到的角色映射到 LiteLLM 的内部角色。JWT_AUDIENCE
: JWT 令牌的目标受众。用于验证 JWT 令牌的目标受众。通过环境变量设置。
令牌示例
{
"aud": "api://LiteLLM_Proxy",
"oid": "eec236bd-0135-4b28-9354-8fc4032d543e",
"roles": ["litellm.api.consumer"]
}
角色映射规范
role
: JWT 令牌中预期的角色。internal_role
: LiteLLM 的内部角色,用于控制访问。
支持的内部角色
team
: 团队对象将用于 RBAC 消费跟踪。用于跟踪特定“用例”的消费。internal_user
: 用户对象将用于 RBAC 消费跟踪。用于跟踪特定“个人用户”的消费。proxy_admin
: 代理管理员将用于 RBAC 消费跟踪。用于授予令牌管理员访问权限。
架构图(控制模型访问)
[测试版]使用作用域控制模型访问
控制 JWT 可以访问哪些模型。设置 enforce_scope_based_access: true
以强制执行基于作用域的访问控制。
1. 使用作用域映射设置 config.yaml。
model_list:
- model_name: anthropic-claude
litellm_params:
model: anthropic/claude-3-5-sonnet
api_key: os.environ/ANTHROPIC_API_KEY
- model_name: gpt-3.5-turbo-testing
litellm_params:
model: gpt-3.5-turbo
api_key: os.environ/OPENAI_API_KEY
general_settings:
enable_jwt_auth: True
litellm_jwtauth:
team_id_jwt_field: "client_id" # 👈 set the field in the JWT token that contains the team id
team_id_upsert: true # 👈 upsert the team to db, if team id is not found in db
scope_mappings:
- scope: litellm.api.consumer
models: ["anthropic-claude"]
- scope: litellm.api.gpt_3_5_turbo
models: ["gpt-3.5-turbo-testing"]
enforce_scope_based_access: true # 👈 enforce scope-based access control
enforce_rbac: true # 👈 enforces only a Team/User/ProxyAdmin can access the proxy.
作用域映射规范
scope
: 用于 JWT 令牌的作用域。models
: JWT 令牌可以访问的模型。值是model_list
中的model_name
。注意:目前不支持通配符路由。
2. 创建带有正确作用域的 JWT。
预期的令牌
{
"scope": ["litellm.api.consumer", "litellm.api.gpt_3_5_turbo"] # can be a list or a space-separated string
}
3. 测试流程。
curl -L -X POST 'http://0.0.0.0:4000/v1/chat/completions' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer eyJhbGci...' \
-d '{
"model": "gpt-3.5-turbo-testing",
"messages": [
{
"role": "user",
"content": "Hey, how'\''s it going 1234?"
}
]
}'