{"id":303,"date":"2008-09-19T16:47:41","date_gmt":"2008-09-19T16:47:41","guid":{"rendered":"http:\/\/dalelane.co.uk\/blog\/?p=303"},"modified":"2009-08-24T15:53:54","modified_gmt":"2009-08-24T15:53:54","slug":"programmatically-accessing-authenticated-google-app-engine-services","status":"publish","type":"post","link":"https:\/\/dalelane.co.uk\/blog\/?p=303","title":{"rendered":"Programmatically accessing authenticated Google App Engine services"},"content":{"rendered":"<p>This one has been bugging me for a few days, and with help from a <a target=\"_blank\"  href=\"http:\/\/stackoverflow.com\/users\/12030\/arachnid\">very helpful Google engineer<\/a> I&#8217;ve finally got this working, so I thought I&#8217;d share my code where the next poor soul to try and do it might find it! <\/p>\n<p><strong>The problem:<\/strong><br \/>\nI&#8217;ve written a small web service which I am hosting on <a target=\"_blank\" href=\"http:\/\/code.google.com\/appengine\/\">Google App Engine<\/a>. <\/p>\n<p>By adding &#8220;<code>login: required<\/code>&#8221; to specific services in the app&#8217;s app.yaml file, I can <a target=\"_blank\" href=\"http:\/\/code.google.com\/appengine\/docs\/configuringanapp.html#Requiring_Login_or_Administrator_Status\">make sure that you need to login to access a service<\/a>.<\/p>\n<p>If you&#8217;re accessing the service from a web browser, this is fine &#8211; you get redirected to a Google login page, and after entering your username and password and hitting &#8216;submit&#8217;, you get sent on to the web service you wanted.<\/p>\n<p>But how do you do that programmatically? I wanted to do it from a Python application on my desktop, without being able to navigate the HTML login form. <\/p>\n<p><!--more-->I tried asking for help on <a href=\"http:\/\/stackoverflow.com\/\" target=\"_blank\">Stack Overflow<\/a>, and within a couple of hours, someone <a target=\"_blank\" href=\"http:\/\/stackoverflow.com\/questions\/101742\/how-do-you-access-an-authenticated-google-app-engine-service-from-a-non-web-pyt#102509\">pointed me in the right direction<\/a>. (<em>Which is very cool, by the way<\/em>)<\/p>\n<p>A simplified version of my current code is below. <\/p>\n<p>In short, you use the <a href=\"http:\/\/code.google.com\/apis\/accounts\/docs\/AuthForInstalledApps.html\">Google ClientLogin API<\/a> to get an AuthToken. <\/p>\n<p>You use this AuthToken to get a cookie from <code>http:\/\/mylovelyapp.appspot.com\/_ah\/login\/<\/code>.<\/p>\n<p>Easy when you know how! <\/p>\n<pre style=\"overflow: scroll; font-size: 1.1em; border: thin solid silver; background-color: #eeeeee; padding: 0.8em\">\r\nimport os\r\nimport urllib\r\nimport urllib2\r\nimport cookielib\r\n\r\nusers_email_address = \"billy.bob@gmail.com\"\r\nusers_password      = \"billybobspassword\"\r\n\r\ntarget_authenticated_google_app_engine_uri = 'http:\/\/mylovelyapp.appspot.com\/mylovelypage'\r\nmy_app_name = \"yay-1.0\"\r\n\r\n\r\n\r\n# we use a cookie to authenticate with Google App Engine\r\n#  by registering a cookie handler here, this will automatically store the \r\n#  cookie returned when we use urllib2 to open http:\/\/mylovelyapp.appspot.com\/_ah\/login\r\ncookiejar = cookielib.LWPCookieJar()\r\nopener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookiejar))\r\nurllib2.install_opener(opener)\r\n\r\n#\r\n# get an AuthToken from Google accounts\r\n#\r\nauth_uri = 'https:\/\/www.google.com\/accounts\/ClientLogin'\r\nauthreq_data = urllib.urlencode({ \"Email\":   users_email_address,\r\n                                  \"Passwd\":  users_password,\r\n                                  \"service\": \"ah\",\r\n                                  \"source\":  my_app_name,\r\n                                  \"accountType\": \"HOSTED_OR_GOOGLE\" })\r\nauth_req = urllib2.Request(auth_uri, data=authreq_data)\r\nauth_resp = urllib2.urlopen(auth_req)\r\nauth_resp_body = auth_resp.read()\r\n# auth response includes several fields - we're interested in \r\n#  the bit after Auth= \r\nauth_resp_dict = dict(x.split(\"=\")\r\n                      for x in auth_resp_body.split(\"\\n\") if x)\r\nauthtoken = auth_resp_dict[\"Auth\"]\r\n\r\n#\r\n# get a cookie\r\n# \r\n#  the call to request a cookie will also automatically redirect us to the page\r\n#   that we want to go to\r\n#  the cookie jar will automatically provide the cookie when we reach the \r\n#   redirected location\r\n\r\n# this is where I actually want to go to\r\nserv_uri = target_authenticated_google_app_engine_uri\r\n\r\nserv_args = {}\r\nserv_args['continue'] = serv_uri\r\nserv_args['auth']     = authtoken\r\n\r\nfull_serv_uri = \"http:\/\/mylovelyapp.appspot.com\/_ah\/login?%s\" % (urllib.urlencode(serv_args))\r\n\r\nserv_req = urllib2.Request(full_serv_uri)\r\nserv_resp = urllib2.urlopen(serv_req)\r\nserv_resp_body = serv_resp.read()\r\n\r\n# serv_resp_body should contain the contents of the \r\n#  target_authenticated_google_app_engine_uri page - as we will have been \r\n#  redirected to that page automatically \r\n#\r\n# to prove this, I'm just gonna print it out\r\nprint serv_resp_body\r\n<\/pre>\n<p><em>Note: If you&#8217;re going to copy and paste this code, be aware that WordPress sometimes screws with single and double-quotes in my posts. So you might need to go through and check they&#8217;re all okay.<\/em><\/p>\n<p><strong>Update:<\/strong> If you want to do this from a C# client, I have <a href=\"http:\/\/dalelane.co.uk\/blog\/?p=894\">written a post about how to do it<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This one has been bugging me for a few days, and with help from a very helpful Google engineer I&#8217;ve finally got this working, so I thought I&#8217;d share my code where the next poor soul to try and do it might find it! The problem: I&#8217;ve written a small web service which I am [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[158,231,212,280],"class_list":["post-303","post","type-post","status-publish","format-standard","hentry","category-code","tag-google","tag-google-app-engine","tag-python","tag-stackoverflow"],"_links":{"self":[{"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/303","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=303"}],"version-history":[{"count":0,"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/303\/revisions"}],"wp:attachment":[{"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=303"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=303"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=303"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}