ASP.NET OWIN OpenID Connect 不创建用户身份验证

我有一个 ASP.NET 4.6 Web 应用程序,我正在尝试使用 OWIN 添加 OpenId Connect。


我添加了我的 Owin 启动类,一切似乎都配置正确,但我遇到的问题是从未创建 ASP Identity/Authenticated 用户。我最终陷入无限循环,OpenId 回调页面重定向回原始页面,然后再重定向到登录页面,等等。


这是我的启动类:


public void Configuration(IAppBuilder app)

    {



     app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);



        app.UseKentorOwinCookieSaver();

        app.UseCookieAuthentication(new CookieAuthenticationOptions

        {

            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,

            LoginPath = new PathString("/Login.aspx"),

            ExpireTimeSpan = TimeSpan.FromDays(7)

        });


        app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions

        {                

            ClientId = _clientId,

            ClientSecret = _clientSecret,

            Authority = _authority,

            RedirectUri = _redirectUri, // LoginCallback

            PostLogoutRedirectUri = "http://localhost:60624/Logout.aspx",


            ResponseType = OpenIdConnectResponseType.CodeIdToken,

            Scope = "openid profile email",


            TokenValidationParameters = new TokenValidationParameters

            {

                NameClaimType = "name"

            },

        });

    }



MYYA
浏览 95回答 3
3回答

千万里不及你

