首页 > 解决方案 > 如何在 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?

标签: oauth-2.0asp.net-web-api2

解决方案


我通过两种方式得到了解决方案。

解决方案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.ParametersValidateClientAuthentication方法本身中使用 userId。

var username = context.Parameters.Get("username");

在这里我可以检索用户(此处不验证)并检查用户是否具有客户端 ID。如果存在,我需要验证客户端否则被拒绝。

为了简单起见,我使用了解决方案 1。第二种解决方案需要从 owin 上下文中获取用户并检查是否存在。

谢谢。


推荐阅读