Skip to content

Include a return URL in /Authenticate requests#76

Merged
mjrousos merged 30 commits intomainfrom
mikerou/72
Jul 20, 2022
Merged

Include a return URL in /Authenticate requests#76
mjrousos merged 30 commits intomainfrom
mikerou/72

Conversation

@mjrousos
Copy link
Copy Markdown
Member

Some auth scenarios (WS-Fed, OIDC) were having issues with remote app auth because, as part of authentication, they redirected to an external auth provider to log the user in. When the auth provider redirected back to the app, it would re-direct back to the ASP.NET app's /systemweb-adapters/authenticate endpoint (which the ASP.NET Core app calls to in order to authenticate the user) instead of to the actual endpoint in the ASP.NET Core app that the user was originally trying to get to.

This PR fixes that by including the original request URL as a query string parameter when calling the authenticate endpoint (for example: https://localhost:4321/systemweb-adapters/authenticate?original-url=http://localhost:8765/SomeController/SomeAction (except that the original-url value is URL encoded)). Then, when the ASP.NET app handles request to /systemweb-adapters/authenticate, if no API key is provided (this is only present when called from the ASP.NET Core app), it will assume that the request may be a redirect back and if an original-url query string is present (the auth flows I tested all preserved the query string), the ASP.NET app will re-direct the request to that URL instead.

This PR also adds an OIDC sample to demonstrate this scenario working.

Fixes #72

@mjrousos mjrousos requested review from Tratcher and twsouthwick July 6, 2022 22:00
mjrousos added 3 commits July 6, 2022 22:12
# Conflicts:
#	Microsoft.AspNetCore.SystemWebAdapters.sln
#	test/Microsoft.AspNetCore.SystemWebAdapters.Framework.Tests/Microsoft.AspNetCore.SystemWebAdapters.Framework.Tests.csproj
@mjrousos mjrousos requested a review from twsouthwick July 11, 2022 15:11
Copy link
Copy Markdown
Member

@twsouthwick twsouthwick left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. I think we'll want @Tratcher to review as well.

Comment thread samples/RemoteAuth/OIDC/OIDCAuth/Controllers/AccountController.cs Outdated
@dotnet dotnet deleted a comment from twsouthwick Jul 14, 2022
@dotnet dotnet deleted a comment from twsouthwick Jul 14, 2022
@mjrousos mjrousos requested review from Tratcher and twsouthwick July 15, 2022 19:02
Copy link
Copy Markdown
Member

@twsouthwick twsouthwick left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ooh this seems much more straightforward. LGTM!

mjrousos and others added 5 commits July 18, 2022 11:28
…teAppAuthenticationHttpHandler.Framework.cs

Co-authored-by: Chris Ross <[email protected]>
This was removed when we were considering a global return url query
string in all authenticate flows but now that we're not using that
approach, this needs added back.
# Conflicts:
#	src/Microsoft.AspNetCore.SystemWebAdapters/Authentication/RemoteAppAuthenticationModule.Framework.cs
@mjrousos
Copy link
Copy Markdown
Member Author

While testing this, I found that the OWIN property approach worked well for OIDC but broke Identity/cookie auth scenarios. In OIDC scenarios, the .redirect property was used to know which URL to re-direct the user back to after authentication completes. However, in cookie scenarios, the .redirect property is being used to determine which URL to re-direct the user to in order to authenticate!

The end-result is that the OWIN property-based change that fixed the OIDC scenario broke cookie scenarios because the URL the user was ultimately trying to get to was set as .redirect and when the OWIN cookie auth handler tried to authenticate the user, it would send them to that URL to sign in causing an infinite loop.

I spent a while trying to figure out if there was a clean way of determining in our HTTP handler which OWIN auth handler was being used (OIDC, cookie, or something else) so that we could change what we set .redirect to accordingly but I couldn't find a good way to do that.

Consequently, I've reverted back to an early approach where the relative path that the user is trying to reach is included as a query string in the ASP.NET Core's call to /authenticate to determine user identity. The ASP.NET Core app also includes a special header indicating that the request is from the ASP.NET Core app for purposes of authentication. All of the OWIN auth flows I've tested will eventually redirect back to the URL where authentication began (/authenticate in this case) and will preserve the query strings but not the headers. This allows the /authenticate HTTP handler to recognize when it's being called as part of a redirect in the auth process (the special "I'm authenticating" header will be missing). In those situations, it redirects back to the path in the query string (relative to the ASP.NET Core app's host) and the user is returned to the path they expected to be at after authenticating.

I've already chatted offline with @Tratcher about this approach, but given that the code is different from how it was approved previously, I'd appreciate another round of reviews, @Tratcher and @twsouthwick. Thanks!

@mjrousos mjrousos requested review from Tratcher and twsouthwick July 19, 2022 14:27
Copy link
Copy Markdown
Member

@twsouthwick twsouthwick left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems fine. I'm glad it's now a relative path - that seems a lot better.

Comment on lines +92 to +93
var redirect = new Uri(context.Request.Url, originalUrlPath);
context.Response.Headers["Location"] = redirect.ToString();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Location can be relative. That's less likely to break.

Suggested change
var redirect = new Uri(context.Request.Url, originalUrlPath);
context.Response.Headers["Location"] = redirect.ToString();
context.Response.Headers["Location"] = originalUrlPath

There are two validations you might want to do before redirecting:

  • originalUrlPath is not null or empty.
  • originalUrlPath starts with '/'

Otherwise return a 4xx.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated

mjrousos added 2 commits July 20, 2022 17:52
# Conflicts:
#	src/Microsoft.AspNetCore.SystemWebAdapters/Adapters/Authentication/AuthenticationConstants.cs
#	src/Microsoft.AspNetCore.SystemWebAdapters/Authentication/AuthenticationConstants.Shared.cs
#	src/Microsoft.AspNetCore.SystemWebAdapters/Authentication/AuthenticationConstants.cs
@mjrousos mjrousos merged commit 655311f into main Jul 20, 2022
@mjrousos mjrousos deleted the mikerou/72 branch July 20, 2022 23:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

A 407 Proxy Authentication Required when using remote authentication

3 participants