xamarin/Xamarin.Auth — pull request #31 by gaearon (2013-06-04 22:31:20+00:00)
Title: Implement authorization using system browser (e.g. Safari)

This commit adds support for authentication via system browser instead of presenting a modal view controller. It includes a working iOS implementation called `SafariUrlHandler`. Android clients [can implement](http://stackoverflow.com/a/2448531/458193) `ICustomUrlHandler` in their code.

Rationale: we noticed that a lot of people are already logged into Twitter/Facebook in Safari but don't remember / care to enter their passwords when presented with a modal form.

![](http://i.imgur.com/zsD62hW.png)

We have a corresponding update for Xamarin.Social (not yet ready as a pull request) that uses this method:

///

/// Attempts to authenticate user with this service using the web browser.
///

public virtual Task> GetAccountsAsync (ICustomUrlHandler customUrlHandler)
{
if (customUrlHandler == null)
throw new ArgumentNullException ("customUrlHandler", "This overload needs a system handler to launch browser and wait for redirect. " +
"On iOS, you can use SafariUrlHandler.Instance, given that you call " +
"its HandleOpenUrl and OnWentForeground methods from your AppDelegate.\n" +
"On Android, you will need to supply your own implementation.");

var tcs = new TaskCompletionSource> ();

var authenticator = GetAuthenticator () as WebAuthenticator;
if (authenticator == null)
throw new NotSupportedException ("This service does not support authentication via web browser.");

authenticator.Completed += (sender, e) => {
if (e.IsAuthenticated) {
AccountStore.Create ().Save (e.Account, this.ServiceId);
tcs.SetResult (new [] { e.Account });
} else {
tcs.SetException (new UnauthorizedAccessException ("Authentication failed."));
}
};

authenticator.AuthenticateWithBrowser (customUrlHandler);
return tcs.Task;
}

So if you want to log into Twitter with Safari (on iOS), you add this to your `AppDelegate`:

public override bool OpenUrl (UIApplication application, NSUrl url, string sourceApplication, NSObject annotation)
{
return SafariUrlHandler.Instance.HandleOpenUrl (new Uri (url.AbsoluteString));
}

public override void WillEnterForeground (UIApplication application)
{
SafariUrlHandler.Instance.WillEnterForeground ();
}

Calling

twitterService.GetAccountsAsync (SafariUrlHandler.Instance).ContinueWith (...)

will open Safari for you and log you in.

Pull request is licensed under MIT/X11.