Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow Stringable and HiddenString as token input #5

Merged
merged 2 commits into from
Jan 6, 2024
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
6 changes: 6 additions & 0 deletions UPGRADE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
UPGRADE
=======

## Upgrade from 1.0.0-BETA1

* The `Rollerworks\Component\SplitToken\SplitTokenFactory::fromString()` method
now also accepts a `Stringable` object or `HiddenString`. Unless a custom factory
implementation is used this should not effect your code.

## Upgrade from 0.1.2

* Support for PHP 8.1 and lower was dropped;
Expand Down
2 changes: 1 addition & 1 deletion src/Argon2SplitTokenFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public function generate(\DateTimeImmutable | \DateInterval $expiresAt = null):
return $splitToken->expireAt($this->getExpirationTimestamp($expiresAt));
}

public function fromString(string $token): SplitToken
public function fromString(#[\SensitiveParameter] string | HiddenString | \Stringable $token): SplitToken
{
return Argon2SplitToken::fromString($token);
}
Expand Down
2 changes: 1 addition & 1 deletion src/FakeSplitTokenFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public function generate(\DateTimeImmutable | \DateInterval $expiresAt = null):
->expireAt($this->getExpirationTimestamp($expiresAt));
}

public function fromString(string $token): SplitToken
public function fromString(string | HiddenString | \Stringable $token): SplitToken
{
return FakeSplitToken::fromString($token);
}
Expand Down
12 changes: 9 additions & 3 deletions src/SplitToken.php
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ abstract class SplitToken
private ?string $verifierHash = null;
private ?\DateTimeImmutable $expiresAt = null;

final private function __construct(HiddenString $token, string $selector, string $verifier)
final private function __construct(HiddenString $token, string $selector, #[\SensitiveParameter] string $verifier)
{
$this->token = $token;
$this->selector = $selector;
Expand Down Expand Up @@ -150,8 +150,14 @@ public function expireAt(\DateTimeImmutable $expiresAt = null): static
*
* Note: The provided $token is zeroed from memory when it's length is valid.
*/
final public static function fromString(string $token): static
final public static function fromString(#[\SensitiveParameter] string | HiddenString | \Stringable $token): static
{
if ($token instanceof HiddenString) {
$token = $token->getString();
}

$token = (string) $token;

if (Binary::safeStrlen($token) !== self::TOKEN_CHAR_LENGTH) {
// Don't zero memory as the value is invalid.
throw new \RuntimeException('Invalid token provided.');
Expand Down Expand Up @@ -253,5 +259,5 @@ protected function configureHasher(array $config): void
abstract protected function verifyHash(string $hash, string $verifier): bool;

/** Produces a hashed version of the verifier. */
abstract protected function hashVerifier(string $verifier): string;
abstract protected function hashVerifier(#[\SensitiveParameter] string $verifier): string;
}
2 changes: 1 addition & 1 deletion src/SplitTokenFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,5 @@ public function generate(\DateTimeImmutable | \DateInterval $expiresAt = null):
* return SplitToken::fromString($token);
* ```
*/
public function fromString(string $token): SplitToken;
public function fromString(#[\SensitiveParameter] string | HiddenString | \Stringable $token): SplitToken;
}
32 changes: 30 additions & 2 deletions tests/Argon2SplitTokenFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,37 @@ public function it_creates_from_string(): void
{
$factory = new Argon2SplitTokenFactory();
$splitToken = $factory->generate();
$fullToken = $splitToken->token()->getString();
$splitTokenFromString = $factory->fromString($fullToken);

$splitTokenFromString = $factory->fromString($splitToken->token()->getString());
self::assertTrue($splitTokenFromString->matches($splitToken->toValueHolder()));
}

#[Test]
public function it_creates_from_hidden_string(): void
{
$factory = new Argon2SplitTokenFactory();
$splitToken = $factory->generate();

$splitTokenFromString = $factory->fromString($splitToken->token());
self::assertTrue($splitTokenFromString->matches($splitToken->toValueHolder()));
}

#[Test]
public function it_creates_from_stringable_object(): void
{
$factory = new Argon2SplitTokenFactory();
$splitToken = $factory->generate();

$stringObj = new class($splitToken->token()->getString()) implements \Stringable {
public function __construct(private string $value) {}

public function __toString(): string
{
return $this->value;
}
};

$splitTokenFromString = $factory->fromString($stringObj);
self::assertTrue($splitTokenFromString->matches($splitToken->toValueHolder()));
}
}
32 changes: 32 additions & 0 deletions tests/FakeSplitTokenFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -100,4 +100,36 @@ public function it_creates_from_string_with_mock_provided_selector(): void
self::assertTrue($splitTokenFromString->matches($splitToken->toValueHolder()));
self::assertTrue($splitTokenFromString2->matches($splitToken->toValueHolder()));
}

#[Test]
public function it_creates_from_hidden_string(): void
{
$factory = new FakeSplitTokenFactory();
$splitToken = $factory->generate();

$splitTokenFromString = $factory->fromString($splitToken->token());
self::assertTrue($splitTokenFromString->matches($splitToken->toValueHolder()));
}

#[Test]
public function it_creates_from_stringable_object(): void
{
$factory = new FakeSplitTokenFactory();
$splitToken = $factory->generate();

$stringObj = new class($splitToken->token()->getString()) implements \Stringable {
public function __construct(
#[\SensitiveParameter]
private string $value
) {}

public function __toString(): string
{
return $this->value;
}
};

$splitTokenFromString = $factory->fromString($stringObj);
self::assertTrue($splitTokenFromString->matches($splitToken->toValueHolder()));
}
}