Add robot helpers and a sample.
diff --git a/oauth2client/appengine.py b/oauth2client/appengine.py
index 71aa8f0..a9766c7 100644
--- a/oauth2client/appengine.py
+++ b/oauth2client/appengine.py
@@ -21,14 +21,29 @@
 
 import httplib2
 import pickle
+import time
+import base64
+import logging
+
+try: # pragma: no cover
+  import simplejson
+except ImportError: # pragma: no cover
+  try:
+    # Try to import from django, should work on App Engine
+    from django.utils import simplejson
+  except ImportError:
+    # Should work for Python2.6 and higher.
+    import json as simplejson
 
 from client import AccessTokenRefreshError
+from client import AssertionCredentials
 from client import Credentials
 from client import Flow
 from client import OAuth2WebServerFlow
 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.ext import db
 from google.appengine.ext import webapp
 from google.appengine.ext.webapp.util import login_required
@@ -36,6 +51,76 @@
 
 OAUTH2CLIENT_NAMESPACE = 'oauth2client#ns'
 
+
+class AppAssertionCredentials(AssertionCredentials):
+  """Credentials object for App Engine Assertion Grants
+
+  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
+
+  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.
+
+  AssertionFlowCredentials objects may be safely pickled and unpickled.
+  """
+
+  def __init__(self, scope, user_agent,
+      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):
+    """Constructor for AppAssertionCredentials
+
+    Args:
+      scope: string, scope of the credentials being requested.
+      user_agent: string, The HTTP User-Agent to provide for this application.
+      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.
+    """
+    self.scope = scope
+    self.audience = audience
+    self.app_name = app_identity.get_service_account_name()
+
+    super(AppAssertionCredentials, self).__init__(
+        assertion_type,
+        user_agent,
+        token_uri)
+
+  def _generate_assertion(self):
+    header = {
+      'typ': 'JWT',
+      'alg': 'RS256',
+    }
+
+    now = int(time.time())
+    claims = {
+      'aud': self.audience,
+      'scope': self.scope,
+      'iat': now,
+      'exp': now + 3600,
+      'iss': self.app_name,
+    }
+
+    jwt_components = [base64.b64encode(simplejson.dumps(seg))
+        for seg in [header, claims]]
+
+    base_str = ".".join(jwt_components)
+    key_name, signature = app_identity.sign_blob(base_str)
+    jwt_components.append(base64.b64encode(signature))
+    return ".".join(jwt_components)
+
+
 class FlowProperty(db.Property):
   """App Engine datastore Property for Flow.
 
@@ -117,7 +202,7 @@
     Args:
       model: db.Model, model class
       key_name: string, key name for the entity that has the credentials
-      property_name: string, name of the property that is an CredentialsProperty
+      property_name: string, name of the property that is a CredentialsProperty
       cache: memcache, a write-through cache to put in front of the datastore
     """
     self._model = model
@@ -189,6 +274,7 @@
         # in API calls
 
   """
+
   def __init__(self, client_id, client_secret, scope, user_agent,
                auth_uri='https://accounts.google.com/o/oauth2/auth',
                token_uri='https://accounts.google.com/o/oauth2/token'):
@@ -205,8 +291,8 @@
       token_uri: string, URI for token endpoint. For convenience
         defaults to Google's endpoints but any OAuth 2.0 provider can be used.
     """
-    self.flow = OAuth2WebServerFlow(client_id, client_secret, scope, user_agent,
-      auth_uri, token_uri)
+    self.flow = OAuth2WebServerFlow(client_id, client_secret, scope,
+      user_agent, auth_uri, token_uri)
     self.credentials = None
     self._request_handler = None
 
@@ -220,6 +306,7 @@
       method: callable, to be decorated method of a webapp.RequestHandler
         instance.
     """
+
     def check_oauth(request_handler, *args):
       user = users.get_current_user()
       # Don't use @login_decorator as this could be used in a POST request.
@@ -255,6 +342,7 @@
       method: callable, to be decorated method of a webapp.RequestHandler
         instance.
     """
