Sunday, December 30, 2012

Installing VNC Server on CentOS


Virtual Network Computing Logo

What is VNC?

VNC (Virtual Network Computing) is a graphical desktop sharing system that is used to remotely control another computer. It transmits the keyboard and mouse events from one computer to another, relaying the graphical screen updates back in the other direction, over a network.

VNC is platform-independent. That is a windows user may connect to a linux server or vice versa. Multiple users using different operating systems can connect to the same VNC server at the same exact time.
Using VNC you can remotely control your home computer from work or vice versa.
You may also remotely control your webserver as long as you have root access to it (usually VPS and Dedicated servers).

Requirements for this Tutorial:

  • Linux CentOS Server
  • Windows Client.
  • In this tutorial I will connect from my windows operating system to my linux server using VNC.
  • To be able to successfully install and run VNC you need to have root access to your server.
  • In this tutorial I'm assuming you are using CentOS operating system. Although installing it on a different Linux operating should be very similar.

Installing VNC Server on CentOS

First we need to install X Window System (X11) which is a software system and network protocol that provides a basis for graphical user interfaces.
yum groupinstall "X Window System"

Then we install the GNOME Desktop Environment, which is a desktop environment and graphical user interface that runs on top of a computer operating system and was developed mainly by Red Hat employees.

For CentOS 5, run the following command:
yum groupinstall "GNOME Desktop Environment"
For CentOS 6, run the following command:
yum groupinstall desktop

Now let's install the VNC Server:
For CentOS 5
yum install vnc-server
For CentOS 6
yum install tigervnc-server

And let's install some fonts (You may skip this step, but later on if you remotely login and you're unable to view the remote desktop's icons and text, you will have to install some fonts)
yum install xorg-x11-fonts-Type1
or
yum groupinstall fonts

Configuring VNC Server for root access:


To login to the remote server as root:

Edit the /etc/sysconfig/vncservers file:
vi /etc/sysconfig/vncservers

Uncomment the following two lines and remove -nolisten tcp -localhost:
# VNCSERVERS="2:myusername"
# VNCSERVERARGS[2]="-geometry 800x600 -nolisten tcp -localhost"

Where 2 is the port number and the myusername is the linux user.

To login as the root with a 800x600 resolution, we change the username to root and the arguments of the port as follow:
VNCSERVERS="2:root"
VNCSERVERARGS[2]="-geometry 800x600"
Save (:w) and quit editing the file (:q)

Create a password for VNC root user using the following command, you can use the same command to change your password later:
vncpasswd

Start the VNC Server:
service vncserver start

After starting the server, a new file will be created /root/.vnc/xstartup


If you are using CentOS 5, edit /root/.vnc/xstartup (You can skip this in CentOS 6):
vi /root/.vnc/xstartup
And comment twm & and append gnome-session & as follow:
#twm &
gnome-session &
Save (:w) and quit editing the file (:q)


Restart the VNC Server:
service vncserver restart

Congratulations, your VNC server should be up and running, check the "Installing VNC Client" below to login and test your connection as root. Or if you want to login as a different user other than root, check the section below:


Configuring VNC Server for root access and another user:


Make sure you are logged in to the server as root:
su -

