Use the high level app_identity call for the AppIdentityCredentials
implementation.

Reviewed in http://codereview.appspot.com/5709043/.
diff --git a/oauth2client/appengine.py b/oauth2client/appengine.py
index b463100..3b7ca3d 100644
--- a/oauth2client/appengine.py
+++ b/oauth2client/appengine.py
@@ -36,7 +36,7 @@
 from client import Storage
 from google.appengine.api import memcache
 from google.appengine.api import users
-from google.appengine.api.app_identity import app_identity
+from google.appengine.api import app_identity
 from google.appengine.ext import db
 from google.appengine.ext import webapp
 from google.appengine.ext.webapp.util import login_required
@@ -56,75 +56,52 @@
   This object will allow an App Engine application to identify itself to Google
   and other OAuth 2.0 servers that can verify assertions. It can be used for
   the purpose of accessing data stored under an account assigned to the App
-  Engine application itself. The algorithm used for generating the assertion is
-  the Signed JSON Web Token (JWT) algorithm. Additional details can be found at
-  the following link:
-
-  http://self-issued.info/docs/draft-jones-json-web-token.html
+  Engine application itself.
 
   This credential does not require a flow to instantiate because it represents
   a two legged flow, and therefore has all of the required information to
   generate and refresh its own access tokens.
-
   """
 
-  def __init__(self, scope,
-      audience='https://accounts.google.com/o/oauth2/token',
-      assertion_type='http://oauth.net/grant_type/jwt/1.0/bearer',
-      token_uri='https://accounts.google.com/o/oauth2/token', **kwargs):
+  def __init__(self, scope, **kwargs):
     """Constructor for AppAssertionCredentials
 
     Args:
-      scope: string, scope of the credentials being requested.
-      audience: string, The audience, or verifier of the assertion.  For
-        convenience defaults to Google's audience.
-      assertion_type: string, Type name that will identify the format of the
-        assertion string.  For convience, defaults to the JSON Web Token (JWT)
-        assertion type string.
-      token_uri: string, URI for token endpoint. For convenience
-        defaults to Google's endpoints but any OAuth 2.0 provider can be used.
+      scope: string or list of strings, scope(s) of the credentials being requested.
     """
+    if type(scope) is list:
+      scope = ' '.join(scope)
     self.scope = scope
-    self.audience = audience
-    self.app_name = app_identity.get_service_account_name()
 
     super(AppAssertionCredentials, self).__init__(
-        assertion_type,
         None,
-        token_uri)
+        None,
+        None)
 
   @classmethod
   def from_json(cls, json):
     data = simplejson.loads(json)
-    retval = AccessTokenCredentials(
-        data['scope'],
-        data['audience'],
-        data['assertion_type'],
-        data['token_uri'])
-    return retval
+    return AppAssertionCredentials(data['scope'])
 
-  def _generate_assertion(self):
-    header = {
-      'typ': 'JWT',
-      'alg': 'RS256',
-    }
+  def _refresh(self, http_request):
+    """Refreshes the access_token.
 
-    now = int(time.time())
-    claims = {
-      'aud': self.audience,
-      'scope': self.scope,
-      'iat': now,
-      'exp': now + 3600,
-      'iss': self.app_name,
-    }
+    Since the underlying App Engine app_identity implementation does its own
+    caching we can skip all the storage hoops and just to a refresh using the
+    API.
 
-    jwt_components = [base64.b64encode(simplejson.dumps(seg))
-        for seg in [header, claims]]
+    Args:
+      http_request: callable, a callable that matches the method signature of
+        httplib2.Http.request, used to make the refresh request.
 
