Have you ever had your account suddenly locked because of suspicious activity or discovered someone else had bought something using one of your online shopping accounts? If so, you’ve experienced firsthand the frustration and risks of an account takeover (ATO) attack .
Account takeover is a rapidly growing threat in which malicious actors gain unauthorized access to user accounts, often leading to significant financial damage for both the user and the business. Fraudsters typically gain access to an account by tricking individuals into revealing personal information, such as through phishing or by exploiting weak or stolen credentials. Once they’ve gained access, they commit fraud, steal sensitive information, or carry out other malicious activities.
For businesses, this can mean loss of customer trust, regulatory penalties, and financial losses. For customers, it can lead to unauthorized transactions, exposure of personal data, and long-lasting effects on their digital identity.
As online fraud becomes more sophisticated, traditional security measures are falling short. To stay ahead, businesses must leverage advanced and precise device intelligence to protect user accounts.
In this guide, we’ll show you how to implement Fingerprint, a leading device intelligence platform, to detect and prevent account takeover attacks while creating a secure and frictionless login experience for returning visitors. We’ll cover the benefits of using accurate visitor data, outline the steps for planning and implementation, and share best practices to enhance your fraud strategy.
Whether you’re a fraud prevention professional, developer, or business leader, this guide will equip you with the knowledge and tools to protect your customers and your business from the growing threat of account takeover attacks.
(To learn more about key trends in account takeover, read our guide to understanding and preventing account takeover fraud.)
Introduction to Fingerprint
Fingerprint is a device intelligence platform that identifies online devices visiting your site or mobile app and offers valuable, real-time insights into their behavior. It uses browser and device attributes to generate a unique visitor identifier for each device, ensuring consistent identification even when device settings change or cookies are cleared. Additionally, Fingerprint Smart Signals provide insights into potentially suspicious activities, such as VPN usage, browser tampering, or bot behavior.
Fingerprint’s highly accurate and stable visitor IDs enable businesses to consistently recognize returning users, detect fraud, and enhance the overall user experience. This reliable identification of devices over time is crucial in preventing account takeover fraud. By analyzing the patterns and behaviors linked to each visitor ID, businesses can quickly identify anomalies — like an unexpected login from a new location or device — and take proactive measures before an account is compromised. With Fingerprint, you can stay ahead of fraudsters by identifying and addressing suspicious activity in real time.
How device intelligence prevents account takeovers
Once you gain deeper insights into the devices interacting with your platform, you can use that data in several different ways to better protect accounts. From recognizing suspicious login attempts from unfamiliar devices to identifying unusual device characteristics, Fingerprint helps you proactively protect your users' accounts while allowing for smooth user experiences. Let’s explore how you can use these insights to prevent account takeover and improve user experience on your platform.
Recognizing known and unknown devices during login
Fingerprint creates a unique visitor ID for each device interacting with your platform. By storing these IDs and linking them to user accounts in your database, you can quickly identify when a login attempt originates from a known device. If the device is unfamiliar, you can take proactive measures, such as requesting additional identity verification, and flagging or blocking potentially fraudulent access before any harm occurs. As an added benefit, you can streamline the login process for recognized legitimate visitors by allowing them to skip additional authentication processes.
Identifying devices involved in past attacks or suspicious activity
Fingerprint visitor IDs remain consistent, even as browsers update or settings change. Because these IDs don’t rely on cookies, which can be blocked or cleared, they are difficult to alter. If a device with a particular visitor ID has been associated with previous attacks or suspicious behavior, you can take preemptive action when it shows up again, helping to prevent repeat offenders from compromising accounts.
Spotting devices accessing an unusual number of accounts
Just as you can link a single account to any visitor IDs that have accessed it, you can also monitor how many accounts are associated with a single visitor ID. If a visitor is found to be accessing an unusually high number of accounts, it may indicate malicious activity, allowing you to intervene before additional accounts are compromised.
Stopping bots with Fingerprint Smart Signals
Fingerprint Smart Signals offer detailed insights into your visitors, including the ability to detect bots. Bots are frequently used to break into accounts in automated attacks, such as brute force or credential stuffing. By identifying bot activity, you can block these automated attackers before they even attempt to log in, protecting your users from unauthorized access to their accounts.
Detecting suspicious attributes like browser tampering, VPN usage, and more
Additionally, you can analyze the signals from visitors on your site to identify unusual or suspicious behavior. While no single signal directly indicates fraudulent intent, you can recognize higher-risk behavior patterns. For instance, Fingerprint Smart Signals can detect if a visitor is using a tampered browser, accessing your site from a blocklisted IP, connected via a VPN, or running on a virtual machine. These insights allow you to assess the risk level of each visitor and take the necessary steps to prevent account takeovers.
By using one or more of these methods, Fingerprint’s device intelligence not only helps you detect and prevent account takeovers but also strengthens your platform, ensuring a safe experience for legitimate users.
Planning your implementation
Fingerprint is designed to integrate with your existing infrastructure, minimizing disruptions to development. Visitor identification and device signals are flexible, and their use can be fully customized to fit your business needs.
To get the most out of Fingerprint, you first need to analyze your users, understand your environment, and consider how Fingerprint’s insights can be applied to your specific use case. Each website's security requirements vary, so it's important to thoroughly evaluate your specific needs before implementing Fingerprint. While Fingerprint supplies the data, it’s up to you to develop a strategy that fits your unique needs and integrates seamlessly with your platform.
In this section, we’ll walk you through understanding your users’ behaviors, evaluating your existing site and systems, and determining the most effective way to integrate Fingerprint into your platform. You’ll develop a clear roadmap for setting up Fingerprint, including setting your own thresholds and rules based on the insights it provides.
Many of these planning steps require data to make informed decisions. If you don’t already have this data, you can start by using Fingerprint to identify and collect visitor information without immediately taking action. By using Fingerprint's dashboard, you can gain a better understanding of your users’ behaviors before implementing your security measures and fraud logic.
Assess your protection needs and visitor identification touchpoints
When planning your account takeover prevention strategy, it’s essential to identify the key pages and actions that require additional protection to prevent unauthorized access. Focus on areas like login pages, transaction processes, or account changes — the ones most vulnerable to account takeovers. Consider the sensitivity of the data being accessed or modified and the potential impact if an account were compromised.
Additionally, you’ll need to determine how often to verify a user's identity to effectively prevent account takeovers. For platforms handling highly sensitive information, such as financial services or confidential data, it may be necessary to verify identity on every page visit to ensure the highest level of security. On platforms with less sensitive information, verification might only be needed during high-risk activities, such as logins or account modifications. Also, keep in mind that identification requests are billed and count towards your monthly quota.
Key questions:
- How sensitive is the information being accessed or modified on my platform?
- Which pages and actions on my site are most vulnerable to account takeover attacks?
- How often should I request Fingerprint visitor identification?
Understand standard user behavior on your site
Next, consider how your users typically interact with your site. For example, consider whether it's usual for a single device to access multiple accounts or for users to log in from multiple devices. Understanding these patterns will help you determine what constitutes normal behavior on your site.
Also, consider the distribution of attributes and signals you observe among your users. For instance, if your audience is more privacy-conscious, it may be common for them to use VPNs, incognito modes, or other privacy settings. In such cases, these behaviors should not automatically trigger security measures but rather be considered in the context of your user base’s typical behavior. On the other hand, if these signals are uncommon for your users, they may indicate a higher risk and warrant action.
As you gather more data and gain a better understanding of your audience over time, you’ll be able to refine your analysis of visitor behavior and identify patterns in unusual activity. Fingerprint’s Suspect Score, which assesses statistically suspicious behavior, can help highlight risky activity as you deepen your insights into your own visitor data.
Key questions:
- What are the typical patterns of device usage among my users?
- Which behaviors should be considered normal versus suspicious?
- How can I refine my device intelligence criteria over time?
Determine thresholds for flagging suspicious behavior
Once you have a solid understanding of your users’ typical behaviors and the activities that need protection, you can begin setting clear thresholds for what counts as suspicious behavior on your platform. By this stage, you should have already examined patterns such as the number of devices usually linked to a single account and how many accounts are typically accessed from one device. With this information, you can set your thresholds for suspicious behavior.
For instance, if most users typically log in from three or four devices, you might decide to flag an account when a fifth device tries to access it. Alternatively, for stricter security, you could flag any device that isn’t already associated with the account as suspicious. Likewise, you can set a threshold for when a device accesses an unusually high number of accounts based on what you consider normal behavior.
In addition to device and account associations, establish specific triggers for further action based on characteristics like VPN usage, browser tampering, IP blocklist matching, or logging in from unfamiliar locations. These triggers should align with what’s normal for your user base. For example, if using a jailbroken mobile device to access your app is uncommon among your users, detecting it could warrant attention.
Key questions:
- What is the typical number of devices associated with a single account on my platform?
- How many accounts are usually accessed from a single device?
- Which specific activities or characteristics should trigger further action?
Define responses to suspicious activity
Once you've set your thresholds, the next step is determining what actions to take when suspicious behavior is detected. The responses could range from requiring multi-factor authentication (MFA) for certain actions to sending alerts to users or temporarily suspending accounts for further verification. It’s important to have a clear, tiered process for escalating these actions based on the severity of the threat detected.
When new devices attempt to access an account, consider implementing extra verification steps, such as sending a one-time passcode (OTP) to the user's registered email or phone number. This helps ensure that the person trying to log in is actually the account owner. Or if you detect a bot accessing your login page and there's no legitimate reason for it to do so, you can choose to block the action entirely.
By setting clear thresholds and defining actions for suspicious behavior, you create a robust framework that helps protect against account takeovers while maintaining a balance between security and user experience.
Key questions:
- What actions should be taken when suspicious behavior is detected?
- How should the severity of the detected threat influence the response?
- What verification steps should be triggered when a new device attempts to access an account?
Consider system integration and data management needs
Another important consideration is how Fingerprint data will integrate with your existing systems and how you’ll manage and use it effectively. Are there other components within your infrastructure that could benefit from incorporating Fingerprint data? For instance, integrating Fingerprint with your Web Application Firewall (WAF) or your fraud analysis tools can offer additional insights into potentially malicious activities.
Next, consider where and how you will store and access Fingerprint identification data. Will you need to establish new infrastructure or update your existing databases? Additionally, determine how you plan to monitor and analyze this data — whether through dashboards, alerts, or automated reporting systems — to effectively analyze visitor data and monitor or refine your implementation. Developing a strong data management strategy will ensure you can get the most out of Fingerprint's insights.
A well-organized data management plan is also essential for evaluating Fingerprint’s effectiveness in preventing account takeovers. Be sure to define specific metrics that align with your objectives, such as the number of account takeovers or fraudulent transactions. Establish a baseline and then regularly review these metrics and benchmarks to measure Fingerprint's impact and adjust your strategy as needed.
Key questions:
- How will Fingerprint data integrate with my existing systems?
- What infrastructure changes might be necessary to store and access Fingerprint identification data?
- How will I monitor and analyze Fingerprint insights in real time?
Additional considerations
At this point in your planning process, you have about everything covered, but there are a couple of additional things to consider.
First, ensure that your use of Fingerprint complies with GDPR and other applicable regulatory requirements. Under GDPR, using Fingerprint for fraud prevention is considered a “legitimate interest,” which means explicit user consent may not be required. However, it’s important to have the appropriate consent mechanisms for collecting and processing user data according to any other regulations you may be subject to. You also should carefully select the appropriate region and data retention policies for Fingerprint data processing to ensure compliance with data residency requirements while respecting user privacy and fulfilling all legal obligations.
While it is unlikely, particularly when the JavaScript agent is well protected, it’s still important to consider what to do in situations where Fingerprint can’t generate a visitor identifier. This can happen due to timeouts, rate limits, or other technical problems. To maintain the effectiveness of your account takeover prevention strategy, it's important to have a backup plan in place, such as consistently requiring MFA when this occurs.
Key questions:
- What consent mechanisms do I need to implement for collecting and processing user data?
- Have I chosen the correct region and data retention policies for Fingerprint data processing?
- What actions will I take if Fingerprint cannot generate an identifier for a device?
Technical overview
Before we dive into the implementation steps for preventing account takeovers, let’s review the key technical components of Fingerprint that you’ll need for a successful setup.
JavaScript agent
The JavaScript agent is a client-side script that gathers device and browser attributes and sends them to Fingerprint for processing, identification, and bot detection. It’s the key component for browser identification and generating unique identifiers for each visitor.
Server API
The Fingerprint Server API enables you to retrieve detailed information about visitors and specific identification events. With this API, you can verify that the visitor ID received from the client side hasn’t been spoofed and access additional data, such as whether the visitor is a bot, using a tampered browser, operating in incognito mode, etc.
Custom subdomain & proxy integrations
Configuring Fingerprint to use a custom subdomain or cloud proxy integration allows you to bypass common ad blockers that might otherwise hinder the JavaScript agent’s functionality. Although this guide won't cover these protections in detail, this setup is crucial for maintaining high data accuracy and comprehensive coverage.
Fingerprint libraries & SDKs
Fingerprint offers SDKs for various web and mobile frameworks and languages, making it easier to integrate the service into your existing infrastructure. These SDKs provide pre-built functions, such as retry logic, and tools that make implementing Fingerprint a breeze.
Implementation steps for preventing account takeover
Now that you’ve thoroughly laid out your plan, you’re ready to implement Fingerprint to prevent account takeovers on your platform. With a solid understanding of your users, a clear set of thresholds and actions, and a well-considered strategy for integrating Fingerprint into your existing infrastructure, you’re well-equipped to move forward.
This section will guide you through the essential implementation steps, ensuring you maximize Fingerprint’s device intelligence.
To frame these steps, let’s consider the example of Acme Co., a European, mid-sized e-commerce company that has recently decided to strengthen its account protection. Acme operates a website where users log in to make purchases and manage their accounts. After completing the planning process laid out above, Acme has decided on the following logic and actions:
- Any new, unknown device attempting to log into an account will be considered suspicious. The user will be required to input a one-time code sent to their phone for verification.
- VPN usage will be flagged as suspicious since it's rare among Acme's users. Visitors identified as using a VPN will be prompted to submit a one-time code as well.
- Visitors identified as bots will be blocked from logging in.
- Devices associated with over five login attempts will not be allowed to log in for 24 hours.
As we go through the implementation steps, we’ll refer back to Acme’s decisions to illustrate how these concepts can be applied in practice. This approach will help you visualize how to execute your own plan effectively, even if your specific needs differ from those of Acme
Step 0: Gather your API keys
Fingerprint provides two API keys: a public key for identification and a secret key for server-side communication. To obtain your API keys, log into the Fingerprint dashboard, navigate to App Settings in the left-hand menu, and click on API Keys. Here, you'll find both keys needed for your implementation, or you can create new ones if you haven't already.
The public key is used on the client side, such as in your JavaScript agent or mobile SDK, while the secret key is intended for server-side interactions to secure sensitive operations. Ensure these keys are stored securely, and never expose your secret key in client-side code or public repositories.
Step 1: Install the JavaScript agent
The first step is to make an identification request to Fingerprint using the JavaScript agent. If your front end is built with modern frameworks like React or Angular, or if you're developing a mobile app, you can use one of our various libraries.
Begin by installing the Fingerprint agent loader NPM package. In this example, we’re using the generic JavaScript library that works with various module bundlers:
npm i @fingerprintjs/fingerprintjs-pro
When using Fingerprint for account takeover protection, you'll want to add the agent to your login page. It’s best to initialize the agent as early as possible. You can then choose when to trigger the identification request — either at page load or when a specific action occurs. For example, Acme chose to trigger the identification request when the login button is pressed, ensuring that the visitor ID is fresh for this sensitive action.
import * as FingerprintJS from "@fingerprintjs/fingerprintjs-pro";
const fpPromise = FingerprintJS.load({
region: "eu",
apiKey: "PUBLIC_API_KEY",
endpoint: "https://fp.acme.com",
scriptUrlPattern: "https://fp.acme.com/web/v<version>/<apiKey>/loader_v<loaderVersion>.js"
});
async function login(username, password) {
// Get the visitor ID when you need it.
const fp = await fpPromise;
const result = await fp.get();
console.log(result.requestId, result.visitorId);
// ... additional login logic
}
In this setup, Acme is using the region
parameter with the load
method to set their region to the EU, which is important because they serve customers in Europe. Additionally, they’ve specified both endpoint
and scriptUrlPattern
parameters since they are using a custom subdomain to prevent ad blockers from interfering with identification requests. The endpoint
parameter is where the agent will send identification requests and the scriptUrlPattern
provides a URL pattern where the agent loader will download the latest code. You can learn more about these parameters in the load
function reference for the agent.
Within the login
function, the identification request is made using fp.get()
, which returns an object containing a requestId
and a visitorId
. The requestId
is unique to each identification and changes with every request, while the visitorId
remains consistent and uniquely identifies the device.
Step 2: Send the identification data to the server
Now that you have made the identification request, you can send the requestId
and visitorId
to your server. There, you can verify the authenticity of the visitor ID, analyze additional characteristics of the visitor, and decide on the appropriate actions to take.
async function login(username, password) {
// Get the visitor ID when you need it.
const fp = await fpPromise;
const result = await fp.get();
const { requestId, visitorId } = result;
const loginData = {
username,
password,
requestId,
visitorId
};
const requestOptions = {
method: "POST",
body: JSON.stringify(loginData),
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
};
const response = await fetch("/api/authenticate", requestOptions);
// ... additional login logic
}
The requestId
is essential for retrieving current information about the visitor and validating the visitorId
so make sure to include both.
Step 3: Confirm the validity of the visitor ID
Before using the visitor ID, it's essential to ensure that it is valid and hasn't been tampered with, such as in replay attacks, where an old request could be reused maliciously. This validation process is performed on the server. Begin by installing your preferred version of the Fingerprint Server API library — here, we’re using the Node SDK, though you can also call the Server API directly.
npm install @fingerprintjs/fingerprintjs-pro-server-api
Let’s set up a main login handler, which will orchestrate the various checks and validations needed during authentication including validating the visitor ID, detecting potential threats like bots or VPN usage, checking passwords, and managing new device logins. As we proceed, we'll add helper functions that address these specific parts of the login process.
async function loginHandler(request) {
const { username, password, requestId, visitorId } = request.body;
const authSuccess = await authenticateUser(username, password); // Pseudo authentication function
if (!authSuccess) {
return { success: false, error: "Invalid username or password." };
}
// ... more to come soon
}
The first helper function will be to validate the visitor identification event. You’ll need to initialize the Fingerprint Server API client, specifying your secret API key and region:
import {
FingerprintJsServerApiClient,
Region,
} from "@fingerprintjs/fingerprintjs-pro-server-api";
async function validateFingerprintResult(requestId, visitorId, request) {
const client = new FingerprintJsServerApiClient({
apiKey: "SECRET_API_KEY",
region: Region.EU,
});
Next, retrieve the identification event using the requestId
sent from the client. This event contains the data needed to validate the visitor ID:
const identificationEvent = await client.getEvent(requestId);
const identification = identificationEvent.products?.identification?.data;
We can now confirm that the visitor ID passed from the client matches the one seen in the identification event, helping to detect if the user was trying to spoof the ID. Additionally, you can avoid passing the visitor ID from the client side altogether, sending only the request ID to retrieve the identification event. By keeping the visitor ID out of the client payload, it becomes a bit harder for attackers to reverse engineer your setup. For even more security, you can encrypt the client payload using sealed client results or use zero trust mode to only receive a request ID from Fingerprint.
// Confirm the visitorId is the same as the one in the identification event
if (!identification.visitorId || visitorId !== identification.visitorId) {
return {
success: false,
error: "Visitor ID does not match the identification event. Potential spoofing attempt.",
};
}
We can also check if the identification event is too old. If the event is more than 3 seconds old, it’s flagged as a potential replay attack:
// Identification event must not be more than 3 seconds old
if (Date.now() - Number(new Date(identification.time)) > 3000) {
return {
success: false,
error: "Old identification request, potential replay attack.",
};
}
You can also verify that the IP address from the identification matches the client’s IP address. This step helps to detect potential spoofing attacks:
// This is an example of obtaining the client's IP address.
// In most cases, it's a good idea to look for the right-most
// external IP address in the list to prevent spoofing.
if (request.headers["x-forwarded-for"].split(",")[0] !== identification.ip) {
return {
success: false,
error:
"Identification IP does not match request IP, potential spoofing attack.",
};
}
Next, the code checks that the request originated from a known and trusted domain. This ensures that the visitor data is coming from a legitimate source, specifically Acme’s website:
const ourOrigin = "https://acme.com";
const visitorDataOrigin = new URL(identification.url).origin;
// Confirm that the request is from our origin.
if (
visitorDataOrigin !== ourOrigin ||
request.headers["origin"] !== ourOrigin
) {
return {
success: false,
error:
"Visit origin does not match request origin, potential spoofing attack.",
};
}
return { success: true, data: identificationEvent };
}
If all checks pass, the function returns the identification event data, confirming that the visitor ID is valid and the request is legitimate. This process ensures that Acme can trust the visitor ID and proceed with any sensitive actions, like logging in the user or generating an OTP code.
Let’s add this helper function into our main login handler:
async function loginHandler(request) {
const { username, password, requestId, visitorId } = request.body;
const authSuccess = await authenticateUser(username, password); // Pseudo authentication function
if (!authSuccess) {
return { success: false, error: "Invalid username or password." };
}
// Validate the visitor ID
const identificationEvent = await validateFingerprintResult(
requestId,
visitorId,
request
);
if (!identificationEvent.success) return identificationEvent;
Step 4: Assess suspicious signals
In this step, we'll create a new function to address device characteristics that raise suspicion and require action. Since VPN usage is uncommon among Acme’s user base, it’s flagged as suspicious, and additional verification steps are required. Visitors identified as using a VPN will be prompted to input a one-time code sent to their phone before logging in. Additionally, any visitors identified as malicious bots will be blocked from logging in entirely.
Here’s how you can implement this in a new function:
function checkDeviceSignals(identificationEvent) {
// Prevent bots from logging in
if (identificationEvent.products?.botd?.data?.bot?.result !== "notDetected") {
return {
success: false,
error: "Bot detected, login is blocked.",
};
}
// Check if the visitor is using a VPN
if (identificationEvent.products?.vpn?.data?.result) {
return {
success: false,
error:
"VPN usage detected. A one-time code has been sent to your phone for verification.",
action: "sendOTP",
};
}
return { success: true };
}
The first check is for bot detection. If the visitor is identified as a bot, the function blocks the login attempt and returns an error message. Then, if a VPN is detected, the visitor is flagged, and the function returns an object that triggers a one-time code to be sent to the visitor’s phone for additional verification. If neither a bot nor a VPN is detected, the function allows the visitor to proceed to the next checks.
You can further customize this function by adding additional checks based on Fingerprint's Smart Signals, tailored to your specific user base and definitions of suspicious characteristics. For example, you might include checks for browser tampering, usage of incognito mode, or other behaviors that are uncommon or potentially risky for your platform.
Let’s now include this function in the login handler:
async function loginHandler(request) {
// ... previous checks
// Perform bot and VPN detection
const deviceSignals = checkDeviceSignals(identificationEvent.data);
if (!deviceSignals.success) return deviceSignals;
Step 5: Handle new, unknown device logins
At this stage, we want to determine if the device attempting to log in is one we recognize and have previously linked to the account. Acme views unrecognized devices as a potential sign of unauthorized access, so these devices will be flagged as suspicious, and users will be required to verify their identity by entering a one-time code sent to their phone.
First, fetch a list of recognized devices from the database. For this example, assume there is a login_attempts
table that stores login attempts with visitor IDs, the accounts they tried to access, and whether the attempts were successful. We'll extract the visitor IDs that have successfully logged in before.
import db from "./db";
async function getKnownVisitorIdsForUser(username) {
// Query to get known visitor IDs for the given username
const [rows] = await db.execute(
"SELECT visitor_id FROM login_attempts WHERE username = ? AND success = TRUE GROUP BY visitor_id",
[username]
);
// Extract visitor IDs from the rows and return them as an array
const visitorIds = rows.map((row) => row.visitor_id);
return visitorIds;
}
Once we get this list in our login handler we can check if the visitor ID has been seen before for this account.
async function loginHandler(request) {
// ... previous checks
// Retrieve known visitor IDs associated with the username
const knownDevices = await getKnownVisitorIdsForUser(username);
// Check if the current visitorId is in the list of known devices
if (!knownDevices.includes(visitorId)) {
return {
success: false,
error: "Unrecognized device detected.",
action: "sendOTP",
};
}
Step 6: Log the user in and capture the attempt
If the visitor has successfully passed all the previous checks you can continue the process to log the user in.
async function loginHandler(request) {
// ... previous checks
return { success: true};
}
Store the result of the login attempt based on the checks in the login handler. Make sure to save the current visitor ID along with the username to enable future device recognition.
const loginResult = await loginHandler(request);
// Store the login attempt in the database alongside the username and visitor ID
await db.execute(
"INSERT INTO login_attempts (username, visitor_id, success, attempted_at) VALUES (?, ?, ?, NOW())",
[username, visitorId, loginResult.success]
);
if (!loginResult.success) {
if (loginResult.action === "sendOTP") {
sendOTP(username); // Pseudo function to send an OTP
}
}
Step 7: Implement failed login attempt tracking
In addition to checking if a device is associated with an account, it can also be beneficial to monitor failed login attempts for each device. If a device exceeds the allowed number of login attempts within a specific timeframe, it can be temporarily blocked from logging in. Here is a simple example that you could add to your loginHandler
function.
async function loginHandler(request) {
// ... identification checks
// Retrieve the number of failed login attempts across any account in the last 24 hours
const [rows] = await db.execute(
"SELECT COUNT(*) AS failed_attempts FROM login_attempts WHERE visitor_id = ? AND success = FALSE AND attempted_at >= NOW() - INTERVAL 24 HOUR",
[visitorId]
);
if (rows[0].failed_attempts > 5) {
return { success: false, error: "Too many failed login attempts in the last 24 hours. Try again later." };
}
With the completion of these implementation steps, you’ve successfully integrated Fingerprint device intelligence and robust logic to protect your users’ accounts from account takeover.
Explore a live demo and sample application
Throughout this guide, we've established mechanisms to detect and handle suspicious activity, such as flagging unknown devices, managing login attempts, verifying identities via one-time codes, and blocking bots.
To see these concepts in action, check out our live demos, specifically the one for credential stuffing, which shares many of the same concepts covered in this guide. The demo provides a hands-on experience where you can test out the logic we've implemented, such as detecting unknown devices and managing login attempts.
You can access the full source code for the credential stuffing demo on GitHub, which allows you to explore, customize, and integrate similar logic into your own platform. These resources will help solidify your understanding and provide a practical reference as you continue to strengthen your platform against account takeover attacks.
Final thoughts for account takeover prevention
In this guide, we’ve explored how to implement Fingerprint to protect your platform against account takeovers. From configuring the JavaScript agent and verifying visitor IDs to tracking login attempts and addressing suspicious activity, you've built a strong foundation to streamline the login process for legitimate users while protecting against key vulnerabilities in the login process.
Now that you're set up with a solid framework, you're ready to implement Fingerprint and bolster your fraud prevention strategies. It's important to regularly evolve your detection logic and stay ahead of emerging threats. As your platform grows, so will the tactics of fraudsters, so be proactive in adapting your approach.
If you need any assistance or additional support in stopping fraudsters, don't hesitate to reach out — we're here to help you keep your platform secure.