Getting "unsupported_grant_type" when trying to refresh xero API token using python - api

Getting "unsupported_grant_type" when trying to refresh token using python
Hi,
I've been trying to get a new access token & refresh token using an existing refresh token that I have. I am following the documentation as stated on the website https://developer.xero.com/documentation/oauth2/auth-flow but I keep getting an error saying "unsupported_grant_type" although I do define grant_type = refresh_token. Here's my code, any help would be greatly appreciated.
import json
from base64 import b64encode
client_id = xxx
client_secret = xxx
RefreshToken = xxx
b64_id_secret = b64encode(client_id + ':' + client_secret)
def XeroRefreshToken(refresh_token):
token_refresh_url = 'https://identity.xero.com/connect/token'
response = requests.post(token_refresh_url,
headers = {
'Authorization' : 'Basic ' + b64_id_secret,
'Content-Type': 'application/x-www-form-urlencoded'
},
data = {
'grant_type' : 'refresh_token',
'refresh_token' : refresh_token
})
json_response = response.json()
print(json_response)
new_refresh_token = json_response['refresh_token']
XeroRefreshToken(RefreshToken)

Related

Need to access to the Bynder API

I am trying to connect to the Bynder API using Python and the documentation https://bynder.docs.apiary.io/ but I can make it to connect to the Analytics endpoint https://bynder.docs.apiary.io/#reference/analytics because I received a 401 response
I have the following code :
from bynder_sdk import BynderClient
headers = {
'Content-Type': 'application/x-www-form-urlencoded',
'Origin': 'Allowed domain for cross-domain requests. Only required if any domains were specified in \'Set HTTP access control (CORS)\' for the OAuth application.',
'Authorization': 'Basic b64("abcd":"abcd")'
}
bynder_client = BynderClient(
domain='abcd.com',
redirect_uri='https://abcd.com/v7/analytics/api/v1/asset/view',
client_id='abcd',
client_secret='abcd',
scopes ="offline analytics.api:read",
grant_type="client_credentials"
)
print(bynder_client.get_authorization_url())
print(bynder_client.get_authorization_url()[1])
params = {"limit":"100", "fromDateTime":"2022-01-01T01:00","toDateTime":"2022-06-01T01:00" }
api_call_headers = {'Authorization': 'Token ' + bynder_client.get_authorization_url()[1]}
api_call_response = requests.get("https://abcd.abcd.com/v7/analytics/api/v1/asset/view", headers=api_call_headers, params=params, verify=False)
can someone help me to understand how to Autorise using OAuth 2.0 the Client ID and Client Secret and use the Analytics endpoint? I have all the details in the bynder_client = BynderClient()
Thanks
For anyone reference this his how I ended up making my code work:
endpoint_api_url="https://abcd.abcd.com/v7/analytics/api/v1/asset/download"
auth_server_url = "https://abcd.abcd.com/v6/authentication/oauth2/token"
client_id = 'abcd'
client_secret='abcd'
token_req_payload = {'grant_type': 'client_credentials'}
token_response = requests.post(auth_server_url,
data=token_req_payload, verify=False, allow_redirects=False,
auth=(client_id, client_secret))
print(token_response.status_code)
if token_response.status_code ==200:
print("Successfuly obtained a new token")
print(token_response.text)
tokens = json.loads(token_response.text)
token = tokens['access_token']
print(token)
else:
print("Failed to obtain token from the OAuth 2.0 server", file=sys.stderr)
sys.exit(1)
params = {"limit":"100", "fromDateTime":"2022-01-01T01:00","toDateTime":"2022-06-01T01:00" }
api_call_headers = {'Authorization': 'Bearer ' + token}
api_call_response = requests.get(endpoint_api_url, headers=api_call_headers, params=params, verify=False)
print(api_call_response.text)

OAuth2: Unable to Authenticate API request

