arguments when using the PHP Facebook API Graph library? - facebook-graph-api

I am trying to pull some statuses in json format from Facebook's Graph API. Since i am using PHP, so I went for the following library.
https://github.com/facebook/facebook-php-sdk/blob/master/examples/example.php
I saw the example, and the class requires some arguments upon instantiation, and I just don't know what they are:
// Create our Application instance (replace this with your appId and secret).
$facebook = new Facebook(array(
'appId' => '344617158898614',
'secret' => '6dc8ac871858b34798bc2488200e503d',
));
And also from the Graph API Explorer I see the access_token, but this PHP library doesn't mention it at all, I thought I need the access_token to make requests, don't I? I hope someone can clear things up for me.

Yes you require an access_token to query on behalf of user on Facebook, it can either be an App access token or User access token. If the user authorizes your app, with required permission which in your case would be read_stream permission, then you can obtain his access token and query for status updates. The default access token is your App access token which can access only public data.
Also I would suggest you to to over the PHP SDK documentation for getting started with it.

Related

Facebook Api Check Access Token Without Hardcoding App Secret

I'm building a manual login flow for my App which is integrating some facebook functionality.
I need to check when the current access_token of the user will expire.
The API documentary says I should do this call:
GET graph.facebook.com/debug_token?
input_token={token-to-inspect} &access_token={app-token-or-admin-token}
So I did this in C#:
Uri inspectAccessTokenUri = new Uri("http://graph.facebook.com/debug_token?input_token="+access_token+"&"); //IDK which value should have the last parameter
HttpWebRequest checkToken = (HttpWebRequest)WebRequest.Create(inspectAccessTokenUri);
var response = await checkToken.GetResponseAsync();
Stream stream = response.GetResponseStream();
StreamReader reader = new StreamReader(stream);
string data = reader.ReadToEnd();
Debug.WriteLine(data);
The last parameter should be the app-token:
BUT: Of course I looked up how to get the app-token and facebook says:
Note that because this request uses your app secret, it must never be
made in client-side code or in an app binary that could be decompiled.
It is important that your app secret is never shared with anyone.
Therefore, this API call should only be made using server-side code.
(Facebook Graph API Documentation 1.1.16)
So my question: Can I check the token without the app-token or hardcoding the app-secret?
App secret is usually used by the server-side app, we don't use it in our UWP app, it could be decompiled.
Read the official doc about FB Graph Debug-Token, this can only be used when you debug your app, for example if you want to check the metadata about a given access token, after you publish your app, your code will not relay on it.
In an UWP app, we use WebAuthenticationBroker class to connect to OAuth providers such as Facebook, Flickr, Google, and Twitter. Maintenance is need during using OAuth connections. For example, expires information is included in the access token, when we use OAuth protocol for authentication and authorization, we need to refresh the access token after it expired.
Due to these conditions, you may reconsider what you can do in an UWP app and which API you should choose.
If the app-token is expired you will get a facebook response error. And you can catch this exception to deal with the situation you want. In this way you don't need to make a request with your app secret.
You can also use fb-uwp sdk that contains AccessTokenData for authenticated users

Retrieve Facebook profile from Xamarin client

