Tornado google oauth error - python

I have the next problem with tornado.oauth : when user logs in with Google,Google sends me code to my redirect uri and then I try to get some information about user with the function get_authenticated_user
class GoogleOAuth2CodeHandler(tornado.web.RequestHandler,
tornado.auth.GoogleOAuth2Mixin):
#tornado.gen.coroutine
def get(self):
user =yield self.get_authenticated_user(
redirect_uri='http://localhost:8890/userdata',
code=self.get_argument("code")
)
self.write("hello world!")
but it fails with the next error:
ERROR:tornado.application:Uncaught exception GET
KeyError: 'google_oauth'
Settings:
settings = dict(
cookie_secret="32oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o/Vo=",
login_url="/auth/login",
redirect_uri="http://localhost:8890/auth",
google_consumer_key="",
google_consumer_secret="",
google_permissions="https://mail.google.com/ https://www.google.com/m8/feeds",
google_permissions2="https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email"
))
consumer_key and consumer_secret are correct
authorize_redirect works correctly and I really get correct google code

google_consumer_key and google_consumer_secret are from the OAuth1 Google mixin. For oauth2, you need a google_oauth setting, which should be a dict containing 'key' and 'secret' fields:
google_oauth={"key": CLIENT_ID, "secret": CLIENT_SECRET},

Related

Showing invalid_scope when adding profile or request

I am trying to access Uber API for requesting rides and I am trying to access appropriate scope like
profile
request_rides
request
And I successfully got the token, clientid, clientsecret, access_token and Then I tried to access profile by calling
from uber_rides.auth import AuthorizationCodeGrant
auth_flow = AuthorizationCodeGrant(
<CLIENT_ID>,
<SCOPES>,
<CLIENT_SECRET>,
<REDIRECT_URI>
)
auth_url = auth_flow.get_authorization_url()
session = auth_flow.get_session(redirect_url)
client = UberRidesClient(session, sandbox_mode=True)
credentials = session.oauth2credential
Above commands didn't raise any errors but when I execute
response = client.get_user_profile()
then I showed
uber_rides.errors.ClientError: 401: This endpoint requires at least one of the following scopes: profile, eats.pos_provisioning, profile.internal_uuid
And When I append profile in below <SCOPES> in browser then It showed invalid_scope . I have no idea why it is showing this error every time I call the url to get the session.
In https://login.uber.com/oauth/v2/token?clientid= POST request, it is showing only "scope": "offline_access" in scope.
So How can I get the access of profile and request_rides scope ?
Any help would be much Appreciated.

ADAL for Python bearer token write access issue

