简体   繁体   English

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

[英]ASP.NET OWIN OpenID Connect not creating user authentication

I have an ASP.NET 4.6 web app that I'm trying to add OpenId Connect using OWIN.我有一个 ASP.NET 4.6 web 应用程序,我正在尝试使用 OWIN 添加 OpenId Connect。

I added my Owin startup class and everything appears to be configured correctly, but the problem I'm having is the ASP Identity/Authenticated user never gets created.我添加了我的 Owin 启动 class 并且一切似乎都配置正确,但我遇到的问题是 ASP 身份/身份验证用户永远不会被创建。 I end up with an endless loop, where the OpenId callback page redirects back to the original page, which then redirects to the login page, etc.我最终陷入了一个无限循环,其中 OpenId 回调页面重定向回原始页面,然后重定向到登录页面等。

Here is my startup class:这是我的启动 class:

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"
            },

            Notifications = new OpenIdConnectAuthenticationNotifications
            {
                AuthorizationCodeReceived = async n =>
                {
                    // Exchange code for access and ID tokens
                    var tokenClient = new TokenClient($"{_authority}/as/token.oauth2", _clientId, _clientSecret);

                    var tokenResponse = await tokenClient.RequestAuthorizationCodeAsync(n.Code, _redirectUri);
                    if (tokenResponse.IsError)
                    {
                        throw new Exception(tokenResponse.Error);
                    }

                    var userInfoClient = new UserInfoClient($"{_authority}/idp/userinfo.openid");
                    var userInfoResponse = await userInfoClient.GetAsync(tokenResponse.AccessToken);

                    var claims = new List<Claim>(userInfoResponse.Claims)
                      {
                        new Claim("id_token", tokenResponse.IdentityToken),
                        new Claim("access_token", tokenResponse.AccessToken)
                      };

                    n.AuthenticationTicket.Identity.AddClaims(claims);



                    //// create the identity
                    //var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationType);

                    //System.Web.HttpContext.Current.GetOwinContext().Authentication.SignIn(new AuthenticationProperties
                    //{
                    //    IsPersistent = true
                    //}, identity);
                }
            }
        });
    }

Here is the Login.aspx page:这是 Login.aspx 页面:

 protected void Page_Load(object sender, EventArgs e)
    {

        if (!Request.IsAuthenticated)
        {
            HttpContext.Current.GetOwinContext().Authentication.Challenge(
              new AuthenticationProperties { RedirectUri = Request["ReturnUrl"] ?? "Default.aspx" },
              OpenIdConnectAuthenticationDefaults.AuthenticationType);
        }        
    }

The page flow goes like this:页面流程是这样的:

1) Request: http://localhost:60624/Page.aspx Response: 302 - redirect to Login.aspx 1) 请求: http://localhost:60624/Page.aspx响应:302 - 重定向到 Login.aspx

2) Request: http://localhost:60624/Login.aspx?ReturnUrl=%2FPage.aspx Response 302 - redirect to https://auth.myprovider.com 2) 请求: http://localhost:60624/Login.aspx?ReturnUrl=%2FPage.aspx响应 302 - 重定向到https://auth.myprovider.Z2ECD5036D9A2DDA40B

Some cookies set here on the response headers:一些 cookies 在响应标头上设置:

Set-Cookie: OpenIdConnect.nonce.KIsuj4RUmGKJIynLrkEScxBvGrZzkMo6ylZ%2F4lRknPM%3D=xxxxxxxxx;设置 Cookie:OpenIdConnect.nonce.KIsuj4RUmGKJIynLrkEScxBvGrZzkMo6ylZ%2F4lRknPM%3D=xxxxxxxxx; path=/;路径=/; expires=Mon, 22-Apr-2019 14:12:00 GMT;过期=格林威治标准时间 2019 年 4 月 22 日星期一 14:12:00; HttpOnly Set-Cookie: OpenIdConnect.nonce.KIsuj4RUmGKJIynLrkEScxBvGrZzkMo6ylZ%2F4lRknPM%3D=yyyyyyyyy; HttpOnly 设置 Cookie:OpenIdConnect.nonce.KIsuj4RUmGKJIynLrkEScxBvGrZzkMo6ylZ%2F4lRknPM%3D=yyyyyyyyy; expires=Mon, 22-Apr-2019 14:12:00 GMT;过期=格林威治标准时间 2019 年 4 月 22 日星期一 14:12:00; path=/;路径=/; HttpOnly HttpOnly

