The Gyroscope Request Key, or GSKey in short, is a security feature that's thoroughly integrated in version 14.0. Modifications to the application records are now insulated to specific records and actions. For example, a request for updating a product profile has a different, unpredictable key from updating a different product, and also from deleting the same product.
Previous versions of Gyroscope applications can be retrofitted with GSKey by merging changes to auth.php, nano.js and tabs.js (both copies). The emitgskey function is called to output an additional parameter "gskey" to be used by the JavaScript handler.
<button
onclick="updateproduct(<?echo $productid;?>
, '<?emitgskey('updateproduct_'.$productid);?>');">
Update
</button>
The parameter is then passed to the gskey argument in the now extended reloadtab or ajxpgn, depending on the context. For example:
updateproduct=function(productid, gskey){
// ...
reloadtab('product_'+productid,'',
'updateproduct&productid='+productid,
null, //callback
null, //POST params
null, //options
gskey
}
Next in updateproduct.inc.php, we validate the key:
checkgskey('updateproduct_'.$productid);
If the key is invalid, checkgskey will terminate the app with an error message.
The Mechanism
A random key is stored in gsreqkey.php that defines a global context $gsreqkey. This key can be modified with an automated rotation script. Each time a rotation is performed, any authorization token that's currently in display will be invalidated. So it's best to rotate the key during system idle time.
The term "gskey" is used to refer both the hash salt $gsreqkey and the computed access token that populates the gskey variable in JavaScript calls. The token is simply a salted hash of the verb, user id, normalized IP address and a random session token.
The makegskey and emitgskey functions also take a secondary parameter that describes the required security context. For example, if the Delete User button requires either "accounts" or "superadmin" privilege, the following call will return blank if the current user doesn't have the required privilege:
<button onclick="deluser(<?echo $userid;?>,
<?emitgskey('deluser_'.$userid,'accounts, superadmin');?>
Delete
</button>
This way, the security token that's required to delete this particular user is not known to the less privileged user. In practice, this access check may not be necessary, as the delete button should be hidden for non-authorized users to begin with. The access parameter is baked in for convenience.
Is it a "nonce"?
A nonce, or a number that's used only once is often used to secure web applications. The GSKey is not a nonce in the strict sense, as the token can be reused. The objective is not to prevent repeated requests, but to make the request parameter unknown to a malicious user. The token is different if any of the target record, action, network location, user is different. The token also changes each time a user signs in again. The token can also be reset, or "rotated" on the server-side, invalidating any in-flight requests.