Skip to content

Instantly share code, notes, and snippets.

@asika32764
Last active January 28, 2024 19:44
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save asika32764/b204ff4799d577fd4eef to your computer and use it in GitHub Desktop.
Save asika32764/b204ff4799d577fd4eef to your computer and use it in GitHub Desktop.
Simple PHP example of using Github's OAuth 2 API. (Please see comments for PHP 8.1 later and latest API version.)
<?php
define('OAUTH2_CLIENT_ID', '');
define('OAUTH2_CLIENT_SECRET', '');
$authorizeURL = 'https://github.com/login/oauth/authorize';
$tokenURL = 'https://github.com/login/oauth/access_token';
$apiURLBase = 'https://api.github.com/';
session_start();
// Start the login process by sending the user to Github's authorization page
if(get('action') == 'login') {
// Generate a random hash and store in the session for security
$_SESSION['state'] = hash('sha256', microtime(TRUE).rand().$_SERVER['REMOTE_ADDR']);
unset($_SESSION['access_token']);
$params = array(
'client_id' => OAUTH2_CLIENT_ID,
'redirect_uri' => 'http://' . $_SERVER['SERVER_NAME'] . $_SERVER['PHP_SELF'],
'scope' => 'user',
'state' => $_SESSION['state']
);
// Redirect the user to Github's authorization page
header('Location: ' . $authorizeURL . '?' . http_build_query($params));
die();
}
// When Github redirects the user back here, there will be a "code" and "state" parameter in the query string
if(get('code')) {
// Verify the state matches our stored state
if(!get('state') || $_SESSION['state'] != get('state')) {
header('Location: ' . $_SERVER['PHP_SELF']);
die();
}
// Exchange the auth code for a token
$token = apiRequest($tokenURL, array(
'client_id' => OAUTH2_CLIENT_ID,
'client_secret' => OAUTH2_CLIENT_SECRET,
'redirect_uri' => 'http://' . $_SERVER['SERVER_NAME'] . $_SERVER['PHP_SELF'],
'state' => $_SESSION['state'],
'code' => get('code')
));
$_SESSION['access_token'] = $token->access_token;
header('Location: ' . $_SERVER['PHP_SELF']);
}
if(session('access_token')) {
$user = apiRequest($apiURLBase . 'user');
echo '<h3>Logged In</h3>';
echo '<h4>' . $user->name . '</h4>';
echo '<pre>';
print_r($user);
echo '</pre>';
} else {
echo '<h3>Not logged in</h3>';
echo '<p><a href="?action=login">Log In</a></p>';
}
function apiRequest($url, $post=FALSE, $headers=array()) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
if($post)
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post));
$headers[] = 'Accept: application/json';
if(session('access_token'))
$headers[] = 'Authorization: Bearer ' . session('access_token');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$response = curl_exec($ch);
return json_decode($response);
}
function get($key, $default=NULL) {
return array_key_exists($key, $_GET) ? $_GET[$key] : $default;
}
function session($key, $default=NULL) {
return array_key_exists($key, $_SESSION) ? $_SESSION[$key] : $default;
}
@Bruno-Meowtel
Copy link

Bruno-Meowtel commented Jan 14, 2022

This was super helpful, Thanks!

It still works 9 years later, you just need to add a User-Agent (now required by Github):

To add in the apiRequest() method:

curl_setopt($ch, CURLOPT_USERAGENT, 'Your User-Agent');

@tkr-sh
Copy link

tkr-sh commented Jun 15, 2022

This was super helpful, Thanks!

It still works 9 years later, you just need to add a User-Agent (now required by Github):

To add in the apiRequest() method:

curl_setopt($ch, CURLOPT_USERAGENT, 'Your User-Agent');

From what I saw, the 'User-Agent' is only to "convert" the access_token to the user info; and you don't need to include it for every api Request.

And also, for thoses who don't know, User-Agent is either your Github name or your app name.

Source:
https://docs.github.com/en/rest/overview/resources-in-the-rest-api#user-agent-required

Copy link

ghost commented Jul 11, 2022

