useTrust

Device trust scoring and risk assessment for authentication events.

Risk Signals: Device fingerprinting, geolocation, behavior analysis, and threat detection

Import

import { useTrust } from '@heliorim/sdk-react';

Type Signature

interface TrustState {
  trustScore: number; // 0-100
  riskLevel: 'low' | 'medium' | 'high' | 'critical';
  deviceInfo: DeviceInfo | null;
  signals: TrustSignal[];
  isAnalyzing: boolean;
  error: Error | null;
}

interface TrustActions {
  analyzeTrust: (options?: AnalyzeOptions) => Promise<TrustResult>;
  reportSuspicious: (reason: string) => Promise<void>;
  whitelistDevice: () => Promise<void>;
  blacklistDevice: (deviceId: string) => Promise<void>;
  getRiskFactors: () => RiskFactor[];
  clearCache: () => void;
}

interface DeviceInfo {
  id: string;
  fingerprint: string;
  platform: string;
  browser: string;
  location?: {
    country: string;
    city: string;
    timezone: string;
  };
  lastSeen: number;
  trustHistory: TrustEvent[];
}

interface TrustSignal {
  type: 'device' | 'behavior' | 'location' | 'network' | 'timing';
  name: string;
  value: any;
  weight: number;
  risk: 'positive' | 'neutral' | 'negative';
}

interface RiskFactor {
  factor: string;
  score: number;
  description: string;
  mitigations: string[];
}

type UseTrustReturn = TrustState & TrustActions;

Basic Usage

function TrustIndicator() {
  const {
    trustScore,
    riskLevel,
    deviceInfo,
    signals,
    analyzeTrust,
    reportSuspicious,
    whitelistDevice
  } = useTrust();

  useEffect(() => {
    // Analyze trust on component mount
    analyzeTrust();
  }, []);

  const handleAuthentication = async () => {
    // Re-analyze before sensitive operations
    const result = await analyzeTrust({
      includeGeolocation: true,
      includeBehavior: true
    });

    if (result.riskLevel === 'high' ?? result.riskLevel === 'critical') {
      // Require additional verification
      alert('Additional verification required due to security concerns');
      return;
    }

    // Proceed with authentication
    await authenticate();
  };

  const getTrustColor = () => {
    if (trustScore >= 80) return 'text-green-600';
    if (trustScore >= 60) return 'text-yellow-600';
    if (trustScore >= 40) return 'text-[color:var(--warning)]';
    return 'text-red-600';
  };

  return (
    <div>
      <div className="trust-indicator">
        <h3>Device Trust Score</h3>
        <div className={getTrustColor()}>
          <span className="text-3xl font-bold">{trustScore}</span>
          <span className="text-sm">/100</span>
        </div>
        <p>Risk Level: {riskLevel}</p>
      </div>

      {deviceInfo && (
        <div className="device-info">
          <p>Device: {deviceInfo.platform} - {deviceInfo.browser}</p>
          {deviceInfo.location && (
            <p>Location: {deviceInfo.location.city}, {deviceInfo.location.country}</p>
          )}
        </div>
      )}

      <button onClick={() => whitelistDevice()}>
        Trust This Device
      </button>

      <button onClick={() => reportSuspicious('User reported suspicious activity')}>
        Report Suspicious Activity
      </button>
    </div>
  );
}

Risk Assessment

Real-time Analysis

function RiskBasedAuth() {
  const { analyzeTrust, getRiskFactors, riskLevel } = useTrust();
  const { authenticate } = usePasskey();

  const performRiskBasedAuth = async () => {
    // Analyze current risk
    const result = await analyzeTrust({
      includeGeolocation: true,
      includeBehavior: true,
      includeNetwork: true
    });

    switch (result.riskLevel) {
      case 'low':
        // Standard authentication
        await authenticate();
        break;

      case 'medium':
        // Require user verification
        await authenticate({
          userVerification: 'required'
        });
        break;

      case 'high':
        // Step-up authentication required
        const factors = getRiskFactors();
        console.log('Risk factors:', factors);
        // Show additional verification UI
        break;

      case 'critical':
        // Block authentication
        alert('Authentication blocked due to security risk');
        break;
    }
  };

  return (
    <button onClick={performRiskBasedAuth}>
      Sign In Securely
    </button>
  );
}

