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

Join the newsletter

700+ people get the latest insights, news, offers + more

(By subscribing you agree to receive news + marketing emails, but we won’t spam or sell your data!)

Code language: JavaScript (DOM), see also: PHP
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.

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:

JavaScript
/**
 * 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 Load a sodium encryption library beforehand, e.g.
 * https://github.com/jedisct1/libsodium.js, as it's not built into 
 * JavaScript
 *
 * @returns Object|bool An object of authentication data on success 
 * and false on fail
 */
function validate_incoming_user_authentication_request()
{
	// Get URL query variable from current URL
	const url_params = new URLSearchParams(window.location.search);

	// Note URLSearchParams() auto applies decodeURIComponent()
	const referral_source = url_params.get('utm_source');

	if (referral_source && referral_source.includes('zucoin_wallet_app_v'))
	{
		// Not a zucoin wallet app referral

		return false;
	}

	const version =
		url_params.get('zucoin__data_pass_through__version');

	if ('1' !== version)
	{
		// Unsupported data pass through version

		return false;
	}

	const key_public__base64urlsafe =
		url_params.get('zucoin__data_pass_through__key_public__base64urlsafe');

	// Will contain a timestamp in secs
	const timestamp_secs__raw =
		url_params.get('zucoin__data_pass_through__data_timestamp_secs');

	if (
		!timestamp_secs__raw ||
		'string' !== typeof timestamp_secs__raw ||
		isNaN(timestamp_secs__raw) ||
		!Number.isInteger(Number(timestamp_secs__raw))
	) {
		// Invalid timestamp secs provided

		return false;
	}

	const timestamp_secs = parseInt(timestamp_secs__raw);

	const timestamp_secs_signature__base64urlsafe =
		url_params.get('zucoin__data_pass_through__data_timestamp_secs_signature__base64urlsafe');

	// Verify the signed data
	const signature__binary = sodium.from_base64(
		timestamp_secs_signature__base64urlsafe,
		sodium.base64_variants.URLSAFE
	);

	const key_public__binary = sodium.from_base64(
		key_public__base64urlsafe,
		sodium.base64_variants.URLSAFE
	);

	const verified = sodium.crypto_sign_verify_detached(
		signature__binary,
		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:

JavaScript
// (Result from above)
const 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)
{
	const time_now_secs = Math.round((Date.now() / 1000));
	const time_passed_secs = time_now_secs - auth_data.timestamp_secs;
	const 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;
}

const expired = is_expired_incoming_user_authentication_request(
	zucoin_user_authenticated
);

if (expired) 
{
	// Stop, invalid
}

That’s it—Let us know what you build with it!