I would like to get basic user information from Facebook after the user has logged in.
I've looked at the documentation in How to: Work with authentication and under the "How to: Retrieve authenticated user information" section, it shows how to do it from the .NET backend code by using an HttpClient to make the call with the AccessToken:
var fbRequestUrl = "https://graph.facebook.com/me/feed?access_token="
+ credentials.AccessToken;
Since the mobile client has the accessToken that we get from MobileServices, can the client make the call directly to a Facebook endpoint, or does the client SDK provide us with any built-in functionality?
I've been following the Xamarin.Forms Sport project and the way they get the user information from Google is by hard-coding the Google endpoint and making a call to get the user info.
Note: Xamarin.Forms Sport uses Mobile Services, not Mobile App, so not sure if that makes any difference.
It sounds like you're doing the server-directed login: where you are making a call to your backend to do the login dance with Facebook. In this, your client application is making a GET call to .auth/login/facebook, which opens up a browser or the Web Authentication Broker where you enter your credentials. The end result is you will receive a Zumo access token (different from Facebook access token).
You cannot use the Zumo access token to access Facebook APIs by itself. In the "How To:" you linked, we show you how to use GetAppServiceIdentityAsync from the backend to get the Facebook access token. This is possible because you have stored your Facebook client ID via portal, which is available to the backend.
The advantage of doing auth like this was that you don't have to deploy your Facebook Client Id with your mobile apps. If you wanted to access the Facebook APIs from the client, though, you'll need to get the Facebook token to the client.
Few ways I can suggest:
Call .auth/me from your client. The response will give you a JSON object you can parse that should include the FB token associated with your Zumo token.
Write a custom API with [Authorize] attribute set that will perform GetAppServiceIdentityAsync and respond with the value of the facebook access token. You can then parse the response from your client. This is basically what .auth/me does, but you can write it to give back only your FB access token.
Use the Facebook .NET SDK http://facebooksdk.net/ to do client-directed login. You will get a Facebook token on your client, and then you can use our LoginAsync(Facebook, access_token) method to get a Zumo token so that your client can access both Facebook and your Mobile App backend. The disadvantage, as I mentioned before, is that you'll have to deploy your FB Client ID with your app.

Generate an OAuth2 token in a view

Let's say I have an AngularJS application that consumes the REST API of a Django application.
The Django application has got a built-in OAuth2 provider that can be called to retrieve an access token and use the protected endpoints of the API. This provider is using django-oauth-toolkit.
Let's assume there is a registered client with "password" grant type, so that the end users only need to provide their credentials in the front-end in order to get an access token from the back-end.
At some point we want to add some support for social networks login and we decide to use python-social-auth (PSA) to that end. Here is the workflow I want to achieve:
The user logs in on Facebook from the front-end (via the Facebook SDK) and we get an access token back from the OAuth2 provider of Facebook.
We send the Facebook token to an endpoint of our REST API. This endpoint uses the Facebook token and django-social-auth to authenticate the user in our Django application (basically matching a Facebook account to a standard account within the app).
If the authentication succeeds, the API endpoint requests an access token from the OAuth2 provider for this newly authenticated user.
The Django access token is sent back to the front-end and can be used to access the REST API in exactly the same way that a regular user (i.e. logged in with his credentials) would do.
Now my problem is: how do I achieve step 3? I first thought I would register a separate OAuth2 client with Client Credentials Grant but then the generated token is not user-specific so it does not make sense. Another option is to use the TokenAuthentication from DRF but that would add too much complexity to my project. I already have an OAuth server and I don't want to set up a second token provider to circumvent my problem, unless this is the only solution.
I think my understanding of PSA and django-oauth-toolkit is not deep enough to find the best way of reaching my goal, but there must be a way. Help!
I managed to get something working using urllib2. I can't speak towards whether or not this is good practice, but I can successfully generate an OAuth2 token within a view.
Normally when I'd generate an access token with cURL, it'd look like this:
curl -X POST -d "grant_type=password&username=<user_name>&password=<password>" -u"<client_id>:<client_secret>" http://localhost:8000/o/token/
So we're tasked with making urllib2 accomplish this. After playing around for some bit, it is fairly straightforward.
import urllib, urlib2, base64, json
# Housekeeping
token_url = 'http://localhost:8000/auth/token/'
data = urllib.urlencode({'grant_type':'password', 'username':<username>, 'password':<password>})
authentication = base64.b64encode('%s:%s' % (<client_id>, <client_secret>))
# Down to Business
request = urllib2.Request(token_url, data)
request.add_header("Authorization", "Basic %s" % authentication)
access_credentials = urllib2.urlopen(request)
json_credentials = json.load(access_credentials)
I reiterate, I do not know if this is in bad practice and I have not looked into whether or not this causes any issues with Django. AFAIK this will do this trick (as it did for me).

Retrieving Linkedin Group discussion posts using ColdFusion