<?php
# add github credentials
define('OAUTH2_CLIENT_ID', ''); //add client id here
define('OAUTH2_CLIENT_SECRET', ''); //add client secret here

# URL of github api
$authorizeURL = 'https://github.com/login/oauth/authorize';
$tokenURL = 'https://github.com/login/oauth/access_token';
$apiURLBase = 'https://api.github.com/';

# start sessions
session_start();

// Start the login process by sending the user to Github's authorization page
if(get('action') == 'login') {
  // Generate a random hash and store in the session for security
  $_SESSION['state'] = hash('sha256', microtime(TRUE).rand().$_SERVER['REMOTE_ADDR']);
  unset($_SESSION['access_token']);

  $params = array(
    'client_id' => OAUTH2_CLIENT_ID,
    'redirect_uri' => 'http://' . $_SERVER['SERVER_NAME'] . $_SERVER['PHP_SELF'],
    'scope' => 'user',
    'state' => $_SESSION['state']
  );

  // Redirect the user to Github's authorization page
  header('Location: ' . $authorizeURL . '?' . http_build_query($params));
  die();
}

// to kill all Sessions and reset code base 
if(get('action') == 'exit') {
    unset($_SESSION['state']);
    unset($_SESSION['access_token']);
    session_destroy();
    exit();
}

// When Github redirects the user back here, there will be a "code" and "state" parameter in the query string
if(get('code')) {
  // Verify the state matches our stored state
  if(!get('state') || $_SESSION['state'] != get('state')) {
    header('Location: ' . $_SERVER['PHP_SELF']);
    die();
  }

  // Exchange the auth code for a token
  $token = apiRequest($tokenURL, array(
    'client_id' => OAUTH2_CLIENT_ID,
    'client_secret' => OAUTH2_CLIENT_SECRET,
    'redirect_uri' => 'http://' . $_SERVER['SERVER_NAME'] . $_SERVER['PHP_SELF'],
    'state' => $_SESSION['state'],
    'code' => get('code')
  ));
  $_SESSION['access_token'] = $token->access_token;

  header('Location: ' . $_SERVER['PHP_SELF']);
}

# if successful show results
if(session('access_token')) {
  $user = apiRequest($apiURLBase.'user');

  echo '<h3>Logged In</h3>';
  echo '<h4>' . $user->login . '</h4>';
  echo '<pre>';
  print_r($user);
  echo '</pre>';

  
#print out full list of urls of github  
  print '<br /><br />';
  print '<h3>Full List of Urls on Github</h3>';
  $full = apiRequest($apiURLBase);
  foreach ($full as $key=>$value)
  {
      print $key .'=>'. $value.'<br />';
  }

} else {

# fail result if no session token
  echo '<h3>Not logged in</h3>';
  echo '<p><a href="?action=login">Log In</a></p>';
}

# main function for curl requests
function apiRequest($url, $post=FALSE, $headers=array()) {
  $ch = curl_init($url);

  curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  curl_setopt($ch, CURLOPT_USERAGENT, 'Linux useragent'); //change agent string

  if($post)
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post));

  $headers[] = 'Accept: application/json';

  # add access token to header 
  if(session('access_token'))
    $headers[] = 'Authorization: Bearer ' . session('access_token');

  curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

  $response = curl_exec($ch);
  return json_decode($response); //decode response
}

# array key existence
function get($key, $default=NULL) {
  return array_key_exists($key, $_GET) ? $_GET[$key] : $default;
}

# array key existence
function session($key, $default=NULL) {
  return array_key_exists($key, $_SESSION) ? $_SESSION[$key] : $default;
}
?>

KUDO'S TO ORIGINAL AUTHOR
-> user agent now required for all calls
-> if no user agent in curl request - Warning: Attempt to read property "name" on null --- now called "login"
-> php 8.1.7 compatible
-> copy paste solution for devs who don't have time for guess work
-> hope it helps somebody.

@edutrul
Copy link

edutrul commented Sep 7, 2022

Thank you so much for sharing this quick piece of code. I have tested, but it didn't work because it lacked of
"https" so I updated the piece of code below...:

<?php

