Python - Basic Authorization (OAuth2.0) to retrieve access token from API - python-3.x

I'm trying to generate an access token from an API using the following required information:
Authorization endpoint: https://api.paylocity.com/IdentityServer/connect/token
Authorization Header
The request is expected to be in the form of a basic authentication request, with the "Authorization" header containing the client-id and client-secret. This means the standard base-64 encoded user:password, prefixed with "Basic" as the value for the Authorization header, where user is the client-id and password is the client-secret.
Content-Type Header
The "Content-Type" header is required to be "application/x-www-form-urlencoded".
Other Values
The request must post the following form encoded values within the request body:
grant_type = client_credentials
scope = WebLinkAPI
I've tried using the Python 'requests' package without success, see below:
import requests
url = "https://api.paylocity.com/IdentityServer/connect/token"
headers = {
'Authorization': "Basic **********:**********",
'Content-Type': "application/x-www-form/urlencoded"
}
body = {
'grant_type': "client_credentials",
'scope': 'WebLinkAPI'
}
response = requests.request("POST", url, headers=headers, params=body)
print(response.text)
Instead of an access token, I receive an error message:
{"error":"invalid_client"}
I've verified that my base64 encoded username and password are correct, it looks something like "G/RaNdOm:MoReRaNdOm==" and when I add them to postman it works so my credentials are correct. What could be wrong?

I resolved this. There were two issues, the Authorization header was not using ASCII as the destination charset with base64 encoding. The other issue was trying to add the additional values to the parameters instead of the body in the requests package. The solution was to replace "params" with "data". Here was the solution:
url = "https://api.paylocity.com/IdentityServer/connect/token"
body = "grant_type=client_credentials&scope=WebLinkAPI"
headers = {
'Content-Type': "application/x-www-form-urlencoded",
'Authorization': "Basic ***(base64ASCII)username:password***",
}
response = requests.request("POST", url, data=body, headers=headers)
print(response.text)

Related

Google Oaut2 - Python using requests whiout Library

I am trying to authenticate not google by means of requests if I use the api but I don't know what I put in the "code" field and it will work, you can help me, or the code follows below.
import requests
url = "https://accounts.google.com/o/oauth2/token"
payload='grant_type=authorization_code&client_secret=xxxxx&client_id=xxxx&redirect_uri=https%3A%2F%2Fpushsistemas.com.br%2F&code='
headers = {
'content-type': 'application/x-www-form-urlencoded',
'Cookie': 'NID=219=RgUebbUM4k3WX0uQr8HVcIZkQ5-rMrb4HHnfnRzNTxUse776sG6-LItgXwpdv-MmaFYf3Tu4otJN-UfP70OzDtdnfam2dwAZkd6yMsr8BW_7lGE4FTaas9QkoG-hOMqXgYEHvI4YK39dWgXhWnL0E5LcsOv0DXnfjJ2kUf7VlTs; __Host-GAPS=1:jGXTa0ipDEC58oJF7pZwNBVeSXCQRw:3IRHy3GC9mAq4nqt'
}
response = requests.request("POST", url, headers=headers, data=payload)
This output
{
"error": "invalid_request",
"error_description": "Missing required parameter: code"
}
if it is not possible to do this way could you send me how to do it using the google library?

How to pass Authorization TOKEN into Python requests header

I am trying to make a http request using Python3.8.5 + requests 2.25.0. The request contains Authorization Token in the header.
When use Postman to make the request, I can get response without issue. But, when I use following python code to make the request, it returns 401. Not sure what is worng in the code.
401 {"detail":"Authentication credentials were not provided."}
Following are the python code having issues.
import requests
url = <MY_URL>
payload={}
headers = {
'Authorization': 'TOKEN <MY_TOKEN>'
}
response = requests.request("GET", url, headers=headers, data=payload)
print(response.text)
The problem resloved by adding a / at the end of the request url. :-)

Yahoo API - Unable to request new access token once previous access token has expired