3) Auth provider, sign-in, and it 302 redirects to /LoginCallback 3) Auth 提供者,登录,它 302 重定向到 /LoginCallback

4) Request: http://localhost:60624/LoginCallback Response 302 - redirect to /Page.aspx 4) 请求: http://localhost:60624/LoginCallback响应 302 - 重定向到 /Page.aspx

Cookies that were set in step 2 are cleared here.在步骤 2 中设置的 Cookies 在此处被清除。

Set-Cookie: OpenIdConnect.nonce.KIsuj4RUmGKJIynLrkEScxBvGrZzkMo6ylZ%2F4lRknPM%3D=;设置 Cookie:OpenIdConnect.nonce.KIsuj4RUmGKJIynLrkEScxBvGrZzkMo6ylZ%2F4lRknPM%3D=; path=/;路径=/; expires=Thu, 01-Jan-1970 00:00:00 GMT Set-Cookie: OpenIdConnect.nonce.KIsuj4RUmGKJIynLrkEScxBvGrZzkMo6ylZ%2F4lRknPM%3D=; expires=Thu, 01-Jan-1970 00:00:00 GMT Set-Cookie: OpenIdConnect.nonce.KIsuj4RUmGKJIynLrkEScxBvGrZzkMo6ylZ%2F4lRknPM%3D=; expires=Thu, 01-Jan-1970 00:00:00 GMT;过期=周四,1970 年 1 月 1 日 00:00:00 GMT; path=/路径=/

5) Back to Page.aspx, user not authenticated; 5)返回Page.aspx,用户未通过身份验证; Goto step 1转到第 1 步

I've done some debugging, and the AuthorizationCodeReceived fires on the Startup, and the backend successfully calls the User Info endpoint.我已经进行了一些调试,并且 AuthorizationCodeReceived 在 Startup 上触发,并且后端成功调用了 User Info 端点。 I've tried to call System.Web.HttpContext.Current.GetOwinContext().Authentication.SignIn() from that Notification, but that doesn't seem to do anything.我试图从该通知中调用 System.Web.HttpContext.Current.GetOwinContext().Authentication.SignIn() ,但这似乎没有任何作用。

At this point, I'm stuck.在这一点上,我被困住了。 Why is the authentication cookie for the user identity not being set?为什么未设置用户身份的身份验证 cookie? It seems like this is supposed to happen automatically.似乎这应该自动发生。 Am I supposed to manually create this myself?我应该自己手动创建吗? ( How can I manually create a authentication cookie instead of the default method? ) 如何手动创建身份验证 cookie 而不是默认方法?

EDIT: After reviewing @ Zaxxon 's reply, I was able to get it working.编辑:在查看 @ Zaxxon的回复后,我能够让它工作。 There were 2 things wrong in the AuthorizationCodeReceived notification AuthorizationCodeReceived 通知中有两处错误

  1. I needed to create the ClaimsIdentity.我需要创建 ClaimsIdentity。 In my original code I submitted above, I had commented out this, but it was also incorrect.在我上面提交的原始代码中,我已经注释掉了这一点,但这也是不正确的。
  2. I had to replace the AuthenticationTicket with a new one with the new identity I just created.我不得不用我刚刚创建的新身份替换 AuthenticationTicket。 Then add the claims to this new Identity.然后将声明添加到这个新身份。

Here is the working code:这是工作代码:

ClaimsIdentity identity = new ClaimsIdentity(DefaultAuthenticationTypes.ApplicationCookie, ClaimTypes.GivenName, ClaimTypes.Role);
 n.AuthenticationTicket = new AuthenticationTicket(identity, n.AuthenticationTicket.Properties);
 n.AuthenticationTicket.Identity.AddClaims(claims);

I have an ASP.NET 4.6 web app that I'm trying to add OpenId Connect using OWIN.我有一个ASP.NET 4.6 Web应用程序,我正在尝试使用OWIN添加OpenId Connect。

I added my Owin startup class and everything appears to be configured correctly, but the problem I'm having is the ASP Identity/Authenticated user never gets created.我添加了Owin启动类,并且所有东西似乎都配置正确,但是我遇到的问题是从未创建过ASP Identity / Authenticated用户。 I end up with an endless loop, where the OpenId callback page redirects back to the original page, which then redirects to the login page, etc.我最终遇到了一个无限循环,在该循环中,OpenId回调页面重定向回原始页面,然后重定向到原始页面,依此类推。

