12

I am trying to incorporate google analytics graph at web app to show user statistics of their app usages. This is the local url http://192.168.100.10:9000/ i login to dashboard (web app) i have a google sign in button. So far here i maintain the session of the user after when he logs in.

And when user click on the sign in button. It triggers callback method. When callback is triggered first time then it has session maintained. I mean session("user") isn't null here.

public Result callback() {
    JsonNode jsonNode = Json.parse(session("user"));
    UserDTO userDTO = Json.fromJson(jsonNode, UserDTO.class);

    if (userDTO.getRole().getType().equals(RoleDTO.EnRoleType.ADMIN.toString()))
        return redirect(com.softoven.ultron.controllers.routes.AccountCTRL.index());
    if (request().queryString().get("code") != null && request().queryString().get("state") != null && request().queryString().get("state")[0].equals(session("state"))) { // Check if he/she is authorized
        session().remove("state");
        Analytics analytics = setAnalytics(userDTO, request());
        session("analytics", Json.toJson(analytics).toString());
        return redirect(com.softoven.ultron.controllers.routes.AccountCTRL.index());
    } else {  // Create Authorization URL
        String url = helper.buildLoginUrl();
        session("state", helper.getStateToken());
        return redirect(url);
    }
}

This is the url when user clicks on the sign in button https://accounts.google.com/o/oauth2/auth?access_type=offline&approval_prompt=force&client_id=784122128025-cvq0fn1e23f24dia4soavsd9v1ovesub.apps.googleusercontent.com&redirect_uri=http://localhost:9000/callback&response_type=code&scope=https://www.googleapis.com/auth/analytics.readonly%20https://www.googleapis.com/auth/analytics.manage.users%20https://www.googleapis.com/auth/analytics%20https://www.googleapis.com/auth/analytics.edit%20https://www.googleapis.com/auth/analytics.manage.users.readonly%20https://www.googleapis.com/auth/analytics.provision&state=google-35808300 And when user click on the allow button on the permission page of the google sign in then control goes back to callback()

enter image description here

but this time session("user") is null. which shouldn't be null because i had set the session when user logged in. I don't know why is it happening and how to fix this.

And this is the end url after the redirect from google permission page. http://localhost:9000/callback?state=google-35808300&code=4/g-FkJ3GGS01jbeXLHK0o95ks-K-drGK7bxgzvi3cELU#

Zeeshan Shabbir
  • 6,704
  • 4
  • 38
  • 74
  • Are you using the [Google Java Client library](https://developers.google.com/api-client-library/java/google-api-java-client/oauth2#web_server_applications)? If not it might greatly simplify what your are trying to do. – Matt Jul 23 '16 at 00:09
  • yes i am using google java client library. – Zeeshan Shabbir Jul 24 '16 at 14:47
  • 1
    IP/localhost? Align out to be the same or use a real domain name and retry (use hosts file to fake a real domainname). HTTP session is tied to a cookie and cookies are IP/domain specific. Browsers are also very strict on this, e.g. Chrome doesn't like a cookie domain being explicitly set to "localhost". – BalusC Jul 24 '16 at 14:53
  • yes i was testing this on localhost. So you are suggesting that i should test it on real domain? – Zeeshan Shabbir Jul 24 '16 at 14:59
  • 1
    I think that what @BalusC suggests was that you must use the same url consistently in your test. If you are testing with `localhost`, do not mix it with the ip version (`192.168.100.10`) since the browser will treat them as different hosts. The cookies from one host are not accessible by another one and Play uses cookies to store session information. – marcospereira Jul 25 '16 at 05:29
  • Thank you so much for commenting on this and explaining. I will let you know if this works – Zeeshan Shabbir Jul 25 '16 at 05:35
  • 1
    Zeeshan, if multiple people have commented on your post, use `@nickname` to notify the target person about a comment-reply, otherwise it goes unnoticed. Yes, you opened the page by an IP address and ended up in a localhost address. This is not correct. As said, cookies depend on IP/domain. Use the same IP or domain throughout the process and don't use "localhost". You can use hosts file to fake a real domain name. Let me know if that works then I will repost it in an answer. – BalusC Jul 25 '16 at 07:08
  • @BalusC Thank you so much. I was so much excited to see your comment on my SO and it worked. You can post this as answer, i will accept right away. – Zeeshan Shabbir Jul 25 '16 at 07:10
  • Only if you have confirmed that it works. I'm not familiar with Play framework so I may have overlooked something. At least I know how HTTP and sessions are supposed to work at low level. – BalusC Jul 25 '16 at 07:11
  • @BalusC it did work. i am also not familiar with Play framework. I just added some calls to already coded api. Anyway thank you once again – Zeeshan Shabbir Jul 25 '16 at 07:13

1 Answers1

5

This is the local url http://192.168.100.10:9000/ ...

... &redirect_uri=http://localhost:9000/ ...

And this is the end url after the redirect from google permission page http://localhost:9000/ ...

The starting URL is different from the ending URL. This is not correct.

Normally, the HTTP session in server side is tied to a session cookie. Cookies are in turn tied to a specific hostname (IP or domain). Webbrowsers are very strict in sending cookies to the specific hostname. Even though the IP would DNS-resolve to the correct domain, webbrowsers may refuse sending the cookie created on an IP address along with a request on the domain name. Basically, the webserver won't retrieve the originally created session cookie and hence creates a new one.

Then there exist webbrowsers who reject cookies whose hostname is explicitly set to "localhost", such as Google Chrome: Chrome doesn't create cookie for domain=localhost in broken https. Browsers may also choose to reject cookies whose hostname is explicitly set to an IP address because this may cause security trouble when client uses a dynamic IP.

It's therefore strongly recommended to use a real domain name such as example.com instead of an IP address or "localhost". Without buying one, you can fake one by simply editing the hosts file. The format of each line is like below, first the IP addres and thereafter the desired domains space separated.

127.0.0.1 localhost example.com anotherexample.com

Then consistently use exactly that domain throughout the process. Start at http://example.com:9000/..., use &redirect_uri=http://example.com:9000/... etc.

I don't do Play Framework, but if you're familiar with Servlet API, you may better understand the working of the HTTP session after reading this related Q&A: How do servlets work? Instantiation, sessions, shared variables and multithreading.

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555