hanko-sdk
v1.0.2
Published
Hanko SDK for Node.js
Downloads
8
Readme
Hanko Node.js SDK
This package is maintained by Hanko.
Contents
- Hanko Node.js SDK
Introduction
This SDK provides an API client that lets you communicate with the Hanko Authentication API to easily integrate FIDO®-based authentication into your web application written in Node.js.
Documentation
- Hanko Documentation website
- Hanko Authentication API reference
Installation
npm install 'hanko-sdk'
Usage
In this guide we'll assume you are using the latest version of Express.js
framework for demonstration purposes only.
Prerequisites
In order to utilize the client provided by the SDK you need an API URL as well as API credentials in the form of an API key ID and an API secret. View our getting started guide in the official documentation on how to obtain these.
Run tests
Trigger tests by going to the root directory and running
npm run test
Create a new Hanko API Client
Once you have set up your account, create a HankoClientConfig
with the API URL, the API Key Id and the API secret and
use it to construct a HankoWebAuthnClient
.
const hankoClientConfig = new HankoClientConfig({
apiUrl: "API_URL",
apiSecret: "API_SECRET",
apiKeyId: "API_KEY_ID",
});
const hankoClient = new HankoWebAuthnClient(hankoClientConfig);
Register a WebAuthn credential
Registration of a WebAuthn credential involves retrieving credential creation options from the Hanko API (initialization), passing these options to the browser's Web Authentication API and lastly sending the WebAuthn response back to the Hanko API for validation (finalization).
For a more complete example of the authentication process, see the implementation guide in the Hanko documentation.
Step 1: Registration initialization
Using defaults
// To create the user object you'll need a userId and a userName. The userName usually comes either from a form a user provides when registering for the first time, or from your existing session store or database, as well as a related userId, which may need to be generated if it is a new user.
const registrationUser = new RegistrationInitializationUser({
id: "1d467gju68jklu14", // existing userId fetched from DB
name: "John Doe",
displayName: "John",
});
const request = new RegistrationInitializationRequest({
user: registrationUser,
options: registrationInitializationOptions,
});
hankoClient
.initializeRegistration(request) //returns a promise
.then((response) => {
res.status(200).json({
status: "ok",
credentialCreationOptions: response.data,
});
})
.catch((error) => console.log(error));
Modifying registration options
You can modify the default credential creation options for registration as follows:
const registrationUser = new RegistrationInitializationUser({
id: "1d467gju68jklu14", // existing userId fetched from DB
name: "John Doe",
displayName: "John",
});
const selectionCriteria = new AuthenticatorSelectionCriteria();
// Example: require a Plattform Authenticator (e.g. Apple Touch ID, Windows Hello etc.)
// Use AuthenticatorAttachment.CROSS_PLATFORM to require a Security Key (e.g. a Yubikey)
selectionCriteria.setAuthenticatorAttachment(AuthenticatorAttachment.PLATFORM);
// Example: require user verification
selectionCriteria.setUserVerification(UserVerificationRequirement.REQUIRED);
// Example: do not require a resident key
selectionCriteria.setRequireResidentKey(false);
const registrationInitializationOptions =
new RegistrationInitializationOptions();
registrationInitializationOptions.setAttestation(
// Example: require Attestation
AttestationConveyancePreference.DIRECT
);
registrationInitializationOptions.setAuthenticatorSelection(selectionCriteria);
const request = new RegistrationInitializationRequest({
user: registrationUser,
options: registrationInitializationOptions,
});
hankoClient
.initializeRegistration(request) // returns a promise
.then((response) => {
res.status(200).json({
status: "ok",
credentialCreationOptions: response.data,
});
})
.catch((error) => console.log(error));
Step 2: Pass Hanko API response to the browser's Web Authentication API
Initialization with the Hanko API returns a response that represents
PublicKeyCredentialCreationOptions
that must be provided to the WebAuthn Authentication API to create a credential.
The WebAuthn Authentication API requires specially encoded json-like data. You can use the Hanko WebAuthn Library in the frontend to take the initializationResponse
data we have just created, encode it and send it to the browser's WebAuthn API.
You need to provide the initializeRegistration
response data to the create
function of the
Hanko WebAuthn Library for creating a credential. For a more complete example of the registration process, see the implementation guide in the Hanko documentation.
Step 3: Registration finalization
Pass the Web Authentication API response as returned from the Hanko WebAuthn library's create
function to the finalizeRegistration
client method.
const { webAuthnResponse } = req.body; //"{\"id\": \"ATIihVy...\", ...}"
hankoClient
.finalizeRegistration(webAuthnResponse) //returns a promise
.then((response) => {
res.status(200).json({
status: "ok",
credential: response.data.credential,
});
})
.catch((error) => console.log(error));
Authenticate with a registered WebAuthn credential
For a more complete example of the authentication process, see the implementation guide in the Hanko documentation.
Step 1: Authentication initialization
const { user_name } = req.query;
const userId = "1d467gju68jklu14"; // found userId in db using user_name
const user = new AuthenticationInitializationUser(userId);
const request = new AuthenticationInitializationRequest();
request.setUser(user);
hankoClient
.initializeAuthentication(request) //returns a promise
.then((response) => {
res.status(200).json({
credentialRequestOptions: response.data,
status: "ok",
});
})
.catch((error) => console.log(error));
Step 2: Pass Hanko API response to Web Authentication API
You can provide the initializeAuthentication
response data to the get
function of the
Hanko WebAuthn Library for authenticating with a credential.
For a more complete example of the authentication process, see the implementation guide in the Hanko documentation.
Step 3: Authentication finalization
Pass the Web Authentication API response as returned from the Hanko WebAuthn Library's get
function to the finalizeAuthentication
client method.
const { webAuthnResponse } = req.body; //"{\"id\": \"DaNOpBx...\", ...}"
hankoClient
.finalizeAuthentication(webAuthnResponse) //returns a promise
.then((response) => {
res.status(200).json({
authenticatedCredential: response.data.credential,
status: "ok",
});
})
.catch((error) => console.log(error));
Making transactions
A transaction is technically the equivalent of an authentication, with the difference being that when initializing a transaction, a transactionText
can be included, which becomes part of the authentication challenge. This way it will be cryptographically signed and cannot be altered anymore.
The message itself can be any type of text, so you could sign a JSON object for example. In the following example we simply use the string Pay 5$ to Bob?
.
Again, this is a 3-step process:
Step 1: Transaction initialization
const { user_name } = req.query;
const userId = "1d467gju68jklu14"; // found userId in your db using user_name
const user = new AuthenticationInitializationUser(userId);
const request = new TransactionInitializationRequest("Pay 5$ to Bob?");
request.setUser(user);
hankoClient
.initializeTransaction(request) // returns a promise
.then((response) => {
res.status(200).json({
credentialRequestOptions: response.data,
status: "ok",
});
})
.catch((error) => console.log(error));
Step 2: Pass Hanko API response to Web Authentication API
You can provide the initializationResponse
to the get
function of the
Hanko WebAuthn Library for authenticating with a credential.
For a more complete example of the authentication process, see the implementation guide in the Hanko documentation.
Step 3: Transaction finalization
Pass the Web Authentication API response as returned from the Hanko WebAutn Library's get
function to the finalizeTransaction
client method.
const { webAuthnResponse } = req.body; // "{\"id\": \"fSmpQnC...\", ...}"
hankoClient
.finalizeTransaction(webAuthnResponse) //returns a promise
.then((response) => {
res.status(200).json({
authenticatedCredential: response.data.credential,
status: "ok",
});
})
.catch((error) => console.log(error));
Credential management
You can list and manage all stored credentials via the Hanko Authentication API.
// Search for credentials filtering by userId and paginating results.
const { user_id, page, page_size } = req.query;
hankoClient
.listCredentials({ user_id, page, page_size })
.then((response) => {
res.status(200).json({
status: "ok",
credentials: response.data,
});
})
.catch((error) => console.log(error));
const { credentialId } = req.params;
// e.g. "AQohBypyLBrx8R_UO0cWQuu7hhRGv7bPRRGtbQLrjl..."
// Get all details of the specified credential.
hankoClient
.getCredential(credentialId) //returns a promise
.then((response) => {
res.status(200).json({
status: "ok",
credential: response.data,
});
})
.catch((error) => console.log(error));
// Update the name of a credential.
const { credentialId } = req.params;
const { credentialName } = req.body;
const updateRequest = new CredentialUpdateRequest();
updateRequest.setName(credentialName);
hankoClient
.updateCredential(credentialId, updateRequest) //returns a promise
.then((response) => {
res.status(200).json({
status: "ok",
});
})
.catch((error) => console.log(error));
// Delete the specified credential.
const { credentialId } = req.params;
hankoClient
.deleteCredential(credentialId)
.then((response) => {
res.status(200).json({
status: "ok",
message: `Deleted credential ${credentialId}`,
});
})
.catch((error) => console.log(error));