我正在开发一个带有“OAuth Client Credentials”流程的Web API 2,在第一次调用授权令牌时,我需要在控制器之后访问一个额外的参数,而不需要一直在请求。
为身份验证过程传递附加参数的最佳方法是什么,稍后在控制器中使用它而不需要在将来的请求中处理它并考虑安全问题?
我发现开发人员在URL中传递这些参数,并将其添加到OWinContext:
public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
string clientId;
string clientSecret;
if (context.TryGetBasicCredentials(out clientId, out clientSecret) ||
context.TryGetFormCredentials(out clientId, out clientSecret))
{
try
{
if (context.Parameters.Any(x => x.Key == "Participant"))
{
// Get Participant(Additional Parameters)
string participant = context.Parameters.First(x => x.Key == "participant").Value[0];
//Validating Client
Microsoft.AspNet.Identity.PasswordHasher passwordHaser = new Microsoft.AspNet.Identity.PasswordHasher();
Client client = _clientAppService.GetById(Guid.Parse(clientId));
if (client != null && passwordHaser.VerifyHashedPassword(client.SecretHash, clientSecret) == Microsoft.AspNet.Identity.PasswordVerificationResult.Success)
{
context.OwinContext.Set<Client>("oauth:client", client);
//Store Participant(Additional Parameters)
context.OwinContext.Set<Participant>("urn:participant", new Participant { Document = participant });
context.Validated();
}
else
{
context.SetError("invalid_client", "Client credentials are invalid.");
context.Rejected();
}
}
else
{
context.SetError("invalid_request", "Participant are invalid.");
context.Rejected();
}
}
catch (Exception)
{
context.SetError("server_error");
context.Rejected();
}
}
else
{
context.SetError("invalid_client", "Client credentials could not be retrieved through the Authorization header.");
context.Rejected();
}
return Task.FromResult(0);
}
我试图通过ModelBinder来获取它,遗憾的是上下文总是返回null:
public class ParticipantModelBinder : IModelBinder
{
public bool BindModel(System.Web.Http.Controllers.HttpActionContext actionContext, ModelBindingContext bindingContext)
{
//Returning null
Participant participant = HttpContext.Current.GetOwinContext().Get<Participant>("urn:participant");
bindingContext.Model = participant;
return true;
}
}
控制器:
[Authorize]
public class ParticipantController : ApiController
{
public decimal GetBalance([ModelBinder(BinderType=typeof(ParticipantModelBinder))] Participant participant)
{
return 0;
}
}
我在网上找到的另一个解决方案是在方法GrantClientCredentials上添加一个新的Claim,但我不知道如何在控制器上获取值:
public override Task GrantClientCredentials(OAuthGrantClientCredentialsContext context)
{
//Client validated, generate token
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
Client client = context.OwinContext.Get<Client>("oauth:client");
if (client.AllowedGrant == OAuthGrant.Client)
{
ClaimsIdentity identity = new ClaimsIdentity(new GenericIdentity(context.ClientId, OAuthDefaults.AuthenticationType));
identity.AddClaim(new Claim(ClaimTypes.Role, "User"));
// Add an custum Claim with the additional parameter
identity.AddClaim(new Claim("Participant", context.OwinContext.Get<Participant>("urn:participant").Document));
context.Validated(identity);
}
else
{
context.SetError(
"unauthorized_client",
"The authenticated client is not authorized to use this authorization grant type");
}
return Task.FromResult(0);
}