mirror of
https://github.com/myronblair/epictravelexpeditions
synced 2026-06-30 17:50:08 -05:00
118 lines
3.0 KiB
PHP
118 lines
3.0 KiB
PHP
<?php
|
|
/**
|
|
* JWT Authentication Functions
|
|
* Simple JWT implementation for PHP
|
|
*/
|
|
|
|
class JWT {
|
|
|
|
/**
|
|
* Create a JWT token
|
|
*/
|
|
public static function encode($payload, $secret) {
|
|
$header = json_encode(['typ' => 'JWT', 'alg' => 'HS256']);
|
|
$payload = json_encode($payload);
|
|
|
|
$base64UrlHeader = self::base64UrlEncode($header);
|
|
$base64UrlPayload = self::base64UrlEncode($payload);
|
|
|
|
$signature = hash_hmac('sha256', $base64UrlHeader . "." . $base64UrlPayload, $secret, true);
|
|
$base64UrlSignature = self::base64UrlEncode($signature);
|
|
|
|
return $base64UrlHeader . "." . $base64UrlPayload . "." . $base64UrlSignature;
|
|
}
|
|
|
|
/**
|
|
* Decode and verify a JWT token
|
|
*/
|
|
public static function decode($jwt, $secret) {
|
|
$parts = explode('.', $jwt);
|
|
|
|
if (count($parts) !== 3) {
|
|
return false;
|
|
}
|
|
|
|
list($base64UrlHeader, $base64UrlPayload, $base64UrlSignature) = $parts;
|
|
|
|
$signature = self::base64UrlDecode($base64UrlSignature);
|
|
$expectedSignature = hash_hmac('sha256', $base64UrlHeader . "." . $base64UrlPayload, $secret, true);
|
|
|
|
if (!hash_equals($signature, $expectedSignature)) {
|
|
return false;
|
|
}
|
|
|
|
$payload = json_decode(self::base64UrlDecode($base64UrlPayload), true);
|
|
|
|
// Check expiration
|
|
if (isset($payload['exp']) && $payload['exp'] < time()) {
|
|
return false;
|
|
}
|
|
|
|
return $payload;
|
|
}
|
|
|
|
/**
|
|
* Create authentication token
|
|
*/
|
|
public static function createToken($email) {
|
|
$payload = [
|
|
'sub' => $email,
|
|
'iat' => time(),
|
|
'exp' => time() + JWT_EXPIRY
|
|
];
|
|
|
|
return self::encode($payload, JWT_SECRET_KEY);
|
|
}
|
|
|
|
/**
|
|
* Verify token from Authorization header
|
|
*/
|
|
public static function verifyToken() {
|
|
$headers = getallheaders();
|
|
|
|
if (!isset($headers['Authorization'])) {
|
|
return false;
|
|
}
|
|
|
|
$authHeader = $headers['Authorization'];
|
|
|
|
if (!preg_match('/Bearer\s+(.*)$/i', $authHeader, $matches)) {
|
|
return false;
|
|
}
|
|
|
|
$token = $matches[1];
|
|
$payload = self::decode($token, JWT_SECRET_KEY);
|
|
|
|
return $payload;
|
|
}
|
|
|
|
/**
|
|
* Base64 URL encode
|
|
*/
|
|
private static function base64UrlEncode($data) {
|
|
return str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($data));
|
|
}
|
|
|
|
/**
|
|
* Base64 URL decode
|
|
*/
|
|
private static function base64UrlDecode($data) {
|
|
return base64_decode(str_replace(['-', '_'], ['+', '/'], $data));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Require authentication middleware
|
|
*/
|
|
function requireAuth() {
|
|
$payload = JWT::verifyToken();
|
|
|
|
if (!$payload) {
|
|
http_response_code(401);
|
|
echo json_encode(['error' => 'Unauthorized']);
|
|
exit;
|
|
}
|
|
|
|
return $payload;
|
|
}
|