在我当前的应用程序中,我使用Owin + Aspnet Identity以及Microsoft Live OAuth提供程序来处理身份验证。
到目前为止,一切正常,除了我尝试检索远程令牌,以便将其存储在我的数据库中。
我在网上发现了一些文档,说在web.config中启用“saveBootstrapContext”,所以我做了:
<system.identityModel>
<identityConfiguration saveBootstrapContext="true">
<securityTokenHandlers>
<securityTokenHandlerConfiguration saveBootstrapContext="true"></securityTokenHandlerConfiguration>
</securityTokenHandlers>
</identityConfiguration>
</system.identityModel>
我只在identityConfiguration
上尝试,然后只在securityTokenHandlerConfiguration
上尝试,然后两者一起,但结果始终相同。在以下代码中,externalData.ExternalIdentity.BootstrapContext
始终为null。
SignIn方法在“ExternalLoginCallback”方法中调用,该方法由中间件调用。
using System.IdentityModel.Tokens;
using System.Security.Claims;
using System.Web;
// custom namespaces redacted
using Microsoft.AspNet.Identity;
using Microsoft.Owin.Security;
public class AuthManager : IAuthManager
{
private readonly IUserBusinessLogic userBusinessLogic;
public AuthManager(IUserBusinessLogic userBusinessLogic)
{
this.userBusinessLogic = userBusinessLogic;
}
public void SignIn()
{
IAuthenticationManager manager = HttpContext.Current.GetOwinContext().Authentication;
var externalData = manager.GetExternalLoginInfo();
UserDto user = this.userBusinessLogic.GetUser(externalData.Login.LoginProvider, externalData.Login.ProviderKey);
var token = ((BootstrapContext)externalData.ExternalIdentity.BootstrapContext).Token;
if (user == null)
{
user = this.userBusinessLogic.AddUser(new UserDto(), externalData.Login.LoginProvider, externalData.Login.ProviderKey, token);
}
user.Token = token;
var claims = new Claim[]
{
new Claim(ClaimTypes.NameIdentifier, user.ID.ToString()),
new Claim(ClaimTypes.UserData, UserData.FromUserDto(user).ToString())
};
var identity = new ClaimsIdentity(claims, DefaultAuthenticationTypes.ApplicationCookie);
var properties = new AuthenticationProperties
{
AllowRefresh = true,
IsPersistent = true
};
manager.SignIn(properties, identity);
}
SO上的其他一些帖子说试图重启IIS,重启机器,清空浏览器cookie并重新启动浏览器。我尝试了所有这些但仍然没有。如果我模拟令牌字符串,其他一切都正常工作。
现在我显然遗漏了一些东西,但我在网上找不到任何明确的文件。
非常感谢任何帮助。
感谢。
答案 0 :(得分:1)
有时没有任何帮助是最好的帮助,因为我被迫深入挖掘,最终找到解决方案。
正当前提是我完全混乱,我在混合三种不同的技术而不了解所有含义。
我的示例在web.config中使用了WIF配置,但后来在代码端使用了OWIN的Aspnet Identity(根本不使用web.config)。
一旦我理解了我的想法,我意识到以下几点:
DefaultAuthenticationTypes
静态类,它提供了一些字符串常量。为了简单起见,我保留了它,但我也可以删除它。所以我的重构(和工作)代码看起来像这样。首先,在Startup.cs
app.UseMicrosoftAccountAuthentication(new MicrosoftAccountAuthenticationOptions
{
ClientId = "myClientId",
ClientSecret = "myClientSecret",
Provider = new MicrosoftAccountAuthenticationProvider
{
OnAuthenticated = context =>
{
// here's the token
context.Identity.AddClaim(new System.Security.Claims.Claim("AccessToken", context.AccessToken));
context.Identity.AddClaim(new System.Security.Claims.Claim("FirstName", context.FirstName));
context.Identity.AddClaim(new System.Security.Claims.Claim("LastName", context.LastName));
return Task.FromResult(true);
}
}
});
然后重新审视SignIn
方法:
public void SignIn()
{
IAuthenticationManager manager = HttpContext.Current.GetOwinContext().Authentication;
var externalData = manager.GetExternalLoginInfo();
UserDto user = this.userBusinessLogic.GetUser(externalData.Login.LoginProvider, externalData.Login.ProviderKey);
if (user == null)
{
user = this.userBusinessLogic.AddUser(
new UserDto
{
FirstName = externalData.ExternalIdentity.Claims.Single(c => c.Type == "FirstName").Value,
LastName = externalData.ExternalIdentity.Claims.Single(c => c.Type == "LastName").Value
},
externalData.Login.LoginProvider,
externalData.Login.ProviderKey,
// here's the token claim that I set in the middleware configuration
externalData.ExternalIdentity.Claims.Single(c => c.Type == "AccessToken").Value);
}
var claims = new Claim[]
{
new Claim(ClaimTypes.NameIdentifier, user.ID.ToString()),
new Claim(ClaimTypes.UserData, UserData.FromUserDto(user).ToString()),
new Claim("AccessToken", user.Token),
new Claim("FirstName", user.FirstName),
new Claim("LastName", user.LastName)
};
var identity = new ClaimsIdentity(claims, DefaultAuthenticationTypes.ApplicationCookie);
var properties = new AuthenticationProperties
{
AllowRefresh = true,
IsPersistent = true
};
manager.SignIn(properties, identity);
}
也许这对我来说很困难,但无论如何我在这里发布我的解决方案,希望它可以节省一些令人头疼的事情和一些发誓同事的日子。
快乐编码^^