GitHub provides a web-based hosting service for version control. It plays an important role in software and web development. Presently GitHub has over 28 million users from around the world. If you want to allow users to log in with their social account, GitHub can be the best option besides the other social media OAuth Login (Facebook OAuth API, Google OAuth API, Twitter OAuth API, etc.). GitHub OAuth Login is a quick and powerful way to integrate user login system into the web application.
GitHub authentication API allows the users to sign in to the website using their GitHub account without registration on your website. Login with GitHub account can be easily implemented using GitHub OAuth API. In this tutorial, we will show you how to integrate the user login and registration system with GitHub using PHP and store the user’s profile data in the MySQL database.
Before getting started, take a look at the file structure to implement GitHub Login with PHP.
github_login_with_php/ ├── config.php ├── index.php ├── logout.php ├── User.class.php ├── src/ │ └──Github_OAuth_Client.php ├── css/ │ └── style.css └── images/ └── github-login.png
You need to create and register OAuth App to access GitHub API. Also, the Client ID and Client Secret need to be specified at the time of the GitHub API call. Follow the below steps to create and configure the GitHub OAuth application.
To store the user’s profile information from the GitHub account, a table needs to be created in the database. The following SQL creates a users
table with some basic fields in the MySQL database.
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`oauth_provider` enum('github','facebook','google','twitter') COLLATE utf8_unicode_ci NOT NULL DEFAULT 'github',
`oauth_uid` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
`name` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
`username` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
`email` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
`location` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
`picture` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`link` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`created` datetime NOT NULL DEFAULT current_timestamp(),
`modified` datetime NOT NULL DEFAULT current_timestamp(),
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
The Github_OAuth_Client class is a custom PHP library that handles GitHub REST API calls for OAuth-related requests.
<?php
/*
* Class Github_OAuth_Client
*
* Author: CodexWorld
* Author URL: https://www.codexworld.com
* Author Email: admin@codexworld.com
*
* The first PHP Library to support OAuth for GitHub REST API.
*/
class Github_OAuth_Client{
public $authorizeURL = "https://github.com/login/oauth/authorize";
public $tokenURL = "https://github.com/login/oauth/access_token";
public $apiURLBase = "https://api.github.com";
public $clientID;
public $clientSecret;
public $redirectUri;
/**
* Construct object
*/
public function __construct(array $config = []){
$this->clientID = isset($config['client_id']) ? $config['client_id'] : '';
if(!$this->clientID){
die('Required "client_id" key not supplied in config');
}
$this->clientSecret = isset($config['client_secret']) ? $config['client_secret'] : '';
if(!$this->clientSecret){
die('Required "client_secret" key not supplied in config');
}
$this->redirectUri = isset($config['redirect_uri']) ? $config['redirect_uri'] : '';
}
/**
* Get the authorize URL
*
* @returns a string
*/
public function getAuthorizeURL($state){
return $this->authorizeURL . '?' . http_build_query([
'client_id' => $this->clientID,
'redirect_uri' => $this->redirectUri,
'state' => $state,
'scope' => 'user:email'
]);
}
/**
* Exchange token and code for an access token
*/
public function getAccessToken($state, $oauth_code){
$token = self::apiRequest($this->tokenURL . '?' . http_build_query([
'client_id' => $this->clientID,
'client_secret' => $this->clientSecret,
'state' => $state,
'code' => $oauth_code
]));
return $token->access_token;
}
/**
* Make an API request
*
* @return API results
*/
public function apiRequest($access_token_url){
$apiURL = filter_var($access_token_url, FILTER_VALIDATE_URL)?$access_token_url:$this->apiURLBase.'user?access_token='.$access_token_url;
$context = stream_context_create([
'http' => [
'user_agent' => 'CodexWorld GitHub OAuth Login',
'header' => 'Accept: application/json'
]
]);
$response = file_get_contents($apiURL, false, $context);
return $response ? json_decode($response) : $response;
}
/**
* Get the authenticated user
*
* @returns object
*/
public function getAuthenticatedUser($access_token) {
$apiURL = $this->apiURLBase . '/user';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $apiURL);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json', 'Authorization: token '. $access_token));
curl_setopt($ch, CURLOPT_USERAGENT, 'CodexWorld GitHub OAuth Login');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
$api_response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if($http_code != 200){
if (curl_errno($ch)) {
$error_msg = curl_error($ch);
}else{
$error_msg = $api_response;
}
throw new Exception('Error '.$http_code.': '.$error_msg);
}else{
return json_decode($api_response);
}
}
}
The User class handles the database related operations (fetch, insert, and update). Specify the database host ($dbHost
), username ($dbUsername
), password ($dbPassword
), and name ($dbName
) as per your MySQL database credentials.
users
table using PHP and MySQL.<?php
/*
* User Class
* This class is used for database related (connect, insert, and update) operations
* @author CodexWorld.com
* @url http://www.codexworld.com
* @license http://www.codexworld.com/license
*/
class User {
private $dbHost = DB_HOST;
private $dbUsername = DB_USERNAME;
private $dbPassword = DB_PASSWORD;
private $dbName = DB_NAME;
private $userTbl = DB_USER_TBL;
function __construct(){
if(!isset($this->db)){
// Connect to the database
$conn = new mysqli($this->dbHost, $this->dbUsername, $this->dbPassword, $this->dbName);
if($conn->connect_error){
die("Failed to connect with MySQL: " . $conn->connect_error);
}else{
$this->db = $conn;
}
}
}
function checkUser($data = array()){
if(!empty($data)){
// Check whether the user already exists in the database
$checkQuery = "SELECT * FROM ".$this->userTbl." WHERE oauth_provider = '".$data['oauth_provider']."' AND oauth_uid = '".$data['oauth_uid']."'";
$checkResult = $this->db->query($checkQuery);
// Add modified time to the data array
if(!array_key_exists('modified',$data)){
$data['modified'] = date("Y-m-d H:i:s");
}
if($checkResult->num_rows > 0){
// Prepare column and value format
$colvalSet = '';
$i = 0;
foreach($data as $key=>$val){
$pre = ($i > 0)?', ':'';
$colvalSet .= $pre.$key."='".$this->db->real_escape_string($val)."'";
$i++;
}
$whereSql = " WHERE oauth_provider = '".$data['oauth_provider']."' AND oauth_uid = '".$data['oauth_uid']."'";
// Update user data in the database
$query = "UPDATE ".$this->userTbl." SET ".$colvalSet.$whereSql;
$update = $this->db->query($query);
}else{
// Add created time to the data array
if(!array_key_exists('created',$data)){
$data['created'] = date("Y-m-d H:i:s");
}
// Prepare column and value format
$columns = $values = '';
$i = 0;
foreach($data as $key=>$val){
$pre = ($i > 0)?', ':'';
$columns .= $pre.$key;
$values .= $pre."'".$this->db->real_escape_string($val)."'";
$i++;
}
// Insert user data in the database
$query = "INSERT INTO ".$this->userTbl." (".$columns.") VALUES (".$values.")";
$insert = $this->db->query($query);
}
// Get user data from the database
$result = $this->db->query($checkQuery);
$userData = $result->fetch_assoc();
}
// Return user data
return !empty($userData)?$userData:false;
}
}
In the config.php
file, database settings and Github OAuth API configuration constant variables are defined.
Database constants:
GitHub API constants:
Call GitHub API:
<?php
// Database configuration
define('DB_HOST', 'MySQL_Database_Host');
define('DB_USERNAME', 'MySQL_Database_Username');
define('DB_PASSWORD', 'MySQL_Database_Password');
define('DB_NAME', 'MySQL_Database_Name');
define('DB_USER_TBL', 'users');
// GitHub API configuration
define('CLIENT_ID', 'Insert_App_Client_ID');
define('CLIENT_SECRET', 'Insert_App_Client_Secret');
define('REDIRECT_URL', 'Callback_URL');
// Start session
if(!session_id()){
session_start();
}
// Include Github client library
require_once 'src/Github_OAuth_Client.php';
// Initialize Github OAuth client class
$gitClient = new Github_OAuth_Client(array(
'client_id' => CLIENT_ID,
'client_secret' => CLIENT_SECRET,
'redirect_uri' => REDIRECT_URL
));
// Try to get the access token
if(isset($_SESSION['access_token'])){
$accessToken = $_SESSION['access_token'];
}
If the user already logged in with the GitHub account, the profile information (account ID, name, username, email, location, profile picture, and profile link) will display, otherwise, GitHub login button will appear.
getAuthenticatedUser()
function of Github_OAuth_Client class.checkUser()
function to insert or update user data in the database.getAccessToken()
function of Github_OAuth_Client class.getAuthorizeURL()
function of Github_OAuth_Client class.<?php
// Include configuration file
require_once 'config.php';
// Include and initialize user class
require_once 'User.class.php';
$user = new User();
if(isset($accessToken)){
// Get the user profile data from Github
$gitUser = $gitClient->getAuthenticatedUser($accessToken);
if(!empty($gitUser)){
// Getting user profile details
$gitUserData = array();
$gitUserData['oauth_uid'] = !empty($gitUser->id)?$gitUser->id:'';
$gitUserData['name'] = !empty($gitUser->name)?$gitUser->name:'';
$gitUserData['username'] = !empty($gitUser->login)?$gitUser->login:'';
$gitUserData['email'] = !empty($gitUser->email)?$gitUser->email:'';
$gitUserData['location'] = !empty($gitUser->location)?$gitUser->location:'';
$gitUserData['picture'] = !empty($gitUser->avatar_url)?$gitUser->avatar_url:'';
$gitUserData['link'] = !empty($gitUser->html_url)?$gitUser->html_url:'';
// Insert or update user data to the database
$gitUserData['oauth_provider'] = 'github';
$userData = $user->checkUser($gitUserData);
// Storing user data in the session
$_SESSION['userData'] = $userData;
// Render Github profile data
$output = '<h2>GitHub Account Details</h2>';
$output .= '<div class="ac-data">';
$output .= '<img src="'.$userData['picture'].'">';
$output .= '<p><b>ID:</b> '.$userData['oauth_uid'].'</p>';
$output .= '<p><b>Name:</b> '.$userData['name'].'</p>';
$output .= '<p><b>Login Username:</b> '.$userData['username'].'</p>';
$output .= '<p><b>Email:</b> '.$userData['email'].'</p>';
$output .= '<p><b>Location:</b> '.$userData['location'].'</p>';
$output .= '<p><b>Profile Link:</b> <a href="'.$userData['link'].'" target="_blank">Click to visit GitHub page</a></p>';
$output .= '<p>Logout from <a href="logout.php">GitHub</a></p>';
$output .= '</div>';
}else{
$output = '<h3 style="color:red">Something went wrong, please try again!</h3>';
}
}elseif(isset($_GET['code'])){
// Verify the state matches the stored state
if(!$_GET['state'] || $_SESSION['state'] != $_GET['state']) {
header("Location: ".$_SERVER['PHP_SELF']);
}
// Exchange the auth code for a token
$accessToken = $gitClient->getAccessToken($_GET['state'], $_GET['code']);
$_SESSION['access_token'] = $accessToken;
header('Location: ./');
}else{
// Generate a random hash and store in the session for security
$_SESSION['state'] = hash('sha256', microtime(TRUE) . rand() . $_SERVER['REMOTE_ADDR']);
// Remove access token from the session
unset($_SESSION['access_token']);
// Get the URL to authorize
$authUrl = $gitClient->getAuthorizeURL($_SESSION['state']);
// Render Github login button
$output = '<a href="'.htmlspecialchars($authUrl).'"><img src="images/github-login.png"></a>';
}
?>
<div class="container">
<!-- Display login button / GitHub profile information -->
<?php echo $output; ?>
</div>
The logout.php
file logs the user out from their Github account.
<?php
// Start session
if(!session_id()){
session_start();
}
// Remove access token and state from session
unset($_SESSION['access_token']);
unset($_SESSION['state']);
// Remove user data from session
unset($_SESSION['userData']);
// Redirect to the homepage
header("Location:index.php");
?>
Our GitHub OAuth PHP Library helps to integrate Login with Github in PHP. You can easily implement the Github OAuth login system in the web application. Also, the example code functionality can be extended as per your application needs. We also recommend you add other social accounts in the PHP login system for providing a user-friendly way to allow the user to log in to your website.
Do you want to get implementation help, or enhance the functionality of this script? Click here to Submit Service Request
Where to find src/Github_OAuth_Client.php?
Download the source code.
How would you integrate this with your own user table’s password field?
Hi,
It was a very good article. thanks for the sharing. Will you please also write an article about single-click login in PHP with google account.
Regards,
We will try to publish your requested tutorial soon. Please stay connected with us to get notified about the new tutorial.