Reputation:
I have hosted two domains on the same server, domain A and domain B.
Domain A will generate the unique access token to the content of domain B.
Domain A
<?php
//http://php.net/manual/en/function.phpversion.php
//echo 'Version of PHP: ' . phpversion();
session_start();
//$expiry_timestamp = time() + $expiry;
//https://davidwalsh.name/random_bytes //https://secure.php.net/random_bytes
//$token = bin2hex(random_bytes(64));
$token = bin2hex(openssl_random_pseudo_bytes(64));
//$time_token = 12000;
//$time_token = srand(floor(time() / $time_token));
//echo $token;
$_SESSION['token']=$token;
?>
<html>
<head>
</head>
<body>
<a href= "domainB.com/content1.php?token=<?php echo $_SESSION['token']; ?>">Content 1</a>
</body>
</html>
The process of generating a token seems to be the right one, it has been easy to generate it.
Now comes my problem, how can I validate the generated token from domain A to domain B ?. The generated token must only be valid for the content that generated the token, the token must not be valid for other content, the token must be unique so that user can not share access to another user if it is not from his or her computer, the token must be valid only for 4 hrs of access after 4 hrs the token will no longer be valid to display the content must generate a new token to access again.
Can this process be done using a cookie without using a database?
Maybe identifying both domains A and B using a key, something like that
$APP_SECRET_KEY = "key code secret";
Upvotes: 6
Views: 3724
Reputation: 3082
Using a shared secret key is a good approach here.
I tend to use HMAC when I need to generate and validate a token (e.g.: E-Mail verification) and don't want to store it in a DB. Plus, HMAC is built in to PHP, so no library is needed here.
The idea is, on top of your data, you add a signature to verify that this token was created by your application on Domain A. You generate the token the same way again on Domain B to verify it.
Example:
Shared function to generate the token:
function buildVerificationToken($expires, $content)
{
// Same function on both domains
$APP_SECRET_KEY = 'key code secret'; // Maybe move that out of source code
$tokenData = [
'expires' => $expires, // Include it in signatur generation to prevent user from changing it in URL
'content' => $content, // Create different token for different content
'ip' => $_SERVER['REMOTE_ADDR'], // Identify the browser to make it not shareable. Best approach I could think of for this part.
];
$serialized = json_encode($tokenData);
return hash_hmac('sha256', $serialized, $APP_SECRET_KEY);
}
Generate the token on Domain A:
<?php
$expires = time() + (4 * 3600); // +4h
?>
<a href= "domainB.com/content1.php?expires=<?php echo $expires; ?>&token=<?php echo buildVerificationToken($expires, 'content1'); ?>">Content 1</a>
Verify it on domain B:
$providedExpires = (int) $_GET['expires'];
$providedToken = $_GET['token'];
$verificationToken = buildVerificationToken($providedExpires, 'content1'); // Build token the same way
if (!hash_equals($verificationToken, $providedToken)) { // hash_equals instead of string comparison to prevent timing attacks
// User provided forged token, token for another content, or another IP
die('Bad token'); // However you want to handle this
}
if (time() > $providedExpires) { // Check expiry time. We can trust the user did not modify it as we checked the HMAC hash
die('Token expired'); // However you want to handle this
}
// User is allowed to see content1
Upvotes: 8
Reputation: 8415
Json Web Token (JWT) seems to fit your requirements. Both applications use one secret key to exchange tokens with encrypted data one another.
Example use-case:
$secret="secret"
iat
field), the user id (the sub
field) and the content id (the content
field)$data = [
"sub" => "1234567890",
"iat" => 1516239022,
"content" => 1
];
Application A encodes the raw data with the secret key using HS256 algorithm ($token = jwt_encode($raw, 'HS256', $secret)
). The output $token
will be:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwiaWF0IjoxNTE2MjM5MDIyLCJjb250ZW50IjoxfQ.idM7d2fgmJVk3WjANwG-Gt6sY0lyE3eTvpKRpwITHRs
You can parse the token to see its content in the JWT home page.
The token is send to the application B. This application decodes the token with the same algorithm and shared secret key ($raw = jwt_decode($token, 'HS256', $secret)
). The raw data will be available in the application B. This data can be used to validate the token:
sub
field and check if it is correctcontent
field and check if it is correctiat
field and check if it is in the last 4 hours.There are several PHP libraries implement JWT for you.
Upvotes: 1