Create the new user(s) and set their password (if they don't exist yet). I will create a new user for this tutorial called userone:
useradd userone
passwd userone

Edit the /etc/sysconfig/vncservers file:
vi /etc/sysconfig/vncservers

Uncomment the following two lines and remove -nolisten tcp -localhost:
# VNCSERVERS="2:myusername"
# VNCSERVERARGS[2]="-geometry 800x600 -nolisten tcp -localhost"
Where 2 is the port number and the myusername is the linux user.

Please note that only the last digit of the port number is entered and the first three are implicit. For example, 2 defines port 5902. 9 indicates use of port 5909

To login as the root with a 640x480 resolution, we change the username to root and the arguments of the port as follow:
VNCSERVERS="1:root"
VNCSERVERARGS[1]="-geometry 640x480"

To login as userone with a 800x600 resolution, we add the port number and the username to VNCSERVERS and we add a new argument for the port. I will use port number 2 for userone.
VNCSERVERS="1:root 2:userone"
VNCSERVERARGS[1]="-geometry 640x480"
VNCSERVERARGS[2]="-geometry 800x600"
 Save (:w) and quit editing the file (:q)


Switch users and create a password for your VNC users using the following command, you can use the same command to change your password later:
su -
vncpasswd

su userone
vncpasswd

Login back as root and start (or restart) the VNC Server:
su -
service vncserver start

After starting the server, a new file for each user will be created:
root will have the following file created: /root/.vnc/xstartup
userone will have the following file created: /home/userone/.vnc/xstartup

If you are using CentOS 5, edit /root/.vnc/xstartup (You can skip this in CentOS 6):
vi /root/.vnc/xstartup
And comment twm & and append gnome-session & as follow:
#twm &
gnome-session &
Save (:w) and quit editing the file (:q)

Do the same for userone: (You can skip this in CentOS 6):
su userone
cd
vi .vnc/xstartup
And comment twm & and append gnome-session & as follow:
#twm &
gnome-session &
Save (:w) and quit editing the file (:q)


Login back to root and Restart the VNC Server:
su -
service vncserver restart

Congratulations, your VNC server should be up and running, check the "Installing VNC Client" below to login and test your connection.


Installing VNC Client


To connect to your server remotely, you need to download install VNC Viewer.

Open VNC Viewer and enter your server's ip or hostname and the port number, for example:

VNC Viewer

Enter the password that you have created with vncpasswd, and connect.

You will see your server's desktop, such as:

VNC Viewer Desktop


Notes:

You will most probably need to disable Network Manager after you install the GUI. Network manager usually overwrite the settings of /etc/resolv.conf after every reboot.
service NetworkManager stop
chkconfig NetworkManager off

If you want to use a web browser to browse the internet, you can install firefox using the following command:
yum install firefox



Tuesday, November 20, 2012

Installing suPHP on CentOS With Virtualmin/Webmin


suPHP


What is suPHP?

suPHP is a tool for executing PHP scripts with the permissions of their owners. It consists of an Apache module (mod_suphp) and a setuid root binary (suphp) that is called by the Apache module to change the uid of the process executing the PHP interpreter. 
suPHP can enhance the security because the PHP scripts will  run as the webserver user and not as "root" or "nobody". So if a different webuser has a vulnerable script installed, it will not affect your scripts.


Installing suPHP

Login to your root server using SSH
Enter the following command
yum install mod_suphp

If you get an error that the package doesn't exist, you have to install RPMforge repository.

If you don't know what's your server architecture (32 bit or 64 bit), you can find out using the following command:
uname -i


For CentOS 6 64 bit:
rpm -i http://packages.sw.be/rpmforge-release/rpmforge-release-0.5.2-2.el6.rf.x86_64.rpm

For CentOS 6 32 bit:
rpm -i http://packages.sw.be/rpmforge-release/rpmforge-release-0.5.2-2.el6.rf.i686.rpm

For CentOS 5 64 bit:
rpm -i http://packages.sw.be/rpmforge-release/rpmforge-release-0.5.2-2.el5.rf.x86_64.rpm

For CentOS 5 32 bit:
rpm -i http://packages.sw.be/rpmforge-release/rpmforge-release-0.5.2-2.el5.rf.i386.rpm


Now install mod_suphp again:
yum install mod_suphp


Configuring suPHP

After installing suPHP, you will have two new configuration files:
/etc/suphp.conf - This is the configuration file for suPHP
/etc/httpd/conf.d/suphp.conf - This is the configuration file for the suPHP and Apache module

Edit the suPHP configuration file first:
vi /etc/suphp.conf

Make sure that the value of webserver_user=apache
webserver_user=apache


Change the value x-httpd-php=php:/usr/bin/php to:
x-httpd-php="php:/usr/bin/php-cgi"

Change the value x-suphp-cgi=execute:!self to:
x-suphp-cgi="execute:!self"


That's how your /etc/suphp.conf should look like (You can just copy/paste it if you want):

[global]
logfile=/var/log/httpd/suphp_log
loglevel=info
webserver_user=apache
docroot=/
env_path=/bin:/usr/bin
umask=0022
min_uid=500
min_gid=500

; Security options
allow_file_group_writeable=true
allow_file_others_writeable=false
allow_directory_group_writeable=true
allow_directory_others_writeable=false

;Check wheter script is within DOCUMENT_ROOT
check_vhost_docroot=true

;Send minor error messages to browser
errors_to_browser=false

[handlers]
;Handler for php-scripts
x-httpd-php="php:/usr/bin/php-cgi"

;Handler for CGI-scripts
x-suphp-cgi="execute:!self"


Edit /etc/httpd/conf.d/suphp.conf
vi /etc/httpd/conf.d/suphp.conf

Delete everything inside the /etc/httpd/conf.d/suphp.conf (or comment them), except the following line:
LoadModule suphp_module modules/mod_suphp.so

We do this to disable suPHP globally, specially if you have more than one virtual host and more than one user, and we enable suPHP below on the virtual hosts in order to run the php scripts as their owner user.

Editing httpd.conf
Go to your Webmin tab => Servers => Apache Webservers => Global Configuration => Edit Config File
Apache Edit Config Files

Make sure the /etc/httpd/conf/httpd.conf is selected,
Find all the <virtualHost> directives and add the following inside everyone:
suPHP_Engine on
suPHP_UserGroup userName groupName
AddHandler x-httpd-php .php .php3 .php4 .php5
suPHP_AddHandler x-httpd-php

Replace userName and groupName by your linux user and group respectively.

If you don't know what's your userName and groupName are, go to VirtualMin tab, choose the virtual server you're editing and you will see the user and group name, in my case, it's "lab" and "lab"

lab tech and dev


My modified Virtual Host look like the following:
<VirtualHost *:80>
SuexecUserGroup "#507" "#506"
ServerName lab.tech-and-dev.com
ServerAlias www.lab.tech-and-dev.com
DocumentRoot /home/lab/public_html
ScriptAlias /cgi-bin/ /home/lab/cgi-bin/
suPHP_Engine on
suPHP_UserGroup lab lab
AddHandler x-httpd-php .php .php3 .php4 .php5
suPHP_AddHandler x-httpd-php

If you were using FastCgi (FCGI), you will have to remove (or comment) the following lines
AddHandler fcgid-script .php
AddHandler fcgid-script .php5
FCGIWrapper /home/example/fcgi-bin/php5.fcgi .php
FCGIWrapper /home/example/fcgi-bin/php5.fcgi .php5


Editing Virtual Hosts default Template
One last thing is we have to add suPHP as the default php handler for the new virtual hosts.
  • Go to Virtualmin tab
  • Click System Settings
  • Click Server Templates
  • Choose your template (or click on Default Settings if you haven't created a template)
  • On top, next to "Edit template section", choose "Apache Website"
  • Below the DocumentRoot ${HOME}/public_html, add the following:
  • suPHP_Engine on
    suPHP_UserGroup ${USER} ${GROUP}
    AddHandler x-httpd-php .php .php3 .php4 .php5
    suPHP_AddHandler x-httpd-php
  • So overall it will look like this:
  • ServerName ${DOM}
    ServerAlias www.${DOM}
    DocumentRoot ${HOME}/public_html
    suPHP_Engine on
    suPHP_UserGroup ${USER} ${GROUP}
    AddHandler x-httpd-php .php .php3 .php4 .php5
    suPHP_AddHandler x-httpd-php
    ErrorLog /var/log/virtualmin/${DOM}_error_log
    CustomLog /var/log/virtualmin/${DOM}_access_log combined
  • Scroll down and change Default PHP execution mode to Apache mod_php (run as Apache's user)

Restart Apache
service httpd restart

Try to access your website now.

Problems and Solutions

If you get a 500 error, make sure your directories and files permissions are correct. Directories should have permission 755 and files should have permission 644.



Any questions? Please leave your comment below!


Sunday, September 16, 2012

Password protecting a directory with htaccess and htpasswd

Password Protecting a web directory with htaccess

Password protecting a web directory can help make a directory private and only accessible to one or several persons that have the username(s) and password(s).
htaccess

How to password protect a directory?

htaccess

  1. Go to the directory you want protected.
  2. Check if you have a .htaccess file.
  3. If a htaccess file is available, you have to edit it, otherwise create a new .htaccess file.
  4. Add the following to the htaccess file:
AuthUserFile /home/linuxuser/.htpasswd
AuthType Basic
AuthName "Tech and Dev Example"
Require valid-user
AuthUserFile: this is the path of the .htpasswd file where the username and password will be stored. The file can be located anywhere, but ideally, it's better if it's placed in a non public directory where users can't access it from the web.

AuthType: should be Basic

AuthName: The title of the window that will be authenticating the user. For example if you're password protecting your private files, you might want to change this to "My Private Files".

htpasswd

This is the file where the username and password are stored.
This file is usually called htpasswd (by convention if you want), however you can rename this file to anything you want. Many applications use their appname followed by htpasswd, for example .awstats-htpasswd
It's always a better idea to keep this file outside of the public folder (www or public_html...)

Assuming you want the username to be username and the password to be password, write the following command in SSH:
#htpasswd -nb username password
Then inside the htpasswd file write the output value from the SSH (the password might be different since everytime a different salt value is used):
username:60lwxfC9Ln84g

You can add as many usernames and passwords as you like, for example:
username:60lwxfC9Ln84g
username2:30dJVEURUeYJc

How is the password getting encrypted?

To understand more on how the password is generated and encrypted, you can check my previous post: Understanding the encryption process in htpasswd file.

To generate a username/password, you can check our online Encryption Tools.

Example

http://lab.tech-and-dev.com/protecteddir/
Username: username
Password: password
or
Username: username2
Password: password2


Any questions or suggestions? Please leave a comment below!


Friday, September 7, 2012

Join our Folding@Home "Tech and Dev" Team

What is Folding@home?

 

Folding
Folding@home is a distributed computing project, that very simply stated, studies protein folding and misfolding.

You can help scientists studying Alzheimer's, Huntington's, and many cancers by simply running a piece of software on your computer or game console.

Distributed Computing is a method of computer processing in which different parts of a program, or different portions of data, are processing simultaneously on two or more computers that are communicating with each other over a network or through the Internet.

Unlike other distributed computing projects, Folding@home is run by an academic institution (specifically the Pande Group, at Stanford University's - Chemistry Department), which is a nonprofit institution dedicated to science research and education. 

Moreover, the data is available for others to use. In particular, the results from Folding@home will be made available on several levels. Most importantly, analysis of the simulations will be submitted to scientific journals for publication, and these journal articles will be posted on the folding@home web page after publication.

The Folding@home software runs behind the scenes using otherwise unused computing time. Mostly likely you will hardly even notice it.

Folding Homepage

Downloading Folding@home

Folding@home can run on computers and game consoles (Playstation, Xbox...).

Folding@home can be downloaded from the Folding Homepage.

Joining Tech and Dev Team

Joining Tech and Dev team is simple, when you are prompt to choose a username and team, just pick any username you want and add the Team id 221575

You can check the team stats below:
Tech and Dev Folding Team


Happy Folding!


Friday, August 24, 2012

Turning your server into a proxy using Squid



Squid is a fully-featured HTTP/1.0 proxy. Squid offers a rich access control, authorization and logging environment to develop web proxy and content serving applications.

 

 

 

Installing Squid

To install squid on CentOS, use yum install command (you must be logged in as root (If you're not familiar with yum and root access, you might want to check the following topic first: 15 most used linux commands and how to use them)):
yum install squid



If you can't install squid using yum, you can download it from http://www1.dk.squid-cache.org/Versions/ using wget command (how to use wget)
Next you have to extract the compressed archive file and change the working directory to the squid directory:
tar -xvzf squid-*-src.tar.gz
cd squid -*

Now enter the following commands in order to configure, compile and install squid
./configure
make
make install


This by default, will install it in "/usr/local/squid".
Type ./configure --help to view all available options.


Configuring Squid

In order to configure squid, we open the squid configuration file located in /etc/squid
vi /etc/squid/squid.conf



By default, squid will listen on port 3128, to make it listen on port 3128, 8080 and port 2083, we add the following:
http_port 3128
http_port 2083
http_port 8080

or if you want to define an IP to listen to instead of all IPs, replace YOUR_SERVER_IP by your server IP:
http_port YOUR_SERVER_IP:3128
http_port YOUR_SERVER_IP:2083
http_port YOUR_SERVER_IP:8080



By default all the http access are denied. The ACL rules must be modified to allow access only to trusted users or all users. This is important if you don't want everyone to use your proxy server and eventually consume resources.

To allow everyone to access and use the proxy server, append the following line to the configuration file:
http_access allow all
(make sure to remove the line http_access deny all for the above to work)


To allow a range of IPs instead of allowing everyone, add the following command
acl my_ranged_ips src 1.2.3.1-1.2.3.254/24
http_access allow my_ranged_ips
http_access deny all

Make sure that http_access deny all is the last statement, this is because the ACLs are checked from top to bottom. Users with IPs in the range of my_ranged_ips will be allowed to use the server, anyone else falls through to the "deny all" and gets a failure message.

Once the configurations are done, restart squid:
service squid restart

To stop squid
service squid stop

To start squid
service squid start


Any comments, questions or suggestions? Post below!


Wednesday, August 22, 2012

Facebook Registration Plugin (With Custom Fields and Examples)

Facebook Registration Plugin (With Custom Fields and Examples)

In this post, I will show you how to implement facebook registration plugin, and I will create some examples, with custom fields, with both the iframe version and XFBML.

You can check the examples directly in here: Facebook Registration Plugin Examples

Scroll down for the entire source code.

The facebook social plugin can be used for users with a facebook account, or users without a facebook account.
If the user does not have a facebook account, or if the user is not logged in to their facebook account, the below subscription form will be displayed.
Facebook Registration Plugin

If the user has a facebook account and is logged in, the registration form will be pre-filled to save the user time. This is very useful to register the user quickly with one mouse click.
Facebook Registration Plugin Pre-filled

Sometimes you might only want users with a facebook account to be able to register on your site. This can be specified with a parameter that will be explained later on. The following registration form will be displayed if the user is not logged in to facebook.
Facebook Registration Plugin Force Login


I will not go in the already explained details on facebook. In this post, I will assume that you have already read this: http://developers.facebook.com/docs/plugins/registration/

For this plugin to work, you will need a facebook app id and a facebook app secret, if you havne't created a facebook app yet, I suggest you read this tutorial first to create an app: Facebook App Tutorial - The Basics

You will also need to set the redirect URI, in my case, I'm going to set it to the same file location of the subscription form in order to display the output.

 

 

Facebook registration plugin (iframe) without custom fields:

In the first example, I'm going to build the registration plugin using iframe and without any custom fields. Simply the code will be as follows:

<?php
$API_KEY = '463292747036958';
$API_SECRET = 'GET_YOUR_APP_SECRET';
$redirect_URI = 'http://lab.tech-and-dev.com/facebookRegistration.php';
?>

<script src="https://connect.facebook.net/en_US/all.js#appId=<?php echo $API_KEY; ?>&xfbml=1"></script>
<div id="fb-root"></div>

<h2>Without Custom Fields</h2>
<iframe src="http://www.facebook.com/plugins/registration?
         client_id=<?php echo $API_KEY; ?>&
         redirect_uri=<?php echo $redirect_URI; ?>&
         fb_only=false&
         fields=name,birthday,gender,location,email"
    scrolling="auto"
    frameborder="no"
    style="border:none"
    allowTransparency="true"
    width="530"
    height="330"
>
</iframe>

<?php
if ($_REQUEST['signed_request'])
{
    $response = parse_signed_request($_REQUEST['signed_request'], $API_SECRET);//secret

    if($response)
    {
        //Fields values
        $email=$response['registration']['email'];
        $name=$response['registration']['name'];
        $gender=$response['registration']['gender'];
        $user_fb_id=$response['user_id'];
        $location=$response['registration']['location']['name'];
        $bday = $response['registration']['birthday'];

        //print entire array response
        echo '<h3>Response Array</h3>';
        echo '<pre>';
        print_r($response);
        echo '</pre>';

        //print values
        echo '<h3>Fields Values</h3>';
        echo 'email: ' . $email . '<br />';
        echo 'Name: ' . $name . '<br />';
        echo 'Gender: ' . $gender . '<br />';
        echo 'Facebook Id: ' . $user_fb_id . '<br />';
        echo 'Location: ' . $location . '<br />';
        echo 'Birthday: ' . $bday . '<br />';

    }
}
?>


<?php
function parse_signed_request($signed_request, $secret)
{
    list($encoded_sig, $payload) = explode('.', $signed_request, 2);

    // decode the data
    $sig = base64_url_decode($encoded_sig);
    $data = json_decode(base64_url_decode($payload), true);

    if (strtoupper($data['algorithm']) !== 'HMAC-SHA256')
    {
        error_log('Unknown algorithm. Expected HMAC-SHA256');
        return null;
    }

    // check sig
    $expected_sig = hash_hmac('sha256', $payload, $secret, $raw = true);
    if ($sig !== $expected_sig)
    {
        error_log('Bad Signed JSON signature!');
        return null;
    }

    return $data;
}

function base64_url_decode($input)
{
    return base64_decode(strtr($input, '-_', '+/'));
}
?>



Facebook registration plugin (iframe) with custom fields:

In this example, I'm going to build the registration plugin using iframe and with custom fields
To use custom fields, we will need to use JSON arrays 
The below example is an array from facebook tutorial, you can define checkbox, date, select, captcha to be filled...

[
 {'name':'name'},
 {'name':'email'},
 {'name':'location'},
 {'name':'gender'},
 {'name':'birthday'},
 {'name':'password'},
 {'name':'like',       'description':'Do you like this plugin?', 'type':'checkbox',  'default':'checked'},
 {'name':'phone',      'description':'Phone Number',             'type':'text'},
 {'name':'anniversary','description':'Anniversary',              'type':'date'},
 {'name':'captain',    'description':'Best Captain',             'type':'select',    'options':{'P':'Jean-Luc Picard','K':'James T. Kirk'}},
 {'name':'force',      'description':'Which side?',              'type':'select',    'options':{'jedi':'Jedi','sith':'Sith'}, 'default':'sith'},
 {'name':'live',       'description':'Best Place to Live',       'type':'typeahead', 'categories':['city','country','state_province']},
 {'name':'captcha'}
]

The code will be as follows:

<?php
$API_KEY = '463292747036958';
$API_SECRET = 'GET_YOUR_APP_SECRET';
$redirect_URI = 'http://lab.tech-and-dev.com/facebookRegistration.php';
?>

<script src="https://connect.facebook.net/en_US/all.js#appId=<?php echo $API_KEY; ?>&xfbml=1"></script>
<div id="fb-root"></div>

<h2>With Custom Fields</h2>
<iframe src="http://www.facebook.com/plugins/registration?
         client_id=<?php echo $API_KEY; ?>&
         redirect_uri=<?php echo $redirect_URI; ?>&
         fb_only=false&
         fields=[
    {'name':'name'},
    {'name':'birthday'},
    {'name':'gender'},
    {'name':'location'},
    {'name':'email'},
    {'name':'favoriteFood', 'description':'Favorite Food', 'type':'select', 'options':{'0':'Pizza','1':'Burger','2':'Hot Dog','3':'Tuna'}},
    {'name':'graduated', 'description':'Graduation Date', 'type':'date'},
]"
    scrolling="auto"
    frameborder="no"
    style="border:none"
    allowTransparency="true"
    width="530"
    height="400"
>
</iframe>
<?php
if ($_REQUEST['signed_request'])
{
    $response = parse_signed_request($_REQUEST['signed_request'], $API_SECRET);//secret

    if($response)
    {
        //Fields values
        $email=$response['registration']['email'];
        $name=$response['registration']['name'];
        $gender=$response['registration']['gender'];
        $user_fb_id=$response['user_id'];
        $location=$response['registration']['location']['name'];
        $bday = $response['registration']['birthday'];

        //custom fields
        $favoriteFood = $response['registration']['favoriteFood'];
        $graduated = $response['registration']['graduated'];


        //print entire array response
        echo '<h3>Response Array</h3>';
        echo '<pre>';
        print_r($response);
        echo '</pre>';

        //print values
        echo '<h3>Fields Values</h3>';
        echo 'email: ' . $email . '<br />';
        echo 'Name: ' . $name . '<br />';
        echo 'Gender: ' . $gender . '<br />';
        echo 'Facebook Id: ' . $user_fb_id . '<br />';
        echo 'Location: ' . $location . '<br />';
        echo 'Birthday: ' . $bday . '<br />';

        //print custom fields
        echo '<h3>Custom Fields Values</h3>';
        echo 'Favorite Food: ' . $favoriteFood . '<br />';
        echo 'Graduated: ' . $graduated . '<br />';
    }
}
?>


<?php
function parse_signed_request($signed_request, $secret)
{
    list($encoded_sig, $payload) = explode('.', $signed_request, 2);

    // decode the data
    $sig = base64_url_decode($encoded_sig);
    $data = json_decode(base64_url_decode($payload), true);

    if (strtoupper($data['algorithm']) !== 'HMAC-SHA256')
    {
        error_log('Unknown algorithm. Expected HMAC-SHA256');
        return null;
    }

    // check sig
    $expected_sig = hash_hmac('sha256', $payload, $secret, $raw = true);
    if ($sig !== $expected_sig)
    {
        error_log('Bad Signed JSON signature!');
        return null;
    }

    return $data;
}

function base64_url_decode($input)
{
    return base64_decode(strtr($input, '-_', '+/'));
}
?>

Facebook registration plugin (iframe) without custom fields and only for facebook users:

Sometimes you might only want to allow facebook users to register on your website, you can use the attribute fb_only=true to achieve this.


<?php
$API_KEY = '463292747036958';
$API_SECRET = 'GET_YOUR_APP_SECRET';
$redirect_URI = 'http://lab.tech-and-dev.com/facebookRegistration.php';
?>

<script src="https://connect.facebook.net/en_US/all.js#appId=<?php echo $API_KEY; ?>&xfbml=1"></script>
<div id="fb-root"></div>

<h2>Without Custom Fields - Only Facebook users allowed.</h2>
<iframe src="http://www.facebook.com/plugins/registration?
         client_id=<?php echo $API_KEY; ?>&
         redirect_uri=<?php echo $redirect_URI; ?>&
         fb_only=true&
         fields=name,birthday,gender,location,email"
    scrolling="auto"
    frameborder="no"
    style="border:none"
    allowTransparency="true"
    width="530"
    height="330"
>
</iframe>


<?php
if ($_REQUEST['signed_request'])
{
    $response = parse_signed_request($_REQUEST['signed_request'], $API_SECRET);//secret

    if($response)
    {
        //Fields values
        $email=$response['registration']['email'];
        $name=$response['registration']['name'];
        $gender=$response['registration']['gender'];
        $user_fb_id=$response['user_id'];
        $location=$response['registration']['location']['name'];
        $bday = $response['registration']['birthday'];

        //print entire array response
        echo '<h3>Response Array</h3>';
        echo '<pre>';
        print_r($response);
        echo '</pre>';

        //print values
        echo '<h3>Fields Values</h3>';
        echo 'email: ' . $email . '<br />';
        echo 'Name: ' . $name . '<br />';
        echo 'Gender: ' . $gender . '<br />';
        echo 'Facebook Id: ' . $user_fb_id . '<br />';
        echo 'Location: ' . $location . '<br />';
        echo 'Birthday: ' . $bday . '<br />';

    }
}
?>


<?php
function parse_signed_request($signed_request, $secret)
{
    list($encoded_sig, $payload) = explode('.', $signed_request, 2);

    // decode the data
    $sig = base64_url_decode($encoded_sig);
    $data = json_decode(base64_url_decode($payload), true);

    if (strtoupper($data['algorithm']) !== 'HMAC-SHA256')
    {
        error_log('Unknown algorithm. Expected HMAC-SHA256');
        return null;
    }

    // check sig
    $expected_sig = hash_hmac('sha256', $payload, $secret, $raw = true);
    if ($sig !== $expected_sig)
    {
        error_log('Bad Signed JSON signature!');
        return null;
    }

    return $data;
}

function base64_url_decode($input)
{
    return base64_decode(strtr($input, '-_', '+/'));
}
?>



Facebook registration plugin (XFBML) with custom fields: 

If you wish to use XFBML instead of iframe, with custom fields, you can use the below example:


<?php
$API_KEY = '463292747036958';
$API_SECRET = 'GET_YOUR_APP_SECRET';
$redirect_URI = 'http://lab.tech-and-dev.com/facebookRegistration.php';
?>

<script src="https://connect.facebook.net/en_US/all.js#appId=<?php echo $API_KEY; ?>&xfbml=1"></script>
<div id="fb-root"></div>

<h2>With Custom Fields - XFBML</h2>
<fb:registration
fields="[
    {'name':'name'},
    {'name':'birthday'},
    {'name':'gender'},
    {'name':'location'},
    {'name':'email'},
    {'name':'favoriteFood', 'description':'Favorite Food', 'type':'select', 'options':{'0':'Pizza','1':'Burger','2':'Hot Dog','3':'Tuna'}},
    {'name':'graduated', 'description':'Graduation Date', 'type':'date'},
]"
  redirect-uri="<?php echo $redirect_URI; ?>"
  width="530">
</fb:registration>
<?php
if ($_REQUEST['signed_request'])
{
    $response = parse_signed_request($_REQUEST['signed_request'], $API_SECRET);//secret

    if($response)
    {
        //Fields values
        $email=$response['registration']['email'];
        $name=$response['registration']['name'];
        $gender=$response['registration']['gender'];
        $user_fb_id=$response['user_id'];
        $location=$response['registration']['location']['name'];
        $bday = $response['registration']['birthday'];

        //custom fields
        $favoriteFood = $response['registration']['favoriteFood'];
        $graduated = $response['registration']['graduated'];


        //print entire array response
        echo '<h3>Response Array</h3>';
        echo '<pre>';
        print_r($response);
        echo '</pre>';

        //print values
        echo '<h3>Fields Values</h3>';
        echo 'email: ' . $email . '<br />';
        echo 'Name: ' . $name . '<br />';
        echo 'Gender: ' . $gender . '<br />';
        echo 'Facebook Id: ' . $user_fb_id . '<br />';
        echo 'Location: ' . $location . '<br />';
        echo 'Birthday: ' . $bday . '<br />';

        //print custom fields
        echo '<h3>Custom Fields Values</h3>';
        echo 'Favorite Food: ' . $favoriteFood . '<br />';
        echo 'Graduated: ' . $graduated . '<br />';
    }
}
?>


<?php
function parse_signed_request($signed_request, $secret)
{
    list($encoded_sig, $payload) = explode('.', $signed_request, 2);

    // decode the data
    $sig = base64_url_decode($encoded_sig);
    $data = json_decode(base64_url_decode($payload), true);

    if (strtoupper($data['algorithm']) !== 'HMAC-SHA256')
    {
        error_log('Unknown algorithm. Expected HMAC-SHA256');
        return null;
    }

    // check sig
    $expected_sig = hash_hmac('sha256', $payload, $secret, $raw = true);
    if ($sig !== $expected_sig)
    {
        error_log('Bad Signed JSON signature!');
        return null;
    }

    return $data;
}

function base64_url_decode($input)
{
    return base64_decode(strtr($input, '-_', '+/'));
}
?>



More info about the facebook registration plugin can be found in here: http://developers.facebook.com/docs/plugins/registration/
Examples can be found in here: Facebook Registration Social Plugin Examples

Any questions or suggestions, please post them below!

Sunday, August 19, 2012

Facebook App Tutorial - The Basics

Facebook applications gives you the opportunity to deeply integrate into the core Facebook experience. Your app can integrate with many aspects of Facebook.com, including the News Feed, Notifications, open-graph and all of the core Facebook Platform technologies, such as Social Plugins, like the registration plugin, like plugin, login.

To create your first facebook application:


Go to https://developers.facebook.com/apps
Click on "Go to app"
Facebook Go To App


On the top right side click on "Create new App"
Facebook Create New App



Choose the name of your app, this can be anything.
Choose the namespace of your app, this is a unique name, so it might be already taken.
Uncheck Web Hosting with Huroku. Huroku allows you to host your app on their servers for free. We won't be using Heroku for this tutorial. I will write a tutorial in the future on how to use Heroku with facebook apps. 
Click "Continue".

Facebook App Name


You might need to verify your facebook account by adding your mobile phone number or credit card.
Facebook Verify App



This is the interface of our new app:
Facebook App Interface


The most important two things in the new app are the "App ID" and the "App Secret". Never share your App Secret with anyone.

Let's go to "Edit Settings"

In "Edit Settings", we can see all the app's important info.
If you want your app to be accessed from one or more website, you can define those websites in the "App Domains". For this tutorial, I'm gonna allow the app to be accessed from tech-and-dev.com, which also includes the subdomains of this site.
Facebook App Edit Settings



If you want to use the facebook login button on your website, you will have to set the URL in the "Website with Facebook Login" section.
Facebook App Website With Facebook Login



If you want your app to be part of facebook, that is, your app displayed in a facebook canvas, you can set the url of your facebook canvas. (I will explain more about this in my next tutorial)
Facebook App Canvas




Let's go to the "Auth Dialog" and configure it. The "Auth Dialog" link is on the left sidebar.
Facebook App Auth Dialog

You can check how will the app dialog will appear by clicking on the Preview Current Dialog.


It's very important to set a logo for your application, otherwise later on, when you decide to work with Open Graph, facebook will reject your application.
Adding a privacy policy and terms of service is a facebook requirements now, and any app that does not have a privacy policy or terms of use URL will receive a warning to add one or the application will be banned from facebook.

You can google for privacy policy and terms & conditions if you don't have any.

A warning will look like the following:
Notice of Violation: Privacy Policy (App ID: [YOUR_APP_ID])

Hi,

We've found the following policy violation with your app and you need to address this issue by [DATE] at [TIME] or your app may be subject to enforcement action.

Our policies require that your app has a privacy policy that tells users what user data you are going to use and how you will use, display, share, or transfer that data and you will include your privacy policy URL in the Developer Application (See Platform Policy II.3, http://developers.facebook.com/policy).

It has come to our attention that your app is missing a privacy policy in the permissions dialogue. Please update the privacy policy URL field in the Developer Application at developers.facebook.com/apps/[YOUR_APP_ID]/auth. Also, please review your app to ensure you are also displaying your privacy policy on your web site or within your app.

Thanks,
Platform Policy Teamen 


Let's add some permissions in the Configure how Facebook refers users to your app:
Facebook App Permissions

All the permissions and their description can be found in here:


You can check the app canvas in here: http://apps.facebook.com/tech-and-dev/
Facebook App

Notice how there is a privacy policy and terms and conditions link on the bottom, and all the permissions we've added.


That's it for our basic tutorial!

In my next tutorial, I will show you to build a php facebook app and work with the permissions and login.

Any questions or suggestions? Leave a comment below!