public Task <BrowserResult> InvokeAsync(BrowserOptions options, CancellationToken cancellationToken = default) { var wait = new TaskCompletionSource <BrowserResult>(); _sf = new SFAuthenticationSession( 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); } }); _sf.Start(); return(wait.Task); }
static async Task BeginAuthentication(UIViewController presentingController, WebAuthenticator authenticator) { try { var uri = (await authenticator.GetInitialUrl()); string redirectUrl = uri.GetParameter("redirect_uri"); var scheme = new Uri(redirectUrl).Scheme; if (!VerifyHasUrlSchemeOrDoesntRequire(scheme)) { authenticator.OnError($"Unable to redirect {scheme}, Please add the Url Scheme to the info.plist"); return; } var url = new NSUrl(uri.AbsoluteUri); if (UIDevice.CurrentDevice.CheckSystemVersion(11, 0)) { var AuthTask = new TaskCompletionSource <object>(); authenticators[scheme] = authenticator; var sf = new SFAuthenticationSession(url, scheme, (callbackUrl, Error) => { if (Error == null) { ResumeAuth(callbackUrl.AbsoluteString); AuthTask.SetResult(null); } else { AuthTask.SetException(new Exception($"SFAuthenticationSession Error: {Error.ToString()}")); } } ); sf.Start(); await AuthTask.Task; return; } if (UIDevice.CurrentDevice.CheckSystemVersion(9, 0)) { var controller = new SFSafariViewController(url, false) { Delegate = new NativeSFSafariViewControllerDelegate(authenticator), }; authenticators [scheme] = authenticator; CurrentController = controller; await presentingController.PresentViewControllerAsync(controller, true); return; } var opened = UIApplication.SharedApplication.OpenUrl(url); if (!opened) { authenticator.OnError("Error opening Safari"); } else { authenticators [scheme] = authenticator; } } catch (Exception ex) { authenticator.OnError(ex.Message); } }
public void Authenticate(Uri authorizationUri, Uri redirectUri, RequestContext requestContext) { try { if (UIDevice.CurrentDevice.CheckSystemVersion(12, 0)) { asWebAuthenticationSession = new AuthenticationServices.ASWebAuthenticationSession(new NSUrl(authorizationUri.AbsoluteUri), redirectUri.Scheme, (callbackUrl, error) => { if (error != null) { ProcessCompletionHandlerError(error); } else { ContinueAuthentication(callbackUrl.ToString()); } }); asWebAuthenticationSession.Start(); } else if (UIDevice.CurrentDevice.CheckSystemVersion(11, 0)) { sfAuthenticationSession = new SFAuthenticationSession(new NSUrl(authorizationUri.AbsoluteUri), redirectUri.Scheme, (callbackUrl, error) => { if (error != null) { ProcessCompletionHandlerError(error); } else { ContinueAuthentication(callbackUrl.ToString()); } }); sfAuthenticationSession.Start(); } else { safariViewController = new SFSafariViewController(new NSUrl(authorizationUri.AbsoluteUri), false); safariViewController.Delegate = this; viewController.InvokeOnMainThread(() => { viewController.PresentViewController(safariViewController, false, null); }); } } catch (Exception ex) { requestContext.Logger.ErrorPii(ex); throw MsalExceptionFactory.GetClientException( CoreErrorCodes.AuthenticationUiFailedError, "Failed to invoke SFSafariViewController", ex); } }
public async Task <BrowserResult> InvokeAsync(BrowserOptions options) { var tcs = new TaskCompletionSource <BrowserResult>(); await InvokeBeforeAuthzRequestHooksAsync(options.StartUrl); async void completionHandler(NSUrl url, NSError error) { session = null; if (url == null) { await InvokeAfterAuthzResponseHooksAsync(null, "UserCancel"); tcs.SetResult(new BrowserResult { ResultType = BrowserResultType.UserCancel }); } else { var response = url.AbsoluteString; if (!response.StartsWith(RedirectUri + "#") && !response.StartsWith(RedirectUri + "?")) { await InvokeAfterAuthzResponseHooksAsync(null, response); tcs.SetResult(new BrowserResult { ResultType = BrowserResultType.UnknownError }); } await InvokeAfterAuthzResponseHooksAsync(response, null); tcs.SetResult(new BrowserResult { ResultType = BrowserResultType.Success, Response = response }); } } if (UIDevice.CurrentDevice.CheckSystemVersion(11, 0)) { session = new SFAuthenticationSession(new NSUrl(options.StartUrl), CustomUrlScheme, completionHandler); session.Start(); } else { SafariViewDelegate.GetInstance().Start(new NSUrl(options.StartUrl), CustomUrlScheme, completionHandler); } return(await tcs.Task); }
internal static Task <BrowserResult> Start(BrowserOptions options) { var tcs = new TaskCompletionSource <BrowserResult>(); SFAuthenticationSession sfWebAuthenticationSession = null; sfWebAuthenticationSession = new SFAuthenticationSession( new NSUrl(options.StartUrl), options.EndUrl, (callbackUrl, error) => { tcs.SetResult(CreateBrowserResult(callbackUrl, error)); sfWebAuthenticationSession.Dispose(); }); sfWebAuthenticationSession.Start(); return(tcs.Task); }
static void AuthSessionCallback(NSUrl cbUrl, NSError error) { if (error == null) { OpenUrl(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; }
public void Authenticate(Uri authorizationUri, Uri redirectUri, RequestContext requestContext) { try { if (UIDevice.CurrentDevice.CheckSystemVersion(12, 0)) { asWebAuthenticationSession = new AuthenticationServices.ASWebAuthenticationSession(new NSUrl(authorizationUri.AbsoluteUri), redirectUri.Scheme, (callbackUrl, error) => { if (error != null) { ProcessCompletionHandlerError(error); } else { ContinueAuthentication(callbackUrl.ToString()); } }); asWebAuthenticationSession.BeginInvokeOnMainThread(() => { if (UIDevice.CurrentDevice.CheckSystemVersion(13, 0)) { // If the presentationContext is missing from the session, // MSAL.NET will pick up an "authentication cancelled" error // With the addition of the presentationContext, .Start() must // be called on the main UI thread asWebAuthenticationSession.PresentationContextProvider = new ASWebAuthenticationPresentationContextProviderWindow(); } asWebAuthenticationSession.Start(); }); } else if (UIDevice.CurrentDevice.CheckSystemVersion(11, 0)) { sfAuthenticationSession = new SFAuthenticationSession(new NSUrl(authorizationUri.AbsoluteUri), redirectUri.Scheme, (callbackUrl, error) => { if (error != null) { ProcessCompletionHandlerError(error); } else { ContinueAuthentication(callbackUrl.ToString()); } }); sfAuthenticationSession.Start(); } else { safariViewController = new SFSafariViewController(new NSUrl(authorizationUri.AbsoluteUri), false) { Delegate = this }; viewController.InvokeOnMainThread(() => { viewController.PresentViewController(safariViewController, false, null); }); } } catch (Exception ex) { requestContext.Logger.ErrorPii(ex); throw new MsalClientException( MsalError.AuthenticationUiFailedError, ex.Message, ex); } }
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 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 11, we use the new SFAuthenticationSession if (UIDevice.CurrentDevice.CheckSystemVersion(11, 0)) { // create the authentication session _authSession = new SFAuthenticationSession( new NSUrl(options.StartUrl), options.EndUrl, (callbackUrl, error) => { if (error != null) { tcs.SetResult(new BrowserResult { ResultType = BrowserResultType.UserCancel, Error = error.ToString() }); } else { tcs.SetResult(new BrowserResult { ResultType = BrowserResultType.Success, Response = callbackUrl.AbsoluteString }); } }); // launch authentication session _authSession.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); }
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); }
public void Authenticate(Uri authorizationUri, Uri redirectUri, RequestContext requestContext) { try { /* For app center builds, this will need to build on a hosted mac agent. The mac agent does not have the latest SDK's required to build 'ASWebAuthenticationSession' * Until the agents are updated, appcenter build will need to ignore the use of 'ASWebAuthenticationSession' for iOS 12.*/ #if !IS_APPCENTER_BUILD if (UIDevice.CurrentDevice.CheckSystemVersion(12, 0)) { asWebAuthenticationSession = new AuthenticationServices.ASWebAuthenticationSession(new NSUrl(authorizationUri.AbsoluteUri), redirectUri.Scheme, (callbackUrl, error) => { if (error != null) { ProcessCompletionHandlerError(error); } else { ContinueAuthentication(callbackUrl.ToString()); } }); asWebAuthenticationSession.Start(); } else if (UIDevice.CurrentDevice.CheckSystemVersion(11, 0)) { sfAuthenticationSession = new SFAuthenticationSession(new NSUrl(authorizationUri.AbsoluteUri), redirectUri.Scheme, (callbackUrl, error) => { if (error != null) { ProcessCompletionHandlerError(error); } else { ContinueAuthentication(callbackUrl.ToString()); } }); sfAuthenticationSession.Start(); } #else if (UIDevice.CurrentDevice.CheckSystemVersion(11, 0)) { sfAuthenticationSession = new SFAuthenticationSession(new NSUrl(authorizationUri.AbsoluteUri), redirectUri.Scheme, (callbackUrl, error) => { if (error != null) { ProcessCompletionHandlerError(error); } else { ContinueAuthentication(callbackUrl.ToString()); } }); sfAuthenticationSession.Start(); } #endif else { safariViewController = new SFSafariViewController(new NSUrl(authorizationUri.AbsoluteUri), false) { Delegate = this }; viewController.InvokeOnMainThread(() => { viewController.PresentViewController(safariViewController, false, null); }); } } catch (Exception ex) { requestContext.Logger.ErrorPii(ex); throw new MsalClientException( MsalError.AuthenticationUiFailedError, "Failed to invoke SFSafariViewController", ex); } }
internal static async Task <AuthResult> NavigateAsync(Uri uri, Uri redirectUri) { isWaiting = true; tcsAuth = new TaskCompletionSource <AuthResult>(); WebAuthenticator.redirectUri = redirectUri; try { var scheme = redirectUri.Scheme; if (!VerifyHasUrlSchemeOrDoesntRequire(scheme)) { tcsAuth.TrySetException(new InvalidOperationException("You must register your URL Scheme handler in your app's Info.plist!")); return(await tcsAuth.Task); } if (UIDevice.CurrentDevice.CheckSystemVersion(11, 0)) { var sf = new SFAuthenticationSession(new NSUrl(uri.OriginalString), scheme, (callbackUrl, Error) => { if (Error == null) { UrlOpened(callbackUrl); } else { tcsAuth.TrySetException(new Exception($"SFAuthenticationSession Error: {Error.ToString()}")); } } ); sf.Start(); return(await tcsAuth.Task); } if (UIDevice.CurrentDevice.CheckSystemVersion(9, 0)) { var controller = new SFSafariViewController(new NSUrl(uri.OriginalString), false) { Delegate = new NativeSFSafariViewControllerDelegate { DidFinishHandler = delegate { // Cancel our task if it wasn't already marked as completed if (!(tcsAuth?.Task?.IsCompleted ?? true)) { tcsAuth.TrySetException(new OperationCanceledException()); } Console.WriteLine("Finished"); } }, }; currentViewController = controller; await Platform.PresentingViewController.PresentViewControllerAsync(controller, true); return(await tcsAuth.Task); } var opened = UIApplication.SharedApplication.OpenUrl(uri); if (!opened) { tcsAuth.TrySetException(new Exception("Error opening Safari")); } } catch (Exception ex) { tcsAuth.TrySetException(ex); } return(await tcsAuth.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(); } }