Here is my startup class:这是我的入门班:

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"
            },

            Notifications = new OpenIdConnectAuthenticationNotifications
            {
                AuthorizationCodeReceived = async n =>
                {
                    // Exchange code for access and ID tokens
                    var tokenClient = new TokenClient($"{_authority}/as/token.oauth2", _clientId, _clientSecret);

                    var tokenResponse = await tokenClient.RequestAuthorizationCodeAsync(n.Code, _redirectUri);
                    if (tokenResponse.IsError)
                    {
                        throw new Exception(tokenResponse.Error);
                    }

                    var userInfoClient = new UserInfoClient($"{_authority}/idp/userinfo.openid");
                    var userInfoResponse = await userInfoClient.GetAsync(tokenResponse.AccessToken);

                    var claims = new List<Claim>(userInfoResponse.Claims)
                      {
                        new Claim("id_token", tokenResponse.IdentityToken),
                        new Claim("access_token", tokenResponse.AccessToken)
                      };

                    n.AuthenticationTicket.Identity.AddClaims(claims);



                    //// create the identity
                    //var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationType);

                    //System.Web.HttpContext.Current.GetOwinContext().Authentication.SignIn(new AuthenticationProperties
                    //{
                    //    IsPersistent = true
                    //}, identity);
                }
            }
        });
    }

Here is the Login.aspx page:这是Login.aspx页面:

 protected void Page_Load(object sender, EventArgs e)
    {

        if (!Request.IsAuthenticated)
        {
            HttpContext.Current.GetOwinContext().Authentication.Challenge(
              new AuthenticationProperties { RedirectUri = Request["ReturnUrl"] ?? "Default.aspx" },
              OpenIdConnectAuthenticationDefaults.AuthenticationType);
        }        
    }

The page flow goes like this:页面流如下所示:

1) Request: http://localhost:60624/Page.aspx Response: 302 - redirect to Login.aspx 1)请求: http:// localhost:60624 / Page.aspx响应:302-重定向到Login.aspx

2) Request: http://localhost:60624/Login.aspx?ReturnUrl=%2FPage.aspx Response 302 - redirect to https://auth.myprovider.com 2)请求: http:// localhost:60624 / Login.aspx?ReturnUrl =%2FPage.aspx响应302-重定向到https://auth.myprovider.com

Some cookies set here on the response headers:此处在响应标头上设置了一些cookie:

Set-Cookie: OpenIdConnect.nonce.KIsuj4RUmGKJIynLrkEScxBvGrZzkMo6ylZ%2F4lRknPM%3D=xxxxxxxxx;设置Cookie:OpenIdConnect.nonce.KIsuj4RUmGKJIynLrkEScxBvGrZzkMo6ylZ%2F4lRknPM%3D = xxxxxxxxx; path=/;路径= /; expires=Mon, 22-Apr-2019 14:12:00 GMT; expires =星期一,2019年4月22日14:12:00 GMT; HttpOnly Set-Cookie: OpenIdConnect.nonce.KIsuj4RUmGKJIynLrkEScxBvGrZzkMo6ylZ%2F4lRknPM%3D=yyyyyyyyy; HttpOnly Set-Cookie:OpenIdConnect.nonce.KIsuj4RUmGKJIynLrkEScxBvGrZzkMo6ylZ%2F4lRknPM%3D = yyyyyyyyy; expires=Mon, 22-Apr-2019 14:12:00 GMT; expires =星期一,2019年4月22日14:12:00 GMT; path=/;路径= /; HttpOnly HttpOnly

3) Auth provider, sign-in, and it 302 redirects to /LoginCallback 3)身份验证提供程序,登录,并将其重定向到/ LoginCallback 302

4) Request: http://localhost:60624/LoginCallback Response 302 - redirect to /Page.aspx 4)请求: http:// localhost:60624 / LoginCallback响应302-重定向到/Page.aspx

Cookies that were set in step 2 are cleared here.在此清除在步骤2中设置的Cookie。

