Facebook OAuth access_token error - facebook

Full code.
public function indexAction(){
echo 'Login met facebook ';
}
const FB_GRAPH_URL = "https://graph.facebook.com/";
public function fbloginAction() {
$fbCode = $this->_getParam("code");
$getStr = self::FB_GRAPH_URL. 'oauth/access_token?' .http_build_query(array(
'client_id' => 'APP_ID',
'type' => 'client_cred',
'client_secret' => 'SECRET_KEY',
'code' => $fbCode)
);
$accessToken = file_get_contents( $getStr );
krumo($accessToken) ;
$dbpath = "https://graph.facebook.com/me?$accessToken" ;
$cont = file_get_contents($dbpath ) ;
krumo($cont);
}
When i try make GET query to Facebook.
$dbpath = "https://graph.facebook.com/me?$accessToken" ;
$cont = file_get_contents($dbpath ) ;
I receive the error :
failed to open stream: HTTP request failed! HTTP/1.0 400 Bad Request
in /home.....
When paste manually the $dbpath value(path) to web browser, i got next error:
{
"error": {
"message": "An active access token must be used to query information about the current user.",
"type": "OAuthException",
"code": 2500
}
}
How fix that error?

You probably want to use the Server-Side Authentication flow. By checking the calls in the documentation it is quite clear, which of your calls are wrong.
First, your call to the oauth/access_token endpoint takes no argument 'type' => 'client_cred', but it needs the parameter for your redirect_uri again:
$getStr = self::FB_GRAPH_URL . 'oauth/access_token?' . http_build_query(array(
'client_id' => 'APP_ID',
'redirect_uri' => 'REDIRECT_URI',
'client_secret' => 'SECRET_KEY',
'code' => $fbCode)
);
Then, you can't just take the answer of this call as your access_token, as there is much more in it:
access_token=USER_ACCESS_TOKEN&expires=NUMBER_OF_SECONDS_UNTIL_TOKEN_EXPIRES
and you only want the access_token part of it:
$response = file_get_contents($getStr);
$params = null;
parse_str($response, $params);
$dbpath = "https://graph.facebook.com/me?access_token=" . $params['access_token'];

Related

How to request permission access from user without asking the user to insert information Google Sign-Up

I have implemented google sign-in for my web app, in which I've used this library: https://metacpan.org/pod/Google::RestApi::Auth::OAuth2Client to get the code value, the access token and after that the user's information (email, name, google-id).
My problem in this implementation is that the user is prompt for consent where he needs to insert his information (email and password) and I would like to redirect the user for consent where he is able to select the accounts, and not insert his information. I don't know if my implementation, where I make the GET request, is incorrect or if it is because of the library that I use.
In front-end, I have a form which calls a route that redirects to my back-end function 'on_google_login':
sub on_google_login {
my $self = shift;
my $redirect_name = $self->get_redirect_name();
$self->session(redirect => $redirect_name);
my $google = Google::RestApi::Auth::OAuth2Client->new(
client_id => $ENV{GOOGLE_CLIENT_ID},
client_secret => $ENV{GOOGLE_SECRET},
redirect_uri => $ENV{GOOGLE_BASE_URL} . '/google_callback'
);
my $url = $google->authorize_url(
display => 'page'
);
$self->redirect_to($url);
}
And this is my callback function, where I extract the 'code' and I request the user's information using the access token.
sub on_google_callback {
my $self = shift;
my $code = $self->req->param('code');
my $google = Google::RestApi::Auth::OAuth2Client->new(
client_id => $ENV{GOOGLE_CLIENT_ID},
client_secret => $ENV{GOOGLE_SECRET},
redirect_uri => $ENV{GOOGLE_BASE_URL} . '/google_callback'
);
if (not (defined $code)) {
return $self->render(text => 'Did not connect to Google');
}
my $redirect_name = $self->session('redirect') // 'home';
delete $self->session->{'redirect'};
my $access_token = $google->access_token($code)->access_token;
my $url = $ENV{GOOGLE_ENDPOINT} . $access_token;
my $request = HTTP::Request->new(GET => $url);
my $ua = LWP::UserAgent->new();
my $info = decode_json($ua->request($request)->content);
my ($google_id, $name, $mail) = ($info->{sub}, $info->{name}, $info->{email});
if (!defined $google_id) {
return $self->render(
template => 'validation/custom_error',
title => 'Error logging in with Google',
message => 'Sorry, something went wrong when attempting to log you in ' .
'with Google. Please try again and contact us in the chat if this ' .
'persists.',
status => 400);
}
my $found_user = $self->db->resultset('User')->by_mail($mail);
if ($found_user) {
return unless validate_user_can_login($self, $found_user);
return unless set_user_data_on_login($self, $found_user);
$self->redirect_to($redirect_name);
} else {
$self->session(name => $name);
$self->session(mail => $mail);
$self->redirect_to('/register');
}
return;
}

