Explanation of Oauth Authorization Code-Php Oauth2 Implementation

> What is Oauth2?

Oauth is an Open Network Identity. The current version is 2.0, so it is called Oauth2.

> Why use Oauth2?

For example, if you want to log on to XX website, but XX website needs to register, it is very troublesome, and if all websites need to log on, it is very difficult to remember, then if we only register a website, other websites will kill two birds with one stone through our login status on this XXX website! And we can get the public information of XX website, such as nickname, city, and so on. It also facilitates the expansion of other website information.

> Authorization process

  +--------+                               +---------------+
     |        |--(A)- Authorization Request ->|   Resource    |
     |        |                               |     Owner     |
     |        |<-(B)-- Authorization Grant ---|               |
     |        |                               +---------------+
     |        |
     |        |                               +---------------+
     |        |--(C)-- Authorization Grant -->| Authorization |
     | Client |                               |     Server    |
     |        |<-(D)----- Access Token -------|               |
     |        |                               +---------------+
     |        |
     |        |                               +---------------+
     |        |--(E)----- Access Token ------>|    Resource   |
     |        |                               |     Server    |
     |        |<-(F)--- Protected Resource ---|               |
     +--------+                               +---------------+

Extracted from RFC6749

Client Authorization Mode

  • Authorization code
  • Simplified Patterns (implicit)
  • Resource owner password credentials
  • Client Credentials

Authorization code form:

  +----------+
     | Resource |
     |   Owner  |
     |          |
     +----------+
          ^
          |
         (B)
     +----|-----+          Client Identifier      +---------------+
     |         -+----(A)-- & Redirection URI ---->|               |
     |  User-   |                                 | Authorization |
     |  Agent  -+----(B)-- User authenticates --->|     Server    |
     |          |                                 |               |
     |         -+----(C)-- Authorization Code ---<|               |
     +-|----|---+                                 +---------------+
       |    |                                         ^      v
      (A)  (C)                                        |      |
       |    |                                         |      |
       ^    v                                         |      |
     +---------+                                      |      |
     |         |>---(D)-- Authorization Code ---------'      |
     |  Client |          & Redirection URI                  |
     |         |                                             |
     |         |<---(E)----- Access Token -------------------'
     +---------+       (w/ Optional Refresh Token)

(A) The user accesses the client, which forwards it to the authentication server

(B) The user chooses whether to authorize the client

(C) If the user is authorized, the authentication server directs the user to the uri set up beforehand, with an auth_code attached.

(D) The client receives the authorization code, attaches an earlier URI, and requests a token from the authentication server.

(E) The authentication server checks the authorization code and redirects the URI, confirms that it is correct, and sends access token and refresh token to the client.

Actual combat:

So let's talk about how to use php to build Oauth2

First we install a composer dependency

composer require bshaffer/oauth2-server-php "~1.8" (provided you install composer dependencies)

OR uses git clone

mkdir my-oauth2-walkthrough
cd my-oauth2-walkthrough
git clone https://github.com/bshaffer/oauth2-server-php.git -b master

Create tables after downloading

CREATE TABLE oauth_clients (client_id VARCHAR(80) NOT NULL, client_secret VARCHAR(80), redirect_uri VARCHAR(2000) NOT NULL, grant_types VARCHAR(80), scope VARCHAR(100), user_id VARCHAR(80), CONSTRAINT clients_client_id_pk PRIMARY KEY (client_id));
CREATE TABLE oauth_access_tokens (access_token VARCHAR(40) NOT NULL, client_id VARCHAR(80) NOT NULL, user_id VARCHAR(255), expires TIMESTAMP NOT NULL, scope VARCHAR(2000), CONSTRAINT access_token_pk PRIMARY KEY (access_token));
CREATE TABLE oauth_authorization_codes (authorization_code VARCHAR(40) NOT NULL, client_id VARCHAR(80) NOT NULL, user_id VARCHAR(255), redirect_uri VARCHAR(2000), expires TIMESTAMP NOT NULL, scope VARCHAR(2000), CONSTRAINT auth_code_pk PRIMARY KEY (authorization_code));
CREATE TABLE oauth_refresh_tokens (refresh_token VARCHAR(40) NOT NULL, client_id VARCHAR(80) NOT NULL, user_id VARCHAR(255), expires TIMESTAMP NOT NULL, scope VARCHAR(2000), CONSTRAINT refresh_token_pk PRIMARY KEY (refresh_token));
CREATE TABLE oauth_users (username VARCHAR(255) NOT NULL, password VARCHAR(2000), first_name VARCHAR(255), last_name VARCHAR(255), CONSTRAINT username_pk PRIMARY KEY (username));
CREATE TABLE oauth_scopes (scope TEXT, is_default BOOLEAN);
CREATE TABLE oauth_jwt (client_id VARCHAR(80) NOT NULL, subject VARCHAR(80), public_key VARCHAR(2000), CONSTRAINT jwt_client_id_pk PRIMARY KEY (client_id));

