Skip to content

Commit 8c222b0

Browse files
committed
:octocat: move URI generation to the respective authenticator classes
1 parent 6528215 commit 8c222b0

File tree

6 files changed

+91
-42
lines changed

6 files changed

+91
-42
lines changed

src/Authenticator.php

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

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

2418
/**
2519
* Yet another Google authenticator implementation!
@@ -133,46 +127,16 @@ public function verify(#[SensitiveParameter] string $otp, int|null $data = null)
133127
* @deprecated 5.3.0 The parameter `$omitSettings` will be removed in favor of `AuthenticatorOptions::$omitUriSettings`
134128
* in the next major version (6.x)
135129
* @see \chillerlan\Authenticator\AuthenticatorOptionsTrait::$omitUriSettings
136-
* @throws \InvalidArgumentException
130+
*
131+
* @codeCoverageIgnore
137132
*/
138133
public function getUri(string $label, string $issuer, int|null $hotpCounter = null, bool|null $omitSettings = null):string{
139-
$label = trim($label);
140-
$issuer = trim($issuer);
141-
142-
if(empty($label) || empty($issuer)){
143-
throw new InvalidArgumentException('$label and $issuer cannot be empty');
144-
}
145-
146-
$values = [
147-
'secret' => $this->authenticator->getSecret(),
148-
'issuer' => $issuer,
149-
];
150-
151-
if($this->authenticator::MODE === AuthenticatorInterface::HOTP){
152-
153-
if($hotpCounter === null || $hotpCounter < 0){
154-
throw new InvalidArgumentException('initial counter value must be set and greater or equal to 0');
155-
}
156-
157-
$values['counter'] = $hotpCounter;
158-
}
159-
160-
if(($omitSettings ?? $this->options->omitUriSettings) !== true){
161-
$values['digits'] = $this->options->digits;
162-
$values['algorithm'] = $this->options->algorithm;
163-
164-
if($this->authenticator::MODE === AuthenticatorInterface::TOTP){
165-
$values['period'] = $this->options->period;
166-
}
167-
134+
// a little reckless but good enough until the deprecated parameter is removed
135+
if($omitSettings !== null){
136+
$this->options->omitUriSettings = $omitSettings;
168137
}
169138

170-
return sprintf(
171-
'otpauth://%s/%s?%s',
172-
$this->authenticator::MODE,
173-
rawurlencode($label),
174-
http_build_query($values, '', '&', PHP_QUERY_RFC3986),
175-
);
139+
return $this->authenticator->getUri($label, $issuer, $hotpCounter);
176140
}
177141

178142
}

src/Authenticators/AuthenticatorAbstract.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,13 @@
1717
use InvalidArgumentException;
1818
use RuntimeException;
1919
use SensitiveParameter;
20+
use function http_build_query;
2021
use function random_bytes;
22+
use function rawurlencode;
23+
use function sprintf;
2124
use function time;
2225
use function trim;
26+
use const PHP_QUERY_RFC3986;
2327

2428
/**
2529
*
@@ -116,4 +120,28 @@ protected function checkEncodedSecret(string $encodedSecret):string{
116120
return $encodedSecret;
117121
}
118122

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

src/Authenticators/AuthenticatorInterface.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,4 +123,13 @@ public function code(int|null $data = null):string;
123123
*/
124124
public function verify(#[SensitiveParameter] string $otp, int|null $data = null):bool;
125125

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

src/Authenticators/HOTP.php

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

1414
use RuntimeException;
1515
use SensitiveParameter;
16+
use function array_merge;
1617
use function hash_equals;
1718
use function hash_hmac;
1819
use function pack;
@@ -94,4 +95,25 @@ public function verify(#[SensitiveParameter] string $otp, int|null $data = null)
9495
return hash_equals($this->code($data), $otp);
9596
}
9697

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

src/Authenticators/SteamGuard.php

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

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

src/Authenticators/TOTP.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 SensitiveParameter;
15+
use function array_merge;
1516
use function floor;
1617
use function hash_equals;
1718
use function time;
@@ -60,4 +61,25 @@ public function verify(#[SensitiveParameter] string $otp, int|null $data = null)
6061
return false;
6162
}
6263

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

0 commit comments

Comments
 (0)