Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions example/src/Auth.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,13 @@ public function getNonce()

private function getPrincipalNameFromCertificate(X509 $userCertificate): string
{
$givenName = CertificateData::getSubjectGivenName($userCertificate);
$surname = CertificateData::getSubjectSurname($userCertificate);
$givenname = CertificateData::getSubjectGivenName($userCertificate);
if ($surname && $givenname) {
$principalName = $givenname . " " . $surname;
if ($givenName && $surname) {
return $givenName . " " . $surname;
} else {
$principalName = CertificateData::getSubjectCN($userCertificate);
return CertificateData::getSubjectCN($userCertificate);
}
return $principalName;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion example/tpl/welcome.phtml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
<h1 class="text-center mt-5">Hello <?php echo $auth_user;?></h1>
<h1 class="text-center mt-5">Hello <?php echo htmlspecialchars($auth_user);?></h1>
<p class="text-center"><a href="./logout">Logout</a></p>
13 changes: 0 additions & 13 deletions src/authtoken/WebEidAuthToken.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,6 @@ class WebEidAuthToken
* @var string Format
*/
private ?string $format = null;
/**
* @var string App version
*/
private ?string $appVersion = null;

public function __construct(string $authenticationTokenJSON)
{
Expand All @@ -76,10 +72,6 @@ public function __construct(string $authenticationTokenJSON)
if (isset($jsonDecoded['format'])) {
$this->format = $this->filterString('format', $jsonDecoded['format']);
}
// appVersion
if (isset($jsonDecoded['appVersion'])) {
$this->appVersion = $this->filterString('appVersion', $jsonDecoded['appVersion']);
}
}

public function getUnverifiedCertificate(): ?string
Expand All @@ -102,11 +94,6 @@ public function getFormat(): ?string
return $this->format;
}

public function getAppVersion(): ?string
{
return $this->appVersion;
}

private function filterString(string $key, $data): string
{
$type = gettype($data);
Expand Down
7 changes: 3 additions & 4 deletions src/certificate/CertificateData.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,15 +80,14 @@ public static function getSubjectCountryCode(X509 $certificate): ?string
/**
* Get specified subject field from x509 certificate
*
* @return string
* @return ?string
*/
private static function getField(X509 $certificate, string $fieldId): ?string
{
$result = $certificate->getSubjectDNProp($fieldId);
if ($result) {
return join(" ", $result);
}
else {
return join(", ", $result);
} else {
return null;
}
}
Expand Down
13 changes: 4 additions & 9 deletions src/ocsp/OcspRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@

class OcspRequest
{
private array $ocspRequest = [];
private array $ocspRequest;

public function __construct()
{
Expand All @@ -41,8 +41,6 @@ public function __construct()
$this->ocspRequest = [
"tbsRequest" => [
"version" => "v1",
"requestList" => [],
"requestExtensions" => [],
],
];
}
Expand All @@ -62,18 +60,15 @@ public function addNonceExtension(string $nonce): void
"critical" => false,
"extnValue" => ASN1::encodeDER($nonce, ['type' => ASN1::TYPE_OCTET_STRING]),
];
$this->ocspRequest["tbsRequest"][
"requestExtensions"
][] = $nonceExtension;
$this->ocspRequest["tbsRequest"]["requestExtensions"][] = $nonceExtension;
}

/**
* @copyright 2022 Petr Muzikant pmuzikant@email.cz
*/
public function getNonceExtension(): string
public function getNonceExtension(): ?string
{
// TODO: the ?? '' is here only for v1.0 API compatibility. Remove this in version 1.2 and change the return type to ?string.
return AsnUtil::decodeNonceExtension($this->ocspRequest["tbsRequest"]["requestExtensions"]) ?? '';
return AsnUtil::decodeNonceExtension($this->ocspRequest["tbsRequest"]["requestExtensions"] ?? []);
}

public function getEncodeDer(): string
Expand Down
12 changes: 6 additions & 6 deletions src/validator/AuthTokenSignatureValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,19 +54,19 @@ public function __construct(Uri $siteOrigin)

public function validate(string $algorithm, string $signature, $publicKey, string $currentChallengeNonce): void
{
$this->requireNotEmpty($algorithm, "algorithm");
$this->requireNotEmpty($signature, "signature");
if (empty($currentChallengeNonce)) {
throw new ChallengeNullOrEmptyException();
}

if (is_null($publicKey)) {
throw new InvalidArgumentException("Public key is null");
}

if (empty($currentChallengeNonce)) {
throw new ChallengeNullOrEmptyException();
}
$this->requireNotEmpty($algorithm, "algorithm");
$this->requireNotEmpty($signature, "signature");

if (!in_array($algorithm, self::ALLOWED_SIGNATURE_ALGORITHMS)) {
throw new AuthTokenParseException("Invalid signature algorithm");
throw new AuthTokenParseException("Unsupported signature algorithm");
}

$decodedSignature = base64_decode($signature);
Expand Down
4 changes: 4 additions & 0 deletions src/validator/ocsp/OcspRequestBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

namespace web_eid\web_eid_authtoken_validation_php\validator\ocsp;

use InvalidArgumentException;
use web_eid\web_eid_authtoken_validation_php\ocsp\OcspRequest;
use web_eid\web_eid_authtoken_validation_php\util\SecureRandom;

Expand Down Expand Up @@ -58,6 +59,9 @@ public function enableOcspNonce(bool $ocspNonceEnabled): OcspRequestBuilder
public function build(): OcspRequest
{
$ocspRequest = new OcspRequest();
if (is_null($this->certificateId)) {
throw new InvalidArgumentException("Certificate Id must not be null");
}
$ocspRequest->addCertificateId($this->certificateId);

if ($this->ocspNonceEnabled) {
Expand Down
4 changes: 3 additions & 1 deletion src/validator/ocsp/OcspServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

namespace web_eid\web_eid_authtoken_validation_php\validator\ocsp;

use InvalidArgumentException;
use phpseclib3\File\X509;
use web_eid\web_eid_authtoken_validation_php\validator\ocsp\service\AiaOcspService;
use web_eid\web_eid_authtoken_validation_php\validator\ocsp\service\AiaOcspServiceConfiguration;
Expand All @@ -41,7 +42,8 @@ class OcspServiceProvider
public function __construct(?DesignatedOcspServiceConfiguration $designatedOcspServiceConfiguration, AiaOcspServiceConfiguration $aiaOcspServiceConfiguration)
{
$this->designatedOcspService = !is_null($designatedOcspServiceConfiguration) ? new DesignatedOcspService($designatedOcspServiceConfiguration) : null;
$this->aiaOcspServiceConfiguration = $aiaOcspServiceConfiguration;
$this->aiaOcspServiceConfiguration = $aiaOcspServiceConfiguration ?? throw new InvalidArgumentException("AIA Ocsp Service Configuration must not be null");

}

/**
Expand Down
4 changes: 4 additions & 0 deletions src/validator/ocsp/OcspUrl.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
use phpseclib3\File\X509;
use GuzzleHttp\Psr7\Uri;
use Exception;
use InvalidArgumentException;

final class OcspUrl
{
Expand All @@ -43,6 +44,9 @@ public function __construct()
*/
public static function getOcspUri(X509 $certificate): ?Uri
{
if (is_null($certificate)) {
throw new InvalidArgumentException("Certificate must not be null");
}
$authorityInformationAccess = $certificate->getExtension("id-pe-authorityInfoAccess");
if ($authorityInformationAccess) {
foreach ($authorityInformationAccess as $accessDescription) {
Expand Down
4 changes: 4 additions & 0 deletions src/validator/ocsp/service/AiaOcspService.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
use DateTime;
use web_eid\web_eid_authtoken_validation_php\validator\ocsp\OcspResponseValidator;
use Exception;
use InvalidArgumentException;

/**
* An OCSP service that uses the responders from the Certificates' Authority Information Access (AIA) extension.
Expand All @@ -48,6 +49,9 @@ class AiaOcspService implements OcspService

public function __construct(AiaOcspServiceConfiguration $configuration, X509 $certificate)
{
if (is_null($configuration)) {
throw new InvalidArgumentException("Configuration cannot be null");
}
$this->url = self::getOcspAiaUrlFromCertificate($certificate);
$this->trustedCACertificates = $configuration->getTrustedCACertificates();
$this->supportsNonce = !in_array($this->url->jsonSerialize(), $configuration->getNonceDisabledOcspUrls()->getUrlsArray());
Expand Down
1 change: 0 additions & 1 deletion tests/authtoken/WebEidAuthTokenTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ public function testValidateAuthTokenParameters(): void
$this->assertEquals("RS256", $authToken->getAlgorithm());
$this->assertEquals("HBjNXIaUskXbfhzYQHvwjKDUWfNu4yxXZh", $authToken->getSignature());
$this->assertEquals("web-eid:1.0", $authToken->getFormat());
$this->assertEquals("https://web-eid.eu/web-eid-app/releases/v2.0.0", $authToken->getAppVersion());
}

public function testWhenNotAuthToken(): void
Expand Down
21 changes: 5 additions & 16 deletions tests/certificate/CertificateDataTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,25 +49,14 @@ public function testWhenOrganizationCertificateThenSubjectCNAndIdCodeAndCountryC
$this->assertEquals("EE", CertificateData::getSubjectCountryCode($cert));
}

public function testWhenOrganizationCertificateThenSubjectGivenNameAndSurnameAreNull(): void
{
$cert = Certificates::getOrganizationCert();
$this->assertEquals(null, CertificateData::getSubjectGivenName($cert));
$this->assertEquals(null, CertificateData::getSubjectSurname($cert));
}

public function testWhenOrganizationCertificateThenSucceeds(): void
public function testWhenOrganizationCertificateThenSubjectGivenNameAndSurnameAreEmptyAndSubjectCNSucceeds(): void
{
$cert = Certificates::getOrganizationCert();
$givenName = CertificateData::getSubjectGivenName($cert);
$surname = CertificateData::getSubjectSurname($cert);
$givenname = CertificateData::getSubjectGivenName($cert);
if ($surname && $givenname) {
$principalName = $givenname . " " . $surname;
} else {
$principalName = CertificateData::getSubjectCN($cert);
}

$this->assertEmpty($givenName);
$this->assertEmpty($surname);
$principalName = CertificateData::getSubjectCN($cert);
$this->assertEquals("Testijad.ee isikutuvastus", $principalName);

}
}
27 changes: 25 additions & 2 deletions tests/ocsp/OcspRequestTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ private function getRequest(): array
return [
'tbsRequest' => [
'version' => 'v1',
'requestList' => [],
'requestExtensions' => [],
],
];
}
Expand Down Expand Up @@ -101,4 +99,29 @@ public function testWhenGetNonceExtensionSuccess(): void

$this->assertEquals("nonce", $request->getNonceExtension());
}

public function testBinaryNonce(): void
{
// Create a nonce with a mixture of potentially problematic bytes,
// null bytes, control characters and high-byte values (above 0x7F),
// which are common sources of string decoding problems.
$nonce = "\0\1\2\3\4\5\6\7\x08\x09\x10\0"
. "\x0A\x0D\x1B"
. "\xE2\x82\xAC"
. "\xFF";
$request = new OcspRequest();
$request->addNonceExtension($nonce);

$this->assertEquals($nonce, $request->getNonceExtension());
}

public function testOidNonce(): void
{
// Create a nonce that contains DER-encoded OID for SHA-256: 2.16.840.1.101.3.4.2.1.
$nonce = "\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01";
$request = new OcspRequest();
$request->addNonceExtension($nonce);

$this->assertEquals($nonce, $request->getNonceExtension());
}
}
4 changes: 2 additions & 2 deletions tests/validator/AuthTokenAlgorithmTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public function testWhenAlgorithmNoneThenValidationFails(): void
$authToken = $this->replaceTokenField(self::VALID_AUTH_TOKEN, "algorithm", "NONE");

$this->expectException(AuthTokenParseException::class);
$this->expectExceptionMessage("Invalid signature algorithm");
$this->expectExceptionMessage("Unsupported signature algorithm");
$this->validator->validate($authToken, self::VALID_AUTH_TOKEN);
}

Expand All @@ -53,7 +53,7 @@ public function testWhenAlgorithmInvalidThenParsingFails(): void
$authToken = $this->replaceTokenField(self::VALID_AUTH_TOKEN, "algorithm", "\\u0000\\t\\ninvalid");

$this->expectException(AuthTokenParseException::class);
$this->expectExceptionMessage("Invalid signature algorithm");
$this->expectExceptionMessage("Unsupported signature algorithm");
$this->validator->validate($authToken, self::VALID_AUTH_TOKEN);
}
}