Session fingerprinting utilities for preventing session hijacking.
This module provides functions to create and verify session fingerprints based on IP address and user agent data. These fingerprints help detect when a session token is being used from a different location or device than where it was created.
Security Considerations
- IP addresses can change (mobile users, VPNs, etc.), so strict enforcement may impact legitimate users
- User agents can be spoofed, but provide an additional layer of verification
- This is defense-in-depth: fingerprinting complements, not replaces, other security measures
Configuration
You can configure the strictness level in your application config:
config :phoenix_kit,
session_fingerprint_enabled: true,
session_fingerprint_strict: false # true = force re-auth, false = log warningsExamples
# Create a fingerprint from a connection
fingerprint = SessionFingerprint.create_fingerprint(conn)
# Verify a fingerprint
case SessionFingerprint.verify_fingerprint(conn, stored_ip, stored_ua_hash) do
:ok -> # Fingerprint matches
{:warning, :ip_mismatch} -> # IP changed, but might be legitimate
{:warning, :user_agent_mismatch} -> # User agent changed
{:error, :fingerprint_mismatch} -> # Both changed, likely hijacked
end
Summary
Functions
Creates a session fingerprint from a Plug.Conn connection.
Checks if session fingerprinting is enabled in the application config.
Extracts the IP address from a connection.
Extracts and hashes the user agent from a connection.
Checks if strict fingerprint verification is enabled.
Verifies a session fingerprint against the current connection.
Types
Functions
Creates a session fingerprint from a Plug.Conn connection.
Returns a %SessionFingerprint{} struct with :ip_address and :user_agent_hash fields.
Examples
iex> create_fingerprint(conn)
%SessionFingerprint{ip_address: "192.168.1.1", user_agent_hash: "a1b2c3d4..."}
Checks if session fingerprinting is enabled in the application config.
Examples
iex> fingerprinting_enabled?()
true
Extracts the IP address from a connection.
Handles proxied connections by checking X-Forwarded-For and X-Real-IP headers, falling back to the direct connection IP.
Examples
iex> get_ip_address(conn)
"192.168.1.1"
Extracts and hashes the user agent from a connection.
Returns a SHA256 hash of the user agent string for privacy and storage efficiency.
Examples
iex> hash_user_agent(conn)
"a1b2c3d4e5f6..."
Checks if strict fingerprint verification is enabled.
When strict mode is enabled, fingerprint mismatches will force re-authentication. When disabled, mismatches only log warnings.
Examples
iex> strict_mode?()
false
Verifies a session fingerprint against the current connection.
Returns:
:okif fingerprint matches{:warning, :ip_mismatch}if only IP changed{:warning, :user_agent_mismatch}if only user agent changed{:error, :fingerprint_mismatch}if both changed:okif stored fingerprint is nil (backward compatibility)
Examples
iex> verify_fingerprint(conn, "192.168.1.1", "abc123")
:ok
iex> verify_fingerprint(conn, "10.0.0.1", "abc123")
{:warning, :ip_mismatch}