Skip to main content
Snipe-IT provides comprehensive security features to protect your asset management data. This page covers authentication mechanisms, access control, and security hardening.

Authentication Methods

Snipe-IT supports multiple authentication methods:
  • Local Authentication - Built-in username/password authentication
  • LDAP/Active Directory - Integration with directory services
  • SAML 2.0 - Single Sign-On with enterprise identity providers
  • Two-Factor Authentication (2FA) - TOTP-based second factor

Local Authentication

Users are authenticated against the users table using Laravel’s built-in authentication system (configured in config/auth.php:16-19):
'defaults' => [
    'guard' => 'web',
    'passwords' => 'users',
],
Passwords are hashed using bcrypt by default, with configurable work factor:
.env
HASHING_DRIVER=bcrypt
BCRYPT_ROUNDS=10
Increasing BCRYPT_ROUNDS makes password hashing more computationally expensive, providing better protection against brute-force attacks at the cost of slower authentication.
Alternatively, use Argon2 for password hashing:
.env
HASHING_DRIVER=argon2
ARGON_MEMORY=1024
ARGON_THREADS=2
ARGON_TIME=2

Login Throttling

Protect against brute-force attacks with login throttling:
.env
# Maximum login attempts before lockout
LOGIN_MAX_ATTEMPTS=5

# Lockout duration in seconds
LOGIN_LOCKOUT_DURATION=60

# Disable autocomplete on login form (security compliance)
LOGIN_AUTOCOMPLETE=false
LOGIN_MAX_ATTEMPTS
integer
default:"5"
Number of failed login attempts before the account is temporarily locked.
LOGIN_LOCKOUT_DURATION
integer
default:"60"
Duration in seconds that the account remains locked after exceeding max attempts.
LOGIN_AUTOCOMPLETE
boolean
default:"false"
Enable browser autocomplete on the login form. Set to false for security compliance.
Throttle configuration is defined in config/auth.php:101-104:
'throttle' => [
    'max_attempts' => env('LOGIN_MAX_ATTEMPTS', 5),
    'lockout_duration' => env('LOGIN_LOCKOUT_DURATION', 60),
]

Password Reset Security

.env
# Password reset link expiration (in minutes)
RESET_PASSWORD_LINK_EXPIRES=15

# Password confirmation timeout (in seconds)
PASSWORD_CONFIRM_TIMEOUT=10800

# Max password reset attempts per minute
PASSWORD_RESET_MAX_ATTEMPTS_PER_MIN=50

# Invitation link expiration (in minutes)
INVITE_PASSWORD_LINK_EXPIRES=1500
How many minutes before a password reset link expires (default: 15 minutes).
PASSWORD_CONFIRM_TIMEOUT
integer
default:"10800"
How many seconds before requiring password re-confirmation for sensitive actions (default: 3 hours).
PASSWORD_RESET_MAX_ATTEMPTS_PER_MIN
integer
default:"50"
Rate limit for password reset requests per minute.

Two-Factor Authentication (2FA)

Snipe-IT implements TOTP (Time-based One-Time Password) 2FA using the Google2FA package.

Enabling 2FA

Two-factor authentication can be:
  1. Optionally enabled by individual users
  2. Enforced globally for all users (via Settings > Security)
  3. Enforced for specific users (via user edit)

2FA Configuration

Configure 2FA settings in .env:
.env
# Enable/disable 2FA globally
OTP_ENABLED=true

# 2FA session lifetime (0 = eternal)
OTP_LIFETIME=0

# Keep 2FA session alive on new requests
OTP_KEEP_ALIVE=true

# Throw exceptions on 2FA errors
OTP_THROW_EXCEPTION=true
These settings are defined in config/google2fa.php:8-75.
OTP_ENABLED
boolean
default:"true"
Master switch for 2FA functionality. Set to false to completely disable 2FA.
OTP_LIFETIME
integer
default:"0"
How long (in minutes) before users must re-enter their 2FA code. 0 means eternal - users only authenticate once per session.
OTP_KEEP_ALIVE
boolean
default:"true"
Renew the 2FA session lifetime on each request. When true, users stay authenticated as long as they’re active.

Setting Up 2FA as a User

  1. Click on your name in the top-right corner
  2. Select Account Settings
  3. Go to the Security tab
  4. Click Enable Two-Factor Authentication
  5. Scan the QR code with an authenticator app (Google Authenticator, Authy, 1Password, etc.)
  6. Enter the 6-digit code to confirm
  7. Save your recovery codes in a secure location

Enforcing 2FA for All Users

As an administrator:
  1. Navigate to Settings > Security
  2. Enable Require Two-Factor Authentication
  3. Save settings
Users without 2FA enrolled will be redirected to the enrollment page on next login.

2FA Implementation Details

The 2FA workflow is implemented in app/Http/Controllers/Auth/LoginController.php:398-437:
public function getTwoFactorAuth()
{
    // Display 2FA code entry form
}

