Using Xamarin.Auth with Xamarin.Forms

DavidTavarezDavidTavarez DOMember ✭✭✭

How you can use Xamarin.Auth when you're using Xamarin.Forms?

I have this:

async public System.Threading.Tasks.Task<bool> LoginWithFacebook (object dialog, string FacebookAppID)
        {
            var user = new ParseUser ();
            var auth = new OAuth2Authenticator (
                           clientId: FacebookAppID,
                           scope: "",
                           authorizeUrl: new Uri ("https://m.facebook.com/dialog/oauth/"),
                           redirectUrl: new Uri ("http://www.facebook.com/connect/login_success.html"));
            auth.AllowCancel = true;
            // If authorization succeeds or is canceled, .Completed will be fired.
            auth.Completed += async (object sender, AuthenticatorCompletedEventArgs ee) => {

                // Now that we're logged in, make a OAuth2 request to get the user's info.
                var accessToken = ee.Account.Properties ["access_token"].ToString ();
                var expiresIn = Convert.ToDouble (ee.Account.Properties ["expires_in"]);
                var expiryDate = DateTime.Now + TimeSpan.FromSeconds (expiresIn);

                // Now that we're logged in, make a OAuth2 request to get the user's id.
                var request = new OAuth2Request ("GET", new Uri ("https://graph.facebook.com/me"), null, ee.Account);
                var response = await request.GetResponseAsync ();
                var obj = JObject.Parse (response.GetResponseText ());
                var id = obj ["id"].ToString ().Replace ("\"", ""); // Id has extraneous quotation marks
                user = await ParseFacebookUtils.LogInAsync (id, accessToken, expiryDate);

            };
            var dvc = ((DialogViewController)dialog);
            dvc.PresentViewController (auth.GetUI (), true, null);  
            return user.IsAuthenticated;
        }

But I can't cast ContentPage to DialogViewController or an Activity

Best Answer

«1