Using this config in the https://github.com/Azure-Samples/ms-identity-python-webapp worked for me. The scope must include the CDS organization/environment API URL.
CLIENT_SECRET = "**********************************"
AUTHORITY = "https://login.microsoftonline.com/common"
CLIENT_ID = "3641e71b-ad98-4489-8423-f77532d0a5d5"
REDIRECT_PATH = "/getAToken"
ENDPOINT = 'https://graph.microsoft.com/v1.0/users'
CDS_ENDPOINT = "https://REPLACE_WITH_ORG_NAME.api.crm.dynamics.com/api/data/v9.0/msmrw_guides?$select=msmrw_name&$expand=msmrw_guide_Annotations"
# cds environment / crm org, MUST be a part of the scope
SCOPE = ["https://REPLACE_WITH_ORG_NAME.api.crm.dynamics.com/user_impersonation"]
SESSION_TYPE = "filesystem"
ADAL issue Pyhton bearer token issue
I am authenticating non-interactively with a client id and secret for my REST application that interacts with the Common Data Service. Testing first in Postman I am able to perform both read and write operations using my credentials successfully.
When implementing the REST API in Python I can only perform Read operations through the Azure AD Authentication Library (ADAL) with version adal==1.2.2. I am using the same credentials from my Postman environment in Python through a config file, an example is further below. I also tested this Python ADAL generated token in Postman to verify that I can make get requests since I noticed the token strings are different between the one I generate in Python and one I generate in Postman. When making a post request I get the error shown even further below. My guess is I need logic in python to somehow tell ADAL the user requesting the token is allowed write permissions.
Code and Postman error
import adal
from .config import *
class AzureAuth:
bearerToken = ""
def __init__(self):
authCtx = adal.AuthenticationContext(AUTHORITY_URL)
tokenResponse = authCtx.acquire_token_with_client_credentials(RESOURCE, CLIENT_ID, CLIENT_SECRET)
self.bearerToken = tokenResponse["accessToken"]
Here's an example of what my config.py looks like.
AUTHORITY_URL=""
CDS_API_URL=""
CLIENT_ID=""
CLIENT_SECRET=""
REDIRECT_URI=""
RESOURCE="" # like "https://your_cds_environment.api.crm.dynamics.com/"
TENANT="" # like "https://login.microsoftonline.com/put_your_tenant"
Error thrown in Postman when I copy paste the Python token into a Postman post request.
{
"error": {
"code": "0x80048306",
"message": "{\"CallerPrincipal\":{\"PrincipalId\":\"96b856f4-134c-e911-a823-000d3a1d5de8\",\"Type\":8,\"IsUserPrincipal\":true,\"IsTeamPrincipal\":false,\"TypeName\":\"user\"},\"OwnerPrincipal\":{\"PrincipalId\":\"96b856f4-134c-e911-a823-000d3a1d5de8\",\"Type\":8,\"IsUserPrincipal\":true,\"IsTeamPrincipal\":false,\"TypeName\":\"user\"},\"CallerInfo\":{\"IsSystemUser\":false,\"IsSupportUser\":false,\"IsAdministrator\":false,\"IsCustomizer\":false,\"IsDisabled\":false,\"IsIntegrationUser\":false,\"Privileges\":null,\"Teams\":null,\"Roles\":null},\"ObjectId\":\"00000000-0000-0000-0000-000000000000\",\"ObjectTypeCode\":10410,\"ObjectBusinessUnitId\":\"1abfdddc-8140-e911-a823-000d3a1a25b8\",\"OrganizationId\":\"08907b95-ee84-4861-b141-b584fecc774d\",\"EntityName\":\"msmrw_guide\",\"EntityOwnershipTypeMask\":1,\"EntityPrivileges\":[{\"Id\":\"915a1feb-2a56-4a8c-bea0-3256728785e5\",\"ObjectTypeCode\":10410,\"Name\":\"prvCreatemsmrw_guide\",\"AccessRight\":32,\"PrivilegeType\":0,\"CanBeBasic\":true,\"CanBeLocal\":true,\"CanBeDeep\":true,\"CanBeGlobal\":true,\"CanBeEntityReference\":true,\"CanBeParentEntityReference\":true},{\"Id\":\"6415b9e2-24c4-408a-a830-85c21ab8ac72\",\"ObjectTypeCode\":10410,\"Name\":\"prvReadmsmrw_guide\",\"AccessRight\":1,\"PrivilegeType\":1,\"CanBeBasic\":true,\"CanBeLocal\":true,\"CanBeDeep\":true,\"CanBeGlobal\":true,\"CanBeEntityReference\":true,\"CanBeParentEntityReference\":true},{\"Id\":\"229dfe7f-1394-47fe-84d4-8d5d7747cbd2\",\"ObjectTypeCode\":10410,\"Name\":\"prvWritemsmrw_guide\",\"AccessRight\":2,\"PrivilegeType\":2,\"CanBeBasic\":true,\"CanBeLocal\":true,\"CanBeDeep\":true,\"CanBeGlobal\":true,\"CanBeEntityReference\":true,\"CanBeParentEntityReference\":true},{\"Id\":\"d6624737-6846-49c7-bfef-25f6f482e297\",\"ObjectTypeCode\":10410,\"Name\":\"prvDeletemsmrw_guide\",\"AccessRight\":65536,\"PrivilegeType\":3,\"CanBeBasic\":true,\"CanBeLocal\":true,\"CanBeDeep\":true,\"CanBeGlobal\":true,\"CanBeEntityReference\":true,\"CanBeParentEntityReference\":true},{\"Id\":\"4f4fa37d-b977-4acf-a05a-d003ac32fc44\",\"ObjectTypeCode\":10410,\"Name\":\"prvAssignmsmrw_guide\",\"AccessRight\":524288,\"PrivilegeType\":4,\"CanBeBasic\":true,\"CanBeLocal\":true,\"CanBeDeep\":true,\"CanBeGlobal\":true,\"CanBeEntityReference\":true,\"CanBeParentEntityReference\":true},{\"Id\":\"09e5b82f-5cd8-46ea-a7ae-acbc472ae2b2\",\"ObjectTypeCode\":10410,\"Name\":\"prvSharemsmrw_guide\",\"AccessRight\":262144,\"PrivilegeType\":5,\"CanBeBasic\":true,\"CanBeLocal\":true,\"CanBeDeep\":true,\"CanBeGlobal\":true,\"CanBeEntityReference\":true,\"CanBeParentEntityReference\":true},{\"Id\":\"93b7f403-fc9b-442b-b602-9ba347ddda26\",\"ObjectTypeCode\":10410,\"Name\":\"prvAppendmsmrw_guide\",\"AccessRight\":4,\"PrivilegeType\":6,\"CanBeBasic\":true,\"CanBeLocal\":true,\"CanBeDeep\":true,\"CanBeGlobal\":true,\"CanBeEntityReference\":true,\"CanBeParentEntityReference\":true},{\"Id\":\"776967fe-67f4-4b3d-908a-dfb4306d2372\",\"ObjectTypeCode\":10410,\"Name\":\"prvAppendTomsmrw_guide\",\"AccessRight\":16,\"PrivilegeType\":7,\"CanBeBasic\":true,\"CanBeLocal\":true,\"CanBeDeep\":true,\"CanBeGlobal\":true,\"CanBeEntityReference\":true,\"CanBeParentEntityReference\":true}],\"RightsToCheck\":\"CreateAccess\",\"RoleAccessRights\":\"None\",\"PoaAccessRights\":\"None\",\"HsmAccessRights\":\"None\",\"Messages\":[\"PrincipalHasOwnerPrincipalWithAtLeastBasicPrivilegeDepth = False\",\"EntityUserGroupRights = None\",\"MinimumPrivilegeDepthRequired = Local\",\"GrantedRights = None\",\"SecLib::AccessCheckEx2 failed. Owner Data: roleCount=1, privilegeCount=0, accessMode=4; Principal Data: roleCount=1, privilegeCount=0, accessMode=4\"],\"IsHsmEnabled\":false,\"IsOwnerDirectReport\":false,\"IsDirectReportInOwningTeam\":false,\"IsReadAccessFromIndirectReport\":false}",
"innererror": {
"message": "{\"CallerPrincipal\":{\"PrincipalId\":\"96b856f4-134c-e911-a823-000d3a1d5de8\",\"Type\":8,\"IsUserPrincipal\":true,\"IsTeamPrincipal\":false,\"TypeName\":\"user\"},\"OwnerPrincipal\":{\"PrincipalId\":\"96b856f4-134c-e911-a823-000d3a1d5de8\",\"Type\":8,\"IsUserPrincipal\":true,\"IsTeamPrincipal\":false,\"TypeName\":\"user\"},\"CallerInfo\":{\"IsSystemUser\":false,\"IsSupportUser\":false,\"IsAdministrator\":false,\"IsCustomizer\":false,\"IsDisabled\":false,\"IsIntegrationUser\":false,\"Privileges\":null,\"Teams\":null,\"Roles\":null},\"ObjectId\":\"00000000-0000-0000-0000-000000000000\",\"ObjectTypeCode\":10410,\"ObjectBusinessUnitId\":\"1abfdddc-8140-e911-a823-000d3a1a25b8\",\"OrganizationId\":\"08907b95-ee84-4861-b141-b584fecc774d\",\"EntityName\":\"msmrw_guide\",\"EntityOwnershipTypeMask\":1,\"EntityPrivileges\":[{\"Id\":\"915a1feb-2a56-4a8c-bea0-3256728785e5\",\"ObjectTypeCode\":10410,\"Name\":\"prvCreatemsmrw_guide\",\"AccessRight\":32,\"PrivilegeType\":0,\"CanBeBasic\":true,\"CanBeLocal\":true,\"CanBeDeep\":true,\"CanBeGlobal\":true,\"CanBeEntityReference\":true,\"CanBeParentEntityReference\":true},{\"Id\":\"6415b9e2-24c4-408a-a830-85c21ab8ac72\",\"ObjectTypeCode\":10410,\"Name\":\"prvReadmsmrw_guide\",\"AccessRight\":1,\"PrivilegeType\":1,\"CanBeBasic\":true,\"CanBeLocal\":true,\"CanBeDeep\":true,\"CanBeGlobal\":true,\"CanBeEntityReference\":true,\"CanBeParentEntityReference\":true},{\"Id\":\"229dfe7f-1394-47fe-84d4-8d5d7747cbd2\",\"ObjectTypeCode\":10410,\"Name\":\"prvWritemsmrw_guide\",\"AccessRight\":2,\"PrivilegeType\":2,\"CanBeBasic\":true,\"CanBeLocal\":true,\"CanBeDeep\":true,\"CanBeGlobal\":true,\"CanBeEntityReference\":true,\"CanBeParentEntityReference\":true},{\"Id\":\"d6624737-6846-49c7-bfef-25f6f482e297\",\"ObjectTypeCode\":10410,\"Name\":\"prvDeletemsmrw_guide\",\"AccessRight\":65536,\"PrivilegeType\":3,\"CanBeBasic\":true,\"CanBeLocal\":true,\"CanBeDeep\":true,\"CanBeGlobal\":true,\"CanBeEntityReference\":true,\"CanBeParentEntityReference\":true},{\"Id\":\"4f4fa37d-b977-4acf-a05a-d003ac32fc44\",\"ObjectTypeCode\":10410,\"Name\":\"prvAssignmsmrw_guide\",\"AccessRight\":524288,\"PrivilegeType\":4,\"CanBeBasic\":true,\"CanBeLocal\":true,\"CanBeDeep\":true,\"CanBeGlobal\":true,\"CanBeEntityReference\":true,\"CanBeParentEntityReference\":true},{\"Id\":\"09e5b82f-5cd8-46ea-a7ae-acbc472ae2b2\",\"ObjectTypeCode\":10410,\"Name\":\"prvSharemsmrw_guide\",\"AccessRight\":262144,\"PrivilegeType\":5,\"CanBeBasic\":true,\"CanBeLocal\":true,\"CanBeDeep\":true,\"CanBeGlobal\":true,\"CanBeEntityReference\":true,\"CanBeParentEntityReference\":true},{\"Id\":\"93b7f403-fc9b-442b-b602-9ba347ddda26\",\"ObjectTypeCode\":10410,\"Name\":\"prvAppendmsmrw_guide\",\"AccessRight\":4,\"PrivilegeType\":6,\"CanBeBasic\":true,\"CanBeLocal\":true,\"CanBeDeep\":true,\"CanBeGlobal\":true,\"CanBeEntityReference\":true,\"CanBeParentEntityReference\":true},{\"Id\":\"776967fe-67f4-4b3d-908a-dfb4306d2372\",\"ObjectTypeCode\":10410,\"Name\":\"prvAppendTomsmrw_guide\",\"AccessRight\":16,\"PrivilegeType\":7,\"CanBeBasic\":true,\"CanBeLocal\":true,\"CanBeDeep\":true,\"CanBeGlobal\":true,\"CanBeEntityReference\":true,\"CanBeParentEntityReference\":true}],\"RightsToCheck\":\"CreateAccess\",\"RoleAccessRights\":\"None\",\"PoaAccessRights\":\"None\",\"HsmAccessRights\":\"None\",\"Messages\":[\"PrincipalHasOwnerPrincipalWithAtLeastBasicPrivilegeDepth = False\",\"EntityUserGroupRights = None\",\"MinimumPrivilegeDepthRequired = Local\",\"GrantedRights = None\",\"SecLib::AccessCheckEx2 failed. Owner Data: roleCount=1, privilegeCount=0, accessMode=4; Principal Data: roleCount=1, privilegeCount=0, accessMode=4\"],\"IsHsmEnabled\":false,\"IsOwnerDirectReport\":false,\"IsDirectReportInOwningTeam\":false,\"IsReadAccessFromIndirectReport\":false}",
"type": "System.ServiceModel.FaultException`1[[Microsoft.Xrm.Sdk.OrganizationServiceFault, Microsoft.Xrm.Sdk, Version=9.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]",
"stacktrace": " at Microsoft.Crm.Extensibility.OrganizationSdkServiceInternal.CreateInternal(Entity entity, InvocationContext invocationContext, CallerOriginToken callerOriginToken, WebServiceType serviceType, Boolean checkAdminMode, Dictionary`2 optionalParameters)\r\n at Microsoft.Crm.Extensibility.OData.CrmODataExecutionContext.CreateOrganizationResponse(Entity entity)\r\n at Microsoft.Crm.Extensibility.OData.CrmODataServiceDataProvider.CreateEdmEntity(CrmODataExecutionContext context, String edmEntityName, EdmEntityObject entityObject, Boolean isUpsert)\r\n at Microsoft.Crm.Extensibility.OData.EntityController.PostEntitySetImplementation(String& entitySetName, EdmEntityObject entityObject)\r\n at Microsoft.PowerApps.CoreFramework.ActivityLoggerExtensions.Execute[TResult](ILogger logger, EventId eventId, ActivityType activityType, Func`1 func, IEnumerable`1 additionalCustomProperties)\r\n at Microsoft.Xrm.Telemetry.XrmTelemetryExtensions.Execute[TResult](ILogger logger, XrmTelemetryActivityType activityType, Func`1 func)\r\n at lambda_method(Closure , Object , Object[] )\r\n at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.<GetExecutor>b__9(Object instance, Object[] methodParameters)\r\n at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()"
}
}
}
These are the fields I file out in Postman when requesting a token and the values for these fields, I removed the secret for security.
These are the permissions my app uses.
According to the code and picture you provided, in the postman, you use the OAuth 2.0 code grant flow to require Azure AD access token. The way is getting access on behalf of a user. The token is user token. But in your application, you use the method acquire_token_with_client_credentials to require Azure AD access token. It means that you use OAuth 2.0 Client Credentials Grant Flow to require Azure AD access token. The way is getting access without a user. The token is app token. They are different.
Besides, according to the error, you do not have enough privilege and you need to configure the permissions. It means that if you still want to use OAuth 2.0 Client Credentials Grant Flow to require access token, you need to provide enough privilege for the service principal(the AD application ) you use. Or you change your code to use OAuth 2.0 code grant flow to require access token. For more details about how to change, please refer to the sample

