Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GAE Not Recognizing Cookie?

I'm playing around with GAE and Android trying to get an app made for a webservice. I'm going through the steps to get the auth token from AccountManager on Android, getting the Cookie as required, then attaching that cookie to a GET request that the GAE python application handles. For some reason the GAE application doesn't seem to recognize the cookie, or something. Sorry for the huge post, I figured I'd get as much code in here as possible to help explain.

I have this basic class in GAE to test if the user is recognized.

class TestUser(webapp.RequestHandler):
  def get(self):
    if users.get_current_user():
        self.response.out.write(users.get_current_user().nickname())
    else:
        self.response.out.write('no user')

application = webapp.WSGIApplication([
  ('/', MainPage),
  ('/testuser', TestUser)
], debug=True)

def main():
  run_wsgi_app(application)

if __name__ == '__main__':
  main()

From a browser, this works great. I see the user. When executing on Android, I get "no user".

Here's a bunch of Android code:

onCreate:

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        cookieLength = (TextView)findViewById(R.id.cookielength);

        cookie = "";        

        AccountManager manager = AccountManager.get(getApplicationContext());
        Account[] accounts = manager.getAccountsByType("com.google"); 
        new GetAuthTokenTask().execute(accounts);
    }

Get the auth token, invalidate it, and get it again to avoid expired tokens:

private class GetAuthTokenTask extends AsyncTask<Account, Object, String> {

    @Override
    protected String doInBackground(Account... accounts) {
        AccountManager manager = AccountManager.get(getApplicationContext());
        Account account = accounts[0];
        String token = this.buildToken(manager, account);
        Log.d(TAG, "First token: "+token);
        manager.invalidateAuthToken(account.type, token);
        return this.buildToken(manager, account);
    }

    private String buildToken(AccountManager manager, Account account) {
        try {
            AccountManagerFuture<Bundle> future = manager.getAuthToken (account, "ah", false, null, null);
            Bundle bundle = future.getResult();
            return bundle.getString(AccountManager.KEY_AUTHTOKEN);
         } catch (OperationCanceledException e) {
                Log.w(TAG, e.getMessage());
         } catch (AuthenticatorException e) {
                Log.w(TAG, e.getMessage());
         } catch (IOException e) {
                Log.w(TAG, e.getMessage());
         }
         return null;
    }

    protected void onPostExecute(String authToken) {
        Log.d(TAG, "Second token: "+authToken);
        getCookie(authToken);
    }
}

Get the user's cookie, stored in global cookie string.