// Code taken from https://gist.github.com/asika32764/b204ff4799d577fd4eef
// Code changes by @edutrul "added https" in all responses
// Makes sure when creating the app you deploy to a hosting/cloud
// If you want to do it quickly then use heroku.
// When adding the app in github make sure you just add the domain name like https://example.com
// Notice the "https" being added in the callback, website and other fields in github page.

define('OAUTH2_CLIENT_ID', '<YOUR CLIENT ID>');
define('OAUTH2_CLIENT_SECRET', '<YOUR CLIENT SECRET GENERATED ONCE in GITHUB APP - make sure to take notes>');

# URL of github api
$authorizeURL = 'https://github.com/login/oauth/authorize';
$tokenURL = 'https://github.com/login/oauth/access_token';
$apiURLBase = 'https://api.github.com/';

# start sessions
session_start();

print_r($_SESSION);

// Start the login process by sending the user to Github's authorization page
if (get('action') == 'login') {
  // Generate a random hash and store in the session for security
  $_SESSION['state'] = hash('sha256', microtime(TRUE).rand().$_SERVER['REMOTE_ADDR']);
  unset($_SESSION['access_token']);

  $params = array(
    'client_id' => OAUTH2_CLIENT_ID,
    'redirect_uri' => 'https://' . $_SERVER['SERVER_NAME'] . $_SERVER['PHP_SELF'],
    'scope' => 'user',
    'state' => $_SESSION['state']
  );

  // Redirect the user to Github's authorization page
  header('Location: ' . $authorizeURL . '?' . http_build_query($params));
  die();
}

// to kill all Sessions and reset code base
if (get('action') == 'exit') {
  unset($_SESSION['state']);
  unset($_SESSION['access_token']);
  session_destroy();
  exit();
}

// When Github redirects the user back here, there will be a "code" and "state" parameter in the query string
if (get('code')) {
  // Verify the state matches our stored state
  if(!get('state') || $_SESSION['state'] != get('state')) {
    header('Location: ' . $_SERVER['PHP_SELF']);
    die();
  }

  // Exchange the auth code for a token
  $token = apiRequest($tokenURL, array(
    'client_id' => OAUTH2_CLIENT_ID,
    'client_secret' => OAUTH2_CLIENT_SECRET,
    'redirect_uri' => 'https://' . $_SERVER['SERVER_NAME'] . $_SERVER['PHP_SELF'],
    'state' => $_SESSION['state'],
    'code' => get('code')
  ));
  $_SESSION['access_token'] = $token->access_token;

  header('Location: ' . $_SERVER['PHP_SELF']);
}

# if successful show results
if (session('access_token')) {
  $user = apiRequest($apiURLBase.'user');

  echo '<h3>Logged In</h3>';
  echo '<h4>' . $user->login . '</h4>';
  echo '<pre>';
  print_r($user);
  echo '</pre>';


# print out full list of urls of github
  print '<br /><br />';
  print '<h3>Full List of Urls on Github</h3>';
  $full = apiRequest($apiURLBase);
  foreach ($full as $key=>$value)
  {
    print $key .'=>'. $value.'<br />';
  }

} else {

# fail result if no session token
  echo '<h3>Not logged in</h3>';
  echo '<p><a href="?action=login">Log In</a></p>';
}

# main function for curl requests
function apiRequest($url, $post=FALSE, $headers=array()) {
  $ch = curl_init($url);

  curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  curl_setopt($ch, CURLOPT_USERAGENT, 'Linux useragent'); //change agent string

  if($post)
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post));

  $headers[] = 'Accept: application/json';

  # add access token to header
  if(session('access_token'))
    $headers[] = 'Authorization: Bearer ' . session('access_token');

  curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

  $response = curl_exec($ch);
  return json_decode($response); //decode response
}

# array key existence
function get($key, $default=NULL) {
  return array_key_exists($key, $_GET) ? $_GET[$key] : $default;
}

# array key existence
function session($key, $default=NULL) {
  return array_key_exists($key, $_SESSION) ? $_SESSION[$key] : $default;
}
?>

Also make sure you add https

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment