Skip to content

Instantly share code, notes, and snippets.

@grittyninja
Created August 27, 2024 05:56
Show Gist options
  • Save grittyninja/edb1cf6fefff5288bdedbfceb250ede8 to your computer and use it in GitHub Desktop.
Save grittyninja/edb1cf6fefff5288bdedbfceb250ede8 to your computer and use it in GitHub Desktop.
<?php
// JWT implementation with SQLite in PHP supporting RS256, HS256, and none
// Initialize SQLite database
$db = new SQLite3('users.db');
// Create users table if not exists
$db->exec('CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT UNIQUE,
password TEXT,
email TEXT
)');
// Insert sample user data
$db->exec("INSERT OR IGNORE INTO users (username, password, email) VALUES
('user1', '" . password_hash('password1', PASSWORD_DEFAULT) . "', '[email protected]'),
('user2', '" . password_hash('password2', PASSWORD_DEFAULT) . "', '[email protected]')");
// JWT Secret Key for HS256 (in a real-world scenario, this should be stored securely)
$jwt_secret = 'your_secret_key_here';
// RSA keys for RS256 (in a real-world scenario, these should be stored securely)
$private_key = <<<EOD
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQC8kGa1pSjbSYZVebtTRBLxBz5H4i2p/llLCrEeQhta5kaQu/Rn
vuER4W8oDH3+3iuIYW4VQAzyqFpwuzjkDI+17t5t0tyazyZ8JXw+KgXTxldMPEL9
5+qVhgXvwtihXC1c5oGbRlEDvDF6Sa53rcFVsYJ4ehde/zUxo6UvS7UrBQIDAQAB
AoGAb/MXV46XxCFRxNuB8LyAtmLDgi/xRnTAlMHjSACddwkyKem8//8eZtw9fzxz
bWZ/1/doQOuHBGYZU8aDzzj59FZ78dyzNFoF91hbvZKkg+6wGyd/LrGVEB+Xre0J
Nil0GReM2AHDNZUYRv+HYJPIOrB0CRczLQsgFJ8K6aAD6F0CQQDzbpjYdx10qgK1
cP59UHiHjPZYC0loEsk7s+hUmT3QHerAQJMZWC11Qrn2N+ybwwNblDKv+s5qgMQ5
5tNoQ9IfAkEAxkyffU6ythpg/H0Ixe1I2rd0GbF05biIzO/i77Det3n4YsJVlDck
ZkcvY3SK2iRIL4c9yY6hlIhs+K9wXTtGWwJBAO9Dskl48mO7woPR9uD22jDpNSwe
k90OMepTjzSvlhjbfuPN1IdhqvSJTDychRwn1kIJ7LQZgQ8fVz9OCFZ/6qMCQGOb
qaGwHmUK6xzpUbbacnYrIM6nLSkXgOAwv7XXCojvY614ILTK3iXiLBOxPu5Eu13k
eUz9sHyD6vkgZzjtxXECQAkp4Xerf5TGfQXGXhxIX52yH+N2LtujCdkQZjXAsGdm
B2zNzvrlgRmgBrklMTrMYgm1NPcW+bRLGcwgW2PTvNM=
-----END RSA PRIVATE KEY-----
EOD;
$public_key = <<<EOD
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8kGa1pSjbSYZVebtTRBLxBz5H
4i2p/llLCrEeQhta5kaQu/RnvuER4W8oDH3+3iuIYW4VQAzyqFpwuzjkDI+17t5t
0tyazyZ8JXw+KgXTxldMPEL95+qVhgXvwtihXC1c5oGbRlEDvDF6Sa53rcFVsYJ4
ehde/zUxo6UvS7UrBQIDAQAB
-----END PUBLIC KEY-----
EOD;
// Function to generate JWT
function generateJWT($user_id, $username, $alg = 'HS256', $exp = 3600) {
global $jwt_secret, $private_key;
$header = [
'typ' => 'JWT',
'alg' => $alg
];
$payload = [
'user_id' => $user_id,
'username' => $username,
'exp' => time() + $exp
];
$base64_header = base64_encode(json_encode($header));
$base64_payload = base64_encode(json_encode($payload));
$signature = '';
switch ($alg) {
case 'HS256':
$signature = hash_hmac('sha256', "$base64_header.$base64_payload", $jwt_secret, true);
break;
case 'RS256':
openssl_sign("$base64_header.$base64_payload", $signature, $private_key, OPENSSL_ALGO_SHA256);
break;
case 'none':
// No signature for 'none' algorithm
break;
}
$base64_signature = base64_encode($signature);
return "$base64_header.$base64_payload.$base64_signature";
}
// Function to validate JWT
function validateJWT($token) {
global $jwt_secret, $public_key;
$parts = explode('.', $token);
if (count($parts) != 3) return false;
$header = json_decode(base64_decode($parts[0]), true);
$payload = json_decode(base64_decode($parts[1]), true);
$signature = base64_decode($parts[2]);
if ($payload['exp'] < time()) return false;
$base64_header = $parts[0];
$base64_payload = $parts[1];
switch ($header['alg']) {
case 'HS256':
$expected_signature = hash_hmac('sha256', "$base64_header.$base64_payload", $jwt_secret, true);
return hash_equals($expected_signature, $signature) ? $payload : false;
case 'RS256':
return openssl_verify("$base64_header.$base64_payload", $signature, $public_key, OPENSSL_ALGO_SHA256) === 1 ? $payload : false;
case 'none':
// Warning: 'none' algorithm is insecure and should not be used in production
return $payload;
default:
return false;
}
}
// Handle requests
$request_method = $_SERVER['REQUEST_METHOD'];
$request_uri = $_SERVER['REQUEST_URI'];
switch ($request_uri) {
case '/login':
if ($request_method === 'POST') {
$data = json_decode(file_get_contents('php://input'), true);
$username = $data['username'] ?? '';
$password = $data['password'] ?? '';
$alg = $data['alg'] ?? 'HS256';
$stmt = $db->prepare('SELECT id, password FROM users WHERE username = :username');
$stmt->bindValue(':username', $username, SQLITE3_TEXT);
$result = $stmt->execute();
$user = $result->fetchArray(SQLITE3_ASSOC);
if ($user && password_verify($password, $user['password'])) {
$token = generateJWT($user['id'], $username, $alg);
echo json_encode(['token' => $token]);
} else {
http_response_code(401);
echo json_encode(['error' => 'Invalid credentials']);
}
}
break;
case '/refresh':
if ($request_method === 'POST') {
$headers = getallheaders();
$token = $headers['Authorization'] ?? '';
$token = str_replace('Bearer ', '', $token);
$payload = validateJWT($token);
if ($payload) {
$parts = explode('.', $token);
$header = json_decode(base64_decode($parts[0]), true);
$new_token = generateJWT($payload['user_id'], $payload['username'], $header['alg']);
echo json_encode(['token' => $new_token]);
} else {
http_response_code(401);
echo json_encode(['error' => 'Invalid token']);
}
}
break;
case '/user':
if ($request_method === 'GET') {
$headers = getallheaders();
$token = $headers['Authorization'] ?? '';
$token = str_replace('Bearer ', '', $token);
$payload = validateJWT($token);
if ($payload) {
$stmt = $db->prepare('SELECT id, username, email FROM users WHERE id = :id');
$stmt->bindValue(':id', $payload['user_id'], SQLITE3_INTEGER);
$result = $stmt->execute();
$user = $result->fetchArray(SQLITE3_ASSOC);
if ($user) {
echo json_encode($user);
} else {
http_response_code(404);
echo json_encode(['error' => 'User not found']);
}
} else {
http_response_code(401);
echo json_encode(['error' => 'Invalid token']);
}
}
break;
default:
http_response_code(404);
echo json_encode(['error' => 'Not found']);
break;
}
$db->close();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment