Update docs

This commit is contained in:
2026-10-06 23:12:12 -03:00
parent 85722f1a53
commit 01f7228f6f
7 changed files with 107 additions and 111 deletions
+5 -5
View File
@@ -1,13 +1,13 @@
---
title: Tune a Protection Profile
title: Tune a Policy
description:
Learn how to tune your protection profiles to better protect your application while enhancing
your users' experiences.
Learn how to tune your policies to better protect your application while enhancing your users'
experiences.
---
### Throttling Windows
The first of all settings a protection profile has are the throttling windows. Throttling windows
rate-limit challenge issuance.
The first of all settings a policy has are the throttling windows. Throttling windows rate-limit
challenge issuance.
![Screenshot](/images/screenshot-dashboard-throttling-windows.png)
+12 -12
View File
@@ -37,11 +37,11 @@ Duckity serves challenges through the duckling API. It's separate from the manag
a specialized backend. The hosted endpoint of such version is at `https://api.duckity.com/d1`.
Subsequent versions of this API will be named `d2`, `d3`, and so on.
To get a challenge, you need to be able to make HTTP requests and a protection profile ID. Requests
to get challenges look like follows:
To get a challenge, you need to be able to make HTTP requests and a policy ID. Requests to get
challenges look like follows:
```http
POST /d1/challenges/{protection_profile_id}/issue HTTP/1.1
POST /d1/challenges/{policy_id}/issue HTTP/1.1
Host: api.duckity.com
Accept: application/json
```
@@ -89,8 +89,8 @@ X-RateLimit-Penalty-Resets-In: 500
}
```
Other errors, like an invalid protection profile, will result in a response of similar body
structure and with the corresponding status code.
Other errors, like an invalid policy, will result in a response of similar body structure and with
the corresponding status code.
## Decoding the Challenge [step]
@@ -109,7 +109,7 @@ type Challenge = {
challenge_id: string; // The challenge's unique ID. 21-character NanoID using the default alphabet.
ip: string; // The IP of the client the challenge was issued for. Only this client may submit a solution for validation.
timestamp: number; // The milliseconds since UNIX epoch when the challenge was issued.
protection_profile_id: string; // The ID of the protection profile this challenge was issued for. 21-character NanoID using the default alphabet.
policy_id: string; // The ID of the policy this challenge was issued for. 21-character NanoID using the default alphabet.
n: number[]; // An array of 32-bit unsigned digits, most significant digit first. The Wesolowski VDF N parameter.
x: number[]; // An array of 32-bit unsigned digits, most significant digit first. The Wesolowski VDF X parameter.
t: number; // The Wesolowski VDF T parameter.
@@ -128,8 +128,8 @@ These code pieces implement the decoding as a reference.
ip: string;
// The unix timestamp, in milliseconds, in which the challenge was issued.
timestamp: number;
// The ID of the protection profile this challenge was issued for.
protection_profile_id: string;
// The ID of the policy this challenge was issued for.
policy_id: string;
// The unsigned 32-bit digits of the N Wesolowski VDF parameter, most significant digit first.
n: number[];
// The unsigned 32-bit digits of the X Wesolowski VDF parameter, most significant digit first.
@@ -172,8 +172,8 @@ These code pieces implement the decoding as a reference.
"""The IP of the client this challenge was issued for."""
timestamp: int
"""The UNIX timestamp in milliseconds at which this challenge was issued."""
protection_profile_id: str
"""The ID of the protection profile this challenge was issued for."""
policy_id: str
"""The ID of the policy this challenge was issued for."""
n: list[int]
"""The unsigned 32-bit digits of the N Wesolowski VDF parameter, most significant digit first."""
x: list[int]
@@ -210,7 +210,7 @@ These code pieces implement the decoding as a reference.
id=data["challenge_id"],
ip=data["ip"],
timestamp=data["timestamp"],
protection_profile_id=data["protection_profile_id"],
policy_id=data["policy_id"],
n=data["n"],
x=data["x"],
t=data["t"]
@@ -1078,7 +1078,7 @@ the Duckling API to check whether the token is valid.
The request looks like follows:
```http
POST /d1/{protection_profile_id}/validate HTTP/1.1
POST /d1/{policy_id}/validate HTTP/1.1
Host: api.duckity.com
Authorization: Bearer <application-id>
Accept: application/json
+37 -41
View File
@@ -24,21 +24,21 @@ now have your first application created.
origins. If your application is not a web app, you can leave the CORS origins empty.
</Callout>
## Create a Protection Profile [step]
## Create a Policy [step]
Applications commonly have multiple features that need to be protected. For example, you may have a
signup form and a login form with different protection needs. For each, you'll create one
**protection profile** with settings tuned to each feature's specific needs.
signup form and a login form with different protection needs. For each, you'll create one **policy**
with settings tuned to each feature's specific needs.
Each application needs at least one protection profile to work. To create your first one, press the
**+ Create Protection Profile** button.
Each application needs at least one policy to work. To create your first one, press the **+ Create
Policy** button.
Set the name to the name of the feature you'll be protecting, like "Sign-up Form" or "Add Friend".
This is for you to recognize it later, it won't be displayed to your users. Once you're done filling
it, press on **✓ Create Protection Profile**.
it, press on **✓ Create Policy**.
Copy your protection profile's ID using the button at the top right corner, that's all you'll need
to integrate it into your application.
Copy your policy's ID using the button at the top right corner, that's all you'll need to integrate
it into your application.
<Callout>
Don't worry about all the settings displayed for now, you'll learn to tune them later.
@@ -46,9 +46,9 @@ to integrate it into your application.
## Install a Client SDK [step]
To integrate your protection profile into your application, you'll need to install a client SDK in
your client and validate solution tokens from your server. This is very simple to do and will take
you little to no time.
To integrate your policy into your application, you'll need to install a client SDK in your client
and validate solution tokens from your server. This is very simple to do and will take you little to
no time.
<Tabs items={["JavaScript", "React", "Python", "Rust", "Other"]} groupId="sdk-language">
<Tab value="JavaScript">
@@ -91,7 +91,7 @@ you little to no time.
```ts
async function handleSubmit(e) {
e.preventDefault();
const solution: string = await duckity.solve(PROTECTION_PROFILE_ID);
const solution: string = await duckity.solve(POLICY_ID);
// Send it to your backend.
}
```
@@ -143,7 +143,7 @@ you little to no time.
import { useChallenge } from "@duckity/react";
function MyComponent() {
const duckity = useChallenge(process.env.NEXT_PUBLIC_DUCKITY_PROTECTION_PROFILE_ID);
const duckity = useChallenge(process.env.NEXT_PUBLIC_DUCKITY_POLICY_ID);
}
```
</Tab>
@@ -152,7 +152,7 @@ you little to no time.
import { useChallenge } from "@duckity/react";
function MyComponent() {
const duckity = useChallenge(import.meta.env.VITE_DUCKITY_PROTECTION_PROFILE_ID);
const duckity = useChallenge(import.meta.env.VITE_DUCKITY_POLICY_ID);
}
```
</Tab>
@@ -165,14 +165,14 @@ you little to no time.
export async function loader() {
return json({
ENV: {
DUCKITY_PROTECTION_PROFILE_ID: process.env.DUCKITY_PROTECTION_PROFILE_ID,
DUCKITY_POLICY_ID: process.env.DUCKITY_POLICY_ID,
},
});
}
function MyComponent() {
const data = useLoaderData<typeof loader>();
const duckity = useChallenge(data.ENV.DUCKITY_PROTECTION_PROFILE_ID);
const duckity = useChallenge(data.ENV.DUCKITY_POLICY_ID);
}
```
</Tab>
@@ -181,7 +181,7 @@ you little to no time.
import { useChallenge } from "@duckity/react";
function MyComponent() {
const duckity = useChallenge(process.env.GATSBY_DUCKITY_PROTECTION_PROFILE_ID);
const duckity = useChallenge(process.env.GATSBY_DUCKITY_POLICY_ID);
}
```
</Tab>
@@ -190,7 +190,7 @@ you little to no time.
import { useChallenge } from "@duckity/react";
function MyComponent() {
const duckity = useChallenge(process.env.EXPO_PUBLIC_DUCKITY_PROTECTION_PROFILE_ID);
const duckity = useChallenge(process.env.EXPO_PUBLIC_DUCKITY_POLICY_ID);
}
```
</Tab>
@@ -199,7 +199,7 @@ you little to no time.
import { useChallenge } from "@duckity/react";
function MyComponent() {
const duckity = useChallenge(import.meta.env.PUBLIC_DUCKITY_PROTECTION_PROFILE_ID);
const duckity = useChallenge(import.meta.env.PUBLIC_DUCKITY_POLICY_ID);
}
```
@@ -270,14 +270,14 @@ you little to no time.
</Tab>
</Tabs>
Solving a challenge only requires your protection profile ID.
Solving a challenge only requires your policy ID.
<Tabs items={["Async", "Sync"]} groupId="python-sync" persist>
<Tab value="Async">
```py
import duckity
solution: str = await duckity.solve(PROTECTION_PROFILE_ID)
solution: str = await duckity.solve(POLICY_ID)
```
The CPU-intensive part of solving the challenge is done in a
@@ -289,7 +289,7 @@ you little to no time.
import duckity
solution: str = asyncio.run(duckity.solve(PROTECTION_PROFILE_ID))
solution: str = asyncio.run(duckity.solve(POLICY_ID))
```
The CPU-intensive part of solving the challenge is done in a
@@ -303,7 +303,7 @@ you little to no time.
```py
import requests
solution: str = asyncio.run(duckity.solve(PROTECTION_PROFILE_ID))
solution: str = asyncio.run(duckity.solve(POLICY_ID))
requests.post(
"https://api.example.com/login",
@@ -338,7 +338,7 @@ you little to no time.
To get and solve a challenge, use `duckity::solve()` like follows:
```rs
let solution: str = duckity::solve(PROTECTION_PROFILE_ID).await?;
let solution: str = duckity::solve(POLICY_ID).await?;
```
That's it! Once you have your solution token, you can send it over to your backend for
@@ -410,7 +410,7 @@ Once you have a solution token in your server, validating it is quite easy.
solution, // The solution token submitted by the client.
clientIp, // The IP address of the client that submitted the solution.
applicationSecret, // Your application's secret. Get it from the dashboard.
protectionProfileId, // The protection profile ID used to generate the challenge.
policyId, // The policy ID used to generate the challenge.
);
```
@@ -449,10 +449,10 @@ Once you have a solution token in your server, validating it is quite easy.
solution: str # The solution token submitted by the client.
client_ip: str # The IP address of the client that submitted the solution.
application_secret: str # Your application's secret. Get it from the dashboard.
protection_profile_id: str # The protection profile ID used to generate the challenge.
policy_id: str # The policy ID used to generate the challenge.
is_valid: bool = await duckity.validate(
solution, client_ip, application_secret, protection_profile_id
solution, client_ip, application_secret, policy_id
)
```
</Tab>
@@ -465,10 +465,10 @@ Once you have a solution token in your server, validating it is quite easy.
solution: str # The solution token submitted by the client.
client_ip: str # The IP address of the client that submitted the solution.
application_secret: str # Your application's secret. Get it from the dashboard.
protection_profile_id: str # The protection profile ID used to generate the challenge.
policy_id: str # The policy ID used to generate the challenge.
is_valid: bool = asyncio.run(
duckity.validate(solution, client_ip, application_secret, protection_profile_id)
duckity.validate(solution, client_ip, application_secret, policy_id)
)
```
</Tab>
@@ -493,7 +493,7 @@ Once you have a solution token in your server, validating it is quite easy.
solution, // The solution token submitted by the client.
client_ip, // The IP address of the client that submitted the solution.
APPLICATION_SECRET, // Your application's secret. Get it from the dashboard.
PROTECTION_PROFILE_ID // The protection profile ID used to generate the challenge.
POLICY_ID // The policy ID used to generate the challenge.
)
.await?;
```
@@ -506,7 +506,7 @@ Once you have a solution token in your server, validating it is quite easy.
hand by making the HTTP request by hand instead.
```http
POST /d1/challenges/{protection_profile_id}/validate HTTP/1.1
POST /d1/challenges/{policy_id}/validate HTTP/1.1
Host: api.duckity.com
Accept: application/json
Content-Type: application/json
@@ -548,8 +548,8 @@ Once you have a solution token in your server, validating it is quite easy.
Content-Type: application/json
{
"title": "Protection Profile Not Found",
"message": "The protection profile ID you specified was not found."
"title": "Policy Not Found",
"message": "The policy ID you specified was not found."
}
```
</Tab>
@@ -594,7 +594,7 @@ Once you have a solution token in your server, validating it is quite easy.
Note that status codes are related to server actions, not to client actions. An invalid
solution token submitted by the client will return `200` because the token was validated
successfully (even if the result was that it was invalid), while a wrong application secret
or an incorrect protection profile ID will return `4xx` status codes.
or an incorrect policy ID will return `4xx` status codes.
</Tab>
</Tabs>
@@ -608,11 +608,7 @@ combine settings to produce a more powerful setup, check out the following guide
configuration by configuration to teach you how to configure the parameters you need to suit your
application's needs.
<Card
href="/guides/tune-a-protection-profile"
title="Tune a Protection Profile"
icon={<LiPencil />}
>
Learn how to tune your protection profiles to better protect your application while enhancing
your users' experiences.
<Card href="/guides/tune-a-policy" title="Tune a Policy" icon={<LiPencil />}>
Learn how to tune your policies to better protect your application while enhancing your users'
experiences.
</Card>
+9 -9
View File
@@ -23,8 +23,8 @@ Before you can integrate Duckity into your application, you'll need to have the
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
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](https://app.duckity.com) or
read the [Quick Start](/quick-start) guide to learn how to set those up.
@@ -78,7 +78,7 @@ Once you have the SDK installed, you can request a challenge whenever you need i
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);
let solution: string = await duckity.solve(POLICY_ID);
```
### Validate a Challenge [step]
@@ -86,18 +86,18 @@ let solution: string = await duckity.solve(PROTECTION_PROFILE_ID);
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.
Once in the server, you'll need the client's IP, their submitted solution token, the policy's ID,
and the application secret.
```ts
import * as duckity from "@duckity/js";
let applicationSecret: string;
let protectionProfileId: string;
let policyId: string;
let clientIp: string;
let solution: string;
let isValid = await duckity.validate(solution, clientIp, applicationSecret, protectionProfileId);
let isValid = await duckity.validate(solution, clientIp, applicationSecret, policyId);
if (isValid) {
// Keep processing the request.
@@ -144,7 +144,7 @@ wait.
<script type="module">
import * as duckity from "https://esm.sh/@duckity/js";
const PROTECTION_PROFILE_ID = "<your-protection-profile-id>";
const POLICY_ID = "<your-policy-id>";
const form = document.getElementById("form");
const submitButton = document.getElementById("submit-button");
@@ -153,7 +153,7 @@ wait.
// 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);
let solutionPromise = duckity.solve(POLICY_ID);
form.addEventListener("submit", async (e) => {
e.preventDefault();
+20 -20
View File
@@ -19,8 +19,8 @@ event loop's version of it.
Before you can integrate Duckity into your application, you'll need to have the following:
1. An application,
2. At least one protection profile created in that application, and
3. The ID of the protection profiles to use
2. At least one policy created in that application, and
3. The ID of the policies 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.
@@ -52,14 +52,14 @@ Install the SDK from PyPI using your favorite package manager:
### Solve a Challenge [step]
Solving a challenge only requires a protection profile ID.
Solving a challenge only requires a policy ID.
<Tabs items={["Async", "Sync"]} groupId="python-sync" persist>
<Tab value="Async" id="async">
```py
import duckity
solution: str = await duckity.solve(PROTECTION_PROFILE_ID)
solution: str = await duckity.solve(POLICY_ID)
```
The CPU-intensive part of solving the challenge is done in a `ProcessPoolExecutor()`.
@@ -71,7 +71,7 @@ Solving a challenge only requires a protection profile ID.
import duckity
solution: str = asyncio.run(duckity.solve(PROTECTION_PROFILE_ID))
solution: str = asyncio.run(duckity.solve(POLICY_ID))
```
The CPU-intensive part of solving the challenge is done in a `ProcessPoolExecutor()`. The
@@ -90,7 +90,7 @@ To validate a solution token, you'll need 4 things:
1. The solution token,
2. The IP of the client that submitted the solution,
3. The application's secret, and
4. The protection profile's ID.
4. The policy's ID.
Once you have them, you can validate a solution token as follows:
@@ -102,10 +102,10 @@ Once you have them, you can validate a solution token as follows:
solution: str
client_ip: str
application_secret: str
protection_profile_id: str
policy_id: str
is_valid: bool = await duckity.validate(
solution, client_ip, application_secret, protection_profile_id
solution, client_ip, application_secret, policy_id
)
```
</Tab>
@@ -118,10 +118,10 @@ Once you have them, you can validate a solution token as follows:
solution: str
client_ip: str
application_secret: str
protection_profile_id: str
policy_id: str
is_valid: bool = asyncio.run(
duckity.validate(solution, client_ip, application_secret, protection_profile_id)
duckity.validate(solution, client_ip, application_secret, policy_id)
)
```
</Tab>
@@ -154,7 +154,7 @@ import duckity
async def login():
solution_task = asyncio.create_task(duckity.solve(PROTECTION_PROFILE_ID))
solution_task = asyncio.create_task(duckity.solve(POLICY_ID))
email = await asyncio.to_thread(input, "Enter your email: ")
password = await asyncio.to_thread(getpass.getpass, "Enter your password (hidden): ")
@@ -191,7 +191,7 @@ from pydantic import BaseModel
dotenv.load_dotenv(override=True)
PROTECTION_PROFILE_ID = os.environ["DUCKITY_PROTECTION_PROFILE_ID"]
POLICY_ID = os.environ["DUCKITY_POLICY_ID"]
APPLICATION_SECRET = os.environ["DUCKITY_APPLICATION_SECRET"]
@@ -208,7 +208,7 @@ async def protected(request: Request, payload: RequestBodySchema):
payload.solution,
request.client.host, # Make sure to take into account X-Forwarded-For if behind a reverse proxy.
APPLICATION_SECRET,
PROTECTION_PROFILE_ID
POLICY_ID
)
if not is_valid:
@@ -240,7 +240,7 @@ dotenv.load_dotenv(override=True)
app = Flask(__name__)
PROTECTION_PROFILE_ID = os.environ["DUCKITY_PROTECTION_PROFILE_ID"]
POLICY_ID = os.environ["DUCKITY_POLICY_ID"]
APPLICATION_SECRET = os.environ["DUCKITY_APPLICATION_SECRET"]
@@ -257,7 +257,7 @@ async def protected():
solution,
client_ip,
APPLICATION_SECRET,
PROTECTION_PROFILE_ID,
POLICY_ID,
)
if not is_valid:
@@ -300,7 +300,7 @@ async def protected(request):
solution,
client_ip,
settings.DUCKITY_APPLICATION_SECRET,
settings.DUCKITY_PROTECTION_PROFILE_ID,
settings.DUCKITY_POLICY_ID,
)
if not is_valid:
@@ -339,7 +339,7 @@ async def protected(request, payload: RequestBodySchema):
payload.solution,
client_ip,
settings.DUCKITY_APPLICATION_SECRET,
settings.DUCKITY_PROTECTION_PROFILE_ID,
settings.DUCKITY_POLICY_ID,
)
if not is_valid:
@@ -378,7 +378,7 @@ class ProtectedView(APIView):
serializer.validated_data["solution"],
client_ip,
settings.DUCKITY_APPLICATION_SECRET,
settings.DUCKITY_PROTECTION_PROFILE_ID,
settings.DUCKITY_POLICY_ID,
)
if not is_valid:
@@ -405,7 +405,7 @@ import strawberry
dotenv.load_dotenv(override=True)
PROTECTION_PROFILE_ID = os.environ["DUCKITY_PROTECTION_PROFILE_ID"]
POLICY_ID = os.environ["DUCKITY_POLICY_ID"]
APPLICATION_SECRET = os.environ["DUCKITY_APPLICATION_SECRET"]
@@ -430,7 +430,7 @@ class Mutation:
solution,
client_ip,
DUCKITY_APPLICATION_SECRET,
DUCKITY_PROTECTION_PROFILE_ID,
DUCKITY_POLICY_ID,
)
if not is_valid:
+9 -9
View File
@@ -21,8 +21,8 @@ Before you can integrate Duckity into your application, you'll need to have the
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
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](https://app.duckity.com) or
read the [Quick Start](/quick-start) guide to learn how to set those up.
@@ -55,7 +55,7 @@ Use the hook as follows:
import { useChallenge } from "@duckity/react";
function MyComponent() {
const duckity = useChallenge(process.env.NEXT_PUBLIC_DUCKITY_PROTECTION_PROFILE_ID);
const duckity = useChallenge(process.env.NEXT_PUBLIC_DUCKITY_POLICY_ID);
}
```
</Tab>
@@ -64,7 +64,7 @@ Use the hook as follows:
import { useChallenge } from "@duckity/react";
function MyComponent() {
const duckity = useChallenge(import.meta.env.VITE_DUCKITY_PROTECTION_PROFILE_ID);
const duckity = useChallenge(import.meta.env.VITE_DUCKITY_POLICY_ID);
}
```
</Tab>
@@ -77,14 +77,14 @@ Use the hook as follows:
export async function loader() {
return json({
ENV: {
DUCKITY_PROTECTION_PROFILE_ID: process.env.DUCKITY_PROTECTION_PROFILE_ID,
DUCKITY_POLICY_ID: process.env.DUCKITY_POLICY_ID,
},
});
}
function MyComponent() {
const data = useLoaderData<typeof loader>();
const duckity = useChallenge(data.ENV.DUCKITY_PROTECTION_PROFILE_ID);
const duckity = useChallenge(data.ENV.DUCKITY_POLICY_ID);
}
```
</Tab>
@@ -93,7 +93,7 @@ Use the hook as follows:
import { useChallenge } from "@duckity/react";
function MyComponent() {
const duckity = useChallenge(process.env.GATSBY_DUCKITY_PROTECTION_PROFILE_ID);
const duckity = useChallenge(process.env.GATSBY_DUCKITY_POLICY_ID);
}
```
</Tab>
@@ -102,7 +102,7 @@ Use the hook as follows:
import { useChallenge } from "@duckity/react";
function MyComponent() {
const duckity = useChallenge(process.env.EXPO_PUBLIC_DUCKITY_PROTECTION_PROFILE_ID);
const duckity = useChallenge(process.env.EXPO_PUBLIC_DUCKITY_POLICY_ID);
}
```
</Tab>
@@ -111,7 +111,7 @@ Use the hook as follows:
import { useChallenge } from "@duckity/react";
function MyComponent() {
const duckity = useChallenge(import.meta.env.PUBLIC_DUCKITY_PROTECTION_PROFILE_ID);
const duckity = useChallenge(import.meta.env.PUBLIC_DUCKITY_POLICY_ID);
}
```
+15 -15
View File
@@ -19,8 +19,8 @@ in case you want to use the `core` module later on.
Before you can integrate Duckity into your application, you'll need to have the following:
1. An application,
2. At least one protection profile created in that application, and
3. The ID of the protection profiles to use
2. At least one policy created in that application, and
3. The ID of the policies 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.
@@ -40,7 +40,7 @@ cargo add duckity
To get and solve a challenge, use `duckity::solve()` like follows:
```rs
let solution: str = duckity::solve(PROTECTION_PROFILE_ID).await?;
let solution: str = duckity::solve(POLICY_ID).await?;
```
That's it! Once you have your solution token, you can send it over to your backend for validation.
@@ -60,7 +60,7 @@ To validate a solution token, you'll need 4 things:
1. The solution token,
2. The IP of the client that submitted the solution,
3. The application's secret, and
4. The protection profile's ID.
4. The policy's ID.
Once you have them, you can validate a solution token as follows:
@@ -69,7 +69,7 @@ let is_valid: bool = duckity::validate(
solution,
client_ip,
APPLICATION_SECRET,
PROTECTION_PROFILE_ID
POLICY_ID
)
.await?;
```
@@ -95,7 +95,7 @@ challenge while the user is filling up their username and password. For example:
```rs
use std::io::{self, Write};
const PROTECTION_PROFILE_ID: &str = "<your-own-protection-profile-id>";
const POLICY_ID: &str = "<your-own-policy-id>";
struct Credentials {
email: String,
@@ -104,7 +104,7 @@ struct Credentials {
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let solution_task = tokio::spawn(duckity::solve(PROTECTION_PROFILE_ID).into_future());
let solution_task = tokio::spawn(duckity::solve(POLICY_ID).into_future());
let credentials = tokio::task::spawn_blocking(|| {
let mut email = String::new();
@@ -169,11 +169,11 @@ simple. For example, the following snippet shows how to solve and validate a cha
```rs
use async_compat::CompatExt;
const PROTECTION_PROFILE_ID: &str = "<insert-your-protection-profile-here>";
const POLICY_ID: &str = "<insert-your-policy-here>";
fn main() -> anyhow::Result<()> {
smol::block_on(async {
let solution = duckity::solve(PROTECTION_PROFILE_ID).into_future().compat().await?;
let solution = duckity::solve(POLICY_ID).into_future().compat().await?;
Ok(())
})
@@ -199,7 +199,7 @@ use tokio::net::TcpListener;
// In an actual application, make these two configurable. `clap` is a good tool for that.
const APPLICATION_SECRET: &str = "<your-application-secret>";
const PROTECTION_PROFILE_ID: &str = "<your-protection-profile-id>";
const POLICY_ID: &str = "<your-policy-id>";
#[tokio::main]
async fn main() {
@@ -229,7 +229,7 @@ async fn handler(
payload.solution,
addr.ip(),
APPLICATION_SECRET,
PROTECTION_PROFILE_ID,
POLICY_ID,
)
.await
.unwrap();
@@ -256,7 +256,7 @@ use warp::{Filter, Reply};
// In an actual application, make these two configurable. `clap` is a good tool for that.
const APPLICATION_SECRET: &str = "<your-application-secret>";
const PROTECTION_PROFILE_ID: &str = "<your-protection-profile-id>";
const POLICY_ID: &str = "<your-policy-id>";
#[tokio::main]
async fn main() {
@@ -287,7 +287,7 @@ async fn handler(
payload.solution,
addr.ip(),
APPLICATION_SECRET,
PROTECTION_PROFILE_ID,
POLICY_ID,
)
.await
.unwrap();
@@ -317,7 +317,7 @@ use serde::Deserialize;
// In an actual application, make these two configurable. `clap` is a good tool for that.
const APPLICATION_SECRET: &str = "<your-application-secret>";
const PROTECTION_PROFILE_ID: &str = "<your-protection-profile-id>";
const POLICY_ID: &str = "<your-policy-id>";
#[actix_web::main]
async fn main() -> std::io::Result<()> {
@@ -342,7 +342,7 @@ async fn protected(req: HttpRequest, payload: Json<ProtectedRequestPayload>) ->
payload.solution.clone(),
addr.ip(),
APPLICATION_SECRET,
PROTECTION_PROFILE_ID,
POLICY_ID,
)
.await
.unwrap();