Docs / API Reference / Authentication

Authentication

NET Backup Vault uses short-lived JWT access tokens and rotating refresh tokens. Every protected endpoint requires an Authorization: Bearer <token> header. This page covers login, MFA, token lifecycle, and credential management.

Overview

All protected endpoints require a Bearer token in the request header. Tokens are issued on login and expire after a short window. Use the refresh endpoint to obtain a new access token without re-authenticating.

Authentication header

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Token lifecycle

Token type Lifetime Use
Access token Short (minutes) Sent in Authorization header for every request
Refresh token Long (days) POST /api/auth/refresh to obtain a new access token
MFA temp token Single use Exchanged for access token after MFA verification

Login

POST /api/auth/login

Authenticates with email and password. Returns JWT tokens on success. If MFA is enabled, returns a mfa_required: true response with a temporary token to be passed to POST /api/mfa/verify.

Request body

Field Type Description
email string User email address
password string User password

Success response (200), no MFA

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refresh_token": "dGhpcyBpcyBhIHJlZnJlc2ggdG9rZW4...",
  "token_type": "bearer"
}

MFA required response (200)

{
  "mfa_required": true,
  "temp_token": "eyJ0ZW1wIjp0cnVlLCJ1c2VyX2lkIjoiLi4uIn0..."
}

cURL example

curl -X POST https://your-netbackupvault-host/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email": "[email protected]", "password": "your-password"}'

Multi-Factor Authentication

NET Backup Vault supports TOTP-based MFA (Google Authenticator, Authy, etc.) and single-use backup codes. MFA is optional per user and can be enabled at any time.

POST /api/mfa/setup Auth required

Initiates MFA enrollment. Returns a TOTP secret and a QR code URI to display in your app. The setup is not active until confirmed with POST /api/mfa/setup/confirm.

Success response (200)

{
  "secret": "JBSWY3DPEHPK3PXP",
  "qr_code_uri": "otpauth://totp/NetBackupVault:[email protected]?secret=JBSWY3DPEHPK3PXP&issuer=NetBackupVault"
}
POST /api/mfa/setup/confirm

Confirms MFA enrollment by verifying a TOTP code from the authenticator app. On success, MFA is active for all future logins.

code string 6-digit TOTP code from the authenticator app
POST /api/mfa/verify

Completes login when MFA is required. Pass the temp_token from the login response alongside the TOTP code. Returns the full LoginResponse with access and refresh tokens.

temp_token Temporary token returned by the login endpoint when mfa_required is true
code 6-digit TOTP code from the authenticator app
POST /api/mfa/verify-backup

Same as /api/mfa/verify but uses a single-use backup code instead of a TOTP code. Each backup code is consumed on use.

Other MFA endpoints

POST
/api/mfa/disable

Disable MFA. Requires current TOTP code to confirm.

POST
/api/mfa/backup-codes/regenerate

Invalidate existing backup codes and generate a fresh set. Requires current TOTP code.

GET
/api/mfa/status

Returns whether MFA is enabled for the current user.

Token Refresh

POST /api/auth/refresh

Exchanges a valid refresh token for a new access token. The refresh token itself is rotated on each use; store the new one returned in the response.

refresh_token The refresh token issued at login or from the previous refresh call
curl -X POST https://your-netbackupvault-host/api/auth/refresh \
  -H "Content-Type: application/json" \
  -d '{"refresh_token": "dGhpcyBpcyBhIHJlZnJlc2ggdG9rZW4..."}'

Current User

GET /api/auth/me Auth required

Returns profile information for the currently authenticated user, including their role, customer association, and Meraki key IDs.

Success response (200)

{
  "id": "uuid",
  "email": "[email protected]",
  "full_name": "Alex Admin",
  "role": "system_admin",
  "customer_id": "uuid",
  "mfa_enabled": true,
  "is_active": true,
  "email_verified": true
}
GET /api/auth/verify-token

Lightweight token validation. Returns HTTP 200 if the Bearer token is valid and not expired. Useful as a health check for frontend session guards.

Logout

POST /api/auth/logout Auth required

Invalidates the current session. Pass the refresh token in the request body to ensure server-side revocation.

refresh_token The refresh token to revoke. Recommended to prevent replay attacks.

Password Management

POST /api/auth/change-password Auth required

Changes the password for the currently authenticated user. Requires the current password for verification.

current_password The user's current password
new_password The new password to set
POST /api/auth/forgot-password

Sends a password reset email if the address exists in the system. Always returns 200 regardless of whether the email exists (to prevent enumeration).

email Email address to send the reset link to
POST /api/auth/reset-password

Resets the password using the token from the reset email link.

token Reset token from the email link
new_password The new password to set

Email Verification

New accounts require email verification before full access is granted. The verification email contains a token that is passed to the verify endpoint.

POST
/api/auth/verify-email

Verify an email address using the token from the verification email. Body: { token: string }.

POST
/api/auth/resend-verification

Resend the verification email for the currently authenticated but unverified user.

GET
/api/auth/verification-status

Check whether the current user's email has been verified.

Error Reference

All errors follow a consistent JSON structure. Validation errors (422) include a detail array describing each invalid field.

Status Meaning
401 Unauthorized Missing or expired Bearer token. Re-authenticate or use the refresh endpoint.
403 Forbidden Valid token but insufficient permissions for the requested resource.
422 Unprocessable Request body or query parameters failed validation. Check the detail array.
429 Too Many Requests Rate limit exceeded on login or password reset endpoints.

Validation error shape

{
  "detail": [
    {
      "loc": ["body", "email"],
      "msg": "value is not a valid email address",
      "type": "value_error.email"
    }
  ]
}