ipasis
Blog/Security Engineering

Implementing IP Risk Scoring to Harden Signup Authentication

January 04, 20264 min read

The Problem: Frictionless Signups vs. Fraud

Modern authentication flows aim for zero friction to maximize conversion. However, this lack of verification opens the door to Sybil attacks, credential stuffing, and bonus abuse. While CAPTCHAs mitigate basic bots, sophisticated attackers utilize high-quality residential proxies that bypass frontend challenges.

The most effective defense layer sits on the backend: IP Intelligence.

By analyzing the connection type (VPN, Tor, Proxy, Hosting) and historical reputation of an ingress IP address before writing to the database, engineers can filter malicious actors without degrading the user experience for legitimate customers.

Architecture Integration

The IP risk check should occur immediately after payload validation but before database insertion or third-party auth provider calls (e.g., Auth0/Firebase). This saves database IOPS and prevents costs associated with verification emails or SMS.

The Logic Flow

  1. Receive Payload: Endpoint accepts email/password.
  2. Extract IP: Normalize X-Forwarded-For or CF-Connecting-IP headers.
  3. Query IPASIS: Asynchronous call to the intelligence API.
  4. Evaluate Risk: Apply logic based on risk score and connection type.
  5. Decision: Allow, Challenge (MFA), or Block.

Implementation

Below is a backend implementation using Python (FastAPI) and Node.js to demonstrate the integration of IPASIS during the registration route.

Python (FastAPI/Requests)

import os
import requests
from fastapi import FastAPI, Request, HTTPException

app = FastAPI()
IPASIS_API_KEY = os.getenv("IPASIS_KEY")

def check_ip_risk(ip_address: str) -> dict:
    url = f"https://api.ipasis.com/v1/{ip_address}?key={IPASIS_API_KEY}"
    try:
        response = requests.get(url, timeout=2.0)
        response.raise_for_status()
        return response.json()
    except requests.RequestException:
        # Fail open configuration: allow traffic if API is unreachable
        return {"risk_score": 0, "is_proxy": False}

@app.post("/signup")
async def register_user(request: Request, user_data: dict):
    client_ip = request.client.host
    
    # Get IP Intelligence
    ip_data = check_ip_risk(client_ip)
    
    # 1. Block High Risk or TOR
    if ip_data.get("risk_score") > 85 or ip_data.get("is_tor"):
        raise HTTPException(status_code=403, detail="Registration blocked due to high risk IP.")
    
    # 2. Flag/Challenge Moderate Risk (e.g., Data Center IPs)
    if ip_data.get("is_datacenter") or ip_data.get("risk_score") > 50:
        # Logic to trigger mandatory email verification or CAPTCHA
        pass

    # 3. Proceed with User Creation
    return {"status": "success", "message": "User created"}

Node.js (Express/Axios)

const express = require('express');
const axios = require('axios');
const app = express();

const IPASIS_KEY = process.env.IPASIS_KEY;

app.post('/signup', async (req, res) => {
  const clientIp = req.headers['x-forwarded-for'] || req.socket.remoteAddress;

  try {
    const response = await axios.get(`https://api.ipasis.com/v1/${clientIp}?key=${IPASIS_KEY}`, { timeout: 2000 });
    const { risk_score, is_proxy, is_vpn } = response.data;

    // Strict Blocking Policy
    if (risk_score > 80 || (is_proxy && risk_score > 50)) {
      return res.status(403).json({ error: 'Access denied.' });
    }

    // Proceed with database logic...
    res.json({ success: true });

  } catch (error) {
    // Log error and fail open
    console.error('IPASIS Lookup Failed', error.message);
    // Proceed to allow signup to avoid business disruption
    res.json({ success: true });
  }
});

Defining Risk Thresholds

Risk scoring is not binary. You must define thresholds based on your application's risk appetite.

  • Score 0-30 (Low): Residential and Mobile ISPs. Action: Allow.
  • Score 31-75 (Medium): Corporate VPNs, Public Proxies, Data Centers. Action: Enforce Email Verification or SMS 2FA.
  • Score 76-100 (High): Known botnets, Tor exit nodes, abusive proxies. Action: Hard Block or Shadowban.

Performance Considerations

When adding external API calls to authentication paths, latency is critical.

  1. Timeout Handling: Always set a strict timeout (e.g., 2000ms). If the IP API hangs, your signup flow should not.
  2. Fail Open vs. Fail Closed: For most B2C applications, "Fail Open" (allowing the signup on API error) is preferred to avoid blocking legitimate users during a service outage. Financial applications should "Fail Closed."
  3. Caching: Do not cache IP risk data for long periods. IP reputation is volatile; a residential IP used by a botnet today might be clean tomorrow.

FAQ

Does IP risk scoring replace CAPTCHA?

No. It works in tandem. CAPTCHA validates the frontend interaction, while IP scoring validates the network identity. Using them together provides defense-in-depth.

How do we handle IPv6?

IPASIS fully supports IPv6. Ensure your backend properly normalizes IPv6 addresses before querying the API.

Will this block legitimate VPN users?

You can configure your logic to allow VPNs (is_vpn: true) while blocking high-risk proxies (is_proxy: true). Many privacy-conscious users utilize legitimate VPNs; looking at the risk_score is often more effective than blocking by connection type alone.


Ready to stop fraudulent signups?

Integrate IPASIS today to detect proxies, VPNs, and high-risk IPs in real-time. Get your API Key and secure your onboarding flow.

Start detecting VPNs and Bots today.

Identify anonymized traffic instantly with IPASIS.

Get API Key