Django OAuth2 unsupported_grant_type - django

I'm trying to send a request with django to get an access_token from my api using OAuth2. I'm executing this code :
data = {'username': 'admin', 'password': '123123', 'grant_type':
'password','client_id': 'xxx','client_secret': 'xxx'}
headers = {'content-type': 'application/x-www-form-urlencoded'}
r = requests.post(url, data=data, headers=headers)
When I send this request I get this error :
{'error': 'unsupported_grant_type'}
Thanks for your help !

If anyone is interested the correct request was :
payload = "grant_type=password&client_secret=xxx&client_id=xxx&username=username&password=password"
headers = {
'content-type': "application/x-www-form-urlencoded",
'cache-control': "no-cache",
}
response = requests.request("POST", url, data=payload, headers=headers)

If you don't want to encode data in url, you can put this in your settings.
OAUTH2_PROVIDER = {
'OAUTH2_BACKEND_CLASS': 'oauth2_provider.oauth2_backends.JSONOAuthLibCore',
}

I had the same problem and later I found that the grant type should be a string.
payload = {'grant_type': 'refresh_token', 'refresh_token': refresh_token}

Related

Fastapi Testclient not able to send POST request using form-data

Currently I am doing Unit Testing in Fastapi using from fastapi.testclient import TestClient
def test_login_api_returns_token(session,client):
form_data = {
"username": "mike#gmail.com",
"password": "mike"
}
response = client.post(
"/api/login",
data=form_data,
headers={"content-type": "multipart/form-data"}
# headers={"content-type": "application/x-www-form-urlencoded"}
)
result = response.json()
assert response.status_code == 200
I am supposed to get token as response which I am getting when I run the fastapi application but not able to proceed with Unit Testing with the same.
Example of postman request for the same
How do I make sure form-data is being sent from TestClient?
api/login.py
#router.post("/login")
async def user_login(form_data: OAuth2PasswordRequestForm = Depends(), session: Session = Depends(get_session)):
user = authenticated_user(form_data.username, form_data.password, session)
user = user[0]
if not user:
raise token_exception()
token_expires = timedelta(minutes=120)
token = create_access_token(username=user.username, user_id=user.id, expires_delta=token_expires)
token_exp = jwt.decode(token, SECRET, algorithms=[ALGORITHM])
return {
"status_code": status.HTTP_200_OK,
"data":{
"username": user.username,
"token": token,
"expiry": token_exp['exp'],
"user_id": user.id
}
}
Try set the header to Content-Type form-data like
def test_login_api_returns_token(session,client):
form_data = {
"username": "mike#gmail.com",
"password": "mike"
}
response = client.post(
"/api/login",
json=form_data,
headers={ 'Content-Type': 'application/x-www-form-urlencoded'}
)
result = response.json()
assert response.status_code == 200

AWS API Gateway Post Requests

I created an api with AWS Api Gateway and when I try to execute a POST request I get a 403 vs when I do GET request it returns 200 and returns the data I expect.
data = json.dumps({'to': 'USD', 'from': 'CNY', 'start': '2022-03-01', 'end': '2022-12-01'})
requests.get(url,headers = headers,data=data).json()
headers = {'Content-type': 'application/json'}
data = json.dumps({'to': 'USD', 'from': 'CNY', 'start': '2022-03-01', 'end': '2022-12-01'})
requests.post(url,headers = headers,data=data).json()
>>> {'message': 'Missing Authentication Token'}
How do I authenticate to get a 200 for a post requests ?

Invoking PowerBi rest api and generate token

I want to invoke PowerBI rest api calls to upload pbix files from local/specific repository.
How should I generate bearer token for authorization from Postman?
Will this rest api call work to generateToken?
What needs to passed as authorization token for this rest call?
Does myorg is the PowerBI account name? from where can I fetch the myorg value?
POST https://api.powerbi.com/v1.0/myorg/GenerateToken
Below are few more calls that I want to invoke through postman:
GET https://api.powerbi.com/v1.0/myorg/imports
GET https://api.powerbi.com/v1.0/myorg/reports/{reportId}
and few post calls also.
What will be a quick solution for generating token?
You can use this function to request access
it is necessary to create the Client ID in azure
https://learn.microsoft.com/en-us/power-bi/developer/embedded/register-app?tabs=customers%2CAzure
application_id= 'None'
application_secret= 'None'
user_id= 'None'
user_password= 'None'
accessToken = None
requestHeaders = None
tokenExpiry = None
accessToken_AD = None
requestHeaders_AD = None
tokenExpiry_AD = None
def pbi_auth(application_id,application_secret,user_id,user_password):
global accessToken
global requestHeaders
global tokenExpiry
data = {
'grant_type': 'password',
'scope': 'openid',
'resource': "https://analysis.windows.net/powerbi/api",
'client_id': application_id,
'client_secret': application_secret,
'username': user_id,
'password': user_password
}
token = requests.post("https://login.microsoftonline.com/common/oauth2/token", data=data)
assert token.status_code == 200, "Fail to retrieve token: {}".format(token.text)
#print("Got access token: ")
#print(token.json())
accessToken = token.json()['access_token']
requestHeaders= {
'Content-Type': 'application/json; charset=utf-8',
'Authorization': "Bearer {}".format(accessToken)
}
pbi_auth(application_id,application_secret,user_id,user_password)
reportId= ""
URI = "https://api.powerbi.com/v1.0/myorg/reports/{}".format(reportId)
queryResults = requests.get(URI, headers=requestHeaders)