Create a BootsTrap boot file [server.php]

Bootstrap your OAuth2 Server

We need to create and configure our OAuth2 Server object. This will be used by all the endpoints in our application. Name this file server.php:

$dsn      = 'mysql:dbname=my_oauth2_db;host=localhost';
$username = 'root';
$password = '';

// error reporting (this is a demo, after all!)
ini_set('display_errors',1);error_reporting(E_ALL);

// Autoloading (composer is preferred, but for this example let's just do this)
require_once('oauth2-server-php/src/OAuth2/Autoloader.php');
OAuth2\Autoloader::register();

// $dsn is the Data Source Name for your database, for exmaple "mysql:dbname=my_oauth2_db;host=localhost"
$storage = new OAuth2\Storage\Pdo(array('dsn' => $dsn, 'username' => $username, 'password' => $password));

// Pass a storage object or array of storage objects to the OAuth2 server class
$server = new OAuth2\Server($storage);

// Add the "Client Credentials" grant type (it is the simplest of the grant types)
$server->addGrantType(new OAuth2\GrantType\ClientCredentials($storage));

// Add the "Authorization Code" grant type (this is where the oauth magic happens)
$server->addGrantType(new OAuth2\GrantType\AuthorizationCode($storage));

Create a Token Controller [tonken.php] to get access_token through the authorization code

// include our OAuth2 Server object
require_once __DIR__.'/server.php';

// Handle a request for an OAuth2.0 Access Token and send the response to the client
$server->handleTokenRequest(OAuth2\Request::createFromGlobals())->send();

Insert a record to oauth_clients, ps: Like other companies, it's usually necessary to apply for an audit before inserting a record.

INSERT INTO oauth_clients (client_id, client_secret, redirect_uri) VALUES ("testclient", "testpass", "http://fake/");

Create a resource controller resource.php to make resource requests after getting access_token

require_once __DIR__.'/server.php';

//echo file_put_contents("test.txt",json_encode($_POST));
//var_dump($_POST);die;
if(!$server->verifyResourceRequest(OAuth2\Request::createFromGlobals())){
    $server->getResponse()->send();
    die;
}

$token = $server->getAccessTokenData(OAuth2\Request::createFromGlobals());

Authorization page, asking the user if authorize.php is authorized

require_once __DIR__.'/server.php';

$request = OAuth2\Request::createFromGlobals();
$response = new OAuth2\Response();

// validate the authorize request
if (!$server->validateAuthorizeRequest($request, $response)) {
    $response->send();
    die;
}
// display an authorization form
if (empty($_POST)) {
  exit('
<form method="post">
  <label>Do You Authorize TestClient?</label><br />
  <input type="submit" name="authorized" value="yes">
  <input type="submit" name="authorized" value="no">
</form>');
}

// print the authorization code if the user has authorized your client
$is_authorized = ($_POST['authorized'] === 'yes');
$server->handleAuthorizeRequest($request, $response, $is_authorized);
<!--if ($is_authorized) {-->
<!--  // this is only here so that you get to see your code in the cURL request. Otherwise, we'd redirect back to the client-->
<!--  $code = substr($response->getHttpHeader('Location'), strpos($response->getHttpHeader('Location'), 'code=')+5, 40);-->
<!--  exit("SUCCESS! Authorization Code: $code");-->
<!--}-->
$response->send();

After api.php gets the user authorization code, it calls back, calls back the content, and uses curl to make the post request.

<?php

require_once __DIR__ . '/server.php';
//Is the authorization code empty?
$code = empty($_GET['code']) ? '' : $_GET['code'];
//Default parameters
$config = array('client_id' => 'testclient', 'client_secret' => 'testpass');
$query = array(
    //Authorization Category
    'grant_type' => 'authorization_code',
    //Authorization code
    'code' => $code,
    'client_id' => $config['client_id'],
    'client_secret' => $config['client_secret'],
);
//Simulated Post Request for access_token
$url = "http://127.0.0.1:8881/token.php";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($query));
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
$output = curl_exec($ch);
curl_close($ch);
$res = json_decode($output, true);

//Simulate post with access_token
$resource = array('access_token' => $res['access_token']);
$url = "http://127.0.0.1:8881/resource.php";
//$header = 'Content-Type:application/x-www-form-urlencoded';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
//must be http_build_query_build to convert the array format to url-encode mode
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($resource));
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));
$info = curl_getinfo($ch);
$output = curl_exec($ch);
curl_close($ch);
var_dump($info);
//var_dump($info1);

var_dump($output);

We can get user_id by accessing resources, and the Oauth2 process is over. Thank you.~

Keywords: PHP git MySQL curl

Added by scanreg on Sun, 07 Jul 2019 00:48:49 +0300