OAuth Login Authenticating With Identity Provider In Xamarin.Forms

Introduction

OAuth is an authorization framework that enables application to obtain limited access to user accounts on HTTP service on Facebook, Google, and Microsoft etc. Nowadays, there is no need to create registration logic. Alternatively, you can choose using identity provider login. In this case, a person signs up for the app using identity provider login, an account is created for them, and the authentication step is taken care of by identity provider.

In this article, I will explain how to implement the below OAuth identity provider in Xamarin Forms and manage the authentication process in a Xamarin Forms application.

  1. GOOGLE
  2. FACEBOOK
  3. TWITTER
  4. MICROSOFT
  5. LINKEDIN
  6. GITHUB
  7. FLICKER
  8. YAHOO
  9. DROPBOX
xamarin Forms application

Register Mobile App with Identity Provider

You can find my previous article for registering mobile app with identity provider from here.

Step 1 - Create New Xamarin.Forms Project

Let's start with creating a new Xamarin Forms Project in Visual Studio.

Open Run - Type Devenev.Exe and enter - New Project (Ctrl+Shift+N) - select Blank Xaml App (Xamarin.Forms Portable) template.

Blank

It will automatically create multiple projects, like Portable, Android, iOS, and UWP but here, I will be targeting only Android. However, the implementation of iOS and UWP is similar.

Step 2 - Install OAuth Client Components

Xamarin.Auth is a cross-platform SDK for authenticating users and storing their accounts. It includes OAuth authenticators that provide support for consuming identity providers.

Let's add the Xamarin.Auth component for OAuth. We will have to add this in all platform-specific projects, separately.

Go to any project (DevEnVExeLogin.Droid) - Components - Right click on "Get More Components".

If you are not logged in already, it will show the login page. So, login there.

Next, search and double-click on Xamarin.Auth component and click on "Add to App".

Xamarin.Auth

Step 3 - Create Base Login Page (LoginPage.Xaml)

I have created quick and simple login screens .You can modify them as per your requirement.

Right click on Portable Class Library - Add New Item - Select Xaml Page(Login Page).

LoginPage.Xaml

  1. <?xml version="1.0" encoding="utf-8" ?>  
  2. <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:DevEnvExeLogin" x:Class="DevEnvExeLogin.LoginPage">  
  3.     <StackLayout>  
  4.         <Entry Placeholder="Username" />  
  5.         <Entry IsPassword="true" Placeholder="Password" />  
  6.         <Button Text="Login" HeightRequest="50" />  
  7.         <Button Text="Google" Clicked="LoginClick" Image="GOOGLE.png" HeightRequest="50" />  
  8.         <Button Text="FaceBook" Clicked="LoginClick" Image="FACEBOOK.png" HeightRequest="50" />  
  9.         <Button Text="Twitter" Clicked="LoginClick" Image="TWITTER.png" HeightRequest="50" />  
  10.         <Button Text="Github" Clicked="LoginClick" Image="GITHUB.png" HeightRequest="50" />  
  11.         <Button Text="Yahoo" Clicked="LoginClick" Image="YAHOO.png" HeightRequest="50" />  
  12.         <Button Text="DropBox" Clicked="LoginClick" Image="DROPBOX.png" HeightRequest="50" />  
  13.         <Button Text="LinkedIn" Clicked="LoginClick" Image="LINKEDIN.png" HeightRequest="50" />  
  14.         <Button Text="Flicker" Clicked="LoginClick" Image="FLICKER.png" HeightRequest="40" />  
  15.         <Button Text="Twitter" Clicked="LoginClick" Image="MICROSOFT.png" HeightRequest="40" /> </StackLayout>  
  16. </ContentPage>  
LoginPage.Xaml.CS