Trust Signals

function TrustSignalsDisplay() {
  const { signals, trustScore } = useTrust();

  const groupedSignals = signals.reduce((acc, signal) => {
    if (!acc[signal.type]) acc[signal.type] = [];
    acc[signal.type].push(signal);
    return acc;
  }, {} as Record<string, TrustSignal[]>);

  return (
    <div className="trust-signals">
      <h3>Trust Analysis Details</h3>

      {Object.entries(groupedSignals).map(([type, typeSignals]) => (
        <div key={type} className="signal-group">
          <h4>{type.charAt(0).toUpperCase() + type.slice(1)} Signals</h4>
          <ul>
            {typeSignals.map((signal, idx) => (
              <li key={idx} className={
                signal.risk === 'positive' ? 'text-green-600' :
                signal.risk === 'negative' ? 'text-red-600' :
                'text-gray-600'
              }>
                {signal.name}: {signal.value}
                <span className="text-xs ml-2">
                  (weight: {signal.weight})
                </span>
              </li>
            ))}
          </ul>
        </div>
      ))}

      <div className="trust-summary">
        <p>Overall Trust Score: {trustScore}/100</p>
      </div>
    </div>
  );
}

Device Management

Trusted Devices

function TrustedDevices() {
  const { deviceInfo, whitelistDevice, blacklistDevice } = useTrust();
  const [trustedDevices, setTrustedDevices] = useState<DeviceInfo[]>([]);

  useEffect(() => {
    // Load trusted devices
    fetchTrustedDevices().then(setTrustedDevices);
  }, []);

  const trustCurrentDevice = async () => {
    await whitelistDevice();
    // Refresh list
    const devices = await fetchTrustedDevices();
    setTrustedDevices(devices);
  };

  const removeTrustedDevice = async (deviceId: string) => {
    await blacklistDevice(deviceId);
    setTrustedDevices(prev =>
      prev.filter(d => d.id !== deviceId)
    );
  };

  return (
    <div>
      <h3>Manage Trusted Devices</h3>

      <div className="current-device">
        <h4>Current Device</h4>
        {deviceInfo && (
          <div>
            <p>{deviceInfo.platform} - {deviceInfo.browser}</p>
            <button onClick={trustCurrentDevice}>
              Add to Trusted Devices
            </button>
          </div>
        )}
      </div>

      <div className="trusted-list">
        <h4>Trusted Devices</h4>
        {trustedDevices.map(device => (
          <div key={device.id} className="device-item">
            <span>{device.platform} - {device.browser}</span>
            <span>Last seen: {new Date(device.lastSeen).toLocaleDateString()}</span>
            <button onClick={() => removeTrustedDevice(device.id)}>
              Remove
            </button>
          </div>
        ))}
      </div>
    </div>
  );
}

Geolocation Verification

function LocationVerification() {
  const { deviceInfo, signals, reportSuspicious } = useTrust();
  const [expectedLocation, setExpectedLocation] = useState<string>('');

  const verifyLocation = () => {
    const locationSignals = signals.filter(s => s.type === 'location');
    const currentLocation = deviceInfo?.location;

    if (!currentLocation) {
      console.warn('Location not available');
      return false;
    }

    // Check for impossible travel
    const lastLocation = locationSignals.find(s => s.name === 'last_location');
    if (lastLocation) {
      const distance = calculateDistance(lastLocation.value, currentLocation);
      const timeDiff = Date.now() - lastLocation.value.timestamp;
      const speed = distance / (timeDiff / 3600000); // km/h

      if (speed > 1000) { // Faster than commercial flight
        reportSuspicious('Impossible travel detected');
        return false;
      }
    }

    // Check for VPN/Proxy
    const vpnSignal = signals.find(s => s.name === 'vpn_detected');
    if (vpnSignal?.value) {
      console.warn('VPN/Proxy detected');
      // May want to require additional verification
    }

    return true;
  };

  return (
    <div className="location-verification">
      <h3>Location Security</h3>
      {deviceInfo?.location ? (
        <div>
          <p>Current Location: {deviceInfo.location.city}, {deviceInfo.location.country}</p>
          <p>Timezone: {deviceInfo.location.timezone}</p>
          <button onClick={verifyLocation}>
            Verify Location
          </button>
        </div>
      ) : (
        <p>Location information not available</p>
      )}
    </div>
  );
}

