2
  • I have a MainPage in PCL which then navigates to a Platform Specific Login Page on LoginButton Click Event
  • The LoginPage is inherited from platform specific PageRenderer as it needs platform specific Authentication to Social Providers (Facebook, Google, Twitter, Microsoft, etc.)
  • I am using Xamarin.Auth to do the authentication.
  • Inside the OnElementChanged event of the LoginPage, it instantiates the OAuth2Authenticator object.
  • Upon successful instantiation (based on provider and app details), it needs to call the UI of the specific provider.
  • To do that, I call the auth.GetUI where auth is Xamarin.Auth.OAuth2Authenticator object.

I have two questions:

  1. In UWP, how do I navigate to the provider login UI? More specifically, what is the equivalent in UWP of the following code snippets in iOS and Android? In iOS, the following code is used: PresentViewController(auth.GetUI(), true, null); where auth is Xamarin.Auth.OAuth2Authenticator object. In Android the following is used: activity.StartActivity(auth.GetUI(activity));

I am looking for the equivalent code in UWP. Please bear in mind that these calls are made from the LoginPage which is derived from Platform specific PageRenderer

  1. How do I navigate back to my MainPage (which is in PCL) upon successful authentication?

The code is based off of a sample from the following source: http://www.c-sharpcorner.com/article/oauth-login-authenticating-with-identity-provider-in-xamarin-forms/

Here is my code for the LoginPage:

using System;
using Valufy;
using Xamarin.Forms.Platform.UWP;
using System.ComponentModel;
using Valufy.UWP;
using Valufy.AuthConfiguration;
using Xamarin.Forms;
[assembly: ExportRenderer(typeof(ProviderLoginPage), typeof(LoginRenderer))]

namespace Valufy.UWP
{
class LoginRenderer: PageRenderer
{
protected override void OnElementChanged (ElementChangedEventArgs<Xamarin.Forms.Page> e)
{
    base.OnElementChanged(e);

    //Get and Assign ProviderName from ProviderLoginPage
    ProviderLoginPage loginPage = (ProviderLoginPage)Element;
    string providername = loginPage.ProviderName;

        //Create OauthProviderSetting class with Oauth Implementation .Refer Step 6
        OAuthProviderSetting oauth = new OAuthProviderSetting();

            Xamarin.Auth.OAuth2Authenticator auth = oauth.LoginWithProvider(providername);  

            // After facebook,google and all identity provider login completed 
            auth.Completed += Auth_Completed;

            Type page_type = auth.GetUI();
//////THIS IS WHERE I AM STUCK...HOW DO I GO TO THE PROVIDER AUTH UI ////////////

//this.Frame.Navigate(page_type, auth);
//parentPage.Navigation.PushModalAsync(auth.GetUI());

            }

    }

    private void Auth_Completed(object sender, Xamarin.Auth.AuthenticatorCompletedEventArgs e)
    {
        if (e.IsAuthenticated)
        {
            OAuthConfig.User = new UserDetails();
            // Get and Save User Details 
            OAuthConfig.User.Token = e.Account.Properties["oauth_token"];
            OAuthConfig.User.TokenSecret = e.Account.Properties["oauth_token_secret"];
            OAuthConfig.User.TwitterId = e.Account.Properties["user_id"];
        OAuthConfig.User.ScreenName = e.Account.Properties["screen_name"];

/////NOW, HOW GO I GO BACK TO THE CALLING PAGE IN PCL ///////////////////

    }
    else
    {
        // The user cancelled
/////NOW, HOW GO I GO BACK TO THE CALLING PAGE IN PCL ///////////////////
}
}
}
}                
sidsud
  • 25
  • 9
  • The issue is well discussed and the solution posted [here](https://github.com/xamarin/Xamarin.Auth/issues/146) and [here](https://forums.xamarin.com/discussion/88969/navigating-from-platform-specific-uwp-pagerenderer-and-back-to-pcl-page#latest). Thank you for your reply @apineda. While your answer was not complete, it did help me to think in the right direction. – sidsud Mar 21 '17 at 19:46

2 Answers2

1

Here is the code to navigate to the provider login for UWP: WindowsPage windowsPage = new WindowsPage();

                _frame = windowsPage.Frame;
                if (_frame == null)
                {
                    _frame = new Windows.UI.Xaml.Controls.Frame
                    {
                        Language = global::Windows.Globalization.ApplicationLanguages.Languages[0]
                    };
                    windowsPage.Content = _frame;
                    SetNativeControl(windowsPage);
                }

                Type pageType = auth.GetUI();
                _frame.Navigate(pageType, auth);

To navigate back to my page upon successful authentication, here is the code:

private async void Auth_Completed(object sender, Xamarin.Auth.AuthenticatorCompletedEventArgs e)
    {
        if (e.IsAuthenticated)
        {

            var request = new OAuth2Request("GET", new Uri("https://login.microsoftonline.com/common/oauth2/V2.0/token?oauth2_access_token=" + e.Account.Properties["access_token"]), null, e.Account);
            try
            {
                string response = await MSGetUserInfo(e.Account);


            }
            catch (System.OperationCanceledException)
            {
                                }
            catch (Exception ex)
            {
                                }
            this.Element.Navigation.PushModalAsync(new MainPage());


        }
        else
        {
            // The user cancelled
        }
    }
sidsud
  • 25
  • 9
0

1- In UWP, how do I navigate to the provider login UI

You need to create a UWP Page object, the same object you are will use to display in the renderer is the one you will use to do the navigation.

Type page_type = auth.GetUI();

page = new MyUWPLoginPage();

page.Frame.Navigate(page_type, auth);

2- How do I navigate back to my MainPage (which is in PCL) upon successful authentication?

There are many ways to do this, the easiest one is creating a public method in your ProviderLoginPage class and from the renderer classes call this method and pass-in the parameters.

public class ProviderLoginPage: ContentPage
{
    ......

    public void AuthenticationCompleted(object sender, Xamarin.Auth.AuthenticatorCompletedEventArgs e)
    {
        // Do your logic
    }

}

In your Renderer using the Element:

private void Auth_Completed(object sender, Xamarin.Auth.AuthenticatorCompletedEventArgs e)
{
    var xamElement = Element as ProviderLogin;

    xamElement?.AuthenticationCompleted(sender, e);
}

Move all the logic to the PCL class so you don't have to repeat it on each renderer.

This should help.

pinedax
  • 9,246
  • 2
  • 23
  • 30
  • Thanks for your reply @apineda. My ProviderLoginPage is a Xamarin.Forms.Page object and it does not expose the Frame property. Also since I am already in the ProviderLoginPage, wouldn't I just use the "this" instead of creating a new object. In any case, I will have the same issue, i.e., the Frame property is not exposed. – sidsud Feb 20 '17 at 01:26
  • You misunderstood. For the navigation you need to create a UWP Page not talking about the Xamarin Page. You will create this object in the `LoginRenderer` class. – pinedax Feb 20 '17 at 01:30
  • I created a new UWP page in the UWP project. I instantiated it as you suggested. Here it is: Type page_type = auth.GetUI(); UWPLoginPage page = new UWPLoginPage(); page.Frame.Navigate(page_type, auth); The page type that I get is + page_type {Name = "WebAuthenticatorPage" FullName = "Xamarin.Auth.WebAuthenticatorPage"} System.Type {System.RuntimeType} The auth object is as follows: {Xamarin.Auth.OAuth2Authenticator} But I get an exception as follows: "Object reference not set to an instance of an object." – sidsud Feb 20 '17 at 01:46