-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstore-and-authenticate.php
67 lines (53 loc) · 1.74 KB
/
store-and-authenticate.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<?php
/**
* Example of securely storing key in a database and then authenticating key
*
* Table structure (MySQL):
*
* CREATE TABLE apikeys (
* id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
* identifier VARBINARY(255) NOT NULL,
* hash VARCHAR(255) NOT NULL,
* UNIQUE INDEX apikeys_identifier_udx (identifier)
* )
*/
declare(strict_types=1);
use Kynx\ApiKey\ApiKey;
use Kynx\ApiKey\KeyGenerator;
require '../vendor/autoload.php';
$pdo = new PDO('mysql:host=127.0.0.1;dbname=api', 'apiuser', 'apipass');
$generator = new KeyGenerator('xyz_sandbox');
$insert = $pdo->prepare('INSERT INTO apikeys (identifier, hash) VALUES (:identifier, :hash)');
// store api identifier and hash of secret, retrying when duplicate key error occurs
$retries = 0;
while (true) {
$apiKey = $generator->generate();
$hash = password_hash($apiKey->getSecret(), PASSWORD_DEFAULT);
try {
$insert->execute(['identifier' => $apiKey->getIdentifier(), 'hash' => $hash]);
break;
} catch (PDOException $e) {
// check for unique constraint violation - mysql-specific
if ($e->errorInfo[1] !== 1062 || $retries >= 9) {
throw $e;
}
}
$retries++;
}
assert($apiKey instanceof ApiKey);
$key = $apiKey->getKey();
// verify key is well-formed
$parsed = $generator->parse($key);
if ($parsed === null) {
echo "Invalid key!\n";
exit;
}
// validate apikey against stored hash
$select = $pdo->prepare('SELECT id, hash FROM apikeys WHERE identifier = :identifier');
$select->execute(['identifier' => $parsed->getIdentifier()]);
$row = $select->fetch();
if (password_verify($parsed->getSecret(), $row['hash'])) {
echo "Authenticated ID " . $row['id'] . "\n";
} else {
echo "Not authenticated\n";
}