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.

@ibreakthecloud

This comment has been minimized.

Copy link

ibreakthecloud 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;
}
@Sad0k

This comment has been minimized.

Copy link

Sad0k commented Apr 20, 2020

can you please give us a simple example of OAuth2 server side application that can be accessed using this code.

@martin-programming

This comment has been minimized.

Copy link

martin-programming commented Jun 29, 2020

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.

puts some respect on curl!

@martin-programming

This comment has been minimized.

Copy link

martin-programming commented Jun 29, 2020

I have a working PHP codes for Github OAuth

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

BULLSHIT!!!

@martin-programming

This comment has been minimized.

Copy link

martin-programming commented Jun 29, 2020

@MrStonedOne You better show some respect to PHP

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.