SAP GATEWAY & UI5: How can reset the CSRF token?= - sapui5

I need to reset the CSRF token in an OData model. Based on the UI5 documentation I am trying to do that with refreshSecurityToken(fnSuccess?, fnError?, bAsync?) function. (click here for reference)
I wrote the following code:
var oDataModel = this.getOwnerComponent().getModel("ZMDM_ODATA_FILE_SRV");
oDataModel.setTokenHandlingEnabled(true);
oDataModel.refreshSecurityToken(function() {
var token = oDataModel.getSecurityToken();
console.log(token);
// can upload the file if token reset
});
The problem is that this token is not reset for 30 minutes and that is our session timeout. Actually it is valid during the session lifetime. I even checked the following link:
https://blogs.sap.com/2014/08/26/gateway-protection-against-cross-site-request-forgery-attacks/
Actually many people had this problem, but I couldn't find a clear solution for resetting the token. I did all the required steps in the front-end for the sending a Head request for resting the token. I think something is missing regarding the back-end gateway settings or ABAP coding.
What do I have to do?

You can delete a CSRF Token (per user/token) via transaction SM05.

seems like you need to set a interval in your front-end application to fetch and update the token more often. But that's a paradox: if your back-end sets the timeout for 30 minutes, why would you keep it live for more time?
SecurityToken timeout is important to make sure the active session is being used and that no individual "forgot" it and left the system open and unwatched/unused.
But if you really need to keep your front-end session always available and force the back-end to be too, you can setInterval() to fetch the CSRF and update the application:
var oDataModel = this.getOwnerComponent().getModel("ZMDM_ODATA_FILE_SRV");
oDataModel.setTokenHandlingEnabled(true);
var fnRefreshToken = oDataModel.refreshSecurityToken(function() {
var token = oDataModel.getSecurityToken();
console.log(token);
// can upload the file if token reset
});
window.setInterval(function(){
fnRefreshToken;
}, 1800000); // where 1.800.000 miliseconds represents 30 minutes
And then you should store your new token in the token variable and allow upload if token is reset.
Kindly regards,
Henrique Mattos

Related

Maintain flask_login session in flutter

Soo...I have an app with flask backend and flutter frontend. It utilizes flask_login to manage users. Problem is - I don't know how to maintain session on client side. Flutter client gets response from server, but I don't see any token, or user_id inside.
So far, I've tried to parse responce, with no luck and I've used solution from How do I make an http request using cookies on flutter?
also, without success.
Server-side https://github.com/GreenBlackSky/COIN/blob/master/api_app/app/login_bp.py
Client-side https://github.com/GreenBlackSky/coin_web_client/blob/master/lib/session.dart
Maybe, using flask_login was not such a good idea after all..
Have you tried with the request_loader approach? You can log in from Flutter client using a url argument and the Authorization header. Quoting from the documentation,
For example, to support login from both a url argument and from Basic Auth using the Authorization header:
#login_manager.request_loader
def load_user_from_request(request):
# first, try to login using the api_key url arg
api_key = request.args.get('api_key')
if api_key:
user = User.query.filter_by(api_key=api_key).first()
if user:
return user
# next, try to login using Basic Auth
api_key = request.headers.get('Authorization')
if api_key:
api_key = api_key.replace('Basic ', '', 1)
try:
api_key = base64.b64decode(api_key)
except TypeError:
pass
user = User.query.filter_by(api_key=api_key).first()
if user:
return user
# finally, return None if both methods did not login the user
return None
If you don't want to use flask_login anymore, I would suggest flask_jwt_extended for your case. Note that authentication will be carried out using JWT tokens instead of sessions.
Basically, you would need to create three routes: one for creating access and refresh tokens when the user logged in, one for refreshing the expired access token with the refresh token and one for removing the tokens when the user logged out. Then you would protect your API endpoints with the #jwt_required decorators.
Please refer to the documentation for detailed implementation.

Facebook OAuth Login - access_token API returning "This authorization code has been used"

