facebook sdk (php) can't get access token - facebook-php-sdk

EDITS: See this picture: http://trackauthoritymusic.com/wwwroot/images/fb-issue-bug.jpg.
For snapshots of the Network tab and all HTTPS headers from my page through FB's redirect.
The windows in the image above show the var_dump's in the code below:
For an access token I only get default the combined appId|secret.
When I var_dump $_REQUESTS at the first point of contact from Facebook, I get nothing so know codeigniter is not stripping the values, but i'm definitely not getting an "signed_request" post from Facebook!
I'm 85.1% sure my Facebook app settings are fine. I've made dozens of tweaks and resets while testing to no success.
And when I switch the settings to client-side approach with the access token in the browser hash, i DO get a valid token, but am desperately trying to avoid all that javascript on my page and will need the php integrated anyway.
All of this only happens once you've approved the app, and I can manually look up their membership in Insights, but know they can't access the app without seeing their token.
I had put this bug aside until now, since my ORIGINAL POST below April 24:....
It's been 3 days with trial-n-error and research:
My Environment: LAMP using facebook sdk 3 & CodeIgniter 2
Login Code:
$CI->load->library('facebook', array("appId"=>APP_ID, "secret"=>APP_SECRET));
$this->visitor['access_token'] = $CI->facebook->getAccessToken();
$fb_id = $CI->facebook->getUser();
var_dump($CI->facebook); // see picture above
var_dump($fb_id); // == 0
if ($fb_id && $fb_id > 0) {
$temp = $CI->users->getUserByFb($fb_id);
if (!$temp) {
$this->insertFBUser($fb_id);
$this->visitor['redirect'] = "?prompt=newfb";
} else {
$this->visitor = array_merge($this->visitor, $temp);
if (isset($this->visitor['user_allowed']) && $this->visitor['user_allowed'] == 0) {
$CI->users->updateUser(array("user_allowed" => 1), $this->visitor['user_id']);
}
}
} else {
array_push($this->errors, $CI->input->get_post("error_msg", false));
array_push($this->errors, $CI->input->get_post("error_code", false));
array_push($this->errors, $CI->input->get_post("error_reason", false));
array_push($this->errors, $CI->input->get_post("error", false));
array_push($this->errors, $CI->input->get_post("error_description", false));
if ($CI->input->get_post("autoclose", false) == true) {
array_push($this->errors, "javascript stackoverflow is encoding weird, but basically changes the hashtag of the pop-window, so the parent page automatically closes it");
}
var_dump($this->errors);
die("nada");
}
Research & Debugging:
This post describes my problem as well, but the solution did not work: stackoverflow.com/questions/8587098/suddenly-getuser-became-to-return-0-php-3-1-1-sdk with or without the trailing comma in the DROP_QUERY_PARAMS array on this page.
Facebook is sending me NO error messages in the url, post, or session and scraping my page fine
EVERYTHING worked fine a few days ago and i've changed very little around this code.
The login now fails whether i use http or https
The popup link opens at:
www.facebook.com/dialog/oauth?client_id=222912307731474&redirect_uri=https%3A%2F%2Ftrackauthoritymusic.com%2Fmanage%2Fusers%2Flogin%3Fautoclose%3Dtrue&state=4522cb9da5bf5107d690a22eee6c5a2e&scope=email&display=popup while redirecting successfully to my desired login url with both state and code parameters apparently valid: trackauthoritymusic.com/manage/users/login?autoclose=true&state=4522cb9da5bf5107d690a22eee6c5a2e&code=AQBfSkI4y_VxhCuF3coVvNmjetdGZjugyFv0UsLlKt5sR5MEGdY8KqpDXZKvqHTGaSHhzY4pHXuR_zmilkwmoQ5y6M9jh15GPI6DXz5E2fSBizAVlrlebriNGcNZb4DRaDFK8cxPJoa9xB2ERuimtuizmlZERNa8hwJxLXtztqkWWhkLFCaGjQvAyyf5jJRkuoztmvfKDIZz3W9lslM6fk_m
but at this point, the sdk cannot get any access token or facebook session data.
PLEASE HELP!

