Recently I have played again with the Twitter API and finally have OAuth working. When I have first played with the Twitter API I have used the example from Tour de Flex. The example loads up the friends list and uses the Twitter AS3 API. The API is not really my taste but offers the functionality to build a Twitter client application. However when you want to have your client application to show up as the source of tweets you have to use OAuth for user authentication. It adds another step to get started but is a good decision to force developers to use OAuth which should provide more trust into the client app because users don’t like to enter their Twitter credentials into a 3rd party application.
After a bit of research a came across the awesome open source library oauth-as3. There were no examples yet but I remembered an Email from my friend Claus with a link to this github project. The example application uses the oauth-as3 library and demonstrates how to integrate the library.
To use OAuth in your Twitter application you need a consumerKey and consumerSecret which you can get after the registration of your client app: http://twitter.com/oauth_clients/ or go to your settings and select the “Connections” tab for an overview and further links.
However, the github example doesn’t work anymore because Twitter changed their API recently and implemented a PIN mechanism for desktop cients which should provide even more security.
So how does it work?
- Get the request token with your consumerKey/Secret
- Open the browser and pass the request token
- User authenticates on the Twitter site and gets a 6 digit pin code
- User enters pin code in the AIR app which you need to get the access token
- Save the accessKey/Secret in the EncryptedLocaleStorage for all further requests/sessions
I have build a high level AS3/Flex library for OAuth which is hosted on github. The library is licensed under Apache License, Version 2.0.
Check the inline comments of the IOAuth interface which should already explain the basics.
Here a little semi pseudo code example:
// create OAuth oauth:IOAuth = new OAUth(consumerKey, consumerSecret); // get request token var loader:URLLoader = oauth.getRequestToken("http://twitter.com/oauth/request_token"); loader.addEventListener(Event.COMPLETE, requestTokenHandler); function requestTokenHandler(e:Event):void { requestToken = OAuthUtil.getTokenFromResponse(e.currentTarget.data as String); var request:URLRequest = oauth.getAuthorizeRequest("http://twitter.com/oauth/authorize", requestToken.key); // opens website where user has to login on Twitter and gets 6 digit pin code navigateToURL(request, "_blank"); } function getAccessToken(pin:int):void { var loader:URLLoader = oauth.getAccessToken("http://twitter.com/oauth/access_token", requestToken, {oauth_verifier:pin}); loader.addEventListener(Event.COMPLETE, accessTokenHandler); } function accessTokenHandler(e:Event):void { accessToken = OAuthUtil.getTokenFromResponse(e.currentTarget.data as String); // TODO store accessToken.key and accessToken.secret in EncryptedLocalStorage for all further requests }
Instead of opening the Twitter authorization page in the browser the library also contains OAuthLoader which is a wrapper around HTMLLoader which enables to directly show the authorization page within an AIR window:
// use this in the requestTokenHandler instead of navigateToURL var loader:OAuthLoader = new OAuthLoader(); loader.load(request); loader.percentWidth = 100; loader.percentHeight = 100; var w:Window = new Window(); w.width = 800; w.height = 400; w.title = req.url; w.addChild(loader); w.open();
The OAuth library is not only considered to be used with Twitter but this was the first thing I have tested from AIR. When you build a web client there will be no pin mechanism but I haven’t tested this yet. If you have it working or see problems/bugs for web clients please drop a comment a or better file a bug.
Big thanks to Shannon Hicks for his core oauth as3 library and to Masayoshi Sekimura for the example which got me started.
Links





