Python - OAUTH2 How to get access token using PCKE? - python

I am trying to get this access token with Python. With Postman I can get an access token. After configurations in the screenshots, I click the Get Access Token button, and A pop-up throws for username and password. Then I fill them. After that, I can get an access token from Postman.
To get an access token with Python, I wrote the code below. In the first get request, I get the cookies and Redirect URL(to post user credentials). Then, I post user credentials and cookies to Redirected URL. After that, the response header["location"] must include a code parameter to get the token. But, the header parameter does not have a code parameter. It has an Authorization URL with query parameters. How can get this code parameter? Finally, I will post a request(to token URL) with this code to get an access token on the response body.
import base64
import hashlib
import json
import os
import re
import urllib.parse
import requests
from bs4 import BeautifulSoup
from rich import print
username = 'username '
password = 'password '
client_id = 'xxxxxxxxxxxxxxxxxxxxxxxxxx'
client_secret = 'yyyyyyyyyyyyyyyyyyyyyyyyyy'
prod_url = 'https://url:port'
callback_url = prod_url + '/main/ifsapplications/projection/oauth2/callback'
authorization_url = prod_url + '/openid-connect-provider/idp/authorization'
token_url = prod_url + '/openid-connect-provider/idp/token'
code_challenge_method = "S256" #SHA-256
scope = 'openid'
response_type ='code'
#Add auth data to request headers
#Grant type = authorization code with pkce
#send client credentials in body
code_verifier = base64.urlsafe_b64encode(os.urandom(40)).decode('utf-8')
code_verifier = re.sub('[^a-zA-Z0-9]+', '', code_verifier)
code_challenge = hashlib.sha256(code_verifier.encode('utf-8')).digest()
code_challenge = base64.urlsafe_b64encode(code_challenge).decode('utf-8')
code_challenge = code_challenge.replace('=', '')
resp = requests. Get(
url=authorization_url,
params={
"response_type": response_type,
"client_id": client_id,
"scope": scope,
"redirect_uri": callback_url,
"code_challenge": code_challenge,
"code_challenge_method": code_challenge_method,
},
allow_redirects=False
)
cookie = resp.headers['Set-Cookie']
cookie = '; '.join(c.split(';')[0] for c in cookie. Split(', '))
soup = BeautifulSoup(resp.text, 'html.parser')
form_action = soup. Find('a').text
resp = requests. Post(
url=form_action,
data={
"username": username,
"password": password
},
headers={"Cookie": cookie,
"Referer": form_action},
allow_redirects=False
)
redirect = resp.headers['Location']
print(resp.text)
print(resp.headers)
OUTPUT:

Related

Request API with Bearer token

I am trying to use the Malwarebytes API to get data. However, I am not getting the results for request. I get the "Unauthorized" message. My understanding of the documentation is to get the "access token" using my client ID and client secret. I was able to get the access token. However, I am not sure how to run the access token I received to the headers so I can get data. help is appreciated.
from requests_oauthlib import OAuth2Session
from oauthlib.oauth2 import BackendApplicationClient
import requests
import json
CLIENT_ID = "Client id "
CLIENT_SECRET = "client secret"
grant_type = 'client_credentials'
body_params = {'grant_type' : grant_type}
url='https://api.malwarebytes.com/oneview/oauth2/token'
response = requests.post(url, data=body_params, auth = (CLIENT_ID, CLIENT_SECRET))
#Gets only access token
response_token = response.json()
response_token2 = json.dumps(response_token, indent=2)
token_response = response_token.get("access_token",[0])
##BEARER AUTHORIZATION
headers = {
'Authorization':'Bearer token_response',
'Content-Type':'application/x-www-form-urlencoded'
}
companies = requests.get('https://api.malwarebytes.com/oneview/v1/sites', headers=headers)
print(companies.text)
print(companies.status_code)
Issue with getting data after getting access token

Python Request Token from REST API

Im struggling with this Dokumentation here:
Send your credential base64 encoded to the authentication server.
Get a response including an UUID for authentication.
Use the UUID to authenticate REST requests.
It shows this request as an example:
**Header**
“`json
{
‘Content-Type’: ‘application/x-www-form-urlencoded’,
‘authorization’: ‘Basic <base64 encoded username:password>’
}
“`
**Body**
“`json
{
‘grant_type’: ‘client_credentials’
}
“`
How do I turn with into a requests.post() ?
you have to build dictionaries and post them with requests :
import requests
import base64
import json
username = "user"
password = "password"
url = 'https://myurl.com'
headers = {}
headers['Content-Type'] = 'application/x-www-form-urlencoded'
headers['authorization'] = 'Basic ' + base64.b64encode(bytes(username + ':' + password, 'utf-8')).decode('utf-8')
body = {}
body['grant_type'] = 'client_credentials'
r = requests.post(url, data=json.dumps(body), headers=json.dumps(headers))

Azure Access Token Request returning HTML

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.

"Error parsing JSON" when using Spotify API

