Skip to content
This repository

Session getting "lost" in calls to LinkedIn #3

Closed
jeliotb opened this Issue March 30, 2012 · 11 comments

2 participants

jeliotb Antony Jones
jeliotb

I am configuring grails-oauth-scribe for use with LinkedIn, and finding that the requestToken set in the session scope parameters during the oauth/authenticate action is gone in oauth/callback, resulting in a null pointer exception. Based on the output of debug, it is clear that the initial session used in authenticate has expired by the time that control returns to my application through the LinkedIn callback. As this is a matter of seconds, it is not at all clear why. To illustrate the problem, I have attached the results of setting debug = true, and added print statements that captured the session id and scope parameters.

As additional background, the context this occurs in is that the user starts from a login page generated by the spring-security-core plugin. Once they submit the form, the LoginController's index action redirects them to the oauth/authenticate action, and that's where the problem takes hold.

obtaining request token from https://api.linkedin.com/uas/oauth/requestToken
setting oauth_callback to http://myhost:8080/trunk/oauth/callback
generating signature...
base string is: POST&https%3A%2F%2Fapi.linkedin.com%2Fuas%2Foauth%2FrequestToken&oauth_callback%3Dhttp%253A%252F%252Fmyhost%253A8080%252Ftrunk%252Foauth%252Fcallback%26oauth_consumer_key%3DXXX0%26oauth_nonce%3D2011197064%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1333127525%26oauth_version%3D1.0
signature is: M+qRt73lvk8Y6KgZH20CxMaPFqQ=
appended additional OAuth parameters: { oauth_callback -> http://myhost:8080/trunk/oauth/callback , oauth_signature -> M+qRt73lvk8Y6KgZH20CxMaPFqQ= , oauth_version -> 1.0 , oauth_nonce -> 2011197064 , oauth_signature_method -> HMAC-SHA1 , oauth_consumer_key -> XXX , oauth_timestamp -> 1333127525 }
using Http Header signature
sending request...
response status code: 200
response body: oauth_token=21ce3626-6323-4145-a707-c3fb8a002688&oauth_token_secret=4e0b7f32-7979-4b1b-a30c-da5f9666e3d1&oauth_callback_confirmed=true&xoauth_request_auth_url=https%3A%2F%2Fapi.linkedin.com%2Fuas%2Foauth%2Fauthorize&oauth_expires_in=599
session.id is CF2FCF26E84929E986F59AEFCBE926A8 in authenticate
attribute names for session in authenticate:
oasRequestToken
attribute is a Token? true
url is https://api.linkedin.com/uas/oauth/authorize?oauth_token=21ce3626-6323-4145-a707-c3fb8a002688
session.id is 94A56B5549ABFEB2A550A1F2FCE9E95D in callback
attribute names for session in callback:
requstToken null? true and verifier null? false
obtaining access token from https://api.linkedin.com/uas/oauth/accessToken
| Error 2012-03-30 10:12:13,242 [http-bio-8080-exec-7] ERROR errors.GrailsExceptionResolver - NullPointerException occurred when processing request: [GET] /trunk/oauth/callback - parameters:
oauth_token: 21ce3626-6323-4145-a707-c3fb8a002688
oauth_verifier: 86389
Stacktrace follows:
Message: null
Line | Method
->> 75 | getAccessToken in org.scribe.oauth.OAuth10aServiceImpl


| 118 | getAccessToken in uk.co.desirableobjects.oauth.scribe.OauthService
| 25 | doCall . . . . in uk.co.desirableobjects.oauth.scribe.OauthController$_closure1
| 886 | runTask in java.util.concurrent.ThreadPoolExecutor$Worker
| 908 | run . . . . . in ''
^ 662 | run in java.lang.Thread

jeliotb

In case it isn't clear, I do not submit "XXX" or use "myhost" as parameters above. I have simply replaced the original text to avoid compromising my application.

jeliotb

As an additional update, I have tried two things to work around this, one of which didn't work, and the other of which did, but is a bad idea for production.

The thing that didn't work was to change Grails versions. I had been running 2.0.1, which I realized I didn't specify above, so I tried testing in Grails 1.3.8. This had no effect.

The thing that DID work was to switch the scope in which the requestToken was saved in OauthController.authenticate. Instead of session, I put it in servletContext. This produced the desired results, but is not something I would want to release, even with a bit of cleverness about using the oauth_token as the key so that there wouldn't be conflicts.

Although LinkedIn is the only API that I presently need to authenticate against, I will try doing this with Twitter and see if anything is different. As the problem appears to be purely a matter of the session object being lost and recreated, I would not expect this to be the case, but in the interests of exhaustively isolating the issue, it ought to be done.

jeliotb

Twitter produced the same results as LinkedIn, after I modified my application settings on the Twitter developer site to include a default callback URL. Oddly -- and quite contrary to Twitter's own stated advice on the application settings page -- passing an explicit callback URL is ignored in favor of whatever is in the settings. Considering that one would think a live request from the application is the most current URL to use, this is highly unintuitive behavior. However, without that setting on Twitter's end, you get the results that I posted here below a little earlier:

Working with Twitter proved a dead-end, as it apparently won't tolerate anything but the out-of-band approach for desktop applications (per the pasted error below, run from a local app named 'oauth' created just for testing this library). I'm happy to try the code with anything else you might suggest.

Error 500: Internal Server Error

URI
/oauth/oauth/authenticate
Class
org.scribe.exceptions.OAuthException
Message
Response body is incorrect. Can't extract token and secret from this: '<?xml version="1.0" encoding="UTF-8"?> Desktop applications only support the oauth_callback value 'oob'/oauth/request_token '

Antony Jones
Owner
aiten commented March 31, 2012

Hi There,

Sorry to hear you are having so much trouble - and thank you for the bug report!

I'll have a look into this/see if I can determine the cause of the issue and get back to you. I've not tried the plugin with linkedin yet, but I am using Grails 2.0.1 with Xero (http://xero.com) as my test bed.

If you can provide some sort of sample application that would really help - but I will understand if you can't.

Cheers,
Antony

jeliotb

Thanks so much for your reply. I'll have a sample application up on GitHub tonight with a few different providers and as much documentation as I can muster. It's actually mostly written already (once I realized what was happening, I wanted to make sure it wasn't an artifact of something else in my code.; I just need to write more useful GSPs for examining the output.

jeliotb

Hi Antony,

I tried to set things up with Xero, but found I was having a devil of a time. I have, however, checked in my sample application at: https://github.com/jeliotb/oauth-scribe-test. In Config.groovy, you will need to supply whatever API and keys you wish to use.

Here is an interesting new result: In the DemoController class, on the failure action, I tried to pass a null token result in flash scope. I was quite surprised when that failed. It turns out that the original session -- the one that existed when the user starts from the login page, through the call to oauth/authenticate -- actually "comes back" on the redirect from the oauth/callback failure action. Thus, the only place where a new session exists is during the redirect and callback sequence, and the original session is still preserved.

This is what printed when I ran it:

session.id is 0EC29A4C722DF5C2CE65BDC284337BCF in authenticate
attribute names for session in authenticate:
oasRequestToken
attribute is a Token? true
url is https://api.linkedin.com/uas/oauth/authorize?oauth_token=1f87232d-cc23-44cb-8400-cfb72437de11
//here, we leave the grails app and visit LinkedIn
session.id is 9FE7FD8E15BC41C2F7F7100FD383A826 in callback
attribute names for session in callback:
//the following lines print in the DemoController failure action
flash message is now null
session message is now null
session id is now 0EC29A4C722DF5C2CE65BDC284337BCF in /demo/failure

Antony Jones
Owner
aiten commented April 01, 2012

Thus, the only place where a new session exists is during the redirect and callback sequence, and the original session is still preserved.

That sounds reasonable - since your oauth provider's callback will be given a new session when it hits your application.

I'll check out your code asap and give it a go.

Antony Jones
Owner
aiten commented April 09, 2012

Hi There,

I've checked-out and run the sample application, and it performs without issue for me. What exactly do you see when you connect using your grails-oauth-test application? I'm seeing all the things you might expect, in the console then "Sing it, Mr. S!" on the connected page.

Is the error you are receiving consistent? Or sporadic?

Let me know!
Cheers,
Antony

jeliotb

This is bizarre -- after I saw your comments, I proceeded to check out a copy of my own code from GitHub, and ran it in my IDE, resulting in no errors. That same code reliably produced failures of the sort seen in my original report, but produced new errors on a clean checkout.

I then re-ran my original production code, which is identical to the test code except for the specific callback URL and success/failure URLs -- and got the same bug again. In my installations, it is consistent every time I run it. I am going to try checking my own code out of my company's repository and see what happens -- if it works without further errors, this will no doubt be the strangest bug I have ever seen.

jeliotb

Well, the good news is that it's not a bug in version control somewhere. I have now figured out how to reliably reproduce it for the FIRST LOGIN ONLY. If I do not have the web browser that I am going to use open, and open it only after the app has launched (to guarantee that no prior session state exists), the bug occurs. On any attempt to access the application AFTER the first login, it no longer occurs. The same is true if I then open a different browser (say, Chrome after starting with Firefox). As I get the same results if I start with Chromium and then switch to Firefox, this is not a bug in session management in the browsers. Oddly, while I can get the bug in my production application, I cannot get it to happen in the test code.

I have no idea where the bug actually resides at this point. I am satisfied, however, that it does not reside in your plugin, nor in the browsers being used. Thus, I am going to mark this closed, and thank you profusely for your time.

jeliotb jeliotb closed this April 10, 2012
Antony Jones
Owner
aiten commented April 23, 2012

Hi,

Just wondered about your problem as I ran into something similar today. Check that the URL your app is using locally has the same domain and port. If you click authenticate when your browser url is http://localhost:8080 but the provider calls back to http://your.demo.url/oauth/callback then you will get a new (blank!) session.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.