I have been requested by a client to pull the latest posts from their LinkedIn group to one of our website pages.
I am developing using ColdFusion 9 and have been researching this for quite a few days now and decided to post my query here in the hopes that someone will be able to help me out.
I can get to the point where I have a requestToken. My understanding is that I now need to sign the request token to get the accessToken. My problem is that I need to do this behind-the-scenes. However, all the examples that I can find are redirecting the front-end user to the authorisation url to allow the user to authenticate, but I don't want the user to authenticate, I want to authenticate server-side instead.
I am trying to use the Scribe Java wrapper library. Below is the code that I have so far which gets the requestToken (as well as the authorisation url). I need someone to point me in the right direction to sign the token on the server-side code so that I can make the necessary calls to consume the Groups API (e.g. http://api.linkedin.com/v1/groups/{id}/posts?count=5&start=1)
<cfscript>
var l = {};
//The LinkedIn public and private keys for application
l.oauth_consumer_key = "[My public key]";
l.oauth_sign_key = "[My secret key]";
l.serviceBuilder = CreateObject("java","org.scribe.builder.ServiceBuilder");
l.LinkedInApiClass = CreateObject("java", "org.scribe.builder.api.LinkedInApi").getClass();
l.service = l.serviceBuilder.provider(l.LinkedInApiClass).apiKey(l.oauth_consumer_key).apiSecret(l.oauth_sign_key).callback("[My callback url]").build();
l.requestToken = l.service.getRequestToken();
l.authUrl = l.service.getAuthorizationUrl(l.requestToken);
// I NEED TO DEFINE WHAT TO DO AT THIS POINT TO SIGN THE REQUEST SERVER SIDE
...
...
</cfscript>
Kirsten is technically correct - Linked In Api's require user authentication. It's annoying because you need to authenticate to even retrieve group posts.
However there are ways round it.
With scribe you can manually create an access token. So what I would do is create a dummy user account on Linked In, authenticate that user as normal and save the returned signed credentials on your database, which you can then use to create the token:
var accessToken = createObject("java", "org.scribe.model.Token").init(
"singedTokenStringReturnBackFromLinkedIn",
"singedSecretStringReturnBackFromLinkedIn",
"oauth_token=singedTokenStringReturnBackFromLinkedIn&oauth_token_secret=singedSecretStringReturnBackFromLinkedIn&oauth_expires_in=0&oauth_authorization_expires_in=0"
);
You can then skip the authenticate part and call the api allowing you to display the group posts without the current user having to sign in:
var req = createObject("java", "org.scribe.model.OAuthRequest").init(
createObject("java", "org.scribe.model.Verb").GET,
"http://api.linkedin.com/v1/groups/123456/posts"
);
oAuthService.signRequest(accessToken, req);
I have no idea if this would violate Linked In's T&C though.
OAuth authentication is designed for the user to give their permission to the application via a login on the site (in this case LinkedIn). It is not designed for you to automatically have the user grant permission for your application.
In order to get an access token to use the LinkedIn APIs, you have to include the part of the authentication flow that sends the user to LinkedIn to give your application permission to act on their behalf, at which point you can retrieve a verifier token either via PIN (which the user inputs) or via a callback to your application.
In short, there is no way to "authenticate server-side" without having the user interact with the LinkedIn site.

How can I verify a Google authentication API access token?

How can I verify a Google authentication access token?
I need to somehow query Google and ask: Is [given access token] valid for the [example#example.com] Google account?
Short version
It's clear how an access token supplied through the Google Authentication Api :: OAuth Authentication for Web Applications can be used to then request data from a range of Google services. It is not clear how to check if a given access token is valid for a given Google account. I'd like to know how.
Long version
I'm developing an API that uses token-based authentication. A token will be returned upon provision of a valid username+password or upon provision of a third-party token from any one of N verifiable services.
One of the third-party services will be Google, allowing a user to authenticate against my service using their Google account. This will later be extended to include Yahoo accounts, trusted OpenID providers and so on.
Schematic example of Google-based access:
The 'API' entity is under my full control. The 'public interface' entity is any web- or desktop-based app. Some public interfaces are under my control, others will not be and others still I may never even know about.
Therefore I cannot trust the token supplied to the API in step 3. This will be supplied along with the corresponding Google account email address.
I need to somehow query Google and ask: Is this access token valid for example#example.com?
In this case, example#example.com is the Google account unique identifier - the email address someone uses to log in to their Google account. This cannot be assumed to be a Gmail address - someone can have a Google account without having a Gmail account.
The Google documentation clearly states how, with an access token, data can be retrieved from a number of Google services. Nothing seems to state how you can check if a given access token is valid in the first place.
Update
The token is valid for N Google services. I can't try a token against a Google service as means of verifying it as I won't know which subset of all Google's services a given user actually uses.
Furthermore, I'll never be using the Google authentication access token to access any Google services, merely as a means of verifying a supposed Google user actually is who they say they are. If there is another way of doing this I'm happy to try.
For user check, just post
get the access token as accessToken and post it and get the response
https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=accessToken
you can try in address bar in browsers too, use httppost and response in java also
response will be like
{
"issued_to": "xxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com",
"audience": "xxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com",
"user_id": "xxxxxxxxxxxxxxxxxxxxxxx",
"scope": "https://www.googleapis.com/auth/userinfo.profile https://gdata.youtube.com",
"expires_in": 3340,
"access_type": "offline"
}
The scope is the given permission of the accessToken. you can check the scope ids in this link
Update:
New API
post as below
https://oauth2.googleapis.com/tokeninfo?id_token=XYZ123
Response will be as
{
// These six fields are included in all Google ID Tokens.
"iss": "https://accounts.google.com",
"sub": "110169484474386276334",
"azp": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com",
"aud": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com",
"iat": "1433978353",
"exp": "1433981953",
// These seven fields are only included when the user has granted the "profile" and
// "email" OAuth scopes to the application.
"email": "testuser#gmail.com",
"email_verified": "true",
"name" : "Test User",
"picture": "https://lh4.googleusercontent.com/-kYgzyAWpZzJ/ABCDEFGHI/AAAJKLMNOP/tIXL9Ir44LE/s99-c/photo.jpg",
"given_name": "Test",
"family_name": "User",
"locale": "en"
}
For more info, https://developers.google.com/identity/sign-in/android/backend-auth
Ok, most answers are valid but not quite right. The idea of JWT is that you can validate the token without the need to contact the issuer everytime. You must check the id and verify the signature of the token with the known public key of the certificate google used to sign the token.
See the next post why and how to do this.
http://ncona.com/2015/02/consuming-a-google-id-token-from-a-server/
you can verify a Google authentication access token by using this endpoint:
https://www.googleapis.com/oauth2/v3/tokeninfo?access_token=<access_token>
This is Google V3 OAuth AccessToken validating endpoint, you can refer from google document below: (In OAUTH 2.0 ENDPOINTS Tab)
https://developers.google.com/identity/protocols/OAuth2UserAgent#validate-access-token
function authenticate_google_OAuthtoken($user_id)
{
$access_token = google_get_user_token($user_id); // get existing token from DB
$redirecturl = $Google_Permissions->redirecturl;
$client_id = $Google_Permissions->client_id;
$client_secret = $Google_Permissions->client_secret;
$redirect_uri = $Google_Permissions->redirect_uri;
$max_results = $Google_Permissions->max_results;
$url = 'https://www.googleapis.com/oauth2/v1/tokeninfo?access_token='.$access_token;
$response_contacts = curl_get_responce_contents($url);
$response = (json_decode($response_contacts));
if(isset($response->issued_to))
{
return true;
}
else if(isset($response->error))
{
return false;
}
}
Use the below endpoint to get user info such as name, email, photo etc.
https://www.googleapis.com/oauth2/v3/userinfo?access_token=<access token>
Use the below endpoint to get token info, such as expiry time, token scope etc.
https://www.googleapis.com/oauth2/v3/tokeninfo?access_token=<access token>
Google oauth code flow response in addition to access_token also returns id_token that contains useful for validation info in encrypted form.
One thing that makes ID tokens useful is that fact that you can pass
them around different components of your app. These components can use
an ID token as a lightweight authentication mechanism authenticating
the app and the user. But before you can use the information in the ID
token or rely on it as an assertion that the user has authenticated,
you must validate it.
Validation of an ID token requires several steps:
Verify that the ID token is a JWT which is properly signed with an appropriate Google public key.
Verify that the value of aud in the ID token is equal to your app’s client ID.
Verify that the value of iss in the ID token is equal to accounts.google.com or https://accounts.google.com.
Verify that the expiry time (exp) of the ID token has not passed.
If you passed a hd parameter in the request, verify that the ID token has a hd claim that matches your Google Apps hosted domain.
https://developers.google.com/identity/protocols/OpenIDConnect#validatinganidtoken link has code samples for validation of ID tokens.
See also https://security.stackexchange.com/questions/37818/why-use-openid-connect-instead-of-plain-oauth.
As per Google's documentation, you should use Google's AP Client Library that makes this (token verification, claim extraction etc.) much easier than writing your own custom code.
From a performance perspective, the token should be parsed locally without making a call to Google again. Off-course Google's public key is needed and retrieval of that key is done using a caching strategy, implemented in the Google's client library from #1 above.
FYI only. Google also uses a JWT token. See image below for reference.
Here's an example using Guzzle:
/**
* #param string $accessToken JSON-encoded access token as returned by \Google_Client->getAccessToken() or raw access token
* #return array|false False if token is invalid or array in the form
*
* array (
* 'issued_to' => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com',
* 'audience' => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com',
* 'scope' => 'https://www.googleapis.com/auth/calendar',
* 'expires_in' => 3350,
* 'access_type' => 'offline',
* )
*/
public static function tokenInfo($accessToken) {
if(!strlen($accessToken)) {
return false;
}
if($accessToken[0] === '{') {
$accessToken = json_decode($accessToken)->access_token;
}
$guzzle = new \GuzzleHttp\Client();
try {
$resp = $guzzle->get('https://www.googleapis.com/oauth2/v1/tokeninfo', [
'query' => ['access_token' => $accessToken],
]);
} catch(ClientException $ex) {
return false;
}
return $resp->json();
}
I need to somehow query Google and ask: Is this access token valid for example#example.com?
No. All you need is request standard login with Federated Login for Google Account Users from your API domain. And only after that you could compare "persistent user ID" with one you have from 'public interface'.
The value of realm is used on the Google Federated Login page to identify the requesting site to the user. It is also used to determine the value of the persistent user ID returned by Google.
So you need be from same domain as 'public interface'.
And do not forget that user needs to be sure that your API could be trusted ;) So Google will ask user if it allows you to check for his identity.
Try making an OAuth-authenticated request using your token to https://www.google.com/accounts/AuthSubTokenInfo. This is only documented to work for AuthSub, but it works for OAuth too. It won't tell you which user the token is for, but it will tell you which services it's valid for, and the request will fail if the token is invalid or has been revoked.
An arbitrary OAuth access token can't be used for authentication, because the meaning of the token is outside of the OAuth Core spec. It could be intended for a single use or narrow expiration window, or it could provide access which the user doesn't want to give. It's also opaque, and the OAuth consumer which obtained it might never have seen any type of user identifier.
An OAuth service provider and one or more consumers could easily use OAuth to provide a verifiable authentication token, and there are proposals and ideas to do this out there, but an arbitrary service provider speaking only OAuth Core can't provide this without other co-ordination with a consumer. The Google-specific AuthSubTokenInfo REST method, along with the user's identifier, is close, but it isn't suitable, either, since it could invalidate the token, or the token could be expired.
If your Google ID is an OpenId identifier, and your 'public interface' is either a web app or can call up the user's browser, then you should probably use Google's OpenID OP.
OpenID consists of just sending the user to the OP and getting a signed assertion back. The interaction is solely for the benefit of the RP. There is no long-lived token or other user-specific handle which could be used to indicate that a RP has successfully authenticated a user with an OP.
One way to verify a previous authentication against an OpenID identifier is to just perform authentication again, assuming the same user-agent is being used. The OP should be able to return a positive assertion without user interaction (by verifying a cookie or client cert, for example). The OP is free to require another user interaction, and probably will if the authentication request is coming from another domain (my OP gives me the option to re-authenticate this particular RP without interacting in the future). And in Google's case, the UI that the user went through to get the OAuth token might not use the same session identifier, so the user will have to re-authenticate. But in any case, you'll be able to assert the identity.
Check below URL. It works well. Its official document from Google itself.
Using one of the Google API Client Libraries (e.g. Java, Node.js, PHP, Python) is the recommended way to validate Google ID tokens.
https://developers.google.com/identity/sign-in/android/backend-auth#using-a-google-api-client-library