Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Simple PHP example of using Github's OAuth 2 API
<?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;
}
@Xeoncross

This comment has been minimized.

Copy link

Xeoncross commented Sep 4, 2012

array_key_exists() isn't required because it's impossible for a user input param to be NULL. Use isset().

@waylandzhang

This comment has been minimized.

Copy link

waylandzhang commented Apr 13, 2015

Thanks this is a nice code Gist. However as described in Github's newest API, we need to pass the following 'User-Agent' header value in order to get this code work now.

$headers[] = 'User-Agent: YOUR_APP_NAME';

@irfan88

This comment has been minimized.

Copy link

irfan88 commented Jun 27, 2016

i can't get $response

@achim-hl

This comment has been minimized.

Copy link

achim-hl commented Feb 15, 2017

@waylandzhang: Thanks, you saved my day!

@produktive

This comment has been minimized.

Copy link

produktive commented Feb 21, 2017

@Xeoncross Are you saying to get rid of the get() and session() functions and instead use isset($_GET['key']) and isset($_SESSION['key']) instead?

@Pepijn1908

This comment has been minimized.

Copy link

Pepijn1908 commented Jul 4, 2017

@produktive Yes. :)

@MrStonedOne

This comment has been minimized.

Copy link

MrStonedOne commented Sep 19, 2017

Why the hell would you use curl for this when file_get_contents with a http context fully supports everything you need to do AND doesn't require a extension be installed.

You threw away portability for seemingly no reason.

@ctubio

This comment has been minimized.

Copy link

ctubio commented Jan 2, 2018

@MrStonedOne show some respect to cURL and check yourself the benchmarks against file_get_contents; you will discover why ppl use cURL faster than what you expect.

@harshvkarn

This comment has been minimized.

Copy link

harshvkarn commented Jan 14, 2018

I have a working PHP codes for Github OAuth

https://gist.github.com/harshvkarn/ce6aa436cecf5388c5c6d275a3d5c108

@gplcart

This comment has been minimized.

Copy link

gplcart commented Feb 5, 2018

@MrStonedOne

Why the hell would you use curl for this

file_get_contents requires allow_url_fopen, so it will not work on many cheap hostings

@jessp01

This comment has been minimized.

Copy link

jessp01 commented Oct 16, 2019

Thanks for this. Saved me some time. Here's a revised example that sets the User Agent header and dynamically detects the protocol rather than assume HTTP:

<?php
define('OAUTH2_CLIENT_ID', '');
define('OAUTH2_CLIENT_SECRET', '');
// see https://developer.github.com/v3/#user-agent-required
define('APP_NAME','GH WHATEVER');

$authorizeURL = 'https://github.com/login/oauth/authorize';
$tokenURL = 'https://github.com/login/oauth/access_token';
$apiURLBase = 'https://api.github.com';
// or, in the case of https://education.github.com/pack, uncomment this:
//$apiURLBase = 'https://education.github.com/api';

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' => $_SERVER['SERVER_PROTOCOL'].'://' . $_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' => $_SERVER['SERVER_PROTOCOL']. '://' . $_SERVER['SERVER_NAME'] . $_SERVER['PHP_SELF'],
    'state' => $_SESSION['state'],
    'User-Agent' => APP_NAME,
    'code' => get('code')
  ));
  $_SESSION['access_token'] = $token->access_token;
  header('Location: ' . $_SERVER['PHP_SELF']);
}

if(session('access_token')) {
  $response = apiRequest($apiURLBase. '/user');
  echo '<h3>Logged In</h3>';
  echo '<pre>';
  print_r($response);
  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');
    $headers[] = 'User-Agent:' . APP_NAME;
  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;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.