Been tasked to export forms and items from Podio using the API. Trying to do this with straight Python and Requests instead of the canned API tool. Am successful at retrieving the access and refresh tokens, but am unable to make the simplest Get request. The response has the error:
"error_description":"Authentication as None is not allowed for this method"
Tried this with 2 versions of using OAuth2 in Requests, both return that response.
What is it trying to tell me? Aside from giving the token, is there any other authentication attributes required?
client = BackendApplicationClient(client_id=CLIENT_ID)
oauth = OAuth2Session(client=client)
token = oauth.fetch_token(token_url=auth_url, client_id=CLIENT_ID,
client_secret=CLIENT_SECRET)
print('token:', token)
access_token = token["access_token"]
api_url = base_url + 'user/status'
r = oauth.get(api_url)
print(r.text)
headers = {'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
"Authorization": "Bearer " + token["access_token"]}
response = requests.get(api_url, headers=headers, verify=True)
print(response.text)
Here is full response:
{"error_parameters":{},"error_detail":null,"error_propagate":false,"request":{"url":"http://api.podio.com/user/status","query_string":"","method":"GET"},"error_description":"Authentication as None is not allowed for this method","error":"forbidden"}

Successful Login to API; Unsuccessful at accessing any data due to being unauthorized

I am attempting to come up with a live leaderboard for my local club using the PDGA's (Professional Disc Golf Association) API. I am writing a Google Apps Script intending to auto populate a Google Sheet with a Club Ranking that can be refreshed as needed.
Right now, all I am trying to do is make pull of data to ensure I am able to begin using the API, but I can't seem to do even that.
For reference, here are the only two resources I have to work with regarding this specific API:
PDGA REST API Authentication
PDGA REST API Services
I have got the original login to work using this code:
function apiLogin() {
var LoginUrl = 'https://api.pdga.com/services/json/user/login';
var LoginDetails = {
'username' : Username,
'password' : Password
};
var LoginRequest = {
'method' : 'post',
'Content-Type' : 'application/json',
'payload' : LoginDetails
};
var LoginResponse = UrlFetchApp.fetch(LoginUrl, LoginRequest);
var json = LoginResponse.getContentText();
var LoginData = JSON.parse(json);
Logger.log(LoginData);
var SessionID = LoginData['sessid'];
var SessionName = LoginData['session_name'];
var Tok = LoginData['token'];
var playerFetchPar = {
'method' : 'get',
'Cookie' : SessionID + '=' + SessionName
};
var PlayerResponse = UrlFetchApp.fetch('https://api.pdga.com/services/json/players?pdga_number=1',playerFetchPar); //ERROR
Logger.log(PlayerResponse);
};
It's the last part when I am trying to call on data from a player that I get the following error message:
Exception: Request failed for https://api.pdga.com returned code 403. Truncated server response: ["Access denied for user anonymous"] (use muteHttpExceptions option to examine full response)
I am guessing that my screw up is in my interpretion of the parameter Cookie from that second link. In the initial response to make sure I was logging in properly, I received a session_name and sessid but I can't seem to figure out what is expected from Cookie. I am sorry if the answer is obvious, but any help would be greatly appreciated!
The documentation says
Cookie: session_name=sessid
You've used
Cookie: sessid=session_name
Reverse it:
'Cookie' : `${SessionName}=${SessionID}`
And you need to send it as a header:
const playerFetchPar = {
method : 'get',
headers: {'Cookie' : `${SessionName}=${SessionID}`}
};

Keycloak error : Code not valid - for client token request

