TwoFAccountModelTest.php 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  1. <?php
  2. namespace Tests\Feature\Models;
  3. use App\Models\TwoFAccount;
  4. use Tests\FeatureTestCase;
  5. use Tests\Classes\OtpTestData;
  6. /**
  7. * @covers \App\Models\TwoFAccount
  8. */
  9. class TwoFAccountModelTest extends FeatureTestCase
  10. {
  11. /**
  12. * App\Models\TwoFAccount $customTotpTwofaccount
  13. */
  14. protected $customTotpTwofaccount;
  15. /**
  16. * App\Models\TwoFAccount $customTotpTwofaccount
  17. */
  18. protected $customHotpTwofaccount;
  19. /**
  20. * @test
  21. */
  22. public function setUp() : void
  23. {
  24. parent::setUp();
  25. // $this->twofaccountService = $this->app->make('App\Services\TwoFAccountService');
  26. $this->customTotpTwofaccount = new TwoFAccount;
  27. $this->customTotpTwofaccount->legacy_uri = OtpTestData::TOTP_FULL_CUSTOM_URI;
  28. $this->customTotpTwofaccount->service = OtpTestData::SERVICE;
  29. $this->customTotpTwofaccount->account = OtpTestData::ACCOUNT;
  30. $this->customTotpTwofaccount->icon = OtpTestData::ICON;
  31. $this->customTotpTwofaccount->otp_type = 'totp';
  32. $this->customTotpTwofaccount->secret = OtpTestData::SECRET;
  33. $this->customTotpTwofaccount->digits = OtpTestData::DIGITS_CUSTOM;
  34. $this->customTotpTwofaccount->algorithm = OtpTestData::ALGORITHM_CUSTOM;
  35. $this->customTotpTwofaccount->period = OtpTestData::PERIOD_CUSTOM;
  36. $this->customTotpTwofaccount->counter = null;
  37. $this->customTotpTwofaccount->save();
  38. $this->customHotpTwofaccount = new TwoFAccount;
  39. $this->customHotpTwofaccount->legacy_uri = OtpTestData::HOTP_FULL_CUSTOM_URI;
  40. $this->customHotpTwofaccount->service = OtpTestData::SERVICE;
  41. $this->customHotpTwofaccount->account = OtpTestData::ACCOUNT;
  42. $this->customHotpTwofaccount->icon = OtpTestData::ICON;
  43. $this->customHotpTwofaccount->otp_type = 'hotp';
  44. $this->customHotpTwofaccount->secret = OtpTestData::SECRET;
  45. $this->customHotpTwofaccount->digits = OtpTestData::DIGITS_CUSTOM;
  46. $this->customHotpTwofaccount->algorithm = OtpTestData::ALGORITHM_CUSTOM;
  47. $this->customHotpTwofaccount->period = null;
  48. $this->customHotpTwofaccount->counter = OtpTestData::COUNTER_CUSTOM;
  49. $this->customHotpTwofaccount->save();
  50. // $this->group = new Group;
  51. // $this->group->name = 'MyGroup';
  52. // $this->group->save();
  53. }
  54. /**
  55. * @test
  56. */
  57. public function test_fill_with_custom_totp_uri_returns_correct_value()
  58. {
  59. $twofaccount = new TwoFAccount;
  60. $twofaccount->fillWithURI(OtpTestData::TOTP_FULL_CUSTOM_URI);
  61. $this->assertEquals('totp', $twofaccount->otp_type);
  62. $this->assertEquals(OtpTestData::TOTP_FULL_CUSTOM_URI, $twofaccount->legacy_uri);
  63. $this->assertEquals(OtpTestData::SERVICE, $twofaccount->service);
  64. $this->assertEquals(OtpTestData::ACCOUNT, $twofaccount->account);
  65. $this->assertEquals(OtpTestData::SECRET, $twofaccount->secret);
  66. $this->assertEquals(OtpTestData::DIGITS_CUSTOM, $twofaccount->digits);
  67. $this->assertEquals(OtpTestData::PERIOD_CUSTOM, $twofaccount->period);
  68. $this->assertEquals(null, $twofaccount->counter);
  69. $this->assertEquals(OtpTestData::ALGORITHM_CUSTOM, $twofaccount->algorithm);
  70. $this->assertStringEndsWith('.png',$twofaccount->icon);
  71. }
  72. /**
  73. * @test
  74. */
  75. public function test_fill_with_basic_totp_uri_returns_default_value()
  76. {
  77. $twofaccount = new TwoFAccount;
  78. $twofaccount->fillWithURI(OtpTestData::TOTP_SHORT_URI);
  79. $this->assertEquals('totp', $twofaccount->otp_type);
  80. $this->assertEquals(OtpTestData::TOTP_SHORT_URI, $twofaccount->legacy_uri);
  81. $this->assertEquals(OtpTestData::ACCOUNT, $twofaccount->account);
  82. $this->assertEquals(null, $twofaccount->service);
  83. $this->assertEquals(OtpTestData::SECRET, $twofaccount->secret);
  84. $this->assertEquals(OtpTestData::DIGITS_DEFAULT, $twofaccount->digits);
  85. $this->assertEquals(OtpTestData::PERIOD_DEFAULT, $twofaccount->period);
  86. $this->assertEquals(null, $twofaccount->counter);
  87. $this->assertEquals(OtpTestData::ALGORITHM_DEFAULT, $twofaccount->algorithm);
  88. $this->assertEquals(null, $twofaccount->icon);
  89. }
  90. /**
  91. * @test
  92. */
  93. public function test_fill_with_custom_hotp_uri_returns_correct_value()
  94. {
  95. $twofaccount = new TwoFAccount;
  96. $twofaccount->fillWithURI(OtpTestData::HOTP_FULL_CUSTOM_URI);
  97. $this->assertEquals('hotp', $twofaccount->otp_type);
  98. $this->assertEquals(OtpTestData::HOTP_FULL_CUSTOM_URI, $twofaccount->legacy_uri);
  99. $this->assertEquals(OtpTestData::SERVICE, $twofaccount->service);
  100. $this->assertEquals(OtpTestData::ACCOUNT, $twofaccount->account);
  101. $this->assertEquals(OtpTestData::SECRET, $twofaccount->secret);
  102. $this->assertEquals(OtpTestData::DIGITS_CUSTOM, $twofaccount->digits);
  103. $this->assertEquals(null, $twofaccount->period);
  104. $this->assertEquals(OtpTestData::COUNTER_CUSTOM, $twofaccount->counter);
  105. $this->assertEquals(OtpTestData::ALGORITHM_CUSTOM, $twofaccount->algorithm);
  106. $this->assertStringEndsWith('.png',$twofaccount->icon);
  107. }
  108. /**
  109. * @test
  110. */
  111. public function test_fill_with_basic_hotp_uri_returns_default_value()
  112. {
  113. $twofaccount = new TwoFAccount;
  114. $twofaccount->fillWithURI(OtpTestData::HOTP_SHORT_URI);
  115. $this->assertEquals('hotp', $twofaccount->otp_type);
  116. $this->assertEquals(OtpTestData::HOTP_SHORT_URI, $twofaccount->legacy_uri);
  117. $this->assertEquals(null, $twofaccount->service);
  118. $this->assertEquals(OtpTestData::ACCOUNT, $twofaccount->account);
  119. $this->assertEquals(OtpTestData::SECRET, $twofaccount->secret);
  120. $this->assertEquals(OtpTestData::DIGITS_DEFAULT, $twofaccount->digits);
  121. $this->assertEquals(null, $twofaccount->period);
  122. $this->assertEquals(OtpTestData::COUNTER_DEFAULT, $twofaccount->counter);
  123. $this->assertEquals(OtpTestData::ALGORITHM_DEFAULT, $twofaccount->algorithm);
  124. $this->assertEquals(null, $twofaccount->icon);
  125. }
  126. /**
  127. * @test
  128. */
  129. public function test_filled_with_uri_persists_correct_values_to_db()
  130. {
  131. $twofaccount = new TwoFAccount;
  132. $twofaccount->fillWithURI(OtpTestData::TOTP_SHORT_URI);
  133. $twofaccount->save();
  134. $this->assertDatabaseHas('twofaccounts', [
  135. 'otp_type' => 'totp',
  136. 'legacy_uri' => OtpTestData::TOTP_SHORT_URI,
  137. 'service' => null,
  138. 'account' => OtpTestData::ACCOUNT,
  139. 'secret' => OtpTestData::SECRET,
  140. 'digits' => OtpTestData::DIGITS_DEFAULT,
  141. 'period' => OtpTestData::PERIOD_DEFAULT,
  142. 'counter' => null,
  143. 'algorithm' => OtpTestData::ALGORITHM_DEFAULT,
  144. 'icon' => null,
  145. ]);
  146. }
  147. /**
  148. * @test
  149. */
  150. public function test_fill_with_invalid_uri_returns_ValidationException()
  151. {
  152. $this->expectException(\Illuminate\Validation\ValidationException::class);
  153. $twofaccount = new TwoFAccount;
  154. $twofaccount->fillWithURI(OtpTestData::INVALID_OTPAUTH_URI);
  155. }
  156. /**
  157. * @test
  158. */
  159. public function test_fill_with_uri_without_label_returns_ValidationException()
  160. {
  161. $this->expectException(\Illuminate\Validation\ValidationException::class);
  162. $twofaccount = new TwoFAccount;
  163. $twofaccount->fillWithURI('otpauth://totp/?secret='.OtpTestData::SECRET);
  164. }
  165. /**
  166. * @test
  167. */
  168. public function test_create_custom_totp_from_parameters_returns_correct_value()
  169. {
  170. $twofaccount = new TwoFAccount;
  171. $twofaccount->fillWithOtpParameters(OtpTestData::ARRAY_OF_FULL_VALID_PARAMETERS_FOR_CUSTOM_TOTP);
  172. $this->assertEquals('totp', $twofaccount->otp_type);
  173. $this->assertEquals(OtpTestData::SERVICE, $twofaccount->service);
  174. $this->assertEquals(OtpTestData::ACCOUNT, $twofaccount->account);
  175. $this->assertEquals(OtpTestData::SECRET, $twofaccount->secret);
  176. $this->assertEquals(OtpTestData::DIGITS_CUSTOM, $twofaccount->digits);
  177. $this->assertEquals(OtpTestData::PERIOD_CUSTOM, $twofaccount->period);
  178. $this->assertEquals(null, $twofaccount->counter);
  179. $this->assertEquals(OtpTestData::ALGORITHM_CUSTOM, $twofaccount->algorithm);
  180. $this->assertStringEndsWith('.png',$twofaccount->icon);
  181. }
  182. /**
  183. * @test
  184. */
  185. public function test_create_basic_totp_from_parameters_returns_correct_value()
  186. {
  187. $twofaccount = new TwoFAccount;
  188. $twofaccount->fillWithOtpParameters(OtpTestData::ARRAY_OF_MINIMUM_VALID_PARAMETERS_FOR_TOTP);
  189. $this->assertEquals('totp', $twofaccount->otp_type);
  190. $this->assertEquals(null, $twofaccount->service);
  191. $this->assertEquals(OtpTestData::ACCOUNT, $twofaccount->account);
  192. $this->assertEquals(OtpTestData::SECRET, $twofaccount->secret);
  193. $this->assertEquals(OtpTestData::DIGITS_DEFAULT, $twofaccount->digits);
  194. $this->assertEquals(OtpTestData::PERIOD_DEFAULT, $twofaccount->period);
  195. $this->assertEquals(null, $twofaccount->counter);
  196. $this->assertEquals(OtpTestData::ALGORITHM_DEFAULT, $twofaccount->algorithm);
  197. $this->assertEquals(null, $twofaccount->icon);
  198. }
  199. /**
  200. * @test
  201. */
  202. public function test_create_custom_hotp_from_parameters_returns_correct_value()
  203. {
  204. $twofaccount = new TwoFAccount;
  205. $twofaccount->fillWithOtpParameters(OtpTestData::ARRAY_OF_FULL_VALID_PARAMETERS_FOR_CUSTOM_HOTP);
  206. $this->assertEquals('hotp', $twofaccount->otp_type);
  207. $this->assertEquals(OtpTestData::SERVICE, $twofaccount->service);
  208. $this->assertEquals(OtpTestData::ACCOUNT, $twofaccount->account);
  209. $this->assertEquals(OtpTestData::SECRET, $twofaccount->secret);
  210. $this->assertEquals(OtpTestData::DIGITS_CUSTOM, $twofaccount->digits);
  211. $this->assertEquals(null, $twofaccount->period);
  212. $this->assertEquals(OtpTestData::COUNTER_CUSTOM, $twofaccount->counter);
  213. $this->assertEquals(OtpTestData::ALGORITHM_CUSTOM, $twofaccount->algorithm);
  214. $this->assertStringEndsWith('.png',$twofaccount->icon);
  215. }
  216. /**
  217. * @test
  218. */
  219. public function test_create_basic_hotp_from_parameters_returns_correct_value()
  220. {
  221. $twofaccount = new TwoFAccount;
  222. $twofaccount->fillWithOtpParameters(OtpTestData::ARRAY_OF_MINIMUM_VALID_PARAMETERS_FOR_HOTP);
  223. $this->assertEquals('hotp', $twofaccount->otp_type);
  224. $this->assertEquals(null, $twofaccount->service);
  225. $this->assertEquals(OtpTestData::ACCOUNT, $twofaccount->account);
  226. $this->assertEquals(OtpTestData::SECRET, $twofaccount->secret);
  227. $this->assertEquals(OtpTestData::DIGITS_DEFAULT, $twofaccount->digits);
  228. $this->assertEquals(null, $twofaccount->period);
  229. $this->assertEquals(OtpTestData::COUNTER_DEFAULT, $twofaccount->counter);
  230. $this->assertEquals(OtpTestData::ALGORITHM_DEFAULT, $twofaccount->algorithm);
  231. $this->assertEquals(null, $twofaccount->icon);
  232. }
  233. /**
  234. * @test
  235. */
  236. public function test_create_from_parameters_persists_correct_values_to_db()
  237. {
  238. $twofaccount = new TwoFAccount;
  239. $twofaccount->fillWithOtpParameters(OtpTestData::ARRAY_OF_MINIMUM_VALID_PARAMETERS_FOR_TOTP);
  240. $twofaccount->save();
  241. $this->assertDatabaseHas('twofaccounts', [
  242. 'otp_type' => 'totp',
  243. 'legacy_uri' => OtpTestData::TOTP_SHORT_URI,
  244. 'service' => null,
  245. 'account' => OtpTestData::ACCOUNT,
  246. 'secret' => OtpTestData::SECRET,
  247. 'digits' => OtpTestData::DIGITS_DEFAULT,
  248. 'period' => OtpTestData::PERIOD_DEFAULT,
  249. 'counter' => null,
  250. 'algorithm' => OtpTestData::ALGORITHM_DEFAULT,
  251. 'icon' => null,
  252. ]);
  253. }
  254. /**
  255. * @test
  256. */
  257. public function test_create_from_unsupported_parameters_returns_unsupportedOtpTypeException()
  258. {
  259. $this->expectException(\App\Exceptions\UnsupportedOtpTypeException::class);
  260. $twofaccount = new TwoFAccount;
  261. $twofaccount->fillWithOtpParameters(OtpTestData::ARRAY_OF_PARAMETERS_FOR_UNSUPPORTED_OTP_TYPE);
  262. }
  263. /**
  264. * @test
  265. */
  266. public function test_create_from_invalid_parameters_type_returns_InvalidOtpParameterException()
  267. {
  268. $this->expectException(\App\Exceptions\InvalidOtpParameterException::class);
  269. $twofaccount = new TwoFAccount;
  270. $twofaccount->fillWithOtpParameters([
  271. 'account' => OtpTestData::ACCOUNT,
  272. 'otp_type' => 'totp',
  273. 'digits' => 'notsupported',
  274. ]);
  275. }
  276. /**
  277. * @test
  278. */
  279. public function test_create_from_invalid_parameters_returns_InvalidOtpParameterException()
  280. {
  281. $this->expectException(\App\Exceptions\InvalidOtpParameterException::class);
  282. $twofaccount = new TwoFAccount;
  283. $twofaccount->fillWithOtpParameters([
  284. 'account' => OtpTestData::ACCOUNT,
  285. 'otp_type' => 'totp',
  286. 'algorithm' => 'notsupported',
  287. ]);
  288. }
  289. /**
  290. * @test
  291. */
  292. public function test_update_totp_returns_updated_model()
  293. {
  294. $twofaccount = $this->customTotpTwofaccount;
  295. $twofaccount->fillWithOtpParameters(OtpTestData::ARRAY_OF_MINIMUM_VALID_PARAMETERS_FOR_TOTP);
  296. $this->assertEquals('totp', $twofaccount->otp_type);
  297. $this->assertEquals(null, $twofaccount->service);
  298. $this->assertEquals(OtpTestData::ACCOUNT, $twofaccount->account);
  299. $this->assertEquals(OtpTestData::SECRET, $twofaccount->secret);
  300. $this->assertEquals(OtpTestData::DIGITS_DEFAULT, $twofaccount->digits);
  301. $this->assertEquals(OtpTestData::PERIOD_DEFAULT, $twofaccount->period);
  302. $this->assertEquals(null, $twofaccount->counter);
  303. $this->assertEquals(OtpTestData::ALGORITHM_DEFAULT, $twofaccount->algorithm);
  304. $this->assertEquals(null, $twofaccount->counter);
  305. $this->assertEquals(null, $twofaccount->icon);
  306. }
  307. /**
  308. * @test
  309. */
  310. public function test_update_hotp_returns_updated_model()
  311. {
  312. $twofaccount = $this->customTotpTwofaccount;
  313. $twofaccount->fillWithOtpParameters(OtpTestData::ARRAY_OF_MINIMUM_VALID_PARAMETERS_FOR_HOTP);
  314. $this->assertEquals('hotp', $twofaccount->otp_type);
  315. $this->assertEquals(null, $twofaccount->service);
  316. $this->assertEquals(OtpTestData::ACCOUNT, $twofaccount->account);
  317. $this->assertEquals(OtpTestData::SECRET, $twofaccount->secret);
  318. $this->assertEquals(OtpTestData::DIGITS_DEFAULT, $twofaccount->digits);
  319. $this->assertEquals(null, $twofaccount->period);
  320. $this->assertEquals(OtpTestData::COUNTER_DEFAULT, $twofaccount->counter);
  321. $this->assertEquals(OtpTestData::ALGORITHM_DEFAULT, $twofaccount->algorithm);
  322. $this->assertEquals(null, $twofaccount->counter);
  323. $this->assertEquals(null, $twofaccount->icon);
  324. }
  325. /**
  326. * @test
  327. */
  328. public function test_update_totp_persists_updated_model()
  329. {
  330. $twofaccount = $this->customTotpTwofaccount;
  331. $twofaccount->fillWithOtpParameters(OtpTestData::ARRAY_OF_MINIMUM_VALID_PARAMETERS_FOR_TOTP);
  332. $twofaccount->save();
  333. $this->assertDatabaseHas('twofaccounts', [
  334. 'otp_type' => 'totp',
  335. 'service' => null,
  336. 'account' => OtpTestData::ACCOUNT,
  337. 'secret' => OtpTestData::SECRET,
  338. 'digits' => OtpTestData::DIGITS_DEFAULT,
  339. 'period' => OtpTestData::PERIOD_DEFAULT,
  340. 'counter' => null,
  341. 'algorithm' => OtpTestData::ALGORITHM_DEFAULT,
  342. 'icon' => null,
  343. ]);
  344. }
  345. /**
  346. * @test
  347. */
  348. public function test_getOTP_for_totp_returns_the_same_password()
  349. {
  350. $twofaccount = new TwoFAccount;
  351. $otp_from_model = $this->customTotpTwofaccount->getOTP();
  352. $otp_from_uri = $twofaccount->fillWithURI(OtpTestData::TOTP_FULL_CUSTOM_URI)->getOTP();
  353. if ($otp_from_model->generated_at === $otp_from_uri->generated_at) {
  354. $this->assertEquals($otp_from_model, $otp_from_uri);
  355. }
  356. $otp_from_model = $this->customTotpTwofaccount->getOTP();
  357. $otp_from_parameters = $twofaccount->fillWithOtpParameters(OtpTestData::ARRAY_OF_FULL_VALID_PARAMETERS_FOR_CUSTOM_TOTP)->getOTP();
  358. if ($otp_from_model->generated_at === $otp_from_parameters->generated_at) {
  359. $this->assertEquals($otp_from_model, $otp_from_parameters);
  360. }
  361. }
  362. /**
  363. * @test
  364. */
  365. public function test_getOTP_for_hotp_returns_the_same_password()
  366. {
  367. $twofaccount = new TwoFAccount;
  368. $otp_from_model = $this->customHotpTwofaccount->getOTP();
  369. $otp_from_uri = $twofaccount->fillWithURI(OtpTestData::HOTP_FULL_CUSTOM_URI)->getOTP();
  370. $this->assertEquals($otp_from_model, $otp_from_uri);
  371. $otp_from_parameters = $twofaccount->fillWithOtpParameters(OtpTestData::ARRAY_OF_FULL_VALID_PARAMETERS_FOR_CUSTOM_HOTP)->getOTP();
  372. $this->assertEquals($otp_from_model, $otp_from_parameters);
  373. }
  374. /**
  375. * @test
  376. */
  377. public function test_getOTP_for_totp_with_invalid_secret_returns_InvalidSecretException()
  378. {
  379. $twofaccount = new TwoFAccount;
  380. $this->expectException(\App\Exceptions\InvalidSecretException::class);
  381. $otp_from_uri = $twofaccount->fillWithURI('otpauth://totp/'.OtpTestData::ACCOUNT.'?secret=0')->getOTP();
  382. }
  383. /**
  384. * @test
  385. */
  386. public function test_getOTP_for_totp_with_undecipherable_secret_returns_UndecipherableException()
  387. {
  388. $twofaccount = new TwoFAccount;
  389. $this->expectException(\App\Exceptions\UndecipherableException::class);
  390. $otp_from_uri = $twofaccount->fillWithOtpParameters([
  391. 'account' => OtpTestData::ACCOUNT,
  392. 'otp_type' => 'totp',
  393. 'secret' => __('errors.indecipherable'),
  394. ])->getOTP();
  395. }
  396. /**
  397. * @test
  398. */
  399. public function test_getURI_for_custom_totp_model_returns_uri()
  400. {
  401. $uri = $this->customTotpTwofaccount->getURI();
  402. $this->assertStringContainsString('otpauth://totp/', $uri);
  403. $this->assertStringContainsString(OtpTestData::SERVICE, $uri);
  404. $this->assertStringContainsString(OtpTestData::ACCOUNT, $uri);
  405. $this->assertStringContainsString('secret='.OtpTestData::SECRET, $uri);
  406. $this->assertStringContainsString('digits='.OtpTestData::DIGITS_CUSTOM, $uri);
  407. $this->assertStringContainsString('period='.OtpTestData::PERIOD_CUSTOM, $uri);
  408. $this->assertStringContainsString('algorithm='.OtpTestData::ALGORITHM_CUSTOM, $uri);
  409. }
  410. /**
  411. * @test
  412. */
  413. public function test_getURI_for_custom_hotp_model_returns_uri()
  414. {
  415. $uri = $this->customHotpTwofaccount->getURI();
  416. $this->assertStringContainsString('otpauth://hotp/', $uri);
  417. $this->assertStringContainsString(OtpTestData::SERVICE, $uri);
  418. $this->assertStringContainsString(OtpTestData::ACCOUNT, $uri);
  419. $this->assertStringContainsString('secret='.OtpTestData::SECRET, $uri);
  420. $this->assertStringContainsString('digits='.OtpTestData::DIGITS_CUSTOM, $uri);
  421. $this->assertStringContainsString('counter='.OtpTestData::COUNTER_CUSTOM, $uri);
  422. $this->assertStringContainsString('algorithm='.OtpTestData::ALGORITHM_CUSTOM, $uri);
  423. }
  424. }