OAuth2 Server

Submitted by admin on So, 11.12.2016 - 11:35

Annahmen

  • Als Backend wird ein Active Directory Server (hier Samba 4) verwendet
  • Als lokale OAuth2 Datenbank wird MySQL verwendet
  • Der Apache Webserver wurde für https konfiguriert, http muss aus Sicherheitsgründen komplett abgeschaltet werden.

Voraussetzungen

Zunächst muss ein Webserver installiert werden, der den OAuth2 Webservice bereitstellt. Der Webserver benötigt noch eine SQL Datenbank, die Statusdaten der einzelnen Sessions speichert. In diesem Fall wird MariaDB/MySQL verwendet. Unter Debian bzw. Ubuntu werden zunächst folgende Pakete installiert:

  • libapache2-mod-php5
  • php5-cli
  • php5-json
  • php5-ldap
  • php5-mysqlnd
  • git-core

GIT wird benötigt, um die OAuth2 Library zu installieren.

Installation

cd /usr/src
git clone https://github.com/bshaffer/oauth2-server-php.git
cp -a oauth2-server-php/src/OAuth2 /var/www/html/

OAuth2 Webcontent

server.php

<?php
$dsn      = 'mysql:dbname=oauth;host=mysql.lan';
$username = 'oauth';
$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/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));
?>

resource.php

<?php
require_once __DIR__.'/server.php';

if (!$server->verifyResourceRequest(OAuth2\Request::createFromGlobals())) {
    $server->getResponse()->send();
    die;
}

$token = $server->getAccessTokenData(OAuth2\Request::createFromGlobals());
$json_userdata=$token['user_id'];
echo $json_userdata;
?>

token.php

<?php
require_once __DIR__.'/server.php';
$server->handleTokenRequest(OAuth2\Request::createFromGlobals())->send();
?>

authorize.php

<?php
// include our OAuth2 Server object
require_once __DIR__.'/server.php';
require_once __DIR__.'/ldap.inc';
require_once __DIR__.'/displayForm.inc';

$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)) {
  displayLoginForm();
  exit();
}

// print the authorization code if the user has authorized your client
$username=preg_replace ('/@/', '#', $_POST['username']);
$password = $_POST['password'];
$userdata=ldapBind($username, $password);
$is_authorized = ($userdata!=false);

$server->handleAuthorizeRequest($request, $response, $is_authorized);
if ($is_authorized) {
  //TODO: Write userdata to database
  for ($i=0; $i<$userdata["count"]; $i++) {
    if($userdata['count'] > 1)
     break;
     $json_userdata=json_encode(array(
        'id' => $userdata[$i]["uidnumber"][0],
        "user_login" => $userdata[$i]["samaccountname"][0],
        "emails" => $userdata[$i]["mail"],
        "display_name" => $userdata[$i]["displayname"][0],
	    "user_nicename" => $userdata[$i]["sn"][0]." ".$userdata[$i]["givenname"][0],
        "user_registered" => $userdata[$i]["whencreated"][0],
    ));

    $server->handleAuthorizeRequest($request, $response, $is_authorized, $json_userdata);
    }
}
$response->send();
?>

displayForm.inc

Die hier zu definierende Funktion displayForm() hat lediglich ein HTML Formular auszugeben, das die Felder username und password als POST Request sendet.

ldap.inc

Die Implementierung der Funktion ldapBind als Beispiel für einen Active Directory Server. Es wird ein LDAP Auth mit den user Credentials durchgeführt, es werden also keine administrativen User benötigt.

<?php

function ldapBind ($username,$password)
{
    $adServer = "ldaps://my.dom";
    $adDomain = "dc=MY,dc=DOM";

    $ldap = ldap_connect($adServer);

    $ldaprdn = $username.'@my.dom';

    ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
    ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);

    $bind = @ldap_bind($ldap, $ldaprdn, $password);

    if ($bind) {
        $filter="(sAMAccountName=$username)";
        $result = ldap_search($ldap, $adDomain, $filter);
        ldap_sort($ldap,$result,"sn");
        $info = ldap_get_entries($ldap, $result);
        @ldap_close($ldap);
        return $info;
    } else {
        return false;
    }
}

Anmerkung: Diese Lösung funktioniert auch mit PHP7