Duckity

JavaScript

Learn how to integrate Duckity into your web application.

Welcome to the Duckity JavaScript SDK documentation! This guide will teach you how to install and set up the SDK in no time.

The following SDKs depend on this one and provide specialized wrappers for different frameworks:

Quick Start

Before you can integrate Duckity into your application, you'll need to have the following:

  1. An application,
  2. CORS origins set up pointing to your application's origin(s),
  3. At least one policy created in that application, and
  4. The ID of the policies to use

If you're missing either of those, head over to the Duckity Dashboard or read the Quick Start guide to learn how to set those up.

Once you got those ready, follow these steps to get things running on your client:

Install the SDK

Follow these steps depending on your application:

Run the following line in your terminal to install the Duckity SDK.

npm install @duckity/js

Then import it in your code:

import * as duckity from "@duckity/js";

Solve a Challenge

Once you have the SDK installed, you can request a challenge whenever you need it using duckity.solve().

import duckity from "@duckity/js";

/// Slow! Runs in a web worker, yet don't let it block code below unless necessary.
let solution: string = await duckity.solve(POLICY_ID);

Validate a Challenge

Send the solution token to your backend server any way you want. A header or parameter in a JSON field will work.

Once in the server, you'll need the client's IP, their submitted solution token, the policy's ID, and the application secret.

import * as duckity from "@duckity/js";

let applicationSecret: string;
let policyId: string;
let clientIp: string;
let solution: string;

let isValid = await duckity.validate(solution, clientIp, applicationSecret, policyId);

if (isValid) {
    // Keep processing the request.
} else {
    // Return an error to the client.
}

That's it! Now Duckity is protecting your endpoint. You can customize the behavior in the Duckity Dashboard.

Advanced Usage

Solving a challenge on request works well for simple setups. However, UX can be greatly improved changing a few settings and planning when to solve challenges.

Asynchronous Challenge Solving

The challenge does not need to wait for the user to finish filling up a form or completing an action to be issued. When you can guess the user will need a solution token, it is a good idea to start computing it before the user needs it.

For example, if the user opens a login page, you can infer the user will need a challenge solved to be able to attempt to log in. You can solve a challenge beforehand so that the user does not need to wait.

<!doctype html>
<html>
    <head>
        <style>
            .hidden {
                display: none;
            }
        </style>
    </head>
    <body>
        <form id="form">
            <input name="email" />
            <input name="password" />
            <button type="submit" id="submit-button">Log In</button>
            <div id="submit-loading" class="hidden">Logging you in...</div>
        </form>
        <script type="module">
            import * as duckity from "https://esm.sh/@duckity/js";

            const POLICY_ID = "<your-policy-id>";

            const form = document.getElementById("form");
            const submitButton = document.getElementById("submit-button");
            const submitLoading = document.getElementById("submit-loading");

            // A Promise<string>, it will solve a challenge in the background while the user logs
            // in. Do not `await` it here, it will prevent the `form.addEventListener()` call from
            // running until the challenge is solved, which takes some time.
            let solutionPromise = duckity.solve(POLICY_ID);

            form.addEventListener("submit", async (e) => {
                e.preventDefault();

                submitButton.classList.add("hidden");
                submitLoading.classList.remove("hidden");

                let solution = await solutionPromise;

                // Do your stuff.
            });
        </script>
    </body>
</html>

Solution tokens expire after the time set in the dashboard. In case of failure to validate, try refreshing the challenge (calling duckity.solve() again).

Contributing & License

All contributions are welcome to the SDK. Whether it's bug fixes, suggestions, new features, documentation updates, or fixing a typo, if you think you can make this SDK better, feel free to make a pull request in the GitHub repository.

This SDK is licensed under the permissive MIT License, and so will be all contributions to the SDK.

On this page