I am learning Python and I am trying to create a playlist using the Spotify web api but get a http 400 error: Error parsing json. I guess it has to do with an incorrect variable type in the token but I am having a really hard time debugging it as I can't figure out a way to see the post request in raw format.
Posting through the API requires authorizing and this is the script I've created for that:
import requests
import base64
requests.packages.urllib3.disable_warnings()
client_id = 'ID'
client_secret = 'SECRET'
redirect_uri = 'http://spotify.com/'
scope = 'playlist-modify-private playlist-read-private'
def request_token():
# 1. Your application requests authorization
auth_url = 'https://accounts.spotify.com/authorize'
payload = {'client_id': client_id, 'response_type':'code','redirect_uri':redirect_uri}
auth = requests.get(auth_url,params = payload)
print '\nPlease go to this url to authorize ', auth.url
# 2. The user is asked to authorize access within the scopes
# 3. The user is redirected back to your specified URI
resp_url = raw_input('\nThen please copy-paste the url you where redirected to: ')
resp_code= resp_url.split("?code=")[1].split("&")[0]
# 4. Your application requests refresh and access tokens
token_url = 'https://accounts.spotify.com/api/token'
payload = {'redirect_uri': redirect_uri,'code': resp_code, 'grant_type': 'authorization_code','scope':scope}
auth_header = base64.b64encode(client_id + ':' + client_secret)
headers = {'Authorization': 'Basic %s' % auth_header}
req = requests.post(token_url, data=payload, headers=headers, verify=True)
response = req.json()
return response
This is the function actually trying to create the playlist using the authorization token (import authorizer is the function above):
import requests
import authorizer
def create_playlist(username, list_name):
token = authorizer.request_token()
access_token = token['access_token']
auth_header = {'Authorization': 'Bearer {token}'.format(token=access_token), 'Content-Type': 'application/json'}
api_url = 'https://api.spotify.com/v1/users/%s/playlists' % username
payload = {'name': list_name, 'public': 'false'}
r = requests.post(api_url, params=payload, headers=auth_header)
But whatever I try it only leads to a 400 error. Can anyone please point out my error here?
Solved by adding a json.dumps for the input: json.dumps(payload) and changing the payload to be 'data' and not 'params' in the request.
So the new functioning request equals:
r = requests.post(api_url, data=json.dumps(payload), headers=auth_header)

Getting an oauth request token from etrade in Python

I'm trying to get an oauth request token from the etrade api (sandbox) in Python with this thing:
import requests
from oauthlib.oauth1 import Client
consumer_key = 'foo' # actual key used
consumer_secret = 'bar' # actual secret used
request_url = 'https://etwssandbox.etrade.com/oauth/sandbox/request_token'
client = Client(consumer_key, client_secret = consumer_secret)
uri, headers, body = client.sign(request_url)
add_params = ', realm="", oauth_token= "", oauth_callback="oob"'
headers['Authorization'] += add_params
r = requests.get(url = uri, headers = headers)
print(r.text) # abbreviated resp: " . . . .auth_problem=consumer_key_rejected,oauth_problem_advice=The oauth_consumer_key foo can be used only in SANDBOX environment . . .
The header generated is:
{'Authorization': 'OAuth oauth_nonce="99985873301258063061424248905", oauth_timestamp="1424248905", oauth_version="1.0", oauth_signature_method="HMAC-SHA1", oauth_consumer_key="foo", oauth_signature="A7ZY91UyZz6NfSGmMA5YWGnVM%2FQ%3D", realm="", oauth_token= "", oauth_callback="oob"'}
I have also tried the url: 'https://etwssandbox.etrade.com/oauth/sandbox/rest/request_token'
And I have tried the header without the add_params (it seems to need the blank oauth_token?)
Note: Confusingly, the response periodically comes back: "Http/1.1 400 Bad Request" with exactly the same url/header.
Any idea what I'm doing wrong?
A helpful person at etrade clarified for the doc-challenged that all oauth api requests (whether you are working in the sandbox or not) need to be sent to the main api url: 'https://etws.etrade.com/oauth/{api}'.
It is only after authenticating a session that the sandbox urls should be used: 'https://etwssandbox.etrade.com/{non-oauth-module}/sandbox/rest/{api}'.
In case others are having problems authenticating a session with etrade in python3, this works in the sandbox at least:
from rauth import OAuth1Service
import webbrowser
def getSession():
# Create a session
# Use actual consumer secret and key in place of 'foo' and 'bar'
service = OAuth1Service(
name = 'etrade',
consumer_key = 'foo',
consumer_secret = 'bar',
request_token_url = 'https://etws.etrade.com/oauth/request_token',
access_token_url = 'https://etws.etrade.com/oauth/access_token',
authorize_url = 'https://us.etrade.com/e/t/etws/authorize?key={}&token={}',
base_url = 'https://etws.etrade.com')
# Get request token and secret
oauth_token, oauth_token_secret = service.get_request_token(params =
{'oauth_callback': 'oob',
'format': 'json'})
auth_url = service.authorize_url.format(consumer_key, oauth_token)
# Get verifier (direct input in console, still working on callback)
webbrowser.open(auth_url)
verifier = input('Please input the verifier: ')
return service.get_auth_session(oauth_token, oauth_token_secret, params = {'oauth_verifier': verifier})
# Create a session
session = getSession()
# After authenticating a session, use sandbox urls
url = 'https://etwssandbox.etrade.com/accounts/sandbox/rest/accountlist.json'
resp = session.get(url, params = {'format': 'json'})
print(resp)
Thanks #ethann - this actually still works as of 6/17/2020 with changed urls.
from rauth import OAuth1Service
import webbrowser
service = OAuth1Service(
name = 'etrade',
consumer_key = 'foo',
consumer_secret = 'bar',
request_token_url = 'https://apisb.etrade.com/oauth/request_token',
access_token_url = 'https://apisb.etrade.com/oauth/access_token',
authorize_url = 'https://us.etrade.com/e/t/etws/authorize?key={}&token={}',
base_url = 'https://apisb.etrade.com')
oauth_token, oauth_token_secret = service.get_request_token(params =
{'oauth_callback': 'oob',
'format': 'json'})
auth_url = service.authorize_url.format('foo again', oauth_token)
webbrowser.open(auth_url)
verifier = input('Please input the verifier: ')
session = service.get_auth_session(oauth_token, oauth_token_secret, params = {'oauth_verifier': verifier})
url = 'https://apisb.etrade.com/v1/accounts/list'
resp = session.get(url, params = {'format': 'json'})
print(resp.text)

Categories

Resources