I am attempting to use Yahoo's API for fantasy football. I am able to receive an access token and refresh token initially, but once that access token has expired, I am unable to get another one.
My code is as follows:
from requests import Request, get, post
import webbrowser
import base64
baseURL = 'https://api.login.yahoo.com/'
oauthENDPOINT = "https://api.login.yahoo.com/oauth2/request_auth"
## Generate a url using the endpoint and parameters above
params = {'client_id' : client_id,
'redirect_uri' : "oob",
'response_type' : 'code'}
p = Request('GET', oauthENDPOINT, params=params).prepare()
webbrowser.open(p.url)
The last line sends me to the Yahoo website where I allow myself access and receive authCode.
encoded = base64.b64encode((client_id + ':' + client_secret).encode("utf-8"))
headers = {
'Authorization': f'Basic {encoded.decode("utf-8")}',
'Content-Type': 'application/x-www-form-urlencoded'
}
data = {
'grant_type': 'authorization_code',
'redirect_uri': 'oob',
'code': authCode}
tokenResponse = post(baseURL + 'oauth2/get_token', headers=headers, data=data)
tokenResponseJSON = tokenResponse.json()
access_token = tokenResponseJSON['access_token']
refresh_token = tokenResponseJSON['refresh_token']
I now have all the information necessary to examine the settings of my league (for example).
fbURL = 'https://fantasysports.yahooapis.com/fantasy/v2'
leagueURL1 = f'{fbURL}/leagues;league_keys=nfl.l.{leagueID}/settings'
headers = {
'Authorization': f'Bearer {access_token}',
'Accept': 'application/json',
'Content-Type': 'application/json'
}
response2 = get(leagueURL1, headers=headers,params={'format': 'json'})
The above works as expected. However, the access_token lasts for 3600 seconds and once that time has expired I am unable to request a new one, using my refresh_token. My attempt:
accessTokenData = {
'grant_type': 'refresh_token',
'redirect_uri': 'oob',
'code': authCode,
'refresh_token': refresh_token
}
accessTokenResponse = post(baseURL + 'oauth2/get_token', headers=headers, data=accessTokenData)
accessTokenJSON = accessTokenResponse.json()
In the above, I am hoping to receive a new access_token, but instead accessTokenJSON is this:
{'error': {'localizedMessage': 'client request is not acceptable or not supported',
'errorId': 'INVALID_INPUT',
'message': 'client request is not acceptable or not supported'}}
Up to this point I have been following these steps, which worked well up to this point. What am I doing wrong? I understand many Python users use yahoo_oauth or rauth for authentication, but that involves saving the client_id and client_secret in a .json file separately and I'm looking to load those in dynamically. I don't think I'm very far away from succeeding, but I'm just missing something when it comes to generating a new refresh_token. All help much appreciated!
Thanks to referring back to our guide.
Managed to reproduce your error and it's really simple to solve.
You are redefining the headers variable in your request to the fantasyspot url.
The headers variable should be the same in the call for requesting a new access_token using the refresh_token as it was when initially getting both tokens using the auth_code.
So just define header before making requesting a new access_token. Should look like the the following:
headers = {
'Authorization': f'Basic {encoded.decode("utf-8")}',
'Content-Type': 'application/x-www-form-urlencoded'
}
response = post(base_url + 'oauth2/get_token', headers=headers, data=data)
Should work now.
Recommend using different variable names for the headers used for getting an access_token and the one used to the fantasy sport url.

pisignage API login error: "This username/email is not registered or active"

From there api docs, I have created a request to login and get the token. The code is under below, it returns 401 . The credentials are right and I can log in from web, but through API I can not.
import requests
import json
params_dict = {
"email": "example#mail.com",
"password": "example",
"getToken": True
}
response = requests.post(
'https://example.piathome.com/api/session',
data=params_dict
# headers={'Content-type': 'application/json', 'accept': 'application/json'} returns 500
)
json_response = response.json()
print(json_response)
Make sure that the API endpoint is set to username.pisignage.com (not just pisignage.com).
And the headers are absolutely required. Request and Response types must be set to application/json.

Error calling CF API login one time passcode

I am working with the CF API RESTful services. Trying to get an access token from cloud foundry's UAA API using https://login..../oauth/token web method.
I have verified that headers & body content is correct, but calling the api always returns a 400 error code with message missing grant type.
I have implemented this call in Objective-C, Swift & now Python. All tests return the same result. Here is my code example in Python:
import json
import requests
import urllib
params = {"grant_type": "password",
"passcode": "xxx"
}
url = "https://login.system.aws-usw02-pr.ice.predix.io/oauth/token"
headers = {"Authorization": "Basic Y2Y6", "Content-Type": "application/json", "Accept": "application/x-www-form-urlencoded"}
encodeParams = urllib.parse.urlencode(params)
response = requests.post(url, headers=headers, data=encodeParams)
rjson = response.json()
print(rjson)
Each time I run this, I get the response
error invalid request, Missing grant type
Any help would be greatly appreciated.
Your code mostly worked for me, although I used a different UAA server.
I had to make only one change. You had the Accept and Content-Type headers flipped around. Accept should be application/json because that's the format you want back, and Content-Type should be application/x-www-form-urlencoded because that's the format you are sending.
See the API Docs for reference.
import json
import requests
import urllib
import getpass
UAA_SERVER = "https://login.run.pivotal.io"
print("go to {}/passcode".format(UAA_SERVER))
params = {
"grant_type": "password",
"passcode": getpass.getpass(),
}
url = "https://login.run.pivotal.io/oauth/token"
headers = {
"Authorization": "Basic Y2Y6",
"Content-Type": "application/x-www-form-urlencoded",
"Accept": "application/json"
}
encodeParams = urllib.parse.urlencode(params)
response = requests.post(url, headers=headers, data=encodeParams)
rjson = response.json()
print(json.dumps(rjson, indent=4, sort_keys=True))
I made a couple other minor changes, but they should affect the functionality.
Use getpass.getpass() to load the passcode.
Set the target server as a variable.
Pretty print the JSON response.
The only other thing to note, is that the OAuth2 client you use must be allowed to use the password grant type. It looks like you're using the same client that the cf cli uses, so if your UAA server is part of a standard Cloud Foundry install that is likely to be true, but if it still doesn't work for you then you may need to talk with an administrator and make sure the client is set up to allow this.

Resources