-    base_str = ".".join(jwt_components)
-    key_name, signature = app_identity.sign_blob(base_str)
-    jwt_components.append(base64.b64encode(signature))
-    return ".".join(jwt_components)
+    Raises:
+      AccessTokenRefreshError: When the refresh fails.
+    """
+    try:
+      (token, _) = app_identity.get_access_token(self.scope)
+    except app_identity.Error, e:
+      raise AccessTokenRefreshError(str(e))
+    self.access_token = token
 
 
 class FlowProperty(db.Property):
diff --git a/samples/appengine_with_robots/app.yaml b/samples/appengine_with_robots/app.yaml
index e83ac03..c313482 100644
--- a/samples/appengine_with_robots/app.yaml
+++ b/samples/appengine_with_robots/app.yaml
@@ -1,4 +1,4 @@
-application: urlshortener-robot
+application: robot-sample
 version: 2
 runtime: python
 api_version: 1
diff --git a/samples/appengine_with_robots/main.py b/samples/appengine_with_robots/main.py
index 5bfe13d..7462024 100644
--- a/samples/appengine_with_robots/main.py
+++ b/samples/appengine_with_robots/main.py
@@ -51,8 +51,10 @@
   def get(self):
     path = os.path.join(os.path.dirname(__file__), 'welcome.html')
     shortened = service.url().list().execute()
-    short_and_long = [(item["id"], item["longUrl"]) for item in
-        shortened["items"]]
+    short_and_long = []
+    if 'items' in shortened:
+      short_and_long = [(item["id"], item["longUrl"]) for item in
+          shortened["items"]]
 
     variables = {
         'short_and_long': short_and_long,
@@ -61,6 +63,7 @@
 
   def post(self):
     long_url = self.request.get("longUrl")
+    credentials.refresh(http)
     shortened = service.url().insert(body={"longUrl": long_url}).execute()
     self.redirect("/")
 
diff --git a/tests/test_oauth2client_appengine.py b/tests/test_oauth2client_appengine.py
index 1f58814..a0f32b2 100644
--- a/tests/test_oauth2client_appengine.py
+++ b/tests/test_oauth2client_appengine.py
@@ -24,6 +24,7 @@
 
 import base64
 import httplib2
+import time
 import unittest
 import urlparse
 
@@ -38,9 +39,12 @@
 from apiclient.http import HttpMockSequence
 from google.appengine.api import apiproxy_stub
 from google.appengine.api import apiproxy_stub_map
+from google.appengine.api import app_identity
 from google.appengine.api import users
+from google.appengine.api.memcache import memcache_stub
 from google.appengine.ext import testbed
 from google.appengine.ext import webapp
+from google.appengine.runtime import apiproxy_errors
 from oauth2client.anyjson import simplejson
 from oauth2client.appengine import AppAssertionCredentials
 from oauth2client.appengine import OAuth2Decorator
@@ -49,7 +53,6 @@
 from oauth2client.client import FlowExchangeError
 from webtest import TestApp
 
-
 class UserMock(object):
   """Mock the app engine user service"""
 
@@ -76,51 +79,57 @@
   account_name = "service_account_name@appspot.com"
   signature = "signature"
 
+
   class AppIdentityStubImpl(apiproxy_stub.APIProxyStub):
 
     def __init__(self):
       super(TestAppAssertionCredentials.AppIdentityStubImpl, self).__init__(
           'app_identity_service')
 
-    def _Dynamic_GetServiceAccountName(self, request, response):
-      return response.set_service_account_name(
-          TestAppAssertionCredentials.account_name)
+    def _Dynamic_GetAccessToken(self, request, response):
+      response.set_access_token('a_token_123')
+      response.set_expiration_time(time.time() + 1800)
 
-    def _Dynamic_SignForApp(self, request, response):
-      return response.set_signature_bytes(
-          TestAppAssertionCredentials.signature)
 
-  def setUp(self):
-    app_identity_stub = self.AppIdentityStubImpl()
+  class ErroringAppIdentityStubImpl(apiproxy_stub.APIProxyStub):
+
+    def __init__(self):
+      super(TestAppAssertionCredentials.ErroringAppIdentityStubImpl, self).__init__(
+          'app_identity_service')
+
+    def _Dynamic_GetAccessToken(self, request, response):
+      raise app_identity.BackendDeadlineExceeded()
+
+  def test_raise_correct_type_of_exception(self):
+    app_identity_stub = self.ErroringAppIdentityStubImpl()
+    apiproxy_stub_map.apiproxy = apiproxy_stub_map.APIProxyStubMap()
     apiproxy_stub_map.apiproxy.RegisterStub("app_identity_service",
                                             app_identity_stub)
+    apiproxy_stub_map.apiproxy.RegisterStub(
+      'memcache', memcache_stub.MemcacheServiceStub())
 
-    self.scope = "http://www.googleapis.com/scope"
-    self.credentials = AppAssertionCredentials(self.scope)
+    scope = "http://www.googleapis.com/scope"
+    try:
+      credentials = AppAssertionCredentials(scope)
+      http = httplib2.Http()
+      credentials.refresh(http)
+      self.fail('Should have raised an AccessTokenRefreshError')
+    except AccessTokenRefreshError:
+      pass
 
-  def test_assertion(self):
-    assertion = self.credentials._generate_assertion()
+  def test_get_access_token_on_refresh(self):
+    app_identity_stub = self.AppIdentityStubImpl()
+    apiproxy_stub_map.apiproxy = apiproxy_stub_map.APIProxyStubMap()
+    apiproxy_stub_map.apiproxy.RegisterStub("app_identity_service",
+                                            app_identity_stub)
+    apiproxy_stub_map.apiproxy.RegisterStub(
+      'memcache', memcache_stub.MemcacheServiceStub())
 
-    parts = assertion.split(".")
-    self.assertTrue(len(parts) == 3)
-
-    header, body, signature = [base64.b64decode(part) for part in parts]
-
-    header_dict = simplejson.loads(header)
-    self.assertEqual(header_dict['typ'], 'JWT')
-    self.assertEqual(header_dict['alg'], 'RS256')
-
-    body_dict = simplejson.loads(body)
-    self.assertEqual(body_dict['aud'],
-                     'https://accounts.google.com/o/oauth2/token')
-    self.assertEqual(body_dict['scope'], self.scope)
-    self.assertEqual(body_dict['iss'], self.account_name)
-
-    issuedAt = body_dict['iat']
-    self.assertTrue(issuedAt > 0)
-    self.assertEqual(body_dict['exp'], issuedAt + 3600)
-
-    self.assertEqual(signature, self.signature)
+    scope = "http://www.googleapis.com/scope"
+    credentials = AppAssertionCredentials(scope)
+    http = httplib2.Http()
+    credentials.refresh(http)
+    self.assertEqual('a_token_123', credentials.access_token)
 
 
 class DecoratorTests(unittest.TestCase):