コード例 #1
0
        public Task <BrowserResult> InvokeAsync(BrowserOptions options)
        {
            var wait = new TaskCompletionSource <BrowserResult>();

            _af = new ASWebAuthenticationSession(
                new NSUrl(options.StartUrl),
                options.EndUrl,
                (callbackUrl, error) =>
            {
                if (error != null)
                {
                    var errorResult = new BrowserResult
                    {
                        ResultType = BrowserResultType.UserCancel,
                        Error      = error.ToString()
                    };

                    wait.SetResult(errorResult);
                }
                else
                {
                    var result = new BrowserResult
                    {
                        ResultType = BrowserResultType.Success,
                        Response   = callbackUrl.AbsoluteString
                    };

                    wait.SetResult(result);
                }
            });

            _af.Start();
            return(wait.Task);
        }
コード例 #2
0
        public void SignIn()
        {
            var url            = NSUrl.FromString(AuthUrl);
            var callbackScheme = "exampleauth";
            var session        = new ASWebAuthenticationSession(url, callbackScheme, (callbackUrl, error) =>
            {
                if (error != null)
                {
                    // TODO: Handle error
                    return;
                }

                if (callbackUrl == null)
                {
                    // TODO: Handle error
                    return;
                }

                // The callback URL format depends on the provider. For this example:
                //   exampleauth://auth?token=1234
                var queryItems = NSUrlComponents.FromString(callbackUrl.AbsoluteString).QueryItems;
                var token      = queryItems?.FirstOrDefault(x => x.Name == "token")?.Value;

                // TODO: Check token
            })
            {
                PresentationContextProvider = _presentationContext
            };

            session.Start();
        }
        internal static Task <BrowserResult> Start(BrowserOptions options)
        {
            var tcs = new TaskCompletionSource <BrowserResult>();

            ASWebAuthenticationSession asWebAuthenticationSession = null;

            asWebAuthenticationSession = new ASWebAuthenticationSession(
                new NSUrl(options.StartUrl),
                options.EndUrl,
                (callbackUrl, error) =>
            {
                tcs.SetResult(CreateBrowserResult(callbackUrl, error));
                asWebAuthenticationSession.Dispose();
            });

            // iOS 13 requires the PresentationContextProvider set
            if (UIDevice.CurrentDevice.CheckSystemVersion(13, 0))
            {
                asWebAuthenticationSession.PresentationContextProvider = new PresentationContextProviderToSharedKeyWindow();
            }

            asWebAuthenticationSession.Start();

            return(tcs.Task);
        }