Answers

  • JosephSauveJosephSauve USMember ✭✭

    In your core Xamarin.Forms PCL library, create an empty LoginPage class:

    public class LoginPage : ContentPage
    {
    
    }
    

    In your Xamarin.Forms iOS app, create a LoginPageRenderer class:

    [assembly: ExportRenderer (typeof (LoginPage), typeof (LoginPageRenderer))]
    
    namespace Demo.XForms.iOS
    {
        public class LoginPageRenderer : PageRenderer
        {
            public override void ViewDidAppear (bool animated)
            {
                base.ViewDidAppear (animated);
    
                // I've used the values from your original post
                var auth = new OAuth2Authenticator (
                    clientId: FacebookAppID,
                    scope: "basic",
                    authorizeUrl: new Uri ("https://m.facebook.com/dialog/oauth/"),
                    redirectUrl: new Uri ("http://www.facebook.com/connect/login_success.html"));
    
                auth.Completed += (sender, eventArgs) => {
                    // We presented the UI, so it's up to us to dismiss it on iOS.
                    DismissViewController (true, null);
                    // you may want to also do something to dismiss THIS viewcontroller, 
                    // or else you'll keep seeing the login screen              
    
                    if (eventArgs.IsAuthenticated) {
                        // Use eventArgs.Account to do wonderful things
                        // ...such as saving the token, and then getting some more detailed user info from the API
                        App.SaveToken(eventArgs.Account.Properties["access_token"]);
                    } else {
                        // The user cancelled
                    }
                };
    
                PresentViewController (auth.GetUI (), true, null);
            }
        }
    }
    

    Note the importance of...

    [assembly: ExportRenderer (typeof (LoginPage), typeof (LoginPageRenderer))]
    

    ...immediately before the namespace declaration of the LoginPageRenderer class.

    In your App class in the Xamarin.Forms PCL library, your GetMainPage() method might look something like this:

    public static Page GetMainPage ()
    {   
        return new LoginPage ();
    }
    

    It'll actually probably be more complex, checking for whether or not a user is already authenticated or not, but I've left it simple, just to illustrate the basics. This is working for me with Xamarin.Auth and Instagram.

  • DavidTavarezDavidTavarez DOMember ✭✭✭

    @jsauve‌ thanks!! :D

  • JadenRogers.0147JadenRogers.0147 NZMember ✭✭

    Thanks that also helped with an issue I was having, how do you take it further though?

    I have a library which OAuth sits at the core of it (Xamarin.Auth), what is the best way to just instantiate that part on each platform, and then use the methods as normal without using OAuth directly.

    I was thinking of just having a "GetOAuth" method in a interface and then implement an override for it on each platform... the other issue though is the return type of the interface would have to be object as I can't reference "OAuth1Authenticator" and just cast it.

    Is that the right way to go about it, is there a better way?

  • EdHubbellEdHubbell USMember ✭✭

    I've forked the github repo @jsauve posted (thanks!) to use Azure AD authentication. It required overriding some Xamarin.Auth methods (along with much pulling of hair and late night searching). Take a look here - https://github.com/EdHubbell/OAuthTwoDemo.XForms

    There are also a few updates in there that have to do with the latest version of Xamarin.Forms. I'm just starting out with Xamarin, so I am aware that I'm still doing it wrong - But hey, better than not doing it.

  • DavidTavarezDavidTavarez DOMember ✭✭✭

    If you're using Facebook you have to double PopAsync()

  • Hi @JoeSauve‌ ,@EdHubbel i need to use this iOS statement "DismissViewController (true, null);" in my android LoginPageRenderer. How I Can Dismiss this activity and return control to xamarin.forms LoginPage.

  • aaragaoaaragao BRMember
    edited December 2014

    Hi guys, I'm trying to use Xamarin.Auth with Xamarin.Forms using Facebook and it is displaying the redirect url (https://www.facebook.com/connect/login_success.html) with a plain white background and nasty red text "SECURITY WARNING: Please treat the URL above as you would your password and do not share it with anyone. See the Facebook Help Center for more information." on iOS. It keeps the user stuck on that page. And shows a popup message "Authentication Erro Expected access_token in response, but did not receive one.". Anyone can help me on this? Thanks.

  • @aaragao You need to hook into auth.Completed and call DismissViewController (see above code examples)

  • NickWilsonNickWilson USMember

    @aaragao‌ I had this same problem.. The solution for me was to use scope: "" like in @DavidTavarez‌'s example instead of scope: "basic" like in @JoeSauve.0077‌'s example.

  • EdHubbellEdHubbell USMember ✭✭

    I just published https://github.com/EdHubbell/XamarinFormsOauth2Demo, which uses an approach enabled by Xamarin.Forms 1.3.X. We set the MainPage property of the App object in order to set the current page.

    Feedback is welcome - Trying to get something implemented that is reliable and repeatable.

  • BrunoVTBrunoVT BEUniversity ✭✭

    Ok, so I also tried this code and it works. I have only one small bug. On the page I use after my login page I have a custom label that crashes on iOS with a nullreference exception in my ios labelrenderer.

    public class CustomLabel_iOS : LabelRenderer
        {
            protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
            {
                base.OnElementChanged(e);
    
                var view = (CustomLabel)Element;
    
                UpdateUi(view, Control);
                SetPlaceholder(view);
            }
    
            protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
            {
                base.OnElementPropertyChanged(sender, e);
    
                var view = (CustomLabel)Element;
    
                if (e.PropertyName == CustomLabel.MaxLinesProperty.PropertyName)
                {
                    SetPlaceholder(view);
                }
            }
    
            private void UpdateUi(CustomLabel view, UILabel control)
            {
                if (view.MaxLines > 0){
                    control.Lines = view.MaxLines;
                } else {
                    control.Lines = 1;
                }
            }
    
            private void SetPlaceholder(CustomLabel view)
            {
                LayoutSubviews();
            }
        }
    
  • Anyone gotten this to work on windows mobile ? If so is there a repository somewhere ?

  • KarthikMurugesan.1084KarthikMurugesan.1084 USMember, University

    Joe, I was looking at your blog post on using Xamarin.Auth with Xamarin.Forms. Great stuff! Just curious if I'll still need the LoginPageRenderer part if I am not using Facebook or Google and have my own simple oAuth server that just expects a token in the authorization header. In this case I just want to use Xamarin.Auth to store and retrieve Account information securely. I'd really appreciate any tips on how to use Xamarin.Auth with Xamarin.Forms just to store and retrieve Account object.

  • OswaldoCotesOswaldoCotes USMember

    Hi @jsauve, @EdHubbell‌ , I need to use this iOS statement "DismissViewController (true, null)" in my Android LoginPagerender.

    protected override void OnElementChanged (ElementChangedEventArgs e)
    {
    base.OnElementChanged(e);
    var activity = this.Context as Activity;
    if (!done) {
    client.LoginAsync (this.Context) // current controller
    .ContinueWith (
    task => this.ShowResult (task),
    this.scheduler);
    done = true;
    }
    }
    private void ShowResult(Task taskResult)
    {
    Exception error = taskResult.Exception != null ? taskResult.Exception.Flatten () : null;
    if (error == null && taskResult.IsCanceled) {
    error = new Exception ("Authentication was canceled.");
    }

            if (error == null) {
                //// I want to dismiss this activity!!!!
                App.EmailAuth0 = taskResult.Result.Profile ["email"].ToString();
                App.LoginInfo = taskResult.Result.Profile.ToString ();
    
            }
    

    }

  • OswaldoCotesOswaldoCotes USMember

    Hi @jsauve, @EdHubbell‌ , I need to use this iOS statement "DismissViewController (true, null)" in my Android LoginPagerender.

    protected override void OnElementChanged (ElementChangedEventArgs e)
    {
    base.OnElementChanged(e);
    var activity = this.Context as Activity;
    if (!done) {
    client.LoginAsync (this.Context) // current controller
    .ContinueWith (
    task => this.ShowResult (task),
    this.scheduler);
    done = true;
    }
    }
    private void ShowResult(Task taskResult)
    {
    Exception error = taskResult.Exception != null ? taskResult.Exception.Flatten () : null;
    if (error == null && taskResult.IsCanceled) {
    error = new Exception ("Authentication was canceled.");
    }

            if (error == null) {
                //// I want to dismiss this activity!!!!
                App.EmailAuth0 = taskResult.Result.Profile ["email"].ToString();
                App.LoginInfo = taskResult.Result.Profile.ToString ();
    
            }
    

    }

  • Daniel.9388Daniel.9388 USMember

    @KarthikMurugesan.1084 Did you get an answer to your question ? I got the same case : I have a custom server and just want to use OAuth for the connexion (credentials, permissions) and get some data.

    Since I want to only do the OAuth authentication, is it the only way to do it ? I mean : Create a PageRenderer, code for each platform, etc. Or am I using an "overkill" component ?

  • ClarkRensberryClarkRensberry CAMember, University

    Daniel - I'm going to be doing something very similar shortly and reading up on it. I noticed that the Xamarin-store-app example they provide does this authentication in a shared library - thus bypassing the need for special code on each platform. I may try that idea to work in a fresh new 3 platform Xamarin forms solution in Visual Studio. I'd be curious to know if anyone has tried this approach. Now off to research the server side of it...

  • Daniel.9388Daniel.9388 USMember

    @northberry : You can look at the source code for Xamarin.Auth and use this component by referencing the project directly in your solution. This way, you can change some code to be less platform specific, but it takes a lot of time and work to have something generic.

    Personnaly, I did not use Xamarin.Auth finally and preferred the HttpClient way in Visual Studio, just because you don't have constraints about passing Android properties to the shared project. It has been much easier working with HttpClient and doing "manual" requests to the server, retrieving the account informations, etc. just because managing the renderer was too "heavy" for me.

    A good thing is that you can use Xamarin.Auth just for the authentication and retrieving the account data. After that, you can manage yourself the requests and keep it in the shared project. I don't know if I gave you a kind of answer, tell me if you need some more information about what I have done ;)

  • SaggySaggy USMember
    edited May 2015

    HI Guys,

    I need help or suggestion for implement the functionality of login and suggestion am using OAuth2Request for facebook login authentication, and i am successfully implemented it, but i need to get the user email ID in response, and Does any body now how to add the facebook permissions in OAuth2Request for getting such facebook response..?
    i am trying to implementing on android this functionality
    Any type of help will be appreciated..

  • ZacharyCamaraZacharyCamara USMember

    @Saggy In order to request additional permissions, you need to modify the scope of your OAuth2Request

    scope: "email", // the scopes for the particular API you're accessing, delimited by "+" symbols

    will give you access to user emails

  • MalikKhanMalikKhan USMember, University

    I need to authenticate users against a adfs server and login to the app. And there are some Web api which needs to be called from the app which needs this token.. Can someone help me.. With a sample.. I am unable to add the xamarin. Auth to my forms app it's says not compatible.. Any help and pointers are greatly appreciated

  • tohweitohwei USMember ✭✭

    Hi there,

    May I know how to handle OnCancelled?
    Or... when user click 'Cancel' ?

  • JoshuaNovakJoshuaNovak USMember ✭✭

    Is there a way to call the Auth view on click?

  • @JoeSauve
    I have execute your instagram demo program of github in visual studio but i got an error in Resource.Designer.cs file.

    Number of Error 1095

    one of sample line of error

    'Resource.Style' does not contain a definition for 'Widget_Design_TextInputLayout'  OAuthTwoDemo.XForms.Android D:\Received\OAuthTwoDemo.XForms-master (1)\OAuthTwoDemo.XForms-master\Android\Resources\Resource.designer.cs
    
  • MichelangeloFrancoMichelangeloFranco ITUniversity ✭✭

    Any example for twitter? I try using oauth1 but when I insert my login an password I'm redirect to twitter timeline instead of page of my App

  • dlo3dlo3 USMember

    Hello. I know this is an old thread, but it's pretty relevant to an issue I'm having.

    I'm using Xamarin.Auth with an Xamarin.Forms application, currently working on the Android platform to authenticate a Facebook login. I created my own login flow similar to Joe's, only different in a few unimportant aspects. I have this in my Droid PageRenderer subclass in the OnElementChanged(... e) method:

    var authenticator = new OAuth2Authenticator( clientId: MyAppId, scope: "", authorizeUrl: new Uri("https://m.facebook.com/dialog/oauth/"), redirectUrl: new Uri("http://www.facebook.com/connect/login_success.html") );

    I then go on to add the Completed event handler as normal, and then start the activity via,

    activity.StartActivity(authenticator.GetUI(activity));

    This should work fine, but when I test my button view that calls the authentication page, I get this:

    http://imgur.com/a/bg9p1 (sorry, image wasn't loading in post)

    I've added the redirect URL properly to my Client OAuth settings on my Facebook App Dashboard, so I don't think that's the issue... Really not sure what's going on. Would be grateful if anyone could help out.

    Thanks,
    Dave

  • ChristopherDrososChristopherDrosos GRMember ✭✭
    edited November 2016

    I have an issue with xamarin.auth too. while it is logging in the user i cant display a loading message, please check here for more info: http://stackoverflow.com/questions/40529682/making-a-prettier-facebook-login-screen-for-parse-com-server-with-xamarin-androi
    Also i get a bloody success message sometimes from login_success.html which i dont understand why
    thanks

  • foluisfoluis USMember ✭✭

    How can I sign out of AAD?

  • rafaelbparafaelbpa BRMember ✭✭

    @JosephSauve said:
    I've provided a much better example on Stack Overflow and on my blog.

    Heys, guys. Can someone help me?

    I am developing a xamarin forms app and I am trying to authenticate a user with xamarin auth (facebook login). Everything is running perfectly on iOS, but on Android I'm getting this error:

    "Android.Content.ActivityNotFoundException has been thrown
    Unable to find explicit activity class {com.rafaelbpa/md550f8a10a740eb4fb6376baab8337ce22.WebAuthenticatorActivity}; have you declared this activity in your AndroidManifest.xml?"

    when the code reach this line: activity.StartActivity (auth.GetUI(activity));

    I'm following Joe Sauve steps.

    Am I missing something? Thanks.

  • moljacmoljac HRBeta ✭✭✭

    @rafaelbpa

    version? I think I need more info. Smells like 1.4.0.Bump to 1.4.1 of go for 1.5.0-alpha-*

    For more info go here:

    Xamarin community slack team and #xamarin-auth-social channel

    https://xamarinchat.slack.com/messages/C4TD1NHPT/

    Samples with highest update cadence (those are samples from Xamarin.Auth repo, but extracted for easier maintenace)

    https://github.com/moljac/Xamarin.Auth.Samples.NugetReferences

  • MartinGiannechiniMartinGiannechini USMember ✭✭

    @MichelangeloFranco hey man, I'm having the same problem as you, Can you resolve it? Thanks

  • NitishSharmaNitishSharma USMember ✭✭

    @JosephSauve Thanks. :smile:

  • MuratSavasMuratSavas USMember ✭✭

    Hi,
    I started to get Authentication Error "An SSL error has occured and a secure connection to the server cannot be made" when trying to login via Facebook. I am using Xamarin.Auth.iOS through Xamarin Forms App.
    I tried to change Info plist and set;
    NSAppTransportSecurity
    NSAllowsArbitraryLoads (true)
    but it also did not work for me.
    Any idea?
    Thanks

  • SunnyKhan.3452SunnyKhan.3452 USMember ✭✭

    Hello guys, I have implemented facebook and gmail login and now would like to know how to sign out user from both accounts and also implement a functionality similar to "Remember Me", so that user won't be directed to sign page again. Also, is there a way to do this using Xamarin.Auth because in it other configuration are pretty much straight forward.

  • SunnyKhan.3452SunnyKhan.3452 USMember ✭✭
    edited December 2017

    Hi all, I would like to update on my previous comment. I have managed to get "Remember Me" functionality done using the below steps:-

    Save the data in a store

    Account account = new Account();
    AccountStore.Create(this).Save(account, "Gmail");
    

    Fetch the saved data from a store

    var cache = AccountStore.Create().FindAccountsForService("Gmail").FirstOrDefault();

    Delete the data from the store

     AccountStore.Create(this).Delete(cache, "Gmail");  
    

    If anyone needs any help, here is the link:- https://wtcindia.wordpress.com/2017/01/05/xamarin-mobile-apps-authentication-using-xamarin-auth-gmail/

    Hope this helps someone.

    Also, for logout, I am going to use Delete the cache and then navigate to LoginPage manually. This is a workaround but still I would like to know if anyone can provide a proper solution for "Logout" functionality.

  • Is there WhatsApp auth?
  • moljacmoljac HRBeta ✭✭✭

    @WaleedMohamed.9053

    WhatsApp does support OAuth. Ping me if you find something

Sign In or Register to comment.