我在使用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中获取当前用户。 有没有解决方案?
答案 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对此进行验证,但您可以添加自己的过滤器。