コード例 #4
0
        public Task <BrowserResult> InvokeAsync(BrowserOptions options, CancellationToken cancellationToken = default)
        {
            var tcs = new TaskCompletionSource <BrowserResult>();

            try
            {
                _asWebAuthenticationSession = new ASWebAuthenticationSession(
                    new NSUrl(options.StartUrl),
                    options.EndUrl,
                    (callbackUrl, error) =>
                {
                    tcs.SetResult(CreateBrowserResult(callbackUrl, error));
                    _asWebAuthenticationSession.Dispose();
                });

                // iOS 13 requires the PresentationContextProvider set
                if (UIDevice.CurrentDevice.CheckSystemVersion(13, 0))
                {
                    _asWebAuthenticationSession.PresentationContextProvider = new PresentationContextProviderToSharedKeyWindow();
                }

                _asWebAuthenticationSession.Start();
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return(tcs.Task);
        }
コード例 #5
0
        internal static Task <BrowserResult> Start(BrowserOptions options, ASWebAuthenticationSessionOptions sessionOptions = null)
        {
            var tcs = new TaskCompletionSource <BrowserResult>();

            ASWebAuthenticationSession asWebAuthenticationSession = null;

            asWebAuthenticationSession = new ASWebAuthenticationSession(
                new NSUrl(options.StartUrl),
                new NSUrl(options.EndUrl).Scheme,
                (callbackUrl, error) =>
            {
                tcs.SetResult(CreateBrowserResult(callbackUrl, error));
                asWebAuthenticationSession.Dispose();
            });

            if (UIDevice.CurrentDevice.CheckSystemVersion(13, 0))
            {
                // iOS 13 requires the PresentationContextProvider set
                asWebAuthenticationSession.PresentationContextProvider = new PresentationContextProviderToSharedKeyWindow();
                // PrefersEphemeralWebBrowserSession is only available on iOS 13 and up.
                asWebAuthenticationSession.PrefersEphemeralWebBrowserSession = sessionOptions != null ? sessionOptions.PrefersEphemeralWebBrowserSession : false;
            }

            asWebAuthenticationSession.Start();

            return(tcs.Task);
        }
コード例 #6
0
 public UIWindow GetPresentationAnchor(ASWebAuthenticationSession session)
 {
     if (View == null)
     {
         throw new Exception("View is null: Should not happen...");
     }
     return(View.Window);
 }
コード例 #7
0
ファイル: WebAuthenticator.macos.cs プロジェクト: hevey/maui
                static void AuthSessionCallback(NSUrl cbUrl, NSError error)
                {
                    if (error == null)
                    {
                        OpenUrl(cbUrl);
                    }
                    else if (error.Domain == asWebAuthenticationSessionErrorDomain && error.Code == asWebAuthenticationSessionErrorCodeCanceledLogin)
                    {
                        tcsResponse.TrySetCanceled();
                    }
                    else
                    {
                        tcsResponse.TrySetException(new NSErrorException(error));
                    }

                    was = null;
                }
コード例 #8
0
        public Task <string> GetToken()
        {
            var url = new NSUrl(Constants.Url);
            var taskCompletionSource = new TaskCompletionSource <string>();

            void CompletionHandler(NSUrl callbackurl, NSError error)
            {
                var urlParts = callbackurl.Fragment;

                taskCompletionSource.SetResult(urlParts);
            }

            var session = new ASWebAuthenticationSession(url, null, CompletionHandler);

            session.PresentationContextProvider = LoginPageRenderer.Instance;
            session.Start();
            return(taskCompletionSource.Task);
        }
        internal static Task <BrowserResult> Start(BrowserOptions options)
        {
            var tcs = new TaskCompletionSource <BrowserResult>();

            ASWebAuthenticationSession asWebAuthenticationSession = null;

            asWebAuthenticationSession = new ASWebAuthenticationSession(
                new NSUrl(options.StartUrl),
                options.EndUrl,
                (callbackUrl, error) =>
            {
                tcs.SetResult(CreateBrowserResult(callbackUrl, error));
                asWebAuthenticationSession.Dispose();
            });

            asWebAuthenticationSession.Start();

            return(tcs.Task);
        }
コード例 #10
0
        public Task <BrowserResult> InvokeAsync(BrowserOptions options, CancellationToken cancellationToken = default)
        {
            var wait = new TaskCompletionSource <BrowserResult>();

            _af = new ASWebAuthenticationSession(
                new NSUrl(options.StartUrl),
                options.EndUrl,
                (callbackUrl, error) =>
            {
                if (error != null)
                {
                    var errorResult = new BrowserResult
                    {
                        ResultType = BrowserResultType.UserCancel,
                        Error      = error.ToString()
                    };

                    wait.SetResult(errorResult);
                }
                else
                {
                    var result = new BrowserResult
                    {
                        ResultType = BrowserResultType.Success,
                        Response   = callbackUrl.AbsoluteString
                    };

                    wait.SetResult(result);
                }
            });

            // iOS 13 requires the PresentationContextProvider set
            if (UIDevice.CurrentDevice.CheckSystemVersion(13, 0))
            {
                _af.PresentationContextProvider = new PresentationContextProviderToSharedKeyWindow();
            }

            _af.Start();
            return(wait.Task);
        }
コード例 #11
0
 public UIWindow GetPresentationAnchor(ASWebAuthenticationSession session)
 {
     return(Anchor);
 }
コード例 #12
0
 public UIWindow GetPresentationAnchor(ASWebAuthenticationSession session)
 {
     return(UIApplication.SharedApplication.KeyWindow);
 }
コード例 #13
0
        public async Task <WebAuthenticatorResult> AuthenticateAsync(WebAuthenticatorOptions webAuthenticatorOptions)
        {
            var url         = webAuthenticatorOptions?.Url;
            var callbackUrl = webAuthenticatorOptions?.CallbackUrl;
            var prefersEphemeralWebBrowserSession = webAuthenticatorOptions?.PrefersEphemeralWebBrowserSession ?? false;

            if (!VerifyHasUrlSchemeOrDoesntRequire(callbackUrl.Scheme))
            {
                throw new InvalidOperationException("You must register your URL Scheme handler in your app's Info.plist.");
            }

            // Cancel any previous task that's still pending
            if (tcsResponse?.Task != null && !tcsResponse.Task.IsCompleted)
            {
                tcsResponse.TrySetCanceled();
            }

            tcsResponse = new TaskCompletionSource <WebAuthenticatorResult>();
            redirectUri = callbackUrl;
            var scheme = redirectUri.Scheme;

#if __IOS__
            void AuthSessionCallback(NSUrl cbUrl, NSError error)
            {
                if (error == null)
                {
                    OpenUrlCallback(cbUrl);
                }
                else if (error.Domain == asWebAuthenticationSessionErrorDomain && error.Code == asWebAuthenticationSessionErrorCodeCanceledLogin)
                {
                    tcsResponse.TrySetCanceled();
                }
                else if (error.Domain == sfAuthenticationErrorDomain && error.Code == sfAuthenticationErrorCanceledLogin)
                {
                    tcsResponse.TrySetCanceled();
                }
                else
                {
                    tcsResponse.TrySetException(new NSErrorException(error));
                }

                was = null;
                sf  = null;
            }

            if (OperatingSystem.IsIOSVersionAtLeast(12, 0))
            {
                was = new ASWebAuthenticationSession(WebUtils.GetNativeUrl(url), scheme, AuthSessionCallback);

                if (OperatingSystem.IsIOSVersionAtLeast(13, 0))
                {
                    var ctx = new ContextProvider(WindowStateManager.Default.GetCurrentUIWindow());
                    was.PresentationContextProvider       = ctx;
                    was.PrefersEphemeralWebBrowserSession = prefersEphemeralWebBrowserSession;
                }
                else if (prefersEphemeralWebBrowserSession)
                {
                    ClearCookies();
                }

                using (was)
                {
                    was.Start();
                    return(await tcsResponse.Task);
                }
            }

            if (prefersEphemeralWebBrowserSession)
            {
                ClearCookies();
            }

            if (OperatingSystem.IsIOSVersionAtLeast(11, 0))
            {
                sf = new SFAuthenticationSession(WebUtils.GetNativeUrl(url), scheme, AuthSessionCallback);
                using (sf)
                {
                    sf.Start();
                    return(await tcsResponse.Task);
                }
            }

            // This is only on iOS9+ but we only support 10+ in Essentials anyway
            var controller = new SFSafariViewController(WebUtils.GetNativeUrl(url), false)
            {
                Delegate = new NativeSFSafariViewControllerDelegate
                {
                    DidFinishHandler = (svc) =>
                    {
                        // Cancel our task if it wasn't already marked as completed
                        if (!(tcsResponse?.Task?.IsCompleted ?? true))
                        {
                            tcsResponse.TrySetCanceled();
                        }
                    }
                },
            };

            currentViewController = controller;
            await WindowStateManager.Default.GetCurrentUIViewController().PresentViewControllerAsync(controller, true);
#else
            var opened = UIApplication.SharedApplication.OpenUrl(url);
            if (!opened)
            {
                tcsResponse.TrySetException(new Exception("Error opening Safari"));
            }
#endif

            return(await tcsResponse.Task);
        }
コード例 #14
0
 public UIWindow GetPresentationAnchor(ASWebAuthenticationSession session)
 => Window;
コード例 #15
0
 public UIWindow GetPresentationAnchor(ASWebAuthenticationSession session)
 {
     return(_windowProviderRef.TryGetTarget(out var windowProvider)
         ? windowProvider.Invoke()
         : UIApplication.SharedApplication.KeyWindow);
 }
コード例 #16
0
 public NSWindow GetPresentationAnchor(ASWebAuthenticationSession session) => NSApplication.SharedApplication.KeyWindow;
コード例 #17
0
        internal static async Task <WebAuthenticatorResult> PlatformAuthenticateAsync(Uri url, Uri callbackUrl)
        {
            // Cancel any previous task that's still pending
            if (tcsResponse?.Task != null && !tcsResponse.Task.IsCompleted)
            {
                tcsResponse.TrySetCanceled();
            }

            tcsResponse = new TaskCompletionSource <WebAuthenticatorResult>();
            redirectUri = callbackUrl;

            try
            {
                var scheme = redirectUri.Scheme;

                if (!VerifyHasUrlSchemeOrDoesntRequire(scheme))
                {
                    tcsResponse.TrySetException(new InvalidOperationException("You must register your URL Scheme handler in your app's Info.plist!"));
                    return(await tcsResponse.Task);
                }

#if __IOS__
                void AuthSessionCallback(NSUrl cbUrl, NSError error)
                {
                    if (error == null)
                    {
                        OpenUrl(cbUrl);
                    }
                    else
                    {
                        tcsResponse.TrySetException(new NSErrorException(error));
                    }
                }

                if (UIDevice.CurrentDevice.CheckSystemVersion(12, 0))
                {
                    was = new ASWebAuthenticationSession(new NSUrl(url.OriginalString), scheme, AuthSessionCallback);

                    if (UIDevice.CurrentDevice.CheckSystemVersion(13, 0))
                    {
                        var ctx = new ContextProvider(Platform.GetCurrentWindow());
                        void_objc_msgSend_IntPtr(was.Handle, ObjCRuntime.Selector.GetHandle("setPresentationContextProvider:"), ctx.Handle);
                    }

                    using (was)
                    {
                        was.Start();
                        return(await tcsResponse.Task);
                    }
                }

                if (UIDevice.CurrentDevice.CheckSystemVersion(11, 0))
                {
                    sf = new SFAuthenticationSession(new NSUrl(url.OriginalString), scheme, AuthSessionCallback);
                    using (sf)
                    {
                        sf.Start();
                        return(await tcsResponse.Task);
                    }
                }

                // THis is only on iOS9+ but we only support 10+ in Essentials anyway
                var controller = new SFSafariViewController(new NSUrl(url.OriginalString), false)
                {
                    Delegate = new NativeSFSafariViewControllerDelegate
                    {
                        DidFinishHandler = (svc) =>
                        {
                            // Cancel our task if it wasn't already marked as completed
                            if (!(tcsResponse?.Task?.IsCompleted ?? true))
                            {
                                tcsResponse.TrySetException(new OperationCanceledException());
                            }
                        }
                    },
                };

                currentViewController = controller;
                await Platform.GetCurrentUIViewController().PresentViewControllerAsync(controller, true);

                return(await tcsResponse.Task);
#else
                var opened = UIApplication.SharedApplication.OpenUrl(url);
                if (!opened)
                {
                    tcsResponse.TrySetException(new Exception("Error opening Safari"));
                }
#endif
            }
            catch (Exception ex)
            {
                tcsResponse.TrySetException(ex);
            }

            return(await tcsResponse.Task);
        }
コード例 #18
0
        protected virtual async Task <WebAuthenticationResult> AuthenticateAsyncCore(
            WebAuthenticationOptions options,
            Uri requestUri,
            Uri callbackUri,
            CancellationToken ct)
        {
            var tcs = new TaskCompletionSource <WebAuthenticationResult>();

            void AuthSessionCallback(NSUrl?callbackUrl, NSError?error)
            {
                if (error != null)
                {
                    if ((error.Domain == asWebAuthenticationSessionErrorDomain &&
                         error.Code == asWebAuthenticationSessionErrorCodeCanceledLogin)
#if __IOS__
                        || (error.Domain == sfAuthenticationErrorDomain &&
                            error.Code == sfAuthenticationErrorCanceledLogin)
#endif
                        )
                    {
                        tcs.SetResult(new WebAuthenticationResult(
                                          null,
                                          0,
                                          WebAuthenticationStatus.UserCancel));
                    }
                    tcs.SetResult(new WebAuthenticationResult(
                                      error.ToString(),
                                      0,
                                      WebAuthenticationStatus.ErrorHttp));
                }
                else
                {
                    tcs.SetResult(new WebAuthenticationResult(
                                      callbackUrl?.AbsoluteString,
                                      0,
                                      WebAuthenticationStatus.Success));
                }
            }

            IDisposable?was = default;

            void Cancel()
            {
                var w = was;

                if (w is ASWebAuthenticationSession aswas)
                {
                    aswas.Cancel();
                }
#if __IOS__
                else if (w is SFAuthenticationSession sfwas)
                {
                    sfwas.Cancel();
                }
#endif

                w?.Dispose();
                was = null;
            }

            await using var x = ct.Register(Cancel);

            var startUrl    = new NSUrl(requestUri.OriginalString);
            var callbackUrl = callbackUri.OriginalString;

            var schemes = GetApplicationCustomSchemes().ToArray();
            if (!schemes.Any(s => callbackUrl.StartsWith(s)))
            {
                var message = schemes.Length == 0
                                        ? "No schemes defined in info.plist. You must define a custom scheme (CFBundleURLSchemes) for your callback url."
                                        : $"No schemes defined for callback url {callbackUrl}. Defined schemes are: {schemes.JoinBy(" ")}";
                throw new InvalidOperationException(message);
            }


#if __IOS__
            if (UIDevice.CurrentDevice.CheckSystemVersion(12, 0))
#else
            var osVersion = NSProcessInfo.ProcessInfo.OperatingSystemVersion;
            if (new Version((int)osVersion.Major, (int)osVersion.Minor) >= new Version(10, 15))
#endif
            {
                var aswas = new ASWebAuthenticationSession(startUrl, callbackUrl, AuthSessionCallback);
                was = aswas;

#if __IOS__
                if (UIDevice.CurrentDevice.CheckSystemVersion(13, 0))
#endif
                {
                    aswas.PresentationContextProvider       = new PresentationContextProviderToSharedKeyWindow();
                    aswas.PrefersEphemeralWebBrowserSession =
                        WinRTFeatureConfiguration.WebAuthenticationBroker.PrefersEphemeralWebBrowserSession;
                }

                var dispatcher = CoreDispatcher.Main;
                if (dispatcher.HasThreadAccess)
                {
                    Start();
                }
                else
                {
                    var t = dispatcher.RunAsync(CoreDispatcherPriority.Normal, Start);
                }

                void Start()
                {
                    if (!aswas.Start())
                    {
                        tcs.TrySetException(new InvalidOperationException("Unable to start authentication"));
                    }
                }
            }
#if __IOS__
            else
            {
                if (UIDevice.CurrentDevice.CheckSystemVersion(11, 0))
                {
                    var sfwas = new SFAuthenticationSession(startUrl, callbackUrl, AuthSessionCallback);
                    was = sfwas;

                    if (!sfwas.Start())
                    {
                        tcs.TrySetException(new InvalidOperationException("Unable to start authentication"));
                    }
                }

                else
                {
                    throw new InvalidOperationException("iOS v11+ is required for this implementation of WebAuthenticationBroker.");
                }
            }
#endif

            try
            {
                return(await tcs.Task);
            }
            finally
            {
                Cancel();
            }
        }
コード例 #19
0
        public Task <BrowserResult> InvokeAsync(BrowserOptions options)
        {
            if (string.IsNullOrWhiteSpace(options.StartUrl))
            {
                throw new ArgumentException("Missing StartUrl", nameof(options));
            }

            if (string.IsNullOrWhiteSpace(options.EndUrl))
            {
                throw new ArgumentException("Missing EndUrl", nameof(options));
            }

            // must be able to wait for the authentication session to be finished to continue
            // with setting the task result
            var tcs = new TaskCompletionSource <BrowserResult>();

            // For iOS 12, we use ASWebAuthenticationSession
            if (UIDevice.CurrentDevice.CheckSystemVersion(12, 0))
            {
                // create the authentication session
                _asWebAuthenticationSession = new ASWebAuthenticationSession(
                    new NSUrl(options.StartUrl),
                    options.EndUrl,
                    (callbackUrl, error) =>
                {
                    var browserResult = new BrowserResult();

                    if (error != null)
                    {
                        if (error.Code == (long)ASWebAuthenticationSessionErrorCode.CanceledLogin)
                        {
                            browserResult.ResultType = BrowserResultType.UserCancel;
                        }
                        else
                        {
                            browserResult.ResultType = BrowserResultType.UnknownError;
                        }

                        browserResult.Error = error.ToString();

                        tcs.SetResult(browserResult);
                    }
                    else
                    {
                        tcs.SetResult(new BrowserResult
                        {
                            ResultType = BrowserResultType.Success,
                            Response   = callbackUrl.AbsoluteString
                        });
                    }
                });

                // launch authentication session
                _asWebAuthenticationSession.Start();
            }
            // For iOS 11, we use SFAuthenticationSession
            else if (UIDevice.CurrentDevice.CheckSystemVersion(11, 0))
            {
                // create the authentication session
                _sfAuthenticationSession = new SFAuthenticationSession(
                    new NSUrl(options.StartUrl),
                    options.EndUrl,
                    (callbackUrl, error) =>
                {
                    var browserResult = new BrowserResult();

                    if (error != null)
                    {
                        if (error.Code == (long)SFAuthenticationError.CanceledLogin)
                        {
                            browserResult.ResultType = BrowserResultType.UserCancel;
                        }
                        else
                        {
                            browserResult.ResultType = BrowserResultType.UnknownError;
                        }

                        browserResult.Error = error.ToString();

                        tcs.SetResult(browserResult);
                    }
                    else
                    {
                        tcs.SetResult(new BrowserResult
                        {
                            ResultType = BrowserResultType.Success,
                            Response   = callbackUrl.AbsoluteString
                        });
                    }
                });

                // launch authentication session
                _sfAuthenticationSession.Start();
            }
            else // For pre-iOS 11, we use a normal SFSafariViewController
            {
                // create Safari controller
                _safari = new SFSafariViewController(new NSUrl(options.StartUrl))
                {
                    Delegate = this
                };

                ActivityMediator.MessageReceivedEventHandler callback = null;
                callback = async(response) =>
                {
                    // remove handler
                    ActivityMediator.Instance.ActivityMessageReceived -= callback;

                    if (response == "UserCancel")
                    {
                        tcs.SetResult(new BrowserResult
                        {
                            ResultType = BrowserResultType.UserCancel
                        });
                    }
                    else
                    {
                        // Close Safari
                        await _safari.DismissViewControllerAsync(true);

                        // set result
                        tcs.SetResult(new BrowserResult
                        {
                            Response   = response,
                            ResultType = BrowserResultType.Success
                        });
                    }
                };

                // attach handler
                ActivityMediator.Instance.ActivityMessageReceived += callback;

                // https://forums.xamarin.com/discussion/24689/how-to-acces-the-current-view-uiviewcontroller-from-an-external-service
                var window = UIApplication.SharedApplication.KeyWindow;
                var vc     = window.RootViewController;
                while (vc.PresentedViewController != null)
                {
                    vc = vc.PresentedViewController;
                }

                // launch Safari
                vc.PresentViewController(_safari, true, null);
            }

            // Result for this task will be set in the authentication session
            // completion handler
            return(tcs.Task);
        }