diff --git a/src/Essentials/src/WebAuthenticator/WebAuthenticator.shared.cs b/src/Essentials/src/WebAuthenticator/WebAuthenticator.shared.cs index 25302b1782cd..d6616ffcdc58 100644 --- a/src/Essentials/src/WebAuthenticator/WebAuthenticator.shared.cs +++ b/src/Essentials/src/WebAuthenticator/WebAuthenticator.shared.cs @@ -19,11 +19,9 @@ public interface IWebAuthenticator /// A instance containing additional configuration for this authentication call. /// A object with the results of this operation. /// Thrown when the user canceled the authentication flow. - /// Windows: Thrown when a HTTP Request error occured. - /// Windows: Thrown when a unexpected HTTP response was received. + /// Windows: Thrown when called on Windows. /// iOS/macOS: Thrown when iOS version is less than 13 is used or macOS less than 13.1 is used. /// - /// Windows: Thrown when the callback custom URL scheme is not registered in the AppxManifest.xml file. /// Android: Thrown when the no IntentFilter has been created for the callback URL. /// Task AuthenticateAsync(WebAuthenticatorOptions webAuthenticatorOptions); @@ -76,13 +74,19 @@ public static class WebAuthenticator /// Begin an authentication flow by navigating to the specified url and waiting for a callback/redirect to the callbackUrl scheme. /// Url to navigate to, beginning the authentication flow. /// Expected callback url that the navigation flow will eventually redirect to. - /// Returns a result parsed out from the callback url. + /// Returns a result parsed out from the callback url. +#if !NETSTANDARD + [System.Runtime.Versioning.UnsupportedOSPlatform("windows")] +#endif public static Task AuthenticateAsync(Uri url, Uri callbackUrl) => Current.AuthenticateAsync(url, callbackUrl); /// Begin an authentication flow by navigating to the specified url and waiting for a callback/redirect to the callbackUrl scheme.The start url and callbackUrl are specified in the webAuthenticatorOptions. /// Options to configure the authentication request. /// Returns a result parsed out from the callback url. +#if !NETSTANDARD + [System.Runtime.Versioning.UnsupportedOSPlatform("windows")] +#endif public static Task AuthenticateAsync(WebAuthenticatorOptions webAuthenticatorOptions) => Current.AuthenticateAsync(webAuthenticatorOptions); diff --git a/src/Essentials/src/WebAuthenticator/WebAuthenticator.uwp.cs b/src/Essentials/src/WebAuthenticator/WebAuthenticator.uwp.cs index 8f233e9720cf..c097d2d2ba51 100644 --- a/src/Essentials/src/WebAuthenticator/WebAuthenticator.uwp.cs +++ b/src/Essentials/src/WebAuthenticator/WebAuthenticator.uwp.cs @@ -1,64 +1,13 @@ using System; -using System.IO; -using System.Linq; -using System.Net.Http; using System.Threading.Tasks; -using System.Xml; -using System.Xml.Linq; -using System.Xml.XPath; -using Microsoft.Maui.ApplicationModel; -using Microsoft.Maui.Storage; -using Windows.Security.Authentication.Web; namespace Microsoft.Maui.Authentication { partial class WebAuthenticatorImplementation : IWebAuthenticator { - public async Task AuthenticateAsync(WebAuthenticatorOptions webAuthenticatorOptions) + public Task AuthenticateAsync(WebAuthenticatorOptions webAuthenticatorOptions) { - var url = webAuthenticatorOptions?.Url; - var callbackUrl = webAuthenticatorOptions?.CallbackUrl; - - if (!IsUriProtocolDeclared(callbackUrl.Scheme)) - throw new InvalidOperationException($"You need to declare the windows.protocol usage of the protocol/scheme `{callbackUrl.Scheme}` in your AppxManifest.xml file"); - - try - { - var r = await WebAuthenticationBroker.AuthenticateAsync(WebAuthenticationOptions.None, url, callbackUrl); - - switch (r.ResponseStatus) - { - case WebAuthenticationStatus.Success: - // For GET requests this is a URI: - var resultUri = new Uri(r.ResponseData.ToString()); - return new WebAuthenticatorResult(resultUri, webAuthenticatorOptions?.ResponseDecoder); - case WebAuthenticationStatus.UserCancel: - throw new TaskCanceledException(); - case WebAuthenticationStatus.ErrorHttp: - throw new HttpRequestException("Error: " + r.ResponseErrorDetail); - default: - throw new Exception("Response: " + r.ResponseData.ToString() + "\nStatus: " + r.ResponseStatus); - } - } - catch (FileNotFoundException) - { - throw new TaskCanceledException(); - } - } - - static bool IsUriProtocolDeclared(string scheme) - { - var docPath = FileSystemUtils.PlatformGetFullAppPackageFilePath(PlatformUtils.AppManifestFilename); - var doc = XDocument.Load(docPath, LoadOptions.None); - var reader = doc.CreateReader(); - var namespaceManager = new XmlNamespaceManager(reader.NameTable); - namespaceManager.AddNamespace("x", PlatformUtils.AppManifestXmlns); - namespaceManager.AddNamespace("uap", "http://schemas.microsoft.com/appx/manifest/uap/windows10"); - - // Check if the protocol was declared - var decl = doc.Root.XPathSelectElements($"//uap:Extension[@Category='windows.protocol']/uap:Protocol[@Name='{scheme}']", namespaceManager); - - return decl != null && decl.Any(); + throw new PlatformNotSupportedException("This implementation of WebAuthenticator does not support Windows. See https://github.com/microsoft/WindowsAppSDK/issues/441 for more details."); } } } diff --git a/src/Essentials/test/DeviceTests/Tests/WebAuthenticator_Tests.cs b/src/Essentials/test/DeviceTests/Tests/WebAuthenticator_Tests.cs index 20219b4a7d3b..645d636bd2ee 100644 --- a/src/Essentials/test/DeviceTests/Tests/WebAuthenticator_Tests.cs +++ b/src/Essentials/test/DeviceTests/Tests/WebAuthenticator_Tests.cs @@ -21,14 +21,21 @@ public class WebAuthenticator_Tests [Trait(Traits.InteractionType, Traits.InteractionTypes.Human)] public async Task Redirect(string urlBase, string callbackScheme, string accessToken, string refreshToken, int expires) { - var r = await WebAuthenticator.AuthenticateAsync( +#pragma warning disable CA1416 // Validate platform compatibility: Not supported on Windows + var authenticationTask = WebAuthenticator.AuthenticateAsync( new Uri($"{urlBase}?access_token={accessToken}&refresh_token={refreshToken}&expires={expires}"), new Uri($"{callbackScheme}://")); +#pragma warning restore CA1416 // Validate platform compatibility +#if WINDOWS + var exception = await Assert.ThrowsAsync(async () => await authenticationTask); +#else + var r = await authenticationTask; Assert.Equal(accessToken, r?.AccessToken); Assert.Equal(refreshToken, r?.RefreshToken); Assert.NotNull(r?.ExpiresIn); Assert.True(r?.ExpiresIn > DateTime.UtcNow); +#endif } [Theory] @@ -42,18 +49,24 @@ public async Task Redirect(string urlBase, string callbackScheme, string accessT public async Task RedirectWithResponseDecoder(string urlBase, string callbackScheme, string accessToken, string refreshToken, int expires) { var responseDecoder = new TestResponseDecoder(); - var r = await WebAuthenticator.AuthenticateAsync(new WebAuthenticatorOptions +#pragma warning disable CA1416 // Validate platform compatibility: Not supported on Windows + var authenticationTask = WebAuthenticator.AuthenticateAsync(new WebAuthenticatorOptions { Url = new Uri($"{urlBase}?access_token={accessToken}&refresh_token={refreshToken}&expires={expires}"), CallbackUrl = new Uri($"{callbackScheme}://"), ResponseDecoder = responseDecoder }); - +#pragma warning restore CA1416 // Validate platform compatibility +#if WINDOWS + var exception = await Assert.ThrowsAsync(async () => await authenticationTask); +#else + var r = await authenticationTask; Assert.Equal(accessToken, r?.AccessToken); Assert.Equal(refreshToken, r?.RefreshToken); Assert.NotNull(r?.ExpiresIn); Assert.True(r?.ExpiresIn > DateTime.UtcNow); Assert.Equal(1, responseDecoder.CallCount); +#endif } [Theory]