Elegant Facebook Login For Desktop Application

Default facebook login page is usualy opened in new browser window or popup window, so user lose focus from your page. This application opens facebook login page within your flash application, so user will not lose your page. In fact little iframe trick is used.

This post connects my 3 previous posts: Flex IFrame – Web browser in flash, FacebookLogger and Facebook Extended Permissions With Authorization by Overriding Class in swc in order to create elegant solution for facebook connect with your desktop application (means outside facebook iframe or fbml). I recomend to read all previous mentioned posts before trying to run this app.

Final application (view source enabled)

FB class. Read more about FacebookLogger class here.

package
{
    import flash.net.URLRequest;
    import flash.net.URLVariables;
    
    import mx.core.Application;
    
    import sk.yoz.events.FacebookLoggerEvent;
    import sk.yoz.net.FacebookLogger;
    
    public class FB extends FacebookLogger
    {
        private static const SINGLETON_LOCK:Object = {};
        private static const _instence:FB = new FB(SINGLETON_LOCK);
        
        protected var API_KEY:String = "bc55511efba53af7a3529ea9e7d1989b";
        protected var APP_SECRET:String = "727616ab7a9acb969e7cec3c7de04d79";
        
        private var initCallback:Function;
        
        public function FB(lock:Object)
        {
            super();
            
            if(lock != SINGLETON_LOCK)
                throw new Error("Use FB.instance!");
            
            addEventListener(FacebookLoggerEvent.CONNECTED, loggerConnectedHandler)
        }
        
        public static function get instance():FB
        {
            return _instence;
        }
        
        public function init2(application:Application):void
        {
            if(public::connected)
                return;
            init(API_KEY, APP_SECRET, application.loaderInfo);
        }
        
        public function initWithCallback(application:Application, callback:Function):void
        {
            initCallback = callback;
            init2(application);
        }
        
        private function loggerConnectedHandler(event:FacebookLoggerEvent):void
        {
            if(initCallback != null)
                initCallback();
            initCallback = null;
            // now we are connected, your code may go here
        }
        
        public function openPopup(login_url:String, auth_token:String):void
        {
            var request:URLRequest = new URLRequest(login_url);
            var variables:URLVariables = new URLVariables();
                
            variables.req_perms = 'publish_stream';
            variables.api_key = facebook.api_key;
            variables.v = facebook.api_version;
            variables.auth_token = auth_token;
            variables.fbconnect = "true";
            variables.connect_display = "popup";
            
            request.data = variables;
            
            FacebookPopup.open(request);
        }
    }
}

DesktopSession class. Read more about Overriding Class in swc.

... some code ...

protected function onLogin(p_event:FacebookEvent):void {
	p_event.target.removeEventListener(FacebookEvent.COMPLETE, onLogin);
	
	if (p_event.success) {
		_auth_token = (p_event.data as StringResultData).value;
		
		FB.instance.openPopup(login_url, _auth_token);
		
		_waiting_for_login = true;
		dispatchEvent(new FacebookEvent(FacebookEvent.WAITING_FOR_LOGIN));
	} else {
		onConnectionError(p_event.error);
	}
}

... some code ...

FacebookPopup class. Read more about Flex IFrame.

<?xml version="1.0" encoding="utf-8"?>
<mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" 
    width="510" height="465" xmlns:html="sk.yoz.html.*" move="moveHandler()"
    title="Facebook login">
