我的应用程序要求使用客户端凭据和其他代码(哈希)进行身份验证。
我遵循此link来创建和使用自定义IExtensionGrantValidator
。
我设法通过批准的授权来调用自定义IExtensionGrantValidator
,但是客户总是会遇到invalid_grant
错误。
由于某种原因,d Result
(属性ExtensionGrantValidationContext
)的设置操作总是失败(覆盖Error
值会将覆盖的值返回给客户端)。
这是CustomGrantValidator
代码:
public class CustomGrantValidator : IExtensionGrantValidator
{
public string GrantType => "grant-name";
public Task ValidateAsync(ExtensionGrantValidationContext context)
{
var hash = context.Request.Raw["hash"]; //extract hash from request
var result = string.IsNullOrEmpty(hash) ?
new GrantValidationResult(TokenRequestErrors.InvalidRequest) :
new GrantValidationResult(hash, GrantType);
context.Result = result
}
}
Startup.cs
包含以下行:
services.AddTransient<IExtensionGrantValidator, CustomGrantValidator>();
最后是客户的代码:
var httpClient = new HttpClient() { BaseAddress = new Uri("http://localhost:5000") };
var disco = await httpClient.GetDiscoveryDocumentAsync("http://localhost:5000");
var cReq = await httpClient.RequestTokenAsync(new TokenRequest
{
GrantType = "grant-name",
Address = disco.TokenEndpoint,
ClientId = clientId,// client Id taken from appsetting.json
ClientSecret = clientSecret, //client secret taken from appsetting.json
Parameters = new Dictionary<string, string> { { "hash", hash } }
});
if (cReq.IsError)
//always getting 'invalid_grant' error
throw InvalidOperationException($"{cReq.Error}: {cReq.ErrorDescription}");
答案 0 :(得分:0)
以下代码适用于我的环境:
public async Task ValidateAsync(ExtensionGrantValidationContext context)
{
var hash = context.Request.Raw["hash"]; //extract hash from request
var result = string.IsNullOrEmpty(hash) ?
new GrantValidationResult(TokenRequestErrors.InvalidRequest) :
new GrantValidationResult(hash, GrantType);
context.Result = result;
return;
}
不要忘记注册客户端以允许自定义授予:
return new List<Client>
{
new Client
{
ClientId = "client",
// no interactive user, use the clientid/secret for authentication
AllowedGrantTypes = { "grant-name" },
// secret for authentication
ClientSecrets =
{
new Secret("secret".Sha256())
},
// scopes that client has access to
AllowedScopes = { "api1" }
}
};
答案 1 :(得分:0)
我遇到了同样的问题,并从@Sarah Lissachell 找到了答案,结果证明我需要实现 IProfileService。这个接口有一个叫做 IsActiveAsync 的方法。如果不实现这个方法,ValidateAsync 的答案永远是false。
public class IdentityProfileService : IProfileService
{
//This method comes second
public async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
//IsActiveAsync turns out to be true
//Here you add the claims that you want in the access token
var claims = new List<Claim>();
claims.Add(new Claim("ThisIsNotAGoodClaim", "MyCrapClaim"));
context.IssuedClaims = claims;
}
//This method comes first
public async Task IsActiveAsync(IsActiveContext context)
{
bool isActive = false;
/*
Implement some code to determine that the user is actually active
and set isActive to true
*/
context.IsActive = isActive;
}
}
然后你必须在你的启动页面中添加这个实现。
public void ConfigureServices(IServiceCollection services)
{
// Some other code
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddAspNetIdentity<Users>()
.AddInMemoryApiResources(config.GetApiResources())
.AddExtensionGrantValidator<CustomGrantValidator>()
.AddProfileService<IdentityProfileService>();
// More code
}