I have an issue related to access_token which I've received from a React Native app. The React Native app uses the expo-facebook library and when the pop-up of authentication disappears the token is created and sent to the backend API. The token is created by logInWithReadPermissionsAsync method.
const { type, token, expirationDate, permissions, declinedPermissions, graphDomain } =
await Facebook.logInWithReadPermissionsAsync({
permissions: ["public_profile", "email"],
});
I see that the server received this token on http://localhost:8000/api/rest-auth/facebook/ endpoint and sends it to the Facebook endpoint verify. The problem occurs on the response from Facebook. I expect that it should be valid by Facebook, but it seems that something went wrong.
HTTP 400 Bad Request
Allow: POST, OPTIONS
Content-Type: application/json
Vary: Accept
{
"non_field_errors": [
"Incorrect value."
],
"code": 400,
"message": "Bad Request"
}
An access token that I generate in Graph API Explorer is shorter (when I use it, it works in the backend app) than the token which is generated in the React Native expo app. Why are these two tokens different? And why doesn't it work as I am expecting?
I discovered where the issue was. I knew that the issue is was in the token, a good direction was a response from Facebook.
{"error":{"message":"Invalid appsecret_proof provided in the API argument","type":"GraphMethodException","code":100}}.
After that, I realized that probably something is wrong with React Native Expo. Expo-facebook doesn't react when you even pass the app id, it used the wrong APP ID which was defined in the expo environment(APP_ID=1696089354000816). App-id was set in settings and also in the
await Facebook.initializeAsync({
appId: '<APP_ID>',
});".
So the main issue was that I relied on an access_token that didn't belong to my app.
Related
Context
I'm migrating to Google's new auth solution that doesn't require 3rd party cookies using the following guide:
My app is a frontend built in Vue.js and a backend in Python (Flask).
Problem
Once I receive the Authorization token from Google (looks something like 4/0AdQt...bg), I'm unable to exchange it for a refresh & access token.
For Python, the official Google documentation only shows an example that uses Flask (using the Flow object) to request the token and verify it.
I've tried to build a simple POST request with postman
import requests
url = "https://oauth2.googleapis.com/token"
payload='code=4%2F...bg&client_id=92...cac42tg.apps.googleusercontent.com&client_secret=hw...u8D&redirect_uri=https%3A%2F%2Fco...pp&grant_type=authorization_code'
headers = {
'Content-Type': 'application/x-www-form-urlencoded'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
But I get the following unhelpful 400 Bad Request response
{
"error": "invalid_grant",
"error_description": "Bad Request"
}
I tried to change the different form parameters and got different errors (The OAuth client was not found., Unauthorized, invalid_request, ...) so most likely the error is in the actual code.
If anyone has faced a similar issue, I'd love some help!
I want to route my Google Analytics Reporting API request (code will be in AWS Lambda) through a gateway which accepts a REST endpoint only. Since I cant use the Client package method in my interaction with the gateway, I need to query the API as a REST-ful endpoint.
The official document says this (Link) :
Authorization: Bearer {oauth2-token}
GET https://www.googleapis.com/analytics/v3/data/ga
?ids=ga:12345
&start-date=2008-10-01
&end-date=2008-10-31
&metrics=ga:sessions,ga:bounces
I do not know to create the oauth2-token in Python. I have created a service account and have the secrets_json which includes the client id and secret key.
Then client package method as given in this link works. But I need the Rest method only!
Using these, how can I create the oauth2-token ?
You can use Oauth2 for this I have done it in the past but you will need to monitor it. You will need to authorize this code once and save the refresh token. Refresh tokens are long lived they normally dont expire but your code should be able to contact you if it does so that you can authorize it again. If you save the refresh token you can use the last step at any time to request a new access token.
Oauth2 is basicly built up into three calls. I can give you the HTTP calls i will let you work out the Python Google 3 Legged OAuth2 Flow
Authencation and authorization
The first thing you need is the permission of the user. To get that you build a link on the authorization server. This is a HTTP get request you can place it in a normal browser window to test it.
GET https://accounts.google.com/o/oauth2/auth?client_id={clientid}&redirect_uri=urn:ietf:wg:oauth:2.0:oob&scope=https://www.googleapis.com/auth/analytics.readonly&response_type=code
Note on redirect uri. If you are running this on a server or something then use urn:ietf:wg:oauth:2.0:oob it basicly tells the server to return the code back where it came from other wise if you are hosing on a website you can supply a url to the page that will be handling the response.
If the user accepts the above then you will have an authorization code.
Exchange code
What you need to do next is exchange the authorization code returned by the above response and request an access token and a refresh token. THis is a http post call
POST https://accounts.google.com/o/oauth2/token
code=4/X9lG6uWd8-MMJPElWggHZRzyFKtp.QubAT_P-GEwePvB8fYmgkJzntDnaiAI&client_id={ClientId}&client_secret={ClientSecret}&redirect_uri=urn:ietf:wg:oauth:2.0:oob&grant_type=authorization_code
The body parameter should be as i have shown separated by & and the content type of the request is application/x-www-form-urlencoded
Responce
{
"access_token" : "ya29.1.AADtN_VSBMC2Ga2lhxsTKjVQ_ROco8VbD6h01aj4PcKHLm6qvHbNtn-_BIzXMw",
"token_type" : "Bearer",
"expires_in" : 3600,
"refresh_token" : "1/J-3zPA8XR1o_cXebV9sDKn_f5MTqaFhKFxH-3PUPiJ4"
}
The access token can be used in all of your requests to the api by adding either an authorization header bearer token with the access token or by sending access_token= as your parameter in your requests.
Refresh access token
Refresh tokens are long lived they should not expire they can so you code should be able to handle that but normally they are good forever. Access tokens are only valid for one hour and you will need to request a new access token.
POST https://accounts.google.com/o/oauth2/token
client_id={ClientId}&client_secret={ClientSecret}&refresh_token=1/ffYmfI0sjR54Ft9oupubLzrJhD1hZS5tWQcyAvNECCA&grant_type=refresh_token
response
{
"access_token" : "ya29.1.AADtN_XK16As2ZHlScqOxGtntIlevNcasMSPwGiE3pe5ANZfrmJTcsI3ZtAjv4sDrPDRnQ",
"token_type" : "Bearer",
"expires_in" : 3600
}
I have access to an API that I'm trying to start leveraging to automate some tasks and I jumped right into it but was stymied by JWT, which I have never used. I'm also coming off a couple years not using python, so I'm a little rusty. Please bear with me.
Here is a direct quote from the API documentation:
The authentication mode for an organization is with a JSON Web Token. Users
must pass a JSON Web Token (JWT) in the header of each API request made.
To obtain the JWT, send the user’s API key (UUID) and password in a JSON Web
Token GET Request. The authorization method of “Bearer” and a
space is then prefixed to the encoded token string returned. The token will
be tied to the user account that generated the JWT.
I've tried with requests but I'm get 405 errors, I've also installed and imported pyjwt but it's confusing to me. This is essentially what I'm trying to send via python:
POST https://<our endpoint>/v1/token/get HTTP/1.1
Content-Type: application/json
{
"username": "<myUsername>",
"password": "<myPassword>"
I've verified that the target API is working, as there is a small set of functionality that works without JWT and was easily accessed via requests
Advice is welcome, as are any tutorials. I've tried to read several JWT tutorials but I'm having a hard time translating it to python.
Thanks!
Question: To obtain the JWT, send the user’s API key (UUID) and password in a JSON Web Token GET Request
Solution using python_jwt.
Assumptions:
Encoding Method = HS256
claims Fieldname 'consumerId'
claims Fieldname 'httpMethod'
Your JWT in the url looks like:
'http://httpbin.org/get?eyJ0eXAiOiAiSldUIiwgImFsZyI6ICJIUzI1NiJ9... (omitted for brevity)
response.json() contains the requested JWT you have to use afterwards.
Note: Your have to use https://<base url>/v1/token/get
import python_jwt as jwt
# Create claims dictionary for generation of JwToken
claims = {
'consumerId': 'My App ID',
'httpMethod': 'GET'
}
import datetime
# create JWToken
jwtoken = jwt.generate_jwt(claims, 'My secret', 'HS256', datetime.timedelta(minutes=5))
response = requests.get('http://httpbin.org/get', jwtoken)
print(response.json())
Tested with Python:3.4.2 - requests:2.11.1
While requesting http://www.sonyliv.com/api/v2/vod/search API, I am getting "Invalid csrf token" message in chrome postman.
{
"code": "403",
"name": "Bad Request",
"message": "Invalid csrf token"
}
When I look to Chrome Inspect Element > Network tab in Headers section, I found
"X-XSRF-TOKEN:tGXcHOmy-ro-GQfTestDSAp8EINq85dwHpdU"
as a token but this token is changed in every session, how can i pass X-XSRF-TOKEN value in my request to get the required result.
Please Help.
The idea of the CSRF tokens is that you can't call an API service if you're not doing it from the expected form, that's why it always changes its value.
I'm guessing you're trying to use that API not officially... so what you could try is to GET the base website and store in a cookie jar all the cookies it sends you and then try to query the search endpoint.
That way your request will include the XSRF token and the rest of the cookies and hopefully the server will think you request is legit.
Hope it helps
I'm trying to enlarge value of 'expires_in' (from credential object, now it is 3600 seconds), because I want to allow user to use my app for a long time. I'm using refreshing token, but it refreshed only if user uses app quite often.
If you know how to change token_expiry date - I'm interested of that solution too.
Thank you for any tips.
For security reason, expiration time is short and it cannot be changed. However, you can extend user's authorization without interacting with user using refresh_token. Basically, as a response to auth code exchange, the server provides refresh_token which looks like this:
{
"access_token" : "ya29.AHES6ZTtm7SuokEB-RGtbBty9IIlNiP9-eNMMQKtXdMP3sfjL1Fc",
"token_type" : "Bearer",
"expires_in" : 3600,
"refresh_token" : "1/HKSmLFXzqP0leUihZp2xUt3-5wkU7Gmu2Os_eBnzw74"
}
When token expires, all you have to do is to use refresh_token to reauthorize, without user interaction. Like this:
POST /o/oauth2/token HTTP/1.1
Host: accounts.google.com
Content-Type: application/x-www-form-urlencoded
client_id=21302922996.apps.googleusercontent.com&
client_secret=XTHhXh1SlUNgvyWGwDk1EjXB&
refresh_token=1/HKSmLFXzqP0leUihZp2xUt3-5wkU7Gmu2Os_eBnzw74
grant_type=refresh_token
To make things more simple, when you are using Python, you don't even have to care about refresh_token if you are using Credentials class from google-api-python-client. Just use Credentials.authorize() and it will automatically authorize or refresh token based on your status.