2

我尝试扩展标准 MVC Auth 示例(http://www.asp.net/mvc/overview/security/create-an-aspnet-mvc-5-app-with-facebook-and-google-oauth2-and- openid-sign-on)使用 OpenID Connect 身份验证到 Thinktecture IdentityServer 的实例(https://github.com/IdentityServer/IdentityServer3.Samples/tree/master/source/Simplest%20OAuth2%20Walkthrough)。

我将“openid”范围添加到 IdentityServer 的范围中。我使用https://github.com/IdentityServer/IdentityServer3.Samples/blob/master/source/MVC%20Authentication/EmbeddedMvc ​​/Startup.cs 中的示例代码将额外调用添加到 userinfo 端点。

UseCookieAuthentication根据 MVC Auth 示例,身份验证中间件链中较高的部分是UseExternalSignInCookie.

当我在 中放置断点时OpenIdConnectAuthenticationNotifications.SecurityTokenValidated,我可以看到所有声明都很好地进入了。因此与 IdentityServer 的通信是正确的。

但是当我AccountController.ExternalLoginCallback接到电话时

var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();

总是返回 null。

当我使用 Google OAuth2 登录时,它不为空。

我怀疑UseOpenIdConnectAuthentication设置(或不设置)Cookie 信息的方式与UseCookieAuthentication提取方式之间存在不匹配。但我不知道如何解决这个问题。

4

2 回答 2

3

事实证明,https://github.com/IdentityServer/IdentityServer3.Samples/blob/master/source/MVC%20Authentication/EmbeddedMvc ​​/Startup.cs 中的示例代码确实用类型覆盖了声明

"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier". 

如果未找到此声明,则未找到 loginInfo。

问题代码(Startup.Auth.cs):

var nid = new ClaimsIdentity(
    n.AuthenticationTicket.Identity.AuthenticationType,
    Constants.ClaimTypes.GivenName, // "given_name"
    Constants.ClaimTypes.Role // "role"
);

解决方案是保留原始声明,如下所示:

var nid = new ClaimsIdentity(
    n.AuthenticationTicket.Identity, 
    n.AuthenticationTicket.Identity.Claims
);
于 2015-07-23T14:41:01.537 回答
0

我遇到了类似的问题,虽然我没有想出为什么有时可以进行身份​​验证并带回身份声明的原因,但我确实通过下载和调试 Microsoft 代码设法找出了 ExternalLoginInfo 始终为空的原因。

对我来说,问题在于 OpenIdConnectAuthenticationOptions 中提供的ResponseType - 我将其设置为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
于 2018-11-12T16:23:45.213 回答