Skip to content

Commit 27ead33

Browse files
committed
:octocat: move URI generation to the respective authenticator classes
(cherry picked from commit 8c222b0)
1 parent 87314ec commit 27ead33

File tree

6 files changed

+93
-42
lines changed

6 files changed

+93
-42
lines changed

src/Authenticator.php

Lines changed: 8 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,6 @@
1313

1414
use chillerlan\Authenticator\Authenticators\AuthenticatorInterface;
1515
use chillerlan\Settings\SettingsContainerInterface;
16-
use InvalidArgumentException;
17-
use function http_build_query;
18-
use function rawurlencode;
19-
use function sprintf;
20-
use function trim;
21-
use const PHP_QUERY_RFC3986;
2216

2317
/**
2418
* Yet another Google authenticator implementation!
@@ -63,6 +57,8 @@ public function setOptions(SettingsContainerInterface $options):self{
6357
$this->authenticator = new $class($this->options);
6458
}
6559

60+
$this->authenticator->setOptions($this->options);
61+
6662
return $this;
6763
}
6864

@@ -129,46 +125,16 @@ public function verify(string $otp, ?int $data = null):bool{
129125
* @deprecated 5.3.0 The parameter `$omitSettings` will be removed in favor of `AuthenticatorOptions::$omitUriSettings`
130126
* in the next major version (6.x)
131127
* @see \chillerlan\Authenticator\AuthenticatorOptionsTrait::$omitUriSettings
132-
* @throws \InvalidArgumentException
128+
*
129+
* @codeCoverageIgnore
133130
*/
134131
public function getUri(string $label, string $issuer, ?int $hotpCounter = null, ?bool $omitSettings = null):string{
135-
$label = trim($label);
136-
$issuer = trim($issuer);
137-
138-
if(empty($label) || empty($issuer)){
139-
throw new InvalidArgumentException('$label and $issuer cannot be empty');
140-
}
141-
142-
$values = [
143-
'secret' => $this->authenticator->getSecret(),
144-
'issuer' => $issuer,
145-
];
146-
147-
if($this->authenticator::MODE === AuthenticatorInterface::HOTP){
148-
149-
if($hotpCounter === null || $hotpCounter < 0){
150-
throw new InvalidArgumentException('initial counter value must be set and greater or equal to 0');
151-
}
152-
153-
$values['counter'] = $hotpCounter;
154-
}
155-
156-
if(($omitSettings ?? $this->options->omitUriSettings) !== true){
157-
$values['digits'] = $this->options->digits;
158-
$values['algorithm'] = $this->options->algorithm;
159-
160-
if($this->authenticator::MODE === AuthenticatorInterface::TOTP){
161-
$values['period'] = $this->options->period;
162-
}
163-
132+
// a little reckless but good enough until the deprecated parameter is removed
133+
if($omitSettings !== null){
134+
$this->options->omitUriSettings = $omitSettings;
164135
}
165136

166-
return sprintf(
167-
'otpauth://%s/%s?%s',
168-
$this->authenticator::MODE,
169-
rawurlencode($label),
170-
http_build_query($values, '', '&', PHP_QUERY_RFC3986),
171-
);
137+
return $this->authenticator->getUri($label, $issuer, $hotpCounter);
172138
}
173139

174140
}

src/Authenticators/AuthenticatorAbstract.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,13 @@
1616
use chillerlan\Settings\SettingsContainerInterface;
1717
use InvalidArgumentException;
1818
use RuntimeException;
19+
use function http_build_query;
1920
use function random_bytes;
21+
use function rawurlencode;
22+
use function sprintf;
2023
use function time;
2124
use function trim;
25+
use const PHP_QUERY_RFC3986;
2226

2327
/**
2428
*
@@ -117,4 +121,28 @@ protected function checkEncodedSecret(string $encodedSecret):string{
117121
return $encodedSecret;
118122
}
119123

124+
/**
125+
* Returns an array with settings for a mobile authenticator URI for the current authenticator mode/instance
126+
*/
127+
abstract protected function getUriParams(string $issuer, ?int $counter = null):array;
128+
129+
/**
130+
* @inheritDoc
131+
*/
132+
public function getUri(string $label, string $issuer, ?int $counter = null):string{
133+
$label = trim($label);
134+
$issuer = trim($issuer);
135+
136+
if($label === '' || $issuer === ''){
137+
throw new InvalidArgumentException('$label and $issuer cannot be empty');
138+
}
139+
140+
return sprintf(
141+
'otpauth://%s/%s?%s',
142+
$this::MODE,
143+
rawurlencode($label),
144+
http_build_query($this->getUriParams($issuer, $counter), '', '&', PHP_QUERY_RFC3986),
145+
);
146+
}
147+
120148
}

src/Authenticators/AuthenticatorInterface.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,4 +122,13 @@ public function code(?int $data = null):string;
122122
*/
123123
public function verify(string $otp, ?int $data = null):bool;
124124

125+
/**
126+
* Creates a URI string for a mobile authenticator (otpauth://...)
127+
*
128+
* The parameter `$counter` only has effect in HOTP mode
129+
*
130+
* @link https://github.com/google/google-authenticator/wiki/Key-Uri-Format#parameters
131+
*/
132+
public function getUri(string $label, string $issuer, ?int $counter = null):string;
133+
125134
}

src/Authenticators/HOTP.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace chillerlan\Authenticator\Authenticators;
1313

1414
use RuntimeException;
15+
use function array_merge;
1516
use function hash_equals;
1617
use function hash_hmac;
1718
use function pack;
@@ -93,4 +94,25 @@ public function verify(string $otp, ?int $data = null):bool{
9394
return hash_equals($this->code($data), $otp);
9495
}
9596

97+
/**
98+
* @inheritDoc
99+
*/
100+
protected function getUriParams(string $issuer, ?int $counter = null):array{
101+
102+
$params = [
103+
'secret' => $this->getSecret(),
104+
'issuer' => $issuer,
105+
'counter' => $this->getCounter($counter),
106+
];
107+
108+
if(!$this->options->omitUriSettings){
109+
$params = array_merge($params, [
110+
'digits' => $this->options->digits,
111+
'algorithm' => $this->options->algorithm,
112+
]);
113+
}
114+
115+
return $params;
116+
}
117+
96118
}

src/Authenticators/SteamGuard.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,10 @@ public function getOTP(int $code):string{
101101
return $str;
102102
}
103103

104+
public function getUri(string $label, string $issuer, ?int $counter = null):string{
105+
throw new RuntimeException('Not supported');
106+
}
107+
104108
/**
105109
* @inheritDoc
106110
* @throws \RuntimeException

src/Authenticators/TOTP.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace chillerlan\Authenticator\Authenticators;
1313

14+
use function array_merge;
1415
use function floor;
1516
use function hash_equals;
1617
use function time;
@@ -59,4 +60,25 @@ public function verify(string $otp, ?int $data = null):bool{
5960
return false;
6061
}
6162

63+
/**
64+
* @inheritDoc
65+
*/
66+
protected function getUriParams(string $issuer, ?int $counter = null):array{
67+
68+
$params = [
69+
'secret' => $this->getSecret(),
70+
'issuer' => $issuer,
71+
];
72+
73+
if(!$this->options->omitUriSettings){
74+
$params = array_merge($params, [
75+
'digits' => $this->options->digits,
76+
'algorithm' => $this->options->algorithm,
77+
'period' => $this->options->period,
78+
]);
79+
}
80+
81+
return $params;
82+
}
83+
6284
}

0 commit comments

Comments
 (0)