Some usefull references
- FB Developer Page
- My Apps Page
- change username
- Web apps JS
- JS SDK
- APIs
- Graph API
- SDKs
- PHP SDK
- Access token with PHP
- Access Token with PHP from JS
- Android SDK
Sequence
-
On access of an url or in welcome page the Facebook Login button is shown. The user will click the FB button to login into the Java web application. On click of that button a Facebook URL will be invoked.
-
Facebook will validate the application ID and then will redirect to its login page.
- User will enter the FB login credentials and submit the form.
- Facebook will validate the credentials and then redirect back to the browser with a request to forward to the redirect_url.
- Redirect_url is the URL in our application which will take care of further processing.
-
Browser will call the redirect url.
-
Redirect URL page will again call the Facebook to request for access_token.
-
Facebook on validation success will respond back with access_token.
-
Redirect URL page will again call the Facebook to request for user data by sending the access_token.
-
Facebook on validating the access_token will respond back with user data requested.
-
Redirect URL page will forward to a page showing user data in the client browser.
Some usefull aspects
Test Users
The test user need to register as Facebook developer (if he not reregistered already)
Link: https://developers.facebook.com/async/registration/
After that he need to approve the request from the app
Then he need to approve the request at this link Link: https://developers.facebook.com/settings/developer/requests
Facebook adding tester users and admin is: (pending), what does that mean?
Found the answer, its a bit silly but if anyone else gets the same issue...
After you add a new user to the "Testers" he gets a notification that he must accept, so the "Pending" will go away, and the user will be activated.
This notification does not get to the Facebook home page, only to the "Developer section" of that user. As @rmp251 mentioned, that can be found on this page
Remove Apps Consent
https://www.facebook.com/settings/?tab=applications
Usefull rerences for FB app development
Graph API reference
https://developers.facebook.com/docs/graph-api
Graph API V16(latest as on 10-05-2023) changelog
https://developers.facebook.com/docs/graph-api/changelog/version16.0
Graph API Old (eg: V2.6) changelog
https://developers.facebook.com/docs/graph-api/changelog/archive/version2.6/
Graph Explorer Tool
https://developers.facebook.com/tools/explorer
Graph API permissions
https://developers.facebook.com/docs/permissions/reference/
-
Under
Settings >> Basic
- set
App domains
- get
App Id
andApp secret
Created App url will be likehttps://developers.facebook.com/apps/App-ID/settings/basic/
- Under
Website
>>Site URL
setpath of your loginRedirectURL
- set
composer require facebook/graph-sdk
- Under Products >> Facebook Login >> Settings
setValid OAuth Redirect URIs
- replace
App Id
,App secret
andOAuth Redirect URI
in the below code
Possible Errors
PHP Code for FB Login
This is based on this
<?php
require 'vendor/autoload.php';
session_start();
//session_destroy();exit;// uncomment this line for testing
$app_id = "YOUR_APP_ID";
$app_secret = "YOUR_APP_SECRET";
$OAuthRedirectURI = "YOUR_POST_LOGIN_URL";
$fb = new Facebook\Facebook([
'app_id' => $app_id,
'app_secret' => $app_secret,
'default_graph_version' => 'v2.5',
]);
$helper = $fb->getRedirectLoginHelper();
$permissions = ['email']; // optional
try {
if (isset($_SESSION['facebook_access_token'])) {
$accessToken = $_SESSION['facebook_access_token'];
}
else
{
$accessToken = $helper->getAccessToken();
}
} catch(Facebook\Exceptions\facebookResponseException $e) {
// When Graph returns an error
echo 'Graph returned an error: ' . $e->getMessage();
exit;
} catch(Facebook\Exceptions\FacebookSDKException $e) {
// When validation fails or other local issues
echo 'Facebook SDK returned an error: ' . $e->getMessage();
exit;
}
if (isset($accessToken)) {
if (isset($_SESSION['facebook_access_token'])) {
$fb->setDefaultAccessToken($_SESSION['facebook_access_token']);
}
else
{
// getting short-lived access token
$_SESSION['facebook_access_token'] = (string) $accessToken;
// OAuth 2.0 client handler
$oAuth2Client = $fb->getOAuth2Client();
// Exchanges a short-lived access token for a long-lived one
$longLivedAccessToken = $oAuth2Client->getLongLivedAccessToken($_SESSION['facebook_access_token']);
$_SESSION['facebook_access_token'] = (string) $longLivedAccessToken;
// setting default access token to be used in script
$fb->setDefaultAccessToken($_SESSION['facebook_access_token']);
}
// getting basic info about user
try {
$profile_request = $fb->get('/me?fields=name,first_name,last_name,email');
$requestPicture = $fb->get('/me/picture?redirect=false&height=200'); //getting user picture
$picture = $requestPicture->getGraphUser();
$profile = $profile_request->getGraphUser();
$fbid = $profile->getProperty('id'); // To Get Facebook ID
$fbfullname = $profile->getProperty('name'); // To Get Facebook full name
$fbemail = $profile->getProperty('email'); // To Get Facebook email
$fbpic = "<img src='".$picture['url']."' class='img-rounded'/>";
# save the user nformation in session variable
$_SESSION['fb_id'] = $fbid.'</br>';
$_SESSION['fb_name'] = $fbfullname.'</br>';
$_SESSION['fb_email'] = $fbemail.'</br>';
$_SESSION['fb_pic'] = $fbpic.'</br>';
echo "Done setting SESSION Vars!! go to <a href=\"profile.php\">Profile page</a> or <a href=\"fbAlbums.php\">Albums page</a>";
}
catch(Facebook\Exceptions\FacebookResponseException $e) {
// When Graph returns an error
echo 'Graph returned an error: ' . $e->getMessage();
session_destroy();
// redirecting user back to app login page
header("Location: ./");
exit;
} catch(Facebook\Exceptions\FacebookSDKException $e) {
// When validation fails or other local issues
echo 'Facebook SDK returned an error: ' . $e->getMessage();
exit;
}
// redirect the user to the profile page if it has "code" GET variable
if (isset($_GET['code'])) {
//die('Location: profile.php');
header('Location: profile.php');
}
}
else
{
// replace your website URL same as added in the developers.Facebook.com/apps e.g. if you used http instead of https and you used
//$loginUrl = $helper->getLoginUrl('https://phpstack-21306-56790-161818.cloudwaysapps.com', $permissions);
$loginUrl = $helper->getLoginUrl($OAuthRedirectURI, $permissions);
echo '<a href="' . $loginUrl . '">Log in with Facebook!</a>';
}
?>
With Android
Reference
Reference
FBLoginSample on GitHub
Getting Hash Key for debugging
Getting Hash Key for release
Invalid key hash. The key hash does not match any stored key hashes
Hash Key issue
Solution:
- Note the new Key shown in the error message .
- copy it in FB developer console
- try again
keytool -exportcert -alias YOUR_RELEASE_KEY_ALIAS -keystore YOUR_RELEASE_KEY_PATH | openssl sha1 -binary | openssl base64
Android Code
package com.example.causelist;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.facebook.AccessToken;
import com.facebook.AccessTokenTracker;
import com.facebook.CallbackManager;
import com.facebook.FacebookCallback;
import com.facebook.FacebookException;
import com.facebook.GraphRequest;
import com.facebook.GraphRequestAsyncTask;
import com.facebook.GraphResponse;
import com.facebook.HttpMethod;
import com.facebook.LoginStatusCallback;
import com.facebook.Profile;
import com.facebook.login.LoginManager;
import com.facebook.login.LoginResult;
import com.facebook.login.widget.LoginButton;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.Arrays;
//https://developers.facebook.com/docs/facebook-login/android/?sdk=maven
//project:My First Test App
//App ID: 1497939987182600
/*
keytool -exportcert -alias androiddebugkey -keystore "C:\Users\DELL\.android\debug.keystore" | "PATH_TO_OPENSSL_LIBRARY\bin\openssl" sha1 -binary | "PATH_TO_OPENSSL_LIBRARY\bin\openssl" base64
keytool -exportcert -alias androiddebugkey -keystore "C:\Users\DELL\.android\debug.keystore" | "C:\openSSL\bin\openssl" sha1 -binary | "C:\openSSL\bin\openssl" base64
Keystore password:123456
ga0RGNYHvNM5d0SLGQfpQWAPGJ8=
By code
+gztLysQuYVmCj1tOoQdE1ib6is=
//https://stackoverflow.com/questions/23674131/android-facebook-integration-with-invalid-key-hash
*/
/*
Error: App not setup: This app is still in development mode
https://stackoverflow.com/questions/30085246/app-not-setup-this-app-is-still-in-development-mode
*/
public class FbLoginActivity extends AppCompatActivity {
private static final String EMAIL = "email";
CallbackManager callbackManager;
LoginButton loginButton;
TextView txtFBUser;
String logTag = "FB_LOGIN_TEST";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fb_login);
txtFBUser = findViewById(R.id.txtFBUser);
//https://stackoverflow.com/questions/23674131/android-facebook-integration-with-invalid-key-hash
/*String packageName = getPackageName();
Log.d("KeyHash:", "packageName is "+packageName);
try {
PackageInfo info = getPackageManager().getPackageInfo(
packageName,
PackageManager.GET_SIGNATURES);
for (Signature signature : info.signatures) {
MessageDigest md = MessageDigest.getInstance("SHA");
md.update(signature.toByteArray());
Log.d("KeyHash:", Base64.encodeToString(md.digest(), Base64.DEFAULT));
}
}
catch (PackageManager.NameNotFoundException e) {
Log.d("KeyHash:", "PackageManager.NameNotFoundException");
}
catch (NoSuchAlgorithmException e) {
Log.d("KeyHash:", "NoSuchAlgorithmException");
}
*/
Profile fbProfile = Profile.getCurrentProfile();
if (fbProfile == null) {
Log.d(logTag, "NOT logged in");
}
else
{
fbProfile.getName();
Log.d(logTag, "fbProfile.getName() is " + fbProfile.getName());
}
AccessToken accessToken = AccessToken.getCurrentAccessToken();
boolean isLoggedIn = accessToken != null && !accessToken.isExpired();
//LoginManager.getInstance().logInWithReadPermissions(this, Arrays.asList("public_profile"));
if(isLoggedIn)
{
extractUSerInfo(accessToken);
}
else {
callbackManager = CallbackManager.Factory.create();
LoginManager.getInstance().registerCallback(callbackManager,
new FacebookCallback<LoginResult>() {
@Override
public void onSuccess(LoginResult loginResult) {
// App code
Log.d("FB_LOGIN_TEST", "Logged in to FB");
// App code
extractUSerInfo(loginResult.getAccessToken());
}
@Override
public void onCancel() {
// App code
Log.d("FB_LOGIN_TEST", "FB Login cancelled");
txtFBUser.setText("Not Logged In");
}
@Override
public void onError(FacebookException exception) {
// App code
Log.d("FB_LOGIN_TEST", "Error while loging into FB");
}
});
loginButton = (LoginButton) findViewById(R.id.login_button);
//loginButton.setReadPermissions(Arrays.asList(EMAIL));
loginButton.setPermissions(Arrays.asList("public_profile", "email", "user_birthday", "user_friends"));
// If you are using in a fragment, call loginButton.setFragment(this);
}
}
protected void extractUSerInfo(AccessToken assessToken)
{
AccessTokenTracker accessTokenTracker = new AccessTokenTracker() {
@Override
protected void onCurrentAccessTokenChanged(AccessToken oldAccessToken,
AccessToken currentAccessToken) {
if (currentAccessToken == null) {
//write your code here what to do when user logout
Log.d("FB_LOGIN_TEST", "FB Logged out");
txtFBUser.setText("Not Logged In");
}
}
};
GraphRequest request = GraphRequest.newMeRequest(
assessToken/*loginResult.getAccessToken()*/,
new GraphRequest.GraphJSONObjectCallback() {
@Override
public void onCompleted(JSONObject object, GraphResponse response) {
Log.v("FB_LOGIN_TEST", "Roken Request Response is " + response.toString());
try {
String Name = object.getString("name");
String FEmail = object.getString("email");
Log.v("Email = ", " " + FEmail);
Toast.makeText(getApplicationContext(), "Name " + Name, Toast.LENGTH_LONG).show();
txtFBUser.setText(Name);
} catch (JSONException e) {
e.printStackTrace();
}
}
});
Bundle parameters = new Bundle();
parameters.putString("fields", "id,name,email,gender,birthday");
request.setParameters(parameters);
request.executeAsync();
//https://stackoverflow.com/questions/14996868/android-facebook-get-user-access-token-on-successful-login
GraphRequestAsyncTask graphRequestAsyncTask = new GraphRequest(
assessToken /*login_result.getAccessToken()*/,
//AccessToken.getCurrentAccessToken(),
"/me/friends",
null/*bundle*/,
HttpMethod.GET,
new GraphRequest.Callback() {
public void onCompleted(GraphResponse response) {
try {
JSONArray rawName = response.getJSONObject().getJSONArray("data");
Log.d(logTag,"rawName friendList"+String.valueOf(rawName));
AccessToken token = AccessToken.getCurrentAccessToken();
Log.d(logTag,"access token is: "+String.valueOf(token));
} catch (JSONException e) {
e.printStackTrace();
}
}
}
).executeAsync();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
callbackManager.onActivityResult(requestCode, resultCode, data);
super.onActivityResult(requestCode, resultCode, data);
}
protected void fbExpressLogin()
{
LoginManager.getInstance().retrieveLoginStatus(this, new LoginStatusCallback() {
@Override
public void onCompleted(AccessToken accessToken) {
// User was previously logged in, can log them in directly here.
// If this callback is called, a popup notification appears that says
// "Logged in as <User Name>"
}
@Override
public void onFailure() {
// No access token could be retrieved for the user
}
@Override
public void onError(Exception exception) {
// An error occurred
}
});
}
}
|
|