OAuth2 InvalidScopeError in Backend Application flow - python

I am trying to implement the Backend Application flow to get an access token from the Datahug API (Following instructions in https://api.datahug.com/#gettingstarted).
from oauthlib.oauth2 import BackendApplicationClient
from requests_oauthlib import OAuth2Session
def get_access_token():
token_url = 'https://apps.datahug.com/identity/connect/token'
client_id = CLIENT_ID
client_secret = CLIENT_SECRET
scope = 'datahug_api'
client = BackendApplicationClient(client_id=client_id)
client.prepare_request_body(scope=[scope])
oauth = OAuth2Session(client=client)
token = oauth.fetch_token(token_url=token_url,
client_id=client_id,
client_secret=client_secret)
return token
if __name__ == '__main__':
token = get_access_token()
print(token)
When running this code I'm getting an InvalidScopeError, namely
user:dh user$ python so_test.py
Traceback (most recent call last):
File "so_test.py", line 21, in <module>
token = get_access_token()
File "so_test.py", line 17, in get_access_token
client_secret=client_secret)
File "/Users/user/anaconda3/lib/python3.5/site-packages/requests_oauthlib/oauth2_session.py", line 244, in fetch_token
self._client.parse_request_body_response(r.text, scope=self.scope)
File "/Users/user/anaconda3/lib/python3.5/site-packages/oauthlib/oauth2/rfc6749/clients/base.py", line 409, in parse_request_body_response
self.token = parse_token_response(body, scope=scope)
File "/Users/user/anaconda3/lib/python3.5/site-packages/oauthlib/oauth2/rfc6749/parameters.py", line 376, in parse_token_response
validate_token_parameters(params)
File "/Users/user/anaconda3/lib/python3.5/site-packages/oauthlib/oauth2/rfc6749/parameters.py", line 383, in validate_token_parameters
raise_from_error(params.get('error'), params)
File "/Users/user/anaconda3/lib/python3.5/site-packages/oauthlib/oauth2/rfc6749/errors.py", line 325, in raise_from_error
raise cls(**kwargs)
oauthlib.oauth2.rfc6749.errors.InvalidScopeError: (invalid_scope)
It seems that the problem is in the value scope='datahug_api', but this is the value suggested in the datahug api. Any suggestions on how to solve this much appreciated.

You are missing scope in the oauth.fetch_token().
So, your variable token should be:
token = oauth.fetch_token(token_url=token_url,scope=scope,client_id=client_id,
client_secret=client_secret)

I had success adding the scope to the BackendApplicationClient as can be seen from the developer docs.
client = BackendApplicationClient(client_id=client_id, scope=scope)
oauth = OAuth2Session(client=client)
token = oauth.fetch_token(token_url=url, client_id=client_id, client_secret=client_secret)

Related

google api token expired or revoked?

I have set up a discord bot a week ago that uses google drive api. The bot worked for a week in a web hosting server, and today I checked and it's been giving me this error every time i started up the bot.
client_secret.json-drive-v3-(['https://www.googleapis.com/auth/drive'],)
['https://www.googleapis.com/auth/drive']
Traceback (most recent call last):
File "C:\Users\Unknown1\Documents\discordbot\bot.py", line 5, in <module>
from googledrive import find_recent
File "C:\Users\Unknown1\Documents\discordbot\googledrive.py", line 10, in <module>
service = Create_Service(CLIENT_SECRET_FILE, API_NAME, API_VERSION, SCOPES)
File "C:\Users\Unknown1\Documents\discordbot\Google.py", line 28, in Create_Service
cred.refresh(Request())
File "C:\Users\Unknown1\AppData\Local\Programs\Python\Python39\lib\site-packages\google\oauth2\credentials.py", line 200, in refresh
access_token, refresh_token, expiry, grant_response = _client.refresh_grant(
File "C:\Users\Unknown1\AppData\Local\Programs\Python\Python39\lib\site-packages\google\oauth2\_client.py", line 248, in refresh_grant
response_data = _token_endpoint_request(request, token_uri, body)
File "C:\Users\Unknown1\AppData\Local\Programs\Python\Python39\lib\site-packages\google\oauth2\_client.py", line 124, in _token_endpoint_request
_handle_error_response(response_body)
File "C:\Users\Unknown1\AppData\Local\Programs\Python\Python39\lib\site-packages\google\oauth2\_client.py", line 60, in _handle_error_response
raise exceptions.RefreshError(error_details, response_body)
google.auth.exceptions.RefreshError: ('invalid_grant: Token has been expired or revoked.', '{\n "error": "invalid_grant",\n "error_description": "Token has been expired or revoked."\n}')
PS C:\Users\Unknown1\Documents\discordbot>
I checked the client_secret_file.json and redownloaded it from google cloud api credentials and its still the same thing. I'm not sure where to go about from here to fix this issue.
import pandas as pd
import datetime
CLIENT_SECRET_FILE = 'client_secret.json'
API_NAME = 'drive'
API_VERSION = 'v3'
SCOPES = ['https://www.googleapis.com/auth/drive']
service = Create_Service(CLIENT_SECRET_FILE, API_NAME, API_VERSION, SCOPES)
#in the google drive web link, there will be a folder id.
folder_id = '1ANm4frKaL_JeMEewRMDBLWiiY3Srh-B-'
query = f"parents = '{folder_id}'"
response = service.files().list(q=query).execute()
files = response.get('files')
nextPageToken = response.get('nextPageToken')
while nextPageToken:
response = service.files().list(q=query,pageToken=nextPageToken).execute()
files.extend(response.get('files'))
nextpageToken = response.get('nextPageToken')
df = pd.DataFrame(files)
I have set up a new project , OAuth 2.0 Client ID Credentials, following this youtube video:https://www.youtube.com/watch?v=FAM_4J7ywcE&ab_channel=nouthemes
and deleted the old one in hopes of replacing the client secret file with the new one. Now I am getting a new error :
client_secret.json-drive-v3-(['https://www.googleapis.com/auth/drive'],)
['https://www.googleapis.com/auth/drive']
Traceback (most recent call last):
File "C:\Users\Unknown1\Documents\discordbot\bot.py", line 5, in <module>
from googledrive import find_recent
File "C:\Users\Unknown1\Documents\discordbot\googledrive.py", line 10, in <module>
service = Create_Service(CLIENT_SECRET_FILE, API_NAME, API_VERSION, SCOPES)
File "C:\Users\Unknown1\Documents\discordbot\Google.py", line 28, in Create_Service
cred.refresh(Request())
File "C:\Users\Unknown1\AppData\Local\Programs\Python\Python39\lib\site-packages\google\oauth2\credentials.py", line 200, in refresh
access_token, refresh_token, expiry, grant_response = _client.refresh_grant(
File "C:\Users\Unknown1\AppData\Local\Programs\Python\Python39\lib\site-packages\google\oauth2\_client.py", line 248, in refresh_grant
response_data = _token_endpoint_request(request, token_uri, body)
File "C:\Users\Unknown1\AppData\Local\Programs\Python\Python39\lib\site-packages\google\oauth2\_client.py", line 124, in _token_endpoint_request
_handle_error_response(response_body)
File "C:\Users\Unknown1\AppData\Local\Programs\Python\Python39\lib\site-packages\google\oauth2\_client.py", line 60, in _handle_error_response
raise exceptions.RefreshError(error_details, response_body)
google.auth.exceptions.RefreshError: ('deleted_client: The OAuth client was deleted.', '{\n "error": "deleted_client",\n "error_description": "The OAuth client was deleted."\n}')
I'm stuck.

SecretClient class in azure-keyvault-secrets python package throws unexpected errir

I've been trying to get my python script to retrieve a secret from an Azure key vault. For the authentication I've been using the ServicePrincipal credential and the Azure-keyvault-secrets package which comes with a SecretClient class. But it's throwing an error which might be because of any updates in the python package.
Could anyone point out what's going wrong?
from azure.common.credentials import ServicePrincipalCredentials
from azure.keyvault.secrets import SecretClient
CLIENT_ID '...' #app_id
TENANT_ID = '...'
KEY = '...'
credentials = ServicePrincipalCredentials(
client_id=CLIENT_ID,
secret=KEY,
tenant=TENANT_ID
)
vault_url = '...'
secret_name = "..."
secret_version = '...'
client = SecretClient(vault_url=vault_url, credential=credentials)
secret = client.get_secret(secret_name)
It gives the following error :
Traceback (most recent call last):
File "key-vault.py", line 23, in <module>
secret = client.get_secret("cromaprivate128")
File "/Users/rishavputatunda/Library/Python/3.7/lib/python/site-packages/azure/core/tracing/decorator.py", line 71, in wrapper_use_tracer
return func(*args, **kwargs)
File "/Users/rishavputatunda/Library/Python/3.7/lib/python/site-packages/azure/keyvault/secrets/_client.py", line 71, in get_secret
**kwargs
File "/Users/rishavputatunda/Library/Python/3.7/lib/python/site-packages/azure/keyvault/secrets/_shared/_generated/v7_0/operations/_key_vault_client_operations.py", line 1621, in get_secret
pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs)
File "/Users/rishavputatunda/Library/Python/3.7/lib/python/site-packages/azure/core/pipeline/_base.py", line 208, in run
return first_node.send(pipeline_request) # type: ignore
File "/Users/rishavputatunda/Library/Python/3.7/lib/python/site-packages/azure/core/pipeline/_base.py", line 80, in send
response = self.next.send(request)
File "/Users/rishavputatunda/Library/Python/3.7/lib/python/site-packages/azure/core/pipeline/_base.py", line 80, in send
response = self.next.send(request)
File "/Users/rishavputatunda/Library/Python/3.7/lib/python/site-packages/azure/core/pipeline/_base.py", line 80, in send
response = self.next.send(request)
File "/Users/rishavputatunda/Library/Python/3.7/lib/python/site-packages/azure/core/pipeline/policies/_redirect.py", line 157, in send
response = self.next.send(request)
File "/Users/rishavputatunda/Library/Python/3.7/lib/python/site-packages/azure/core/pipeline/policies/_retry.py", line 418, in send
response = self.next.send(request)
File "/Users/rishavputatunda/Library/Python/3.7/lib/python/site-packages/azure/keyvault/secrets/_shared/challenge_auth_policy.py", line 67, in send
self._handle_challenge(request, challenge)
File "/Users/rishavputatunda/Library/Python/3.7/lib/python/site-packages/azure/keyvault/secrets/_shared/challenge_auth_policy.py", line 91, in _handle_challenge
access_token = self._credential.get_token(scope)
AttributeError: 'ServicePrincipalCredentials' object has no attribute 'get_token'
We cannot use the ServicePrincipalCredentials to create a SecretClient. Because the ServicePrincipalCredentials cannot provide the access token. If you want to access key vault, please try to use the Credentials provided by sdk azure.identity.
For example
1. Create a service principal with Azure CLI
az login
az ad sp create-for-rbac -n "MyApp" --sdk-auth
Set access policy
az keyvault set-policy -n <your-unique-keyvault-name> --spn <clientId-of-your-service-principal> --secret-permissions delete get list set --key-permissions create decrypt delete encrypt get list unwrapKey wrapKe
code
from azure.identity import ClientSecretCredential
from azure.keyvault.secrets import SecretClient
tenant_id="<your sp tenant>"
client_id="<your sp client id>"
client_secret="<your sp client secret>"
credential = ClientSecretCredential(tenant_id, client_id, client_secret)
secret_client = SecretClient(vault_url="https://my-key-vault.vault.azure.net/", credential=credential)
secret = secret_client.get_secret("secret-name")
print(secret.name)
print(secret.value)

Why is oauth2client throwing a urlencode error in my dev environment?

I am using google-api-python-client to site-wide delegate auth for a calendar building program I am writing.
import pytz
from datetime import datetime, timedelta
import httplib2
import json
from apiclient.discovery import build
from oauth2client.client import SignedJwtAssertionCredentials
with open('privatekey.pem', 'rb') as f:
key = f.read()
with open('config.json') as f:
config = json.load(f)
service_account_name = config['account_email']
calendarId = config['calendarId']
credentials = SignedJwtAssertionCredentials(
service_account_name, key,
scope=['https://www.googleapis.com/auth/calendar',
'https://www.googleapis.com/auth/calendar.readonly'])
http = httplib2.Http()
http = credentials.authorize(http)
service = build(serviceName='calendar', version='v3', http=http)
I do not have any issue running this on my production server, however on my dev (personal laptop) it is throwing a I do not have any issue running this on my production server, however on my dev (personal laptop) is throwing an error on urlencode. From my understanding urllib.parse.urlencode is the python 3 path? Why is my dev calling this ?
File "cal.py", line 27, in <module>
service = build(serviceName='calendar', version='v3', http=http)
return wrapped(*args, **kwargs)
File "/Library/Python/2.7/site-packages/googleapiclient/discovery.py", line 196, in build
resp, content = http.request(requested_url)
File "/Library/Python/2.7/site-packages/oauth2client/util.py", line 137, in positional_wrapper
return wrapped(*args, **kwargs)
File "/Library/Python/2.7/site-packages/oauth2client/client.py", line 534, in new_request
self._refresh(request_orig)
File "/Library/Python/2.7/site-packages/oauth2client/client.py", line 748, in _refresh
self._do_refresh_request(http_request)
File "/Library/Python/2.7/site-packages/oauth2client/client.py", line 772, in _do_refresh_request
body = self._generate_refresh_request_body()
File "/Library/Python/2.7/site-packages/oauth2client/client.py", line 1381, in _generate_refresh_request_body
body = urllib.parse.urlencode({
AttributeError: 'Module_six_moves_urllib_parse' object has no attribute 'urlencode'
Thanks for you help!

Python Google drive SDK - getting error sequence item 0: expected str instance, bytes found

Consider the code below:
#!/usr/bin/python
import httplib2
import pprint
from apiclient.discovery import build
from apiclient.http import MediaFileUpload
from oauth2client.client import OAuth2WebServerFlow
from oauth2client.client import OAuth2Credentials
from oauth2client import GOOGLE_AUTH_URI
from oauth2client import GOOGLE_REVOKE_URI
from oauth2client import GOOGLE_TOKEN_URI
#Refresh token
REFRESH_TOKEN = ""
# Copy your credentials from the console
CLIENT_ID = ''
CLIENT_SECRET = ''
## Check https://developers.google.com/drive/scopes for all available scopes
OAUTH_SCOPE = ['https://www.googleapis.com/auth/drive','http://localhost:5001/storage/getGDriveAuth']
## Redirect URI for installed apps
REDIRECT_URI = ''
credentials = OAuth2Credentials(None, CLIENT_ID,
CLIENT_SECRET, REFRESH_TOKEN, None,
GOOGLE_TOKEN_URI, None,
revoke_uri=GOOGLE_REVOKE_URI,
id_token=None,
token_response=None)
# Create an httplib2.Http object and authorize it with our credentials
http = httplib2.Http()
http = credentials.authorize(http)
drive_service = build('drive', 'v2', http=http) #getting error here
file = drive_service.files().list().execute()
pprint.pprint(file)
exit();
I am getting following error:
Traceback (most recent call last):
File "python-quickstart/main.py", line 64, in <module>
drive_service = apiclient.discovery.build('drive', 'v2', http=http)
File "d:\xampp\htdocs\driveTest\lib\site-packages\oauth2client\util.py", line 137, in positional_wrapper
return wrapped(*args, **kwargs)
File "d:\xampp\htdocs\driveTest\lib\site-packages\googleapiclient\discovery.py", line 196, in build
resp, content = http.request(requested_url)
File "d:\xampp\htdocs\driveTest\lib\site-packages\oauth2client\util.py", line 137, in positional_wrapper
return wrapped(*args, **kwargs)
File "d:\xampp\htdocs\driveTest\lib\site-packages\oauth2client\client.py", line 551, in new_request
redirections, connection_type)
File "d:\xampp\htdocs\driveTest\lib\site-packages\httplib2\__init__.py", line 1139, in request
headers = self._normalize_headers(headers)
File "d:\xampp\htdocs\driveTest\lib\site-packages\httplib2\__init__.py", line 1107, in _normalize_headers
return _normalize_headers(headers)
File "d:\xampp\htdocs\driveTest\lib\site-packages\httplib2\__init__.py", line 195, in _normalize_headers
return dict([ (key.lower(), NORMALIZE_SPACE.sub(value, ' ').strip()) for (key, value) in headers.items()])
File "d:\xampp\htdocs\driveTest\lib\site-packages\httplib2\__init__.py", line 195, in <listcomp>
return dict([ (key.lower(), NORMALIZE_SPACE.sub(value, ' ').strip()) for (key, value) in headers.items()])
TypeError: sequence item 0: expected str instance, bytes found
Any idea why it is happening?
This error occurs because of the difference in the way Python 2 and Python 3 handle byte strings, more details about this are available here:
https://docs.python.org/3/whatsnew/3.0.html
This issue occurs because of the way that oath2client and httplib2 handled strings as bytes - the latest version of httplib2 which is newer than the current PyPI version(as of 03/25/2015) has included a work around for this issue.
Eventually the developers might decide on a different solution to the problem, however, you can use the newer version of httplib2 to resolve this problem in your code.

OAuth1 with requests_oauthlib produces URL encoding error

I am using the requests_oauthlib module for OAuth authentication.
Unfortunately I cannot reproduce the OAuth1 workflow acoording to step one in this tutorial: http://requests-oauthlib.readthedocs.org/en/latest/oauth1_workflow.html
If I try to obtain a fetch response it throws me the followin error:
Traceback (most recent call last):
File "/home/neumannr/test.py", line 18, in <module>
fetch_response = oauth.fetch_request_token(request_token_url)
File "/usr/lib/python2.7/site-packages/requests_oauthlib/oauth1_session.py", line 195, in fetch_request_token
token = self._fetch_token(url)
File "/usr/lib/python2.7/site-packages/requests_oauthlib/oauth1_session.py", line 264, in _fetch_token
token = dict(urldecode(self.post(url).text))
File "/usr/lib/python2.7/site-packages/oauthlib/common.py", line 135, in urldecode
raise ValueError('Not a valid urlencoded string.')
ValueError: Not a valid urlencoded string.
My testing code looks as follows:
#! /usr/bin/env python
# Using OAuth1Session
from requests_oauthlib import OAuth1Session
# Using OAuth1 auth helper
import requests
from requests_oauthlib import OAuth1
client_key = 'a'
client_secret = 'b'
request_token_url = 'https://api.twitter.com/oauth/request_token'
# Using OAuth1Session
oauth = OAuth1Session(client_key, client_secret=client_secret)
fetch_response = oauth.fetch_request_token(request_token_url)
Since the URL is not being URL encoded within the tutorial either, I do not understand why this happens. If I try to URL encode the URL like this:
#! /usr/bin/env python
# Using OAuth1Session
import urllib
from requests_oauthlib import OAuth1Session
# Using OAuth1 auth helper
import requests
from requests_oauthlib import OAuth1
client_key = 'a'
client_secret = 'b'
request_token_url = urllib.quote('https://api.twitter.com/oauth/request_token')
# Using OAuth1Session
oauth = OAuth1Session(client_key, client_secret=client_secret)
fetch_response = oauth.fetch_request_token(request_token_url)
I get a missing schema error:
Traceback (most recent call last):
File "/home/neumannr/test.py", line 19, in <module>
fetch_response = oauth.fetch_request_token(request_token_url)
File "/usr/lib/python2.7/site-packages/requests_oauthlib/oauth1_session.py", line 195, in fetch_request_token
token = self._fetch_token(url)
File "/usr/lib/python2.7/site-packages/requests_oauthlib/oauth1_session.py", line 264, in _fetch_token
token = dict(urldecode(self.post(url).text))
File "/usr/lib/python2.7/site-packages/requests/sessions.py", line 377, in post
return self.request('POST', url, data=data, **kwargs)
File "/usr/lib/python2.7/site-packages/requests/sessions.py", line 324, in request
prep = req.prepare()
File "/usr/lib/python2.7/site-packages/requests/models.py", line 222, in prepare
p.prepare_url(self.url, self.params)
File "/usr/lib/python2.7/site-packages/requests/models.py", line 291, in prepare_url
raise MissingSchema("Invalid URL %r: No schema supplied" % url)
requests.exceptions.MissingSchema: Invalid URL u'https%3A//api.twitter.com/oauth/request_token': No schema supplied
How do I use oauthlib_requests anyway?
Thanks,
Richard
The error can be a result of a failed attempt to decode the response. For more details, please see OAuthlib issue 124.

Categories

Resources