Passwordless Third Party Logins - How Do I Authenticate A Zucoin Wallet On My Website Or App? (Using PHP)

Code language: PHP, see also: JavaScript (DOM).
Available since: Zucoin wallet app v177.
Applies to feature version: v1+.
Document version: v1.

The Zucoin wallet app can allow a user to "pass through" certain credentials onto third-party websites and services.

The Zucoin user must first action this by, for example, clicking a button in the Zucoin wallet app that will load the selected website or service in a HTML iframe element.

The link to the website will have additional URL query parameter variables appended (for example: ?aaa=bbb&ccc=ddd).

A website or service can check for this incoming information and use it to authenticate a Zucoin wallet user.

This useful feature allows websites to automatically authenticate a Zucoin user.

As an example, the result of this authentication can be used to login a user into their an account (or create an account if one doesn't exist), then immediately load a dashboard, product page or other points of interest.

For websites that want to accept incoming Zucoin users, web developers can use the follow code example to authenticate incoming data from the Zucoin wallet app.

Here's a simple example of how to do it:

PHP
<?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 fail
 */
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 && strpos($referral_source, 'zucoin_wallet_app_v') !== false) 
	{
		// 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 secs
	$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;

	// Verify the signed data
	$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,
		// Ensure the timestamp is a string as required by sodium_crypto_sign_verify_detached
		(string) $timestamp_secs, 
		$key_public_binary
	);

	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 the "key_public__base64urlsafe" as a user ID.

It's strongly recommended developers also check the timestamp of when the authentication data was last cryptographically signed.

For instance, old login credentials from two weeks ago should fail.

You can use the following example to check if an authentication request is less than 30 seconds old:

PHP
<?php
// (Result from above)
$zucoin_user_authenticated = validate_incoming_user_authentication_request();

if (!$zucoin_user_authenticated) 
{
    // Stop, invalid
}

// Check if it's too old
function is_expired_incoming_user_authentication_request($auth_data)
{
	$time_now_secs = time();
	$time_passed_secs = $time_now_secs - $auth_data['timestamp_secs'];
	$expiry_time_secs = 30;

	if ($time_passed_secs > $expiry_time_secs) 
	{
		// Authentication data is too old to be valid, fail

		return true;
	}

	// Authentication data is recent

	return false;
}

$expired = is_expired_incoming_user_authentication_request($zucoin_user_authenticated);

if ($expired) 
{
	// Stop, invalid
}

Once the above verification functions are called and successfully pass, you can then use this data, such as the user's public key, in your website or app to check if a user exists or not, and run the appropriate processes.

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.

 

© MyZucoins. See Terms and Privacy.