getting code 400 message Bad request syntax , after post from flutter

getting code 400 message Bad request syntax , after post from flutter,
with postman request send and no problem but with flutter after Post Map data to Django server i get this error
[19/May/2020 14:58:13] "POST /account/login/ HTTP/1.1" 406 42
[19/May/2020 14:58:13] code 400, message Bad request syntax ('32')
[19/May/2020 14:58:13] "32" 400 -
Django
#api_view(['POST'])
def login_user(request):
print(request.data)
if request.method == 'POST':
response = request.data
username = response.get('username')
password = response.get('password')
if password is not None and username is not None:
user = authenticate(username=username, password=password)
if user is not None:
create_or_update_token = Token.objects.update_or_create(user=user)
user_token = Token.objects.get(user=user)
return Response({'type': True, 'token': user_token.key, 'username': user.username},
status=status.HTTP_200_OK)
else:
return Response({'type': False, 'message': 'User Or Password Incorrect'},
status=status.HTTP_404_NOT_FOUND)
else:
return Response({'type': False, 'message': 'wrong parameter'}, status=status.HTTP_406_NOT_ACCEPTABLE)
else:
return Response({'type': False, 'message': 'method is wrong'}, status=status.HTTP_405_METHOD_NOT_ALLOWED)
flutter
Future<dynamic> postGoa(String endpoint, Map data)async{
Map map = {
"username":"user",
"password":"password"
};
var url = _getUrl("POST", endpoint);
var client = new HttpClient();
HttpClientRequest request = await client.postUrl(Uri.parse(url));
request.headers.set('content-type', 'application/json');
request.headers.set('Authorization', 'Bearer '+ athenticated
);
request.add(utf8.encode(json.encode(map)));
HttpClientResponse response = await request.close();
String mydata= await response.transform(utf8.decoder).join();
client.close();
return mydata;
}
}
after add
request.add(utf8.encode(json.encode(map)));
i get error in Django console
Try printing out your request headers from the Django application.
print(request.headers)
I bet one of the headers is Content-Type: ''. If that is the case, Django isn't reading your POST data because it thinks there is no data. I recommend calculating the length of the content you are sending in Flutter, then sending the correct Content-Length header with your request.
That might look something like this (in your Flutter app):
encodedData = jsonEncode(data); // jsonEncode is part of the dart:convert package
request.headers.add(HttpHeaders.contentLengthHeader, encodedData.length);

migrate from urllib2 to requests python 2.7

I am trying to take some working code and change from urlib2 to requests.
The original code provides basic login information of username, password and posts the KEY and SECRET in the header of the urllib2 request. The following code is my attempt to change to using the requests module and gain some functionality for making additional API calls. I have tried dozens of combinations and all return a code 400. Apparently, my requests code does not successfully furnish the needed information to return a 200 response and provide the needed authorization token.
## Import needed modules
import urllib2, urllib, base64
import httplib
import requests
import json
## initialize variables
KEY = "7f1xxxx-3xxx-4xxx-9a7f-8be66839dede"
SECRET = "45xxxxxx-45xxx-469a-9ae9-a7927a76cfeb"
userName = "my-email#xxx.com"
passWord = "mypassword"
URL = "https://company.com/auth/token"
token = None
sessionid = None
DATA = urllib.urlencode({"grant_type":"password",
"username":userName,
"password":passWord})
base64string = base64.encodestring('%s:%s' % (KEY, SECRET)).replace('\n', '')
request = urllib2.Request(URL, DATA)
request.add_header("Authorization", "Basic %s" % base64string)
result = urllib2.urlopen(request)
token = result.read()
print token
This returns my authorization token and all is well. I can pass the token to the authorization server and have full access to the api for interacting with the database. Below is the attempt to use requests and have the added functions it provides.
client = requests.session()
payload = {"grant_type":"password",
"username":userName,
"password":passWord,
"applicationId": KEY
}
headers = {'content-type':'application/json',
"grant_type":"password",
"username":userName,
"password":passWord,
'applicationsId': KEY,
'Authorization': base64string,
'token': token,
'sessionid': sessionid
}
response = client.post(URL, params = payload, headers=headers)
token = response.content
print token
{"error":"invalid_request"}
print response
<Response [400]>
If you want to use basic auth you should use the method from requests..
Your post should look like
response = client.post(
URL,
params = payload,
headers=headers,
auth=HTTPBasicAuth(
KEY,
SECRET
))
Somewhere in a post a contributor to another question mentioned some items actually needed to be in the body of the request not in the header. I tried various combos and the following solved the 400 response and accomplished my goals.
data = {"grant_type":"password",
"username":userName,
"password":passWord,
"applicationId": KEY
}
headers = {'Authorization': "Basic %s" % base64string,
'token': token
}
response = client.post(URL, data = data, headers=headers)
token = response.text
print token