I fixed this by using codeigniter's input library within the Facebook SDK to get the code/token and all $_GET/$_POST/$_REQUEST globals.
See the git diff on the facebook sdk. I'm still not sure what i did to break thisthough. OAuth/Login WAS working consistently before a certain point. I'm sure this wasn't just some race condition on codeigniter occasionally clearing the globals
## -490,10 +490,11 ##
*/
public function getSignedRequest() {
if (!$this->signedRequest) {
- if (!empty($_REQUEST['signed_request'])) {
- $this->signedRequest = $this->parseSignedRequest(
- $_REQUEST['signed_request']);
- } elseif (!empty($_COOKIE[$this->getSignedRequestCookieName()])) {
+ $CI = & get_instance();
+ $signed_request = $CI->input->get_post("signed_request");
+ if (!empty($signed_request)) {
+ $this->signedRequest = $this->parseSignedRequest($signed_request);
+ } else if (!empty($_COOKIE[$this->getSignedRequestCookieName()])) {
$this->signedRequest = $this->parseSignedRequest(
$_COOKIE[$this->getSignedRequestCookieName()]);
}
## -691,15 +692,18 ##
protected function getCode() {
- if (isset($_REQUEST['code'])) {
- if ($this->state !== null &&
- isset($_REQUEST['state']) &&
- $this->state === $_REQUEST['state']) {
-
+ $CI = & get_instance();
+ $code = $CI->input->get_post("code");
+ if (!empty($code)) {
+ $state = $CI->input->get_post("state");
+ if ($this->state !== null && $state && $this->state === $state) {
// CSRF state has done its job, so clear it
$this->state = null;
$this->clearPersistentData('state');
- return $_REQUEST['code'];
+ return $code;
} else {
self::errorLog('CSRF state token does not match one provided.');
return false;
$params['access_token'] = $this->getAccessToken();
}

Related

Is it possible to use google recaptcha on client side without server side support? If possible how?

Currently, I am working on Nuxtjs 2 project in which I have to implement Recaptcha on the client side, I do not want backend support for Recaptcha. I want to handle it only on the front end. How can I do this on the front-end with or without any library that is compatible with nuxtjs2?
There is no reason to use reCAPTCHA without server.
reCAPTCHA is for protecting the backend from spam.
If you really want to do it, you can make the same request with JavaScript.
But again: Makes no sense.
reCAPTCHA validation for PHP:
function validate_captcha_response($code){
if($_SERVER['HTTP_HOST']=="localhost") return true;
if($code && strlen($code)>32){
$secret = "<your reCaptcha v3 secret>";
$ip = $_SERVER['REMOTE_ADDR'];
$gcaptcha = json_decode(file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=$secret&response=$code&remoteip=$ip"), true);
return ($gcaptcha['success'] == true && $gcaptcha['score'] >= 0.8 && $gcaptcha['hostname'] == $_SERVER['SERVER_NAME']);
}
return false;
}
The same code in JavaScript:
function validate_captcha_response(code){
if(window.location.hostname=="localhost") return true;
if(code && code.length>32){
let secret = "<your reCaptcha v3 secret>";
let gcaptcha = json_decode(file_get_contents(`https://www.google.com/recaptcha/api/siteverify?secret=${secret}&response=${code}`), true);
return (gcaptcha['success'] == true && gcaptcha['score'] >= 0.8 && gcaptcha['hostname'] == window.location.hostname);
}
return false;
}
(Please note I removed the IP functionality)
Code Source: https://www.custom-captcha.com/

CSS missing in the eyes of Google

When I load the website in a browser, it shows up correctly. However, when testing it with search.google.com it shows up without style sheets (and thereby not passing the test to be suitable for mobile devices). I assume it is because of the service worker I am using. However, I don't know that the problem is with it?
Below is the full code of the service worker in place:
const
_ = {
domain: 'https://matchflix.ch/',
name: 'matchflix'
},
cachable = [_.domain, 'https://fonts.googleapis.com/', 'https://ajax.googleapis.com/'],
log = 'ServiceWorker 1.1'
;
self.addEventListener('fetch', event => {
if(event.request.method !== 'GET')
return;
if(!event.request.referrer.startsWith(_.domain))
return;
if(!cachable.some(url => event.request.url.startsWith(url)))
return;
function versionedURL(request){
switch(request.destination){
case 'image':
case 'script':
case 'style':
let
version = self.serviceWorker.scriptURL.split('?')[1]
;
return new Request(request.url + '?' + version);
default:
return request;
}
}
let
internal = event.request.url.startsWith(_.domain),
request = internal ? versionedURL(event.request) : event.request
;
event.respondWith(caches.open(_.name)
.then(cache => fetch(request)
.then(response => {
console.debug(log, 'Caching', internal, response, request);
if(internal)
cache.put(request, response.clone());
return response;
})
.catch(() => cache.match(request))
)
);
});
This is how the website looks in the eyes of Google:
What I tried so far
Commenting out the registration of the service worker, did not change anything unfortunately.
On search.google.com I saw under more information that there was an unknown error loading the script and style sheets. Unfortunately, no further information was given.
Your site is too slow. The entire page, including all assets needs to load within about 5 seconds so that Googlebot doesn't give up on rendering. I'm opening your site now and the spinner is still going after 30 seconds.

Symfony3 add locale in deeplink

I create a new site in symfony3 following the getting started section in the official symfony documentation in https://symfony.com/doc/current/setup.html
Everything is working ok.. if I put mydomain.com as the URL, the framework add /en or the correct local.
My question is if there is a way that if the user do a deeplink to mydomain.com/blog the framework found that the local is not present so it can add and transform the url to mydomain.com/en/blog
I'm not adding the code as it is the default one. Let me know if you need it.
There are multiple ways to do this. Probably the easiest is to have an EventSubscriber or -Listener that catches request without a locale and then handles adding that information. Since you based your project on the demo application you might want to look at their solution: https://github.com/symfony/demo/blob/master/src/EventSubscriber/RedirectToPreferredLocaleSubscriber.php
The steps to perform in your event handler are roughly these:
Listen to kernel.request event
Return early based on some criteria, e.g. homepage, a cookie with the language is set, or something else
Detect the language either by getting the default locale or determining from your available locales and the browser header which language fits best (see: https://github.com/willdurand/Negotiation#language-negotiation)
Redirect, add the locale as attribute to request, write the currently set language to a cookie, or whatever else you need to do to change the route
Thanks to #dbrumann I get to this solution... For sure it can be improve to use less code but it just did the trick.
I updated the onKernelRequest method in RedirectToPreferredLocaleSubscriber class
public function onKernelRequest(GetResponseEvent $event): void
{
$request = $event->getRequest();
$path = explode('/',$request->getPathInfo());
$hasLocale = false;
foreach ($this->locales as $key => $l) {
if($l == $path[1]){
$hasLocale = true;
}
}
if(!$hasLocale){
// Ignore sub-requests and all URLs but the homepage
if (!$event->isMasterRequest() || '/' !== $request->getPathInfo()) {
$preferredLanguage = $request->getPreferredLanguage($this->locales);
if ($preferredLanguage !== $this->defaultLocale) {
$url = "";
foreach ($path as $key => $p) {
if($key > 0){
$url .= "/" . $p;
}
}
//print_r('/' . $preferredLanguage . $url);exit;
$response = new RedirectResponse('/' . $preferredLanguage . $url);
$event->setResponse($response);
}
}
else{
// Ignore requests from referrers with the same HTTP host in order to prevent
// changing language for users who possibly already selected it for this application.
if (0 === mb_stripos($request->headers->get('referer'), $request->getSchemeAndHttpHost())) {
return;
}
$preferredLanguage = $request->getPreferredLanguage($this->locales);
if ($preferredLanguage !== $this->defaultLocale) {
$response = new RedirectResponse($this->urlGenerator->generate('homepage', ['_locale' => $preferredLanguage]));
$event->setResponse($response);
}
}
}
}

Apigee 401 Unauthorized with token_expired

I'm trying to create a user account through the apigee JS API. This worked just fine when I was last doing this before the holidays in mid December. Now, however, I get a 401 Unauthorized error reading token_expired.
Is there a way to refresh the token? I don't know why it would have expired.
This is what I'm trying. First I instantiate the data client. No problems here:
var dataClient;
var client_creds = {
orgName: '*******',
appName: '*******'
}
dataClient = new Apigee.Client(client_creds);
Later, when trying to create a new user, I get the token_expired error:
dataClient.request(options, function (error, response) {
if (error) {
console.log(response);
alert("Something went wrong when trying to create the user. " + response.error)
// Error
} else {
// Success - the user has been created, now login.
dataClient.login(user.email, user.password,
function (err) {
if (err) {
//error - could not log user in
console.log("There was an error logging in " + user.name);
} else {
//success - user has been logged in
}
}
);
}
});
I've also tried dataClient.signup, but same error.
There are no refresh tokens within App Services; you'll need to follow the login flow in order to retrieve a new token. Note that you can specify the ttl parameter, like so, so you don't need to do this as frequently:
https://api.usergrid.com/{org}/{app}/token?ttl=604800
By default, this is set to 7 days, but you can change the default app max ttl to 0 (non-expiring) or something else like 31104000000 (365 days).
To do that, you make a PUT request:
https://api.usergrid.com/{org}/{app}/?client_id={app_client_id}&client_secret={app_client_secret}
With JSON payload:
{
"accesstokenttl":0
}
Or for 1 year:
{
"accesstokenttl":31104000000
}
If that doesn't work for you, the authorization tokens for the JavaScript SDK are kept in your browser's local storage. In Chrome, use the Developer Tools. In the Resources tab on the left hand side expand the Local Storage entry. You should see something like "http://usergrid.dev" or something similar. Choose that and on the right hand side you should see an entry for accessToken. Delete that and it should solve your problem.

sandbox paypal La transaction a expire

Here's the correct translation for this question, which was originally asked in french. Note that I have taken liberty to translate the comments in the code.
My procedure worked correctly during tests in my sandbox. When I put it into operational mode, it still worked correctly. Then I added a check in my code to prevent access to the sandbox version by copy/pasting the URL. Now my website works correctly in operational mode, but my sandbox vresion doesn't work anymore.
Link to operational mode.
Link to sandbox mode.
The procedure:
//
// VENDOR PARAMETERS FOR SANDBOX VERSION
//
if ($proctest == "1")
{
$url_nvp = 'https://api-3t.sandbox.paypal.com/nvp'; // Sandbox version
$version = 64.0; // Version
$iduser = 'f-facilitator_api1.x.fr'; // User
$passwrd = '0123456789'; // Password
// Signature
$signature = 'AFcWxV21C7fd0v3bYYYRCpSSRl31ALWKEzeddmFHrClYoc6tJpZiawjH';
}
//
// VENDOR PARAMETERS FOR OPERATIONAL VERSION
//
else
{
$url_nvp = 'https://api-3t.paypal.com/nvp'; // Operational website
$version = 64.0; // Version
$iduser = 'f_api1.x.fr'; // User
$passwrd = '0123456789'; // Password
// Signature
$signature = 'Apekq0Tf.isqMqkIsEX7RsjIFTVCA8EehX5M263oELbE40NBWWYxhtW1';
}
//
// BUILDING THE STRING
//
$api_paypal= $url_nvp.'?VERSION=' .$version // Builds the URL
.'&USER=' .$iduser
.'&PWD=' .$passwrd
.'&SIGNATURE=' .$signature;
return $api_paypal; // Returns the string
}
Then:
//
// TEST ENVIRONMENT FOR NVP'S API
//
if ($proctest == "1")
{
header("Location: https://www.sandbox.paypal.com/webscr&cmd=_express-checkout&token=".$liste_param_paypal['TOKEN']);
}
//
// OPERATIONAL ENVIRONMENT FOR NVP'S API
//
else
{
header("Location: https://www.paypal.com/webscr&cmd=_express-checkout&token=".$liste_param_paypal['TOKEN']);
}
I can't find what prevents the sandbox version from running correctly.

Resources