Basic Google API Oauth2 Authentication Setup Fails To Give Objects?

I have coded an authentication and I get an access token, but when I use it to grab an object I just end up getting 'NoneType' object is not callable.
Exception Location: googleads\adwords.py in GetService, line 365
Exception Type: Type Error
Exception Value: Internal Server Error: /oauth2callback
I get the same result whether calling for Customer or CampaignService. I don't understand what I am doing wrong.
I am following the code in Googleads.
def getAdwordsFlow():
FLOW.redirect_uri = 'http://localhost/oauth2callback'
# Generate URL for request to Google's OAuth 2.0 server.
authorization_url, state = FLOW.authorization_url(
access_type='offline',
include_granted_scopes='true')
return authorization_url
def getAdwordsTokens(request):
auth_code = request.GET.get('code')
FLOW.fetch_token(code=auth_code)
credentials = FLOW.credentials
oauth2_client = oauth2.GoogleAccessTokenClient(
FLOW.credentials.token, FLOW.credentials.expiry)
adwords_client = adwords.AdWordsClient(
"DEVELOPER-TOKEN", oauth2_client, "USER-AGENT", "CLIENT-CUSTOMER-ID")
customer = adwords_client.GetService('CustomerService').getCustomers()[0]
print('You are logged in as customer: %s' % customer['customerId'])
return HttpResponseRedirect("/")
url.py
urlpatterns = [
re_path(r'^oauth2callback', queries.getAdwordsTokens, name='auth_calledback'),] #How
view.py
def index(request):
return redirect(getAdwordsFlow())
Terminal output:
"GET /oauth2callback?state=XXXXXXXXX&code=4/XXXXXXXXXXX&scope=https://www.googleapis.com/auth/adwords+https://www.googleapis.com/auth/userinfo.profile+https://www.googleapis.com/auth/userinfo.email HTTP/1.1" 500 80213
Why is it 500?
I notice my access token has a different value when I call for it. So I am assuming it's working.
According to your question, your service call is -
GET /oauth2callback?state=XXXXXXXXX&code=4/XXXXXXXXXXX&scope=https://www.googleapis.com/auth/adwords+https://www.googleapis.com/auth/userinfo.profile+https://www.googleapis.com/auth/userinfo.email HTTP/1.1
This call is neither get access token call nor having access_token in the request and as per your reference code it will generate access_token from refresh_token.
def main(access_token, token_expiry, client_customer_id, developer_token,
user_agent):
oauth2_client = oauth2.GoogleAccessTokenClient(access_token, token_expiry)
adwords_client = adwords.AdWordsClient(
developer_token, oauth2_client, user_agent,
client_customer_id=client_customer_id)
customer = adwords_client.GetService('CustomerService').getCustomers()[0]
print 'You are logged in as customer: %s' % customer['customerId']
if __name__ == '__main__':
args = parser.parse_args()
# Retrieve a new access token for use in this example. In a production
# application, you may use a credential store to share access tokens for a
# given user across applications.
oauth2credentials = client.OAuth2Credentials(
None, args.client_id, args.client_secret, args.refresh_token,
datetime.datetime(1980, 1, 1, 12), GOOGLE_OAUTH2_ENDPOINT,
USER_AGENT)
oauth2credentials.refresh(httplib2.Http())
main(oauth2credentials.access_token, oauth2credentials.token_expiry,
args.client_customer_id, args.developer_token, USER_AGENT)
So to use your code, first generate refresh_token using this code and then use it in your given code.

