fancyDevelopment / Fancy.ResourceLinker

A set of libraries to easily create API Gateways, Backend for Frontends (BFF) and truly RESTful Web APIs based on ASP.NET Core
Apache License 2.0
18 stars 5 forks source link

Expand browser based calls check #35

Open Pieter-1337 opened 2 weeks ago

Pieter-1337 commented 2 weeks ago

@fancyDevelopment, I ran into an issue today with the gateway. Let's say we have a cookie/session that is timed out, but our user is still on the page in the frontend, he now clicks a button that makes an api call, the UseGatewayAuthentication will now see that the cookie is expired an will try to call the authorize endpoint on the idp. Basically this image .

this results in a cors exception on my end. image

did you encounter this situation yet performing normal login logout from the same origin works as expected so it's only when challenging after an api call from the frontend that this happens I would epect a 401 here perhaps instead of a 302 on the api call we are making?

it seems that we are trying to handle that here however the header you are checking on is not present in my context image image

I think we might need to check for fetch api for instance instead of only the ajax calls we are checking now?

I would propose something like this image

If i do this I get a 401 in the browser instead of the cors error, at that point the SPA can handle this as it sees fit?

Pieter-1337 commented 2 weeks ago

@fancyDevelopment In addition to this it seems that when I let the cookie expire the first time I make a call I don't get the 401, but a 400 with image If I make the api call once more, I do get the 401

@fancyDevelopment handled further in #36

fancyDevelopment commented 2 weeks ago

Hi @Pieter-1337, thanks for your input. What I do normally is that I provide the X-Requested-With: XmlHttpRequest header manually form a javascript client. This way a javascript client receives a 401 instead of a 302 if the cookie timed out. If I receive a 401 in a javascript client then I do typically something linke this:

window.location.href  = './login?redirectUrl=' + encodeURIComponent(window.location.href);

This then triggers the OAuth flow and brings the user back to the url where he was before the cookie times out.

But what Iike is your proposal with the standard fetch headers. In Angular the standard is still XmlHttpRequest. But instead of writing custom interceptors we could opt in the fetch api into the HttpClient and then we don't need to add a custom interceptor. Can you confirm that your proposal works with provideHttpClient(withFetch())?

Pieter-1337 commented 2 weeks ago

@fancyDevelopment it actually seems to work without the provideHttpClient(withFetch()) image here as you can see I am importing the HttpClientModule in the importProvidersFrom and am not specifying the withFetch() method. I stll get these headers if I make a call image

Pieter-1337 commented 2 weeks ago

@fancyDevelopment I did some more research on this:

Apparently these fetch headers aren't related tot he fetch API they are security headers that are present on every xhr/fetch request . Below a timeline of the browsers (and from which version) that support these headers:

Timeline of Fetch Metadata Request Headers Support in Major Browsers Google Chrome:

Version 76: Released on July 30, 2019 Introduced support for Fetch Metadata Request Headers. Mozilla Firefox:

Version 90: Released on July 13, 2021 Added support for Fetch Metadata Request Headers​ (PortSwigger)​​ (The Mozilla Blog)​. Microsoft Edge:

Version 90: Released on April 15, 2021 Added support for Fetch Metadata Request Headers as part of its Chromium-based updates. Safari:

Version 16.4: Released in March 2023 Included support for Fetch Metadata Request Headers. References MDN Web Docs: Fetch Metadata Request Headers​ (MDN Web Docs)​​ (MDN Web Docs)​ Web.dev: Protect your resources from web attacks with Fetch Metadata Mozilla Security Blog: Firefox 90 supports Fetch Metadata Request Headers​ (The Mozilla Blog)​ These sources provide detailed information about the introduction and support timeline of Fetch Metadata Request Headers in various browsers.

So yeah It seems that besides safari most browsers are supporting these headers for over 3 years now, however I still think that your solution should still be implemented and that the custom header should be added on the request to support older browser version of chrome, firefox, edge and also the not so much older versions of safari.

However in a timeperiod of another 3 years it might be dependable enough? What are you thoughts concerning this?

Here some more info concerning these headers: Key Fetch Metadata Request Headers Sec-Fetch-Mode: Indicates the mode of the request (e.g., cors, no-cors, same-origin, navigate). Sec-Fetch-Site: Indicates the relationship between the origin of the request and the origin of the requested resource (e.g., same-origin, same-site, cross-site). Sec-Fetch-Dest: Describes the destination of the fetch request (e.g., document, script, style, image). Sec-Fetch-User: Indicates whether the request was triggered by a user activation (e.g., a click). Purpose and Use These headers help enhance security by allowing servers to apply policies based on the context of the request. This can help protect against cross-site request forgery (CSRF), cross-site script inclusion (XSSI), and other cross-origin attacks.

Browser Support Fetch Metadata Request Headers are supported by all modern browsers, including Chrome, Firefox, Edge, and Safari. These headers are automatically included by the browser in both Fetch API and XMLHttpRequest (XHR) requests.

Documentation and Further Reading For more detailed information, you can refer to the following sources:

MDN Web Docs: Fetch Metadata Request Header Web.dev: Protect your resources from web attacks with Fetch Metadata MDN Web Docs: Sec-Fetch-Site

Pieter-1337 commented 2 weeks ago

also I noticed that when adding the header to the request as such image sometimes .NET seems to set the key to lowerCase (on the request in the network its still set as expected). So I currently added some middleware to check fo the lowercased key and setting it back to the normal casing however performing a check for both the normal and lower cased version might be suitable in the gatewayAuthentication?