Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exception invoking back-channel logout and PostLogout url is always null #1180

Open
apetrut opened this issue Mar 25, 2024 · 16 comments
Open

Comments

@apetrut
Copy link

apetrut commented Mar 25, 2024

Which version of Duende IdentityServer are you using?
v6.0.2
Which version of .NET are you using?
6
Describe the bug

image

image

A clear and concise description of what the bug is.

I have an Angular app that is redirecting to the login page for login. Once the login is finished it redirects back to the FE app.
When the user logs out with success from FE, he is redirected to the Duende logout page and the session is cleared. If the user tries to log back again, after login he is redirected to the Duende Identity Server page instead of the FE app landing page.

For the login flow the redirect url appears in the query string, but for the logout flow it's not. PostLogoutRedirectUri is always null.

Here are a few settings I have added:

options.UserInteraction.LoginReturnUrlParameter = "https://subdomain.domain.com";
options.UserInteraction.LogoutUrl = "https://subdomain.domain.com/Account/Logout";
options.UserInteraction.AllowOriginInReturnUrl = true;
options.DynamicProviders.SignOutScheme = IdentityConstants.ApplicationScheme;

Also, I have added a few logs:

2024-03-26T21:14:42.6388019Z [21:14:42 DBG] Attempting to bind parameter 'returnUrl' of type 'System.String' ...
2024-03-26T21:14:42.6399944Z [21:14:42 DBG] Attempting to bind parameter 'returnUrl' of type 'System.String' using the name '' in request data ...
2024-03-26T21:14:42.6407905Z [21:14:42 DBG] Could not find a value in the request with name '' for binding parameter 'returnUrl' of type 'System.String'.
2024-03-26T21:14:42.6420321Z [21:14:42 DBG] Done attempting to bind parameter 'returnUrl' of type 'System.String'.
2024-03-26T21:14:42.6484580Z [21:14:42 DBG] Done attempting to bind parameter 'returnUrl' of type 'System.String'.
2024-03-26T21:14:42.6493013Z [21:14:42 DBG] Attempting to validate the bound parameter 'returnUrl' of type 'System.String' ...
2024-03-26T21:14:42.6503347Z [21:14:42 DBG] Done attempting to validate the bound parameter 'returnUrl' of type 'System.String'.
2024-03-26T21:14:42.6511657Z [21:14:42 VRB] Action Filter: Before executing OnActionExecutionAsync on filter Microsoft.AspNetCore.Mvc.Filters.ControllerActionFilter.
2024-03-26T21:14:42.6578087Z [21:14:42 VRB] Action Filter: Before executing OnActionExecuting on filter Microsoft.AspNetCore.Mvc.ModelBinding.UnsupportedContentTypeFilter.
2024-03-26T21:14:42.6590206Z [21:14:42 VRB] Action Filter: After executing OnActionExecuting on filter Microsoft.AspNetCore.Mvc.ModelBinding.UnsupportedContentTypeFilter.
2024-03-26T21:14:42.6597912Z [21:14:42 VRB] Action Filter: Before executing OnActionExecutionAsync on filter HTC.IdentityServer.STS.Identity.Helpers.SecurityHeadersAttribute.
2024-03-26T21:14:42.6608224Z [21:14:42 INF] Executing action method HTC.IdentityServer.STS.Identity.Controllers.AccountController<HTC.IdentityServer.Admin.EntityFramework.Shared.Entities.Identity.UserIdentity, string>.Login (HTC.IdentityServer.STS.Identity) - Validation state: Valid
2024-03-26T21:14:42.6617106Z [21:14:42 VRB] Executing action method HTC.IdentityServer.STS.Identity.Controllers.AccountController<HTC.IdentityServer.Admin.EntityFramework.Shared.Entities.Identity.UserIdentity, string>.Login (HTC.IdentityServer.STS.Identity) with arguments ([""])
2024-03-26T21:14:42.6681790Z [21:14:42 VRB] returnUrl is not valid
2024-03-26T21:14:42.6693296Z [21:14:42 VRB] No AuthorizationRequest being returned
2024-03-26T21:14:42.6700311Z [21:14:42 VRB] No AuthorizationRequest being returned
2024-03-26T21:14:42.6707500Z [21:14:42 INF] Executed action method HTC.IdentityServer.STS.Identity.Controllers.AccountController<HTC.IdentityServer.Admin.EntityFramework.Shared.Entities.Identity.UserIdentity, string>.Login (HTC.IdentityServer.STS.Identity), returned result Microsoft.AspNetCore.Mvc.ViewResult in 0.1018ms.
  1. How can I setup the flow in order to logout but still keep the redirect url if I try to login again?

  2. Is there a way to increase the timeout for the BackChannelLogoutHttpClient?

