I am using simplejwt to get an access and refresh tokens. In a view I need to create a dict, where the both will be stored as well as access token claims and another additional data. Everything works but by some reason when the refrsh token is added to dict, it returns its decoded value, but not the token.
my views.py
#csrf_exempt
##api_view(('GET',))
def check_token(request):
token_refresh = RefreshToken.for_user(request.user)
print('REFRESH', token_refresh)
token = request.META.get('HTTP_AUTHORIZATION', " ").split(' ')[1]
data = {'token': token, 'refresh_token': token_refresh}
try:
valid_data = TokenBackend(algorithm='HS256').decode(token, verify=False)
data['uui'] = valid_data['user_id']
data['validUntil'] = valid_data['exp']
data['clientId'] = 'default'
print(data)
return JsonResponse(data)
except ValidationError as v:
print("Validation error", v)
print('REFRESH', token_refresh) returns the token:
'REFRESH eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI...'
but data object returns:
{'token': 'eyJ0eXAiOiJKV1QiLCJhbGci...', 'refresh_token': {'token_type': 'refresh', 'exp': 1628664751, 'jti': '38f0e3a4d7bb452681834a6b149aa496', 'user_id': 'None'}, 'uui': 1, 'validUntil': 1628059131, 'clientId': 'default'}
my ideal result:
{'token': 'eyJ0eXAiOiJKV1QiLCJhbGci...', 'refresh_token': 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI...', 'uui': 1, 'validUntil': 1628059131, 'clientId': 'default'}
if you want to create tokens manually for user in djangorestframework-simplejwt you can do this:
from rest_framework_simplejwt.tokens import RefreshToken
def get_tokens_for_user(user):
refresh = RefreshToken.for_user(user)
return {
'refresh': str(refresh),
'access': str(refresh.access_token),
# Add additional fields here
}
now you can use this function in your views.
Related
I'am trying to make an API request where I add some optional values but if I don't add them I don't want them to be in the request.
In this case, I would like the parameters to be 'startblock' & 'endblock'
def get_transactions_by_address_(self, address, action='txlist'):
"""
:param address:
:param action: [txlist, txlistinternal]
:return:
"""
token = self.etherscan_api_key
return requests.get('https://api.etherscan.io/api'
'?module=account'
f'&action={action}'
f'&address={address}'
# '&startblock=0'
# '&endblock=92702578'
'&page=1'
'&offset=1000'
'&sort=desc'
f'&apikey={token}'
)
I was thinking on adding some conditionals like
request_url = 'https://api.etherscan.io/api...'
if startblock:
request_url = request_url + f'&startblock={startblock}'
if endblock:
request_url = request_url + f'&endblock={endblock}'
But I don't know if it is the most pythonic way to do it and I would like to get other options on how to do it
Use the payload option instead of constructing the URL yourself. For example, create a dict containing all the required options, then add additional parameters to the dict as necessary. requests.get will build the required URL from the base URL and the values found in your dict.
options = {
'module': 'account',
'action': action,
'address': address,
'apikey': token,
'sort': sort,
'page': page,
'offset': offset
}
if startblock:
options['startblock'] = startblock
if endblock:
options['endblock'] = endblock
return requests.get('https://api.etherscan.io/api', params=options)
The correct way to implement is:
def get_transactions_by_address_(self, address,
action='txlist',
sort='desc',
page=1,
offset=1000,
startblock=None,
endblock=None):
token = self.etherscan_api_key
options = {
'module': 'account',
'action': action,
'address': address,
'apikey': token,
'sort': sort,
'page': page,
'offset': offset
}
if startblock:
options['startblock'] = startblock
if endblock:
options['endblock'] = endblock
return requests.get('https://api.etherscan.io/api',
params=options
)
This is my code to extract player data from an endpoint containing basketball data for a Data Science project.NOTE: I changed the name of the actual API key I was given since it's subscription. And I change the username/password because for privacy purposes. Using the correct credentials, I wouldn't receive a syntax error but the status code always returns 401. Since it wasn't accepting the API key, I added my account username, password, and the HTTP authentication header as well, but the status code still returns 401.
In case this is relevant, this is the website's recommendation in the developer portal: **The API key can be passed either as a query parameter or using the following HTTP request header.
Please let me know what changes I can make to my code. Any help is appreciated.
Ocp-Apim-Subscription-Key: {key}**
PS: My code got fragmented while posting this, but it is all in one function.
def getData():
user_name = "name#gmail.com"
api_endpoint = "https://api.sportsdata.io/v3/nba/stats/json/PlayerGameStatsByDate/2020-FEB7"
api_key = "a45;lkf"
password = "ksaljd"
header = "Ocp-Apim-Subscription-Key"
PARAMS = {'user': user_name, 'pass': password, 'header': header, 'key': api_key}
response = requests.get(url = api_endpoint, data = PARAMS)
print(response.status_code)
file = open("Data.csv", "w")
file.write(response.text)
file.close()
def _get_auth_headers() -> dict:
return {
'Content-Type': 'application/json',
'Ocp-Apim-Subscription-Key': "`Insert key here`"
}
api_endpoint = "https://api.sportsdata.io/v3/nba/stats/json/PlayerGameStatsByDate/2020-FEB7"
PARAMS = {
# Your params here
}
response = requests.get(
api_endpoint,
headers=_get_auth_headers(),
params=PARAMS
)
Instead of just a string, you need to pass dict in the headers parameter and auth param exist so you can use it as follow:
def getData():
[...]
header = {
"Ocp-Apim-Subscription-Key": api_key
}
[...]
response = requests.get(url = api_endpoint, data = PARAMS, headers=header, auth = (user_name, password))
According to the API documentation you don't need to provide email and password. You're only need to add your API Key to header:
import requests
r = requests.get(url='https://api.sportsdata.io/v3/nba/stats/json/PlayerGameStatsByDate/2020-FEB7', headers={'Ocp-Apim-Subscription-Key': 'API_KEY'})
print(r.json())
Output:
[{
'StatID': 768904,
'TeamID': 25,
'PlayerID': 20000788,
'SeasonType': 1,
'Season': 2020,
'Name': 'Tim Hardaway Jr.',
'Team': 'DAL',
'Position': 'SF',
'Started': 1,
'FanDuelSalary': 7183,
'DraftKingsSalary': 7623,
'FantasyDataSalary': 7623,
...
I want to use this route here (below) and render my react file. Using a python route.... Could someone give me some direction on how I can accomplish this?
#Auth.route('/login', methods=['GET'])
def login():
#data = {'username':'bob', 'password':'peepee123'}
#session['token'] = 'jsdkfkj934ujeklfjdlndsflds'
auth = request.authorization
if auth and auth.password == 'password':
token = jwt.encode({'user': auth.username}, app.config['SECRET_KEY'])
return jsonfiy({'token': token.decode('UTF-8')})
return make_response('Could Not verify!', 401, {'WWW-Authenticate': 'Basic realm = "Login Required"'})
If you want to render react in server site in python you can use python-react-v8, but you need to have the same react tree in server and client or it wont work, checkout hydrate in docs. For that you need to have working react app.
Example of usage:
import react
# setup react
react.set_up() # Initialize V8 machinery
react.utils.load_libs(['./bundle.js'])
#Auth.route('/login', methods=['GET'])
def login():
#data = {'username':'bob', 'password':'peepee123'}
#session['token'] = 'jsdkfkj934ujeklfjdlndsflds'
auth = request.authorization
if auth and auth.password == 'password':
token = jwt.encode({'user': auth.username}, app.config['SECRET_KEY'])
data = {'token': token.decode('UTF-8')};
react_ = react.React({
'url': request.get_full_url(),
'data': data
})
context = {
'content': react_.render(),
'data': react_.to_json(data)}
return render('index.html', context);
data = {'token': null, 'reason': "Login Required"}
react_ = react.React({
'url': request.get_full_url(),
'data': data
})
context = {
'content': react_.render(),
'data': react_.to_json(data)
}
return render('index.html', context);
I am trying to retrieve data from the first available date to present date from an API. I've tried using min and max in parameter.
def getcomplete(cid, pid, tag, type):
api_endpoint = ''
headers = {'token': get_token()['access_token'], 'Content-Type': 'application/json'}
params = {'cid': str(cid),
'from-date': datetime.datetime.min,
'to-date': datetime.datetime.max,
'tag': str(tag),
'type': str(type),
'pid': str(pid)
}
r = requests.post(url=api_endpoint, headers=headers, params=params)
return r.json()
getcomplete(10,12,'x','y')
This returns {'status': 'success', 'message': 'success', 'data': []}.
Is there anything wrong with the written function.
Thanks
Pythons min() and max() have an optional default parameter. This will prevent them from throwing errors
min("", default="")
I have clien-server app.
I localized trouble and there logic of this:
Client:
# -*- coding: utf-8 -*-
import requests
def fixing:
response = requests.post('http://url_for_auth/', data={'client_id': 'client_id',
'client_secret':'its_secret', 'grant_type': 'password',
'username': 'user', 'password': 'password'})
f = response.json()
data = {'coordinate_x': 12.3, 'coordinate_y': 8.4, 'address': u'\u041c, 12',
'products': [{'count': 1, 'id': 's123'},{'count': 2, 'id': 's124'}]}
data.update(f)
response = requests.post('http://url_for_working/, data=data)
response.text #There I have an Error about which I will say later
oAuth2 working well. But in server-side I have no products in request.data
<QueryDict: {u'token_type': [u'type_is_ok'], u'access_token': [u'token_is_ok'],
u'expires_in': [u'36000'], u'coordinate_y': [u'8.4'],
u'coordinate_x': [u'12.3'], u'products': [u'count', u'id', u'count',
u'id'], u'address': [u'\u041c, 12'], u'scope': [u'read write'],
u'refresh_token': [u'token_is_ok']}>
This part of QueryDict make me sad...
'products': [u'count', u'id', u'count', u'id']
And when I tried to make python dict:
request.data.dict()
... u'products': u'id', ...
And for sure other fields working well with Django serializer's validation. But not that, because there I have wrong values.
Looks like request (because it have x-www-encoded-form default) cant include list of dicts as value for key in dict so... I should use json in this case.
Finally I maked this func:
import requests
import json
def fixing:
response = requests.post('http://url_for_auth/', data={'client_id': 'client_id',
'client_secret':'its_secret', 'grant_type': 'password',
'username': 'user', 'password': 'password'})
f = response.json()
headers = {'authorization': f['token_type'].encode('utf-8')+' '+f['access_token'].encode('utf-8'),
'Content-Type': 'application/json'}
data = {'coordinate_x': 12.3, 'coordinate_y': 8.4, 'address': u'\u041c, 12',
'products': [{'count': 1, 'id': 's123'},{'count': 2, 'id': 's124'}]}
response = requests.post('http://url_for_working/', data=json.dumps(data),
headers=headers)
response.text
There I got right response.
Solved!
Hello i would like to refresh this topic, cause i have similar problem to this and above solution doesn`t work for me.
import requests
import urllib.request
import pprint
import json
from requests import auth
from requests.models import HTTPBasicAuth
payload = {
'description': 'zxcy',
'tags':[{
'id': 22,
'label': 'Card'}]
}
files = {'file': open('JAM5.pdf','rb')}
client_id = 32590
response = requests.post('https://system...+str(client_id)' , files=files ,data=payload, auth=HTTPBasicAuth(...)
Above code succesfully add file to CRM system and description to added file, but i have to add label to this too, and its seems doesnt work at all
When i try it with data=json.dumps(payload) i got this:
raise ValueError("Data must not be a string.")
ValueError: Data must not be a string.