private void getCookie(final String authToken) {
    new Thread(new Runnable() {
        public void run() {
            String href = "https://someawesomeapp.appspot.com/_ah/login?continue=http://localhost/&auth="+authToken;
            Log.d(TAG, "href: "+href);

            DefaultHttpClient httpclient = new DefaultHttpClient();
            final HttpParams params = new BasicHttpParams();
            HttpClientParams.setRedirecting(params, false);
            httpclient.setParams(params);
            HttpGet httpget = new HttpGet(href);
            try {
                    HttpResponse response = httpclient.execute(httpget);
                    HttpEntity entity = response.getEntity();
                    if (entity != null) {
                        entity.consumeContent();
                    }
                    List<Cookie> cookies = httpclient.getCookieStore().getCookies();
                    Log.d(TAG, "Cookies");
                    if (cookies.isEmpty()) {
                        Log.d(TAG, "None");
                    } else {
                        for (int i = 0; i < cookies.size(); i++) {
                            Log.d(TAG, "- " + cookies.get(i).toString());
                            Cookie c = cookies.get(i);
                            Log.d(TAG, "cookie.getname(): "+c.getName());
                            if (c.getName().contentEquals("SACSID")) {
                                Log.d(TAG, "Found SACSID cookie");
                                cookie = c.getValue();
                                Log.d(TAG, "cookie now set to: "+cookie);
                            }
                        }
                    }
                } catch (ClientProtocolException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

        }
    }).start();
}

We now have a cookie stored, user pressed Test User button in interface, this is executed:

public void testUser(View view) { Log.d(TAG, "testUser()");

String href = "http://someawesomeapp.appspot.com/testuser";


DefaultHttpClient httpclient = new DefaultHttpClient();
    final HttpParams params = new BasicHttpParams();
    HttpClientParams.setRedirecting(params, false);
    httpclient.setParams(params);
    HttpGet httpget = new HttpGet(href);
    httpget.setHeader("Cookie", cookie);
    try {
        HttpResponse response = httpclient.execute(httpget);
        StatusLine status = response.getStatusLine();
        if (status.getStatusCode() != 200) {
            throw new IOException("Invalid response from server: " + status.toString());
        }
        HttpEntity entity = response.getEntity();
        if (entity != null) {
            //entity.consumeContent();
            InputStream inputStream = entity.getContent();
            ByteArrayOutputStream content = new ByteArrayOutputStream();

            // Read response into a buffered stream
            int readBytes = 0;
            byte[] sBuffer = new byte[512];
            while ((readBytes = inputStream.read(sBuffer)) != -1) {
                content.write(sBuffer, 0, readBytes);
            }
            String dataAsString = new String(content.toByteArray());
            Log.d(TAG, "response: "+dataAsString);
        }

    } catch (ClientProtocolException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}

Here's a sniff of the connection from WireShark:

GET /testuser HTTP/1.1
Cookie: AJKiYcEcp6zZHFUoNU5KVlEII_wcWzlBoRQpo-KQ0T_4lwoo0znXn6t7oKpmpa7ctaVY58GO5BmwxkSZ4yZ-e7EOuwTZxeGAuKwI2YrisqjnNuQB36wuzlyBfdY6c7ECcVXuu7BNYlYJtDoB7zJDUCeSXfBmGzrfSh3fHmVO56C540aRmwZKoftRB0ejkdLB6PhUGRXcBI2rbFdvKwuNKJqB0XIr8W_zcEo9AuMjBQqXkDqDUIaGn_ehKfw9c99kzw8cJNHx1EKxVL5Tc2QIYjXWnzTJAYscITCq6IiTTNSdfzWrkbK6Ys9ZOBYNqooaAOxHM5Urx7Cgg0jo2nWQ-tNyKSHfa9Ur7IxBkp137hW7Ar5pimJYb8Jd8oZGwB4uzNHV5V5yZs9aKCqXcaQoz0wgmT5FjT-zqcGz-JfMpGTeubgPg-tQjSvhwPB6mBaXWsOOyuyZPxNeFFDh51WEv53wQs_5fdTwGQ7rQ7ZTEfoBPZNA-JNfo3ecy54DQMmhflmL_IzGE__pNToBi02WlERFm0LclPXtKm4SsDXfTfMPWAve2W1wp-mP-bwB4PljC6NP98WLPWGizRw7g2NwQ_y0iWIogIq9ag
Host: someawesomeapp.appspot.com
Connection: Keep-Alive

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Cache-Control: no-cache
Expires: Fri, 01 Jan 1990 00:00:00 GMT
Vary: Accept-Encoding
Date: Sun, 13 Nov 2011 17:42:34 GMT
Server: Google Frontend
Transfer-Encoding: chunked

7
no user
0

The response here is "No User" from GAE. Any thoughts on how to get GAE to accept and act on the cookie as the user?

27 seconds later, I think I found an issue. Here's a sniff from the browser, I don't have that ACSID= part.

Cookie: ACSID=AJKiYcFeUHZUP56a

Thanks for your help!
Stateful

EDIT: I got it fixed. I need to wait a while to answer my own question though, not enough reputation. Basically, since I'm getting the cookie with SSL, the cookie needs to be prefixed with SACSID rather than ACSID and the testuser url needs to be https as well since that's the cookie we're using.

like image 823
Stateful Avatar asked Nov 13 '11 17:11

Stateful


1 Answers

I got it fixed. For anyone else pulling their hair out:

When you send the request to get the cookie using SSL the response will be prefixed with SACSID, if not it will be ACSID.

on the HTTP request I've changed the cookie addition to:

httpget.setHeader("Cookie", "SACSID="+cookie);

And also, since that's the S cookie, I have to send the request via SSL as such:

like image 50
Stateful Avatar answered Oct 29 '22 17:10

Stateful