ExternalIdentity.BootstrapContext 始终为空
ExternalIdentity.BootstrapContext always null
在我当前的应用程序中,我使用 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
始终为空。
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并重新启动浏览器。我尝试了所有这些,但仍然一无所获。如果我模拟令牌字符串,其他一切正常。
现在我显然遗漏了一些东西,但我在网上找不到任何明确的文档。
非常感谢任何帮助。
谢谢。
有时候没有帮助就是最好的帮助,因为我不得不越来越深入地挖掘,最终找到解决方案。
前提是我当时一头雾水,在不理解所有含义的情况下混合了三种不同的技术。
我的示例在 web.config 中使用了 WIF 配置,但随后在代码端使用了 OWIN 之上的 Aspnet Identity(根本不使用 web.config)。
当我理清思路后,我意识到以下几点:
- WIF 完全不需要,因此我摆脱了所有配置(和 WIF 一起)
- 由于我的 MS 身份验证是由处理它的特定 OWIN 中间件执行的,因此我必须了解如何配置它以检索令牌
- Aspnet Identity 仅用于
DefaultAuthenticationTypes
静态 class,它提供了一些字符串常量。为了简单起见,我保留了它,但我也可以删除它。
所以我的重构(和工作)代码看起来像这样。首先,中间件配置需要让 MS 身份验证与令牌一起工作,在 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);
}
也许这对我来说很难,但无论如何我都会在这里发布我的解决方案,希望它可以避免一些头痛和一些开发人员发誓的日子。
编码愉快^^
在我当前的应用程序中,我使用 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
始终为空。
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并重新启动浏览器。我尝试了所有这些,但仍然一无所获。如果我模拟令牌字符串,其他一切正常。
现在我显然遗漏了一些东西,但我在网上找不到任何明确的文档。
非常感谢任何帮助。
谢谢。
有时候没有帮助就是最好的帮助,因为我不得不越来越深入地挖掘,最终找到解决方案。
前提是我当时一头雾水,在不理解所有含义的情况下混合了三种不同的技术。
我的示例在 web.config 中使用了 WIF 配置,但随后在代码端使用了 OWIN 之上的 Aspnet Identity(根本不使用 web.config)。
当我理清思路后,我意识到以下几点:
- WIF 完全不需要,因此我摆脱了所有配置(和 WIF 一起)
- 由于我的 MS 身份验证是由处理它的特定 OWIN 中间件执行的,因此我必须了解如何配置它以检索令牌
- Aspnet Identity 仅用于
DefaultAuthenticationTypes
静态 class,它提供了一些字符串常量。为了简单起见,我保留了它,但我也可以删除它。
所以我的重构(和工作)代码看起来像这样。首先,中间件配置需要让 MS 身份验证与令牌一起工作,在 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);
}
也许这对我来说很难,但无论如何我都会在这里发布我的解决方案,希望它可以避免一些头痛和一些开发人员发誓的日子。
编码愉快^^