Configuring the Xamarin.Auth component to authenticate using Facebook and Google+
Overview
I recently had the need to implement delegated authentication for a new cross platform mobile app I'm helping to build. The app is being built using Xamarin. It’s the best tool out there for building cross platform native mobile apps. If you’re a mobile developer and you haven’t looked into Xamarin, I recommend it. If you'd like to learn more about it, here are a few references:- Xamarin Cross-platform Application Development
- Xamarin reference: Building Cross Platform Applications
Before I get into the details of the subject of this post, there’s a little background I should provide. If you’re familiar with OAuth and the typical challenges of identity and access management in mobile apps, or you don’t care and just want to get to the point, skip down to the section titled: Getting to it… finally.
Identity Confusion
First, when it comes to identity and access management, there are a few things you should know which are outside the scope of this post. The following terms are often misused, but it’s important to understand what each is, and the differences between them.- SSO: Wikipedia article on single sign-on
- OAuth: Wikipedia article on OAuth
- OpenID: Wikipedia article on OpenID
- Delegated Authentication and federated identity: Article on delegated versus federated identity
A few important and relevant excerpts:
“Other shared authentication schemes not to be confused with SSO include OAuth, OpenID, OpenID Connect and Facebook Connect, which require the user to enter their login credentials each time they access a different site or application.”
“OAuth is a service that is complementary to and distinct from OpenID.”Our app will be implementing delegated authentication using OAuth. And even though we're using OAuth, we're not necessarily using OpenID, because Facebook Login doesn’t use it. See this StackOverflow question to get an idea of the confusion between OAuth and OpenID.
Setup
So with that background, I moved on to beginning my research to find the right tool for the job. We are required to provide delegated authentication through Facebook and Google+, as well as our own custom provider. I'm a very pragmatic developer, and as such, I like to start simple. I use real TDD when possible. I refactor when the code and requirements tell me it’s time. I develop for requirements I know now, not for requirements that might come later, but I plan for how to handle possibilities which later might become requirements.So, when tasked with this, my first thought was to use each provider's native SDK. Xamarin's component store had both Facebook and Google SDKs, so I added them both to the iOS and Android projects and got to work.
iOS:
Android:
- https://components.xamarin.com/view/googleiossignin
- https://developer.xamarin.com/samples/monodroid/google-services%5CSigninQuickstart/
I looked into identity and access management providers like Azure Access Control Service, Amazon Cognito and Auth0. These would provide a consistent API for authenticating, and would allow us to add providers later without having to add code and deploy an app update. That’s a good, forward-thinking design, but we don't currently have a requirement for this. So I noted it and moved on.
I quickly narrowed my research to Xamarin Components. I discovered the Xamarin.Auth component, which seemed to fit the bill. If we use this component, we can avoid the duplication of referencing multiple SDKs, and the duplicate code resulting from having to manage the OAuth token obtained from each of them. And if in the future we needed to move to Azure ACS or one of the other identity and access management providers, this component would minimize the impact of that change.
But in trying to get this component working, I found the documentation for configuring each provider to be lacking, and because of the nature of Xamarin cross platform development, each provider’s documentation for configuring for OAuth wasn’t exactly clear. So the purpose of this post is to provide some documentation which I found to be lacking.
Getting to it... finally
Now that you’ve waded through the overview, background and setup, I’m finally getting to the point. In order to use the Xamarin.Auth component for delegated authentication to any provider, you first need to configure each provider. But configuration is confusing. I found this especially true for Google+. Maybe that’s because the documentation for the Xamarin.Auth component provided an example for Facebook, which while it does conform to the OAuth 2 standard, does not support OpenID.Choose iOS or Android (it doesn't matter which and you'll only need one). Give it a name and create it. There may be some interstitial configuration screens, but what you enter there is not relevant to this post. Just fill them out as you see fit and get to the point of creating a new app ID.
You can ignore most of the instructions for getting started on the native platform and just include your bundle ID. I should note that if for some reason you're using different bundle IDs for iOS and Android, you'll have to create separate Facebook App IDs. Once you've added your bundle identifier, you're almost done.
Some additional configuration you should set: Embedded Browser OAuth Login needs to be turned on. You should also specify that this is for a native or desktop app.
Google+
I found this blog post pretty useful in helping me figure out the proper configuration of the Project in the Google Developers Console. First, sign into the Google Developers console, then Manage Projects -> Create project.Create a new project. Give it a name and optionally customize the Project Id.
Once that's complete you'll be redirected to the dashboard. From the dashboard, choose "Enable and Manage APIs".
This will give you a list of APIs currently enabled for the project. When you create a new project, several APIs are already enabled.
For simplicity, I remove the APIs I'm not using. We only need the Google+ API, which currently isn't enabled by default. So after disabling all the APIs I'm not using, I add the Google+ API.
This is where it gets a little confusing. When you go to create a new credential, the configuration wizard starts by asking you where you'll be calling the API from. Even though this is being used in a native app, something about how Xamarin.Auth is designed requires this configuration to be for a web app. Select that option. You will be presented with a form to configure additional information. The configuration here is the callback URL. Set it to https://www.googleapis.com/plus/v1/people/me
You may get a confirmation screen that includes a clientSecret or other information. This is not needed by the Xamarin.Auth component.
Usage in Xamarin iOS and Android
Once you have those created and configured, using it is simple and the component documentation is clear. There are some considerations with app configuration, especially with Application Transport Security in iOS. Documentation there is pretty good, so I'll leave that out of scope for this post.partial void btnFacebookSignIn_Click (NSObject sender) {
var auth = new OAuth2Authenticator (
"App ID from https://developers.facebook.com/apps",
"",
new Uri ("https://m.facebook.com/dialog/oauth/"),
new Uri ("http://www.facebook.com/connect/login_success.html"));
auth.Completed += (s, e) => {
// We presented the UI, so it's up to us to dimiss it on iOS.
this.DismissViewController (true, null);
if (e.IsAuthenticated) {
AccountStore.Create ().Save (e.Account, "Facebook");
// Use eventArgs.Account to do wonderful things
} else {
// The user cancelled
}
};
this.PresentViewController (auth.GetUI (), true, null);
}
Google +
Google configuration is similar, but you should include scope of "opened":partial void btnGoogleSignIn_Click (NSObject sender) {
var auth = new OAuth2Authenticator (
"ClientID from google developer console",
"openid",
new Uri ("https://accounts.google.com/o/oauth2/auth"),
new Uri ("https://www.googleapis.com/plus/v1/people/me"));
auth.Completed += (s, e) => {
// We presented the UI, so it's up to us to dimiss it on iOS.
this.DismissViewController (true, null);
if (e.IsAuthenticated) {
AccountStore.Create ().Save (e.Account, "MovieExplorer");
// Use eventArgs.Account to do wonderful things
} else {
// The user cancelled
}
};
this.PresentViewController (auth.GetUI (), true, null);
}
Comments
Post a Comment