如何在Asp.Net中使用OAuth2生成令牌之前获取当前用户?

时间:2017-07-03 06:46:43

标签: asp.net asp.net-mvc oauth-2.0 asp.net-identity owin

我在使用Owin和Oauth2(在Mvc项目中)生成令牌时遇到问题。 我的一些应用程序用户拥有子集用户,他们希望在不知道密码的情况下登录他们的面板。

问题:

public class ApplicationOAuthProvider : OAuthAuthorizationServerProvider
{
    public ApplicationOAuthProvider2(string publicClientId)
    {
    }

    public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
    {
        //get current user
        var user1 = HttpContext.Current.User;//null
        var user2 = Thread.CurrentPrincipal;//null
        var user3 = context.OwinContext.Authentication.User;//null

    }
}

我的OauthOptions:

OAuthOptions = new OAuthAuthorizationServerOptions
            {
                TokenEndpointPath = new PathString("/Token"),
                Provider = new ApplicationOAuthProvider(PublicClientId),
                AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
                AllowInsecureHttp = true
            };

我无法在OauthProvider中获取当前用户。 有没有解决方案?

1 个答案:

答案 0 :(得分:1)

在GrantResourceOwnerCredentials中,当前用户为空是合乎逻辑的。您需要验证凭据,用户名/密码并在上下文中设置用户。

您似乎想要模仿(子)用户。这就是你能做的。请注意,这是伪代码。阅读评论:

public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
    // assume that context contains username, password and childusername

    var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>();            

    //  First validate the credentials of the parent:
    var appUser = await userManager.FindAsync(context.UserName, context.Password);

    // Check if user is valid AND user is parent of childUserName

    // now find the user to impersonate
    appUser = await userManager.FindByNameAsync(context.ChildUserName);

    // If found, appuser is child user:

    // you may add information so you know that the user was impersonated by a parent user.
    var propertyDictionary = new Dictionary<string, string> { { "userName", appUser.UserName }, { "parent", context.UserName } };
    var properties = new AuthenticationProperties(propertyDictionary);

    var oAuthIdentity = await appUser.GenerateUserIdentityAsync(userManager);
    var ticket = new AuthenticationTicket(oAuthIdentity, properties);

    // Token is validated.
    context.Validated(ticket);

    // parent is now child user.
 }

这只是冒充孩子的想法。您需要添加正常登录的流程:子登录或父级未指定childUserName。

- 更新 -

根据您的评论我已更新答案。

access_token是自包含的。您无法更改或更新它。因此,如果父用户没有再次登录,则无法切换当前子集用户。由于您无法使用当前的access_token获取新的或其他access_token。

因此有两种选择:使用上述流程或向父用户添加声明。这不会设置当前用户,但您可以在网址中添加当前子集用户。

您还可以添加包含subsetUser的其他标头。在这种情况下,您不需要检查网址。

如果您想添加声明,我建议您像模板一样使用ApplicationUser:

public class ApplicationUser : IdentityUser
{
    public List<string> SubsetUsers { get; set; }

    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
    {
        var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);

        // Add custom user claims here
        userIdentity.AddClaim(new Claim("subsetUsers", string.Join(",", SubsetUsers)));

        return userIdentity;
    }
}

或类似的东西。我不知道你如何以及在哪里坚持子集用户。

要获取可用子集用户的列表,假设子集用户来自url:

user = (System.Security.Claims.ClaimsIdentity)User.Identity;
var subset = user.FindFirstValue("subsetUsers").Split(',');
if(subset.Contains(UserNameFromUrl))
    IsValid = true;

您无法使用默认的AuthorizeAttribute对此进行验证,但您可以添加自己的过滤器。