public function postTwoFactorAuth(Request $request)
{
    $user = auth()->user();
    $secret = $request->input('two_factor_secret');
    
    if (Google2FA::verifyKey($user->two_factor_secret, $secret)) {
        // Mark 2FA as verified for this session
        session(['google2fa' => true]);
        return redirect()->intended('/');
    }
    
    return redirect()->back()->withErrors(['two_factor_secret' => 'Invalid authentication code']);
}

Resetting User 2FA

Administrators can reset a user’s 2FA if they lose access to their authenticator:
  1. Navigate to People > Users
  2. Edit the user
  3. Click Reset Two-Factor Authentication
  4. Confirm the reset
This action is logged in the activity log (app/Http/Controllers/Api/UsersController.php:828).

2FA Permissions

Users need the self.two_factor permission to manage their own 2FA settings (config/permissions.php:452-453):
[
    'permission' => 'self.two_factor',
    'display'    => true,
],

API Authentication

Snipe-IT uses Laravel Passport for OAuth2-based API authentication.

API Token Expiration

.env
API_TOKEN_EXPIRATION_YEARS=15
API_TOKEN_EXPIRATION_YEARS
integer
default:"15"
How many years before API personal access tokens expire.
Configured in config/passport.php:16:
'expiration_years' => env('API_TOKEN_EXPIRATION_YEARS', 20),

Generating API Tokens

Users can generate personal API tokens:
  1. Go to Account Settings
  2. Click the API Tokens tab
  3. Click Create New Token
  4. Give the token a name (e.g., “Mobile App”, “Automation Script”)
  5. Copy the token immediately - it won’t be shown again
API tokens have the same permissions as the user who created them. Create dedicated service accounts with limited permissions for API integrations.

Using API Tokens

Include the token in the Authorization header:
curl -H "Authorization: Bearer YOUR_TOKEN_HERE" \
     https://snipeit.company.com/api/v1/hardware

API Rate Limiting

Protect your API from abuse with rate limiting:
.env
API_THROTTLE_PER_MINUTE=120
API_THROTTLE_PER_MINUTE
integer
default:"120"
Maximum API requests allowed per minute per IP address.
When the limit is exceeded, the API returns a 429 Too Many Requests response.

API Token Permissions

The self.api permission controls whether users can create their own API tokens (config/permissions.php:457-459):
[
    'permission' => 'self.api',
    'display'    => true,
],
Disable this permission to prevent non-admin users from generating API tokens.

CSRF Protection

Cross-Site Request Forgery (CSRF) protection is enabled by default for all POST, PUT, PATCH, and DELETE requests.

CSRF Configuration