Passing a Facebook Oauth2 object while using Tornado

I am trying to implement oauth manually on my website which is being implemented using tornado. My url (localhost/form) contains a button which when clicked brings up a facebook login and then if the login is successful redirects back to the same site with a token (localhost/form?code=XXX) where I collect the token/code and begins taking requests from facebook.
My issue is that upon redirecting back to localhost/form with a given code, it appears that I reinitialize a brand new oauth2session object which does not match up with the token and I receive a GET request error. How should I correctly pass this oauth2session object or correctly reinitialize it? Is this reinitialization causing my error or something else? My current code which does not work is:
class FormHandler (BaseHandler):
def get(self):
client_id =XXX
client_secret =XXX
authorization_base_url = 'https://www.facebook.com/dialog/oauth'
token_url = 'https://graph.facebook.com/oauth/access_token'
facebook = OAuth2Session(client_id, redirect_uri='http://localhost/form')
facebook = facebook_compliance_fix(facebook)
authorization_url, state = facebook.authorization_url(authorization_base_url)
self.write('<button id="FacebookManual" type="button">Facebook Manual</button><br><script> document.getElementById("FacebookManual").onclick = function () {location.href ="'+authorization_url+'";};</script>')
#Check to see if I get redirected with a code
authorization_code=self.get_argument("code", default=None, strip=False)
if authorization_code is not None:
redirect_response='https://localhost/form/?code='+authorization_code
facebook.fetch_token(token_url, client_secret=client_secret, authorization_response=redirect_response)
r = facebook.get('https://graph.facebook.com/me?')
self.write('Hello'+r.content)
#Roughly how my tornado is set up
def make_app():
return Application(
[
url('/', BaseHandler, { "var":"nothing" }, name="root"), # this is for the root! :)
url('/form', FormHandler, { "var":"initialize this!" }, name = "forlorn"),
],
# settings:
debug = True,
)
Edit: A friend advised me to include the error that I was receiving. The error that I get is a oauthlib.oauth2.rfc6749.errors.MismatchingStateError: (mismatching_state) CSRF Warning! State not equal in request and response.
ERROR:tornado.access:500 GET /form?code=XxX

