Trying to understand how it works oauth
How to get authorized user details using Blizzard api?
import json
import requests
client_id = ""
client_secret = ""
region = "eu"
data = {
'grant_type': 'client_credentials'
}
access_token_response = requests.post(f"https://{region}.battle.net/oauth/token", data=data, allow_redirects=False, auth=(client_id, client_secret))
access_token = json.loads(access_token_response.text)["access_token"]
api_call_headers = {
'Authorization': 'Bearer ' + access_token
}
api_call_response = requests.get(f"https://{region}.battle.net/oauth/userinfo", headers=api_call_headers)
I want to trigger the cloud functions with a self-signed JWT for a Google-signed ID token. However, it produces the response Your client does not have permission to the requested URL. I am sure that that account has "Cloud Functions Invoker" access and I also get the token successfully.
import time
import jwt
import json
# import http.client
# payload
private_key = "\n-----END PRIVATE KEY-----\n"
token_dict = {
"iss": "het-query-function#smarter-poc.iam.gserviceaccount.com",
"scope": "https://www.googleapis.com/auth/cloud-platform",
"aud": "https://www.googleapis.com/oauth2/v4/token",
# "aud": "https://europe-central2-smarter-poc.cloudfunctions.net/query_soc_ota_information",
"exp": time.time()+3600,
'iat': time.time(), # 时间戳
"sub":"het-query-function#smarter-poc.iam.gserviceaccount.com"
}
"""payload 中一些固定参数名称的意义, 同时可以在payload中自定义参数"""
# iss 【issuer】发布者的url地址
# sub 【subject】该JWT所面向的用户,用于处理特定应用,不是常用的字段
# aud 【audience】接受者的url地址
# exp 【expiration】 该jwt销毁的时间;unix时间戳
# nbf 【not before】 该jwt的使用时间不能早于该时间;unix时间戳
# iat 【issued at】 该jwt的发布时间;unix 时间戳
# jti 【JWT ID】 该jwt的唯一ID编号
# headers
headers = {
'alg': "RS256", # 声明所使用的算法
'typ': 'JWT'
}
# 调用jwt库,生成json web token
jwt_token = jwt.encode(token_dict, # payload, 有效载体
private_key, # 进行加密签名的密钥
algorithm="RS256", # 指明签名算法方式, 默认也是HS256
headers=headers # json web token 数据结构包含两部分, payload(有效载体), headers(标头)
).decode('ascii') # python3 编码后得到 bytes, 再进行解码(指明解码的格式), 得到一个str
print(jwt_token)
import http.client
conn = http.client.HTTPSConnection("www.googleapis.com")
# payload = 'grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjllN2Q5ZTk1YjZkNTdiY2NiZjBhYmM2NzgzYzc2N2RhYjE2MzFjOWIiLCJ0eXAiOiJKV1QifQ.eyJpYXQiOjE2NDMwMDUwMzAsImV4cCI6MTY0MzAwNTYzMCwic3ViIjoiZ2NwLXN0b3JhZ2VAc21hcnRlci1wb2MuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJpc3MiOiJnY3Atc3RvcmFnZUBzbWFydGVyLXBvYy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsImF1ZCI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL29hdXRoMi92NC90b2tlbiIsInNjb3BlIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vYXV0aC9jbG91ZC1wbGF0Zm9ybSJ9.eAgCd5JbliFLoggcE9z7Ybhrd0GO3vb3zBW9N48iDe9tGBkQKaFdgAeANutoYLmLuvQM4m4NSavIKFHWYJHiZ6-ioehUvrs0qHZFe2bBkbNYAMQTW73ERr1XjufnZkgK6u1TUTpcX9u2EiJyMHIuku4PBYlhv8aniIsYojVfA_wVcmKhN0dVeBQzixZ_mhJsIZRPKYDPkJKn4H4oOXgy_ymbvKmguZyYLuPGezgycZpKwhFOvQQTbVSuoKikow9v4JIISXlt0fuspFLlsaEVWRx4468GUJ1SNyYThkXARRFxQAWMsgAJ2Z25I38Z3i-owWDnFKJl8KrtjSGG52sa8w'
payload = 'grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion='+jwt_token
headers = {
'Authorization': 'Bearer '+jwt_token,
'Content-Type': 'application/x-www-form-urlencoded'
}
conn.request("POST", "/oauth2/v4/token", payload, headers)
res = conn.getresponse()
data = res.read()
jwt = data.decode("utf-8")
print(jwt)
jwt_list = json.loads(jwt)
print(jwt_list['access_token'])
for v in range(len(jwt_list['access_token'])-1,-1,-1):
# print(jwt_list['access_token'][v])
if jwt_list['access_token'][v]!='.':
break
print(jwt_list['access_token'][v])
print("!!!!!!!")
jwt_str = jwt_list['access_token'][0:v+1]
print(jwt_str)
conn = http.client.HTTPSConnection("europe-central2-smarter-poc.cloudfunctions.net")
headers = {
'Authorization': 'bearer '+jwt_str
}
payload = ""
conn.request("GET", "/query_soc_ota_information/?hello=hello", payload, headers)
res = conn.getresponse()
data = res.read()
re = data.decode("utf-8")
print(re)
OK, your code works for me but with several changes.
It would be helpful to include which JWT you're library; I assume PyJWT
You need to include target_audience
ALG="RS256"
PROJECT=os.getenv("PROJECT")
REGION=os.getenv("REGION")
ACCOUNT=os.getenv("ACCOUNT")
FUNCTION=os.getenv("FUNCTION")
EMAIL="{account}#{project}.iam.gserviceaccount.com".format(
account=ACCOUNT,
project=PROJECT,
)
ROOT="{region}-{project}.cloudfunctions.net".format(
region=REGION,
project=PROJECT,
)
ENDPOINT="https://{root}/{function}".format(
root=ROOT,
function=FUNCTION,
)
token_dict = {
"target_audience": ENDPOINT,
"iss": EMAIL,
"sub": EMAIL,
"exp": time.time()+3600,
"iat": time.time(),
"aud": "https://www.googleapis.com/oauth2/v4/token",
}
NOTE I think exp and iat should be integers but your code works as-is.
The .decode("ascii") appended to jwt.encode().decode("ascii") is incorrect.
The payload should not be URL-encoded:
payload = "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion={jwt}".format(
jwt=jwt_token,
)
The /oauth2/v4/token endpoint does not return an access_token per #john-hanley comment. It returns an id_token (as described by Google in the doc you reference).
jwt = data.decode("utf-8")
jwt_list = json.loads(jwt)
id_token=jwt_list["id_token"]
conn = http.client.HTTPSConnection(ROOT)
headers = {
"Authorization": "Bearer {token}".format(token=id_token),
}
conn.request("GET", "/{function}".format(function=FUNCTION), headers=headers)
NOTE No payload (null) not ""
main.py:
import http.client
import json
import jwt
import os
import time
ALG="RS256"
# Use GOOGLE_APPLICATION_CREDENTIALS for consistency
CREDENTIALS=os.getenv("GOOGLE_APPLICATION_CREDENTIALS")
f=open(CREDENTIALS)
key=json.load(f)
PRIVATE_KEY=key["private_key"]
PROJECT=os.getenv("PROJECT")
REGION=os.getenv("REGION")
ACCOUNT=os.getenv("ACCOUNT")
FUNCTION=os.getenv("FUNCTION")
EMAIL="{account}#{project}.iam.gserviceaccount.com".format(
account=ACCOUNT,
project=PROJECT,
)
ROOT="{region}-{project}.cloudfunctions.net".format(
region=REGION,
project=PROJECT,
)
ENDPOINT="https://{root}/{function}".format(
root=ROOT,
function=FUNCTION,
)
token_dict = {
"target_audience": ENDPOINT,
"iss": EMAIL,
"sub": EMAIL,
"exp": time.time()+3600,
"iat": time.time(),
"aud": "https://www.googleapis.com/oauth2/v4/token",
}
headers = {
'alg': ALG,
'typ': 'JWT'
}
jwt_token = jwt.encode(
token_dict,
PRIVATE_KEY,
algorithm=ALG,
headers=headers,
)
payload = "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion={jwt}".format(
jwt=jwt_token,
)
headers = {
"Authorization": "Bearer {token}".format(
token=jwt_token,
),
"Content-Type": 'application/x-www-form-urlencoded'
}
conn = http.client.HTTPSConnection("www.googleapis.com")
conn.request("POST", "/oauth2/v4/token", payload, headers)
res = conn.getresponse()
data = res.read()
jwt = data.decode("utf-8")
jwt_list = json.loads(jwt)
id_token=jwt_list["id_token"]
conn = http.client.HTTPSConnection(ROOT)
headers = {
"Authorization": "Bearer {token}".format(token=id_token),
}
conn.request("GET", "/{function}".format(function=FUNCTION), headers=headers)
res = conn.getresponse()
data = res.read()
re = data.decode("utf-8")
print(re)
Traceback error while connecting with salesforce API: [{'message': 'INVALID_HEADER_TYPE', 'errorCode': 'INVALID_AUTH_HEADER'}]
What is the problem?
My python codes are as follows:
client_id = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
client_secret = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
redirect_url = 'http://localhost/'
cm_user = 'XXXXXXXXXXXXXXXXXXXXXX'
cm_pass = 'XXXXXXXXXXXXXXXXXXXXXX'
auth_url = 'https://login.salesforce.com/services/oauth2/token'
response = requests.post(auth_url, data = {
'client_id': client_id,
'client_secret': client_secret,
'grant_type':'password',
'username': cm_user,
'password': cm_pass
})
json_res = response.json()
access_token = json_res['access_token']
auth = {'Authorization': 'Bearer' + access_token}
instance_url = json_res['instance_url']
url = instance_url + '/services/data/v45.0/sobjects/contact/describe'
res = requests.get(url, headers=auth)
r = res.json()
print(r)
You are missing a space after the word Bearer, which renders your authorization header invalid.
I'm trying to automate a process in which i have to download some brazilian fund quotes from Anbima (Brazil regulator). I have been able to work around the first steps to retrieve the access token but i don't know how to use the token in order to make requests. Here is the tutorial website https://developers.anbima.com.br/en/como-acessar-nossas-apis/.
I have tried a lot of thing but all i get from the request is 'Could not find a required APP in the request, identified by HEADER client_id.'
If someone could share some light. Thank you in advance.
import requests
import base64
import json
requests.get("https://api.anbima.com.br/feed/fundos/v1/fundos")
ClientID = '2Xy1ey11****'
ClientSecret = 'faStF1Hc****'
codeString = ClientID + ":" + ClientSecret
codeStringBytes = codeString.encode('ascii')
base64CodeBytes = base64.b64encode(codeStringBytes)
base64CodeString = base64CodeBytes.decode('ascii')
url = "https://api.anbima.com.br/oauth/access-token"
headers = {
'content-type': 'application/json'
,'authorization': f'Basic {base64CodeString}'
}
body = {
"grant_type": "client_credentials"
}
r = requests.post(url=url, data=json.dumps(body), headers=headers, allow_redirects=True)
jsonDict = r.json()
##################
urlFundos = "https://api-sandbox.anbima.com.br/feed/precos-indices/v1/titulos-publicos/mercado-secundario-TPF"
token = jsonDict['access_token']
headers2 = {
'content-type': 'application/json'
,'authorization': f'Bearer {token}'
}
r2 = requests.get(url=urlFundos, headers=headers2)
r2.status_code
r2.text
I was having the same problem, but today I could advance. I believe you need to adjust some parameters in the header.
Follows the piece of code I developed.
from bs4 import BeautifulSoup
import requests
PRODUCTION_URL = 'https://api.anbima.com.br'
SANDBOX_URL = 'https://api-sandbox.anbima.com.br'
API_URL = '/feed/fundos/v1/fundos/'
CODIGO_FUNDO = '594733'
PRODUCTION = False
if PRODUCTION:
URL = PRODUCTION_URL
else:
URL = SANDBOX_URL
URL = URL + API_URL + CODIGO_FUNDO
HEADER = {'access_token': 'your token',
'client_id' : 'your client ID'}
html = requests.get(URL, headers=HEADER).content
soup = BeautifulSoup(html, 'html.parser')
print(soup.prettify())
The sandbox API will return a dummy JSON. To access the production API you will need to request access (I'm trying to do this just now).
url = 'https://api.anbima.com.br/oauth/access-token'
http = 'https://api-sandbox.anbima.com.br/feed/precos-indices/v1/titulos-publicos/pu-intradiario'
client_id = "oLRa*******"
client_secret = "6U2nefG*****"
client_credentials = "oLRa*******:6U2nefG*****"
client_credentials = client_credentials.encode('ascii')
senhabytes = base64.b64encode(client_credentials)
senha = base64.b64decode(senhabytes)
print(senhabytes, senha)
body = {
"grant_type": "client_credentials"
}
headers = {
'content-type': 'application/json',
'Authorization': 'Basic b0xSYTJFSUlOMWR*********************'
}
request = requests.post(url, headers=headers, json=body, allow_redirects=True)
informacoes = request.json()
token = informacoes['access_token']
headers2 = {
"content-type": "application/json",
"client_id": f"{client_id}",
"access_token": f"{token}"
}
titulos = requests.get(http, headers=headers2)
titulos = fundos.json()
I used your code as a model, then I've made some changes. I've printed the encode client_id:client_secret and then I've copied and pasted in the headers.
I've changed the data for json.
I am trying to convert successful python (flask) OAuth 2.0 authentication / api request into Postman.
My current process is:
From the front end, I hit an /auth endpoint in python using fetch:
fetch("/auth")
.then(function (response) {
return response.json();
})
.then(function (json) {
const code = json.code;
window.location = `[hostname.com]/auth/authorize?request_token=${code}&redirect_uri=http://[hostname]/menu`;
});
The backend flask auth endpoint looks like this:
url = 'https://[hostname].com/v3/oauth/request'
headers = CaseInsensitiveDict()
headers['Host'] = '[hostname].com'
headers['Content-Type'] = 'application/json'
headers['X-Accept'] = 'application/json'
data = json.dumps({'consumer_key': 'XXXX', 'redirect_uri':'[hostname]/success'})
resp = requests.post(url, headers=headers, data=data)
json_resp = json.loads(resp.content)
auth_code = json_resp['code']
auth_resp = {'code': auth_code}
return jsonify(auth_resp)
The access endpoint takes that auth code to get the token
cur_auth = session.get('auth_code',None)
url = 'https://[hostname.com]/v3/oauth/authorize'
headers = CaseInsensitiveDict()
headers['Host'] = '[hostname].com'
headers['Content-Type'] = 'application/json; charset=UTF-8'
headers['X-Accept'] = 'application/json'
data = json.dumps({'consumer_key': 'XXXX', 'code': cur_auth})
resp = requests.post(url, headers=headers, data=data)
json_resp = resp.json()
access_token = json_resp['access_token']
username = json_resp['username']
session['access_token']=access_token
session['username']=username
access_resp = {'access': access_token, 'user': username}
return jsonify(access_resp)
But when I try to translate this into a postman request, I can't really understand where some of the things like the consumer_key request_token and code get defined.
I'm currently getting a 400 bad request with this setup:
where the consumer_key is in Postman's client secret field, and where
https://[hostname].com/v3/oauth/request is in Postman's auth field and
https://getpocket.com/v3/oauth/authorize is in Postman's access token url field.