oauth-2.0 - 如何在 ValidateClientAuthentication 方法中获取用户名
问题描述
在我的 webAPI 应用程序中,我用于Resource Owner Password Credentials Grant
身份验证。当前代码使用用户名和密码可以正常工作。
现在应用程序包含多租户,因此我在用户表中添加了“clientId”详细信息。无论如何,客户端详细信息都在另一个云中,我们可以调用该 api 通过传递 clientId 和密码来验证客户端。
为了实现这一点,我使用ValidateClientAuthentication
方法来验证客户端和GrantResourceOwnerCredentials
方法来验证用户。这也很好。
问题: 基本上,我还需要支持老客户,所以他们没有客户详细信息。所以如果用户有clientId,我们需要验证客户端,否则只验证用户。
执行:
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>();
ApplicationUser user = await userManager.FindAsync(context.UserName, context.Password);
if (user == null)
{
context.SetError("invalid_grant", "The user name or password is incorrect.");
return;
}
ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager,
OAuthDefaults.AuthenticationType);
ClaimsIdentity cookiesIdentity = await user.GenerateUserIdentityAsync(userManager,
CookieAuthenticationDefaults.AuthenticationType);
AuthenticationProperties properties = CreateProperties(user.UserName,context.ClientId);
AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties);
context.Validated(ticket);
context.Request.Context.Authentication.SignIn(cookiesIdentity);
}
public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
string clientId;
string clientSecret;
context.TryGetFormCredentials(out clientId, out clientSecret);
TenantCloud clientAPI = new TenantCloud();
context.TryGetFormCredentials(out clientId, out clientSecret);
if (clientId != null || clientSecret != null)
{
var tenantResponseJson = await clientAPI.AuthorizeTenant(clientId, clientSecret).ConfigureAwait(false);
if (tenantResponseJson == null || (tenantResponseJson != null && tenantResponseJson.AccessToken == null))
{
context.Rejected();
return;
}
}
context.Validated();
return;
}
如果用户传递客户详细信息,当前代码可以正常工作。但我想确认用户是否有clientid。如果用户有 clientId,它应该验证或返回错误。
为此,任何从请求中获取用户名的选项,以便我可以获得相应的用户并检查用户是否有 clientId?
解决方案
我通过两种方式得到了解决方案。
解决方案1:
如果用户有客户端 ID,我可以检查 context.ClientId 是否为空。更新如下;
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>();
ApplicationUser user = await userManager.FindAsync(context.UserName, context.Password);
if (user == null || user.IsDeleted)
{
context.SetError("invalid_grant", "The user name or password is incorrect.");
return;
}
//Ensure that user has client/ tenant. If user have tenant and the tenant is not passed, set the context as rejected.
if (!string.IsNullOrEmpty(user.ClientId) && string.IsNullOrEmpty(context.ClientId))
{
context.SetError("invalid_grant", "The client credentials are incorrect.");
return;
}
ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager,
OAuthDefaults.AuthenticationType);
ClaimsIdentity cookiesIdentity = await user.GenerateUserIdentityAsync(userManager,
CookieAuthenticationDefaults.AuthenticationType);
AuthenticationProperties properties = CreateProperties(user.UserName, !string.IsNullOrEmpty(user.ClientId) ? context.ClientId : string.Empty);
AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties);
context.Validated(ticket);
context.Request.Context.Authentication.SignIn(cookiesIdentity);
}
解决方案2:
这正是问题的答案。我可以context.Parameters
在ValidateClientAuthentication
方法本身中使用 userId。
var username = context.Parameters.Get("username");
在这里我可以检索用户(此处不验证)并检查用户是否具有客户端 ID。如果存在,我需要验证客户端否则被拒绝。
为了简单起见,我使用了解决方案 1。第二种解决方案需要从 owin 上下文中获取用户并检查是否存在。
谢谢。
推荐阅读
- java - 纪元的格式化日期未设置为 01/01/1970 00:00
- ruby-on-rails - 如何使用 Rails 6.1 下载旧的活动存储文件?
- swift - 将 Swift 函数转为可复用的扩展
- java - 构建 Java Native Access 表单源:可能未定义的宏:AC_PROG_LIBTOOL
- python - 如何根据元素值组合列表中的列表元素?
- c++ - C++:同时使用整数和对整数的引用
- swift - swift 协议中的泛型
- css - 在 php cookie 中保存暗模式
- java - 使用java流API比较后如何合并两个列表
- python - PyWebIO 按钮刷新页面