<mx:Script>
<![CDATA[
    import mx.core.Application;
    import mx.managers.PopUpManager;
    
    [Bindable]
    protected var url:String;
    
    [Bindable]
    protected var fb:FB = FB.instance;
    
    protected function moveHandler():void
    {
        iframe.positionChanged = true;
        iframe.invalidateProperties();
    }
    
    public function set request(value:URLRequest):void
    {
        var url:String = value.url;
        url += "?";
        for(var param:String in value.data)
            url += "&" + param + "=" + value.data[param];
        this.url = url;
    }
    
    public static function open(request:URLRequest):void
    {
        var window:FacebookPopup = new FacebookPopup();
        window.request = request;
        window.visible = true;
        PopUpManager.addPopUp(window, Application(Application.application));
        PopUpManager.centerPopUp(window);
    }
    
    protected function validateLogin():void
    {
        fb.validate();
        close();
    }
    
    protected function close():void
    {
        visible = false;
        PopUpManager.removePopUp(this);
    }
    
    protected function refresh():void
    {
        iframe.url = url;
    }
]]>
</mx:Script>
<html:IFrame width="100%" height="100%" id="iframe" autoResize="true" 
    url="{url}" visible="{visible}"/>
<mx:HBox width="100%">
    <mx:Text text="Clik Ok after you login to Facebook." />
    <mx:Spacer width="100%" />
    <mx:Label text="refresh" click="refresh()" textDecoration="underline" 
        buttonMode="true"/>
</mx:HBox>
<mx:HBox width="100%" horizontalAlign="center" >
    <mx:Button label="Ok" click="validateLogin()"/>
    <mx:Button label="Cancel" click="close()"/>
</mx:HBox>
</mx:TitleWindow>

Application (do not forget to add facebook flex .swc, version 3.4 used in example)

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
    import FB;
    
    [Bindable]
    private var fb:FB = FB.instance;
]]>
</mx:Script>
<mx:Button label="Facebook connect" click="fb.init2(this)"/>
<mx:Text text="{fb.connected ? 'connected' : 'not connected'}" />
</mx:Application>

Application html template. More about flexiframe.js here.

... some code ...
<script type="text/javascript" src="flexiframe.js"></script>
... some code ...

10 comments so far

  1. Tufik February 8, 2010 22:15

    now, this method isn’t work

  2. Jozef Chúťka February 9, 2010 11:04

    Hi Tufik,
    thank you for letting me know, I just checked this and few other examples in firefox and realized that most of them didnt worked due to my stupid html mistake:
    <div style=”width:100%px; height: 100%px;”>
    🙂

  3. greeshma May 21, 2010 19:40

    Jozef i got it now i understood clearly.now i am trying to work on it but i am getting error saying

    5000: The class ‘likebutton’ must subclass ‘flash.display.MovieClip’ since it is linked to a library symbol of that type.

  4. Jozef Chúťka May 22, 2010 12:16

    hm… I think there is a security protectom from facebook that fades its html content when it is iframed.
    @greeshma what is likebutton? Isnt it part of your code?

  5. greeshma May 23, 2010 20:31

    Thanks for the reply jozef,Its just the instance name,I am working on new like button in flash.When user clicks on the button it should check for authorization and it should post some message in users wall.You think thats possible.If so can you guide me how to do that like

    i saw your new application

    http://blog.yoz.sk/2010/05/facebook-graph-api-and-oauth-2-and-flash/

    Just want to know if we can auto publish some message ?

  6. Jozef Chúťka May 23, 2010 20:37

    @greeshma
    with the new class you can do it easily by overriding confirmConnection() method and adding publish call in there. but its not the good practice to autopublish, your app may get banned.

  7. greeshma May 24, 2010 20:34

    Jozef,

    I just want to know whether we can put the new LIKE button from graph API into our flash website.If so can you please tell me how to do it.

    Thanks

  8. Jozef Chúťka May 24, 2010 20:46

    as far as I know, like button is available just as a javascript widget, you can create one here:
    http://www.facebook.com/facebook-widgets/likebadges.php
    faning via api is currently not possible

  9. Madhu March 8, 2011 12:18

    How to post on facebook wall from a blackberry playbook application using flex..??
    ie,facebook login for mobile application..

  10. Jozef Chúťka March 10, 2011 10:07

Leave a comment

Please be polite and on topic. Your e-mail will never be published.