I am trying to send POST request in order to recieve access and refresh tokens for OAuth2 authorization in Exact Online services.
I was able to retrieve authorization code, which is used to obtain these tokens. When I try to send POST request with the following parameters, I recieve an error "invalid_request" with description "Handle could not be extracted".
Screenshot of an error message
My code is pretty simple but I cant see the problem.
import requests
id_client = '***'
secret_key_client = '***'
redirect_uri = 'https://www.redirect.uri/'
response_type = 'code'
force_login = '0'
code = "***"
response = requests.post('https://start.exactonline.be/api/oauth2/token',
data={
'code': code,
'redirect_uri': redirect_uri,
'response_type': 'code',
'client_id': id_client,
'client_secret': secret_key_client
})
print(response.text)
I have also tried to change parameter name "response_type" to "grant_type" and its value to "autorization_code" and it didnt work for me.
Related
When I try to change the volume, I get:
requests.exceptions.HTTPError: 403 Client Error: Forbidden for url: https://api.spotify.com/v1/me/player/volume
I checked if my client_id and client_secret, everything seems fine. Also I have premium account.
import requests
from client_secrets import client_id, client_secret
AUTH_URL = 'https://accounts.spotify.com/api/token'
# POST
auth_response = requests.post(AUTH_URL, {
'grant_type': 'client_credentials',
"scope": "user-modify-playback-state",
'client_id': client_id,
'client_secret': client_secret,
})
# convert the response to JSON
auth_response_data = auth_response.json()
# save the access token
access_token = auth_response_data['access_token']
headers = {
'Authorization': 'Bearer {token}'.format(token=access_token)
}
data = {"volume_percent": 10}
response = requests.put("https://api.spotify.com/v1/me/player/volume",data=data, headers=headers)
response.raise_for_status()
Several authorization flows are detailed in their documentation but your request doesn't match any of them. If I understand correctly your app is just a server-side code without any frontend which means that the Client Credentials Flow is the one that best matches your need. In this flow you don't need to send the client ID and secret in the request body instead, you need to send them in the Authorization header in the following format: Basic <base64 encoded client_id:client_secret>.
Also, make sure to set the Content-Type header to application/x-www-form-urlencoded as stated in the documentation.
Otherwise, the rest seems fine.
I'm building a discord bot with discord.py and I'm trying to get the spotify user saved tracks.
This is my auth def:
#classmethod
def get_token(self):
CLIENT_ID = 'myclientid'
CLIENT_SECRET = "myclientsecret"
SPOTIFY_TOKEN_URL = "https://accounts.spotify.com/api/token"
client_token = base64.b64encode("{}:{}".format(CLIENT_ID, CLIENT_SECRET).encode('UTF-8')).decode('ascii')
headers = {"Authorization": "Basic {}".format(client_token)}
payload = {"grant_type": "client_credentials"}
token_request = requests.post(SPOTIFY_TOKEN_URL, data=payload, headers=headers)
access_token = json.loads(token_request.text)["access_token"]
return access_token
This is my def where I try to get the user saved tracks:
#commands.command(name='splayfav', aliases=['splayfavorites', 'splaysavedtracks'], description="Command to see the info from spotify \n __Example:__ \u200b \u200b *!infos*")
async def play_saved_tracks_from_spotify(self, ctx):
token = self.get_token(ctx)
headers = {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': f'Bearer {token}',
}
response = requests.get('https://api.spotify.com/v1/me/tracks', headers=headers)
print(response.text)
I get this error:
{
"error" : {
"status" : 401,
"message" : "Missing token"
}
}
But If I go in the Spotify API console and get manually a token and put it manually after bearer, then it works, obviously I'm trying to automate the process so I can't take it by hand every time. If I print the token it's actually a token(I mean it's not None or similar), but it's like if It is the wrong one.
How can I fix this problem?
This error message is stupid. What it should tell you is that your authorization token does not have the grant to access the user.
There's 2 different ways to authorize:
client credentials (as you do, can't access any user related stuff)
Authorization Code Flow, see: https://developer.spotify.com/documentation/general/guides/authorization/code-flow/
The second way requires a bit more setup in your app. Basically get redirected to spotify webpage, then the user selects allow for the required permissions, then you get back a code and with that you can get a token and the refresh token (this one is the interesting part).
Now this is quite a hustle to get through, but once you have the refresh token you can basically do almost the same call you do just to get a refreshed access token. (See "Request a refreshed Access Token" at the bottom of the page I linked above)
So with refresh token you can do:
POST https://accounts.spotify.com/api/token
HEADER:
Authorization: Basic $base64(clientId:clientSecret)
BODY Parameters (form url encoded)
grant_type: refresh_token
refresh_token: <your value here>
Use this improved access token and it will work.
I'm trying to make an app that makes requests to Dynamics CRM Web API from python using urllib2.
So far I can login an user with an Azure application by making a post request to https://login.microsoftonline.com/common/oauth2/authorize
then with the retrieved authorization_code I can get the access_token, refresh_token and others with urllib2
url = 'https://login.microsoftonline.com/common/oauth2/token'
post_fields = {'grant_type': 'authorization_code',
'client_id': CLIENT_ID,
'client_secret': CLIENT_SECRET,
'redirect_uri': REDIRECT_URI,
'resource': 'https://graph.microsoft.com',
'code': code}
request = Request(url, urlencode(post_fields).encode())
resp = urlopen(request).read().decode()
resp = json.loads(resp)
refresh_token = resp['refresh_token']
id_token = resp['id_token']
id_token = jwt.decode(id_token,verify=False)
access_token = resp['access_token']
Then I tried to make another post request by using the access_token but had no luck.
I keep getting:
HTTP Error 401: Unauthorized
Just as a test I make a post directly to .dynamics.com/api/data/v8.1/leads
as follows:
url = 'https://<company_uri>.dynamics.com/api/data/v8.1/leads'
post_fields = {"name": "Sample Account",
"creditonhold": "false",
"address1_latitude": 47.639583,
"description": "This is the description of the sample account",
"revenue": 5000000,
"accountcategorycode": 1
}
request = Request(url, urlencode(post_fields).encode())
request.add_header('Authorization', 'Bearer ' + access_token )
request.add_header("Content-Type", "application/json; charset=utf-8")
request.add_header('OData-MaxVersion','4.0')
request.add_header('OData-Version','4.0')
request.add_header('Accept','application/json')
resp = urlopen(request).read().decode()
But i keep getting the same 401 error code.
I've looked all over msdn documentation but didn't find the way to do this directly without using any library, I just want to use a simple post request.
Since the error code says Unauthorized I think the access_token must be sent in some other way.
Can someone help me on how to correctly use the access_token on Dynamics CRM?
Thanks!
The access token you got back is for the Azure AD Graph API. Not Dynamics CRM.
To call that, you must ask for an access token with resource set to Dynamics CRM API's App ID URI, not https://graph.windows.net.
According to documentation you should set resource to https://<company_uri>.crm.dynamics.com.
So when you are retrieving token:
url = 'https://login.microsoftonline.com/common/oauth2/token'
post_fields = {'grant_type': 'authorization_code',
'client_id': CLIENT_ID,
'client_secret': CLIENT_SECRET,
'redirect_uri': REDIRECT_URI,
'resource': 'https://<company_uri>.crm.dynamics.com',
'code': code}
I am trying to request an authorization code as documented here.
I am using Python requests package to do this and have the following example code:
import requests
auth_endpoint = 'https://login.microsoftonline.com/%s/oauth2/authorize?api-version=1.0' % TENANT_ID
payload = {
'client_id': CLIENT_ID,
'response_type': 'code',
'resource': APP_ID_URI,
'redirect_uri': REPLY_URL
}
response = requests.get(url=auth_endpoint, data=payload)
However, when I run the code above, I get back HTML in the body and not the response I'm expecting. It seems like the HTML code is for a login page.
When I take the formatted endpoint URI and plug it into a browser, I am able to get the auth code from the redirect URI. But, is there a way to get this from the body of the response while still using the requests package?
Please use session class of requests module to implement your requirement. Please refer to the following code sample:
import requests
s = requests.Session()
USERNAME = '<username_email>'
PASSWORD = '<userpassword>'
s.auth = (USERNAME, PASSWORD)
TENANT_ID = '<tenant_id>'
# Authorize URL
authorize_url = 'https://login.microsoftonline.com/%s/oauth2/authorize' % TENANT_ID
# Token endpoint.
token_url = 'https://login.microsoftonline.com/%s/oauth2/token' % TENANT_ID
payload = { 'response_type': 'code',
'client_id': '<tenant_id>',
'redirect_uri': 'http://localhost',
'authority' :'authority'
}
response = s.get(authorize_url, params=payload ,allow_redirects=True)
print response
print response.url
Any further concern, please feel free to let me know.
I'm trying this code:
import requests
url_token = 'https://accounts.google.com/o/oauth2/token'
params = {
'code': request.values.get('code', '', type=str),
'client_id': app.config['SOCIAL_GOOGLE']['consumer_key'],
'client_secret': app.config['SOCIAL_GOOGLE']['consumer_secret'],
'redirect_uri': urllib.quote_plus("https://example.com/google/code"),
'grant_type': 'authorization_code'
}
out = requests.post(url_token, params=params)
using Python-Request in Flask. But I get error response:
ERROR - out={
"error" : "invalid_request",
"error_description" : "Required parameter is missing: grant_type"
}
It is standard POST request. Any hint why Google doesn't see grant_type parameter? Or is it misleading error message?
params is for adding query parameters to the URL in GET requests, data is for passing data to POST requests so you should pass the form POST parameters as:
out = requests.post(url_token, data=params)
see the docs at: http://docs.python-requests.org/en/latest/user/quickstart/#more-complicated-post-requests