Few days Ago I have integrate keycloak with my php application.
Which working fine. Now I am trying to do same thing for my vue js app.
In 2nd step (for client token request using authorization code) I am getting 400 error.
Response Message "Code not valid".
1st step : (inside mounted )
const AUTHORIZE_URL = 'auth/realms/rstore/protocol/openid-connect/auth';
const params = {
'response_type': 'code',
'redirect_uri': 'http://localhost:8080/sso/callback',
'client_id': client_id,
'nonce': uuid(),
'state': uuid(),
'scope': 'openid profile email'
};
window.location = baseUrl + AUTHORIZE_URL + '?' + queryString.stringify(params);
2nd step : (For client token request)
let url = baseUrl + ACCESS_TOKEN_URL;
let params = {
'grant_type': 'authorization_code',
'code': code,
'redirect_uri': 'http://localhost:8080/sso/callback',
'client_id': client_id,
'client_secret': client_secret
};
let result = fetch(url, {
method: 'POST',
body: queryString.stringify(params),
headers: {
'Content-Type': 'application/x-www-form-urlencoded' // ,
}
})
.then(resp => {
return resp.json();
})
.catch(error => {
throw new Error('FetchError in request to ES: ' + error.toString())
})
I also tried from command prompt --->
curl -X POST 'https://example.com/auth/realms/nstore/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=authorization_code' \
--data-urlencode 'code=095516b7-e545-4b02-9dad-ec9c6366e0e4.33e1f298-a440-4bdc-9118-96ed669cabcd.e1c5d85f-3441-490d-a1fd-eb3b00d3c47c' \
--data-urlencode 'client_id=vue' \
--data-urlencode 'client_secret=b329ade3-2b71-4e3b-ab25-926cb32c5c8c' \
--data-urlencode 'redirect_uri=http://localhost:8080/sso/callback'
output same ---> {"error":"invalid_grant","error_description":"Code not valid"}
The "Code not valid" error message is a general one. It may have one of the following meanings:
http://localhost:8080/auth/realms/{realm_name}/protocol/openid-connect/auth
code is not valid, or is valid but incorrently URL encoded
the code is correct, but it has been already used by other user
session
Each authorization code can be used only once, to generate single new access token. As such, generating multiple access tokens from one code is not possible.
One reason why you may be receiving this error is because authorization code was already used, either by Postman or by web application.
Solution : regenerate the client_secret in the keycloak server for your realm and then do the complete process again and you will get the accesstoken and referesh token.
Note : Each authorization code can be used only once, to generate single new access token. As such, generating multiple access tokens from one code is not possible.

Unable to generate OAuth 2.0 Access Token from Office365 via JavaScript

I'm trying to pull an access token from Office365's /token identity platform endpoint via OAuth 2.0 client credentials grant flow. I have my app registered, the client ID & secret, etc...
I can make the POST request in Postman and receive the access token without issue:
However, when I try the POST request via JavaScript (by way of Google Apps Script), I receive an error message: AADSTS900144: The request body must contain the following parameter: 'grant_type'
I've already Google'd this error and found a bunch of different solutions, and have tried implementing them to no avail. I imagine this has to do with the URL encoding, but cannot figure it out.
Code:
function getO365() {
// POST Request (To get Access Token)
var tenantID = 'longstringhere'
var appID = 'longstringhere'
var appSecret = 'longstringhere'
var graphScore = 'https://graph.microsoft.com/.default'
var url = 'https://login.microsoftonline.com/' + tenantID + '/oauth2/v2.0/token'
var data = {
'client_id': appID,
'scope': graphScore,
'client_secret': appSecret,
'grant_type': 'client_credentials'
};
var postOptions = {
'method': 'POST',
'headers': {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded'
},
'body': data,
'redirect': 'follow'
};
var authToken = UrlFetchApp.fetch(url, postOptions);
}
The only real difference between my code and the JavaScript Fetch code I pulled off of Postman is:
var urlencoded = new URLSearchParams();
urlencoded.append("client_id", "longstringhere");
urlencoded.append("scope", "https://graph.microsoft.com/.default");
urlencoded.append("client_secret", "longstringhere");
urlencoded.append("grant_type", "client_credentials");
When I try to use URLSearchParams in Google Apps Script, I keep getting this error: ReferenceError: URLSearchParams is not defined
Any ideas? Thanks in advance!
This was resolved by changing 'body' to 'payload' for UrlFetchApp per the documentation. Edited code to reflect the change. Credit to #TheMaster for pointing out my mistake.
'payload': data,//from 'body': data,