authentication in progress; sso with cas and some views implemented

parent 07eb4fb5
......@@ -54,22 +54,77 @@ $container['events'] = function ($c) {
);
};
// Database
$container['db'] = function ($c) {
$settings = $c->get('settings');
try {
$pdo = new \PDO(
$settings['db']['dsn'],
$settings['db']['user'],
$settings['db']['pass'],
$settings['db']['options']
);
return $pdo;
} catch (\PDOException $e) {
$c->get('logger')->error($e->getMessage());
return;
}
};
// Authentication service
$container['Service\\Authentication\\Adapter'] = function ($c) {
return new \GrEduLabs\Authentication\Adapter\Events($c->get('events'));
$container['Service\\Authentication\\DbAdapter'] = function ($c) {
return new \GrEduLabs\Authentication\Adapter\Pdo($c->get('db'));
};
$container['Service\\Authentication\\CasAdapter'] = function ($c) {
$settings = $c->get('settings');
return new GrEduLabs\Authentication\Adapter\Cas($settings['phpcas']);
};
$container['Service\\Authentication\\Storage'] = function ($c) {
return new \GrEduLabs\Authentication\Storage\PhpSession($_SESSION);
};
$container['Service\\Authentication'] = function ($c) {
return new \Zend\Authentication\AuthenticationService(
$c->get('Service\\Authentication\\Storage')
);
};
// Actions
$service = new \Zend\Authentication\AuthenticationService(
$c->get('Service\\Authentication\\Storage'),
$c->get('Service\\Authentication\\Adapter')
$container['GrEduLabs\\Action\\User\\Login'] = function ($c) {
return new GrEduLabs\Action\User\Login(
$c->get('view'),
function ($identity, $credential) use ($c) {
$service = $c->get('Service\\Authentication');
$adapter = $c->get('Service\\Authentication\\DbAdapter');
$adapter->setIdentity($identity)
->setCredential($credential);
return $service->authenticate($adapter);
}
);
};
return $service;
$container['GrEduLabs\\Action\\User\\LoginSso'] = function ($c) {
return new GrEduLabs\Action\User\LoginSso(function () use ($c) {
$service = $c->get('Service\\Authentication');
$adapter = $c->get('Service\\Authentication\\CasAdapter');
return $service->authenticate($adapter);
});
};
$container['GrEduLabs\\Action\\User\\Logout'] = function ($c) {
return new GrEduLabs\Action\User\Logout(
$c->get('Service\\Authentication'),
$c->get('router')->pathFor('index')
);
};
......@@ -17,4 +17,13 @@ $app->get('/', function ($request, $response, $args) use ($app) {
$view->render($response, 'home.twig');
return $response;
})->setName('index');
// authentication
$app->group('/user', function () {
$this->map(['GET', 'POST'], '/login', 'GrEduLabs\\Action\\User\\Login')->setName('user.login');
$this->get('/login-sso', 'GrEduLabs\\Action\\User\\LoginSso')->setName('user.loginSso');
$this->get('/logout', 'GrEduLabs\\Action\\User\\Logout')->setName('user.logout');
$this->get('/profile', 'GrEduLabs\\Action\\User\\Profile')->setName('user.profile');
});
<?php
/**
* gredu_labs
*
* @link https://github.com/eellak/gredu_labs for the canonical source repository
* @copyright Copyright (c) 2008-2015 Greek Free/Open Source Software Society (https://gfoss.ellak.gr/)
* @license GNU GPLv3 http://www.gnu.org/licenses/gpl-3.0-standalone.html
*/
namespace GrEduLabs\Action\User;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Slim\Views\Twig;
class Login
{
/**
* @var Twig
*/
protected $view;
/**
* @var callable
*/
protected $authenticate;
/**
* Constructor
* @param Twig $view
*/
public function __construct(
Twig $view,
callable $authenticate
) {
$this->view = $view;
$this->authenticate = $authenticate;
}
public function __invoke(ServerRequestInterface $req, ResponseInterface $res, array $args = [])
{
if ($req->isPost()) {
$authenticate = $this->authenticate;
$result = $authenticate(
$req->getParam('email'),
$req->getParam('password')
);
var_dump($result);
}
return $this->view->render($res, 'user/login.twig');
}
}
<?php
/**
* gredu_labs
*
* @link https://github.com/eellak/gredu_labs for the canonical source repository
* @copyright Copyright (c) 2008-2015 Greek Free/Open Source Software Society (https://gfoss.ellak.gr/)
* @license GNU GPLv3 http://www.gnu.org/licenses/gpl-3.0-standalone.html
*/
namespace GrEduLabs\Action\User;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Slim\Views\Twig;
class LoginSso
{
/**
* @var callable
*/
protected $authenticate;
/**
* Constructor
* @param Twig $view
*/
public function __construct(callable $authenticate)
{
$this->authenticate = $authenticate;
}
public function __invoke(ServerRequestInterface $req, ResponseInterface $res, array $args = [])
{
$authenticate = $this->authenticate;
$result = $authenticate();
var_dump($result);
return $res;
}
}
<?php
/**
* gredu_labs
*
* @link https://github.com/eellak/gredu_labs for the canonical source repository
* @copyright Copyright (c) 2008-2015 Greek Free/Open Source Software Society (https://gfoss.ellak.gr/)
* @license GNU GPLv3 http://www.gnu.org/licenses/gpl-3.0-standalone.html
*/
namespace GrEduLabs\Action\User;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Zend\Authentication\AuthenticationServiceInterface;
class Logout
{
/**
* @var AuthenticationServiceInterface
*/
protected $authService;
/**
* @var string
*/
protected $redirectUrl;
public function __construct(
AuthenticationServiceInterface $authService,
$redirectUrl
) {
$this->authService = $authService;
$this->router = $router;
$this->redirectUrl = $redirectUrl;
}
public function __invoke(ServerRequestInterface $req, ResponseInterface $res, array $args = [])
{
if ($this->authService->hasIdentity()) {
$this->authService->clearIdentity();
}
return $res->withRedirect($this->redirectUrl);
}
}
<?php
/**
* gredu_labs
*
* @link https://github.com/eellak/gredu_labs for the canonical source repository
* @copyright Copyright (c) 2008-2015 Greek Free/Open Source Software Society (https://gfoss.ellak.gr/)
* @license GNU GPLv3 http://www.gnu.org/licenses/gpl-3.0-standalone.html
*/
namespace GrEduLabs\Authentication\Adapter;
use Exception;
use GrEduLabs\Authentication\Identity;
use phpCAS;
use Zend\Authentication\Adapter\AdapterInterface;
use Zend\Authentication\Result;
class Cas implements AdapterInterface
{
public function __construct(array $settings = [])
{
phpCAS::client(
$settings['serverVersion'],
$settings['serverHostname'],
$settings['serverPort'],
$settings['serverUri'],
$settings['changeSessionId']
);
if (($casServerCaCert = $settings['casServerCaCert'])) {
if ($settings['casServerCnValidate']) {
phpCAS::setCasServerCACert($casServerCaCert, true);
} else {
phpCAS::setCasServerCACert($casServerCaCert, false);
}
}
if ($settings['noCasServerValidation']) {
phpCAS::setNoCasServerValidation();
}
}
public function authenticate()
{
try {
phpCAS::handleLogoutRequests();
phpCAS::forceAuthentication();
if (!phpCAS::isAuthenticated()) {
return new Result(Result::FAILURE, null, ['Authentication failure']);
}
return new Result(
Result::SUCCESS,
self::identityFormCasAttributes(),
['Authentication success']
);
} catch (Exception $e) {
return new Result(Result::FAILURE_UNCATEGORIZED, null, [$e->getMessage()]);
}
}
private static function identityFormCasAttributes()
{
$attributes = phpCAS::getAttributes();
$identity = phpCAS::getUser();
$filterAttribute = function ($attribute) use ($attributes) {
if (!isset($attributes[$attribute])) {
return;
}
if (is_array($attributes[$attribute])) {
return $attributes[$attribute];
}
return $attributes[$attribute];
};
return new Identity(
$identity,
$filterAttribute('mail'),
$filterAttribute('cn'),
$filterAttribute('ou')
);
}
}
<?php
/**
* gredu_labs
*
* @link https://github.com/eellak/gredu_labs for the canonical source repository
* @copyright Copyright (c) 2008-2015 Greek Free/Open Source Software Society (https://gfoss.ellak.gr/)
* @license GNU GPLv3 http://www.gnu.org/licenses/gpl-3.0-standalone.html
*/
namespace GrEduLabs\Authentication\Adapter;
use PDO as PDOConnection;
use Zend\Authentication\Adapter\AbstractAdapter;
use Zend\Authentication\Result;
class Pdo extends AbstractAdapter
{
/**
* @var EventManagerInterface
*/
protected $events;
/**
* Construct adapter
*
* @param PDOConnection $db
*/
public function __construct(PDOConnection $db)
{
$this->db = $db;
}
public function authenticate()
{
return new Result(Result::FAILURE, null, ['Authentication failure']);
}
}
<?php
/**
* gredu_labs
*
* @link https://github.com/eellak/gredu_labs for the canonical source repository
* @copyright Copyright (c) 2008-2015 Greek Free/Open Source Software Society (https://gfoss.ellak.gr/)
* @license GNU GPLv3 http://www.gnu.org/licenses/gpl-3.0-standalone.html
*/
namespace GrEduLabs\Authentication;
use JsonSerializable;
class Identity implements JsonSerializable
{
protected $uid;
protected $mail;
protected $displayName;
protected $officeName;
public function __construct($uid, $mail, $displayName, $officeName)
{
$this->uid = $uid;
$this->mail = $mail;
$this->displayName = $displayName;
$this->officeName = $officeName;
}
public function __get($name)
{
if (property_exists($name, $this)) {
return $this->{$name};
}
return;
}
public function __toString()
{
return $this->displayName;
}
public function getUid()
{
return $this->uid;
}
public function toArray()
{
return [
'uid' => $this->uid,
'mail' => $this->mail,
'displayName' => $this->displayName,
'officeName' => $this->officeName,
];
}
public function jsonSerialize()
{
return $this->toArray();
}
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>GrEduLabs</title>
<link href="{{ base_url() }}/css/style.css" rel="stylesheet" type="text/css">
</head>
<body>
<h1>GrEduLabs</h1>
<div>Welcome!</div>
</body>
</html>
\ No newline at end of file
{% extends "layout.twig" %}
{% block content %}
Welcome
<a href="{{ path_for('user.login') }}">Login</a>
{% endblock %}
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>GrEduLabs</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
<link href="{{ base_url() }}/css/style.css" rel="stylesheet" type="text/css">
</head>
<body>
{% block content %}{% endblock %}
<script src="//code.jquery.com/jquery-2.2.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>
{% block inlinejs %}{% endblock %}
</body>
</html>
\ No newline at end of file
{% extends "layout.twig" %}
{% block content %}
<form method="post" action="{{ path_for('user.login') }}" id="user-login-form" class="form-horizontal">
<div class="form-group">
<label class="hidden-sm col-sm-2 control-label">Email</label>
<div class="col-xs-12 col-sm-5">
<div class="input-group">
<span class="input-group-addon">@</span>
<input name="email" type="text" value="{{ vm.username }}" class="form-control" required autocomplete="off">
</div>
</div>
</div>
<div class="form-group">
<label class="hidden-sm col-sm-2 control-label">Password</label>
<div class="col-xs-12 col-sm-5">
<div class="input-group">
<span class="input-group-addon">
<i class="glyphicon glyphicon-lock"></i>
</span>
<input name="password" type="password" value="" class="form-control" required autocomplete="off">
</div>
</div>
</div>
<hr>
<div class="form-group">
<button type="submit" name="login_method" value="credentials" class="btn btn-primary">Sing in</button>
<a href="{{ path_for('user.loginSso') }}" class="btn bnt-default">SSO</a>
</div>
</form>
{% endblock %}
\ No newline at end of file
......@@ -24,7 +24,8 @@
"monolog/monolog": "^1.13",
"kanellov/config-merge": "dev-master",
"zendframework/zend-authentication": "^2.0",
"zendframework/zend-eventmanager": "^3.0"
"zendframework/zend-eventmanager": "^3.0",
"jasig/phpcas": "1.3.4"
},
"require-dev": {
"fabpot/php-cs-fixer": "1.*",
......
......@@ -4,8 +4,8 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"hash": "8f23b8ce2b3934db70f529ce01ff5b1d",
"content-hash": "335c05fc635c7a452b9fa6e390019a37",
"hash": "3b10c4ba7156b5945f769c486d73237f",
"content-hash": "93b55f3a345026fb7f0e020a6d479b11",
"packages": [
{
"name": "container-interop/container-interop",
......@@ -34,6 +34,60 @@
"description": "Promoting the interoperability of container objects (DIC, SL, etc.)",
"time": "2014-12-30 15:22:37"
},
{
"name": "jasig/phpcas",
"version": "1.3.4",
"source": {
"type": "git",
"url": "https://github.com/Jasig/phpCAS.git",
"reference": "8c74d21630f74278270830fdbdb0c1317bce3f0a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Jasig/phpCAS/zipball/8c74d21630f74278270830fdbdb0c1317bce3f0a",
"reference": "8c74d21630f74278270830fdbdb0c1317bce3f0a",
"shasum": ""
},
"require": {
"ext-curl": "*",
"php": ">=5.0.0"
},
"require-dev": {
"phpunit/phpunit": "~3.7.10"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.3.x-dev"
}
},
"autoload": {
"classmap": [
"source/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "Joachim Fritschi",
"homepage": "https://wiki.jasig.org/display/~fritschi"
},
{
"name": "Adam Franco",
"homepage": "https://wiki.jasig.org/display/~adamfranco"
}
],
"description": "Provides a simple API for authenticating users against a CAS server",
"homepage": "https://wiki.jasig.org/display/CASC/phpCAS",
"keywords": [
"cas",
"jasig"
],
"time": "2015-11-16 20:44:36"
},
{
"name": "kanellov/config-merge",
"version": "dev-master",
......
local.php
*.local.php
\ No newline at end of file
<?php return [
'settings' => [
// Slim Settings
'determineRouteBeforeAppMiddleware' => false,
'displayErrorDetails' => false,
// View settings
'view' => [
'template_path' => __DIR__ . '/../app/templates',
'twig' => [
'cache' => __DIR__ . '/../data/cache/twig',
'debug' => true,
'auto_reload' => true,
],
],
// monolog settings
'logger' => [
'name' => 'app',
'path' => __DIR__ . '/../data/log/' . (isset($_SERVER['SERVER_ADDR']) ? $_SERVER['SERVER_ADDR'] . '/' : '') . 'app.log',
// Slim Settings
'determineRouteBeforeAppMiddleware' => false,
'displayErrorDetails' => false,
// View settings
'view' => [
'template_path' => __DIR__ . '/../app/templates',
'twig' => [
'cache' => __DIR__ . '/../data/cache/twig',
'debug' => true,
'auto_reload' => true,
],
],
// monolog settings
'logger' => [
'name' => 'app',
'path' => __DIR__ . '/../data/log/' . (isset($_SERVER['SERVER_ADDR']) ? $_SERVER['SERVER_ADDR'] . '/' : '') . 'app.log',
],
];
*
!.gitignore
\ No newline at end of file
......@@ -21,6 +21,8 @@
<directory suffix=".php">./app/</directory>
<exclude>
<directory>./app/templates</directory>
<file>./app/src/Authentication/Adapter/Cas.php</file>
<file></file>
</exclude>
</whitelist>
</filter>
......
......@@ -15,9 +15,12 @@ if (PHP_SAPI === 'cli-server' && $_SERVER['SCRIPT_FILENAME'] !== __FILE__) {
require __DIR__ . '/../vendor/autoload.php';
session_name('GrEduLabs');
session_start();
$app = new \Slim\App(Knlv\config_merge('config', ['global', 'local']));
$app = new \Slim\App([
'settings' => Knlv\config_merge('config', ['global', 'local']),
]);
require 'app/dependencies.php';
require 'app/middleware.php';
......
......@@ -22,7 +22,15 @@ class DependenciesTest extends \PHPUnit_Framework_TestCase
],
'logger' => [
'name' => 'app',
'path' => __DIR__,
'path' => __DIR__ . '/tmp/app.log',
],
'db' => [
'dsn' => 'sqlite:' . __DIR__ . '/tmp/db.sq3',
'user' => null,
'pass' => null,
'options' => [
],
],
],
];
......@@ -60,10 +68,10 @@ class DependenciesTest extends \PHPUnit_Framework_TestCase
$this->assertInstanceOf('\Zend\EventManager\EventManagerInterface', $events);
}
public function testAuthAdapter()
public function testDbAuthAdapter()
{
$adapter = self::$container->get('Service\\Authentication\\Adapter');
$this->assertInstanceOf('\Zend\Authentication\Adapter\AdapterInterface', $adapter);
$adapter = self::$container->get('Service\\Authentication\\DbAdapter');
$this->assertInstanceOf('\GrEduLabs\Authentication\Adapter\Pdo', $adapter);
}
public function testAuthStorage()
......@@ -75,6 +83,6 @@ class DependenciesTest extends \PHPUnit_Framework_TestCase
public function testAuthService()
{
$service = self::$container->get('Service\\Authentication');
$this->assertInstanceOf('\Zend\Authentication\AuthenticationServiceInterface', $service);
$this->assertInstanceOf('\Zend\Authentication\AuthenticationService', $service);
}
}
<?php
/**
* gredu_labs
*
* @link https://github.com/eellak/gredu_labs for the canonical source repository
* @copyright Copyright (c) 2008-2015 Greek Free/Open Source Software Society (https://gfoss.ellak.gr/)
* @license GNU GPLv3 http://www.gnu.org/licenses/gpl-3.0-standalone.html
*/
namespace GrEduLabstest\Authentication;
use GrEduLabs\Authentication\Identity;
class IdentityTest extends \PHPUnit_Framework_TestCase
{
public function testConstructor()
{
$identity = new Identity(
'someUid',
'some@mail.com',
'Jonh Doe',
'Office'
);
$this->assertAttributeSame('someUid', 'uid', $identity);
$this->assertAttributeSame('some@mail.com', 'mail', $identity);
$this->assertAttributeSame('Jonh Doe', 'displayName', $identity);
$this->assertAttributeSame('Office', 'officeName', $identity);
}
}
*
!.gitignore
\ No newline at end of file
Markdown is supported
0% or