22 March 2024
—
The Zucoin wallet app can pass signed wallet authentication data through to third-party websites and services.
The user starts this flow in the Zucoin wallet app, for example by opening a selected website or service inside an HTML iframe.
The link to the website includes additional URL query parameters (for example: ?aaa=bbb&ccc=ddd).
A website or service can check this incoming information and use it to authenticate a Zucoin wallet user.
For example, the result of this authentication can be used to sign a user into an existing account, create an account if one does not exist, and then load a dashboard, product page, or other point of interest.
Web developers can use the following code example to authenticate incoming data from the Zucoin wallet app.
Here's a simple example of how to do it:
<?php
/**
* Uses data in URL query variables to parse and validate an incoming
* user authentication request. Use the result to verify a user in a
* back-end system and/or redirect them to a desired endpoint
*
* @tip Use a sodium encryption library, e.g.
* https://www.php.net/manual/en/book.sodium.php is built into PHP
* 7.2 and above
*
* @returns array|bool An associative array of authentication data on
* success and false on failure
*/
function validate_incoming_user_authentication_request()
{
// Get URL query variables
$url_params = $_GET;
// Note: In PHP, URL query parameters are automatically URL-decoded
$referral_source = isset($url_params['utm_source'])?
$url_params['utm_source']:
null;
// Check if a Splitchain authentication pass-through has occurred
if (!$referral_source || false === strpos($referral_source, 'zucoin_wallet_app_v'))
{
// Not a Zucoin wallet app referral
return false;
}
$version = isset($url_params['zucoin__data_pass_through__version'])?
$url_params['zucoin__data_pass_through__version']:
null;
if ($version !== '1')
{
// Unsupported data pass through version
return false;
}
$key_public__base64urlsafe = isset($url_params['zucoin__data_pass_through__key_public__base64urlsafe'])?
$url_params['zucoin__data_pass_through__key_public__base64urlsafe']:
null;
// Will contain a timestamp in seconds
$timestamp_secs_raw = isset($url_params['zucoin__data_pass_through__data_timestamp_secs'])?
$url_params['zucoin__data_pass_through__data_timestamp_secs']:
null;
if (
!$timestamp_secs_raw ||
!is_string($timestamp_secs_raw) ||
!ctype_digit($timestamp_secs_raw)
) {
// Invalid timestamp secs provided
return false;
}
$timestamp_secs = (int)$timestamp_secs_raw;
$timestamp_secs_signature__base64urlsafe =
isset($url_params['zucoin__data_pass_through__data_timestamp_secs_signature__base64urlsafe'])?
$url_params['zucoin__data_pass_through__data_timestamp_secs_signature__base64urlsafe']:
null;
if (
!is_string($key_public__base64urlsafe) ||
!is_string($timestamp_secs_signature__base64urlsafe)
) {
// Invalid public key or signature provided
return false;
}
// Verify the signed data
$verified = false;
try
{
$signature_binary = sodium_base642bin(
$timestamp_secs_signature__base64urlsafe,
SODIUM_BASE64_VARIANT_URLSAFE
);
$key_public_binary = sodium_base642bin(
$key_public__base64urlsafe,
SODIUM_BASE64_VARIANT_URLSAFE
);
$verified = sodium_crypto_sign_verify_detached(
$signature_binary,
// Verify the exact string that the wallet signed
$timestamp_secs_raw,
$key_public_binary
);
}
catch (Throwable $error)
{
// Invalid base64_urlsafe data provided
return false;
}
if (!$verified)
{
// Cryptographic signature verification failed. Invalid details provided
return false;
}
return [
'referral_source' => $referral_source,
'version' => $version,
'key_public__base64urlsafe' => $key_public__base64urlsafe,
'timestamp_secs' => $timestamp_secs,
'timestamp_secs_signature__base64urlsafe' => $timestamp_secs_signature__base64urlsafe,
];
}
You can then use the value of key_public__base64urlsafe as a user ID.
Developers should also check when the authentication data was cryptographically signed.
For example, login credentials from two weeks ago should fail. Future-dated timestamps should fail too.
You can use the following example to check if an authentication request is within 30 seconds of the current time:
<?php
// (Result from above)
$zucoin_user_authenticated = validate_incoming_user_authentication_request();
if (!$zucoin_user_authenticated)
{
// Stop, invalid
return false;
}
// Check if the timestamp is outside the allowed window
function is_expired_incoming_user_authentication_request($auth_data)
{
$time_now_secs = time();
$time_passed_secs = abs($time_now_secs - $auth_data['timestamp_secs']);
$expiry_time_secs = 30;
if ($time_passed_secs > $expiry_time_secs)
{
// Authentication data is outside the allowed time window, fail
return true;
}
// Authentication data is recent
return false;
}
$expired = is_expired_incoming_user_authentication_request($zucoin_user_authenticated);
if ($expired)
{
// Stop, invalid
return false;
}
Once verification succeeds, you can use this data, such as the user's public key, in your website or app to check whether a user exists and run the appropriate process.
If the user exists, you can take them to their home screen, account, or dashboard page.
If the user doesn't exist, create an entry in your database for them first, then take them to their home screen, account, or dashboard page.
That's it—let us know what you build with it!
Disclaimer: Of course, this is not advice, financial or otherwise. It’s also important to consider the risks and challenges associated with any potential benefits.
Get periodic insights, news, offers + more, trusted by 1,000+ readers.
(By subscribing you agree to receive news + marketing emails, but we won't spam or sell your data!)