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
+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();