Thanks.

@apetrut apetrut changed the title Exception invoking back-channel logout Exception invoking back-channel logout and PostLogout url is always null Mar 27, 2024
@RolandGuijt
Copy link

When a session is ended at the identity provider there is a mechanism in place that notifies other clients (using the same session id) of that fact so that they can end their own session.

There are two flavors of this mechanism called frontchannel logout notifications and backchannel logout notifications. Your first screenshot showing the exception suggests you are using backchannel logout notifications.

However, it looks like you're using a frontend without a backend. Or are you using the BFF pattern? From your post it looks like you're interacting with the identity provider from javascript directly and that here is no server-side part to the front-end.
A backchannel request is basically a request being done to the server-side application so that the browser doesn't know about the request.
Since there is no server-side in your case, backchannel logout notifications can't be used.

Please disable backchannel logout notifications and try if the problem goes away. Chances are that you don't have to do much else, assuming you are using spec compliant libraries like oidc-client. These work by performing monitoring on a special iFrame called check_session_iframe.
Here is some more information about client notifications.

Also, some settings on the IdentityServer side might require some explanation. These could also be part of the problem:

options.UserInteraction.LoginReturnUrlParameter = "https://subdomain.domain.com";

This should be the url query parameter name the returnUrl should be taken from.

options.UserInteraction.LogoutUrl = "https://subdomain.domain.com/Account/Logout";

This normally is a relative URL to the logout page.

@apetrut
Copy link
Author

apetrut commented Mar 27, 2024

Hi @RolandGuijt , I am not using BFF. It's just a simple angular app that uses this OAuth library to login/logout (https://github.com/manfredsteyer/angular-oauth2-oidc). The back-end is skoruba, but behind the scenes it's using the Duende software.

I removed all the back and front channel settings and now I get these logs:

2024-03-27T18:32:59.065798019Z [18:32:59 INF] Request finished HTTP/1.1 GET http://mydomain-sts.azurewebsites.net/Account/Logout?logoutId=CfDJ8JdVAPpK845GrVQw6N-VAdR1nkdG0NCCO2i7UpKd-epjteeUuz5RcW7vgbGAAwGt2fVqJ4QkTDJn1xoo70HUQku6DtSHQFEEE4zeojXh1Xk58RvQXDlkEQxOkfuFPIXcED-8GORm_hPqFQRrMvjdB8rPwgnUTkGgNJ5l0lsk5Cc0vtdM__WSikcdyn3sXeGUSYtbAsC8BBUsSE2Hp7jedfDWx4Yl8P2jWscP15FrZGmKFoNND_LHq-tHLKQQlu5qlilPWpq2Hm64IfcpqmDhBeaWkImqcLKdiwGr4h9MXkN5BWqsvoXOJggIScJzlP3Hvrx_XGNfIy7Tjyt3Q1e6iS4 - 0 - 200 - text/html;+charset=utf-8 444.1191ms 2024-03-27T18:32:59.167651376Z [18:32:59 INF] Request starting HTTP/1.1 GET http://mydomain-sts.azurewebsites.net/connect/endsession/callback?endSessionId=CfDJ8JdVAPpK845GrVQw6N-VAdR08Wd1sTco0vOr5YFq3fRRY-pr67JSp4s4HYmrywI8EBJarWZ_yi-Xl4DGZJ5tr20TpTo-ceMglYD6cGWjrhYo4i6TfD3eUfcKC9vtMpNGnjslaNvRmQIDxJNcN5eJk1XcWoYgfFd3vL_RgATWVXhsBgJhfrOEZ9SPxunY0HW7DO3lzwXAJhgi9VtmTU3DJBwLDmXdghEfNoHEZ3n70f4MspdFqPtBN_B8XbEMadERhXewgf1j1uDlWTPTa1jkEtfA8fHE0slhQMYBVVS674TIEejVaHIE7XQQa3sRmxv-Rg - 0

