Identity Browser SDK
Installation
Our Browser SDK is distributed via npm, and can be installed using your preferred package manager.
# Install using npm
npm install --save @zalter/identity-js
# Install using Yarn
yarn add @zalter/identity-js
Initialization
Configure the auth client.
import { Auth } from '@zalter/identity-js';
const config = {
projectId: '<your-project-id>'
};
export const auth = new Auth(config);
Sign in with One-Time-Code
This authentication strategy is based on a one-time-passcode of 8 characters long alphanumeric code.
Start sign in
Initiates the authentication process using an email address.
import { auth } from './auth';
await auth.signInWithCode('start', {
email: '<email>'
});
Finalize sign in
Confirms the authentication with the one-time-code that was sent to the email address.
import { auth } from './auth';
await auth.signInWithCode('finalize', {
code: '<code>'
});
Sign in with Magic Link
This authentication strategy is based on a magic link.
Start sign in
Initiates the authentication process using an email address.
import { auth } from './auth';
await auth.signInWithLink('start', {
email: '<email>',
redirectUri: '<redirectUri>'
});
redirectUri
should match one of the links configured in your project settings.
Finalize sign in
import { auth } from './auth';
await auth.signInWithLink('finalize', {
token: '<token>'
});
token
is the value of the url hash (without #
).
Sign out
Deletes credential from the client's browser storage (by default localStorage) and from Zalter servers such that even if the client credential is somehow preserved, subsequent requests will fail (HTTP Status code of 401).
import { auth } from './auth';
await auth.signOut();
Get signing key identifier
To verify a user signature, on your backend you need to lookup their signing public key by its key ID. The user should attach it to the request along with the signature.
const user = await auth.getCurrentUser();
const keyId = user.subSigKeyId;
console.log(keyId); // e.g. 28KDJ293Lk1
Data signing
Once the user is signed-in, they have the ability to sign any data.
const user = await auth.getCurrentUser();
const dataToSign = new Uint8Array(0); // can be any Uint8Array
const sig = user.signMessage(dataToSign); // results a 64 byte length Uint8Array
Signing a request
Most common use-cases would be signing http requests.
Similar to Authorization
header with Bearer
where you attach a JWT, here you have to attach the
user signature instead. We use a custom header, X-Signature
, to avoid any possible conflict with
standard headers.
/*
* Signing helper function that accepts a requestInit, similar to fetch.
* @param {RequestInit} request
* @return {Promise<RequestInit>}
*/
async function signRequest(request) {
const { method, headers, body } = request;
// Load current user
const user = await auth.getCurrentUser();
// Get signing key ID
const keyId = user.subSigKeyId;
// Convert the body from String to Uint8Array
const dataToSign = new TextEncoder().encode(body);
// Sign the data using the user credentials
const sig = await user.signMessage(dataToSign);
// Convert the sig from Uint8Array to Base64
// You might need an external package to handle Base64 encode/decode
// https://www.npmjs.com/package/buffer
const encodedSig = Buffer.from(sig).toString('base64');
return {
method,
headers: {
...headers,
'x-signature': `${keyId};${encodedSig}`
},
body
};
}
// Signing a GET request (without body)
const request = await signRequest({
method: 'GET'
});
const response = await fetch('/api/orders', request);
// Signing a POST request (with body)
const request = await signRequest({
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
customerId: '12345'
})
});
const response = await fetch('/api/orders', request);