I am having trouble with the Jawbone API. When I step through the oauth proess using https://github.com/karthikbgl/python-jawbone-up.git I can successfully receive an authorization code and then get a token.
def access_token(self, code, grant_type='authorization_code'):
'''
Get the access code for a user with a auth code.
'''
params = {
'code' : code,
'client_id' : self.client_id,
'client_secret' : self.client_secret,
'grant_type' : grant_type
}
context = {
'base_url': self.base_url,
'params' : urllib.urlencode(params)
}
headers = {
'Content-Type': 'application/x-www-form-urlencoded',
'Accept': 'application/json',
'X-Target-URI': 'https://jawbone.com',
'host': 'jawbone.com'
}
token_url = '{base_url}auth/oauth2/token/?{params}'.format(**context)
res = requests.get(token_url, headers=headers)
return res.json()
However the token I receive is always the same, and when I use it to call the API, I receive the error :
{"meta": {"code": 401, "error_detail": "You must be logged in to perform that action", "error_type": "authentication_error", "message": "Unauthorized"}, "data": {}}
Additionally, if I use the module called access_jawbone with this code:
params = urllib.urlencode({
'email': username,
'pwd': password,
'service': 'nudge'
})
tokenresponse = urllib2.urlopen(url, params)
I get a valid token that I can access the API with.
Does anyone know why the oauth token provided is not working
The below question seems to address the same problem, but I do not understand the answer or how to resolve my problem.
Jawbone UP API oAuth and Access Tokens
I had the same issue. I think that this answer is what is happening:
https://stackoverflow.com/a/32984287/1732987
To get around it, I had to log out of all Jawbone stuff in by browser, remove the access token from my new application database, and start the sign in process from a clean slate.
Related
I am trying to have an Ouath2 access token based authentication. I am using django-oauth-toolkit for that. I have registered my app on http://localhost:8000/o/applications.
However, When I tried to hit the URL http://localhost:8000/o/token/ from the react-app . I got 401.
Here is my the useEffect hook that I used for calling that URL :
useEffect(() => {
// axios.get("api/tests")
// .then((res)=>{
// setUsers(JSON.stringify(res.data))
// })
fetch("http://localhost:8000/o/token/", {
body: new URLSearchParams({
grant_type: 'client_credentials',
client_id: client_id,
client_secret: client_secret
}),
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"Authorization": `Basic ${btoa(client_id+":"+client_secret)}`}
,
method: "POST"
}).then((res)=>{
console.log(res)
})
}, [])
Will look forward to some comments and solutions.
I got the solution. Actually I was Using the encrypted version of the client secret. I forgot to copy it before saving. Once it is saved the value is encrypted. So it's better to copy it somewhere prior saving it.
I am attempting to get a refresh token and use it to request a new access token when the temporary access token expires.
Spotify's documentation states the response body should contain the following json data:
{
"access_token": "NgCXRK...MzYjw",
"token_type": "Bearer",
"scope": "user-read-private user-read-email",
"expires_in": 3600,
"refresh_token": "NgAagA...Um_SHo"
}
However, using my code below only provides the following:
{
"access_token": "xxxx....",
"token_type": "Bearer",
"expires_in": 3600
}
I am using the following function to request an access token:
def get_access_token(client_id, client_secret): # getting access token from spotify using client ID
# Encoding Client ID and Client Secret in Base64
token_url = "https://accounts.spotify.com/api/token"
client_creds = f"{client_id}:{client_secret}"
client_creds_b64 = base64.b64encode(client_creds.encode())
token_data = {
"grant_type": "client_credentials"
}
token_headers = {
'Authorization': f"Basic {client_creds_b64.decode()}"
}
r = requests.post(token_url, data=token_data, headers=token_headers)
valid_request = r.status_code in range(200, 299)
token_response_data = r.json()
# pretty print response body
print(json.dumps(token_response_data, indent=2)) # response 200 -> successful attempt
if valid_request:
access_token = token_response_data['access_token']
return access_token
I am unsure why the scope and refresh token are missing from the response body. How can I alter this function to include these?
Thanks in advance for your time!
Spotify documentation: https://developer.spotify.com/documentation/general/guides/authorization/code-flow/
Altering the token data fixes this:
token_data = {
"grant_type": "authorization_code",
"code": "xxxx....",
"redirect_uri": "your redirect uri from Spotify for devs"
}
You need to set up a redirect uri on Spotify for devs, then encode it to use it as a parameter.
To get the 'code' parameter fill-out this URL with your data and you will be redirected to your redirect uri.
https://accounts.spotify.com/authorize?client_id=YOUR CLIENT ID&response_type=code&redirect_uri=YOUR ENCODED REDIRECT URI&scope=playlist-modify-public%20playlist-modify-private
The code will then be in the search bar to copy/paste. It should look something like this:
https://your redirectURI?code=xxx.....
Here is a good video guide for reference:
https://www.youtube.com/watch?v=-FsFT6OwE1A&ab_channel=EuanMorgan
I am developing a watchOS app and I want to send push notifications to my users. I have enabled "Push Notifications" in signing and capabilities and a file called "app_name WatchKit Extension" was generated containing one entitlement called APS environment whose value is set to "development".
I have also generated a .p8 file in the Apple Developer Website with the authentication key and that also gives me the key id.
I have created a Swift class called App Delegate that conforms to UNUserNotificationCenterDelegate. I have implemented the method applicationDidFinishLaunching from where I call WKExtension.shared().registerForRemoteNotifications(). Then I implemented the didRegisterForRemoteNotifications where I receive the device token and convert it into a string by executing these lines of code:
let tokenParts = deviceToken.map { data in String(format: "%02.2hhx", data) }
let token = tokenParts.joined()
Then I send the token to the server. In the server I have a Python script that makes the post request to https://api.sandbox.push.apple.com:443 with the headers and notification payload. However, I always get a 404 error ({"reason":"BadPath"}).
I don't know what I am doing wrong. Am I configuring anything wrong? This is the Python script I am using:
import time
import httpx
import asyncio
import jwt
ALGORITHM = 'ES256'
APNS_AUTH_KEY = "path to .p8 file"
f = open(APNS_AUTH_KEY)
secret = f.read()
apns_token = jwt.encode(
{
'iss': 'cert_id',
'iat': time.time()
},
secret,
algorithm=ALGORITHM,
headers={
'alg':ALGORITHM,
'kid':'key_id'
}
)
dev_server = "https://api.sandbox.push.apple.com:443"
device_token = "9fe2814b6586bbb683b1a3efabdbe1ddd7c6918f51a3b83e90fce038dc058550"
headers = {
'method': 'POST',
'path': '/3/device/{0}'.format(device_token),
'autorization': 'bearer {0}'.format(apns_token),
'apns-push-type': 'myCategory',
'apns-expiration': '0',
'apns-priority': '10',
}
payload = {
"aps" : {
"alert" : {
"title" : "Hello Push",
"message": "This is a notification!"
},
"category": "myCategory"
}
}
async def test():
async with httpx.AsyncClient(http2=True) as client:
client = httpx.AsyncClient(http2=True)
r = await client.post(dev_server, headers=headers, data=payload)
print(r.text)
print(r)
asyncio.run(test())
Is there anything wrong with the way I am setting things up or performing the post request?
Thank you for your help!
I am trying to call xero Accounts api in python but not working for some reason. It works well for the rest of APIs such as Invoices, reports, and so on, but Accounts.
The following script is my python script i am using to call the api.
get_url = 'https://api.xero.com/api.xro/2.0/Accounts'
response = requests.get(get_url,
headers = {
'Authorization': 'Bearer ' + access_token,
'Xero-tenant-id': xero_tenant_id,
'Accept': 'application/json'
})
json_response = response.json()
print(json_response)
But this is throwing the following error:
{'Type': None, 'Title': 'Unauthorized', 'Status': 401, 'Detail': 'AuthorizationUnsuccessful', 'Instance': '3c1649ef-6eed-4e64-8503-04fc99481db2', 'Extensions': {}}
Can anyone tell me why this is happening? why just Accounts?
Can you share what scopes you're requesting? https://developer.xero.com/documentation/oauth2/scopes
Invoices requires accounting.transactions
Reports requires accounting.reports.read
Accounts requires accounting.settings
I'm sure this is a broader question that applies to more than just Reddit, but currently I am attempting to exchange a code for a user access token however I am not understanding how to implement the following steps:
https://github.com/reddit-archive/reddit/wiki/OAuth2#retrieving-the-access-token
If you didn't get an error and the state value checks out,
you may then make a POST request with code to the following URL to retrieve your access token:
https://www.reddit.com/api/v1/access_token
Include the following information in your POST data (NOT as part of the URL)
grant_type=authorization_code&code=CODE&redirect_uri=URI
Okay, so what I did was this:
headers = {
CLIENT_ID: CLIENT_SECRET,
}
r = requests.post(
url="https://www.reddit.com/api/v1/access_token",
data={
"grant_type": "authorization_code",
"code": code,
"redirect_uri": "http://127.0.0.1:5000/callback"
},
headers=headers
)
I think I am failing with the headers, I receive a 429 error, and I don't think I've understood how to arrange the headers correctly as it doesn't clearly explain in the above link.
The "user" is the client_id. The "password" for confidential clients is the client_secret. The "password" for non-confidential clients (installed apps) is an empty string.
CLIENT_ID and CLIENT_SECRET are obviously variables, and they are my Reddit App dev credentials.
EDIT:
I came up with this, it's gross but it seems to work
headers = {
"User-Agent": "MyApp v1.0",
"Authorization": "Basic " + str(base64.b64encode(str.encode(f"{CLIENT_ID}:{CLIENT_SECRET}")))[2:-1],
}
Is there a cleaner way to write that?
Final answer, using an inbuilt method in Python's request:
client_auth = requests.auth.HTTPBasicAuth(CLIENT_ID, CLIENT_SECRET)
r = requests.post(
url="https://www.example.com/api/v1/access_token",
auth=client_auth,
data={
"grant_type": "authorization_code",
"code": code,
"redirect_uri": "http://127.0.0.1:5000/callback"
},
headers={
"User-Agent": "MyApp v1.0",
}
)