Behavioral Analysis

function BehaviorMonitoring() {
  const { signals, analyzeTrust, reportSuspicious } = useTrust();

  // Monitor for suspicious patterns
  useEffect(() => {
    const behaviorSignals = signals.filter(s => s.type === 'behavior');

    // Check for bot-like behavior
    const mouseMovement = behaviorSignals.find(s => s.name === 'mouse_movement');
    if (mouseMovement?.value === 'none') {
      reportSuspicious('No mouse movement detected');
    }

    // Check for rapid actions
    const actionSpeed = behaviorSignals.find(s => s.name === 'action_speed');
    if (actionSpeed?.value < 100) { // Less than 100ms between actions
      reportSuspicious('Bot-like speed detected');
    }

    // Check for copy-paste patterns
    const pasteEvents = behaviorSignals.find(s => s.name === 'paste_events');
    if (pasteEvents?.value > 5) {
      reportSuspicious('Excessive paste events');
    }
  }, [signals]);

  return (
    <div className="behavior-monitoring">
      <h3>Behavior Analysis Active</h3>
      <p>Monitoring for suspicious activity patterns</p>
    </div>
  );
}

Integration with Authentication

function SecureAuthFlow() {
  const { trustScore, riskLevel, analyzeTrust } = useTrust();
  const { authenticate } = usePasskey();
  const { generateBackupCodes } = useRecovery();

  const [requiresStepUp, setRequiresStepUp] = useState(false);

  const handleSecureAuth = async () => {
    // Step 1: Analyze trust
    const trustResult = await analyzeTrust({
      includeGeolocation: true,
      includeBehavior: true,
      includeNetwork: true
    });

    // Step 2: Determine authentication requirements
    if (trustResult.trustScore < 40) {
      setRequiresStepUp(true);

      // Require backup code verification
      const backupCode = prompt('Enter backup code for verification');
      if (!backupCode) return;

      try {
        await verifyBackupCode(backupCode);
      } catch (err) {
        alert('Invalid backup code');
        return;
      }
    }

    // Step 3: Perform authentication with appropriate security
    const authOptions = {
      userVerification: trustScore < 60 ? 'required' : 'preferred',
      timeout: trustScore < 40 ? 30000 : 60000 // Shorter timeout for risky sessions
    };

    try {
      await authenticate(authOptions);

      // Step 4: Post-auth security measures for risky sessions
      if (riskLevel === 'high') {
        // Generate new backup codes for security
        const codes = await generateBackupCodes();
        console.log('New backup codes generated due to high risk');
      }
    } catch (err) {
      console.error('Authentication failed:', err);
    }
  };

  return (
    <div>
      <div className="security-status">
        <p>Security Level: {riskLevel}</p>
        <p>Trust Score: {trustScore}/100</p>
      </div>

      {requiresStepUp && (
        <div className="alert alert-warning">
          Additional verification required due to security concerns
        </div>
      )}

      <button onClick={handleSecureAuth}>
        Secure Sign In
      </button>
    </div>
  );
}

Security Best Practices

✓ Recommended

  • Always analyze trust before sensitive operations
  • Implement step-up authentication for risky sessions
  • Monitor behavioral patterns continuously
  • Allow users to manage trusted devices
  • Log suspicious activities for audit
  • Use geolocation as additional signal, not primary factor

⚠️ Important

  • Trust scores are probabilistic, not deterministic
  • Device fingerprints can change with browser updates
  • VPN usage doesn't always indicate malicious intent
  • Balance security with user experience

Related Hooks