+
     def setup_oauth(request_handler, *args):
       user = users.get_current_user()
       # Don't use @login_decorator as this could be used in a POST request.
@@ -308,10 +396,12 @@
     error = self.request.get('error')
     if error:
       errormsg = self.request.get('error_description', error)
-      self.response.out.write('The authorization request failed: %s' % errormsg)
+      self.response.out.write(
+          'The authorization request failed: %s' % errormsg)
     else:
       user = users.get_current_user()
-      flow = pickle.loads(memcache.get(user.user_id(), namespace=OAUTH2CLIENT_NAMESPACE))
+      flow = pickle.loads(memcache.get(user.user_id(),
+                                       namespace=OAUTH2CLIENT_NAMESPACE))
       # This code should be ammended with application specific error
       # handling. The following cases should be considered:
       # 1. What if the flow doesn't exist in memcache? Or is corrupt?
@@ -328,6 +418,7 @@
 
 application = webapp.WSGIApplication([('/oauth2callback', OAuth2Handler)])
 
+
 def main():
   run_wsgi_app(application)
 
diff --git a/oauth2client/client.py b/oauth2client/client.py
index 3c59980..523a185 100644
--- a/oauth2client/client.py
+++ b/oauth2client/client.py
@@ -83,6 +83,7 @@
     """
     _abstract()
 
+
 class Flow(object):
   """Base class for all Flow objects."""
   pass
@@ -94,7 +95,6 @@
   Store and retrieve a single credential.
   """
 
-
   def get(self):
     """Retrieve credential.
 
@@ -187,6 +187,26 @@
     self.__dict__.update(state)
     self.store = None
 
+  def _generate_refresh_request_body(self):
+    """Generate the body that will be used in the refresh request
+    """
+    body = urllib.urlencode({
+      'grant_type': 'refresh_token',
+      'client_id': self.client_id,
+      'client_secret': self.client_secret,
+      'refresh_token': self.refresh_token,
+      })
+    return body
+
+  def _generate_refresh_request_headers(self):
+    """Generate the headers that will be used in the refresh request
+    """
+    headers = {
+        'user-agent': self.user_agent,
+        'content-type': 'application/x-www-form-urlencoded',
+    }
+    return headers
+
   def _refresh(self, http_request):
     """Refresh the access_token using the refresh_token.
 
