185 lines
5.8 KiB
Plaintext
185 lines
5.8 KiB
Plaintext
---
|
|
title: JavaScript
|
|
description: Learn how to integrate Duckity into your web application.
|
|
icon: SiJavascript
|
|
---
|
|
|
|
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:
|
|
|
|
import { SiReact } from "@icons-pack/react-simple-icons";
|
|
|
|
<Cards>
|
|
<Card href="/sdks/react" title="React" icon={<SiReact />}>
|
|
Integrate client-side code with Duckity using the React SDK.
|
|
</Card>
|
|
</Cards>
|
|
|
|
## 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 protection profile created in that application, and
|
|
4. The ID of the protection profiles to use
|
|
|
|
If you're missing either of those, head over to the [Duckity Dashboard](https://app.duckity.com) or
|
|
read the [Quick Start](/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 [step]
|
|
|
|
Follow these steps depending on your application:
|
|
|
|
<Tabs items={["Installed", "Via CDN"]}>
|
|
<Tab>
|
|
Run the following line in your terminal to install the Duckity SDK.
|
|
|
|
```package-install
|
|
@duckity/js
|
|
```
|
|
|
|
Then import it in your code:
|
|
|
|
```ts
|
|
import * as duckity from "@duckity/js";
|
|
```
|
|
</Tab>
|
|
<Tab>
|
|
If you're using the SDK from a static site, import it using a CDN like
|
|
[esm.sh](https://esm.sh/) instead.
|
|
|
|
```html
|
|
<script type="module">
|
|
// Using esm.sh
|
|
import * as duckity from "https://esm.sh/@duckity/js";
|
|
|
|
// Using jsdelivr.net
|
|
import * as duckity from "https://cdn.jsdelivr.net/npm/@duckity/js";
|
|
|
|
// Using UNPKG
|
|
import * as duckity from "https://unpkg.com/@duckity/js";
|
|
</script>
|
|
```
|
|
</Tab>
|
|
|
|
</Tabs>
|
|
|
|
### Solve a Challenge [step]
|
|
|
|
Once you have the SDK installed, you can request a challenge whenever you need it using
|
|
`duckity.solve()`.
|
|
|
|
```ts
|
|
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(PROTECTION_PROFILE_ID);
|
|
```
|
|
|
|
### Validate a Challenge [step]
|
|
|
|
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 protection
|
|
profile's ID, and the application secret.
|
|
|
|
```ts
|
|
import * as duckity from "@duckity/js";
|
|
|
|
let applicationSecret: string;
|
|
let protectionProfileId: string;
|
|
let clientIp: string;
|
|
let solution: string;
|
|
|
|
let isValid = await duckity.validate(solution, clientIp, applicationSecret, protectionProfileId);
|
|
|
|
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](https://app.duckity.com).
|
|
|
|
## 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.
|
|
|
|
```html
|
|
<!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 PROTECTION_PROFILE_ID = "<your-protection-profile-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(PROTECTION_PROFILE_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>
|
|
```
|
|
|
|
<Callout>
|
|
Solution tokens expire after the time set in the dashboard. In case of failure to validate, try
|
|
refreshing the challenge (calling `duckity.solve()` again).
|
|
</Callout>
|
|
|
|
## 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](https://github.com/duckity-com/sdks).
|
|
|
|
This SDK is licensed under the permissive MIT License, and so will be all contributions to the SDK.
|