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); }
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); }
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); }
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); }
public UIWindow GetPresentationAnchor(ASWebAuthenticationSession session) { if (View == null) { throw new Exception("View is null: Should not happen..."); } return(View.Window); }
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; }
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); }
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); }
public UIWindow GetPresentationAnchor(ASWebAuthenticationSession session) { return(Anchor); }
public UIWindow GetPresentationAnchor(ASWebAuthenticationSession session) { return(UIApplication.SharedApplication.KeyWindow); }
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); }
public UIWindow GetPresentationAnchor(ASWebAuthenticationSession session) => Window;
public UIWindow GetPresentationAnchor(ASWebAuthenticationSession session) { return(_windowProviderRef.TryGetTarget(out var windowProvider) ? windowProvider.Invoke() : UIApplication.SharedApplication.KeyWindow); }
public NSWindow GetPresentationAnchor(ASWebAuthenticationSession session) => NSApplication.SharedApplication.KeyWindow;
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); }
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(); } }
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); }