Add LoginClick event in login page code behind the file and sender object will return the button text name (eg:Facebook,Twitter..etc).
  1. using System;  
  2. using Xamarin.Forms;  
  3. namespace DevEnvExeLogin {  
  4.     public partial class LoginPage: ContentPage {  
  5.         public LoginPage() {  
  6.             InitializeComponent();  
  7.         }  
  8.         void LoginClick(object sender, EventArgs args) {  
  9.             Button btncontrol = (Button) sender;  
  10.             string providername = btncontrol.Text;  
  11.             if (OAuthConfig.User == null) {  
  12.                 Navigation.PushModalAsync(new ProviderLoginPage(providername));  
  13.                 //Need to create ProviderLoginPage so follow Step 4 and Step 5  
  14.             }  
  15.         }  
  16.     }  
  17. }  
Step 4 - Create Identity Provider Login Page

As we will be having platform-specific LoginPage implementation of Xamarin.Auth, we don't need any specific implementation in the portable project.

We do need to add an empty ProviderLoginPage which will be resolved at runtime and substituted by actual implementation regarding this will explain on step 5.

Right Click Portable Project - Add New Item Select Xaml page (ProviderLoginPage.Xaml )
  1. using Xamarin.Forms;  
  2. namespace DevEnvExeLogin {  
  3.     public partial class ProviderLoginPage: ContentPage {  
  4.         //we will refer providename from renderer page  
  5.         public string ProviderName {  
  6.             get;  
  7.             set;  
  8.         }  
  9.         public ProviderLoginPage(string _providername) {  
  10.             InitializeComponent();  
  11.             ProviderName = _providername;  
  12.         }  
  13.     }  
  14. }  
** In Xaml page,  you need to make no changes.

Step 5: Create Platform Specific Login Renderer

Create Platform

We need to create platform-specific LoginRenderer Page. So, you have to create platform-specific Login page (loginRenderer.CS) to iOS, Android, and UWP projects.

We need to add LoginPageRenderer which will be used by Xamarin.Auth to display the webView for OAuth Login Page

Code Snippet Explanation

The below code is for Xamarin.Forms Dependency Service which maps ProviderLoginPage to LoginRenderer.
  1. [assembly: ExportRenderer(typeof(ProviderLoginPage), typeof(LoginRenderer))]  
  2.   
  3.   
  4. Get Identity ProviderName from Providerloginpage  
  5. var loginPage = Element as ProviderLoginPage;  
  6. string providername = loginPage.ProviderName;  
