我正在尝试使用DotNetOpenAuth
实施OAuth2授权服务器。客户端是基于JavaScript的,因此无法保守任何秘密。这与this question完全相同,但与另一个框架相同。
客户端使用以下参数(针对令牌端点)access_token
和refresh_token
请求:
这确实有效。现在我想使用refresh_token
并使用以下参数对令牌端点发出请求:
这给了我以下回应:
{"error":"invalid_client","error_description":"The client secret was incorrect."}
因为RFC6749声明:
,所以(至少有些)感觉到了因为刷新令牌通常是持久的凭据 请求额外访问令牌,刷新令牌绑定到 发给它的客户。如果客户类型是机密或 客户端已获得客户端凭据(或已分配其他凭据) 身份验证要求),客户端必须通过身份验证 授权服务器,如第3.2.1节中所述。
如果我改变了我的请求:
问题是我的客户端不应该保密(因为它毕竟是客户端JavaScript)。
这是客户端的定义方式:
New ClientDescription(ApiKey, New Uri(allowedCallback), ClientType.Public)
我搜索了DotNetOpenAuth源代码,发现没有使用ClientType
。对我来说,它看起来根本就没用过。
也无法设置空客户端密码,因为DotNetOpenAuth源代码主动检查此(ClientAuthenticationModules.cs
):
if (!string.IsNullOrEmpty(clientSecret)) {
if (client.IsValidClientSecret(clientSecret)) {
return ClientAuthenticationResult.ClientAuthenticated;
} else { // invalid client secret
return ClientAuthenticationResult.ClientAuthenticationRejected;
}
} else { // no client secret provided
return ClientAuthenticationResult.ClientIdNotAuthenticated;
}
如果我看看MessageValidationBindingElement.cs
:
if (authenticatedClientRequest != null) {
string clientIdentifier;
var result = this.clientAuthenticationModule.TryAuthenticateClient(this.AuthServerChannel.AuthorizationServer, authenticatedClientRequest, out clientIdentifier);
switch (result) {
case ClientAuthenticationResult.ClientAuthenticated:
break;
case ClientAuthenticationResult.NoAuthenticationRecognized:
case ClientAuthenticationResult.ClientIdNotAuthenticated:
// The only grant type that allows no client credentials is the resource owner credentials grant.
AuthServerUtilities.TokenEndpointVerify(resourceOwnerPasswordCarrier != null, accessTokenRequest, Protocol.AccessTokenRequestErrorCodes.InvalidClient, this.clientAuthenticationModule, AuthServerStrings.ClientSecretMismatch);
break;
default:
AuthServerUtilities.TokenEndpointVerify(false, accessTokenRequest, Protocol.AccessTokenRequestErrorCodes.InvalidClient, this.clientAuthenticationModule, AuthServerStrings.ClientSecretMismatch);
break;
}
特别是评论唯一不允许客户端凭据的授权类型是资源所有者凭据授权。让我感到奇怪。这是否意味着在我的场景中JS客户端应该发送用户名/密码?不会这会引发以下异常:
AccessTokenResourceOwnerPasswordCredentialsRequest parameter 'grant_type' to have value 'password' but had 'refresh_token' instead.
对我来说没问题,因为我不希望客户端保留密码。
所以我的问题在这里:
client_id
是公共知识,所以它不用于任何安全目的。我是对的吗?ClientType.Public
是否有意义?client_id
和client_secret
作为非秘密,会有什么不同吗?例如。只提供虚拟值?有什么安全隐患?