xamarin / Essentials

Xamarin.Essentials is no longer supported. Migrate your apps to .NET MAUI, which includes Maui.Essentials.
https://aka.ms/xamarin-upgrade
Other
1.52k stars 505 forks source link

[Bug] [UWP] WebAuthenticator calls an unsupported method WebAuthenticationBroker.AuthenticateAsync #1791

Open SymboLinker opened 3 years ago

SymboLinker commented 3 years ago

Description

Inside of WebAuthenticator.uwp.cs: the method WebAuthenticationBroker.AuthenticateAsync from the Windows.Security.Authentication.Web namespace seems to work for Google, but not for Dropbox. For Dropbox, it shows "Can't connect to the service".

Fastest way to reproduce:

Use var requestUri = new Uri("https://dropbox.com/oauth2/authorize?dummyQueryString"); in a call with

var response = await WebAuthenticationBroker.AuthenticateAsync(WebAuthenticationOptions.None, requestUri, new Uri("dummycallbackUri:/"));

This results in: Can't connect to the service

Calling it with

var requestUri = new Uri("https://accounts.google.com/o/oauth2/auth?dummyQueryString");

results in Google-content being displayed (a 400 Bad Request, but that is as expected with a dummy query string).

I tested another random requestUri "https://stackoverflow.com/" that has nothing to do with OAuth, I get:

WebAuthenticationBrokers seems to use Internet Explorer

This last example may provide some information on how the WebAuthenticationBroker works...

At StackOverflow I asked:

The answer has surprised me: the WebAuthenticationBroker probably uses an old browser engine and could be considered a "web view", which is unsupported in OAuth flows.

UWP's WebAuthenticator.PlatformAuthenticateAsync should probably be modified to use a system browser.

SymboLinker commented 3 years ago

I've just created pull request #1828 that is a potential fix for this problem. I suspect that the Xamarin.Essentials team waits until the AuthenticationBroker team comes up with a fix and that the pull request will not be merged.

However, if you are an app developer, it may be helpful to see what classes and methods you can use in your own app, working around the temporary shortcoming of the WebAuthenticator for UWP and doing your OAuth flow for UWP without using the WebAuthenticator of Xamarin.Essentials.

ledangvu commented 3 years ago

I also encountered this issue when I work with AWS Cognito UserPool on UWP where as everything work well on iOS, Android, MacOS. and I have to write my own implementation which replaces the AuthenticationBroker. I follow this guide to make it work on other platform, but it does not work on UWP https://dev.to/pietervdw/using-aws-cognito-with-xamarin-forms-46l5

marvinside commented 3 years ago

So sad to have something normal like OAuth2 being broken in the Xamarin framework.

Is there any ETA when this will be fixed? Seems like this bug ticket is totally abandoned by the Xamarin team :disappointed:

SymboLinker commented 3 years ago

Xamarin is getting a major refactor. It will be renamed “.NET MAUI”. The Xamarin.Essentials team is also refactoring the Essentials library to work with MAUI. So, probably after the library is stable for MAUI, open bugs will be taken on.

However, this bug may be out of scope for the Essentials team, because it’s also an issue for the AuthenticationBroker team. Not very nice news to hear… It took me a while too to find this out.

Check out the PR I did to fix it for your app. If you need help, let me know. I can help.

jerryno6 commented 3 years ago

@SymboLinker I used your solution in my Xamarin project with AWS Cognito User Pool. Your solution works in some cases. But for a special case I did with aws cognito, it is likely we need to investigate morewhen we create a new user in aws cognito user pool and set an email as username. Just follow this guide to create a user, but instead of using a normal username, you just need to put an email as username. https://dev.to/pietervdw/using-aws-cognito-with-xamarin-forms-46l5

jerryno6 commented 3 years ago

@SymboLinker I've found out that when we use Chrome or Edge (chromium core), it does not work with these type of accounts from AWS Cognito, but when we use Firefox as external webbrowser, It works. But the problem is that we cannot ask endusers to install firefox onto their PC to use our app, so I made a solution to make it work without depending on the external browser as a pull request in my own repository below. The trick is to use internal webview with URI activation to make it work together. pull request for using webView and UriActivation

I also created a pull request which uses your solution to test for these accounts on aws cognito Pull request for using external webbrowser

If you have time, please take a look at it. You can use your credential from other Identity services (dropbox/facebook/) to test this solution or You can use users/password that I provide below to test it on your project. Authenticate URL: https://vuleinip.auth.us-east-2.amazoncognito.com/login?client_id=5d55renrdia8r2cg2hocmn98me&response_type=token&scope=aws.cognito.signin.user.admin+email+openid+phone+profile&redirect_uri=myxfcognitoapp:// Callback URL: myxfcognitoapp://

Test accounts: username / password: test01 / Test@123 test02 / Test@123 test03xfcognito@yahoo.com / Test@123

Thanks for your contribution.

SymboLinker commented 3 years ago

I've found out that when we use Chrome or Edge (chromium core), it does not work with these type of accounts from AWS Cognito, but when we use Firefox as external webbrowser, It works.

I know nothing about AWS Cognito and its type of accounts. What I do know, is that the full OAuth (PKCE) flow for Dropbox works via FireFox (version 91.0.2), Chrome (Version 93.0.4577.63) and Edge (Version 93.0.961.38). I've just tested those again.

The trick is to use internal webview with URI activation to make it work together.

Using a web view for OAuth might become forbidden in the future. Google and Dropbox do not support it. I've not searched for other organisations that follow the same rule.

If you have time, please take a look at it.

In your pull request that uses an external browser, I think you should ~HtmlEncode~UrlEncode the callback url when you launch the browser. A querystring parameter value with - for example - a slash in it won't work unless you've ~HtmlEncoded~UrlEncoded it as "%2F".

jerryno6 commented 3 years ago

@SymboLinker Thanks for sharing. At the moment aws cognito works well with webview, it is more stable like it works on Android & iOS, it's better than external webbrowser works in some cases. I will temporarily use it until Microsoft fix for the Broker. or we will wait and move to MAUI. When I have a chance to work with google or dropbox, I will remember the solution from you: use external webbrowser for Oauth2.

As for HtmlEncode, I also use HttpUtility.UrlEncode(callbackUrl.OriginalString) but does not return valid string, and I have to replace it with Uri.Uri.EscapeUriString(string).

SymboLinker commented 3 years ago

As for HtmlEncode, I also use HttpUtility.UrlEncode(callbackUrl.OriginalString) but does not return valid string, and I have to replace it with Uri.Uri.EscapeUriString(string).

Hmmm, HtmlEncoding seems not correct indeed. For my app, I skip the step of escaping the url, because a Dropbox library does that for me. Thanks for the feedback!

EDIT (later added): Luckily I used HttpUtility.UrlEncode in the PR I did. In LinqPad I've just tested that System.Web.HttpUtility.UrlEncode("test://") gives "test%3a%2f%2f".

solomonfried commented 1 year ago

October 2023.

I am running into this issue Authenticating users with New York City Board of Ed OAuth.

On UWP, getting the error that "Internet Explorer is not supported"

Has anyone resolved this issue? (thread seems to be dormant for 2 years)

I am using version 1.8 of Xamarin Essentials (latest)

Thanks