This question has been asked a few times on Stack, but there have been no real answers. Let me try to explain my situation anyways.
We use an application that uses Facebook OAuth2 login. This login used to work fine till last week, and all of a sudden it is troubling us now.
Application Flow:
Step 1: User presses login with Facebook button on our website
Step 2: Redirected to Facebook login/authorization page
Step 3: On authorizing the app, the callback comes to our application, with a short lived "code" param.
Step 4: This "code" param would be exchanged for a 60 day Access token using "https://graph.facebook.com/oauth/access_token" URL.
Error in Step 4:
When we try to exchange the short living "code" for the access token, we get this error from Facebook.
{"error":{"message":"This authorization code has been used.","type":"OAuthException","code":100}}
Observation:
For users who are newly coming to the application, the above-said error does not occur.
For a returning user this call fails with the above-said error.
Our application is live for more than 9 months now, and this error has come only in the past 7-10 days. We have had thousands of users using it successfully prior to that.
What I already got from Forums:
Here is my interpretation of what I read. May be inaccurate.
Facebook has some weird policy that necessitates the app developer to maintain the temporary 10 minute code until the 60 day code that was obtained during the first login expires. So we should create a cookie with the Access token on the user's browser. I was even able to see people modifying their code in order to create the cookies.
What's really bothering me?
The suggested solutions assumes that the cookie that they create would be present in the user's browser always. This is a bad assumption to make, as the cookie may be erased at any time.
I have another app Id/app secret that I use for my development (i.e localhost), and that works perfectly. The login happens fine out there, But its only the product machine that has the problem.
This problem didn't happen on the production machine for nearly 10 months since we launched the app, and it has come all of a sudden. Worst of all, I am unable to get any record of recent changes that breaks this flow.
Edit:
Platform: Python, Google Appengine. We do not use any Facebook SDKs, we make direct HTTP Calls to all the login URLs.
Call that fails : https://graph.facebook.com/oauth/access_token - we are passing the appId, secret and code (obtained from facebook) within 20 seconds of the first call happening.
Hope there is enough information here to show that our code is not totally incorrect. Any tips/pointers from people who have encountered and solved this problem is Welcome. If its a Facebook bug, and the Facebook dev comes to notice, I would be even happier.
I got round this issue by using a random GUID which is appended to each callback url i pass into facebook. It seems the code that facebook returns is made up of a few parts including the redirect_uri parameter you have to specify. By using this GUID trick, your app continues to work but facebook thinks it's a different URL hence generating a new code.
If you store that GUID in a temporary session, it's always the same. Here's a very cut down version of what I mean. I'm using C# but the solution will be the same:
Before i start the oauth process:
Session["facebook_buster"] = System.Guid.NewGuid().ToString();
Then to kick off the login:
var facebook = new FacebookClient();
var loginUrl = facebook.GetLoginUrl(new
{
client_id = ...,
redirect_uri = ..."/facebook/oauthcallback?buster=" + Session["facebook_buster"].ToString(),
display = "popup",
scope = "publish_stream,user_photos"
});
And then in my callback method, when I want to exchange that code for a new access_token:
var facebook = new FacebookClient();
dynamic result = facebook.Post("oauth/access_token", new
{
client_id = ...,
client_secret = ...,
redirect_uri = ..."/facebook/oauthcallback?buster=" + Session["facebook_buster"].ToString(),
code = Request["code"] // this is the returned code from the first method
});
Note in that second method i'm using the same session key so that the authorization code is successful.
Been testing this all morning by revoking permissions / manually changing my stored access_token (in my db) / removing my stored access_token completely and it works every time.
Hope this helps!
I struggled with this today for a while too. Not sure if you're using the Facebook PHP class (from what you wrote, it seems you don't), however, it could be a pointer anyways - the problem was that the Facebook PHP library seems to obtain the token from the code automatically and I was trying to do it again.

Google packaged app - identity API - removeCachedAuthToken

