Here, OAuth steps 1 and 2 take place. First, your application requests a request token from Healthx. Then your application exchanges that request token for an authorization token, redirecting the user to the Healthx authorization page. We save the token and secret so that we can use them later, so we need to create a model class. For more on the model class, refer to
You can see in the OAuthPage class, as well as the MainPage class, we store these AppAuthTokens using the
method. We need to store the tokens for each user so that we can retrieve them when the user returns from the login page. We store the verifier so that we can retrieve the authorization token when we direct the user to the GetElig page. This page takes care of OAuth step 3, exchanging an authorized token for an access token, which then gets stored and used to make requests to protected resources.
class GetElig(webapp.RequestHandler):
def post(self):
self.response.headers['Content-Type'] = 'text/html'
self.response.out.write('<html><head><title>Get Eligibility</title></head><body>')
if (self.request.get('oauth_verifier') and self.request.get('oauth_verifier') != 'None'):
upgrade_url=BASEPATH + '/api/Accounts/OAuthGetAccessToken'
consumer = OAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET)
sigMethod = OAuthSignatureMethod_HMAC_SHA1()
query=AppAuthToken.all()
#For this demo, we use verifer to look up your token for convenience because it is already URL encoded.
# This is not suitable for production code, though it is secured through the Service Provider (healthx).
query.filter('verifier =', self.request.get('oauth_verifier'))
mytoken = query.fetch(1)
if ((mytoken[0])==None):
#if can't find the token, prompt the user to get a different one.
self.response.out.write("Oops. We seem to have lost your login, <a href='../oauthtoken'>please login again.</a>'")
#if we haven't gotten an auth token for the user yet, get one.
elif mytoken[0].accessTokenString is None:
token=OAuthToken(urllib.unquote(mytoken[0].tokenkey), mytoken[0].tokensecret)
token.set_verifier(mytoken[0].verifier)
request=OAuthRequest.from_consumer_and_token(consumer,token, None,token.verifier,"GET", upgrade_url.lower())
#from_consumer_and_token automatically puts in oauth_callback, but this param is not allowed by spec
del request.parameters['oauth_callback']
request.sign_request(sigMethod, consumer, token)
authheader=request.to_header()
result = urlfetch.fetch(url=upgrade_url, method=urlfetch.GET, payload="", headers={"Authorization":authheader['Authorization'], "charset":"utf-8"})
if result.status_code != 200:
self.response.out.write("failed with result " + str(result.status_code))
self.response.out.write("<div>" + str(result.content) + "</div>")
else:
tokenstring=(str(result.content))
#UTF-8 strings can sometimes contain BOM character to start, but the parse_qs method inside of OAuthToken.from_string doesn't like BOM.
if (tokenstring.startswith(codecs.BOM_UTF8)):
tokenstring=tokenstring.lstrip(codecs.BOM_UTF8)
token=OAuthToken.from_string(tokenstring)
#if we've already got an auth token for this user, then we'll just use it.
else:
token=OAuthToken.from_string(mytoken[0].accessTokenString)
try:
get_elig_url='%(basepath)s/api/eligibilityv1/json/getfamily' % {'basepath':BASEPATH}
#saving this token in the datastore so if the user clicks the back button, we can reuse the token.
mytoken[0].accessTokenString=token.to_string()
mytoken[0].put()
eligRequest=OAuthRequest.from_consumer_and_token(consumer,token,None,None,"GET",get_elig_url.lower())
eligRequest.sign_request(sigMethod, consumer, token)
eligpostdata=eligRequest.to_postdata()
eligpostdata=simplejson.dumps(eligpostdata)
#realm param is included in signaturebasestring in the Healthx implementation, but not the python library(as per spec).
eligAuthheader=eligRequest.to_header()
eligAuthheader['Authorization']=eligAuthheader['Authorization'].replace('realm="", ','')
eligResult = urlfetch.fetch(url=get_elig_url, method=urlfetch.GET, payload='', headers={"Authorization":eligAuthheader['Authorization'], 'instanceid': INSTANCE_ID, "charset":"utf-8", "content-type":"application/json"})
if eligResult.status_code!=200:
self.response.out.write("Elig Request Failed with result " + str(eligResult.status_code))
self.response.out.write("<div>" + str(eligResult.content) + "</div>")
self.response.out.write("<div>" + str(sigMethod.build_signature_base_string(eligRequest,consumer,token))+ "</div>")
else:
eligInfo = None
if eligResult.status_code == 200:
eligInfo = simplejson.loads(eligResult.content)
#write out data
for eligRec in eligInfo:
type = None
if not eligRec['IsDependent']:
type = 'Member'
else:
type = 'Dependent'
self.response.out.write("<div><h2>%(fname)s %(lname)s</h2></div>" % {'fname':eligRec['FirstName'],'lname':eligRec['LastName']})
self.response.out.write("<div><b>%s</b></div>" % type)
self.response.out.write("<div>Member ID : %s</div>" % eligRec['MemberID'])
self.response.out.write("<div>Address : %s</div>" % eligRec['Address'])
self.response.out.write("<div>Benefit Plan : %s</div>" % eligRec['BnftPlan'])
#self.response.out.write("<div>" + eligAuthheader2 + "</div>")
except KeyError, k:
self.response.out.write("Could not find key : " + str(k.args))
self.response.out.write(eligInfo)
self.response.out.write("<div><a href='../oauthpage'>Click here to start over.</a></div>")
else:
self.redirect('../')
self.response.out.write('</body></html>')