Open BenJKuhn opened 3 years ago
And, of course, this should build on top of WebView2!
Note. The UWP one is based on IE and because of this will not work with many websites, forcing the developer to not be able to use WAB for Oauth with those sites.
This was originally a request on the WebView2 team here: https://github.com/MicrosoftEdge/WebView2Feedback/issues/171
There's probably some interop involved I believe between Edge, the OS, and WebView2?
And, of course, this should build on top of WebView2!
I disagree. I'd rather we use the user's default browser to log in, then use protocol activation to come back to the application, as it follows better practices, and is impossible to spoof, and also has the benefit of supporting any saved credentials the user might have in their browser. I managed to actually make this work, but it was a lot of work, lots of code, manifest changes for protocol activation, dealing with app activation args, finding the right instance, shutting down the app if it was the wrong instance, redirecting to the correct instance, then dealing with resuming the authentication workflow there. It was quite non-trivial, and I really wish this could be wayyyyyyyyyyy easier.
I wish there was just a single call I could make that would do all this for me. Something like
public static Task<Uri> OAuthSignIn(Uri authorizationUri, Uri callbackUri);
and protocol activation, app instance tracking and resuming etc is just magically handled for me. I shouldn't have to configure my app at all, just configure my oauth with the right callback uri, and then pass it in here.
Another reason to not require webview2: There's no guarantee webview2 is actually available to the user.
app instance tracking and resuming etc is just magically handled for me. I shouldn't have to configure my app at all, just configure my oauth with the right callback uri, and then pass it in here
I agree with everything you've got here - it's important to use the same browser as the user is used to because it may have SSO cookies already set up making the auth basically no-op, or the user might have a password manager associated with it (Edge, LastPass, etc.) where they store their cookies.
For reference, there is https://github.com/Microsoft/cpprestsdk/blob/master/Release/src/http/oauth/oauth2.cpp (and its friend https://github.com/Microsoft/cpprestsdk/blob/master/Release/include/cpprest/oauth2.h), which we'd have to review to see if it behaves correctly. VSCode already does this as well, setting itself up a temporary HTTP server to support the redirect, etc.
Clever trick with the temporary http server. Very clever actually. There are some challenges though with available ports, and what ports you get to configure in the oauth redirect configuration
If you need a reference implementation, please feel free to use MSAL's, it is MIT licensed.
WebView2 WebView1 System Browser using http listner
The discussion around embedded vs system browser is long and inconclusive. When it comes to Azure Active Directory, we've concluded that on desktop it's better to use a broker (WAM on Windows) because brokers increase security and SSO. Internally the broker uses an embedded browser.
Many apps use browsers today and generally the embedded browser are preferred because they provide a better user experience. System browsers are cross-plat but the experience is worse. I have not yet seen any conclusive evidence that system browser is better or worse than embedded browser in terms of security. In terms of SSO, embedded browsers fare poorer, because you are likely to have SSO cookies in your system browser already. But once you start using the embedded browser, it should store the cookies as well.
Hope this helps.
Until the WinAppSDK adds this, I've added this ability to WinUIEx v1.4. It's nothing more than a simple one-line call. See https://dotmorten.github.io/WinUIEx/concepts/WebAuthenticator.html
The solution by @dotMorten works well if you are controlling the app, but not so much as a library - and especially as maui which is a framework that libraries will be based on.
The issue is that the auth callback starts a new process - which may be unexpected for the app, and then it also modifies app state unexpectedly (that may override user data or be overridden by user data): https://github.com/dotMorten/WinUIEx/blob/main/src/WinUIEx/WebAuthenticator.cs#L108
The killing of the new process may also be unexpected for the app: https://github.com/dotMorten/WinUIEx/blob/main/src/WinUIEx/WebAuthenticator.cs#L100
Not sure what the best solution is, but having this in a popup that is controlled by wasdk is more contained and does not require any new processes.
This pop out to a browser works on Android/iOS because even though a "new window" happens, it is the same process and can be intercepted in known places. iOS has a special place, and Android can have a special activity designed for handling callbacks.
Windows on the other hand launches a brand new app.
I appreciate that popping out to the browser is a "better" scenario from the user's credential perspective and default browser, but this is not super windows-friendly. The callback triggers a new proc, which is killed and even if there was a way to share data, Windows doesn't have a place to decide where a new app should be launched or not.
it also modifies app state unexpectedly
Note: This only happens if the user didn't already set that state.
Personally I'd like to see something that's a combo of a popup and using the default browser - ie some way a browser knows the request is coming from a specific app and knows to direct you back to that specific app instance and close that tab gain, instead of asking the user to open the app again from the browser - ie overall more akin to what iOS and Android does.
Any movement or guidance on starting new Maui/WebAPI/BlazorServer combined solution? Is a solution soon?
I am following this Microsoft tutorial but says Windows not working yet.
Will there be a way to leverage the ASP. NET CORE API server as the backend server? All of my various clients, including Blazor Server, already go through the API for DB access. If yes, any chance someone could make a tutorial for this solution setup?
Our goal is 100% of business logic and per-method authorization is contained in the API so our customers could build their own clients if they choose as we are a SaaS provider.
@BenJKuhn is there any update to this? I see @mattleibow added maui-7.x and Maui 7.0 went GA - is there any roadmap or expected moment we can use this? Given that the majority of the apps (gut feeling, admittedly) need some form of authentication nowadays, I find it surprising to see that this was not escalated further in Microsoft or made a blocker before going GA... - and this does not only hit MAUI apps but all WindowsAppSDK apps as I understand cc @ujjwalchadha @jonwis @angelazhangmsft
Any update ?
Please?
The fact that this has taken so long to get any traction is incredible.
Authentication for cross platform MAUI apps is dependent on this functionality and people are literally having to beg for updates.
Any updates?
Any updates?
Any update? We're evaluating using MAUI and....well, are kinda blocked on this and surprised at the lack of responses...
A better option is to use WinUIEx as mentioned earlier in this thread
I have actually moved completely away from the Microsoft stack because of this.
Any update ?
A better option is to use WinUIEx as mentioned earlier in this thread
Except it isnt.
As reported when the site calls back to the app: "Windows on the other hand launches a brand new app."
It might be a work around for android / ios but doesnt work for Windows apps.
Maui is supposed to be cross platform and depends on this functionality.
@BenJKuhn sorry to at you but is there any progress or words of wisdom with how we can prioritise?
This is a real put off for many wanting to use Maui for cross platform apps.
I see a lot of people in this thread looking for updates ... and NOBODY getting back with any. What is going on?
I'd like to try the solution with WinUIEx, but I'm using .net 7 and it doesn't seem to be compatible. Is there a solution?
@nterreaux .net 7 is fully supported by WinUIEx
Ok thanks @dotMorten, I'm relatively new to .NET. The WinUIEx package requires at least version 1.3.230502000 of Microsoft.WindowsAppSDK. However, I can't update it. It says that other versions are "blocked by the project". I'll see if I can do something, as I currently have version 1.2.221209.1.
Yes you’ll need to reference 1.3 in any project that uses WinUIEx or depends on a project that uses WinUIEx.
I'm now using WinUIEx for my OAuth 2 authentication. Everything works perfectly except for the fact that the user's default browser page doesn't close automatically. This isn't extremely annoying, but is there a solution for closing the browser after authentication?
@nterreaux since this thread is going more and more off topic let’s try and keep the winuiex questions over in the WinUIEx repo
More because we have zero response from any maintainer, tagged or otherwise, on the gameplan of a core feature of a core platform in this cross-platform framework solution.
Anytime now, MS employees..
@ransagy Agree the lack of response hinders any confidence in the framework and Maui. Sad to say that my team / project have had to abandon in favor of other stacks.
I am also very interested in any status info around this.
Any updates?
It's a basic usage in app, very important, some feedback ? Should be great if dev team focus on fix this.
Heads up: Google's OAuth is going to start blocking embedded webviews for OAuth: https://developers.google.com/identity/protocols/oauth2/policies#browsers I can imagine other providers will start requiring similar things. This makes it even more important to provide an out of the box secure way to sign in with OAuth, since many are currently just falling back to an embedded WebView2.
A better option is to use WinUIEx as mentioned earlier in this thread
Except it isnt.
As reported when the site calls back to the app: "Windows on the other hand launches a brand new app."
It might be a work around for android / ios but doesnt work for Windows apps.
Maui is supposed to be cross platform and depends on this functionality.
@MatthewBacon-Neteo A bit late to the party here. I managed to use a workaround for windows that might help you.
When the second instance of the app is initializing (before the window of the second instance is created), I extract the auth code from my custom uri (e.g. mycustomuri://authorization?authCode=abc), I then use Named Pipes to send this code to the first instance of the app (the one that is waiting for the code) and then kill the second instance.
It is quite a workaround but on Windows it works fine and the second app is not seen by the user. Of course, fixing this issue would make everything easier.
You don't have to use your own named pipes to redirect. There's an actual API for that (RedirectActivationToAsync
). See https://learn.microsoft.com/en-us/windows/apps/windows-app-sdk/applifecycle/applifecycle-instancing#redirection-logic-based-on-activation-kind
Thanks @dotMorten. I don't want to derail the conversation, although I fail to see how I can use that RedirectActivationToAsync in my .net maui app.
I think I found a workaround after many tries:
var redirectUrl = "http://127.0.0.1:{0}/authorize/"; // or "http://localhost:{0}/authorize/"
var tcplistener = new TcpListener(IPAddress.Loopback, 0);
tcplistener.Start();
var port = ((IPEndPoint)tcplistener.LocalEndpoint).Port;
tcplistener.Stop();
redirectUrl = string.Format(redirectUrl, port);
using var httpListener = new HttpListener();
httpListener.Prefixes.Add(redirectUrl);
httpListener.Start();
var oAuth2Url = "your-oauth2-url"; // make sure (if present) redirect_url = redirectUrl
Process.Start(new ProcessStartInfo("cmd", $"/c start \"\" \"{oAuth2Url}\"") { CreateNoWindow = true });
var context = await httpListener.GetContextAsync();
var html = @"<html><head><title>OAuth 2.0 Authentication Token Received</title></head><body> Received verification code. You may now close this window.</body></html>";
var bytes = Encoding.UTF8.GetBytes(html);
context.Response.ContentLength64 = bytes.Length;
context.Response.SendChunked = false;
context.Response.KeepAlive = false;
var output = context.Response.OutputStream;
await output.WriteAsync(bytes);
await output.FlushAsync();
output.Close();
context.Response.Close();
var result = context.Request.QueryString; // contains url result params (eg: code etc)
The only encountered problem is: if you close the browser before user-auth-flow completes,
var context = await httpListener.GetContextAsync();
hangs indefinitely.
Has anybody found a workaround for use in MAUI windows apps? I would appreciate if you can share any insight on this! Really frustrating!
@FedericoSMEC can you post your code for a workaround, please?
Any update?
Has anybody found a workaround for use in MAUI windows app
@elijahmontenegro Yes: https://dotmorten.github.io/WinUIEx/concepts/Maui.html#use-winuiexs-webauthenticator-instead-of-net-mauis
ue is that the auth callback starts a new process - which may be unexpected for the app, and then it also modifies app state unexpectedly (that may override user data or be overridden by user data):
Hi @dotMorten , I tried to reference WinUIEx.WebAuthenticator in the App.xaml.cs but I don't see CheckOAuthRedirectionActivation() method on there. I am using the 1.5 version of WinUIEx package.
Am I missing something?
@ataparia Let's do this over at https://github.com/dotMorten/WinUIEx/discussions
Looks like not only Google, but Facebook has also banned the use of embedded browsers and asking developers to use platform-provided authentication APIs on Android: https://developers.facebook.com/blog/post/2021/06/28/deprecating-support-fb-login-authentication-android-embedded-browsers/ At some point this'll likely come to Windows too.
I'm also having this issue. The workaround suggested might be an option, but please fix! Issues like this makes developers run away from .NET MAUI. :(
I have tried the workarounds from https://dotmorten.github.io/WinUIEx/concepts/Maui.html#use-winuiexs-webauthenticator-instead-of-net-mauis and from here https://github.com/dotnet/maui/issues/2702#issuecomment-1172988972
Both seem to do about the same thing. It does fire up a browser with the login page, however, the created url-parametes gives me 403/forbidden on our auth service. I can work around this, by using the second workaround and comment out the section manipulating the state parameter in the url. In this case, I'm able to login, but while doing so, my app isn't blocked in the background. I would have hoped this would be the case, or do I need to take care of that myself? The bigger problem is that when the browser return it doesn't return to my running app, but instead launches a new instance of the app and returns there... Does this has to do with my manipulation of the state parameter? Or am I doing some other mistake?
@Brosten please, anyone having WinUIEx issues, post them in my WinUIEx repo - let's keep this thread focused on the real issue.
Proposal: Lifted WebAuthenticationBroker API that supports all Reunion OS's and application types
See #398, #366 - This issue is similar, but distinct in that it covers creating a new, lifted API, rather than updating the existing one to work for more application types.
Summary
Create an API that developers can use in any application type to implement OAuth2 functionality in any app supported by Reunion.
Rationale
The existing OS API that provides this functionality requires a core Window, which, for practical purposes, means that it only works for UWP-style application, and can't be used in other types of applications. Even if the OS API were updated, it would likely only be updated for new OS versions. It would be helpful for developers to have consistent support across OS versions.
https://task.ms/31649739