跳到主内容

动态客户端注册

Dynamic Client Registration (DCR) 允许您的软件通过一次 HTTP 请求即可在 Casdoor 中注册 OAuth 客户端,而无需在管理员 UI 中手动创建应用。 这在向最终用户分发工具时很有帮助:MCP客户端、CLI或桌面应用可在首次运行或安装时获取客户端凭据。 Casdoor 实施了 RFC 7591

注册端点

该端点在 OIDC 发现中公开。 请求 /.well-known/openid-configuration

curl https://your-casdoor.com/.well-known/openid-configuration

使用 registration_endpoint 的值(例如 /api/oauth/register)进行注册:

{
"issuer": "https://your-casdoor.com",
"authorization_endpoint": "https://your-casdoor.com/login/oauth/authorize",
"token_endpoint": "https://your-casdoor.com/api/login/oauth/access_token",
"registration_endpoint": "https://your-casdoor.com/api/oauth/register",
...
}

注册客户端

使用 JSON 元数据向 /api/oauth/register 发送 POST 请求:

curl -X POST https://your-casdoor.com/api/oauth/register \
-H "Content-Type: application/json" \
-d '{
"client_name": "Claude Desktop",
"redirect_uris": ["http://localhost:3000/callback"],
"grant_types": ["authorization_code", "refresh_token"],
"token_endpoint_auth_method": "none",
"application_type": "native"
}'

响应包括新的客户端凭据:

{
"client_id": "a1b2c3d4e5f6",
"client_secret": "secret_xyz789...",
"client_id_issued_at": 1737799294,
"client_secret_expires_at": 0,
"redirect_uris": ["http://localhost:3000/callback"],
"grant_types": ["authorization_code", "refresh_token"],
"token_endpoint_auth_method": "none",
"application_type": "native"
}

请安全地存储 client_idclient_secret——您将在后续所有 OAuth 流程中用到它们。

请求参数

您的注册请求需要至少一个重定向 URI。 其他一切均为可选,Casdoor会应用合理的默认值:

  • redirect_uris(必填):允许的回调 URL 数组,Casdoor 在认证后会重定向至此
  • client_name: 用于你的应用程序的显示名称(如果省略则自动生成)
  • grant_types: OAuth 授权类型,您的应用将使用——默认为 ["authorization_code"]
  • token_endpoint_auth_method: 您的应用程序在令牌端点的认证方式(noneclient_secret_postclient_secret_basic
  • application_type: 对于服务器端应用,选择 web;对于桌面/移动应用,选择 native
  • logo_uri: 您应用程序的Logo的URL
  • client_uri: 您应用程序主页的URL
  • scope:您的应用请求的OAuth作用域列表,以空格分隔

通过DCR创建的应用程序具有7天的令牌有效期,并在管理界面中标记为dcr,以便于识别。

按组织控制DCR

Organizations control whether DCR is available through the dcrPolicy setting on the organization configuration page. Two values are supported:

  • disabled (default) — registration requests are rejected with an error. An unset/empty dcrPolicy is also treated as disabled, so DCR is off unless you explicitly opt in. Casdoor's built-in organization ships with DCR disabled.
  • open — anyone can register an application in this organization without authentication.

This gives you flexibility: turn DCR on for developer-friendly organizations while keeping it locked down for production environments that require manual oversight. Because the default is closed, an unauthenticated registration endpoint is never exposed until you deliberately enable it.

安全模型

The registration endpoint itself requires no authentication—this is by design for public clients like mobile apps and desktop tools that can't securely store credentials before registration. To keep that unauthenticated surface from being exposed by accident, DCR is disabled by default and must be turned on per organization (see Controlling DCR Per Organization).

通过DCR创建的应用程序属于组织的管理员账户,并会在您的应用程序列表中显示带有dcr标签。 This tag is not just a label: DCR-registered applications run under a restricted app-dcr role and can only reach the OAuth/OIDC endpoints they need for the login flow (/api/login/oauth/*, /api/get-oauth-token, /api/userinfo, /api/get-application). They cannot use the client credentials to call other management APIs, which limits the blast radius of a self-registered client.

So that end users can actually sign in to a self-registered app, DCR-registered applications have password sign-in enabled and inherit a set of fields from the organization's default application:

  • Providers and sign-in methods — so there is at least one working sign-in method out of the box.
  • Branding — the logo (only when the request omits logo_uri), theme, footer HTML, and form CSS, so the login page matches the rest of the organization.
  • Sign-in items — the same sign-in form layout as the default application.
  • EnableSigninSession and EnableWebAuthn — the default application's session and WebAuthn settings.

默认情况下,客户端密钥不会过期,但您可随时通过管理界面撤销任何应用程序。 对于生产部署,考虑一下您的组织是否真的需要未经过身份验证的注册。 Many scenarios work fine with manual app creation, and leaving DCR disabled removes a potential abuse vector.

完整示例:MCP 客户端

以下是 MCP 客户端从零开始实现 DCR 的方法:

// Discover the registration endpoint
const discovery = await fetch('https://your-casdoor.com/.well-known/openid-configuration')
.then(r => r.json());

// Register the application
const registration = await fetch(discovery.registration_endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
client_name: 'MCP Client',
redirect_uris: ['http://127.0.0.1:6437/callback'],
grant_types: ['authorization_code', 'refresh_token'],
token_endpoint_auth_method: 'none',
application_type: 'native'
})
}).then(r => r.json());

// Store credentials for OAuth flows
const { client_id, client_secret } = registration;

使用这些凭据,客户端将按照标准的OAuth授权码流程进行操作。 用户在浏览器中进行身份验证,Casdoor 会将授权码重定向回您的回调 URL,您再用该授权码换取访问令牌。

处理注册失败

当出现错误时,Casdoor会返回符合RFC 7591规范的错误,并附带一个error代码和便于人类阅读的error_description。 最常见的问题:缺少重定向 URI(invalid_redirect_uri)、参数格式错误(invalid_client_metadata),或组织的 DCR 已禁用(access_denied)。 请查看描述字段,了解需要修复的具体问题。