Skip to content

Commit

Permalink
Merge 1f8ad37 into c8be5a3
Browse files Browse the repository at this point in the history
  • Loading branch information
tvdijen committed Sep 14, 2021
2 parents c8be5a3 + 1f8ad37 commit 77a5338
Show file tree
Hide file tree
Showing 13 changed files with 259 additions and 81 deletions.
1 change: 0 additions & 1 deletion .php_cs.dist
Expand Up @@ -4,7 +4,6 @@ $finder = PhpCsFixer\Finder::create()
__DIR__ . '/lib',
__DIR__ . '/libextinc',
__DIR__ . '/tests',
__DIR__ . '/www',
])
;
return PhpCsFixer\Config::create()
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Expand Up @@ -21,7 +21,7 @@
},
"autoload": {
"psr-4": {
"SimpleSAML\\modules\\yubikey\\": "lib/"
"SimpleSAML\\Module\\authYubikey\\": "lib/"
}
},
"autoload-dev": {
Expand Down
2 changes: 1 addition & 1 deletion lib/Auth/Process/OTP2YubiPrefix.php
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace SimpleSAML\Module\authYubiKey\Auth\Process;
namespace SimpleSAML\Module\authYubikey\Auth\Process;

use SimpleSAML\Assert\Assert;
use SimpleSAML\Auth;
Expand Down
6 changes: 3 additions & 3 deletions lib/Auth/Source/YubiKey.php
@@ -1,6 +1,6 @@
<?php

namespace SimpleSAML\Module\authYubiKey\Auth\Source;
namespace SimpleSAML\Module\authYubikey\Auth\Source;

use Exception;
use SimpleSAML\Assert\Assert;
Expand Down Expand Up @@ -113,7 +113,7 @@ public function authenticate(array &$state): void
$state[self::AUTHID] = $this->authId;

$id = Auth\State::saveState($state, self::STAGEID);
$url = Module::getModuleURL('authYubiKey/yubikeylogin.php');
$url = Module::getModuleURL('authYubikey/login');
$httpUtils = new Utils\HTTP();
$httpUtils->redirectTrustedURL($url, ['AuthState' => $id]);
}
Expand Down Expand Up @@ -153,7 +153,7 @@ public static function handleLogin(string $authStateId, string $otp)
/**
* Attempt to log in.
*
* @var \SimpleSAML\Module\authYubiKey\Auth\Source\YubiKey $source
* @var \SimpleSAML\Module\authYubikey\Auth\Source\YubiKey $source
*/
$attributes = $source->login($otp);
} catch (Error\Error $e) {
Expand Down
102 changes: 102 additions & 0 deletions lib/Controller/Yubikey.php
@@ -0,0 +1,102 @@
<?php

declare(strict_types=1);

namespace SimpleSAML\Module\authYubikey\Controller;

use SimpleSAML\Configuration;
use SimpleSAML\Error;
use SimpleSAML\Module\authYubikey\Auth\Source;
use SimpleSAML\Session;
use SimpleSAML\XHTML\Template;
use Symfony\Component\HttpFoundation\Request;

/**
* Controller class for the authyubikey module.
*
* This class serves the different views available in the module.
*
* @package simplesamlphp/simplesamlphp-module-authyubikey
*/
class Yubikey
{
/** @var \SimpleSAML\Configuration */
protected Configuration $config;

/** @var \SimpleSAML\Session */
protected Session $session;

/**
* @var \SimpleSAML\Module\authYubikey\Auth\Source\YubiKey|string
* @psalm-var \SimpleSAML\Module\authYubikey\Auth\Source\YubiKey|class-string
*/
protected $yubikey = Source\YubiKey::class;


/**
* Controller constructor.
*
* It initializes the global configuration and session for the controllers implemented here.
*
* @param \SimpleSAML\Configuration $config The configuration to use by the controllers.
* @param \SimpleSAML\Session $session The session to use by the controllers.
*
* @throws \Exception
*/
public function __construct(
Configuration $config,
Session $session
) {
$this->config = $config;
$this->session = $session;
}


/**
* Inject the \SimpleSAML\Module\authYubikey\Auth\Source\YubiKey dependency.
*
* @param \SimpleSAML\Module\authYubikey\Auth\Source\YubiKey $yubikey
*/
public function setYubikey(Source\Yubikey $yubikey): void
{
$this->yubikey = $yubikey;
}


/**
* @param \Symfony\Component\HttpFoundation\Request $request The current request.
* @return \SimpleSAML\XHTML\Template
*/
public function main(Request $request): Template
{
$stateId = $request->get('AuthState');
if ($stateId === null) {
throw new Error\BadRequest('Missing AuthState parameter.');
}

$t = new Template($this->config, 'authYubikey:yubikeylogin.twig');

$errorCode = null;
$otp = $request->get('otp');
if ($otp !== null) {
// attempt to log in

/** @psalm-var string $errorCode */
$errorCode = $this->yubikey::handleLogin($stateId, $otp);
$errorCodes = Error\ErrorCodes::getAllErrorCodeMessages();

if (array_key_exists($errorCode, $errorCodes['title'])) {
$t->data['errorTitle'] = $errorCodes['title'][$errorCode];
}

if (array_key_exists($errorCode, $errorCodes['descr'])) {
$t->data['errorDesc'] = $errorCodes['descr'][$errorCode];
}
}

$t->data['errorCode'] = $errorCode;
$t->data['stateParams'] = ['AuthState' => $stateId];

return $t;
}
}
3 changes: 2 additions & 1 deletion libextinc/Yubico.php
Expand Up @@ -121,8 +121,9 @@ public function verify(string $token)
// Support https
$url = "https://api.yubico.com/wsapi/verify?" . $parameters;

$httpUtils = new \SimpleSAML\Utils\HTTP();
/** @var string $responseMsg */
$responseMsg = \SimpleSAML\Utils\HTTP::fetch($url);
$responseMsg = $httpUtils->fetch($url);

$out = [];
if (preg_match("/status=([a-zA-Z0-9_]+)/", $responseMsg, $out) !== 1) {
Expand Down
1 change: 0 additions & 1 deletion phpcs.xml
Expand Up @@ -9,7 +9,6 @@
<file>lib</file>
<file>libextinc</file>
<file>tests</file>
<file>www</file>

<!-- This is the rule we inherit from. If you want to exlude some specific rules, see the docs on how to do that -->
<rule ref="PSR12"/>
Expand Down
38 changes: 19 additions & 19 deletions phpunit.xml
@@ -1,20 +1,20 @@
<?xml version="1.0" encoding="utf-8" ?>
<phpunit bootstrap="tests/bootstrap.php">
<testsuites>
<testsuite name="The project's test suite">
<directory>./vendor/simplesamlphp/simplesamlphp-test-framework/src/</directory>
<directory>tests/</directory>
</testsuite>
</testsuites>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">./lib</directory>
</whitelist>
</filter>
<logging>
<log type="coverage-text" target="php://stdout" showUncoveredFiles="true" />
<log type="coverage-html" target="build/coverage" title="PHP Coveralls" charset="UTF-8" yui="true" highlight="true" lowUpperBound="35" highLowerBound="70" />
<log type="coverage-clover" target="build/logs/clover.xml" />
</logging>
<?xml version="1.0" encoding="utf-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" bootstrap="tests/bootstrap.php" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd">
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">./lib</directory>
</include>
<report>
<clover outputFile="build/logs/clover.xml"/>
<html outputDirectory="build/coverage" lowUpperBound="35" highLowerBound="70"/>
<text outputFile="php://stdout" showUncoveredFiles="true"/>
</report>
</coverage>
<testsuites>
<testsuite name="The project's test suite">
<directory>./vendor/simplesamlphp/simplesamlphp-test-framework/src/</directory>
<directory>tests/</directory>
</testsuite>
</testsuites>
<logging/>
</phpunit>

8 changes: 0 additions & 8 deletions psalm.xml
Expand Up @@ -7,7 +7,6 @@
<projectFiles>
<directory name="lib" />
<directory name="libextinc" />
<directory name="www" />
</projectFiles>

<issueHandlers>
Expand All @@ -27,12 +26,5 @@
<MissingParamType errorLevel="info" />
<UnusedClass errorLevel="info" />
<PossiblyUnusedMethod errorLevel="info" />

<!-- Ignore InvalidClass -->
<InvalidClass>
<errorLevel type="suppress">
<file name="www/yubikeylogin.php" />
</errorLevel>
</InvalidClass>
</issueHandlers>
</psalm>
3 changes: 3 additions & 0 deletions routing/routes/routes.yml
@@ -0,0 +1,3 @@
authyubikey-main:
path: /login
defaults: { _controller: 'SimpleSAML\Module\authyubikey\Controller\Yubikey::main' }
2 changes: 1 addition & 1 deletion tests/bootstrap.php
Expand Up @@ -6,7 +6,7 @@
require_once($projectRoot . '/vendor/autoload.php');

// Symlink module into ssp vendor lib so that templates and urls can resolve correctly
$linkPath = $projectRoot . '/vendor/simplesamlphp/simplesamlphp/modules/authyubikey';
$linkPath = $projectRoot . '/vendor/simplesamlphp/simplesamlphp/modules/authYubikey';
if (file_exists($linkPath) === false) {
echo "Linking '$linkPath' to '$projectRoot'\n";
symlink($projectRoot, $linkPath);
Expand Down
127 changes: 127 additions & 0 deletions tests/lib/Controller/YubikeyTest.php
@@ -0,0 +1,127 @@
<?php

declare(strict_types=1);

namespace SimpleSAML\Test\Module\authYubikey\Controller;

use PHPUnit\Framework\TestCase;
//use SimpleSAML\Auth\State as AuthState;
use SimpleSAML\Configuration;
use SimpleSAML\Error;
use SimpleSAML\Module\authYubikey\Auth\Source\YubiKey;
use SimpleSAML\Module\authYubikey\Controller;
use SimpleSAML\Session;
use SimpleSAML\XHTML\Template;
use Symfony\Component\HttpFoundation\Request;

/**
* Set of tests for the controllers in the "authyubikey" module.
*
* @covers \SimpleSAML\Module\authYubikey\Controller\Yubikey
*/
class YubikeyTest extends TestCase
{
/** @var \SimpleSAML\Configuration */
protected Configuration $config;

/** @var \SimpleSAML\Session */
protected Session $session;


/**
* Set up for each test.
*/
protected function setUp(): void
{
parent::setUp();

$this->config = Configuration::loadFromArray(
[
'module.enable' => ['authYubikey' => true],
],
'[ARRAY]',
'simplesaml'
);

$this->session = Session::getSessionFromRequest();

Configuration::setPreLoadedConfig($this->config, 'config.php');
}


/**
* Test that accessing the otp-endpoint without state results in an error-response
*
* @return void
*/
public function testOtpNoState(): void
{
$request = Request::create(
'/login',
'GET'
);

$c = new Controller\Yubikey($this->config, $this->session);

$this->expectException(Error\BadRequest::class);
$this->expectExceptionMessage("BADREQUEST('%REASON%' => 'Missing AuthState parameter.')");

$c->main($request);
}


/**
* Test that accessing the otp-endpoint without otp results in a Template
*
* @return void
*/
public function testOtpNoOtp(): void
{
$request = Request::create(
'/login',
'GET',
['AuthState' => 'abc123']
);

$c = new Controller\Yubikey($this->config, $this->session);
/**
$c->setAuthState(new class () extends Auth\State {
public static function loadState(string $id, string $stage, bool $allowMissing = false): ?array
{
return [];
}
});
*/
$response = $c->main($request);

$this->assertTrue($response->isSuccessful());
$this->assertInstanceOf(Template::class, $response);
}


/**
* Test that accessing the otp-endpoint with invalid otp returns Template
*
* @return void
*/
public function testWrongOtp(): void
{
$request = Request::create(
'/login',
'GET',
['AuthState' => 'abc123', 'otp' => 'aabbccddeeffgghhiijjkkllmmnnooppqq']
);

$c = new Controller\Yubikey($this->config, $this->session);
$c->setYubikey(new class (['AuthId' => 'authYubikey'], []) extends YubiKey {
public static function handleLogin(string $stateId, string $otp): ?string
{
return 'WRONGUSERPASS';
}
});
$response = $c->main($request);

$this->assertTrue($response->isSuccessful());
$this->assertInstanceOf(Template::class, $response);
}
}

0 comments on commit 77a5338

Please sign in to comment.