C# 通过UseOpenIdConnectAuthentication登录时,loginInfo始终为空
我尝试将带有OpenID Connect身份验证的标准MVC身份验证示例()扩展到Thinktecture IdentityServer()的实例 我将“openid”范围添加到IdentityServer的范围中。 我使用中的示例代码向userinfo端点添加了额外的调用 身份验证中间件链中的更高层是-根据MVC身份验证示例-C# 通过UseOpenIdConnectAuthentication登录时,loginInfo始终为空,c#,asp.net-mvc,oauth-2.0,openid-connect,identityserver3,C#,Asp.net Mvc,Oauth 2.0,Openid Connect,Identityserver3,我尝试将带有OpenID Connect身份验证的标准MVC身份验证示例()扩展到Thinktecture IdentityServer()的实例 我将“openid”范围添加到IdentityServer的范围中。 我使用中的示例代码向userinfo端点添加了额外的调用 身份验证中间件链中的更高层是-根据MVC身份验证示例-UseCookieAuthentication和UseExternalSignInCookie 当我在OpenIdConnectAuthenticationNotific
UseCookieAuthentication
和UseExternalSignInCookie
当我在OpenIdConnectAuthenticationNotifications.SecurityTokenValidated
中放置断点时,我可以看到所有声明都很好地进入。因此,与IdentityServer的通信是正确的
但是当我到达AccountController.ExternalLoginCallback时,调用
var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
始终返回null
当我使用Google OAuth2登录时,它不是空的
我怀疑
UseOpenIdConnectAuthentication
设置(或不设置)Cookie信息的方式与UseCookieAuthentication
提取Cookie信息的方式不匹配。但是我不知道如何解决这个问题。事实证明,中的示例代码确实用类型覆盖了声明
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier".
如果找不到此声明,则找不到loginInfo
问题代码(Startup.Auth.cs):
解决方案是保留原始声明,如下所示:
var nid = new ClaimsIdentity(
n.AuthenticationTicket.Identity,
n.AuthenticationTicket.Identity.Claims
);
我也遇到了类似的问题,虽然我没有提出为什么有时可以进行身份验证并带回身份声明,但我确实通过下载和调试Microsoft代码,找到了ExternalLoginInfo始终为空的原因 我的问题是OpenIdConnectAuthenticationOptions中提供的响应类型-我将其设置为OpenIdConnectResponseType.Code,这是不正确的。。。将其设置为OpenIdConnectResponseType.CodeIdToken使其工作一致 这是我的Startup.Auth.vb源代码的副本:
Public Sub ConfigureAuth(app As IAppBuilder)
app.CreatePerOwinContext(AddressOf ApplicationDbContext.Create)
app.CreatePerOwinContext(Of ApplicationUserManager)(AddressOf ApplicationUserManager.Create)
app.CreatePerOwinContext(Of ApplicationSignInManager)(AddressOf ApplicationSignInManager.Create)
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType)
app.UseCookieAuthentication(New CookieAuthenticationOptions() With {
.AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
.Provider = New CookieAuthenticationProvider() With {
.OnValidateIdentity = SecurityStampValidator.OnValidateIdentity(Of ApplicationUserManager, ApplicationUser)(
validateInterval:=TimeSpan.FromMinutes(30),
regenerateIdentity:=Function(manager, user) user.GenerateUserIdentityAsync(manager))},
.LoginPath = New PathString("/Account/Login")})
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie)
Dim facebookOptions = New FacebookAuthenticationOptions With {
.AppId = ConfigurationManager.AppSettings("FacebookClientID"),
.AppSecret = ConfigurationManager.AppSettings("FacebookClientSecret"),
.Provider = New FacebookAuthenticationProvider With {
.OnAuthenticated = Function(context)
context.Identity.AddClaim(New Claim("Provider", "Facebook"))
context.Identity.AddClaim(New Claim("provider:name", context.Identity.FindFirstValue(ClaimTypes.Name)))
context.Identity.AddClaim(New Claim("provider:accesstoken", context.AccessToken, ClaimValueTypes.String, "Facebook"))
context.Identity.AddClaim(New Claim("provider:picture", String.Format("//graph.facebook.com/{0}/picture?type=square", context.User.Value(Of String)("id"))))
Dim email = context.Identity.FindFirstValue(ClaimTypes.Email)
If email IsNot Nothing Then
context.Identity.AddClaim(New Claim("provider:email", email))
Else
Dim fb = New Facebook.FacebookClient(context.AccessToken)
Dim myInfo = fb.Get("/me?fields=email")
email = myInfo("email")
If email IsNot Nothing Then
context.Identity.AddClaim(New Claim("provider:email", email))
Else
Throw New ArgumentNullException("myInfo.Email")
End If
End If
Return Task.FromResult(0)
End Function}}
facebookOptions.Scope.Add("email")
app.UseFacebookAuthentication(facebookOptions)
app.UseGoogleAuthentication(New GoogleOAuth2AuthenticationOptions() With {
.ClientId = ConfigurationManager.AppSettings("GoogleClientID"),
.ClientSecret = ConfigurationManager.AppSettings("GoogleClientSecret"),
.Provider = New GoogleOAuth2AuthenticationProvider With {.OnAuthenticated = Function(context)
context.Identity.AddClaim(New Claim("Provider", "Google"))
context.Identity.AddClaim(New Claim("provider:name", context.Identity.FindFirstValue(ClaimTypes.Name)))
context.Identity.AddClaim(New Claim("provider:email", context.Identity.FindFirstValue(ClaimTypes.Email)))
context.Identity.AddClaim(New Claim("provider:accesstoken", context.AccessToken, ClaimValueTypes.String, "Google"))
context.Identity.AddClaim(New Claim("provider:picture", context.User.SelectToken("image")?.Value(Of String)("url")))
Return Task.FromResult(0)
End Function}})
app.UseLinkedInAuthentication(New LinkedInAuthenticationOptions With {
.ClientId = ConfigurationManager.AppSettings("LinkedInClientID"),
.ClientSecret = ConfigurationManager.AppSettings("LinkedInClientSecret"),
.Provider = New LinkedInAuthenticationProvider With {.OnAuthenticated = Function(context)
context.Identity.AddClaim(New Claim("Provider", "LinkedIn"))
context.Identity.AddClaim(New Claim("provider:name", context.Name))
context.Identity.AddClaim(New Claim("provider:email", context.Email))
context.Identity.AddClaim(New Claim("provider:accesstoken", context.AccessToken, ClaimValueTypes.String, "LinkedIn"))
context.Identity.AddClaim(New Claim("provider:picture", context.User.SelectToken("pictureUrl").ToString))
Return Task.FromResult(0)
End Function}})
Dim oktaOptions = New OpenIdConnect.OpenIdConnectAuthenticationOptions With {
.AuthenticationType = "okta",
.SignInAsAuthenticationType = "Cookies",
.Authority = ConfigurationManager.AppSettings("okta:Authority"),
.ResponseType = Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectResponseType.CodeIdToken,
.ClientId = ConfigurationManager.AppSettings("okta:ClientId"),
.ClientSecret = ConfigurationManager.AppSettings("okta:ClientSecret"),
.RedirectUri = ConfigurationManager.AppSettings("okta:RedirectUri"),
.TokenValidationParameters = New Microsoft.IdentityModel.Tokens.TokenValidationParameters With {.ValidateIssuer = True},
.Scope = "openid profile email"
}
app.UseOpenIdConnectAuthentication(oktaOptions)
Dim auth0Options = New OpenIdConnect.OpenIdConnectAuthenticationOptions With {
.AuthenticationType = "auth0",
.SignInAsAuthenticationType = "Cookies",
.Authority = ConfigurationManager.AppSettings("auth0:Authority"),
.ResponseType = Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectResponseType.CodeIdToken,
.ClientId = ConfigurationManager.AppSettings("auth0:ClientId"),
.ClientSecret = ConfigurationManager.AppSettings("auth0:ClientSecret"),
.RedirectUri = ConfigurationManager.AppSettings("auth0:RedirectUri"),
.TokenValidationParameters = New Microsoft.IdentityModel.Tokens.TokenValidationParameters With {.ValidateIssuer = True},
.Scope = "openid profile email"
}
app.UseOpenIdConnectAuthentication(auth0Options)
app.MapSignalR
GlobalHost.DependencyResolver.Register(GetType(IUserIdProvider), Function() New MySignalRIdProvider())
End Sub
在我的例子中,解决方案不是保留原始声明,而是确保重新发行的票据始终包含名称标识符声明。
Public Sub ConfigureAuth(app As IAppBuilder)
app.CreatePerOwinContext(AddressOf ApplicationDbContext.Create)
app.CreatePerOwinContext(Of ApplicationUserManager)(AddressOf ApplicationUserManager.Create)
app.CreatePerOwinContext(Of ApplicationSignInManager)(AddressOf ApplicationSignInManager.Create)
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType)
app.UseCookieAuthentication(New CookieAuthenticationOptions() With {
.AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
.Provider = New CookieAuthenticationProvider() With {
.OnValidateIdentity = SecurityStampValidator.OnValidateIdentity(Of ApplicationUserManager, ApplicationUser)(
validateInterval:=TimeSpan.FromMinutes(30),
regenerateIdentity:=Function(manager, user) user.GenerateUserIdentityAsync(manager))},
.LoginPath = New PathString("/Account/Login")})
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie)
Dim facebookOptions = New FacebookAuthenticationOptions With {
.AppId = ConfigurationManager.AppSettings("FacebookClientID"),
.AppSecret = ConfigurationManager.AppSettings("FacebookClientSecret"),
.Provider = New FacebookAuthenticationProvider With {
.OnAuthenticated = Function(context)
context.Identity.AddClaim(New Claim("Provider", "Facebook"))
context.Identity.AddClaim(New Claim("provider:name", context.Identity.FindFirstValue(ClaimTypes.Name)))
context.Identity.AddClaim(New Claim("provider:accesstoken", context.AccessToken, ClaimValueTypes.String, "Facebook"))
context.Identity.AddClaim(New Claim("provider:picture", String.Format("//graph.facebook.com/{0}/picture?type=square", context.User.Value(Of String)("id"))))
Dim email = context.Identity.FindFirstValue(ClaimTypes.Email)
If email IsNot Nothing Then
context.Identity.AddClaim(New Claim("provider:email", email))
Else
Dim fb = New Facebook.FacebookClient(context.AccessToken)
Dim myInfo = fb.Get("/me?fields=email")
email = myInfo("email")
If email IsNot Nothing Then
context.Identity.AddClaim(New Claim("provider:email", email))
Else
Throw New ArgumentNullException("myInfo.Email")
End If
End If
Return Task.FromResult(0)
End Function}}
facebookOptions.Scope.Add("email")
app.UseFacebookAuthentication(facebookOptions)
app.UseGoogleAuthentication(New GoogleOAuth2AuthenticationOptions() With {
.ClientId = ConfigurationManager.AppSettings("GoogleClientID"),
.ClientSecret = ConfigurationManager.AppSettings("GoogleClientSecret"),
.Provider = New GoogleOAuth2AuthenticationProvider With {.OnAuthenticated = Function(context)
context.Identity.AddClaim(New Claim("Provider", "Google"))
context.Identity.AddClaim(New Claim("provider:name", context.Identity.FindFirstValue(ClaimTypes.Name)))
context.Identity.AddClaim(New Claim("provider:email", context.Identity.FindFirstValue(ClaimTypes.Email)))
context.Identity.AddClaim(New Claim("provider:accesstoken", context.AccessToken, ClaimValueTypes.String, "Google"))
context.Identity.AddClaim(New Claim("provider:picture", context.User.SelectToken("image")?.Value(Of String)("url")))
Return Task.FromResult(0)
End Function}})
app.UseLinkedInAuthentication(New LinkedInAuthenticationOptions With {
.ClientId = ConfigurationManager.AppSettings("LinkedInClientID"),
.ClientSecret = ConfigurationManager.AppSettings("LinkedInClientSecret"),
.Provider = New LinkedInAuthenticationProvider With {.OnAuthenticated = Function(context)
context.Identity.AddClaim(New Claim("Provider", "LinkedIn"))
context.Identity.AddClaim(New Claim("provider:name", context.Name))
context.Identity.AddClaim(New Claim("provider:email", context.Email))
context.Identity.AddClaim(New Claim("provider:accesstoken", context.AccessToken, ClaimValueTypes.String, "LinkedIn"))
context.Identity.AddClaim(New Claim("provider:picture", context.User.SelectToken("pictureUrl").ToString))
Return Task.FromResult(0)
End Function}})
Dim oktaOptions = New OpenIdConnect.OpenIdConnectAuthenticationOptions With {
.AuthenticationType = "okta",
.SignInAsAuthenticationType = "Cookies",
.Authority = ConfigurationManager.AppSettings("okta:Authority"),
.ResponseType = Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectResponseType.CodeIdToken,
.ClientId = ConfigurationManager.AppSettings("okta:ClientId"),
.ClientSecret = ConfigurationManager.AppSettings("okta:ClientSecret"),
.RedirectUri = ConfigurationManager.AppSettings("okta:RedirectUri"),
.TokenValidationParameters = New Microsoft.IdentityModel.Tokens.TokenValidationParameters With {.ValidateIssuer = True},
.Scope = "openid profile email"
}
app.UseOpenIdConnectAuthentication(oktaOptions)
Dim auth0Options = New OpenIdConnect.OpenIdConnectAuthenticationOptions With {
.AuthenticationType = "auth0",
.SignInAsAuthenticationType = "Cookies",
.Authority = ConfigurationManager.AppSettings("auth0:Authority"),
.ResponseType = Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectResponseType.CodeIdToken,
.ClientId = ConfigurationManager.AppSettings("auth0:ClientId"),
.ClientSecret = ConfigurationManager.AppSettings("auth0:ClientSecret"),
.RedirectUri = ConfigurationManager.AppSettings("auth0:RedirectUri"),
.TokenValidationParameters = New Microsoft.IdentityModel.Tokens.TokenValidationParameters With {.ValidateIssuer = True},
.Scope = "openid profile email"
}
app.UseOpenIdConnectAuthentication(auth0Options)
app.MapSignalR
GlobalHost.DependencyResolver.Register(GetType(IUserIdProvider), Function() New MySignalRIdProvider())
End Sub