Security

Web Authentication

NetKey uses industry-standard JWT (JSON Web Tokens) with refresh tokens for secure, stateless authentication. This guide covers how authentication works for the web dashboard and API integrations.

Overview

NetKey implements a two-token authentication system following OAuth 2.0 best practices:

Access Token

Short-lived JWT (1 hour) used to authenticate API requests. Stored in memory for security.

Refresh Token

Long-lived token (14-30 days) stored in HttpOnly cookie. Used to obtain new access tokens.

Authentication Flow

1. Login

When a user logs in with username/password:

POST /api/auth/login
{
  "username": "user@example.com",
  "password": "your-password",
  "remember_me": true
}

Response includes:

  • Access token in the JSON response body
  • Refresh token set as an HttpOnly cookie
  • User information (role, group, permissions)
Response
{
  "success": true,
  "token": "eyJhbGciOiJIUzI1NiIs...",
  "expires_in": 3600,
  "user": {
    "id": 1,
    "username": "user@example.com",
    "role": "GROUP_ADMIN",
    "group_id": 3,
    "group_name": "Acme Corp"
  }
}

Set-Cookie: refresh_token=abc123...; HttpOnly; Secure; SameSite=Lax; Max-Age=1209600; Path=/api/auth

2. Using the Access Token

Include the access token in the Authorization header for all API requests:

HTTP Header
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

3. Refreshing the Access Token

When the access token expires (after 1 hour), use the refresh token to get a new one. The refresh token is automatically sent via the HttpOnly cookie.

POST /api/auth/refresh
// No body required - refresh token is in the cookie
fetch('/api/auth/refresh', {
  method: 'POST',
  credentials: 'include'  // Important: sends cookies
});

Response:

Response
{
  "token": "eyJhbGciOiJIUzI1NiIs...",
  "expires_in": 3600
}

Set-Cookie: refresh_token=new_token...; HttpOnly; Secure; ...
Token Rotation

For security, refresh tokens are rotated on each use. The old token is invalidated and a new one is issued.

4. Logout

Logout invalidates both the access token and refresh token:

POST /api/auth/logout
fetch('/api/auth/logout', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer ' + accessToken
  },
  credentials: 'include'
});

Token Details

Access Token (JWT) Payload

The access token is a standard JWT containing:

Claim Description Example
user_id User's unique identifier 3
username User's email/username "user@example.com"
role User's role "GROUP_ADMIN"
group_id User's group ID 3
iat Issued at (Unix timestamp) 1704067200
exp Expiration (Unix timestamp) 1704070800
jti Unique token ID "abc123..."

Token Lifetimes

Token Type Lifetime Storage
Access Token 1 hour Memory / sessionStorage
Refresh Token (default) 14 days HttpOnly cookie
Refresh Token (remember me) 30 days HttpOnly cookie

Security Features

HttpOnly Cookies

Refresh tokens are stored in HttpOnly cookies, preventing JavaScript access and XSS attacks.

Token Rotation

Refresh tokens are rotated on each use, limiting the window for token theft.

Short-lived Access Tokens

Access tokens expire in 1 hour, minimizing exposure if compromised.

Secure Cookie Flags

Cookies use Secure (HTTPS only) and SameSite=Lax flags to prevent CSRF attacks.

No Sensitive Data in localStorage

User profile data is fetched from the API on each session, never stored persistently.

Multi-Factor Authentication

NetKey supports TOTP-based MFA (compatible with Google Authenticator, Authy, etc.). When MFA is enabled, the login flow requires an additional step:

Login with MFA
// Step 1: Initial login returns requires_mfa
{
  "requires_mfa": true,
  "mfa_type": "totp"
}

// Step 2: Submit with TOTP code
POST /api/auth/login
{
  "username": "user@example.com",
  "password": "your-password",
  "totp_code": "123456"
}

API Keys vs JWT

For programmatic access (integrations, scripts, automation), use API Keys instead of JWT tokens. See the API Reference for details.

Feature JWT Tokens API Keys
Use case Web dashboard, user sessions Integrations, automation
Lifetime 1 hour (access) / 14-30 days (refresh) Until revoked
Scope Full user permissions Configurable (read/write)
Header Authorization: Bearer ... X-API-Key: nk_live_...

Error Responses

Status Error Description
401 Invalid credentials Wrong username or password
401 Token expired Access token has expired, use refresh
401 Invalid refresh token Refresh token expired or revoked
403 Account disabled User account has been deactivated
403 MFA required TOTP code needed to complete login