The VerifyCsrfToken middleware is automatically applied to all web routes (app/Http/Middleware/VerifyCsrfToken.php).
API routes (under /api/*) are exempt from CSRF protection as they use token-based authentication.

CSRF Token in Forms

Blade templates automatically include CSRF tokens:
<form method="POST" action="/assets">
    @csrf
    <!-- form fields -->
</form>
For AJAX requests, include the token in the request headers:
$.ajaxSetup({
    headers: {
        'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
    }
});

Content Security Policy (CSP)

Enable CSP to mitigate XSS attacks:
.env
# Enable Content Security Policy
ENABLE_CSP=true

# Additional allowed CSP URLs (comma-separated)
ADDITIONAL_CSP_URLS=https://fonts.googleapis.com,https://cdn.example.com
ENABLE_CSP
boolean
default:"false"
Enable Content Security Policy headers. Test thoroughly before enabling in production.
ADDITIONAL_CSP_URLS
string
Comma-separated list of additional URLs to whitelist in the CSP policy (e.g., CDNs, external fonts).
Enabling CSP can break functionality if not configured correctly. Test in a development environment first and add necessary exceptions to ADDITIONAL_CSP_URLS.

Security Headers

Configure additional security headers:
.env
# Prevent framing (clickjacking protection)
ALLOW_IFRAMING=false

# Referrer policy
REFERRER_POLICY=same-origin

# Enable HTTP Strict Transport Security (HTTPS only)
ENABLE_HSTS=false

# Trusted proxy IPs (for load balancers)
APP_TRUSTED_PROXIES=192.168.1.1,10.0.0.1

# CORS allowed origins
CORS_ALLOWED_ORIGINS=https://app.company.com,https://mobile.company.com
ALLOW_IFRAMING
boolean
default:"false"
Allow Snipe-IT to be embedded in iframes. Keep false to prevent clickjacking attacks.
REFERRER_POLICY
string
default:"same-origin"
Controls how much referrer information is sent with requests. Options: no-referrer, same-origin, strict-origin, etc.
ENABLE_HSTS
boolean
default:"false"
Enable HTTP Strict Transport Security, forcing browsers to only use HTTPS.Only enable if you have a valid SSL certificate and all traffic is HTTPS.
APP_TRUSTED_PROXIES
string
Comma-separated list of trusted proxy IP addresses (load balancers, reverse proxies).Required for correct IP detection when behind a proxy.
CORS_ALLOWED_ORIGINS
string
Comma-separated list of origins allowed to make cross-origin requests to your API.

Session Security

Configure secure session handling:
.env
# Session driver (file, database, redis, memcached)
SESSION_DRIVER=file

# Session lifetime (in minutes)
SESSION_LIFETIME=12000

# Expire session on browser close
EXPIRE_ON_CLOSE=false

# Encrypt session data
ENCRYPT=false

# Session cookie name
COOKIE_NAME=snipeit_session

# Cookie domain (null for current domain)
COOKIE_DOMAIN=null

# Require HTTPS for cookies (enable in production with SSL)
SECURE_COOKIES=false
SESSION_DRIVER
string
default:"file"
Where to store session data. Options: file, database, redis, memcached.Use redis or memcached for multi-server deployments.
SESSION_LIFETIME
integer
default:"12000"
Session lifetime in minutes (12000 = ~8 days).
SECURE_COOKIES
boolean
default:"false"
Only transmit cookies over HTTPS. Enable this in production with SSL.
Set SECURE_COOKIES=true when using HTTPS to prevent session hijacking. Do not enable if you don’t have SSL configured.

Encrypted Custom Fields

Sensitive custom field data can be encrypted at rest: When creating a custom field, enable the Encrypt Field option. The data is encrypted using your APP_KEY.
Critical: If you lose or change your APP_KEY, all encrypted data becomes permanently unrecoverable. Store your APP_KEY securely and include it in backups.
Encryption is handled in app/Models/CustomField.php:389-396:
public function isFieldDecryptable($string)
{
    if (($this->field_encrypted == '1') && ($string != '')) {
        return true;
    }
    return false;
}
The permission assets.view.encrypted_custom_fields controls who can view encrypted field values.

Permission System

Snipe-IT uses a granular permission system defined in config/permissions.php.

Permission Structure

Permissions follow the pattern: {resource}.{action} Examples:
  • assets.view - View assets
  • assets.create - Create assets
  • assets.edit - Edit assets
  • assets.delete - Delete assets
  • assets.checkout - Checkout assets
  • assets.checkin - Checkin assets

Role Hierarchy

  1. Superuser - Full access to everything, bypasses all permission checks
  2. Admin - Administrative access to most features
  3. Custom Roles - Granular permission assignments

Managing Roles and Permissions

  1. Navigate to People > Permissions
  2. Click Create New to create a custom role
  3. Select the specific permissions to grant
  4. Assign users to the role
Or edit a user directly and select their role:
  1. Go to People > Users
  2. Edit the user
  3. Select their Permission Group
  4. Save

Security Best Practices

Enable 2FA for all admins - Require two-factor authentication for all users with administrative permissions.
Use strong APP_KEY - Generate a secure random key using php artisan key:generate. Never share or commit your .env file.
Enable HTTPS - Always use SSL/TLS in production. Set SECURE_COOKIES=true and APP_FORCE_TLS=true.
Limit API access - Only grant API token permissions to users who need it. Use service accounts with minimal permissions for integrations.
Regular security updates - Keep Snipe-IT updated to the latest version to receive security patches.
Audit user permissions - Regularly review user roles and permissions to ensure least privilege access.
Monitor login attempts - Review failed login attempts in the activity log to detect potential attacks.
Backup encryption keys - Include .env in your backup strategy (stored securely!) to ensure you can recover encrypted data.

SAML Authentication

For enterprise Single Sign-On:
.env
# Require SAML authentication (disable local login)
REQUIRE_SAML=false

# SAML key size
SAML_KEY_SIZE=2048
REQUIRE_SAML
boolean
default:"false"
When enabled, all users must authenticate via SAML. Local authentication is disabled.
SAML configuration is done through the web interface at Settings > SAML.

Application Security

Force TLS/HTTPS

.env
# Force all requests to use HTTPS
APP_FORCE_TLS=false

# Allow connections to hosts with invalid/self-signed certificates (dev only!)
APP_ALLOW_INSECURE_HOSTS=false
APP_FORCE_TLS
boolean
default:"false"
Redirect all HTTP requests to HTTPS. Only enable if SSL is properly configured.
APP_ALLOW_INSECURE_HOSTS
boolean
default:"false"
Allow insecure SSL connections (self-signed certificates). Never enable in production.

Application Lock

.env
# Lock the application (maintenance mode)
APP_LOCKED=false
When true, the application is locked and shows a maintenance page to all users except super admins.

Troubleshooting

”CSRF Token Mismatch” Error

Causes:
  • Session expired
  • Session driver misconfigured
  • Proxy/load balancer not forwarding headers correctly
Solution:
  • Add proxy IPs to APP_TRUSTED_PROXIES
  • Check session configuration
  • Clear browser cookies

Users Can’t Enable 2FA

Check:
  • OTP_ENABLED=true in .env
  • User has self.two_factor permission
  • Server time is synchronized (TOTP is time-based)

API Returns 401 Unauthorized

Verify:
  • Token is included in Authorization: Bearer {token} header
  • Token hasn’t expired
  • User account is active and not locked

Next Steps

Configuration

Configure environment and application settings

Backups

Set up secure backup procedures

Users

Manage users and permissions

API Documentation

Secure API integration guide

Build docs developers (and LLMs) love