ebryn / twitter-titanium

The easiest way to handle Twitter authentication in your Titanium Mobile app
75 stars 54 forks source link

Auth now fails, asks user to return to app to enter PIN #11

Open adamdport opened 9 years ago

adamdport commented 9 years ago

On April 8th 2015, Twitter must have changed their form, as this twitter plugin stopped functioning. On line 124 of twitter.js, pin is set to an empty array:

var pin = event.source.evalJS("document.getElementById('oauth_pin').getElementsByTagName('code')[0].innerText");

Upon checking the dom in a browser, I can confirm that there is no element with ID "oauth_pin". The pin appears on the page that is displayed following authorization.

adamdport commented 9 years ago

It looks like Twitter loads the pin with ajax instead of actually reloading the page. This doesn't trigger the "load" event that this plugin relies on. To make it work, I wrote a really gross timeout that just scans the dom for the pin every half-second:

var checkForPin = function(){
    // Grab the PIN code out of the DOM
    var pin = event.source.evalJS("document.getElementById('oauth_pin').getElementsByTagName('code')[0].innerText");

    if (!pin) {
      ...           
      setTimeout(checkForPin, 500); //if the pin doesn't exist, try again in 500ms
    } else {
      ...
    }
};

checkForPin(); //starts the scan

It's not pretty, but it gets some abandoned code functional again...

bradwhiteVB commented 9 years ago

Does your code replace the load listener? And if so, where did you place the call?

Have you tried this on Android devices that have an OS of 4.4.2 or later (KitKat)? I am getting an EvalJS error that I am not sure is caused by the code here.

[INFO] : I/TiWebChromeClient.console: (main) [275,78944] Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "script-src https://abs.twimg.com https://abs-0.twimg.com".

I believe your answer would work in iOS. Also see this for my attempt https://developer.appcelerator.com/question/181846/twitter-auth-recently-stopped-working-for-me.

bradwhiteVB commented 9 years ago

Here are some links to where people are working around it https://github.com/aaronksaunders/test_social/issues/11 http://developer.appcelerator.com/question/181967/cant-access-twitter-pin-in-android#comment-227225

With the second link - it is my question I referenced above, whatever I choose to do will be located there.

adamdport commented 9 years ago

I didn't test on Android–I only needed iOS for my project.

This code does NOT replace the load listener–it sits inside it.

It looks like those solutions require the users to enter the code themselves–an unnecessary extra step imho. I wish I could find another event to hook into other than "load" so I don't need to rely on this timeout, but it works for now. If you find a cleaner way, please post a followup!

natefollmer commented 8 years ago

Hey @bradwhiteVB and @adamdport - Did you ever find a better way to do this? I've still been using this workaround (that's me on the Appcelerator forum BTW, sorry I didn't reply, I never got notification you asked more questions). It works as intended on iOS, but the PIN must be entered by the user on Android. I've tried just about everything I can think of and it never works on Android. I know it has something to do with evalJS not working on Android after KitKat, but never found a better way to grab the PIN automatically.

adamdport commented 8 years ago

I didn't. My timeout solution worked for me on Android, but it's not elegant. The "better way" is to scrap the timeout, hook into the ajax request somehow and retrieve the pin when it completes. jQuery has .ajaxComplete() for example? Good luck! Please post back if you find anything.

bradwhiteVB commented 8 years ago

Sorry for the late reply. I didn’t find another answer either. I was playing with the idea of pattern detection on an overlay (like QR code) but that was a WHOLE lot of work, required camera access and other issues like what if Twitter changed the size/font/location of the code….. A cleaner answer would be to have a module that enables pass through just like Facebook. I believe Alloy has it so why can’t non-Alloy users ???

On 30 Nov 2015, at 12:00 pm, Nate Follmer notifications@github.com wrote:

Hey @bradwhiteVB https://github.com/bradwhiteVB and @adamdport https://github.com/adamdport - Did you ever find a better way to do this? I've still been using this workaround (that's me on the Appcelerator forum BTW, sorry I didn't reply, I never got notification you asked more questions). It works as intended on iOS, but the PIN must be entered by the user on Android. I've tried just about everything I can think of and it never works on Android. I know it has something to do with evalJS not working on Android after KitKat, but never found a better way to grab the PIN automatically.

— Reply to this email directly or view it on GitHub https://github.com/ebryn/twitter-titanium/issues/11#issuecomment-160490362.

natefollmer commented 8 years ago

Thanks guys! I'll see if I can drum up some time to work on this. I have other things more important to finish, but it is quite annoying to have the user enter the PIN. At least it works though! I'll report back if I come up with anything.