Slim 3: How to access user information from request headers

I am using Slim 3.1 and able to authenticate correctly i.e. able to generate the token and use it for another POST request. Now I want to parse the request header to extract the user information so I can identify which user have sent the request.
Here is my code to get the token.
$app->post('/login/token', function (Request $request, Response $response,
array $args) {
$input = $request->getParsedBody();
$now = new DateTime();
$future = new DateTime("+10 minutes");
$server = $request->getServerParams();
$jti = (new Base62)->encode(random_bytes(16));
$payload = [
"iat" => $now->getTimeStamp(),
"exp" => $future->getTimeStamp(),
"jti" => $jti,
"sub" => $input['username']
];
$sql = "SELECT * FROM user WHERE User_Name= :username";
$sth = $this->db->prepare($sql);
$sth->bindParam("username", $input['username']);
$sth->execute();
$user = $sth->fetchObject();
// verify email address.
if(!$user) {
return $this->response->withJson(['error' => true, 'message' => 'These credentials do not match our records.']);
}
// verify password.
if (!password_verify($input['password'],$user->User_Password)) {
return $this->response->withJson(['error' => true, 'message' => 'These credentials do not match our records.']);
}
$settings = $this->get('settings'); // get settings array.
//$token = JWT::encode(['User_ID' => $user->User_ID, 'username' => $user->User_Name], $settings['jwt']['secret'], "HS256");
$token = JWT::encode($payload, $settings['jwt']['secret'], "HS256");
return $this->response->withJson(['token' => $token, 'ACL' => $user->User_ACL]);
});
This returns me a token that I send in the following POST request
$app->group('/api', function(\Slim\App $app) {
$app->post('/createuser', function (Request $request, Response $response,
array $args) {
$headerValueArray = $request->getHeader('HTTP_AUTHORIZATION');
return $this->response->withJson(['success' => true, $token]);
});
});
The above POST request gives the following output
{
"success": true,
"0": ["Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1MzU4Mjk0OTUsImV4cCI6MTUzNTgzNjY5NSwianRpIjoiMWc5ZFM3dUNLbzl1blRQZzBmYjU2diIsInN1YiI6InN5c2FkbWluIn0.vo3FBPhBkhfA2y7AG-afmjfeEhygIYY7lIaaVNX5i5k"]
}
I need to parse this token to extract the user information to see if its the valid user to perform this operation.In other words, how I can decode the above token.
Any help here will be much appreciated!

How to Retrieve HTTP Status Code with Guzzle?