Set-Cookie: OpenIdConnect.nonce.KIsuj4RUmGKJIynLrkEScxBvGrZzkMo6ylZ%2F4lRknPM%3D=;设置Cookie:OpenIdConnect.nonce.KIsuj4RUmGKJIynLrkEScxBvGrZzkMo6ylZ%2F4lRknPM%3D =; path=/;路径= /; expires=Thu, 01-Jan-1970 00:00:00 GMT Set-Cookie: OpenIdConnect.nonce.KIsuj4RUmGKJIynLrkEScxBvGrZzkMo6ylZ%2F4lRknPM%3D=; expires =星期四,1970年1月1日00:00:00 GMT Set-Cookie:OpenIdConnect.nonce.KIsuj4RUmGKJIynLrkEScxBvGrZzkMo6ylZ%2F4lRknPM%3D =; expires=Thu, 01-Jan-1970 00:00:00 GMT; expires =星期四,格林尼治标准时间1970年1月1日00:00:00; path=/路径= /

5) Back to Page.aspx, user not authenticated; 5)返回Page.aspx,用户未通过身份验证; Goto step 1转到步骤1

I've done some debugging, and the AuthorizationCodeReceived fires on the Startup, and the backend successfully calls the User Info endpoint.我已经进行了一些调试,并且在启动时触发了AuthorizationCodeReceived,并且后端成功调用了User Info端点。 I've tried to call System.Web.HttpContext.Current.GetOwinContext().Authentication.SignIn() from that Notification, but that doesn't seem to do anything.我试图从该Notification中调用System.Web.HttpContext.Current.GetOwinContext()。Authentication.SignIn(),但这似乎无济于事。

At this point, I'm stuck.在这一点上,我被困住了。 Why is the authentication cookie for the user identity not being set?为什么未设置用于用户身份的身份验证cookie? It seems like this is supposed to happen automatically.看来这应该是自动发生的。 Am I supposed to manually create this myself?我应该自己手动创建这个吗? ( How can I manually create a authentication cookie instead of the default method? ) 如何手动创建身份验证cookie而不是默认方法?

EDIT: After reviewing @ Zaxxon 's reply, I was able to get it working.编辑:在审查@ Zaxxon的答复后,我能够使其工作。 There were 2 things wrong in the AuthorizationCodeReceived notification AuthorizationCodeReceived通知中有两处错误

  1. I needed to create the ClaimsIdentity.我需要创建ClaimsIdentity。 In my original code I submitted above, I had commented out this, but it was also incorrect.在上面提交的原始代码中,我已经对此进行了注释,但这也是不正确的。
  2. I had to replace the AuthenticationTicket with a new one with the new identity I just created.我必须用刚刚创建的新身份用新的AuthenticationTicket替换。 Then add the claims to this new Identity.然后将声明添加到此新标识中。

Here is the working code:这是工作代码:

ClaimsIdentity identity = new ClaimsIdentity(DefaultAuthenticationTypes.ApplicationCookie, ClaimTypes.GivenName, ClaimTypes.Role);
 n.AuthenticationTicket = new AuthenticationTicket(identity, n.AuthenticationTicket.Properties);
 n.AuthenticationTicket.Identity.AddClaims(claims);

I've got the same issue which you mentioned about Cookies. 我遇到了您提到的关于Cookie的相同问题。 Even I've tried your code it doesn't work (it continuously looping with login uri). 即使我已经尝试过您的代码也不起作用(它与登录uri不断循环)。 Actual problem is I am not getting Access token and id token, AuthorizationCodeReceived handle the authorization code flow and userinfoclient. 实际问题是我没有获取访问令牌和ID令牌,AuthorizationCodeReceived处理授权码流和userinfoclient。

When we pass the Authorization code flow parameters (clientid, ClientSecret, code, redirecturi) it returns the access token and id token , request is going but I didn't get any response. 当我们传递授权代码流参数(clientid,ClientSecret,代码,redirecturi)时,它返回访问令牌和id令牌,请求正在进行,但我没有得到任何响应。

Thanks in advance!. 提前致谢!。

In my case, I didn't need to add anything to the Notifications in the Startup file at all.就我而言,我根本不需要在启动文件中的Notifications中添加任何内容。 I was missing this:我错过了这个:

app.UseCookieAuthentication(new CookieAuthenticationOptions() 
{
    CookieManager = new SystemWebCookieManager()
});

There's some bug in Katana that prevents cookies from getting saved properly, and so adding this one line of code fixed my problem after three days of looking! Katana 中有一些错误会阻止 cookies 正确保存,因此添加这行代码在三天后解决了我的问题!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM