-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathserver_verify.php
More file actions
106 lines (84 loc) · 2.51 KB
/
server_verify.php
File metadata and controls
106 lines (84 loc) · 2.51 KB
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
<?php
/**
* Example ALTCHA server verification.
*
* This example demonstrates a server that only verifies server signature
* payloads such as ALTCHA Sentinel payloads.
* No client challenge flow is involved.
*
* Endpoints:
* POST /verify - Verify a server signature payload
*
* Usage:
* php -S localhost:8080 examples/server_verify.php
*/
declare(strict_types=1);
require __DIR__ . '/../vendor/autoload.php';
use AltchaOrg\Altcha\ServerSignature;
// -- Configuration --
$hmacSecret = getenv('ALTCHA_HMAC_SECRET') ?: 'example-hmac-secret';
// -- CORS --
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');
// -- Routing --
$method = $_SERVER['REQUEST_METHOD'];
$path = parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH);
if ($method === 'OPTIONS') {
http_response_code(204);
return;
}
try {
match (true) {
$method === 'POST' && $path === '/verify' => handleVerify($hmacSecret),
default => sendJson(['error' => 'Not found'], 404),
};
} catch (\Throwable $e) {
sendJson(['error' => $e->getMessage()], 500);
}
// -- Handlers --
function handleVerify(string $hmacSecret): void
{
$body = readJsonBody();
if (!isset($body['payload'])) {
sendJson(['error' => 'Missing "payload" field'], 400);
return;
}
// Accepts both a base64-encoded string and a JSON object
$result = ServerSignature::verifyServerSignature($body['payload'], $hmacSecret);
sendJson([
'verified' => $result->verified,
'expired' => $result->expired,
'invalidSignature' => $result->invalidSignature,
'invalidSolution' => $result->invalidSolution,
'time' => $result->time,
'verificationData' => $result->verificationData?->toArray(),
]);
}
// -- Helpers --
/**
* @return array<string, mixed>
*/
function readJsonBody(): array
{
$raw = file_get_contents('php://input');
if ($raw === false || $raw === '') {
sendJson(['error' => 'Empty request body'], 400);
exit;
}
$data = json_decode($raw, true);
if (!is_array($data)) {
sendJson(['error' => 'Invalid JSON'], 400);
exit;
}
return $data;
}
/**
* @param array<string, mixed> $data
*/
function sendJson(array $data, int $status = 200): void
{
http_response_code($status);
header('Content-Type: application/json');
echo json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) . "\n";
}