3. 客户端注册端点
客户端注册端点 (client registration endpoint) 是本文定义的 OAuth 2.0 端点, 用于允许客户端向授权服务器注册. 客户端注册端点必须接受 HTTP POST 消息, 请求参数以 "application/json" 格式编码在实体正文中. 如第 5 节所述, 客户端注册端点必须由传输层安全机制保护.
客户端注册端点可以是 OAuth 2.0 [RFC6749] 受保护资源, 并且可以接受 OAuth 2.0 access token 形式的初始访问令牌 (initial access token), 从而将注册限制为先前已授权的参与方. 客户端或开发者获得初始访问令牌的方式通常是带外完成的, 不在本规范范围内. 客户端注册端点验证和校验初始访问令牌的方法也不在本规范范围内.
为了支持开放注册并促进更广泛的互操作性, 客户端注册端点应当允许未授权的注册请求, 即请求中不包含初始访问令牌. 这类请求可以被速率限制或以其他方式限制, 以防止针对客户端注册端点的拒绝服务攻击.
3.1. Client Registration Request
此操作将客户端注册到授权服务器. 授权服务器为该客户端分配唯一客户端标识符, 可选地分配客户端密钥, 并将请求中提供的元数据与签发的客户端标识符关联. 请求包含注册期间为客户端指定的任意客户端元数据参数. 授权服务器可以为客户端元数据中省略的项目提供默认值.
注册时, 客户端或开发者向客户端注册端点发送 HTTP POST, 内容类型为 "application/json". HTTP 实体载荷是一个 JSON [RFC7159] 文档, 由一个 JSON 对象组成, 所有请求的客户端元数据值都作为该 JSON 对象的顶层成员.
例如, 如果服务器支持开放注册 (无初始访问令牌), 客户端可以向客户端注册端点发送以下注册请求.
以下是一个不使用初始访问令牌的非规范性请求示例:
POST /register HTTP/1.1
Content-Type: application/json
Accept: application/json
Host: server.example.com
{
"redirect_uris": [
"https://client.example.org/callback",
"https://client.example.org/callback2"],
"client_name": "My Example Client",
"client_name#ja-Jpan-JP":
"\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8\u540D",
"token_endpoint_auth_method": "client_secret_basic",
"logo_uri": "https://client.example.org/logo.png",
"jwks_uri": "https://client.example.org/my_public_keys.jwks",
"example_extension_parameter": "example_value"
}
另一种情况是, 如果服务器支持授权注册, 开发者或客户端会被预配一个初始访问令牌. 初始访问令牌的获取方式不在本规范范围内. 开发者或客户端随后向客户端注册端点发送以下授权注册请求. 请注意, 此示例中初始访问令牌以 OAuth 2.0 Bearer Token [RFC6750] 的形式发送, 但授权服务器也可以使用任何 OAuth 2.0 令牌类型.
以下是一个使用初始访问令牌并以值形式注册 JWK Set 的非规范性请求示例 (值中的换行仅为显示目的):
POST /register HTTP/1.1
Content-Type: application/json
Accept: application/json
Authorization: Bearer ey23f2.adfj230.af32-developer321
Host: server.example.com
{
"redirect_uris": ["https://client.example.org/callback",
"https://client.example.org/callback2"],
"client_name": "My Example Client",
"client_name#ja-Jpan-JP":
"\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8\u540D",
"token_endpoint_auth_method": "client_secret_basic",
"policy_uri": "https://client.example.org/policy.html",
"jwks": {"keys": [{
"e": "AQAB",
"n": "nj3YJwsLUFl9BmpAbkOswCNVx17Eh9wMO-_AReZwBqfaWFcfG
HrZXsIV2VMCNVNU8Tpb4obUaSXcRcQ-VMsfQPJm9IzgtRdAY8NN8Xb7PEcYyk
lBjvTtuPbpzIaqyiUepzUXNDFuAOOkrIol3WmflPUUgMKULBN0EUd1fpOD70p
RM0rlp_gg_WNUKoW1V-3keYUJoXH9NztEDm_D2MQXj9eGOJJ8yPgGL8PAZMLe
2R7jb9TxOCPDED7tY_TU4nFPlxptw59A42mldEmViXsKQt60s1SLboazxFKve
qXC_jpLUt22OC6GUG63p-REw-ZOr3r845z50wMuzifQrMI9bQ",
"kty": "RSA"
}]},
"example_extension_parameter": "example_value"
}
3.1.1. Client Registration Request Using a Software Statement
除 JSON 元素外, 客户端元数据值也可以通过第 2.3 节所述的软件声明 (software statement) 提供. 如果授权服务器不支持此功能, 可以忽略软件声明. 如果服务器支持软件声明, 则软件声明中传递的客户端元数据值必须优先于普通 JSON 元素中传递的值.
软件声明使用以下可选成员包含在请求 JSON 对象中:
software_statement
一个软件声明, 其中以声明 (claims) 形式包含关于客户端软件的客户端元数据值. 这是一个字符串值, 包含完整的已签名 JWT.
在以下示例中, 某些注册参数作为第 2.3 节示例软件声明中的声明传递, 而某些特定于客户端实例的值则作为普通参数传递 (值中的换行仅为显示目的):
POST /register HTTP/1.1
Content-Type: application/json
Accept: application/json
Host: server.example.com
{
"redirect_uris": [
"https://client.example.org/callback",
"https://client.example.org/callback2"
],
"software_statement": "eyJhbGciOiJSUzI1NiJ9.
eyJzb2Z0d2FyZV9pZCI6IjROUkIxLTBYWkFCWkk5RTYtNVNNM1IiLCJjbGll
bnRfbmFtZSI6IkV4YW1wbGUgU3RhdGVtZW50LWJhc2VkIENsaWVudCIsImNs
aWVudF91cmkiOiJodHRwczovL2NsaWVudC5leGFtcGxlLm5ldC8ifQ.
GHfL4QNIrQwL18BSRdE595T9jbzqa06R9BT8w409x9oIcKaZo_mt15riEXHa
zdISUvDIZhtiyNrSHQ8K4TvqWxH6uJgcmoodZdPwmWRIEYbQDLqPNxREtYn0
5X3AR7ia4FRjQ2ojZjk5fJqJdQ-JcfxyhK-P8BAWBd6I2LLA77IG32xtbhxY
fHX7VhuU5ProJO8uvu3Ayv4XRhLZJY4yKfmyjiiKiPNe-Ia4SMy_d_QSWxsk
U5XIQl5Sa2YRPMbDRXttm2TfnZM1xx70DoYi8g6czz-CPGRi4SW_S2RKHIJf
IjoI3zTJ0Y2oe0_EJAiXbL6OyF9S5tKxDXV8JIndSA",
"scope": "read write",
"example_extension_parameter": "example_value"
}
3.2. Responses
Upon a successful registration request, the authorization server returns a client identifier for the client. The server responds with an HTTP 201 Created status code and a body of type "application/json" with content as described in Section 3.2.1.
Upon an unsuccessful registration request, the authorization server responds with an error, as described in Section 3.2.2.
3.2.1. Client Information Response
The response contains the client identifier as well as the client secret, if the client is a confidential client. The response MAY contain additional fields as specified by extensions to this specification.
client_id
REQUIRED. OAuth 2.0 client identifier string. It SHOULD NOT be currently valid for any other registered client, though an authorization server MAY issue the same client identifier to multiple instances of a registered client at its discretion.
client_secret
OPTIONAL. OAuth 2.0 client secret string. If issued, this MUST be unique for each "client_id" and SHOULD be unique for multiple instances of a client using the same "client_id". This value is used by confidential clients to authenticate to the token endpoint, as described in OAuth 2.0 [RFC6749], Section 2.3.1.
client_id_issued_at
OPTIONAL. Time at which the client identifier was issued. The time is represented as the number of seconds from 1970-01-01T00:00:00Z as measured in UTC until the date/time of issuance.
client_secret_expires_at
REQUIRED if "client_secret" is issued. Time at which the client secret will expire or 0 if it will not expire. The time is represented as the number of seconds from 1970-01-01T00:00:00Z as measured in UTC until the date/time of expiration.
Additionally, the authorization server MUST return all registered metadata about this client, including any fields provisioned by the authorization server itself. The authorization server MAY reject or replace any of the client's requested metadata values submitted during the registration and substitute them with suitable values. The client or developer can check the values in the response to determine if the registration is sufficient for use (e.g., the registered "token_endpoint_auth_method" is supported by the client software) and determine a course of action appropriate for the client software. The response to such a situation is out of scope for this specification but could include filing a report with the application developer or authorization server provider, attempted re-registration with different metadata values, or various other methods. For instance, if the server also supports a registration management mechanism such as that defined in [RFC7592], the client or developer could attempt to update the registration with different metadata values. This process could also be aided by a service discovery protocol, such as [OpenID.Discovery], which can list a server's capabilities, allowing a client to make a more informed registration request. The use of any such management or discovery system is optional and outside the scope of this specification.
The successful registration response uses an HTTP 201 Created status code with a body of type "application/json" consisting of a single JSON object [RFC7159] with all parameters as top-level members of the object.
If a software statement was used as part of the registration, its value MUST be returned unmodified in the response along with other metadata using the "software_statement" member name. Client metadata elements used from the software statement MUST also be returned directly as top-level client metadata values in the registration response (possibly with different values, since the values requested and the values used may differ).
以下是一个成功注册的非规范性响应示例:
HTTP/1.1 201 Created
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
{
"client_id": "s6BhdRkqt3",
"client_secret": "cf136dc3c1fc93f31185e5885805d",
"client_id_issued_at": 2893256800,
"client_secret_expires_at": 2893276800,
"redirect_uris": [
"https://client.example.org/callback",
"https://client.example.org/callback2"],
"grant_types": ["authorization_code", "refresh_token"],
"client_name": "My Example Client",
"client_name#ja-Jpan-JP":
"\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8\u540D",
"token_endpoint_auth_method": "client_secret_basic",
"logo_uri": "https://client.example.org/logo.png",
"jwks_uri": "https://client.example.org/my_public_keys.jwks",
"example_extension_parameter": "example_value"
}
3.2.2. Client Registration Error Response
When an OAuth 2.0 error condition occurs, such as the client presenting an invalid initial access token, the authorization server returns an error response appropriate to the OAuth 2.0 token type.
When a registration error condition occurs, the authorization server returns an HTTP 400 status code (unless otherwise specified) with content type "application/json" consisting of a JSON object [RFC7159] describing the error in the response body.
Two members are defined for inclusion in the JSON object:
error
REQUIRED. Single ASCII error code string.
error_description
OPTIONAL. Human-readable ASCII text description of the error used for debugging.
Other members MAY also be included and, if they are not understood, they MUST be ignored.
This specification defines the following error codes:
invalid_redirect_uri
The value of one or more redirection URIs is invalid.
invalid_client_metadata
The value of one of the client metadata fields is invalid and the server has rejected this request. Note that an authorization server MAY choose to substitute a valid value for any requested parameter of a client's metadata.
invalid_software_statement
The software statement presented is invalid.
unapproved_software_statement
The software statement presented is not approved for use by this authorization server.
以下是一个由授权服务器列入黑名单的重定向 URI 导致的非规范性错误响应示例 (值中的换行仅为显示目的):
HTTP/1.1 400 Bad Request
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
{
"error": "invalid_redirect_uri",
"error_description": "The redirection URI
http://sketchy.example.com is not allowed by this server."
}
以下是一个由 "response_types" 和 "grant_types" 值组合不一致导致的非规范性错误响应示例 (值中的换行仅为显示目的):
HTTP/1.1 400 Bad Request
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
{
"error": "invalid_client_metadata",
"error_description": "The grant type 'authorization_code' must be
registered along with the response type 'code' but found only
'implicit' instead."
}