是的,我不得不在 VB.Net 中为此工作获得概念证明,这有点痛苦。这是我的测试代码(即不是生产代码),它基于我看到的其他一些 C# 互联网示例:Imports System.Security.ClaimsImports System.Threading.TasksImports IdentityModelImports IdentityModel.ClientImports Microsoft.AspNet.IdentityImports Microsoft.AspNet.Identity.OwinImports Microsoft.IdentityModel.Protocols.OpenIdConnectImports Microsoft.OwinImports Microsoft.Owin.SecurityImports Microsoft.Owin.Security.CookiesImports Microsoft.Owin.Security.NotificationsImports Microsoft.Owin.Security.OAuthImports Microsoft.Owin.Security.OpenIdConnectImports OwinPartial Public Class Startup    Private Shared _oAuthOptions As OAuthAuthorizationServerOptions    Private Shared _publicClientId As String    Private Shared _clientId As String    Private Shared _clientSecret As String    ' Enable the application to use OAuthAuthorization. You can then secure your Web APIs    Shared Sub New()        _clientId = System.Configuration.ConfigurationManager.AppSettings("OAuth:ClientID").ToString()        _clientSecret = System.Configuration.ConfigurationManager.AppSettings("OAuth:SecretKey").ToString()        PublicClientId = _clientId        OAuthOptions = New OAuthAuthorizationServerOptions() With {            .TokenEndpointPath = New PathString("/Token"), 'New PathString("https://authtesteria.domain.com/as/token.oauth2"), '             .AuthorizeEndpointPath = New PathString("/Account/Authorize"), 'New PathString("https://authtesteria.domain.com/as/authorization.oauth2"), '            .Provider = New ApplicationOAuthProvider(PublicClientId),            .AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),            .AllowInsecureHttp = True        }    End Sub    Public Shared Property OAuthOptions() As OAuthAuthorizationServerOptions        Get            Return _oAuthOptions        End Get        Private Set            _oAuthOptions = Value        End Set    End Property    Public Shared Property PublicClientId() As String        Get            Return _publicClientId        End Get        Private Set            _publicClientId = Value        End Set    End Property    ' For more information on configuring authentication, please visit https://go.microsoft.com/fwlink/?LinkId=301864    Public Sub ConfigureAuth(app As IAppBuilder)        ' Configure the db context, user manager and signin manager to use a single instance per request        app.CreatePerOwinContext(AddressOf ApplicationDbContext.Create)        app.CreatePerOwinContext(Of ApplicationUserManager)(AddressOf ApplicationUserManager.Create)        app.CreatePerOwinContext(Of ApplicationSignInManager)(AddressOf ApplicationSignInManager.Create)        ' Enable the application to use a cookie to store information for the signed in user        ' and to use a cookie to temporarily store inforation about a user logging in with a third party login provider        ' Configure the sign in cookie        ' OnValidateIdentity enables the application to validate the security stamp when the user logs in.        ' This is a security feature which is used when you change a password or add an external login to your account.        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)        ' Enables the application to temporarily store user information when they are verifying the second factor in the two-factor authentication process.        app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5))        ' Enables the application to remember the second login verification factor such as phone or email.        ' Once you check this option, your second step of verification during the login process will be remembered on the device where you logged in from.        ' This is similar to the RememberMe option when you log in.        app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie)        ' Enable the application to use bearer tokens to authenticate users        app.UseOAuthBearerTokens(OAuthOptions)        Dim controller As New AccountController()        'Dim validator As OpenIdConnectProtocolValidator = New OpenIdConnectProtocolValidator()        'validator.ShowPII = False        Dim oidcAuth As New Microsoft.Owin.Security.OpenIdConnect.OpenIdConnectAuthenticationOptions() With {            .ClientId = _clientId,            .ClientSecret = _clientSecret,            .Authority = "https://authtesteria.domain.com",            .Notifications = New Microsoft.Owin.Security.OpenIdConnect.OpenIdConnectAuthenticationNotifications() With {                .RedirectToIdentityProvider = AddressOf OnRedirectToIdentityProvider,                .MessageReceived = AddressOf OnMessageReceived,                .SecurityTokenReceived = AddressOf OnSecurityTokenReceived,                .SecurityTokenValidated = AddressOf OnSecurityTokenValidated,                .AuthorizationCodeReceived = AddressOf OnAuthorizationCodeReceived,                .AuthenticationFailed = AddressOf OnAuthenticationFailed        }}        app.UseOpenIdConnectAuthentication(oidcAuth)    End Sub    Private Function OnRedirectToIdentityProvider(arg As RedirectToIdentityProviderNotification(Of Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectMessage, OpenIdConnectAuthenticationOptions)) As Task        Debug.WriteLine("*** RedirectToIdentityProvider")        If arg.ProtocolMessage.RequestType = Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectRequestType.Logout Then            Dim idTokenHint = arg.OwinContext.Authentication.User.FindFirst("id_token")            If idTokenHint IsNot Nothing Then                arg.ProtocolMessage.IdTokenHint = idTokenHint.Value            End If        End If        Return Task.FromResult(0)    End Function    Private Function OnMessageReceived(arg As MessageReceivedNotification(Of Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectMessage, OpenIdConnectAuthenticationOptions)) As Task        Debug.WriteLine("*** MessageReceived")        Return Task.FromResult(0)    End Function    Private Function OnAuthorizationCodeReceived(arg As AuthorizationCodeReceivedNotification) As Task        Debug.WriteLine("*** AuthorizationCodeReceived")        'Upon successful sign in, get & cache a token if you want here        Return Task.FromResult(0)    End Function    Private Function OnAuthenticationFailed(arg As AuthenticationFailedNotification(Of Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectMessage, OpenIdConnectAuthenticationOptions)) As Task        Debug.WriteLine("*** AuthenticationFailed")        Return Task.FromResult(0)    End Function    Private Function OnSecurityTokenReceived(arg As SecurityTokenReceivedNotification(Of Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectMessage, OpenIdConnectAuthenticationOptions)) As Task        Debug.WriteLine("*** SecurityTokenReceived")        Return Task.FromResult(0)    End Function    Private Async Function OnSecurityTokenValidated(arg As SecurityTokenValidatedNotification(Of Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectMessage, OpenIdConnectAuthenticationOptions)) As Task        Debug.WriteLine("*** SecurityTokenValidated")        'Verify the user signing in should have access or not.  Here I just pass folk thru.        Dim nid = New ClaimsIdentity(              DefaultAuthenticationTypes.ApplicationCookie, 'arg.AuthenticationTicket.Identity.AuthenticationType,              ClaimTypes.GivenName,              ClaimTypes.Role)        Dim tokenClient = New TokenClient("https://authtesteria.domain.com/as/token.oauth2",             _clientId,             _clientSecret)        Dim tokenResponse = Await tokenClient.RequestAuthorizationCodeAsync(arg.ProtocolMessage.Code, arg.ProtocolMessage.RedirectUri)        ' get userinfo data        Dim userInfoClient = New IdentityModel.Client.UserInfoClient("https://authtesteria.domain.com/idp/userinfo.openid")        Dim userInfo = Await userInfoClient.GetAsync(tokenResponse.AccessToken)        userInfo.Claims.ToList().ForEach(Sub(ui) nid.AddClaim(New Claim(ui.Type, ui.Value)))        '' keep the id_token for logout        'nid.AddClaim(New Claim("id_token", arg.ProtocolMessage.IdToken))        '' add access token for sample API        'nid.AddClaim(New Claim("access_token", arg.ProtocolMessage.AccessToken))        '' keep track of access token expiration        'nid.AddClaim(New Claim("expires_at", DateTimeOffset.Now.AddSeconds(Integer.Parse(arg.ProtocolMessage.ExpiresIn)).ToString()))        '' add some other app specific claim        'nid.AddClaim(New Claim("app_specific", "some data"))        nid.AddClaim(New Claim(ClaimTypes.Role, "group1"))        arg.AuthenticationTicket = New AuthenticationTicket(nid, arg.AuthenticationTicket.Properties)        arg.AuthenticationTicket.Properties.RedirectUri = HttpContext.Current.Session("PageRedirect").ToString()     End FunctionEnd Class现在我像这样触发登录:Private Sub SomePageName_Load(sender As Object, e As EventArgs) Handles Me.Load    If Not IsPostBack Then        If User.Identity.IsAuthenticated Then            Console.WriteLine(User.Identity.GetUserName())        Else            Session("PageRedirect") = Request.Url            Response.Redirect("/")        End If    End IfEnd Sub我们有几点不同:我使用 OnSecurityTokenValidated 但我不确定这是否重要我用当前页面的 Request.Url 填充会话变量,然后在启动时在 OnSecurityTokenValidated 的通知参数中使用它:arg.AuthenticationTicket.Properties.RedirectUri = …(参见我的代码)。希望这会有所帮助。享受!

jeck猫

我设置了 RedeemCode=True 和 SaveTokens=True 并将其放入通知中,我终于能够让它工作了。所有的例子都没有包括这个,我不确定为什么,但也许它是代码流所必需的。您不必重新添加声明,否则会重复声明。如果您希望自动填充 User.Identity.Name,也不要忘记设置 TokenValidationParameters NameClaimType="name"。SecurityTokenValidated = (context) =>            {                var ctx = context.OwinContext;                                var applicationCookieIdentity = new ClaimsIdentity(context.AuthenticationTicket.Identity, null, DefaultAuthenticationTypes.ApplicationCookie, null, null);                ctx.Authentication.SignIn(applicationCookieIdentity);                return Task.FromResult(0);            },

LEATH

就我而言,我根本不需要向Notifications启动文件中添加任何内容。我错过了这个:app.UseCookieAuthentication(new CookieAuthenticationOptions() {    CookieManager = new SystemWebCookieManager()});Katana 中有一些错误会阻止 cookie 被正确保存,因此添加这一行代码后,经过三天的查找解决了我的问题!
打开App,查看更多内容
随时随地看视频慕课网APP