In my PHP application, users provide their own Facebook Application ID and Application Secret. I need to validate them and display nice error if they are invalid.
I already found a nice way to do it. I can make a request to https://graph.facebook.com/oauth/access_token?client_id=123456&client_secret=abcdefg&grant_type=client_credentials
If credentials are invalid, the response is as follows:
{
"error": {
"message": "Error validating application. Cannot get application info due to a system error.",
"type": "OAuthException",
"code": 101,
"fbtrace_id": "D8oHjJoc2Nc"
}
}
I'm confused about the ways to do it with PHP SDK. There's a neat get() method to make such a request, but I'm not sure how to send request without authorizing the application. This is what I did:
$app = new Facebook\FacebookApp( $app_id, $app_secret );
$access_token = $app->getAccessToken();
$query = http_build_query([
'client_id' => $app_id,
'client_secret' => $app_secret,
'grant_type' => 'client_credentials',
]);
$facebook = new Facebook\Facebook( [
'app_id' => $app_id,
'app_secret' => $app_secret,
'default_graph_version' => '2.5',
] );
$response = $facebook->get( '/oauth/access_token?' . $query, $access_token );
I'm getting the following error:
Unknown path components: /oauth/access_token
But even if it worked, it's strange to call it with any sender credentials. Is it possible to make an "anonymous" Facebook request with PHP SDK?
The SDK implicitly adds the API version number specified to the path in -> get(), so I think that's causing your error here because the underlying call is being made to /2.5/oauth/access_token (fails for me in a browser)
It should be /v2.5/oauth/access_token (works for me in a browser)
Update default_graph_version to v2.5 and try that
Related
I'm using Microsoft Graph Api (PHP->msGraph SDK) to create online meetings.
I'm Facing 403 error can someone help me out.
$clientId = "***********************************";
$clientSecret = "***********************************";
$tenantId = '***********************************';
$responseUri = "http://localhost:8888/moodle39";
$guzzle = new \GuzzleHttp\Client();
$url = 'https://login.microsoftonline.com/' . $tenantId . '/oauth2/v2.0/token';
$token = json_decode($guzzle->post($url, [
'form_params' => [
'client_id' => $clientId,
'client_secret' => $clientSecret,
'scope' => 'https://graph.microsoft.com/.default',
'grant_type' => 'client_credentials',
],
])->getBody()->getContents());
$accessToken = $token->access_token;
//Create a new Graph client.
$graph = new Graph();
$graph->setAccessToken($accessToken);
$onlinemeet->startDateTime = "2020-09-02T14:30:34.2444915";
$onlinemeet->endDateTime = "2020-09-02T15:30:34.2444915";
$onlinemeet->subject = "Test Meeting";
$jso = json_encode($onlinemeet);
$user = $graph->createRequest("POST", "/me/onlineMeetings")->addHeaders(array("Content-Type" => "application/json"))->attachBody($jso)->setReturnType(User::class) ->execute();
Exception - Client error: POST https://graph.microsoft.com/beta/me/onlineMeetings resulted in a 403 Forbidden response: { "error": { "code": "Forbidden", "message": "", "innerError": { "request-id": "bd43aa57-511e-4 (truncated...)
While creating an application in azure portal
under API permission i gave permission to access
GraphApi->Delegated Permissions->onlinemeetings.ReadWrite.
Can someone help me with a proper example or proper syntax in PHP.
Thankyou !!..
You cannot use the client credential flow to get the token to call the /me endpoint. For the client credential flow, it is usually used for server-to-server interactions that must run in the background and do not interact with the user immediately(No user logged in). For the /me endpoint, it is usually User login is required, so you should use auth code flow.
By the way, APIs under the /beta version in Microsoft Graph are subject to change. Use of these APIs in production applications is not supported. Therefore, it is recommended that you use the /v1.0 version.
please see:here.
Update:
There are many similar samples, I hope they can help you:
OAuth 2.0 PHP Sample Code.
Authentication and Authorization Using Auth0 in PHP.
I am using Microsoft graph API to retrieve my messages from Microsoft account using php SDK (https://github.com/microsoftgraph/msgraph-sdk-php).
My code sample is given below
<?php
// Autoload files using the Composer autoloader.
require_once __DIR__ . '/vendor/autoload.php';
use Microsoft\Graph\Graph;
use Microsoft\Graph\Model;
//get the access token to access graph api
$tenantId = "XXXXXX";
$clientId = "XXXXXXXXXXXX";
$clientSecret = "XXXXXXXXXXX";
$guzzleClient = new \GuzzleHttp\Client(array('curl' => array( CURLOPT_SSL_VERIFYPEER => false)));
$url = 'https://login.microsoftonline.com/' . $tenantId . '/oauth2/token?api-version=1.0';
$token = json_decode($guzzleClient->post($url, [
'form_params' => [
'client_id' => $clientId,
'client_secret' => $clientSecret,
'resource' => 'https://graph.microsoft.com/',
'grant_type' => 'client_credentials',
],
])->getBody()->getContents());
$accessToken = $token->access_token;
//get the messages of user
$graph = new Graph();
$graph->setAccessToken($accessToken);
$messages = $graph->createRequest("GET", "/me/messages")
->setReturnType(Model\User::class)
->execute();
print_r($messages); exit;
But it throws me error as shown below :
Fatal error: Uncaught GuzzleHttp\Exception\ClientException: Client error: GET https://graph.microsoft.com/v1.0/me/messages resulted in a 400 Bad Request response: { "error": { "code": "BadRequest", "message": "Current authenticated context is not valid for this request. (truncated...) in C:\wamp64\www\graph_api\vendor\guzzlehttp\guzzle\src\Exception\RequestException.php on line 113
Is this because of any permission problem to access the Graph API? I have the following permissions set in the Microsoft app registration portal
As well as in azure portal
What may cause this issue? Any way to solve the problem?
You are getting the exception:
Current authenticated context is not valid for this request
since the acquired token is for application permissions (client credentials flow). In this flow, there is no context for Me since it represents signed-in user context.
To get messages in client credentials flow user needs to be explicitly resolved in endpoint:
https://graph.microsoft.com/v1.0/users/{user-id}/messages
Example
$userId = "--user-id-goes-here--";
$messages = $graph->createRequest("GET", "/users/{$userId}/messages")
->setReturnType(\Microsoft\Graph\Model\User::class)
->execute();
I have tried a lot to find out my issue but no luck there.
I am using Guzzle for my authentication and it's giving me the token. So there is no issue. The problem is while i am trying to get data it is showing me
" An uncaught Exception was encountered
Type: GuzzleHttp\Exception\ClientException
Message: Client error: GET https://graph.microsoft.com/v1.0/me resulted in a 400 Bad Request response: { "error": { "code": "BadRequest", "message": "Current authenticated context is not valid for this request. (truncated...) "
Here is my code below
$url = 'https://login.microsoftonline.com/' . $tenantId . '/oauth2/token?api-version=1.0';
$token = json_decode($guzzle->post($url, [
'form_params' => [
'client_id' => $appId,
'client_secret' => $appSecret,
'resource' => 'https://graph.microsoft.com/',
'grant_type' => 'client_credentials',
],
])->getBody()->getContents());
$accessToken = $token->access_token;
$graph = new Graph();
$graph->setAccessToken($accessToken);
$user = $graph->createRequest("GET", "/me")
->setReturnType(Model\User::class)
->execute();
echo "Hello, I am $user->getGivenName() ";
Note: I have successfully got the token, and i am using CodeIgniter framework where CSRF is false. Also i have given the permission for the app User.Read.All, User.ReadWrite.All
Please help me out to solve of this problem.
Thanks in advance.
You cannot call /me using Client Credentials. The purpose of the Client Credentials is to authenticate an application without a user. Therefore there is no way for the API to translate which user you mean when you call /me.
Till 3 days ago, our login service was working fine. Now its broken by a unknown problem with Facebook oAuth.
Our app (built with React Native using native FBSDK), ask for Facebook for an Access Token and forward it to our API.
LoginManager.logInWithReadPermissions(['public_profile', 'email'])
Then, our API try to validate the token against Facebook Graph API. Basically we do this:
public static function getInformationFromFacebook($accessToken)
{
$facebook = new Facebook([
'app_id' => config('services.facebook.app_id'),
'app_secret' => config('services.facebook.app_secret'),
'default_graph_version' => config('services.facebook.default_graph_version'),
]);
try {
$response = $facebook
->get('/me?fields=first_name,last_name,email,picture.type(large)', $accessToken);
} catch (FacebookResponseException $e) {
Log::error(sprintf('Graph returned an error: %s', $e->getMessage()));
throw new \Exception("Facebook graph error.");
} catch (FacebookSDKException $e) {
Log::error(sprintf('Facebook SDK returned an error: %s', $e->getMessage()));
throw new \Exception("Facebook SDK error.");
}
$graph = $response->getGraphUser();
return [
'first_name' => $graph->getFirstName(),
'last_name' => $graph->getLastName(),
'email_address' => $graph->getEmail(),
'picture' => $graph->getPicture()->getUrl(),
];
}
This piece of code uses Laravel 5.2 running with PHP 7.2 with the native Facebook SDK.
The expected behavior is an array with the user data, but it only works at local environment, when we try to debug this on staging server, the scopes from the user's access token are lost.
We discovered that we scopes are lost using this Facebook debug tool
// The OAuth 2.0 client handler helps us manage access tokens
$oAuth2Client = $facebook->getOAuth2Client();
// Get the access token metadata from /debug_token
$tokenMetadata = $oAuth2Client->debugToken($accessToken);
echo '<h3>Metadata</h3>';
var_dump($tokenMetadata);die;
Basically, when we're at the local the scopes are
'scopes' =>
array (size=2)
0 => string 'email' (length=5)
1 => string 'public_profile' (length=14)
when we change the call to the staging environment, the result is
["scopes"]=>
array(0) {
}
We tried all kind of things, even updating our SDK.
I have been trying to implement a simple authentication flow using OAuthv1.a and bit bucket. My issue occurs when I make a request for access tokens using the previously supplied verifier and oauth_token. I am always given a 400 error with no real indication as to why.
Client error response
[status code] 400
[reason phrase] BAD REQUEST
[url] https://bitbucket.org/api/1.0/oauth/access_token?oauth_consumer_key=<snip>&oauth_nonce=fba24cfb3147ca7d32b3924fad43fd509bbb9bc1&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1381034857&oauth_token=fFz369NUmCHNyn7PGj&oauth_verifier=6724267371&oauth_version=1.0&oauth_signature=1H7%2Bvx0fVh2Sj%2FcDAE2QzkTx8us%3D
I am using the OauthPlugin class within guzzle to build signed parameters and submitting post requests as described in the documentation. Has anyone had an issue like this with any other OAuthv1 provider or Bit Bucket specifically?
$client = new Client('https://bitbucket.org/api/1.0/');
$oauth = new OauthPlugin( array(
'request_method' => OauthPlugin::REQUEST_METHOD_QUERY,
'consumer_key' => Config::get('oauthv1.key'),
'token' => Input::get('oauth_token'),
'verifier' => Input::get('oauth_verifier')
)
);
$client->addSubscriber($oauth);
$client->post('oauth/access_token')->send();
Even though the Bitbucket API documentation doesn't mention it, the call to the oauth/access_token endpoint also requires the consumer_secret and oauth_token_secret. The consumer secret is generated by Bitbucket when you create your app and should be stored in your config. You can get the oauth_token_secret from the response of the call to oauth/request_token. Just save it in the session so you can use it when getting the access token.
Request a request token:
$client = new Client('https://bitbucket.org/api/1.0');
$oauth = new OauthPlugin(array(
'consumer_key' => $app['bitbucket.key'],
'consumer_secret' => $app['bitbucket.secret'],
'callback' => 'http://mysite.local/callback',
));
$client->addSubscriber($oauth);
$response = $client->post('oauth/request_token')->send();
// Parse the response
parse_str($response->getBody(), $result);
// Save the token secret in the session
$app['session']->set('oauth_token_secret', $result['oauth_token_secret']);
// Redirect to Bitbucket to authorize the application
return $app->redirect(sprintf('https://bitbucket.org/api/1.0/oauth/authenticate?oauth_token=%s', $result['oauth_token']));
Request an access Token:
$token = $app['request']->get('oauth_token');
$verifier = $app['request']->get('oauth_verifier');
$tokenSecret = $app['session']->get('oauth_token_secret');
$client = new Client('https://bitbucket.org/api/1.0');
$oauth = new OauthPlugin(array(
'consumer_key' => $app['bitbucket.key'],
'consumer_secret' => $app['bitbucket.secret'],
'token' => $token,
'token_secret' => $tokenSecret,
'verifier' => $verifier,
));
$client->addSubscriber($oauth);
$client->post('oauth/access_token')->send();
// Parse the response
$response = parse_str($response->getBody(), $result);
// Get the access token
$accessToken = $result['oauth_token'];