Appengie Oauth: Spreadsheet api client.get_spreadsheets() returns error

trying to list the google spreadsheet using oauth & GData in Google Appengine. But i'm getting following error. Anything wrong in my code?
Please advise.
File "/home/RKS/Appengine/test/main.py", line 99, in get
feed = client.get_spreadsheets()
File "/home/RKS/Appengine/test/gdata/spreadsheets/client.py", line 78, in get_spreadsheets
desired_class=desired_class, **kwargs)
File "/home/RKS/Appengine/test/gdata/client.py", line 640, in get_feed
**kwargs)
File "/home/RKS/Appengine/test/gdata/client.py", line 278, in request
version=get_xml_version(self.api_version))
File "/home/RKS/Appengine/test/atom/core.py", line 520, in parse
tree = ElementTree.fromstring(xml_string)
File "<string>", line 125, in XML
ParseError: no element found: line 1, column 0
Code:
#!/usr/bin/env python
import webapp2
import logging
from google.appengine.api import users
import gdata.auth
import gdata.gauth
import gdata.client
import gdata.service
import gdata.spreadsheets
import gdata.spreadsheets.client
import gdata.spreadsheets.data
SETTINGS = {
'APP_NAME': 'hidden', # intentionally hidden
'CONSUMER_KEY': 'hidden',
'CONSUMER_SECRET': 'hidden',
'SCOPES': ['https://spreadsheets.google.com/feeds'],
'CALLBACK_URL': '',
'SIG_METHOD': gdata.auth.OAuthSignatureMethod.HMAC_SHA1
}
class FetchToken(webapp2.RequestHandler):
def get(self):
current_uid = users.get_current_user().user_id()
if isinstance(gdata.gauth.AeLoad(current_uid), gdata.gauth.OAuthHmacToken):
# the user has gone through the process before
self.redirect('/')
else:
# the user has not gone through this process, or the authorization has expired or been revoked.
SETTINGS['CALLBACK_URL'] = 'http://%s/HandleOAuthCallback' % self.request.host
client = gdata.client.GDClient()
request_token = client.GetOAuthToken(
SETTINGS['SCOPES'],
SETTINGS['CALLBACK_URL'],
SETTINGS['CONSUMER_KEY'],
consumer_secret=SETTINGS['CONSUMER_SECRET'])
gdata.gauth.AeSave(request_token, current_uid)
self.redirect(str(request_token.generate_authorization_url()))
class HandleOAuthCallback(webapp2.RequestHandler):
def get(self):
current_uid = users.get_current_user().user_id()
client = gdata.client.GDClient()
saved_request_token = gdata.gauth.AeLoad(current_uid)
request_token = gdata.gauth.AuthorizeRequestToken(saved_request_token, self.request.uri)
access_token = client.GetAccessToken(request_token)
gdata.gauth.AeSave(access_token, current_uid)
self.redirect('/')
class GetDocsList(webapp2.RequestHandler):
def get(self):
if not users.get_current_user():
self.redirect(users.create_login_url('/'))
else:
current_uid = users.get_current_user().user_id()
if isinstance(gdata.gauth.AeLoad(current_uid), gdata.gauth.OAuthHmacToken):
# the user has gone through the process before
access_token = gdata.gauth.AeLoad(current_uid)
client = gdata.service.GDataService()
oauth_input_params = gdata.auth.OAuthInputParams(
gdata.auth.OAuthSignatureMethod.HMAC_SHA1,
SETTINGS['CONSUMER_KEY'],
SETTINGS['CONSUMER_SECRET']) # consumer_secret=
oauth_token = gdata.auth.OAuthToken(
key=access_token.token,
secret=access_token.token_secret,
scopes=SETTINGS['SCOPES'],
oauth_input_params=oauth_input_params)
client.SetOAuthToken(oauth_token)
client = gdata.spreadsheets.client.SpreadsheetsClient()
feed = client.get_spreadsheets()
else:
self.redirect('/FetchToken')
app = webapp2.WSGIApplication([('/HandleOAuthCallback', HandleOAuthCallback), ('/', GetDocsList), ('/FetchToken', FetchToken)], debug=False)
I recommend switching to OAuth2, and most of my answer will explain how to solve your problem by doing that. However, before trying to switch to OAuth2 I suggest you try this one line change, which may be a quick solution to your problem. The first thing I would try is adding a header to your client as follows.
client.additional_headers = {
'Authorization': 'Bearer %s' % access_token,
}
I have an application using the GData spreadsheets API with OAuth2 and adding that header was necessary for it to work. If I took that header out, I would get an error like the one you described.
Now, on to the answer:
Using OAuth2 in App Engine to do what you're trying to do is even simpler than what you've already done. Here's how it is done.
First create an OAuth2 decorator. (I describe where to create your client ID and client secret at the end of the answer.)
from oauth2client.appengine import OAuth2Decorator
GlobalOAuth2Decorator = OAuth2Decorator(
client_id=OAUTH2_CLIENT_ID,
client_secret=OAUTH2_CLIENT_SECRET,
scope='https://spreadsheets.google.com/feeds',
)
Then use this decorator when you create your request handler.
class SpreadsheetHandler(webapp2.RequestHandler):
#GlobalOAuth2Decorator.oauth_required
def get(self):
client = gdata.spreadsheet.service.SpreadsheetsService()
client.additional_headers = {
'Authorization': 'Bearer %s' % GlobalOAuth2Decorator.credentials.access_token,
}
Notice that I'm using SpreadsheetsService instead of SpreadsheetsClient. This has been working for me, though I haven't given SpreadsheetsClient a try (the client might actually be easier to use).
Once you've created this client object you can use it to read and write spreadsheets as you like. For example sheets = client.GetSpreadsheetsFeeds() will give you a list of spreadsheets that you can access.
Lastly, make sure to include the OAuth handler in your list of handlers when you create the application:
app = webapp2.WSGIApplication([..., (GlobalOAuth2Decorator.callback_path, GlobalOAuth2Decorator.callback_handler())]
In order for OAuth2 to work, you have to go to your developer console at https://console.developers.google.com and 1) select your app, 2) from the Credentials menu create a new Client ID (this will generate a client ID and secret for you), and 3) from the Consent Screen menu give your application an email address and name.

Categories