and also

2024-03-27T18:32:57.882922829Z {"ClientId": null, "ClientName": null, "SubjectId": "7becac79-c29d-4093-897c-e5671dbad0df", "PostLogOutUri": null, "State": null, "Raw": {"post_logout_redirect_uri": "https://sub.domain.com"}, "$type": "EndSessionRequestValidationLog"} 2024-03-27T18:32:57.882936829Z [18:32:57 DBG] Success validating end session request from null

My issue is now similar to this one that was raised here:
#282

I also linked the angular app with the https://demo.duendesoftware.com/ . In this case the redirect_uri is correctly passed in the url after logout and the redirect is done after second login.
Can you indicate what settings are done for this url: demo.duendesoftware.com that we are missing?

Thanks.

@RolandGuijt
Copy link

It seems like the identity token is correctly passed to the logout endpoint and the session is ending after which the session is ended. IdentityServer knows which client ended the session because that's a claim in the token. That's why no redirect_uri is needed.
What you're probably seeing on your identity provider is a logout screen with a link to return to the client. The reason it works on our demo server is probably because there's a small javascript file loaded in the logout page that takes care of that. It is however disabled by default and it is controlled by the AutomaticRedirectAfterSignOut property in LogoutOptions in our quickStart samples.
When you examine LoggedOut.cshtml you can see the boolean being used at the bottom.

@apetrut
Copy link
Author

apetrut commented Mar 29, 2024

I enabled the Automatic redirect flag and now I got these errors in the logs:

