Skip to content

Commit bdbe7f1

Browse files
authored
feature #5 Allow Stringable and HiddenString as token input (sstok)
This PR was merged into the 1.0-dev branch. Discussion ---------- | Q | A | ------------- | --- | Bug fix? | no | New feature? | yes | BC breaks? | yes | Deprecations? | yes/no | Fixed tickets | | License | MIT While considering a BC break this only effects custom factory implementations. Commits ------- 661ba98 Allow Stringable and HiddenString as token input c700405 Add #[\SensitiveParameter] to token and verifier
2 parents 82b76ae + c700405 commit bdbe7f1

7 files changed

+80
-8
lines changed

UPGRADE.md

+6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
UPGRADE
22
=======
33

4+
## Upgrade from 1.0.0-BETA1
5+
6+
* The `Rollerworks\Component\SplitToken\SplitTokenFactory::fromString()` method
7+
now also accepts a `Stringable` object or `HiddenString`. Unless a custom factory
8+
implementation is used this should not effect your code.
9+
410
## Upgrade from 0.1.2
511

612
* Support for PHP 8.1 and lower was dropped;

src/Argon2SplitTokenFactory.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public function generate(\DateTimeImmutable | \DateInterval $expiresAt = null):
4040
return $splitToken->expireAt($this->getExpirationTimestamp($expiresAt));
4141
}
4242

43-
public function fromString(string $token): SplitToken
43+
public function fromString(#[\SensitiveParameter] string | HiddenString | \Stringable $token): SplitToken
4444
{
4545
return Argon2SplitToken::fromString($token);
4646
}

src/FakeSplitTokenFactory.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public function generate(\DateTimeImmutable | \DateInterval $expiresAt = null):
4343
->expireAt($this->getExpirationTimestamp($expiresAt));
4444
}
4545

46-
public function fromString(string $token): SplitToken
46+
public function fromString(string | HiddenString | \Stringable $token): SplitToken
4747
{
4848
return FakeSplitToken::fromString($token);
4949
}

src/SplitToken.php

+9-3
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ abstract class SplitToken
9898
private ?string $verifierHash = null;
9999
private ?\DateTimeImmutable $expiresAt = null;
100100

101-
final private function __construct(HiddenString $token, string $selector, string $verifier)
101+
final private function __construct(HiddenString $token, string $selector, #[\SensitiveParameter] string $verifier)
102102
{
103103
$this->token = $token;
104104
$this->selector = $selector;
@@ -150,8 +150,14 @@ public function expireAt(\DateTimeImmutable $expiresAt = null): static
150150
*
151151
* Note: The provided $token is zeroed from memory when it's length is valid.
152152
*/
153-
final public static function fromString(string $token): static
153+
final public static function fromString(#[\SensitiveParameter] string | HiddenString | \Stringable $token): static
154154
{
155+
if ($token instanceof HiddenString) {
156+
$token = $token->getString();
157+
}
158+
159+
$token = (string) $token;
160+
155161
if (Binary::safeStrlen($token) !== self::TOKEN_CHAR_LENGTH) {
156162
// Don't zero memory as the value is invalid.
157163
throw new \RuntimeException('Invalid token provided.');
@@ -253,5 +259,5 @@ protected function configureHasher(array $config): void
253259
abstract protected function verifyHash(string $hash, string $verifier): bool;
254260

255261
/** Produces a hashed version of the verifier. */
256-
abstract protected function hashVerifier(string $verifier): string;
262+
abstract protected function hashVerifier(#[\SensitiveParameter] string $verifier): string;
257263
}

src/SplitTokenFactory.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,5 +46,5 @@ public function generate(\DateTimeImmutable | \DateInterval $expiresAt = null):
4646
* return SplitToken::fromString($token);
4747
* ```
4848
*/
49-
public function fromString(string $token): SplitToken;
49+
public function fromString(#[\SensitiveParameter] string | HiddenString | \Stringable $token): SplitToken;
5050
}

tests/Argon2SplitTokenFactoryTest.php

+30-2
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,37 @@ public function it_creates_from_string(): void
7171
{
7272
$factory = new Argon2SplitTokenFactory();
7373
$splitToken = $factory->generate();
74-
$fullToken = $splitToken->token()->getString();
75-
$splitTokenFromString = $factory->fromString($fullToken);
7674

75+
$splitTokenFromString = $factory->fromString($splitToken->token()->getString());
76+
self::assertTrue($splitTokenFromString->matches($splitToken->toValueHolder()));
77+
}
78+
79+
#[Test]
80+
public function it_creates_from_hidden_string(): void
81+
{
82+
$factory = new Argon2SplitTokenFactory();
83+
$splitToken = $factory->generate();
84+
85+
$splitTokenFromString = $factory->fromString($splitToken->token());
86+
self::assertTrue($splitTokenFromString->matches($splitToken->toValueHolder()));
87+
}
88+
89+
#[Test]
90+
public function it_creates_from_stringable_object(): void
91+
{
92+
$factory = new Argon2SplitTokenFactory();
93+
$splitToken = $factory->generate();
94+
95+
$stringObj = new class($splitToken->token()->getString()) implements \Stringable {
96+
public function __construct(private string $value) {}
97+
98+
public function __toString(): string
99+
{
100+
return $this->value;
101+
}
102+
};
103+
104+
$splitTokenFromString = $factory->fromString($stringObj);
77105
self::assertTrue($splitTokenFromString->matches($splitToken->toValueHolder()));
78106
}
79107
}

tests/FakeSplitTokenFactoryTest.php

+32
Original file line numberDiff line numberDiff line change
@@ -100,4 +100,36 @@ public function it_creates_from_string_with_mock_provided_selector(): void
100100
self::assertTrue($splitTokenFromString->matches($splitToken->toValueHolder()));
101101
self::assertTrue($splitTokenFromString2->matches($splitToken->toValueHolder()));
102102
}
103+
104+
#[Test]
105+
public function it_creates_from_hidden_string(): void
106+
{
107+
$factory = new FakeSplitTokenFactory();
108+
$splitToken = $factory->generate();
109+
110+
$splitTokenFromString = $factory->fromString($splitToken->token());
111+
self::assertTrue($splitTokenFromString->matches($splitToken->toValueHolder()));
112+
}
113+
114+
#[Test]
115+
public function it_creates_from_stringable_object(): void
116+
{
117+
$factory = new FakeSplitTokenFactory();
118+
$splitToken = $factory->generate();
119+
120+
$stringObj = new class($splitToken->token()->getString()) implements \Stringable {
121+
public function __construct(
122+
#[\SensitiveParameter]
123+
private string $value
124+
) {}
125+
126+
public function __toString(): string
127+
{
128+
return $this->value;
129+
}
130+
};
131+
132+
$splitTokenFromString = $factory->fromString($stringObj);
133+
self::assertTrue($splitTokenFromString->matches($splitToken->toValueHolder()));
134+
}
103135
}

0 commit comments

Comments
 (0)