TwitterLogger Class To Full Twitter API Access From ActionScript 3

For the last couple of days I have been working with Twitter API, trying to make the api usable for flash in browser the same way as FacebookLogger (Facebook API extension) is. Guess what, I did it! I created TwitterLogger. TwitterLogger class extends official TwitterScript (ActionScript API) and implements OAuth (and TwitterOAuth – PHP Library to support OAuth for Twitter’s REST API) authorization protocol to gain full access into Twitter API from flash in browser.
TwitterScript already contains full api access but some call requires authorization that brings you into 2 issues:
- obtain username and password from user – unwanted operation
- crossdomain authorization – only possible for AIR due to Twitter crossdomain policy restriction
Sets the username and password for this instance, setting the flag to use https to true. Note that this will not work at all in Flash player 9.0.115, and will only work in later versions if the remote server has the <code>allow-http-request-headers-from</code> tag set permissively in its crossdomain policy file. For more information see: http://kb.adobe.com/selfservice/viewContent.do?externalId=kb403184. Unfortunately Twitter has it set to (as of Sept 2008): <allow-http-request-headers-from domain=”*.twitter.com” headers=”*” secure=”true”/> which only lets in the twitter badges originating from twitter.com. Since that’s the case, authentication will only work for AIR.
If you use this for Flash in the browser, it will fail over to the browser’s basic auth without an issue. (described in com.twitter.api.Twitter.setAuthenticationCredentials())
This requires another method on scene. Since Twitter introduced OAuth it is possible to get connection into Twitter API via this open source secure authorization. To communicate with Twitter we gonna use server side proxy. So lets start:
1. Register a new twitter application, these settings are crucial:
Application Website: http://blog.yoz.sk/examples/twitterLogger/ Application Type: Browser Callback URL: http://blog.yoz.sk/examples/twitterLogger/callback.php Default Access type: Read & Write Use Twitter for login: Yes
2. download OAuth.php and twitteroauth.php from TwitterOAuth into /library/ dir
3. create /config.php file containing:
<?php
// fill your own Twitter application Consumer key
define('CONSUMER_KEY', 'qSoF24kOuNCiPCQwWfe0yQ');
// fill your own Twitter application Consumer secret
define('CONSUMER_SECRET', 'xahJ7hpJeevq411N5NQXcTbJ5hQFWDwidtTpsbc');
// fill your Twitter application Callback URL
define('OAUTH_CALLBACK', 'http://blog.yoz.sk/examples/twitterLogger/callback.php');
4. /connect.php file:
<?php
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Cache-Control: no-store, no-cache, must-revalidate, pre-check=0, post-check=0, max-age=0");
header("Pragma: no-cache");
header("Last-Modified:".gmdate("D, d M Y H:i:s")." GMT");
header('Content-Type: text/html; charset=utf-8');
session_start();
require_once 'config.php';
require_once 'library/twitteroauth.php';
$connection = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET);
$request_token = $connection->getRequestToken(OAUTH_CALLBACK);
$_SESSION['oauth_token'] = $token = $request_token['oauth_token'];
$_SESSION['oauth_token_secret'] = $request_token['oauth_token_secret'];
$url = $connection->getAuthorizeURL($token);
header('Location: ' . $url);
exit;
5. /callback.php
<?php
session_start();
require_once 'config.php';
require_once 'library/twitteroauth.php';
$connection = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET, $_SESSION['oauth_token'], $_SESSION['oauth_token_secret']);
$access_token = $connection->getAccessToken($_REQUEST['oauth_verifier']);
$_SESSION['access_token'] = $access_token;
unset($_SESSION['oauth_token']);
unset($_SESSION['oauth_token_secret']);
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="sk" lang="sk" dir="ltr">
<head>
<script type="text/javascript">
<!--
if(window.opener && window.opener.confirmTwitterConnection)
{
window.opener.confirmTwitterConnection();
self.close();
}
//-->
</script>
</head>
<body>
<p>You may now close this window.</p>
</body>
</html>
6. /proxy.php
<?php session_start(); require_once 'config.php'; require_once 'library/twitteroauth.php'; $access_token = $_SESSION['access_token']; $connection = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET, $access_token['oauth_token'], $access_token['oauth_token_secret']); $parameters = array(); foreach($_POST as $key => $value) if($key != "method" && $key != "url") $parameters[$key] = $value; echo $connection->OAuthRequest($_POST['url'], $_POST['method'], $parameters);
7. Create new flex project
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical"
applicationComplete="init()">
<mx:Script>
<![CDATA[
import sk.yoz.events.TwitterLoggerEvent;
import sk.yoz.net.TwitterLogger;
private var connector:String = "http://blog.yoz.sk/examples/twitterLogger/connect.php";
private var proxy:String = "http://blog.yoz.sk/examples/twitterLogger/proxy.php";
[Bindable]
private var twitter:TwitterLogger = new TwitterLogger(connector, proxy);
[Bindable]
private var lastCallResult:String = "";
private function init():void
{
twitter.addEventListener(TwitterLoggerEvent.CALL_COMPLETE, callComplete);
}
private function callComplete(event:TwitterLoggerEvent):void
{
lastCallResult = event.data.toString();
}
]]>
</mx:Script>
<mx:HBox>
<mx:Button label="connect" click="twitter.connect()" />
<mx:Label text="{twitter.connected ? 'connected' : 'not connected'}" />
</mx:HBox>
<mx:HBox>
<mx:TextInput id="status" text="hallo world status"/>
<mx:Button click="twitter.setStatus(status.text)" label="update status"/>
</mx:HBox>
<mx:TextArea text="{lastCallResult}" width="100%" height="100%"/>
</mx:Application>
8. Download TwitterScript classes and make sure to rewrite private to protected namespace for these methods and vars in com.twitter.api.Twitter class:
protected var loaders; protected function addLoader(... protected function errorHandler(...
9. Download sk.yoz.net.TwitterLogger, sk.yoz.net.TwitterProxyLoader and sk.yoz.events.TwitterLoggerEvent classes into your flex project under the correct namespace (sk.yoz…)
10. Make sure your index.html wrapper class defines allowScriptAccess and flash id and name, it may look like something like this:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="cs" xml:lang="cs">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta http-equiv="Content-language" content="cs" />
<title>TwitterLogger</title>
<script type="text/javascript" src="js/swfobject.js"></script>
<script type="text/javascript">
//<![CDATA[
var flashvars = {}
var params = {
allowScriptAccess: "sameDomain"
};
var attributes = {
id: "sz",
name: "sz"
};
swfobject.embedSWF("App.swf", "alternative", "100%", "100%", "9.0.124",
"expressInstall.swf", flashvars, params, attributes);
//]]>
</script>
<style>
<!--
body {margin:0px;overflow:hidden;}
html, body, object, embed {width:100%;height:100%;outline:none;}
-->
</style>
</head>
<body style="text-align:center;">
<div id="alternative">
<a href="http://www.adobe.com/go/getflashplayer">
<img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" />
</a>
</div>
</body>
</html>
Publish html template and copy all flash files into your application website. You should now have this structure in there (http://blog.yoz.sk/examples/twitterLogger/)
/js/swfobject.js /library/OAuth.php /library/twitteroauth.php /App.swf /callback.php /config.php /connect.php /index.html /proxy.php
If you do same changes, make sure all these files are on same domain because it uses PHP Session to store token and JavaScript between-window communication. Now lets see our application (http://blog.yoz.sk/examples/twitterLogger/):
To update your satus, first click on connect, window popup opens and redirects itself into Twitter asking for permission. After you click allow in popup, popup closes itself and change status in flex near connect button to “connected”. Now you are ready to update your Twitter status. TextArea contains last Twitter appi call reply (after status update). The good thing with OAuth is, it remembers your acception for some time, so you do not have to click allow every time…
There may occur error on Twitter popup saying:
This page is no longer valid. It looks like someone already used the token information you provided. Please return to the site that sent you to this page and try again … it was probably an honest mistake.
I guess it may have something to do with cached request on connect.php, so I added few expire headers into it.
Where to go from here:
Exellent work! I like it! =)
thanks Klas
You have very helpful examples in your blog!
[...] days before while I was working on TwitterLogger Class for ActionScript 3 I discovered OAuth – an open protocol to allow secure API authorization . While reading all [...]
Thanks for this example. Please let me know how to disconnect/logout of twitter from within flex.
@arun there are multiple methods:
http://stackoverflow.com/questions/1960957/twitter-api-logout
Hi. I get the
“This page is no longer valid. It looks like someone already used the token information you provided. Please return to the site that sent you to this page and try again … it was probably an honest mistake.” message from twitter, even with the headers included in the connect.php file. Also, the twitter-connect window that is launched doesn’t seem to have a ?oauth_token=
value … it’s just blank.. any idea?
I’m thinking it’s because there’s some lag loading the keys, so it goes to the twitter authorize page before those variables are loaded. Just a guess.
For anyone using this, it seems that the proxy.php example hands your tweet string to twitteroauth with escape slashes. So a tweet of:
These are “double quotes”
will show up on Twitter.com as:
These are \”double quotes\”
So I just did the following on line 11 of proxy.php
if($key != “method” && $key != “url”){
$value = str_replace(“\\\”",”\”",$value);
$value = str_replace(“\\’”,”‘”,$value);
$value = str_replace(“\\\\”,”\\”,$value);
$parameters[$key] = $value;
}
I’m sure there’s a better method, but that’s what worked for me.
@Helliax,
thnx for noticing. I am few years out of php but if I am correct, this has to do with archaic Magic Quotes
http://php.net/manual/en/security.magicquotes.php
you should be able to use stripslashes() http://www.php.net/manual/en/function.stripslashes.php if magic quotes are on http://www.php.net/manual/en/function.get-magic-quotes-gpc.php
Thanks for the tip Jozef! I’m not a PHP programmer by any means, so it was a small adventure trying to fix that at first. stripslashes() is much nicer.
I’m getting this error, does anyone know what it means, and how fix it?
securityErrorHandler: [SecurityErrorEvent type="securityError" bubbles=false cancelable=false eventPhase=2 text="Error #2048: Security sandbox violation: http://www.foxflare.com/twitter/App.swf cannot load data from http://twitter.com/statuses/update.xml."]
Here is where my app is located:
http://www.foxflare.com/twitter
I’m using BlueHost as my ISP, and I remember asking about proxy, and the rep said they don’t allow it. Unfortunately I don’t know about proxy concepts at all, so I don’t know what he’s talking about. Could this proxy denial thing be the culprit here?
Jozef thanks for offering another great solution. Your Facebook OAuth2 solution was great and I was relieved when I saw that you took on Twitter as well. I searched for days and it appears you’re the only guy coming up with practical approaches for this stuff.
@Kevin, security error 2048 means you have to download crossdomain.xml from the targeting domain before using the actual data content. you can bypass this by using proxy.php and make your server side do the foreign request
@Kevin your ISP may block proxy servers that routes all your traffic, but that is not our case, proxy.php will work for you just fine.
I figured out what I did wrong. There were some variable types that were changed properly or not overridden properly etc. :p
Hey I am trying to get this running locally with no love. I am using a .local address, could this be the issue? Nothing seems to be happening after calling connect from twitter.connect();
hi Dave,
- does my app work for you?
- could you debug twitter.connect function, where the script finishes exactly?
- does ExternalInterface call get eecuted?
- do you have popup blocker?
Hi there! Cool info but I’m a bit confused, so…
Question: why do you use “air talks to php talks to twitter”? Isn’t there any way to use oauth from within an air app without using any “external stuff” like php on a webserver? Maybe I’m missing something here, so any info would be great!
Tnx
Mike
hi @e-sushi. This class was originaly writen for flash player (.swf) files, not air. While twitter does not provide crossdomain poliecies required for flash player, you can not make direct requests and catch response. However, you can use AIR to make requests directly without backend, just google some oauth actionscript class and you are fine.
Hi,
first thank you for this tutorial, it’s very helpful for me. Second, I try to show the user info, but when the user click on connect button and when he is connected how can I get his idUser ? Because when you call the loadInfo() methods you need to have a userId.
Thanks.
Ben.
Ok, I find the method verify()
You can test here : http://bigbenprod.fr/visiotweet/
Ben.
Hi Jozef,
Nice class, thanks !
Did you know how to get userId after get connected ? I need that to display infos from the user, and the function in twitterscript loadInfo need userId string.
And did you know if there is an autoconnect function to detect at the beginning of the app if the user is connected? like your facebook stuff.
Thanks by advance
Regards
Hi @Ben,
yes it is verify_credentials ( http://apiwiki.twitter.com/Twitter-REST-API-Method:-account%C2%A0verify_credentials -> http://api.twitter.com/1/account/verify_credentials.xml ) method
It is very nice app you have created
Hi @Vincent, please check out my previous comment (verify credentials method) for getting actual user. In order to use autoconnect you may do the following:
1. store access token into a cookie or SharedObject with your first login
2. modify the proxy.php to use access token from cookie or SharedObject (pushing)
3. when your apps starts again try verify_credentials with stored access token, it may be valid for some time
Hi @Jozef,
Thanks for your trick, i have used the method of Ben, verify(), works well
I try for finish to disconnect my user, there is a function called endSession() in twitter api, works welle but did’nt do the job i want, the token seems to be always hee, and when i reload the page, and get connected.
The trick in this link seems a bit difficult http://stackoverflow.com/questions/1960957/twitter-api-logout
Did you have an idea for your class?
thanks
Regards
Hi @Vincent, @Ben, what exactly is verify() method? I am a bit confused now – I can not find any method called “verify”. Do you refer to verify-credentials or some different method?
In order to log out, clean access_token from your _SESSION variable, once the token is trashed, that should do the trick
Jozef,
public function verify():void {
var verifyLoader:URLLoader = this.getLoader(VERIFY);
verifyLoader.load(twitterRequest(VERIFY_URL));
}
line 387 in Twitter.as
@Vincent, thnx, my mistake, I can see it now… it actually calls the verify-credentials
Hi Jozef,
thanks for your work. Seems very promising.
Unfortunately I’m a total php noob and when I click on connect in version of the application this website opens:
http://github.com/abraham/twitteroauth/blob/master/twitteroauth/twitteroauth.php
I’m sure some of my configurations are wrong. Can you please give me a hint on where to look?
Thank you
Hi Dan,
- does that happen when you click connect in my application or in your one?
- did you copied correctly content of connect.php file and other files into your php server?
Hi Jozef,
in my app the connect-popup shows just a white page. I couldn’t figure out exactly what it it, but it seems that the code stops working after the following line in twitteroauth.php line 186:
$request->sign_request($this->sha1_method, $this->consumer, $this->token);
when I echo $this->sha1_method script stops. Any ideas what this means?
best wishes,
Frank
Hi Frank,
please turn your php errors on (E_ALL) and debug the error
these .php classes are not developed by me, please contact the author on http://github.com/abraham/twitteroauth/tree/master/twitteroauth/
Is there a way to stripslashes from tweets before posting them with OAuth? Thx!
Kcal, sure you can, just override setStatus function and strip whatever you want
Hi guys,
I found there’re errors in the code like wrong references and others. some that I found was:
- can’t find com.twitter.api.Twitter rather twitter.api.Twitter (any source in as format that is around for the Twitter API? because I got the SWC only)
- this bit is wrong override protected function addLoader – it says nothing to override and also the last line should’ve been loader rather than loaders
- would probably be easier if someone could convert this to AS based rather than flex if you mind?
Please help me. thanks in advance.
Hi Robert,
yes I am referencing external library (official Twitter one) … You can not use .swc because you need to change some code inside as described in step 8. So you should go to http://code.google.com/p/twitterscript/ click source / browse / trunk / src… and download sources directly than made some changes as described in step 8 (addLoader function to protected etc.).
my TwitterLogger class should work for you with flex compiler, with cs one you should remove [Bindable] metadata and its ok to go…
[...] insightful and helpful tutorial of setting up the OAUTH, proxy and all its necessary backend stuff. Here it is. The steps are quite simple, I managed to set the whole thing up within minutes. It uses flex, [...]
Hey man,
thank you very much for sharing your work. I really appreciate it.
I have one question though. (Maybe I just can’t see the forest for the trees)
Once I have connected I’d like to show the username (screen_name) of the connected user.
But in the event handler for the CONNECTED event the data object is null.
So where to get the users information from?
Any help would be highly appreciated.
Thanks a lot and keep up the great work!
Cheers,
Dan
hi Dan,
you can find your answer in this comment http://blog.yoz.sk/2010/04/twitterlogger-class-to-full-twitter-api-access-from-actionscript-3/#comment-2976
I’ve got the php code under a different domain than the SWF part, and I’m running into a permission denied error when it’s trying to call the ‘confirmTwitterConnection’ ExternalInterface. I’ve got Security.allowdomain(“*”) in the swf, and allowScriptAccess=”always” in the HTML page hosting the SWF.
Do you know off-hand if there is some other security param I need to watch out for?
hi Helliax,
confirmTwitterConnection is an javascript function defined from actionscript. Not quite sure where is your html wrapper for flash hosted from and hard to guess but I think the javascript part is defined in different domain than it is later called from. What is the actual error? is it javascript error or actionscript one?
Jozef, thanks for such a fast reply. I figured out why the error is happening. It’s a javascript crossdomain issue, I believe. confirmTwitterConnection() is on domainA, and callback.php is on domainB (not just different subdomains).
It is a javascript error, and I was looking in the wrong place (the actionscript). I’ve looked online a bit, and there seem to be a few hacks here and there to bypass the javascript permission, so I’ll have to try them out. I don’t know if they work.
hi how to send pics throught twitter update media from this example thanks
hi nite,
have a look at https://dev.twitter.com/docs/api/1/post/statuses/update_with_media
hi how to call user friends data from flash
hi shane, I have not used twitter api for longer time now, from time to time I just hear how unreliable it is. anyway, if you want to proceed I would suggest starting at https://dev.twitter.com/docs/api/1.1
Hi, thanks for share this.
Can you put some link to download this example? i’ll really appreciate that.
Thanks.
hi Felipe,
You can download some sources by following the links in the article- Other than that, I belive article contains all the necessary. if you go through the article carefully and has some base knowledge about these technologies, you should be able to make the app yourself.
Hello. i have trouble with popup window after logging. it has not closed. and i receive “You may now close this window.” message
mb you can provide your actionscript example source code?
i have solved an issue
sorry for inconvenience