[...] is very popular for creating twitter clients, Sönke Rohde just made it much easier to make AIR apps for twitter with an AS3 library for Twitter. This library is built on top of core oauth as3 library by [...]
If you are using the basic auth way, you can simply append a source param to your update.xml request.
http://twitter.com/statuses/update.xml?source=&status=Posted from my app!
Opps, trimmed the tag..
should be ?source=[appId]..
Ryan, you mean to have the application as the source for tweets? The Twitter FAQ says something different here: http://apiwiki.twitter.com/FAQ#HowdoIget%E2%80%9CfromMyApp%E2%80%9DappendedtoupdatessentfrommyAPIapplication
Quote: “We originally allowed applications to create a source paramter for non-OAuth use but that has been discontinued. Applications pre-OAuth source parameters will remain active, but new registrations are no longer accepted.”
Beside that basic authentication should not be used because the user has to enter his Twitter credentials into a 3rd party app.
It still works, I’m using it in an app I’m building currently.
Also, every AIR based twitter client I’ve used you have to put your credentials in the app, I’ve yet to see any with OAuth implemented.
Different strokes, for different folks I guess.
Ok, but you can’t be sure it works in the future and with OAuth you would be on the save side. And I still think that a Twitter client with OAuth generates more trust on the user side.
However, the library is not only considered for Twitter but for OAuth in general.
Agreed, I’m not trying to argue the validity of OAuth for twitter or otherwise, just pointing out there are options.
I ran into a small issue with using oauth_core.swc file in my AIR application. When using a Menu in an ItemRenderere I get an Illegal override (Error #1053). It seems that IFocusManagerContainer which is implemented by Menu is somehow pointing to oauth_core.swc file instead of the framework. When I remove the oauth_core.swc file from my project I can then inspect the IFocusManagerContainer class file within the Flex framework.
@Mister: Do you compile the lib yourself?
You don’t need the oauth_core.swc in your project but only the OAuth.swc compiled from my project.
i’m getting a Flex error when i import your OAuth library:
TypeError: Error #1007: Instantiation attempted on a non-constructor.
at mx.preloaders::Preloader/initialize()[E:\dev\trunk\frameworks\projects\framework\src\mx\preloaders\Preloader.as:253]
at mx.managers::SystemManager/http://www.adobe.com/2006/flex/mx/internal::initialize()[E:\dev\trunk\frameworks\projects\framework\src\mx\managers\SystemManager.as:1860]
at mx.managers::SystemManager/initHandler()[E:\dev\trunk\frameworks\projects\framework\src\mx\managers\SystemManager.as:2315]
the import statement:
import org.flaircode.oauth.*;
causes this error. i haven’t even tried to instantiate any of your objects yet.
any clues? i’m running Flex Builder 3.0.214193
I assume you have only downloaded the swc which I have compiled the Flex 4 SDK. You should get the sources and compile on your own for the Flex 3.
Flex 4! that would explain things. i have downloaded your sources into Flex 3 but it’s not seeing anything in oauth_core.swc. is shannon’s swc compiled for Flex 4 also?
Yes, the oauth_core.swc is also compiled with flex 4.
So please check it out from SVN and add the flex 3 compiled lib to my lib which you then compile with flex 3 and that should be it.
Or switch to Flex 4
Ah ok, I will only use the OAuth.swc file, but I also didn’t realize that oauth_core.swc was compiled with Flex 4. It’s a wee bit early to be compiling things with Flex 4
.
Bleeding edge dude!
Sorry for the confusion. I should have mentioned that it’s compiled with Flex 4 and I now changed the description of the downloadable swc and added a note to the wiki: http://wiki.github.com/srohde/OAuth
Got everything compiling under Flex3 – thx!
Your wrapper code was built for twitter.
I made some changes so it would work with yammer.
Let me know if you want my mods.
Great, yes of course. I’ll write you an email.
Or did you fork the project on github?
Sönke, I’m using your library together with the oauth-as3 library (both on their own without compiling, I’m lazy) in a Flex app. Your psuedo code example above works fine for getting tokens and whatnot but after all that I get asked for id/pass when I try and call the Twitter Update method with the following code within a function call which I presumed should work:
var url:String = ‘https://twitter.com/statuses/update.json’;
var req:URLRequest = oauth.buildRequest(“POST”,url,accessToken,{status:’Test’});
var loader:URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE, onSendRequest);
loader.load(req);
Using Charles I know that Twitter is returning an error string of “Incorrect signature” – any suggestions?
Andrew, I tried
https://twitter.com/account/verify_credentials.json
or https://twitter.com/statuses/friends_timeline.json successfully. Did you register your app and got a consumer key/secret from Twitter which you set in the OAuth class?
Hey, thanks!
I’ve tried to unify both apis to get a single oauth as3 twitter api, but i don’t have the mandatory know how to do this.
Sönke, yes I had tried those too with success (should have mentioned that before) – https://twitter.com/statuses/friends_timeline.json is in the Tour De Flex example because it doesn’t require authentication so I’m not sure if it’s a good indication that things are working…
Sönke, on a quick sampling of Twitter methods I can call something with a GET and it works, call a method with a POST and I get a pop up asking for userid & password. Looking at the request header of the previous code I posted I see at the start of the request: “GET /statuses/update.json?oauth_consumer_key=…”
Andrew, this sounds like a bug on my side.
Are you sure you are using the latest version? I have made a fix regarding POST about two weeks ago.
Otherwise please file a bug and I have a look and try to fix it.
Eder, me disculpar mais nao posso dar ajuda agora porque tenho poco tempo.
Sönke, tried to create an issue twice with no effect, body text:
Using this library together with the oauth-as3 library (both downloaded 27 Jul 2009, both on their own without compiling, I’m lazy) in a Flex app. The psuedo code example at http://soenkerohde.com/2009/07/high-level-as3flex-library-for-oauth-with-twitter-from-air works fine for getting tokens and whatnot but after all that I get asked for id/pass when I try and call the Twitter Update method with the following code within a function call which I presumed should work:
var url:String = ‘https://twitter.com/statuses/update.json’;
var req:URLRequest = oauth.buildRequest(”POST”,url,accessToken,{status:’Test’});
var loader:URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE, onSendRequest);
loader.load(req);
Using Charles I know that Twitter is returning an error string of “Incorrect signature”.
On a quick sampling of Twitter methods I can call something with a GET and it works, call a method with a POST and I get a pop up asking for userid & password. Looking at the request header of the previous code I posted I see at the start of the request: “GET /statuses/update.json?oauth_consumer_key=…”
Suspect that code is unable to call a POST method
Looks like Twitter recently updated their OAuth stuff:
http://groups.google.com/group/twitter-development-talk/browse_thread/thread/8d82abd005002ce0
http://groups.google.com/group/twitter-development-talk/browse_thread/thread/59ed5372f7c1b623
Posting Twitter updates in an AIR app had been working for me until recently (I haven’t tried GET requests). It now pops up a thing asking for your id/pass like Andrew mentioned. I’ve been playing around with some of the google group’s suggestions but haven’t gotten it to work yet.
Wanted to post it here to help spread the word and help facilitate finding a fix.
@Andrew: I have created the issue here: http://github.com/srohde/OAuth/issues/#issue/1
No idea why this did not work for you? You have a github account?
@Paul: thanks for the links!
After sailing the OAuth seas and experimenting, I figured out how to get the POST requests working.
What won’t work:
var url:String = ‘https://twitter.com/statuses/update.json’;
var req:URLRequest = oauth.buildRequest(”POST”,url,accessToken,{status:’Test’});
var loader:URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE, onSendRequest);
loader.load(req);
For the oauth.buildRequest(…) line, when the {status: ‘Test’} is passed in, two things happen: it will be used in the signing process (to make the oauth_signature value– that’s what we want), and it will also be placed in the ‘url’ for the URLRequest object. The end result is something like this:
http://twitter.com/statuses/update.json?oauth_consumer_key=REMOVED&oauth_signature=REMOVED&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1249513985&oauth_token=REMOVED&status=Test
The last bit with ’status=Test’ will cause your request to bring up a prompt asking for the user’s login and password… it won’t work even if you put in the credentials (didn’t for me at least). To get it to work, you need to remove the ’status=Test’ part from the end (and any other non-oauth parameters) and instead, pass them in this way:
var statusString = “Test”;
var variables : URLVariables = new URLVariables();
variables.status = statusString;
request.data = variables;
request.method = “POST”;
I set it explicitly to POST because, like Andrew mentioned, it won’t automatically be set to that even if you pass “POST” in to the .buildRequest() method.
To test out my theory and remove the ’status’ parameter from the url, I just did this:
request.url = request.url.replace(“&status=Test”, “”); // this is specific just for theory testing
In the end, you’ll have the status value passed up via the URLVariables and the resulting URL will look like this (pretty much the same minus the ’status’):
http://twitter.com/statuses/update.json?oauth_consumer_key=REMOVED&oauth_signature=REMOVED&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1249513985&oauth_token=REMOVED
Which ended up working for me (I used xml instead of json though). Here’s a code listing for copying and pasting to see if this works for you:
var statusString = “Test”;
var variables : URLVariables = new URLVariables();
var url:String = “https://twitter.com/statuses/update.json”;
var req:URLRequest = oauth.buildRequest(”POST”, url, accessToken, {status: statusString});
variables.status = statusString;
request.data = variables;
request.method = “POST”;
request.url = request.url.replace(“&status=” + statusString, “”);
var loader:URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE, onSendRequest);
loader.load(req);
For my local project I modified the org.iotashan.OAuthRequest.as file and added a method that grabbed just the encoded OAuth values and returned them as the URLRequest object’s url (instead of including all the other non-oauth parameters when dealing with a POST request):
private function getEncodedOAuthParameters():String {
var aParams:Array = new Array();
// loop over params, find the ones we need
for (var param:String in _requestParams) {
// this will determine whether a parameter is oauth; typically the oauth parameters start with
// “oauth_”
if (param.search(/^oauth_/) != -1) {
aParams.push(param + “=” + URLEncoding.encode(_requestParams[param].toString()));
}
}
// put them in the right order
aParams.sort();
// return them like a querystring
return aParams.join(“&”);
}
Pretty much just like the other methods but it has the conditional inside the loop. Works pretty well. Hope this helps.
Sorry, the URLs I copied and pasted have ‘http’ at the front because I was using ‘http’ in that instance instead of ‘https.’ In this case, it would really start with ‘https.’ Just wanted to clear that minor detail up.
yes, that works, but not for spaces. I modified your code like that to include the fact of URLEncoding:
req.url = req.url.replace(“&status=” + URLEncoding.encode(inParams.status), “”);
var params:URLVariables = new URLVariables();
params.status = URLEncoding.encode(inParams.status);
req.data = params;
req.method = URLRequestMethod.POST;
It works fine for “Test” but for “T e s t”, I got a 401 Error (not authorized) and the smart loginbox..
ok, here the short and simple solution: you should remove the encoded text from the URL (because it has been encoded by the library), but the request.parameter.status must not be encoded. the signature matched anyway.
hope that helps
Thanks for the library, so far so good! I am getting the RequestToken without issue.
Now its time to get the accessToken. Is there a way to collect and send the user credentials from within my air app? Every time I try to use the
oauth.getAuthorizeRequest(“http://twitter.com/oauth/authorize”, requestToken.key );
It responds with a webpage asking for user credentials. Should I call “account/verify_credentials” first?
I would like to collect my users credentials from within my app and not from a webpage. Any help would be much appreciated.
Joe
Ando, you use OAuth to NOT let your user enter his crendentials in your app but on the Twitter website. However, if you use AIR you can display it inside the app.
@zmb0: Thanks, I will try this soon and fix/update the source.
Thanks for the response! This stuff has had me quite confused. So you are saying the only place the users can enter the credentials is through the website? So my app will have to open a web page and wait for the login response from that?
Joe
Yes, this is the deal with OAuth so no 3rd party app will directly ask for the user credentials. Users care about their sensitive Twitter credentials and do not necessarily trust every 3rd party app.
You maybe wanna have a look at http://oauth.net
Hi Sönke
Am new to flex/Air development,can you kindly point me any self explaining examples for oauth implementation, will be great.Thanks in advance
Hi, i am trying to use this library, but i am getting an error all the time, what i am doing wrong?
Error:Error #2044: Unhandled ioError:. text=Error #2032: Stream Error after this i get the url generated, if i try to openit in a browser i get this:
Failed to validate oauth signature and token
Any ideas?
Here is my basic code:
Marcelo, as you can see by the other comments it works.
Did you try the example code from this blog?
Did you use your consumer token/key from Twitter?
[...] is very popular for creating twitter clients, Sönke Rohde just made it much easier to make AIR apps for twitter with an AS3 library for Twitter. This library is built on top of core oauth as3 library by [...]
Hi Sönke, quick question
Is there any reason I shouldn’t be able to get this working for an AS3 only web client?
Sorry, 2 other questions.
1 Is it possible to test OAuth web apps from the IDE or desktop or must you first publish to the application url you defined when registering your application?
2 Is the pin registration ONLY needed for AIR apps? Have read the entire OAuth for Beginners doc but still confused on this.
Thanks for any feedback!
I keep getting the same exact error Marcelo Marmol gets. I testing with and Adobe Air destokp app. Tried POST tried GET, nothing works. Is it possible that this is actually not passing the correct parameters to twitter?
What call do you actually try?
@jimb: yes, pin is only for air apps.
I never tried it within a webapp and I am pretty sure that the lib has to be extended to make it work in the browser.
also check out my twitter lib: http://soenkerohde.com/2010/01/twitter-as3-oauth-lib-with-flex-4-example/
Thanks for the link, I will check it out. This is what I tried:
oauth = new OAuth(consumerKey, consumerSecret);
var loader:URLLoader = oauth.getRequestToken(“http://twitter.com/oauth/request_token”);
loader.addEventListener(Event.COMPLETE, requestTokenHandler);
loader.addEventListener(IOErrorEvent.IO_ERROR, requestTokenErrorHandler);
I get Error #2032: Stream Error. URL: …
Did you set a working consumer key/secret which you got after registering your app on twitter?
Yes (the ones you see under http://twitter.com/apps/ ) that populate consumerKey and consumerSecret .
Hey Sönke, did you get the library to work with Yammer. I put up an Yammer AS3 API on Github (http://github.com/thanksmister/as3yammerlib) and thought about combining your oauth flow into an example for AIR implementation. One of the comments (from Mike?) mentioned a modification to the library that works with the Yammer service.
Hi Michael, I haven’t used Yammer yet so honestly no idea.
But I was in Email contact with Mike and wrote him now that I would like to see his changes.
When I hear back from him I’ll let you know.
Sonke,
Thanks for the classes.
I’m getting the error “Failed to validate oauth signature and token”. I think it has something to do with the “oauthTokenSecret”, maybe? Does this var need to be set before getSignedRequest() gets called?
var key:ByteArray = Hex.toArray( Hex.fromString(encodeURIComponent(Constants.TWITTER_CONSUMER_SECRET) + “&” + encodeURIComponent(oauthTokenSecret)));
Chris
I should add that I am doing this in AIR and have the proper consumer secret and key.