Tiny frontend UI component to enable additional authentication logic using FourSec graphical challenge
#npm
npm i foursec-challenge
# yarn
yarn add foursec-challenge
Using SetChallenge component
import { useEffect } from "react";
import {
SetChallenge,
PresetType,
ChallengeDataType,
} from "foursec-challenge";
const Component = () => {
const [preset, setPreset] = useState<PresetType>();
const fetchPreset = async () => {
const response = await fetch("<link>", { // for GET: https://api.foursec.io/api/v1/preset
method: "GET",
headers: {
"Content-Type": "application/json",
},
});
const { data } = await response.json();
setPreset(data);
};
const saveChallenge = async (challenge: ChallengeDataType) => {
const { data } = await fetch("<link>", { // for POST: https://api.foursec.io/api/v1/challenge
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
device_traits: {
...
},
challenge,
user_uuid: "<user_uuid>",
}),
});
if (data.success) {
// do something
}
};
useEffect(() => {
fetchPreset();
}, []);
return (
<SetChallenge preset={preset} onChange={saveChallenge} />
)
};
Using SolveChallenge component
import { useEffect } from "react";
import {
SolveChallenge,
PresetType,
ChallengeDataType,
} from "foursec-challenge";
const Component = () => {
const [preset, setPreset] = useState<PresetType>();
const fetchPreset = async () => {
const response = await fetch("<link>", { // for GET: https://api.foursec.io/api/v1/challenge
method: "GET",
headers: {
"Content-Type": "application/json",
},
});
const { data } = await response.json();
setPreset(data);
};
const verifyChallenge = async (challenge: ChallengeDataType) => {
const { data } = await fetch("<link>", { // for POST: https://api.foursec.io/api/v1/verify
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
device_traits: {
...
},
challenge,
user_uuid: "<user_uuid>",
}),
});
if (data.success) {
// do something
}
};
useEffect(() => {
fetchPreset();
}, []);
return (
<SolveChallenge preset={preset} onChange={verifyChallenge} />
)
};
You need to implement the backend to handle the challenge data and verify it. Below is an example of implementation 4 API endpoints to handle the challenge data.
const express = require("express");
const app = express();
const port = 3000;
const token = Buffer.from(`<FOURSEC_APP_ID>:<FOURSEC_APP_TOKEN>`).toString(
"base64"
);
// Get preset
app.get("/preset", async (req, res) => {
const { data } = await fetch("https://api.foursec.io/api/v1/preset", {
method: "GET",
headers: {
Authorization: `Basic ${token}`,
},
});
res.send(data);
});
// Save challenge
app.post("/challenge", async (req, res) => {
const { data } = await fetch("https://api.foursec.io/api/v1/challenge", {
method: "POST",
headers: {
Authorization: `Basic ${token}`,
},
body: JSON.stringify(req.body),
});
res.send(data);
});
// Get challenge
app.get("/challenge", async (req, res) => {
const { data } = await fetch(
"https://api.foursec.io/api/v1/challenge?user_uuid=<user_uuid>",
{
method: "GET",
headers: {
Authorization: `Basic ${token}`,
},
}
);
res.send(data);
});
// Verify challenge
app.post("/verify", async (req, res) => {
const { data } = await fetch(
"https://api.foursec.io/api/v1/verify-challenge",
{
method: "POST",
headers: {
Authorization: `Basic ${token}`,
},
body: JSON.stringify(req.body),
}
);
res.send(data);
});
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
});
MIT