@@ -194,16 +214,9 @@
        http: An instance of httplib2.Http.request
            or something that acts like it.
     """
-    body = urllib.urlencode({
-      'grant_type': 'refresh_token',
-      'client_id': self.client_id,
-      'client_secret': self.client_secret,
-      'refresh_token' : self.refresh_token
-      })
-    headers = {
-        'user-agent': self.user_agent,
-        'content-type': 'application/x-www-form-urlencoded'
-    }
+    body = self._generate_refresh_request_body()
+    headers = self._generate_refresh_request_headers()
+
     logging.info("Refresing access_token")
     resp, content = http_request(
         self.token_uri, method='POST', body=body, headers=headers)
@@ -214,14 +227,14 @@
       self.refresh_token = d.get('refresh_token', self.refresh_token)
       if 'expires_in' in d:
         self.token_expiry = datetime.timedelta(
-            seconds = int(d['expires_in'])) + datetime.datetime.now()
+            seconds=int(d['expires_in'])) + datetime.datetime.now()
       else:
         self.token_expiry = None
       if self.store is not None:
         self.store(self)
     else:
-      # An {'error':...} response body means the token is expired or revoked, so
-      # we flag the credentials as such.
+      # An {'error':...} response body means the token is expired or revoked,
+      # so we flag the credentials as such.
       logging.error('Failed to retrieve access token: %s' % content)
       error_msg = 'Invalid response %s.' % resp['status']
       try:
@@ -232,7 +245,8 @@
           if self.store is not None:
             self.store(self)
           else:
-            logging.warning("Unable to store refreshed credentials, no Storage provided.")
+            logging.warning(
+                "Unable to store refreshed credentials, no Storage provided.")
       except:
         pass
       raise AccessTokenRefreshError(error_msg)
@@ -266,6 +280,10 @@
     def new_request(uri, method='GET', body=None, headers=None,
                     redirections=httplib2.DEFAULT_MAX_REDIRECTS,
                     connection_type=None):
+      if not self.access_token:
+        logging.info("Attempting refresh to obtain initial access_token")
+        self._refresh(request_orig)
+
       """Modify the request headers to add the appropriate
       Authorization header."""
       if headers == None:
@@ -275,8 +293,10 @@
         headers['user-agent'] = self.user_agent + ' ' + headers['user-agent']
       else:
         headers['user-agent'] = self.user_agent
+
       resp, content = request_orig(uri, method, body, headers,
                                    redirections, connection_type)
+
       if resp.status == 401:
         logging.info("Refreshing because we got a 401")
         self._refresh(request_orig)
@@ -341,6 +361,57 @@
     raise AccessTokenCredentialsError(
         "The access_token is expired or invalid and can't be refreshed.")
 
+
+class AssertionCredentials(OAuth2Credentials):
+  """Abstract Credentials object used for OAuth 2.0 assertion grants
+
+  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.  It must be subclassed to
+  generate the appropriate assertion string.
+
+  AssertionCredentials objects may be safely pickled and unpickled.
+  """
+
+  def __init__(self, assertion_type, user_agent,
+      token_uri='https://accounts.google.com/o/oauth2/token', **kwargs):
+    """Constructor for AssertionFlowCredentials
+
+    Args:
+      assertion_type: string, assertion type that will be declared to the auth
+          server
+      user_agent: string, The HTTP User-Agent to provide for this application.
+      token_uri: string, URI for token endpoint. For convenience
+        defaults to Google's endpoints but any OAuth 2.0 provider can be used.
+    """
+    super(AssertionCredentials, self).__init__(
+        None,
+        None,
+        None,
+        None,
+        None,
+        token_uri,
+        user_agent)
+    self.assertion_type = assertion_type
+
+  def _generate_refresh_request_body(self):
+    assertion = self._generate_assertion()
+
+    body = urllib.urlencode({
+      'assertion_type': self.assertion_type,
+      'assertion': assertion,
+      'grant_type': "assertion",
+    })
+
+    return body
+
+  def _generate_assertion(self):
+    """Generate the assertion string that will be used in the access token
+    request.
+    """
+    _abstract()
+
+
 class OAuth2WebServerFlow(Flow):
   """Does the Web Server Flow for OAuth 2.0.
 
@@ -420,15 +491,16 @@
       'client_secret': self.client_secret,
       'code': code,
       'redirect_uri': self.redirect_uri,
-      'scope': self.scope
+      'scope': self.scope,
       })
     headers = {
       'user-agent': self.user_agent,
-      'content-type': 'application/x-www-form-urlencoded'
+      'content-type': 'application/x-www-form-urlencoded',
     }
     if http is None:
       http = httplib2.Http()
-    resp, content = http.request(self.token_uri, method='POST', body=body, headers=headers)
+    resp, content = http.request(self.token_uri, method='POST', body=body,
+                                 headers=headers)
     if resp.status == 200:
       # TODO(jcgregorio) Raise an error if simplejson.loads fails?
       d = simplejson.loads(content)
@@ -436,12 +508,13 @@
       refresh_token = d.get('refresh_token', None)
       token_expiry = None
       if 'expires_in' in d:
-        token_expiry = datetime.datetime.now() + datetime.timedelta(seconds = int(d['expires_in']))
+        token_expiry = datetime.datetime.now() + datetime.timedelta(
+            seconds=int(d['expires_in']))
 
       logging.info('Successfully retrieved access token: %s' % content)
-      return OAuth2Credentials(access_token, self.client_id, self.client_secret,
-                               refresh_token, token_expiry, self.token_uri,
-                               self.user_agent)
+      return OAuth2Credentials(access_token, self.client_id,
+                               self.client_secret, refresh_token, token_expiry,
+                               self.token_uri, self.user_agent)
     else:
       logging.error('Failed to retrieve access token: %s' % content)
       error_msg = 'Invalid response %s.' % resp['status']