How to get accesstoken from Xamarin Auth - Google

601 Views Asked by At

I am trying to get auth token from 0auth2 in the android app. The issue is once i sign, in the app is restaring because of the redirect url but I am not getting any auth token from the intent once the app is restarted.

code

var authenticator = new OAuth2Authenticator(ClientID, ClientSecret, Scope, new Uri("https://accounts.google.com/o/oauth2/auth"),
                new Uri("com.app.abcd:/oauthredirect"), new Uri("https://oauth2.googleapis.com/token"), null, true);
 authenticator.Completed += OnAuthCompleted;
                authenticator.Error += OnAuthError;
                var presenter = new Xamarin.Auth.Presenters.OAuthLoginPresenter();
                presenter.Login(authenticator);

 private async void OnAuthCompleted(object sender, AuthenticatorCompletedEventArgs e)
        {
            var authenticator = sender as OAuth2Authenticator;
            if (authenticator != null)
            {
                authenticator.Completed -= OnAuthCompleted;
                authenticator.Error -= OnAuthError;
            }

            IsAuthorized = e.IsAuthenticated;
            //User user = null;
            if (e.IsAuthenticated)
            {}
}

Android

[Activity(Label = "ABCD", MainLauncher = true, LaunchMode = LaunchMode.SingleTask, ConfigurationChanges = ConfigChanges.ScreenSize, ScreenOrientation = ScreenOrientation.Portrait)]
    [IntentFilter(new[] { Intent.ActionView },
              Categories = new[] { Intent.CategoryBrowsable, Intent.CategoryDefault },
        //DataScheme = "abcd",
         DataSchemes = new[] { "com.app.abcd" },
               DataPath = "/oauthredirect",
              AutoVerify = true)]

    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
    {

protected override void OnCreate(Bundle bundle)
        {
            base.SetTheme(Resource.Style.MainTheme);
                base.OnCreate(bundle);
                DependencyService.Register<ChromeCustomTabsBrowser>();
                CrossCurrentActivity.Current.Activity = this;

                TabLayoutResource = Resource.Layout.Tabbar;
                ToolbarResource = Resource.Layout.Toolbar;

                global::Xamarin.Forms.Forms.Init(this, bundle);
                LoadApplication(new App());
        }
protected override void OnNewIntent(Intent intent)
        {
            base.OnNewIntent(intent);
            //HandleNotificationIntent(intent);
        }

        protected override void OnRestart()
        {
            var intent = this.Intent;
            base.OnRestart();
        }
}

When i run this code and presenter.Login(authenticator);is called i can see the google authenticates the user and OnNewIntent is called and app is restarted and OnAuthCompleted is never called and I am not able to get the access token.

Is this the right way to get accesstoken form 0auth2 or am i missing something? can anyone help me with this.

1

There are 1 best solutions below

0
TheDeveloper On BEST ANSWER

I found the solution. Check out the example here.

Common Code:

 private void Authenticate()
        {
            var authenticator = new OAuth2Authenticator(ClientID, ClientSecret, Scope, new Uri("https://accounts.google.com/o/oauth2/auth"),
                            new Uri("com.app.abcd:/oauthredirect"), new Uri("https://oauth2.googleapis.com/token"), null, true);
            authenticator.Completed += OnAuthCompleted;
            authenticator.Error += OnAuthError;
            var presenter = new Xamarin.Auth.Presenters.OAuthLoginPresenter();
            presenter.Login(authenticator);
        }

        private async void OnAuthCompleted(object sender, AuthenticatorCompletedEventArgs e)
        {
            var authenticator = sender as OAuth2Authenticator;
            if (authenticator != null)
            {
                authenticator.Completed -= OnAuthCompleted;
                authenticator.Error -= OnAuthError;
            }

            IsAuthorized = e.IsAuthenticated;
            //User user = null;
            if (e.IsAuthenticated)
            {
                var access_token = e.Account.Properties["access_token"];
                var expires_in = e.Account.Properties["expires_in"];
                var refresh_token = e.Account.Properties["refresh_token"];
            }
        }

ANDROID: Create a new activity:

[Activity(Label = "ActivityCustomUrlSchemeInterceptor", NoHistory = true, LaunchMode = LaunchMode.SingleTop)]
    [IntentFilter(
        new[] { Intent.ActionView },
        Categories = new[] { Intent.CategoryDefault, Intent.CategoryBrowsable },
        DataSchemes = new[] { "com.app.abcd" },
        DataPath = "/oauthredirect")]
    public class ActivityCustomUrlSchemeInterceptor : Activity
    {
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
            global::Android.Net.Uri uri_android = Intent.Data;

            // Convert Android.Net.Url to Uri
            var uri = new Uri(uri_android.ToString());
            // Close browser 
            var intent = new Intent(this, typeof(MainActivity));
            //intent.SetFlags(ActivityFlags.ClearTop | ActivityFlags.SingleTop);
            StartActivity(intent);

            // Load redirectUrl page
            // if the code below isn't accessible, pass `authenticator`
            // created in the common code here which has `OnPageLoading(uri);` method 
           OAuthAuthenticatorHelper.AuthenticationState.OnPageLoading(uri);
            this.Finish();
        }
    }

iOS

Add couple of lines in OpenUrl to handle the url redirect

public override bool OpenUrl(UIApplication application, NSUrl url, string sourceApplication, NSObject annotation)
        {
            // Convert iOS NSUrl to C#/netxf/BCL System.Uri - common API
            Uri uri_netfx = new Uri(url.AbsoluteString);

            // load redirect_url Page for parsing
            OAuthAuthenticatorHelper.AuthenticationState.OnPageLoading(uri_netfx);

            return true;
        }

In info.plist add the urlscheme of the package name:

<key>CFBundleURLSchemes</key>
            <array>
              <string>com.app.abcd</string>
            </array>