[google chrome 28]
I am using chrome.experimental.identity API in a packaged app and getAuthToken works fine - get's token with which I can get user info, etc.
I understand that the identity API is moving out from being experimental to the trunk so as from chrome 29 I will be able to use chrome.identity and remove "experimental" permission from my manifest.
Q: If I want to make a logout button is removeCachedAuthToken the way to go about it? I tried to use it in the experimental.identity but it does nothing.
To revoke token use this function from google sample app.
function revokeToken() {
user_info_div.innerHTML = "";
chrome.identity.getAuthToken({ interactive: false },
function (current_token) {
if (!chrome.runtime.lastError) {
// #corecode_begin removeAndRevokeAuthToken
// #corecode_begin removeCachedAuthToken
// Remove the local cached token
chrome.identity.removeCachedAuthToken({token: current_token}, function(){});
// #corecode_end removeCachedAuthToken
// Make a request to revoke token in the server
var xhr = new XMLHttpRequest();
xhr.open(
"GET",
"https://accounts.google.com/o/oauth2/revoke?token=" + current_token);
xhr.send();
// #corecode_end removeAndRevokeAuthToken
// Update the user interface accordingly
changeState(STATE_START);
sampleSupport.log("Token revoked and removed from cache. " +
"Check chrome://identity-internals to confirm.");
}
});
}
No. It is not the way to go.
removeCachedAuthToken is a function that removes a token acquired using getAuthToken from the internal token cache. However, it does not revoke the token. That means that the application will no longer be able to access to the user resources in current session, until it calls getAuthToken again. When that happens, it will be able to obtain a token again without the user needing to grant access.
As such, this function is not meant to be a logout related routine. It is more of a recovery mechanism, when you realize that the access token that your application is using is stale, or invalid in any other way. That happens, when you make a request using the access token and the HTTP response status is 401 Unauthorized. In that case you can scrap the token and then request a new one using getAuthToken. To simulate that behavior, you can revoke the a relevant grant using the Google Accounts page or form the diagnostic UI: chrome://identity-internals (currently it lists all of the cached tokens).
Please refer to the chrome app samples for GDocs and Identity.
(Pull requests 114 for GDocs and 115 for Identity in case you are doing that in next few days.)
I too struggled with this but I eventually discovered this solution buried in the Chrome App Samples. https://github.com/GoogleChrome/chrome-app-samples/blob/master/gapi-chrome-apps-lib/gapi-chrome-apps.js
removeCachedAuthToken removes it locally, but to revoke the token from Google servers you needs to send a request, hence the second part: xhr.open('GET', 'https://accounts.google.com/o/oauth2/revoke?token=' +
current_token);
Try this:
function revokeToken() {
chrome.identity.getAuthToken({ interactive: false },
function (current_token) {
if (!chrome.runtime.lastError) {
// #corecode_begin removeAndRevokeAuthToken
// #corecode_begin removeCachedAuthToken
// Remove the local cached token
chrome.identity.removeCachedAuthToken({token: current_token}, function(){});
// #corecode_end removeCachedAuthToken
// Make a request to revoke token in the server
var xhr = new XMLHttpRequest();
xhr.open("GET", "https://accounts.google.com/o/oauth2/revoke?token=" +
current_token);
xhr.send();
// #corecode_end removeAndRevokeAuthToken
// Update the user interface accordingly
$("#revoke").get(0).disabled = true;
console.log("Token revoked and removed from cache. " +
"Check chrome://identity-internals to confirm.");
}
});
}

Facebook: Permanent Page Access Token?