New to Guzzle/Http.
I have a API rest url login that answer with 401 code if not authorized, or 400 if missing values.
I would get the http status code to check if there is some issues, but cannot have only the code (integer or string).
This is my piece of code, I did use instruction here ( http://docs.guzzlephp.org/en/stable/quickstart.html#exceptions )
namespace controllers;
use GuzzleHttp\Psr7;
use GuzzleHttp\Exception\ClientException;
$client = new \GuzzleHttp\Client();
$url = $this->getBaseDomain().'/api/v1/login';
try {
$res = $client->request('POST', $url, [
'form_params' => [
'username' => 'abc',
'password' => '123'
]
]);
} catch (ClientException $e) {
//echo Psr7\str($e->getRequest());
echo Psr7\str($e->getResponse());
}
You can use the getStatusCode function.
$response = $client->request('GET', $url);
$statusCode = $response->getStatusCode();
Note: If your URL redirects to some other URL then you need to set false value for allow_redirects property to be able to detect initial status code for parent URL.
// On client creation
$client = new GuzzleHttp\Client([
'allow_redirects' => false
]);
// Using with request function
$client->request('GET', '/url/with/redirect', ['allow_redirects' => false]);
If you want to check status code in catch block, then you need to use $exception->getCode()
More about responses
More about allow_redirects
you can also use this code :
$client = new \GuzzleHttp\Client(['base_uri' 'http://...', 'http_errors' => false]);
hope help you

get the facebook reviews return error

I first get page token with facebook api
function createSession($app_id,$app_secret){
FacebookSession::setDefaultApplication(
$app_id,$app_secret
);
$testUserPermissions = array('user_actions.books','user_actions.fitness','user_actions.music','user_actions.news','user_actions.video','user_birthday','user_games_activity','user_groups','user_hometown','user_interests','user_location','user_relationship_details','user_religion_politics','user_tagged_places','user_videos','user_work_history','read_friendlists','read_page_mailboxes','manage_notifications','read_mailbox','publish_actions','read_stream', 'user_photos','manage_pages','public_profile','user_friends','email','user_about_me','user_activities','user_education_history','user_events','user_likes','user_relationships','user_status','user_website','read_insights','rsvp_event');
$testUserPath = '/' . $app_id . '/accounts/test-users';
#$testUserPath = '/100008488695640/accounts/test-users';
$params = array(
'installed' => true,
'name' => 'User test',
'locale' => 'zh_TW',
'permissions' => implode(',', $testUserPermissions),
);
echo var_dump($params);
$request = new FacebookRequest(new FacebookSession($app_id . '|' .$app_secret), 'POST', $testUserPath, $params);
$response = $request->execute()->getGraphObject();
echo var_dump($response);
#$testUserId = $response->getProperty('id');
$testUserAccessToken = $response->getProperty('access_token');
return new FacebookSession($testUserAccessToken);
}
this is my get token
then i use this token to get reviews
https://graph.facebook.com/v2.2/185342243407/ratings?field=open_graph_story&access_token=$token_value
but it return
{
"error": {
"message": "(#210) This call requires a Page access token.",
"type": "OAuthException",
"code": 210
}
}
how i can get the page token?
the token is not used?
Make sure you are REALLY using a Page Token. Put the Token in the Debugger and see if it´s a Page Token: https://developers.facebook.com/tools/debug/
More information about Tokens:
https://developers.facebook.com/docs/facebook-login/access-tokens/
http://www.devils-heaven.com/facebook-access-tokens/
When you request multiple permissions, some of them may work with the endpoint you are calling, and some of them may not, causing this 210 error.
In my case, adding profile_pic permission to /me?fields=id,first_name,last_name,email caused this error.

Unexpected error when tyring to get the payment transactions of a user

I always get an error when tyring to get the payment transactions of a user.
{
"error": {
"message": "An unexpected error has occurred. Please retry your request later.",
"type": "OAuthException",
"code": 2
}
}
I tried several approaches:
// approach 1
$response = $app['facebook']->api('/'.$app['user']['fbUserID'].'/payment_transactions', 'GET', [
//'request_id' => $order['requestID'],
'access_token' => $app['fb.app_id'].'|'.$app['fb.app_secret']
]);
// approach 2
$url = 'https://graph.facebook.com/'.$app['user']['fbUserID'].'/payment_transactions?fields=id&access_token='.$app['fb.app_id'].'|'.$app['fb.app_secret'];
$ch = curl_init();
$options = [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_TIMEOUT => 60,
CURLOPT_HTTPHEADER => array('Expect:'),
CURLOPT_CAINFO => DIR.'/vendor/facebook/php-sdk/src/fb_ca_chain_bundle.crt'
];
curl_setopt_array($ch, $options);
$result = curl_exec($ch);
curl_close($ch);
// approach 3
// like 2 but with a fresh access token
$appAccessToken = explode('=', file_get_contents('https://graph.facebook.com/oauth/access_token?client_id='.$app['fb.app_id'].'&client_secret='.$app['fb.app_secret'].'&grant_type=client_credentials'))[1];
Even in the Graph API Explorer I get this error. Only if I use the commandline it works:
$ curl 'https://graph.facebook.com/........./payment_transactions?access_token=.......|.........'
The user is an test user which is also a payment tester and made successfull test-purchases. The Local Currency Payments Breaking Changes are disabled.
What am I doing wrong?
You need to use an app access token to GET from that endpoint. See https://developers.facebook.com/docs/graph-api/reference/user#payment_transactions for details.