`2024-03-29T20:15:03.085209846Z [20:15:03 DBG] Attempting to bind parameter 'returnUrl' of type 'System.String'

2024-03-29T20:15:03.086656042Z [20:15:03 DBG] Attempting to bind parameter 'returnUrl' of type 'System.String' using the name '' in request data

2024-03-29T20:15:03.087348141Z [20:15:03 DBG] Could not find a value in the request with name '' for binding parameter 'returnUrl' of type 'System.String'.

2024-03-29T20:15:03.087365341Z [20:15:03 DBG] Done attempting to bind parameter 'returnUrl' of type 'System.String'.
2024-03-29T20:15:03.087936639Z [20:15:03 DBG] Done attempting to bind parameter 'returnUrl' of type 'System.String'.
2024-03-29T20:15:03.087954039Z [20:15:03 DBG] Attempting to validate the bound parameter 'returnUrl' of type 'System.String'
2024-03-29T20:15:03.088681637Z [20:15:03 DBG] Done attempting to validate the bound parameter 'returnUrl' of type 'System.String'.
2024-03-29T20:15:03.088700837Z [20:15:03 VRB] Action Filter: Before executing OnActionExecutionAsync on filter Microsoft.AspNetCore.Mvc.Filters.ControllerActionFilter.

2024-03-29T20:15:03.094344024Z [20:15:03 VRB] Action Filter: Before executing OnActionExecuting on filter Microsoft.AspNetCore.Mvc.ModelBinding.UnsupportedContentTypeFilter.

2024-03-29T20:15:03.101046508Z [20:15:03 VRB] Action Filter: After executing OnActionExecuting on filter Microsoft.AspNetCore.Mvc.ModelBinding.UnsupportedContentTypeFilter.

2024-03-29T20:15:03.101121608Z [20:15:03 VRB] Action Filter: Before executing OnActionExecutionAsync on filter HTC.IdentityServer.STS.Identity.Helpers.SecurityHeadersAttribute.

2024-03-29T20:15:03.101133408Z [20:15:03 INF] Executing action method 

HTC.IdentityServer.STS.Identity.Controllers.AccountController<HTC.IdentityServer.Admin.EntityFramework.Shared.Entities.Identity.UserIdentity, string>.Login (HTC.IdentityServer.STS.Identity) - Validation state: Valid

2024-03-29T20:15:03.101138908Z [20:15:03 VRB] Executing action method 

HTC.IdentityServer.STS.Identity.Controllers.AccountController<HTC.IdentityServer.Admin.EntityFramework.Shared.Entities.Identity.UserIdentity, string>.Login (HTC.IdentityServer.STS.Identity) with arguments ([""])

2024-03-29T20:15:03.101143708Z [20:15:03 VRB] returnUrl is not valid

2024-03-29T20:15:03.101147908Z [20:15:03 VRB] No AuthorizationRequest being returned

Why would the return url not be valid even if I have setup the PostLogoutRedirectURI?
What would a valid url look like?

@RolandGuijt
Copy link

It looks like the login endpoint on the account controller is accessed right after the redirect to the client occurred. Maybe you're redirecting to a protected page after logout?

@apetrut
Copy link
Author

apetrut commented Apr 2, 2024

I have setup the redirect uri and also the post logout uri to point to the Login endpoint which has the [AllowAnonymous] attribute so I don't expect it to be protected.

However, I don't understand why the PostLogoutRedirectURI is null? I have checked and I have a logoutId in the query string which in turn should build the LogoutViewModel with the correct value.

@AndersAbel
Copy link
Member

To make it easier to follow the flow, could you please use the browser dev tools to record the flow and share a screenshot? I would like to see the redirects step by step. To only show the redirects you can use the "Doc" filter in the dev tools.

@RolandGuijt
Copy link

@apetrut Is this resolved for you? If not please provide us with the flow Anders asked for or can we close?

@apetrut
Copy link
Author

apetrut commented Apr 18, 2024

@AndersAbel I have added a few screenshots starting with the Login page. However I couldn't catch the logout redirects because the AutomaticRedirectAfterSignOut flag was set to TRUE and the pages were refreshed so quickly. I will disable that flag and try again.

The problem still stays as the PostLogout Redirect URL is always empty so I need to manually hardcode it to a specific url.

Login step 1:
login_step_1

Login step 2:
login_step_2_callback

@apetrut
Copy link
Author

apetrut commented Apr 18, 2024

@RolandGuijt @AndersAbel The problem is not yet solved for me. You can find below the logout steps that the app is taking.

logout_part_1

logout_part_2

logout_part_3

Note: The flow appears to be working because I hardcoded the PostLogOut redirect uri field. I can't understand why that variable is empty all the time and needs hardcoded.

@RolandGuijt
Copy link

It's hard for us to see the entire flow with all these fragments. In the header of the Network tab is a checkbox "Preserve log". With this enabled the log will survive between requests. Can you please enable that and post the entire flow?

Also, you were mentioning that you're using the login page as the post logout Url. But the purpose of it is to have a means to go back to the client application so it should be a URL that points to that. Please change that while you go through the flow again.

@RolandGuijt
Copy link

@apetrut Would you like to pursue this further or can we close?

@apetrut
Copy link
Author

apetrut commented May 3, 2024

Hi, @RolandGuijt. I will send the flows today.

@apetrut
Copy link
Author

apetrut commented May 3, 2024

Hi @RolandGuijt the flows can be found below:

image

I have disabled the Automatic redirect flag and also the Post_Logout_Redirect uri appears to be set, but it's really hardcoded because it comes as null from Duende (see the logs below):

image

@RolandGuijt
Copy link

This doesn't seem to have anything to do with back-channel logout which is basically a way to notify the other clients (different from the one that initiated the logout) of the fact that the session has ended.

Are you using your OAuth library to initiate the logout? I'm asking because logout might not be as straightforward as you think. As your flow shows there are multiple endpoints that are involved that used different URLs. I can't say how it is implemented exactly in the OAuth library your using. That is outside the scope for this issue tracker. Maybe it's a good idea to post an issue there as well if needed.

Also: it also seems like you're still using the login page as the PostLogoutRedirect URL. It is not designed for that. Instead, it should point to a URL on the client to redirect to when logout is finished. This could be part of the problem too.

@RolandGuijt
Copy link

@apetrut Has this been resolved for you? If so I'd like to close.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants