I have been getting the issue when I'm trying to convert Postman OAuth 2.0 to Python3. I tried to research but seems unfortunate for me, I did not find any example
Here is my code:
from rauth import OAuth2Service
import json
def get_token(client_id, client_secret):
access_token = None
service = OAuth2Service(
name="Viafoura",
client_id=client_id,
client_secret=client_secret,
access_token_url='https://auth.viafoura.io/authorize_client'
)
data = {
'scope': 'xxxxx-xxxx-xxxx-xxxx-xxxxx',
'grant_type': 'client_credentials'
}
session = service.get_auth_session(data=data)
access_token = session
Here is OAuth 2.0 on Postman and it's working:
I want to get the access_token via Python3. Could anyone please help me on it?
Maybe it can help you, an example with the basic algorithm of OAuth2
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from requests import post, auth, exceptions
from json import loads
if __name__ == '__main__':
client_id = ''
client_secret = ''
user = ''
password = ''
access_point = 'https://account.lab.fiware.org/oauth2/token'
grant_type = 'password'
headers = {'Content-Type': 'application/x-www-form-urlencoded'}
auth = auth.HTTPBasicAuth(client_id, client_secret)
data = {'grant_type': grant_type,
'username': user,
'password': password}
resp = None
try:
resp = post(access_point, auth=auth, data=data, headers=headers, timeout=5)
except exceptions.ConnectionError:
exit(1)
if resp.status_code == 200:
resp = loads(resp.text)
if 'access_token' in resp:
print(resp['access_token'])
exit(0)
exit(1)
You need to fix access point, grant type. This source code can be found here
Sorry, I can't help directly with Viafoura and OAuth2Service library.
Related
I am trying to upload a file to my shared drive using drive API v3
it works fine with normal drive ids, but when I put shared drive ids, it fails to work.
my code :-
#!/usr/bin/python3
import argparse
import json
import mimetypes
import os.path
import requests
script_path = os.path.abspath(__file__)
script_dir = os.path.dirname(script_path)
parser = argparse.ArgumentParser()
parser.add_argument('file', metavar='FILE')
parser.add_argument('folder', metavar='FOLDER_ID')
parser.add_argument('-v', '--verbose', action='store_true')
args = parser.parse_args()
file_path = args.file
file_obj = open(file_path, mode='rb')
file_name = os.path.basename(file_path)
file_mime_type = mimetypes.guess_type(file_path)[0]
### client secret ###
client = None
client_name = 'client_secret.json'
client_path = os.path.join(script_dir, client_name)
with open(client_path, 'r') as f:
client = json.load(f)
assert client is not None and 'installed' in client
client = client['installed']
assert 'client_id' in client
if args.verbose:
print('=== client id ===')
print(client['client_id'])
print()
assert 'client_secret' in client
if args.verbose:
print('=== client secret ===')
print(client['client_secret'])
print()
### refresh token ###
refresh_token = None
refresh_name = 'refresh_token.txt'
refresh_path = os.path.join(script_dir, refresh_name)
with open(refresh_path, mode='r') as f:
refresh_token = f.read().rstrip()
if args.verbose:
print('=== refresh token ===')
print(refresh_token)
print()
### access token ###
r = requests.post('https://accounts.google.com/o/oauth2/token', data={
'client_id': client['client_id'],
'client_secret': client['client_secret'],
'refresh_token': refresh_token,
'grant_type': 'refresh_token',
})
r = r.json()
assert 'error' not in r, r['error_description']
access_token = r['access_token']
if args.verbose:
print('=== access token ===')
print(access_token)
print()
### upload file ###
r = requests.post('https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart', files={
'metadata': (
None, json.dumps({
'name': file_name,
'parents': [
args.folder,
],
}),
'application/json; charset=UTF-8'
),
'file': (
file_name,
file_obj,
file_mime_type,
),
}, headers={
'Authorization': 'Bearer ' + access_token,
})
r = r.json()
assert 'error' not in r, '{} - {}'.format(r['error']['code'], r['error']['message'])
if args.verbose:
print('=== file id ===')
print(r['id'])
print()
(sorry for messy code file handling is messy)
I cant find any documentation which helps to create requests for shared drives
I just want it to work when I put a shared drive id as well
please suggest changes :)
Turns out all i had to do was put "&supportsAllDrives=true" after "https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart"
I have been experimenting with flask and the Reddit api, but no matter what I try, I seem to be hitting the 429 'too many requests' error every time I try to receive the access token.
The initial user auth works without any issue, and I receive the code back and can validate that I've auth'd the app in my Reddit settings. I've also made sure to use a unique user-agent, as this seemed to resolve the issue for most people, and am not using any words like 'bot', 'curl', 'web' or anything else which would be a likely blocker.
As far as I'm aware, I am also well under the tolerance of getting rate limited with too many requests.
Given that this is the first time I'm using both flask, and the Reddit API, I'm sure I'm missing something obvious,but after 4 hours, copious Googling and reading all the docs, I don't understand what I'm getting wrong here.
import requests
import requests.auth
from flask import Flask, redirect, request, url_for
import string
import random
app = Flask(__name__)
client_id = "client id of my web app"
client_secret = "client secret of my web app"
base_auth_url = 'https://www.reddit.com/api/v1'
authorization_endpoint = '/authorize'
access_token_endpoint = '/access_token'
#app.route("/login")
def get_the_auth_code():
state = state_generator()
params = {
'client_id': client_id,
'response_type': 'code',
'state': state,
'redirect_uri': 'http://localhost:5000/redditor',
'scope': 'identity',
'user-agent': 'myapp v0.1 by /u/myredditusername'
}
return redirect(url_builder(authorization_endpoint, params))
#app.route("/redditor")
def get_the_access_token():
code = request.args.get('code')
client_auth = requests.auth.HTTPBasicAuth(client_id, client_secret)
post_data = {
'grant_type': 'authorization_code',
'code': code,
'redirect_uri': 'http://localhost:5000/redditor',
'user-agent': 'myapp v0.1 by /u/myredditusername'
}
response = requests.post(base_auth_url + access_token_endpoint, auth=client_auth, data=post_data)
token_json = response.json()
return token_json
def state_generator(size=25, chars=string.ascii_uppercase + string.digits):
return ''.join(random.choice(chars) for _ in range(size))
def url_builder(endpoint, parameters):
params = '&'.join(['%s=%s' % (k, v) for k, v in parameters.items()])
url = '%s%s?%s' % (base_auth_url, endpoint, params)
return url
if __name__ == "__main__":
app.run(debug=True)
With help from the Reddit community (specifically /u/nmtake), I found out where I was going wrong.
In my get_the_access_token() function, I was adding the user-agent field to my data parameters, instead of declaring it as part of the header.
Instead of:
post_data = {
'grant_type': 'authorization_code',
'code': code,
'redirect_uri': 'http://localhost:5000/redditor',
'user-agent': 'myapp v0.1 by /u/myredditusername'
}
response = requests.post(base_auth_url + access_token_endpoint, auth=client_auth, data=post_data)
I am now using the following, which works perfectly:
post_data = {
'grant_type': 'authorization_code',
'code': code,
'redirect_uri': 'http://localhost:5000/redditor',
}
post_headers = {
'user-agent': 'myapp v0.1 by /u/myredditusername'
}
response = requests.post(base_auth_url + access_token_endpoint, auth=client_auth, data=post_data, headers=post_headers)
I'm looking to get access_token from fyers API
I'm able to get authorization_code and build authorization_url to open it in browser to enter user credentials. access_token is displayed in browser's address when user enters credentials but my program is unable to retrieve the access_code.
Your help is much appreciable.
My code is as follows:
from fyers_api import accessToken
from fyers_api import fyersModel
import requests
import webbrowser
import urllib.request as ur
app_id = "XXXXXXXXX"
app_secret = "XXXXXXXXX"
app_session = accessToken.SessionModel(app_id, app_secret)
response = app_session.auth()
if response['code'] != 200:
print('CODE=' + str(response['code']))
print('MESSAGE=' + str(response['message']))
print('Exiting program...')
exit(0)
authorization_code = response['data']['authorization_code']
app_session.set_token(authorization_code)
authorization_url=app_session.generate_token('XXXXXX')
token = webbrowser.open(authorization_url)
#Following authorization url is opened in browser:
#https://api.fyers.in/api/v1/genrateToken?authorization_code=xxxxxxxxxxxxx&appId=xxxxxxxxx&user_id=xxxxxx
#User is redirected to following url after successful log-in:
#https://trade.fyers.in/?access_token=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=&user_id=xxxxxx
print(token)
#token=”your_access_token”
#is_async = False #(By default False, Change to True for asnyc API calls.)
#fyers = fyersModel.FyersModel(is_async)
#fyers. get_profile(token = token)
Instead of writing the mentioned code, it is better to directly call Fyers Api.
import requests
url = 'https://api.fyers.in/api/v1/token'
requestParams = {
"fyers_id":"Your Client ID",
"password":"Your Password",
"pan_dob":"Your PAN card or DOB(DD-MM-YYYY)",
"appId":"YOur APP ID",
"create_cookie":False}
response = requests.post(url, json = requestParams )
print (response.text)
from fyers_api import accessToken
from fyers_api import fyersModel
app_id = "xxxxxxxxxx"
app_secret = "xxxxxxxxxx"
app_session = accessToken.SessionModel(app_id, app_secret)
response = app_session.auth()
print(app_session)
print(response)
authorization_code = response['data']['authorization_code']
app_session.set_token(authorization_code)
gen_token = app_session.generate_token()
print("token url is copy paste this url in browser and copy access
token excluding your id at Last ")
print(gen_token)
print("tokent printed thanks")
token="gAAAAABeTWk7AnufuuQQx0D0NkgABinWk7AnufuuQQx0DQ3ctAFWk7AnufuuQQx0DMQQwacJ-
_xUVnrTu2Pk5K5QCLF0SZmw7nlpaWk7AnufuuQQx0DG4_3EGCYw92-iAh8="
is_async = False
fyers = fyersModel.FyersModel(is_async)
print(fyers. get_profile(token = token))
fyers.funds(token = token)
print(fyers.funds(token = token))
I have been trying to retreive the access token for the paylocity API. I am able to get it through postman with the client id and client secret however when I try and retrieve it with Python I get the message {"error":"invalid_client"}. This is the code that I am using
import json
import base64
import requests
url = "https://api.paylocity.com/IdentityServer/connect/token"
client_id = ''
client_secret = ''
auth = (f'{client_id}:{client_secret}')
headers = {
'content-type': "application/x-www-form-urlencoded",
'Authorization': f"Basic {auth}"
}
body = "grant_type=client_credentials&scope=WebLinkAPI"
response = requests.request("POST", url, data=body, headers=headers)
print (response.text)
In case someone else stumbles on this response, since there are not many search hits for this:
To get the token from Paylocity and call their API:
client_id = {your client id string}
client_secret = {your client secret}
company_id = {your company id from Paylocity dashboard, without leading 'CS'}
prod_auth_url = 'https://api.paylocity.com/IdentityServer/connect/token'
body_params = urllib.parse.urlencode({'grant_type': 'client_credentials','scope':'WebLinkAPI'})
# Requests can use auth= for basic authentication
auth_response = requests.post(prod_auth_url,auth=(client_id, client_secret), data=urllib.parse.urlencode(body_params))
response = json.loads(auth_response.content)
api_call_headers = {'Authorization': 'Bearer ' + response['access_token']}
# Get all employees for a company
empl_response = requests.get(f"https://api.paylocity.com/api/v2/companies/{company_id}/employees/",headers=api_call_headers, verify=False)
pd.DataFrame(json.loads(empl_response.text))
Make sure you're using the client_id and client_secret for your token call, not the company id. It is not necessary to use any OAuth2 libraries to access the API.
for only the token I do:
import requests, json
token_url = "https://apisandbox.paylocity.com/IdentityServer/connect/token"
#client credentials
client_id = 'XXXX'
client_secret = 'XXXXXX'
#step A, B - single call with client credentials as the basic auth header - will return access_token
data = {'grant_type': 'client_credentials', 'scope':'WebLinkAPI'}
access_token_response = requests.post(token_url, data=data, verify=False, allow_redirects=False, auth=(client_id, client_secret))
print(access_token_response.headers)
print (access_token_response.text)
And after that code I recived the Token the same as the PostMan.
you can check: https://developer.byu.edu/docs/consume-api/use-api/oauth-20/oauth-20-python-sample-code
for more information/options.
Try the following with the same variables:
from requests_oauthlib import OAuth2Session
from oauthlib.oauth2 import BackendApplicationClient
client = BackendApplicationClient(client_id=client_id)
oauth = OAuth2Session(client=client)
token = oauth.fetch_token(token_url=url, client_id=client_id, client_secret=client_secret, body=body, headers=headers)
I am using the Flask JWT Extended extension for flask and have built a login application successfully using JWT. I have gone through the tutorial on JWT in Cookies on the JWT extended documentation site using CSRF protection and everything.
What I can't seem to figure out is when using the set_access_cookies() and set_refresh_cookies() methods the JWTs are not saved in a httponly cookie named using the JWT Extended default configuration setting.
app.config.setdefault('JWT_ACCESS_COOKIE_NAME', 'access_token_cookie')
app.config.setdefault('JWT_REFRESH_COOKIE_NAME', 'refresh_token_cookie')
Instead when I debug the return back from the auth call the cookies are saved in the base Flask default configuration instead.
'SESSION_COOKIE_NAME': 'session',
Shouldn't the set_access_cookies() and set_refresh_cookies() methods override the base Flask default configurations as long as make sure to register my app in the JWTManager()?
uscc_login_app = Flask(__name__)
jwt = JWTManager(uscc_login_app)
Or is there something else I missed in the base Flask JWT Extended documentation to ensure that its configuration defaults are used when appropriate?
Updated code via request.
The code is pretty spread out but here is my best shot to include what I think will help.
In init.py:
from flask import Flask, url_for
from flask_restful import Api
from flask_jwt_extended import JWTManager
from resources.auth import Authenticate
from resources.refresh import Refresh
from temp_app.temp import TempApp
from uscc_login.uscc_app_login import *
uscc_login_app = Flask(__name__)
uscc_login_app.config.from_object(os.environ.get('FLASK_ENV'))
jwt = JWTManager(uscc_login_app)
api = Api(uscc_login_app, prefix='/v1')
# Add resources via the add_resource method
api.add_resource(Authenticate, '/login')
api.add_resource(Refresh, '/refresh_token')
login_view = Login.as_view(name='uscc_login')
uscc_login_app.add_url_rule('/login', view_func=login_view, methods=['POST', 'GET'])
In my app.py:
from uscc_login import uscc_login_app
if __name__ == '__main__':
uscc_login_app.run(debug=uscc_login_app.config.get('DEBUG'), threaded=uscc_login_app.config.get('THREADED'),
port=uscc_login_app.config.get('PORT'), host=uscc_login_app.config.get('HOST'))
In my config.py since I am using the Flask config.from_objects
import os
import datetime
uscc_login_app_dir = os.path.abspath(os.path.dirname(__file__))
class BaseConfig:
SECRET_KEY = os.environ.get('USCC_SECRET_KEY') or 'you-will-never-guess'
JWT_SECRET_KEY = os.environ.get('USCC_JWT_KEY') or 'super-secret'
JWT_TOKEN_LOCATION = ['cookies']
JWT_COOKIE_CSRF_PROTECT = True
JWT_HEADER_TYPE = 'JWT'
PROPAGATE_EXCEPTIONS = True
THREADED = True
class DevelopmentConfig(BaseConfig):
DEBUG = True
PORT = 5000 if os.environ.get("PORT") is None else int(os.environ.get("PORT"))
HOST = os.environ.get('HOST') or 'localhost'
if os.environ.get('access_token_expiration') is not None:
JWT_ACCESS_TOKEN_EXPIRES = datetime.timedelta(seconds=int(os.environ.get('access_token_expiration')))
if os.environ.get('refresh_token_expiration') is not None:
JWT_REFRESH_TOKEN_EXPIRES = datetime.timedelta(seconds=int(os.environ.get('refresh_token_expiration')))
So then in my Flask MethodView that contains my login authorization POST I have the following:
auth.py
import sys
import os
from flask import jsonify, request
from flask_restful import Resource
from flask_jwt_extended import create_access_token, create_refresh_token, jwt_refresh_token_required, get_jwt_identity, \
set_access_cookies, set_refresh_cookies
from utilities import Common
class Authenticate(Resource):
#staticmethod
def post():
"""
:return:
"""
api_cred_path = os.environ.get('api_cred_path')
if api_cred_path is None:
response = jsonify({"msg": "Environment Variable 'api_cred_path' is not set."})
response.status_code = 500
return response
if not request.is_json:
response = jsonify({'msg': 'Missing JSON in request'})
response.status_code = 400
return response
params = request.get_json()
user_name = params.get('username')
user_password = params.get('password')
if not user_name:
response = jsonify({'msg': 'Missing username parameter'})
response.status_code = 400
return response
if not user_password:
response = jsonify({'msg': 'Missing password parameter'})
response.status_code = 400
return response
if Common.check_path_exists(api_cred_path):
with open(api_cred_path) as afh:
for line in afh:
file_userid, file_password = line.split('=')
if file_userid == user_name and file_password.strip('\n') == user_password:
access_token = create_access_token(identity=user_name)
refresh_token = create_refresh_token(identity=user_name)
response = jsonify({'login': True})
set_access_cookies(response, access_token)
set_refresh_cookies(response, refresh_token)
# # Identity can be any data that is json serializable
# art = {
# 'access_token': create_access_token(identity=user_name),
# 'refresh_token': create_refresh_token(identity=user_name)}
# response = jsonify(art)
response.status_code = 200
return response
else:
response = jsonify({"msg": "api_cred_path invalid."})
response.status_code = 500
return response
response = jsonify({'msg': 'Bad username or password'})
response.status_code = 401
return response
Could you provide some code to duplicate what you are seeing? When I try running the example token in jwt code (https://github.com/vimalloc/flask-jwt-extended/blob/master/examples/jwt_in_cookie.py) I see the expected cookie values when I login:
$ http :5000/token/auth username=test password=test
...
Set-Cookie: access_token_cookie=<jwt>; HttpOnly; Path=/api/
Set-Cookie: refresh_token_cookie=<jwt>; HttpOnly; Path=/token/refresh
...
So I realized my mistake in this. I was trying to get the access_token_cookie variable to be set from my auth.py which serves as my RESTFUL based microservice of which my login app calls to do the authorization. Realized it won't be available after redirecting back to the caller from the login apps POST method since the cookie was related to the login app UI frontend. So I just base the access and refresh tokens back from the auth.py POST method to the login POST method and let it set the cookies so they are available to the end client.
This was more of design problem than a code problem.