microsoft graph cant get refresh token using refresh token - python

The first time I was able to get both access token and refresh token,
Then when I use the refresh token to refresh it only gave me back access token and doesn't give me back the refresh token too, I want to get both the refresh token and access token,
request_url = "https://login.microsoftonline.com/common/oauth2/v2.0/token"
headers = {"Content-Type": "application/x-www-form-urlencoded"}
scope_list = ["https://graph.microsoft.com/Calendars.ReadWrite"]
scope = "%20".join(scope_list)
# redirect_uri = f"{settings.FRONTEND_BASE_URL}/microsoft/login"
redirect_uri = (
f"https://someuri.com/login"
)
refresh_token = user.profile.calendar_settings.outlook_refresh_token
payload = {
"client_id": "",
"scope": scope,
"redirect_uri": redirect_uri,
"client_secret": "",
"grant_type": "refresh_token",
"refresh_token": refresh_token,
}
response = requests.post(url=request_url, headers=headers, data=payload)

I got it working by changing the scope to this
scope = "https://graph.microsoft.com/Calendars.ReadWrite offline_access"

Please ensure your call includes following parameters in payload
grant_type:refresh_token
client_id:"your_client_id_comes_here"
client_secret:"your_client_secret_comes_here"
response_type:token
refresh_token:"old_refres_token_comes_here"
For more details please refer below screenshot
Postman request to get new access token with refresh token

Related

When I try to change volume with Spotify API, I get error code 403

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.

Spotify API get user saved tracks error 401 missing token

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.

Python Discord OAuth2 - Guild.Join (Joining a Guild)

Hi I'm trying to do a 'Authorize with Discord' that automatically joins the user to my guild.
I'm running a Flask application that handles all of these.
So far, here's my code:
def add_to_guild(access_token, userID, guildID):
url = f"{Oauth.discord_api_url}/guilds/{guildID}/members/{userID}"
headers = {
"Authorization" : f"Bearer {access_token}"
}
response = requests.post(url=url, headers=headers)
print(response.text)
However this doesn't work. I get a error message saying:
{"message": "405: Method Not Allowed", "code": 0}
On the OAuth2 docs, it says that i'm suppose to get a response of 201 if the user successfully joins, or 204 if user is already in the guild.
UPDATE 1:
I changed the method to requests.get and now I receive this error:
{"message": "401: Unauthorized", "code": 0}
UPDATE 2:
I created a Bot, invited it to my discord guild and successfully was able to get some information about my user in the guild. however once i left and try to run the link again, i got this error
{"message": "Unknown Member", "code": 10007}
UPDATE 3:
I changed the method to PUT and now I'm getting a Bad Request
def add_to_guild(access_token, userID):
url = f"{Oauth.discord_api_url}/guilds/{guildid i cant show}/members/{userID}"
botToken = "cant show also"
headers = {
"Authorization" : f"Bot {botToken}",
'Content-Type': 'application/json'
}
response = requests.put(url=url, headers=headers)
print(response.text)
To add a member, you should use requests.put(), and the Guilds Auth header needs to be a Bot token, so change to:
headers = {
"Authorization" : f"Bot {access_token}"
}
And make sure you are passing a Bot token. More at: https://discord.com/developers/docs/reference
The Authorization header must be a Bot token (belonging to the same
application used for authorization), and the bot must be a member of
the guild with CREATE_INSTANT_INVITE permission.
To get the member, you would use requests.get() without the bot header.
Update 3 put() is the way to go
However, you're still missing the JSON payload which must include the user access token received from the token exchange from a code grant.
data = {
"access_token" : access_token
}
Then fire your request with passing data to json, so
response = requests.put(url=url, json=data, headers=headers)
print(response.json)

Python requests to access OAUTH website content - SNL Finance

I've been banging my head up against the wall trying to retrieve content from the news source "SNL Finance". I have valid credentials, so in theory I should be able to programmatically access their news content.
In short, I've tried executing the below script but with no success:
s = requests.Session()
client_id = "..."
client_secret = "..."
token_url = "https://www.snl.com/SNL.Services.Security.Service/oauth/token"
protected_url = "https://www.snl.com/web/client?auth=inherit#news/article?id=40666532&KeyProductLinkType=14"
request_data = {
"client_id": client_id,
"client_secret": client_secret,
"scope": "https://www.snl.com",
"grant_type": "refresh_token",
"refresh_token": refresh_token
}
token_response = s.post(token_url, data=request_data)
### token response is in jwt format, including token_type, expires_in, scope, etc. ###
token = json.loads(token_response.text)["access_token"].split('>')[1].split('<')[0]
request_data["token"] = token
article = s.post(protected_url, headers=request_data)
Sadly, this fails. I end up with a 200 response, but it appears to just be the login page (honestly not entirely sure what I'm looking at).
For more background, I've included browser information as it populates throughout the authentication process:
Attempt to visit protected url, redirected to the below url (omitted snl base):
/web/client?auth=inherit&contextType=external&username=string&enablePersistentLogin=true&OverrideRetryLimit=0&SwitchGetToPostLimit=50000&contextValue=%2Foam&password=secure_string&challenge_url=https%3A%2F%2Fwww.snl.com%2Fweb%2Fclient%3Fauth%3Dinherit&request_id=-6149669210818920852&authn_try_count=0&locale=en_US&resource_url=https%253A%252F%252Fwww.snl.com%252FInteractiveX%252FDefault.aspx%253Ftarget%253Dnews%25252Farticle%25253Fid%25253D40666532%252526KeyProductLinkType%25253D14%2526SNL3%253D1
Request headers are shown here.
Upon entering login / password, a token is retrieved and the protected page loads.
Request cookies are as shown here.
Also, I'm a bit confused at to why the token value of SNL_OAUTH_TOKEN in the above link (second link) differs from what is shown in the jwt token response I receive from my script.
Any guidance here will be hugely appreciated. I'm also happy to send any other non-personal information that proves useful.
Thank you!
I ended up figuring this out. I underestimated Python's requests library.
It appears to be as easy as this:
# prep token request data
request_data = {
"client_id": client_id,
"client_secret": client_secret,
"scope": "https://www.snl.com",
"grant_type": "refresh_token",
"refresh_token": new_refresh_token
}
# post to token url with token credentials
# the request object stores the token response cookies
r1 = requests.post(token_url, data=request_data)
# post to protected url by setting cookies arg as cookies from previous response
r2 = requests.post(protected_url, cookies=r1.cookies)

Making a request to Dynamics CRM Web API

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}

Categories

Resources