Create OAuthProviderSetting class from Portable Class Library with OAuth Implementation. It is explained in Step 6.
  1. //Create OauthProviderSetting class with Oauth Implementation .Refer Step 6  
  2. OAuthProviderSetting oauth = new OAuthProviderSetting();  
  3. var auth = oauth.LoginWithProvider(providername);  
  4. Create Oauth event  
  5. for provider login completed and canceled.  
  6. auth.Completed += (sender, eventArgs) => {  
  7.         if (eventArgs.IsAuthenticated) { //Login Success }  
  8.             else {  
  9.                 // The user cancelled  
  10.             }  
  11.         };  
If you want to get and save user info. You can create UserEntity from Portable Library and refer the below code.
  1. namespace DevEnvExeLogin {  
  2.     public class UserDetails {  
  3.         public string TwitterId {  
  4.             get;  
  5.             set;  
  6.         }  
  7.         public string Name {  
  8.             get;  
  9.             set;  
  10.         }  
  11.         public string ScreenName {  
  12.             get;  
  13.             set;  
  14.         }  
  15.         public string Token {  
  16.             get;  
  17.             set;  
  18.         }  
  19.         public string TokenSecret {  
  20.             get;  
  21.             set;  
  22.         }  
  23.         public bool IsAuthenticated {  
  24.             get {  
  25.                 return !string.IsNullOrWhiteSpace(Token);  
  26.             }  
  27.         }  
  28.     }  
  29. }  
LoginRenderer.CS
  1. using Android.App;  
  2. using Xamarin.Forms.Platform.Android;  
  3. using DevEnvExeLogin;  
  4. using Xamarin.Forms;  
  5. using DevEnvExeLogin.Droid.PageRender;  
  6. [assembly: ExportRenderer(typeof(ProviderLoginPage), typeof(LoginRenderer))]  
  7. namespace DevEnvExeLogin.Droid.PageRender {  
  8.     public class LoginRenderer: PageRenderer {  
  9.         bool showLogin = true;  
  10.         protected override void OnElementChanged(ElementChangedEventArgs < Page > e) {  
  11.             base.OnElementChanged(e);  
  12.             //Get and Assign ProviderName from ProviderLoginPage  
  13.             var loginPage = Element as ProviderLoginPage;  
  14.             string providername = loginPage.ProviderName;  
  15.             var activity = this.Context as Activity;  
  16.             if (showLogin && OAuthConfig.User == null) {  
  17.                 showLogin = false;  
  18.                 //Create OauthProviderSetting class with Oauth Implementation .Refer Step 6  
  19.                 OAuthProviderSetting oauth = new OAuthProviderSetting();  
  20.                 var auth = oauth.LoginWithProvider(providername);  
  21.                 // After facebook,google and all identity provider login completed   
  22.                 auth.Completed += (sender, eventArgs) => {  
  23.                     if (eventArgs.IsAuthenticated) {  
  24.                         OAuthConfig.User = new UserDetails();  
  25.                         // Get and Save User Details   
  26.                         OAuthConfig.User.Token = eventArgs.Account.Properties["oauth_token"];  
  27.                         OAuthConfig.User.TokenSecret = eventArgs.Account.Properties["oauth_token_secret"];  
  28.                         OAuthConfig.User.TwitterId = eventArgs.Account.Properties["user_id"];  
  29.                         OAuthConfig.User.ScreenName = eventArgs.Account.Properties["screen_name"];  
  30.                         OAuthConfig.SuccessfulLoginAction.Invoke();  
  31.                     } else {  
  32.                         // The user cancelled  
  33.                     }  
  34.                 };  
  35.                 activity.StartActivity(auth.GetUI(activity));  
  36.             }  
  37.         }  
  38.     }  
  39. }  
Step 6: OAuth Implementation

The OAuth2Authenticator class is responsible for managing the user interface and communicating with authentication services. It will support all the identity providers. 

But, in Twitter, OAuth authentication will support only on OAuth1Authenticator. So, you can use OAuth1Authenticator instead of OAuth2Authenticator.

The OAuth2Authenticator and OAuth1Authenticator class requires a number of parameters, as shown in the following list. 
  • Client ID – Identity provider client ID. While registering the app, you will need unique Client ID.
  • Client Secret – identifies the client that is making the request. While registering the app, you will need unique Client Secret
  • Scope – identifies the API access being requested by the application, and the value informs the consent screen that is shown to the user.
  • Authorize URL – identifies the URL where the authorization code will be obtained from.
  • Redirect URL –  identifies the URL where the response will be sent. The value of this parameter must match one of the values that appear in the Credentials page of the project.
  • AccessToken URL —  identifies the URL used to request access tokens after an authorization code is obtained.

    Step 6.1: Access GOOGLE Account
    1. var googleauth = new OAuth2Authenticator(  
    2. // For Google login, for configure refer http://www.c-sharpcorner.com/article/register-identity-provider-for-new-oauth-application/  
    3. "ClientId",  
    4. "ClientSecret",  
    5. // Below values do not need changing  
    6. "https://www.googleapis.com/auth/userinfo.email",  
    7. new Uri("https://accounts.google.com/o/oauth2/auth"),  
    8. new Uri("http://www.devenvexe.com"),// Set this property to the location the user will be redirected too after successfully authenticating  
    9. new Uri("https://accounts.google.com/o/oauth2/token")  
    10. );  
    Step 6.2: Access FACEBOOK Account
    1. var OauthFacebook = new OAuth2Authenticator(  
    2. clientId: "MyAppId"// For Facebook login, for configure refer http://www.c-sharpcorner.com/article/register-identity-provider-for-new-oauth-application/  
    3. scope: "",  
    4. authorizeUrl: new Uri("https://m.facebook.com/dialog/oauth/"), // These values do not need changing  
    5. redirectUrl: new Uri("http://www.facebook.com/connect/login_success.html")// These values do not need changing  
    6. );  
    Step 6.3: Access TWITTER Account
    1. OAuth1Authenticator auth = new OAuth1Authenticator(  
    2. consumerKey: "*****"// For Twitter login, for configure refer http://www.c-sharpcorner.com/article/register-identity-provider-for-new-oauth-application/  
    3. consumerSecret: "****"// For Twitter login, for configure refer http://www.c-sharpcorner.com/article/register-identity-provider-for-new-oauth-application/  
    4. requestTokenUrl: new Uri("https://api.twitter.com/oauth/request_token"), // These values do not need changing  
    5. authorizeUrl: new Uri("https://api.twitter.com/oauth/authorize"), // These values do not need changing  
    6. accessTokenUrl: new Uri("https://api.twitter.com/oauth/access_token"), // These values do not need changing  
    7. callbackUrl: new Uri("http://www.devenvexe.com") // Set this property to the location the user will be redirected too after successfully authenticating  
    Step 6.4 Access Microsoft Account
    1. var OauthMicrosoft = new OAuth2Authenticator(  
    2. clientId: "MY ID"// For Micrsoft login, for configure refer http://www.c-sharpcorner.com/article/register-identity-provider-for-new-oauth-application/  
    3. scope: "bingads.manage",  
    4. authorizeUrl: new Uri("https://login.live.com/oauth20_authorize.srf?client_id=myid&scope=bingads.manage&response_type=token&redirect_uri=https://login.live.com/oauth20_desktop.srf"),  
    5. redirectUrl: new Uri("https://adult-wicareerpathways-dev.azurewebsites.net/Account/ExternalLoginCallback")  
    6. );  
    Step 6.5 Access LINKEDIN Account
    1. var authLinkediN = new OAuth2Authenticator(  
    2. clientId: "**",// For LinkedIN login, for configure refer http://www.c-sharpcorner.com/article/register-identity-provider-for-new-oauth-application/  
    3. clientSecret: "**",  
    4. scope: "",  
    5. authorizeUrl: new Uri("https://www.linkedin.com/uas/oauth2/authorization"),  
    6. redirectUrl: new Uri("http://devenvexe.com/"),  
    7. accessTokenUrl: new Uri("https://www.linkedin.com/uas/oauth2/accessToken")  
    Step 6.6 Access GITHUB Account
    1. auth = new OAuth2Authenticator(  
    2. // For GITHUB login, for configure refer http://www.c-sharpcorner.com/article/register-identity-provider-for-new-oauth-application/  
    3. "ClientId",  
    4. "ClientSecret",  
    5. // Below values do not need changing  
    6. "",  
    7. new Uri("https://github.com/login/oauth/authorize"),  
    8. new Uri("http://www.devenvexe.com"),// Set this property to the location the user will be redirected too after successfully authenticating  
    9. new Uri("https://github.com/login/oauth/access_token")  
    10. );  
    Step 6.7 Access FLICKER Account
    1. auth = new OAuth2Authenticator(  
    2. // For Flicker login, for configure refer http://www.c-sharpcorner.com/article/register-identity-provider-for-new-oauth-application/  
    3. "ClientId",  
    4. "ClientSecret",  
    5. // Below values do not need changing  
    6. "",  
    7. new Uri("https://www.flickr.com/services/oauth/request_token"),  
    8. new Uri("http://www.devenvexe.com"),// Set this property to the location the user will be redirected too after successfully authenticating  
    9. new Uri("http://www.flickr.com/services/oauth/access_token")  
    10. );  
    Step 6.8 Access YAHOO Account
    1. auth = new OAuth2Authenticator(  
    2. // For Yahoo login, for configure refer http://www.c-sharpcorner.com/article/register-identity-provider-for-new-oauth-application/  
    3. "ClientId",  
    4. "ClientSecret",  
    5. // Below values do not need changing  
    6. "",  
    7. new Uri("https://api.login.yahoo.com/oauth2/request_auth"),  
    8. new Uri("http://www.devenvexe.com"),// Set this property to the location the user will be redirected too after successfully authenticating  
    9. new Uri("https://api.login.yahoo.com/oauth2/get_token")  
    10. );  

You can download the source code and replace the Client ID or AppID and Client secret.

OUTPUT

OUTPUT

OUTPUT