Update docs
This commit is contained in:
@@ -1,13 +1,13 @@
|
|||||||
---
|
---
|
||||||
title: Tune a Protection Profile
|
title: Tune a Policy
|
||||||
description:
|
description:
|
||||||
Learn how to tune your protection profiles to better protect your application while enhancing
|
Learn how to tune your policies to better protect your application while enhancing your users'
|
||||||
your users' experiences.
|
experiences.
|
||||||
---
|
---
|
||||||
|
|
||||||
### Throttling Windows
|
### Throttling Windows
|
||||||
|
|
||||||
The first of all settings a protection profile has are the throttling windows. Throttling windows
|
The first of all settings a policy has are the throttling windows. Throttling windows rate-limit
|
||||||
rate-limit challenge issuance.
|
challenge issuance.
|
||||||
|
|
||||||

|

|
||||||
|
|||||||
@@ -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`.
|
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.
|
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 a challenge, you need to be able to make HTTP requests and a policy ID. Requests to get
|
||||||
to get challenges look like follows:
|
challenges look like follows:
|
||||||
|
|
||||||
```http
|
```http
|
||||||
POST /d1/challenges/{protection_profile_id}/issue HTTP/1.1
|
POST /d1/challenges/{policy_id}/issue HTTP/1.1
|
||||||
Host: api.duckity.com
|
Host: api.duckity.com
|
||||||
Accept: application/json
|
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
|
Other errors, like an invalid policy, will result in a response of similar body structure and with
|
||||||
structure and with the corresponding status code.
|
the corresponding status code.
|
||||||
|
|
||||||
## Decoding the Challenge [step]
|
## 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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
t: number; // The Wesolowski VDF T parameter.
|
||||||
@@ -128,8 +128,8 @@ These code pieces implement the decoding as a reference.
|
|||||||
ip: string;
|
ip: string;
|
||||||
// The unix timestamp, in milliseconds, in which the challenge was issued.
|
// The unix timestamp, in milliseconds, in which the challenge was issued.
|
||||||
timestamp: number;
|
timestamp: number;
|
||||||
// The ID of the protection profile this challenge was issued for.
|
// The ID of the policy this challenge was issued for.
|
||||||
protection_profile_id: string;
|
policy_id: string;
|
||||||
// The unsigned 32-bit digits of the N Wesolowski VDF parameter, most significant digit first.
|
// The unsigned 32-bit digits of the N Wesolowski VDF parameter, most significant digit first.
|
||||||
n: number[];
|
n: number[];
|
||||||
// The unsigned 32-bit digits of the X Wesolowski VDF parameter, most significant digit first.
|
// 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."""
|
"""The IP of the client this challenge was issued for."""
|
||||||
timestamp: int
|
timestamp: int
|
||||||
"""The UNIX timestamp in milliseconds at which this challenge was issued."""
|
"""The UNIX timestamp in milliseconds at which this challenge was issued."""
|
||||||
protection_profile_id: str
|
policy_id: str
|
||||||
"""The ID of the protection profile this challenge was issued for."""
|
"""The ID of the policy this challenge was issued for."""
|
||||||
n: list[int]
|
n: list[int]
|
||||||
"""The unsigned 32-bit digits of the N Wesolowski VDF parameter, most significant digit first."""
|
"""The unsigned 32-bit digits of the N Wesolowski VDF parameter, most significant digit first."""
|
||||||
x: list[int]
|
x: list[int]
|
||||||
@@ -210,7 +210,7 @@ These code pieces implement the decoding as a reference.
|
|||||||
id=data["challenge_id"],
|
id=data["challenge_id"],
|
||||||
ip=data["ip"],
|
ip=data["ip"],
|
||||||
timestamp=data["timestamp"],
|
timestamp=data["timestamp"],
|
||||||
protection_profile_id=data["protection_profile_id"],
|
policy_id=data["policy_id"],
|
||||||
n=data["n"],
|
n=data["n"],
|
||||||
x=data["x"],
|
x=data["x"],
|
||||||
t=data["t"]
|
t=data["t"]
|
||||||
@@ -1078,7 +1078,7 @@ the Duckling API to check whether the token is valid.
|
|||||||
The request looks like follows:
|
The request looks like follows:
|
||||||
|
|
||||||
```http
|
```http
|
||||||
POST /d1/{protection_profile_id}/validate HTTP/1.1
|
POST /d1/{policy_id}/validate HTTP/1.1
|
||||||
Host: api.duckity.com
|
Host: api.duckity.com
|
||||||
Authorization: Bearer <application-id>
|
Authorization: Bearer <application-id>
|
||||||
Accept: application/json
|
Accept: application/json
|
||||||
|
|||||||
+37
-41
@@ -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.
|
origins. If your application is not a web app, you can leave the CORS origins empty.
|
||||||
</Callout>
|
</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
|
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
|
signup form and a login form with different protection needs. For each, you'll create one **policy**
|
||||||
**protection profile** with settings tuned to each feature's specific needs.
|
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
|
Each application needs at least one policy to work. To create your first one, press the **+ Create
|
||||||
**+ Create Protection Profile** button.
|
Policy** button.
|
||||||
|
|
||||||
Set the name to the name of the feature you'll be protecting, like "Sign-up Form" or "Add Friend".
|
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
|
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
|
Copy your policy's ID using the button at the top right corner, that's all you'll need to integrate
|
||||||
to integrate it into your application.
|
it into your application.
|
||||||
|
|
||||||
<Callout>
|
<Callout>
|
||||||
Don't worry about all the settings displayed for now, you'll learn to tune them later.
|
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]
|
## Install a Client SDK [step]
|
||||||
|
|
||||||
To integrate your protection profile into your application, you'll need to install a client SDK in
|
To integrate your policy into your application, you'll need to install a client SDK in your client
|
||||||
your client and validate solution tokens from your server. This is very simple to do and will take
|
and validate solution tokens from your server. This is very simple to do and will take you little to
|
||||||
you little to no time.
|
no time.
|
||||||
|
|
||||||
<Tabs items={["JavaScript", "React", "Python", "Rust", "Other"]} groupId="sdk-language">
|
<Tabs items={["JavaScript", "React", "Python", "Rust", "Other"]} groupId="sdk-language">
|
||||||
<Tab value="JavaScript">
|
<Tab value="JavaScript">
|
||||||
@@ -91,7 +91,7 @@ you little to no time.
|
|||||||
```ts
|
```ts
|
||||||
async function handleSubmit(e) {
|
async function handleSubmit(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const solution: string = await duckity.solve(PROTECTION_PROFILE_ID);
|
const solution: string = await duckity.solve(POLICY_ID);
|
||||||
// Send it to your backend.
|
// Send it to your backend.
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -143,7 +143,7 @@ you little to no time.
|
|||||||
import { useChallenge } from "@duckity/react";
|
import { useChallenge } from "@duckity/react";
|
||||||
|
|
||||||
function MyComponent() {
|
function MyComponent() {
|
||||||
const duckity = useChallenge(process.env.NEXT_PUBLIC_DUCKITY_PROTECTION_PROFILE_ID);
|
const duckity = useChallenge(process.env.NEXT_PUBLIC_DUCKITY_POLICY_ID);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
</Tab>
|
</Tab>
|
||||||
@@ -152,7 +152,7 @@ you little to no time.
|
|||||||
import { useChallenge } from "@duckity/react";
|
import { useChallenge } from "@duckity/react";
|
||||||
|
|
||||||
function MyComponent() {
|
function MyComponent() {
|
||||||
const duckity = useChallenge(import.meta.env.VITE_DUCKITY_PROTECTION_PROFILE_ID);
|
const duckity = useChallenge(import.meta.env.VITE_DUCKITY_POLICY_ID);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
</Tab>
|
</Tab>
|
||||||
@@ -165,14 +165,14 @@ you little to no time.
|
|||||||
export async function loader() {
|
export async function loader() {
|
||||||
return json({
|
return json({
|
||||||
ENV: {
|
ENV: {
|
||||||
DUCKITY_PROTECTION_PROFILE_ID: process.env.DUCKITY_PROTECTION_PROFILE_ID,
|
DUCKITY_POLICY_ID: process.env.DUCKITY_POLICY_ID,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function MyComponent() {
|
function MyComponent() {
|
||||||
const data = useLoaderData<typeof loader>();
|
const data = useLoaderData<typeof loader>();
|
||||||
const duckity = useChallenge(data.ENV.DUCKITY_PROTECTION_PROFILE_ID);
|
const duckity = useChallenge(data.ENV.DUCKITY_POLICY_ID);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
</Tab>
|
</Tab>
|
||||||
@@ -181,7 +181,7 @@ you little to no time.
|
|||||||
import { useChallenge } from "@duckity/react";
|
import { useChallenge } from "@duckity/react";
|
||||||
|
|
||||||
function MyComponent() {
|
function MyComponent() {
|
||||||
const duckity = useChallenge(process.env.GATSBY_DUCKITY_PROTECTION_PROFILE_ID);
|
const duckity = useChallenge(process.env.GATSBY_DUCKITY_POLICY_ID);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
</Tab>
|
</Tab>
|
||||||
@@ -190,7 +190,7 @@ you little to no time.
|
|||||||
import { useChallenge } from "@duckity/react";
|
import { useChallenge } from "@duckity/react";
|
||||||
|
|
||||||
function MyComponent() {
|
function MyComponent() {
|
||||||
const duckity = useChallenge(process.env.EXPO_PUBLIC_DUCKITY_PROTECTION_PROFILE_ID);
|
const duckity = useChallenge(process.env.EXPO_PUBLIC_DUCKITY_POLICY_ID);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
</Tab>
|
</Tab>
|
||||||
@@ -199,7 +199,7 @@ you little to no time.
|
|||||||
import { useChallenge } from "@duckity/react";
|
import { useChallenge } from "@duckity/react";
|
||||||
|
|
||||||
function MyComponent() {
|
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>
|
</Tab>
|
||||||
</Tabs>
|
</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>
|
<Tabs items={["Async", "Sync"]} groupId="python-sync" persist>
|
||||||
<Tab value="Async">
|
<Tab value="Async">
|
||||||
```py
|
```py
|
||||||
import duckity
|
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
|
The CPU-intensive part of solving the challenge is done in a
|
||||||
@@ -289,7 +289,7 @@ you little to no time.
|
|||||||
|
|
||||||
import duckity
|
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
|
The CPU-intensive part of solving the challenge is done in a
|
||||||
@@ -303,7 +303,7 @@ you little to no time.
|
|||||||
```py
|
```py
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
solution: str = asyncio.run(duckity.solve(PROTECTION_PROFILE_ID))
|
solution: str = asyncio.run(duckity.solve(POLICY_ID))
|
||||||
|
|
||||||
requests.post(
|
requests.post(
|
||||||
"https://api.example.com/login",
|
"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:
|
To get and solve a challenge, use `duckity::solve()` like follows:
|
||||||
|
|
||||||
```rs
|
```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
|
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.
|
solution, // The solution token submitted by the client.
|
||||||
clientIp, // The IP address of the client that submitted the solution.
|
clientIp, // The IP address of the client that submitted the solution.
|
||||||
applicationSecret, // Your application's secret. Get it from the dashboard.
|
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.
|
solution: str # The solution token submitted by the client.
|
||||||
client_ip: str # The IP address of the client that submitted the solution.
|
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.
|
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(
|
is_valid: bool = await duckity.validate(
|
||||||
solution, client_ip, application_secret, protection_profile_id
|
solution, client_ip, application_secret, policy_id
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
</Tab>
|
</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.
|
solution: str # The solution token submitted by the client.
|
||||||
client_ip: str # The IP address of the client that submitted the solution.
|
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.
|
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(
|
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>
|
</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.
|
solution, // The solution token submitted by the client.
|
||||||
client_ip, // The IP address of the client that submitted the solution.
|
client_ip, // The IP address of the client that submitted the solution.
|
||||||
APPLICATION_SECRET, // Your application's secret. Get it from the dashboard.
|
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?;
|
.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.
|
hand by making the HTTP request by hand instead.
|
||||||
|
|
||||||
```http
|
```http
|
||||||
POST /d1/challenges/{protection_profile_id}/validate HTTP/1.1
|
POST /d1/challenges/{policy_id}/validate HTTP/1.1
|
||||||
Host: api.duckity.com
|
Host: api.duckity.com
|
||||||
Accept: application/json
|
Accept: application/json
|
||||||
Content-Type: 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
|
Content-Type: application/json
|
||||||
|
|
||||||
{
|
{
|
||||||
"title": "Protection Profile Not Found",
|
"title": "Policy Not Found",
|
||||||
"message": "The protection profile ID you specified was not found."
|
"message": "The policy ID you specified was not found."
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
</Tab>
|
</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
|
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
|
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
|
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>
|
</Tab>
|
||||||
|
|
||||||
</Tabs>
|
</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
|
configuration by configuration to teach you how to configure the parameters you need to suit your
|
||||||
application's needs.
|
application's needs.
|
||||||
|
|
||||||
<Card
|
<Card href="/guides/tune-a-policy" title="Tune a Policy" icon={<LiPencil />}>
|
||||||
href="/guides/tune-a-protection-profile"
|
Learn how to tune your policies to better protect your application while enhancing your users'
|
||||||
title="Tune a Protection Profile"
|
experiences.
|
||||||
icon={<LiPencil />}
|
|
||||||
>
|
|
||||||
Learn how to tune your protection profiles to better protect your application while enhancing
|
|
||||||
your users' experiences.
|
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ Before you can integrate Duckity into your application, you'll need to have the
|
|||||||
|
|
||||||
1. An application,
|
1. An application,
|
||||||
2. CORS origins set up pointing to your application's origin(s),
|
2. CORS origins set up pointing to your application's origin(s),
|
||||||
3. At least one protection profile created in that application, and
|
3. At least one policy created in that application, and
|
||||||
4. The ID of the protection profiles to use
|
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
|
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.
|
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";
|
import duckity from "@duckity/js";
|
||||||
|
|
||||||
/// Slow! Runs in a web worker, yet don't let it block code below unless necessary.
|
/// 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]
|
### 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
|
Send the solution token to your backend server any way you want. A header or parameter in a JSON
|
||||||
field will work.
|
field will work.
|
||||||
|
|
||||||
Once in the server, you'll need the client's IP, their submitted solution token, the protection
|
Once in the server, you'll need the client's IP, their submitted solution token, the policy's ID,
|
||||||
profile's ID, and the application secret.
|
and the application secret.
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import * as duckity from "@duckity/js";
|
import * as duckity from "@duckity/js";
|
||||||
|
|
||||||
let applicationSecret: string;
|
let applicationSecret: string;
|
||||||
let protectionProfileId: string;
|
let policyId: string;
|
||||||
let clientIp: string;
|
let clientIp: string;
|
||||||
let solution: string;
|
let solution: string;
|
||||||
|
|
||||||
let isValid = await duckity.validate(solution, clientIp, applicationSecret, protectionProfileId);
|
let isValid = await duckity.validate(solution, clientIp, applicationSecret, policyId);
|
||||||
|
|
||||||
if (isValid) {
|
if (isValid) {
|
||||||
// Keep processing the request.
|
// Keep processing the request.
|
||||||
@@ -144,7 +144,7 @@ wait.
|
|||||||
<script type="module">
|
<script type="module">
|
||||||
import * as duckity from "https://esm.sh/@duckity/js";
|
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 form = document.getElementById("form");
|
||||||
const submitButton = document.getElementById("submit-button");
|
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
|
// 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
|
// in. Do not `await` it here, it will prevent the `form.addEventListener()` call from
|
||||||
// running until the challenge is solved, which takes some time.
|
// 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) => {
|
form.addEventListener("submit", async (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|||||||
+20
-20
@@ -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:
|
Before you can integrate Duckity into your application, you'll need to have the following:
|
||||||
|
|
||||||
1. An application,
|
1. An application,
|
||||||
2. At least one protection profile created in that application, and
|
2. At least one policy created in that application, and
|
||||||
3. The ID of the protection profiles to use
|
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
|
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.
|
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]
|
### 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>
|
<Tabs items={["Async", "Sync"]} groupId="python-sync" persist>
|
||||||
<Tab value="Async" id="async">
|
<Tab value="Async" id="async">
|
||||||
```py
|
```py
|
||||||
import duckity
|
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()`.
|
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
|
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
|
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,
|
1. The solution token,
|
||||||
2. The IP of the client that submitted the solution,
|
2. The IP of the client that submitted the solution,
|
||||||
3. The application's secret, and
|
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:
|
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
|
solution: str
|
||||||
client_ip: str
|
client_ip: str
|
||||||
application_secret: str
|
application_secret: str
|
||||||
protection_profile_id: str
|
policy_id: str
|
||||||
|
|
||||||
is_valid: bool = await duckity.validate(
|
is_valid: bool = await duckity.validate(
|
||||||
solution, client_ip, application_secret, protection_profile_id
|
solution, client_ip, application_secret, policy_id
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
</Tab>
|
</Tab>
|
||||||
@@ -118,10 +118,10 @@ Once you have them, you can validate a solution token as follows:
|
|||||||
solution: str
|
solution: str
|
||||||
client_ip: str
|
client_ip: str
|
||||||
application_secret: str
|
application_secret: str
|
||||||
protection_profile_id: str
|
policy_id: str
|
||||||
|
|
||||||
is_valid: bool = asyncio.run(
|
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>
|
</Tab>
|
||||||
@@ -154,7 +154,7 @@ import duckity
|
|||||||
|
|
||||||
|
|
||||||
async def login():
|
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: ")
|
email = await asyncio.to_thread(input, "Enter your email: ")
|
||||||
password = await asyncio.to_thread(getpass.getpass, "Enter your password (hidden): ")
|
password = await asyncio.to_thread(getpass.getpass, "Enter your password (hidden): ")
|
||||||
@@ -191,7 +191,7 @@ from pydantic import BaseModel
|
|||||||
dotenv.load_dotenv(override=True)
|
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"]
|
APPLICATION_SECRET = os.environ["DUCKITY_APPLICATION_SECRET"]
|
||||||
|
|
||||||
|
|
||||||
@@ -208,7 +208,7 @@ async def protected(request: Request, payload: RequestBodySchema):
|
|||||||
payload.solution,
|
payload.solution,
|
||||||
request.client.host, # Make sure to take into account X-Forwarded-For if behind a reverse proxy.
|
request.client.host, # Make sure to take into account X-Forwarded-For if behind a reverse proxy.
|
||||||
APPLICATION_SECRET,
|
APPLICATION_SECRET,
|
||||||
PROTECTION_PROFILE_ID
|
POLICY_ID
|
||||||
)
|
)
|
||||||
|
|
||||||
if not is_valid:
|
if not is_valid:
|
||||||
@@ -240,7 +240,7 @@ dotenv.load_dotenv(override=True)
|
|||||||
app = Flask(__name__)
|
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"]
|
APPLICATION_SECRET = os.environ["DUCKITY_APPLICATION_SECRET"]
|
||||||
|
|
||||||
|
|
||||||
@@ -257,7 +257,7 @@ async def protected():
|
|||||||
solution,
|
solution,
|
||||||
client_ip,
|
client_ip,
|
||||||
APPLICATION_SECRET,
|
APPLICATION_SECRET,
|
||||||
PROTECTION_PROFILE_ID,
|
POLICY_ID,
|
||||||
)
|
)
|
||||||
|
|
||||||
if not is_valid:
|
if not is_valid:
|
||||||
@@ -300,7 +300,7 @@ async def protected(request):
|
|||||||
solution,
|
solution,
|
||||||
client_ip,
|
client_ip,
|
||||||
settings.DUCKITY_APPLICATION_SECRET,
|
settings.DUCKITY_APPLICATION_SECRET,
|
||||||
settings.DUCKITY_PROTECTION_PROFILE_ID,
|
settings.DUCKITY_POLICY_ID,
|
||||||
)
|
)
|
||||||
|
|
||||||
if not is_valid:
|
if not is_valid:
|
||||||
@@ -339,7 +339,7 @@ async def protected(request, payload: RequestBodySchema):
|
|||||||
payload.solution,
|
payload.solution,
|
||||||
client_ip,
|
client_ip,
|
||||||
settings.DUCKITY_APPLICATION_SECRET,
|
settings.DUCKITY_APPLICATION_SECRET,
|
||||||
settings.DUCKITY_PROTECTION_PROFILE_ID,
|
settings.DUCKITY_POLICY_ID,
|
||||||
)
|
)
|
||||||
|
|
||||||
if not is_valid:
|
if not is_valid:
|
||||||
@@ -378,7 +378,7 @@ class ProtectedView(APIView):
|
|||||||
serializer.validated_data["solution"],
|
serializer.validated_data["solution"],
|
||||||
client_ip,
|
client_ip,
|
||||||
settings.DUCKITY_APPLICATION_SECRET,
|
settings.DUCKITY_APPLICATION_SECRET,
|
||||||
settings.DUCKITY_PROTECTION_PROFILE_ID,
|
settings.DUCKITY_POLICY_ID,
|
||||||
)
|
)
|
||||||
|
|
||||||
if not is_valid:
|
if not is_valid:
|
||||||
@@ -405,7 +405,7 @@ import strawberry
|
|||||||
dotenv.load_dotenv(override=True)
|
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"]
|
APPLICATION_SECRET = os.environ["DUCKITY_APPLICATION_SECRET"]
|
||||||
|
|
||||||
|
|
||||||
@@ -430,7 +430,7 @@ class Mutation:
|
|||||||
solution,
|
solution,
|
||||||
client_ip,
|
client_ip,
|
||||||
DUCKITY_APPLICATION_SECRET,
|
DUCKITY_APPLICATION_SECRET,
|
||||||
DUCKITY_PROTECTION_PROFILE_ID,
|
DUCKITY_POLICY_ID,
|
||||||
)
|
)
|
||||||
|
|
||||||
if not is_valid:
|
if not is_valid:
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ Before you can integrate Duckity into your application, you'll need to have the
|
|||||||
|
|
||||||
1. An application,
|
1. An application,
|
||||||
2. CORS origins set up pointing to your application's origin(s),
|
2. CORS origins set up pointing to your application's origin(s),
|
||||||
3. At least one protection profile created in that application, and
|
3. At least one policy created in that application, and
|
||||||
4. The ID of the protection profiles to use
|
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
|
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.
|
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";
|
import { useChallenge } from "@duckity/react";
|
||||||
|
|
||||||
function MyComponent() {
|
function MyComponent() {
|
||||||
const duckity = useChallenge(process.env.NEXT_PUBLIC_DUCKITY_PROTECTION_PROFILE_ID);
|
const duckity = useChallenge(process.env.NEXT_PUBLIC_DUCKITY_POLICY_ID);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
</Tab>
|
</Tab>
|
||||||
@@ -64,7 +64,7 @@ Use the hook as follows:
|
|||||||
import { useChallenge } from "@duckity/react";
|
import { useChallenge } from "@duckity/react";
|
||||||
|
|
||||||
function MyComponent() {
|
function MyComponent() {
|
||||||
const duckity = useChallenge(import.meta.env.VITE_DUCKITY_PROTECTION_PROFILE_ID);
|
const duckity = useChallenge(import.meta.env.VITE_DUCKITY_POLICY_ID);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
</Tab>
|
</Tab>
|
||||||
@@ -77,14 +77,14 @@ Use the hook as follows:
|
|||||||
export async function loader() {
|
export async function loader() {
|
||||||
return json({
|
return json({
|
||||||
ENV: {
|
ENV: {
|
||||||
DUCKITY_PROTECTION_PROFILE_ID: process.env.DUCKITY_PROTECTION_PROFILE_ID,
|
DUCKITY_POLICY_ID: process.env.DUCKITY_POLICY_ID,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function MyComponent() {
|
function MyComponent() {
|
||||||
const data = useLoaderData<typeof loader>();
|
const data = useLoaderData<typeof loader>();
|
||||||
const duckity = useChallenge(data.ENV.DUCKITY_PROTECTION_PROFILE_ID);
|
const duckity = useChallenge(data.ENV.DUCKITY_POLICY_ID);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
</Tab>
|
</Tab>
|
||||||
@@ -93,7 +93,7 @@ Use the hook as follows:
|
|||||||
import { useChallenge } from "@duckity/react";
|
import { useChallenge } from "@duckity/react";
|
||||||
|
|
||||||
function MyComponent() {
|
function MyComponent() {
|
||||||
const duckity = useChallenge(process.env.GATSBY_DUCKITY_PROTECTION_PROFILE_ID);
|
const duckity = useChallenge(process.env.GATSBY_DUCKITY_POLICY_ID);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
</Tab>
|
</Tab>
|
||||||
@@ -102,7 +102,7 @@ Use the hook as follows:
|
|||||||
import { useChallenge } from "@duckity/react";
|
import { useChallenge } from "@duckity/react";
|
||||||
|
|
||||||
function MyComponent() {
|
function MyComponent() {
|
||||||
const duckity = useChallenge(process.env.EXPO_PUBLIC_DUCKITY_PROTECTION_PROFILE_ID);
|
const duckity = useChallenge(process.env.EXPO_PUBLIC_DUCKITY_POLICY_ID);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
</Tab>
|
</Tab>
|
||||||
@@ -111,7 +111,7 @@ Use the hook as follows:
|
|||||||
import { useChallenge } from "@duckity/react";
|
import { useChallenge } from "@duckity/react";
|
||||||
|
|
||||||
function MyComponent() {
|
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
@@ -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:
|
Before you can integrate Duckity into your application, you'll need to have the following:
|
||||||
|
|
||||||
1. An application,
|
1. An application,
|
||||||
2. At least one protection profile created in that application, and
|
2. At least one policy created in that application, and
|
||||||
3. The ID of the protection profiles to use
|
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
|
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.
|
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:
|
To get and solve a challenge, use `duckity::solve()` like follows:
|
||||||
|
|
||||||
```rs
|
```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.
|
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,
|
1. The solution token,
|
||||||
2. The IP of the client that submitted the solution,
|
2. The IP of the client that submitted the solution,
|
||||||
3. The application's secret, and
|
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:
|
Once you have them, you can validate a solution token as follows:
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@ let is_valid: bool = duckity::validate(
|
|||||||
solution,
|
solution,
|
||||||
client_ip,
|
client_ip,
|
||||||
APPLICATION_SECRET,
|
APPLICATION_SECRET,
|
||||||
PROTECTION_PROFILE_ID
|
POLICY_ID
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
```
|
```
|
||||||
@@ -95,7 +95,7 @@ challenge while the user is filling up their username and password. For example:
|
|||||||
```rs
|
```rs
|
||||||
use std::io::{self, Write};
|
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 {
|
struct Credentials {
|
||||||
email: String,
|
email: String,
|
||||||
@@ -104,7 +104,7 @@ struct Credentials {
|
|||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> anyhow::Result<()> {
|
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 credentials = tokio::task::spawn_blocking(|| {
|
||||||
let mut email = String::new();
|
let mut email = String::new();
|
||||||
@@ -169,11 +169,11 @@ simple. For example, the following snippet shows how to solve and validate a cha
|
|||||||
```rs
|
```rs
|
||||||
use async_compat::CompatExt;
|
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<()> {
|
fn main() -> anyhow::Result<()> {
|
||||||
smol::block_on(async {
|
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(())
|
Ok(())
|
||||||
})
|
})
|
||||||
@@ -199,7 +199,7 @@ use tokio::net::TcpListener;
|
|||||||
|
|
||||||
// In an actual application, make these two configurable. `clap` is a good tool for that.
|
// In an actual application, make these two configurable. `clap` is a good tool for that.
|
||||||
const APPLICATION_SECRET: &str = "<your-application-secret>";
|
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]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
@@ -229,7 +229,7 @@ async fn handler(
|
|||||||
payload.solution,
|
payload.solution,
|
||||||
addr.ip(),
|
addr.ip(),
|
||||||
APPLICATION_SECRET,
|
APPLICATION_SECRET,
|
||||||
PROTECTION_PROFILE_ID,
|
POLICY_ID,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -256,7 +256,7 @@ use warp::{Filter, Reply};
|
|||||||
|
|
||||||
// In an actual application, make these two configurable. `clap` is a good tool for that.
|
// In an actual application, make these two configurable. `clap` is a good tool for that.
|
||||||
const APPLICATION_SECRET: &str = "<your-application-secret>";
|
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]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
@@ -287,7 +287,7 @@ async fn handler(
|
|||||||
payload.solution,
|
payload.solution,
|
||||||
addr.ip(),
|
addr.ip(),
|
||||||
APPLICATION_SECRET,
|
APPLICATION_SECRET,
|
||||||
PROTECTION_PROFILE_ID,
|
POLICY_ID,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -317,7 +317,7 @@ use serde::Deserialize;
|
|||||||
|
|
||||||
// In an actual application, make these two configurable. `clap` is a good tool for that.
|
// In an actual application, make these two configurable. `clap` is a good tool for that.
|
||||||
const APPLICATION_SECRET: &str = "<your-application-secret>";
|
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]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
@@ -342,7 +342,7 @@ async fn protected(req: HttpRequest, payload: Json<ProtectedRequestPayload>) ->
|
|||||||
payload.solution.clone(),
|
payload.solution.clone(),
|
||||||
addr.ip(),
|
addr.ip(),
|
||||||
APPLICATION_SECRET,
|
APPLICATION_SECRET,
|
||||||
PROTECTION_PROFILE_ID,
|
POLICY_ID,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|||||||
Reference in New Issue
Block a user