I work on a project that has Facebook pages as one of its data sources. It imports some data from it periodically with no GUI involved. Then we use a web app to show the data we already have.
Not all the information is public. This means I have to get access to the data once and then keep it. However, I don't know the process and I haven't found a good tutorial on that yet. I guess I need an access_token, how can I get it from the user, step by step? The user is an admin of a facebook page, will he have to add some FB app of ours to the page?
EDIT: Thanks #phwd for the tip. I made a tutorial how to get a permanent page access token, even with offline_access no longer existing.
EDIT: I just found out it's answered here: Long-lasting FB access-token for server to pull FB page info
Following the instructions laid out in Facebook's extending page tokens documentation I was able to get a page access token that does not expire.
I suggest using the Graph API Explorer for all of these steps except where otherwise stated.
0. Create Facebook App
If you already have an app, skip to step 1.
Go to My Apps.
Click "+ Add a New App".
Setup a website app.
You don't need to change its permissions or anything. You just need an app that wont go away before you're done with your access token.
1. Get User Short-Lived Access Token
Go to the Graph API Explorer.
Select the application you want to get the access token for (in the "Application" drop-down menu, not the "My Apps" menu).
Click "Get Token" > "Get User Access Token".
In the pop-up, under the "Extended Permissions" tab, check "manage_pages".
Click "Get Access Token".
Grant access from a Facebook account that has access to manage the target page. Note that if this user loses access the final, never-expiring access token will likely stop working.
The token that appears in the "Access Token" field is your short-lived access token.
2. Generate Long-Lived Access Token
Following these instructions from the Facebook docs, make a GET request to
https://graph.facebook.com/v2.10/oauth/access_token?grant_type=fb_exchange_token&client_id={app_id}&client_secret={app_secret}&fb_exchange_token={short_lived_token}
entering in your app's ID and secret and the short-lived token generated in the previous step.
You cannot use the Graph API Explorer. For some reason it gets stuck on this request. I think it's because the response isn't JSON, but a query string. Since it's a GET request, you can just go to the URL in your browser.
The response should look like this:
{"access_token":"ABC123","token_type":"bearer","expires_in":5183791}
"ABC123" will be your long-lived access token. You can put it into the Access Token Debugger to verify. Under "Expires" it should have something like "2 months".
3. Get User ID
Using the long-lived access token, make a GET request to
https://graph.facebook.com/v2.10/me?access_token={long_lived_access_token}
The id field is your account ID. You'll need it for the next step.
4. Get Permanent Page Access Token
Make a GET request to
https://graph.facebook.com/v2.10/{account_id}/accounts?access_token={long_lived_access_token}
The JSON response should have a data field under which is an array of items the user has access to. Find the item for the page you want the permanent access token from. The access_token field should have your permanent access token. Copy it and test it in the Access Token Debugger. Under "Expires" it should say "Never".
Here's my solution using only Graph API Explorer & Access Token Debugger:
Graph API Explorer:
Select your App from the top right dropdown menu
Select "Get User Access Token" from dropdown (right of access token field) and select needed permissions
Copy user access token
Access Token Debugger:
Paste copied token and press "Debug"
Press "Extend Access Token" and copy the generated long-lived user access token
Graph API Explorer:
Paste copied token into the "Access Token" field
Make a GET request with "PAGE_ID?fields=access_token"
Find the permanent page access token in the response (node "access_token")
(Optional) Access Token Debugger:
Paste the permanent token and press "Debug"
"Expires" should be "Never"
(Tested with API Version 2.9-2.11, 3.0-3.1)
In addition to the recommended steps in the Vlasec answer, you can use:
Graph API explorer to make the queries, e.g. /{pageId}?fields=access_token&access_token=THE_ACCESS_TOKEN_PROVIDED_BY_GRAPH_EXPLORER
Access Token Debugger to get information about the access token.
Another PHP answer to make lives easier. Updated for Facebook Graph API 2.9 . Just fill 'er up and load.
<?php
$args=[
/*-- Permanent access token generator for Facebook Graph API version 2.9 --*/
//Instructions: Fill Input Area below and then run this php file
/*-- INPUT AREA START --*/
'usertoken'=>'',
'appid'=>'',
'appsecret'=>'',
'pageid'=>''
/*-- INPUT AREA END --*/
];
echo 'Permanent access token is: <input type="text" value="'.generate_token($args).'"></input>';
function generate_token($args){
$r=json_decode(file_get_contents("https://graph.facebook.com/v2.9/oauth/access_token?grant_type=fb_exchange_token&client_id={$args['appid']}&client_secret={$args['appsecret']}&fb_exchange_token={$args['usertoken']}")); // get long-lived token
$longtoken=$r->access_token;
$r=json_decode(file_get_contents("https://graph.facebook.com/v2.9/me?access_token={$longtoken}")); // get user id
$userid=$r->id;
$r=json_decode(file_get_contents("https://graph.facebook.com/v2.9/{$userid}?fields=access_token&access_token={$longtoken}")); // get permanent token
if($r->id==$args['pageid']) $finaltoken=$r->access_token;
return $finaltoken;
}
?>
Addendum: (alternative)
Graph 2.9 onwards , you can skip much of the hassle of getting a long access token by simply clicking Extend Access Token at the bottom of the Access Token Debugger tool, after having debugged a short access token. Armed with information about pageid and longlivedtoken, run the php below to get permanent access token.
<?php
$args=[
/*-- Permanent access token generator for Facebook Graph API version 2.9 --*/
//Instructions: Fill Input Area below and then run this php file
/*-- INPUT AREA START --*/
'longlivedtoken'=>'',
'pageid'=>''
/*-- INPUT AREA END --*/
];
echo 'Permanent access token is: <input type="text" value="'.generate_token($args).'"></input>';
function generate_token($args){
$r=json_decode(file_get_contents("https://graph.facebook.com/v2.9/{$args['pageid']}?fields=access_token&access_token={$args['longlivedtoken']}"));
return $r->access_token;
}
?>
Although the second code saves you a lot of hassle, I recommend running the first php code unless you are in a lot of hurry because it cross-checks pageid and userid. The second code will not end up working if you choose user token by mistake.
Thanks to dw1 and Rob
I made a PHP script to make it easier. Create an app. In the Graph API Explorer select your App and get a user token with manage_pages and publish_pages permission. Find your page's ID at the bottom of its About page. Fill in the config vars and run the script.
<?php
$args=[
'usertoken'=>'',
'appid'=>'',
'appsecret'=>'',
'pageid'=>''
];
echo generate_token($args);
function generate_token($args){
$r=json_decode(file_get_contents("https://graph.facebook.com/v2.8/oauth/access_token?grant_type=fb_exchange_token&client_id={$args['appid']}&client_secret={$args['appsecret']}&fb_exchange_token={$args['usertoken']}")); // get long-lived token
$longtoken=$r->access_token;
$r=json_decode(file_get_contents("https://graph.facebook.com/v2.8/me?access_token={$longtoken}")); // get user id
$userid=$r->id;
$r=json_decode(file_get_contents("https://graph.facebook.com/v2.8/{$userid}/accounts?access_token={$longtoken}")); // get permanent token
foreach($r->data as $d) if($d->id==$args['pageid']) return $d->access_token;
}
I tried these steps:
https://developers.facebook.com/docs/marketing-api/access#graph-api-explorer
Get Permanent Page Access Token
Go to Graph API Explorer
Select your app in Application
Paste the long-lived access token into Access Token
Next to Access Token, choose the page you want an access token for. The access token appears as a new string.
Click i to see the properties of this access token
Click “Open in Access Token Tool” button again to open the “Access Token Debugger” tool to check the properties
One Tip, it only worked for me when the page language is english.
As all the earlier answers are old, and due to ever changing policies from facebook other mentioned answers might not work for permanent tokens.
After lot of debugging ,I am able to get the never expires token using following steps:
Graph API Explorer:
Open graph api explorer and select the page for which you want to obtain the access token in the right-hand drop-down box, click on the Send button and copy the resulting access_token, which will be a short-lived token
Copy that token and paste it in access token debugger and press debug button, in the bottom of the page click on extend token link, which will extend your token expiry to two months.
Copy that extended token and paste it in the below url with your pageId, and hit in the browser url
https://graph.facebook.com/{page_id}?fields=access_token&access_token={long_lived_token}
U can check that token in access token debugger tool and verify Expires field , which will show never.
Thats it
Most of the answers above now doesn't give permanent token, they only extend it to 2 months. Here's how I got it:
From Graph Explorer tool, select the relevant permissions and get the short lived page access token.
Go to debugger tool and paste your access token. Then, click on 'Extend Token' button at the bottom of the page.
Copy the the extended token and use it in this API:
https://graph.facebook.com/v2.10/me?fields=access_token&access_token=<extended_access_token>
This should return you the permanent access token. You can verify it in debugger tool, the expires at field should say 'Never'.
If you are requesting only page data, then you can use a page access token. You will only have to authorize the user once to get the user access token; extend it to two months validity then request the token for the page. This is all explained in Scenario 5. Note, that the acquired page access token is only valid for as long as the user access token is valid.
While getting the permanent access token I followed above 5 steps as Donut mentioned. However in the 5th step while generating permanent access token its returning the long lived access token(Which is valid for 2 months) not permanent access token(which never expires). what I noticed is the current version of Graph API is V2.5. If you trying to get the permanent access token with V2.5 its giving long lived access token.Try to make API call with V2.2(if you are not able to change version in the graph api explorer,hit the API call https://graph.facebook.com/v2.2/{account_id}/accounts?access_token={long_lived_access_token} in the new tab with V2.2) then you will get the permanent access token(Which never expires)
In addition to mentioned methods it is worth mentioning that for server-to-server applications, you can also use this form of permanent access token:
app_id|app_secret
This type of access token is called App Token. It can generally be used to call Graph API and query for public nodes within your application back-end.
It is mentioned here: https://developers.facebook.com/docs/facebook-login/access-tokens
If you have facebook's app, then you can try with app-id & app-secret.
Like :
access_token={your-app_id}|{your-app_secret}
it will don't require to change the token frequently.
Thanks to #donut I managed to get the never expiring access token in JavaScript.
// Initialize exchange
fetch('https://graph.facebook.com/v3.2/oauth/access_token?grant_type=fb_exchange_token&client_id={client_id}&client_secret={client_secret}&fb_exchange_token={short_lived_token}')
.then((data) => {
return data.json();
})
.then((json) => {
// Get the user data
fetch(`https://graph.facebook.com/v3.2/me?access_token=${json.access_token}`)
.then((data) => {
return data.json();
})
.then((userData) => {
// Get the page token
fetch(`https://graph.facebook.com/v3.2/${userData.id}/accounts?access_token=${json.access_token}`)
.then((data) => {
return data.json();
})
.then((pageToken) => {
// Save the access token somewhere
// You'll need it at later point
})
.catch((err) => console.error(err))
})
.catch((err) => console.error(err))
})
.catch((err) => {
console.error(err);
})
and then I used the saved access token like this
fetch('https://graph.facebook.com/v3.2/{page_id}?fields=fan_count&access_token={token_from_the_data_array}')
.then((data) => {
return data.json();
})
.then((json) => {
// Do stuff
})
.catch((err) => console.error(err))
I hope that someone can trim this code because it's kinda messy but it was the only way I could think of.
Application request limit reached (#4) - FB API v2.1 and greater
This answer led me to the "ultimate answer for us" and so it is very much related so I am appending it here. While it's related to the above it is different and it seems FB has simplified the process some.
Our sharing counts on our site stopped worked when FB rolled over the api to v 2.1. In our case we already had a FB APP and we were NOT using the FB login. So what we needed to do was get a FB APP Token to make the new requests. This is as of Aug. 23 2016.
Go to: https://developers.facebook.com/tools/explorer
Select the api version and then use GET and paste the following:
/oauth/access_token?client_id={app-id}&client_secret={app-secret}&grant_type=client_credentials
You will want to go grab your app id and your app secret from your app page. Main FB Apps developer page
Run the graph query and you will see:
{
"access_token": "app-id|app-token",
"token_type": "bearer"
}
Where "app-id" and "app-token" will be your app id from your FB app page and the generated FB App HASH you just received.
Next go test your new APP access token: FB Access Token tester
You should see, by pasting the "app-token" into the token tester, a single app based token without an expiration date/time.
In our case we are using the FB js sdk so we changed our call to be like so (please note this ONLY gets the share count and not the share and comment count combined like it used to be):
FB.api(
'/','GET',{
// this is our FB app token for our FB app
access_token: FBAppToken,
"id":"{$shareUrl}","fields":"id,og_object{ engagement }"
}
This is now working properly. This took a lot of searching and an official bug report with FB to confirm that we have to start making tokenized requests to the FB api. As an aside I did request that they (FB) add a clue to the Error code (#4) that mentions the tokenized request.
I just got another report from one of our devs that our FB comment count is broken as well due to the new need for tokenized requests so I will update this accordingly.
Many of these examples do not work, not sure if it's because of 2.9v coming out but I was banging my head. Anyways I took #dw1 version and modified it a little with the help of #KFunk video and got this working for me for 2.9. Hope this helps.
$args=[
/*-- Permanent access token generator for Facebook Graph API version 2.9 --*/
//Instructions: Fill Input Area below and then run this php file
/*-- INPUT AREA START --*/
'usertoken'=>'',
'appid'=>'',
'appsecret'=>'',
'pageid'=>''
/*-- INPUT AREA END --*/
];
echo 'Permanent access token is: <input type="text" value="'.generate_token($args).'"></input>';
function generate_token($args){
$r = json_decode(file_get_contents("https://graph.facebook.com/v2.9/oauth/access_token?grant_type=fb_exchange_token&client_id={$args['appid']}&client_secret={$args['appsecret']}&fb_exchange_token={$args['usertoken']}")); // get long-lived token
$longtoken=$r->access_token;
$r=json_decode(file_get_contents("https://graph.facebook.com/{$args['pageid']}?fields=access_token&access_token={$longtoken}")); // get user id
$finaltoken=$r->access_token;
return $finaltoken;
}
As of April 2020, my previously-permanent page tokens started expiring sometime between 1 and 12 hours. I started using user tokens with the manage_pages permission to achieve the previous goal (polling a Page's Events). Those tokens appear to be permanent.
I created a python script based on info found in this post, hosted at github.com/k-funk/facebook_permanent_token, to keep track of what params are required, and which methods of obtaining a permanent token are working.
I created a small NodeJS script based on donut's answer. Store the following in a file called get-facebook-access-token.js:
const fetch = require('node-fetch');
const open = require('open');
const api_version = 'v9.0';
const app_id = '';
const app_secret = '';
const short_lived_token = '';
const page_name = '';
const getPermanentAccessToken = async () => {
try {
const long_lived_access_token = await getLongLivedAccessToken();
const account_id = await getAccountId(long_lived_access_token);
const permanent_page_access_token = await getPermanentPageAccessToken(
long_lived_access_token,
account_id
);
checkExpiration(permanent_page_access_token);
} catch (reason) {
console.error(reason);
}
};
const getLongLivedAccessToken = async () => {
const response = await fetch(
`https://graph.facebook.com/${api_version}/oauth/access_token?grant_type=fb_exchange_token&client_id=${app_id}&client_secret=${app_secret}&fb_exchange_token=${short_lived_token}`
);
const body = await response.json();
return body.access_token;
};
const getAccountId = async (long_lived_access_token) => {
const response = await fetch(
`https://graph.facebook.com/${api_version}/me?access_token=${long_lived_access_token}`
);
const body = await response.json();
return body.id;
};
const getPermanentPageAccessToken = async (
long_lived_access_token,
account_id
) => {
const response = await fetch(
`https://graph.facebook.com/${api_version}/${account_id}/accounts?access_token=${long_lived_access_token}`
);
const body = await response.json();
const page_item = body.data.find(item => item.name === page_name);
return page_item.access_token;
};
const checkExpiration = (access_token) => {
open(`https://developers.facebook.com/tools/debug/accesstoken/?access_token=${access_token}&version=${api_version}`);
}
getPermanentAccessToken();
Fill in the constants and then run:
npm install node-fetch
npm install open
node get-facebook-access-token.js
After running the script a page is opened in the browser that shows the token and how long it is valid.
I found this answer which refers to this tool which really helped a lot.
I hope this answer is still valid when you read this.

Extend auth token without refreshing the page

Users want to use my facebook app for many hours without refreshing the browser.
But token expires in 2 hours. Now I ask users to refresh the page but that's annoying.
I don't want to ask offline access permissions because it will scare some users.
The best solution will be somehow "relogin" and get new token without refreshing the page.
Is it possible?
I would subscribe to the expiry trigger (I think this is authResponseChange), then automate another login check. It won't be a perfect solution as it could trigger a pop up (if they have logged out for example) automatically, which a lot of browsers may block. You could instead, when the token expires, check if they will need to complete a pop up, and display a notification on your page somewhere saying 'Facebook needs your attention to continue', then only launch the pop up from their response, which would stop the pop up being blocked.
FB.Event.subscribe('auth.authResponseChange', function(response) {
// do something with response
FB.login(){
// refresh their session - or use JS to display a notification they can
// click to prevent pop up issues
}
});
An algorithm to workout on this
Ask for permission from the user
Save the token
Periodically check for an access token is near to expire or not
If its in verse of expiry, embed some dummy iframe, which redirects to the facebook homepage. - Extend auth token without refreshing the page
This should refresh the token. You might need to generate another token or continue with the same. Whatever be required, can be done without refreshing the page.
Have you thought of using ajax? After two hours you will check, if user is still active. If so, you send axax request to URL, where his session details will be updated. example:
$(document).ready(function(){
setInterval('update_session()', 5500000);
})
update_session(){
$.post({
URL: ..., // script to update session on server
data:{ /* username, password */ },
})
}
and the server-side just takes username and password from post or and runs relogin.
Try acquiring tokens with the offline_access permission.
I presume, guess this is not possible,FB architecture would not allow it. And why is offline_access such a problem!!!!!!...anyway offline_access is the best optimal solution I guess....
Unfortunately I believe this is impossible by design (if you mean for it to happen without user intervention). If the user is still logged in to Facebook you can redirect the top-level page to Facebook and it will bounce you right back with a new code (as it sounds like you are doing already), but that is only possible because of the Facebook cookie that it can check. If you try to do anything from your server, it will be rejected because that cookie will not accompany the request. Same goes for trying to make a call to facebook from javascript -- since your code is running in a different domain, the cookie will not accompany the call and Facebook will reject it. The only way that Facebook can even know who the user is, and that they are still logged in, is to see that cookie. And the only way that can happen is if the browser itself is redirected to the facebook.com domain.
It's worth mentioning also that Facebook has blocked the only logical workaround, i.e. loading the oauth url in an iframe. If you try it you will see that they detect the page is being loaded in an iframe and output a page with a link on it which does a top-level redirect to break out of the frame. So not only does this approach not work, it's clear that Facebook has specifically made it impossible as part of their architecture.
Edit: If what you mean to do is not avoid the refresh altogether but just have it happen automatically when a new token is needed, you can do something like this:
$status=0;
$data=#file_get_contents("https://graph.facebook.com/me?access_token=$token");
foreach ($http_response_header as $rh) if (substr($rh, 0, 4)=='HTTP') list(,$status,)=explode(' ', $rh, 3);
if ($status==200)
{
//token is good, proceed
}
else
{
//token is expired, get new one
$fburl="http://www.facebook.com/dialog/oauth?client_id=APP_ID&redirect_uri=".urlencode('http://apps.facebook.com/yourapp/thispage.php');
echo "<html>\n<body>\n<script>top.location='$fburl';</script>\n</body>\n</html>\n";
exit;
}
This is assuming you have something before this code that will process a signed_request parameter if it is present and assign a value to $token (either explicit code of your own or the appropriate SDK entries). The shown code can then be used anywhere you need to check if $token is still valid before proceeding.
If you get the access_token without specifying any expiry to them they will not expire ..
atleast not till the time user either changes his Fb credentials or de registers your application ..
I presume you are using the iframe signed_request parameter to get your access token. One method of achieving what you require is to use the oAuth 2.0 method of aquiring an access token. This is more prolonged in the first instance; your server and Facebook's have to exchange credentials which can be slow, but it means that you will be given a code that can be exchanged for an access token regularly, meaning your server can maintain the session periodically (probably from an ajax call from the client). You would then pass this new access_token to the client, and use it in your dialog call for your requests (gifts).
Hope that helps.
Spabby
Have a look at https://developers.facebook.com/docs/offline-access-deprecation/#extend_token
basically you extend the token with
https://graph.facebook.com/oauth/access_token?
client_id=APP_ID&
client_secret=APP_SECRET&
grant_type=fb_exchange_token&
fb_exchange_token=EXISTING_ACCESS_TOKEN
that will give you new token with new expiry time (it should be 60d but I'm noticing similar bug like described here https://developers.facebook.com/bugs/347831145255847/?browse=search_4f5b6e51b18170786854060 )