> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nullpass.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Authentication

> Learn how authentication works in Null Pass API

<Warning>
  **Internal Documentation Only:** If you're not a Null Tools developer, you can close this documentation or visit the [Apps section](/apps/coming-soon) to learn more about using Null Pass in your applications.
</Warning>

## Overview

Null Pass uses JWT (JSON Web Tokens) for authentication. After successful registration or login, you'll receive a JWT token that must be included in subsequent API requests.

## Authentication Flow

<Steps>
  <Step title="Register or Login">
    Users register with email and password, or login with existing credentials. If 2FA is enabled, an additional verification step is required.
  </Step>

  <Step title="Receive Token">
    Upon successful authentication, you receive a JWT token. Store this securely in your application.
  </Step>

  <Step title="Include in Requests">
    Include the token in the Authorization header for all protected endpoints:

    ```
    Authorization: Bearer <your_token>
    ```
  </Step>

  <Step title="Token Expiration">
    Tokens expire after 7 days. Implement token refresh logic or prompt users to log in again.
  </Step>
</Steps>

## Token Format

Tokens are standard JWT tokens that contain user information:

```json theme={null}
{
  "userId": "clx1234567890",
  "email": "user@example.com",
  "iat": 1234567890,
  "exp": 1235173890
}
```

<Warning>
  **Never expose tokens in client-side code, URLs, or logs.** Treat tokens as sensitive credentials.
</Warning>

## Two-Factor Authentication

Null Pass supports TOTP (Time-based One-Time Password) for enhanced security. When 2FA is enabled:

1. User logs in with email and password
2. API responds with `requires2FA: true` and a `pendingToken`
3. User provides verification code from authenticator app
4. API validates code and returns full authentication token

<CardGroup cols={2}>
  <Card title="Enable 2FA" icon="shield-check" href="/api-reference/auth/2fa">
    Learn how to enable two-factor authentication
  </Card>

  <Card title="Login with 2FA" icon="key" href="/api-reference/auth/login">
    See how to handle 2FA during login
  </Card>
</CardGroup>

## Session Management

Null Pass tracks user sessions for security and audit purposes. Each login creates a new session that:

* Is tied to the user's IP address (encrypted)
* Expires after 7 days
* Can be viewed and managed via the sessions API

<Card title="Manage Sessions" icon="list" href="/api-reference/auth/sessions">
  View and delete active sessions
</Card>

## Security Best Practices

<AccordionGroup>
  <Accordion title="Store Tokens Securely" icon="lock">
    * Use secure storage (keychain, secure storage, environment variables)
    * Never store tokens in localStorage for sensitive applications
    * Consider using httpOnly cookies for web applications
  </Accordion>

  <Accordion title="Handle Token Expiration" icon="clock">
    * Implement token refresh logic
    * Handle 401 responses gracefully
    * Prompt users to re-authenticate when tokens expire
  </Accordion>

  <Accordion title="Use HTTPS" icon="shield-check">
    * Always use HTTPS in production
    * Never send tokens over unencrypted connections
    * Validate SSL certificates
  </Accordion>

  <Accordion title="Implement Rate Limiting" icon="gauge">
    * Respect rate limits on your end
    * Implement exponential backoff
    * Cache responses where appropriate
  </Accordion>
</AccordionGroup>

## Example: Complete Authentication Flow

<CodeGroup>
  ```javascript JavaScript theme={null}
  class NullPassAuth {
    constructor(apiUrl) {
      this.apiUrl = apiUrl;
      this.token = null;
    }

    async register(email, password, displayName) {
      const response = await fetch(`${this.apiUrl}/auth/register`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ email, password, displayName })
      });
      
      if (!response.ok) {
        const error = await response.json();
        throw new Error(error.error);
      }
      
      const data = await response.json();
      this.token = data.token;
      return data;
    }

    async login(email, password, verificationCode = null) {
      const body = { email, password };
      if (verificationCode) {
        body.verificationCode = verificationCode;
      }

      const response = await fetch(`${this.apiUrl}/auth/login`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(body)
      });
      
      if (!response.ok) {
        const error = await response.json();
        throw new Error(error.error);
      }
      
      const data = await response.json();
      
      if (data.requires2FA) {
        return { requires2FA: true, pendingToken: data.pendingToken };
      }
      
      this.token = data.token;
      return data;
    }

    async getProfile() {
      if (!this.token) {
        throw new Error('Not authenticated');
      }

      const response = await fetch(`${this.apiUrl}/auth/me`, {
        headers: { 'Authorization': `Bearer ${this.token}` }
      });
      
      if (!response.ok) {
        if (response.status === 401) {
          this.token = null; // Token expired
          throw new Error('Authentication required');
        }
        const error = await response.json();
        throw new Error(error.error);
      }
      
      return await response.json();
    }
  }

  // Usage
  const auth = new NullPassAuth('https://auth.nullpass.xyz/api');

  // Register
  try {
    const result = await auth.register('user@example.com', 'password123', 'John Doe');
    console.log('Registered:', result.user);
  } catch (error) {
    console.error('Registration failed:', error.message);
  }

  // Login
  try {
    const result = await auth.login('user@example.com', 'password123');
    if (result.requires2FA) {
      // Prompt for 2FA code
      const code = prompt('Enter 2FA code:');
      const finalResult = await auth.login('user@example.com', 'password123', code);
      console.log('Logged in:', finalResult.user);
    } else {
      console.log('Logged in:', result.user);
    }
  } catch (error) {
    console.error('Login failed:', error.message);
  }

  // Get profile
  try {
    const profile = await auth.getProfile();
    console.log('Profile:', profile.user);
  } catch (error) {
    console.error('Failed to get profile:', error.message);
  }
  ```

  ```python Python theme={null}
  import requests
  from typing import Optional, Dict, Any

  class NullPassAuth:
      def __init__(self, api_url: str):
          self.api_url = api_url
          self.token: Optional[str] = None
      
      def register(self, email: str, password: str, display_name: Optional[str] = None) -> Dict[str, Any]:
          """Register a new user"""
          response = requests.post(
              f"{self.api_url}/auth/register",
              json={
                  "email": email,
                  "password": password,
                  "displayName": display_name
              }
          )
          response.raise_for_status()
          data = response.json()
          self.token = data["token"]
          return data
      
      def login(self, email: str, password: str, verification_code: Optional[str] = None) -> Dict[str, Any]:
          """Login with email and password"""
          body = {"email": email, "password": password}
          if verification_code:
              body["verificationCode"] = verification_code
          
          response = requests.post(
              f"{self.api_url}/auth/login",
              json=body
          )
          response.raise_for_status()
          data = response.json()
          
          if data.get("requires2FA"):
              return {"requires2FA": True, "pendingToken": data["pendingToken"]}
          
          self.token = data["token"]
          return data
      
      def get_profile(self) -> Dict[str, Any]:
          """Get authenticated user profile"""
          if not self.token:
              raise ValueError("Not authenticated")
          
          response = requests.get(
              f"{self.api_url}/auth/me",
              headers={"Authorization": f"Bearer {self.token}"}
          )
          
          if response.status_code == 401:
              self.token = None
              raise ValueError("Authentication required")
          
          response.raise_for_status()
          return response.json()

  # Usage
  auth = NullPassAuth("https://auth.nullpass.xyz/api")

  # Register
  try:
      result = auth.register("user@example.com", "password123", "John Doe")
      print(f"Registered: {result['user']}")
  except Exception as e:
      print(f"Registration failed: {e}")

  # Login
  try:
      result = auth.login("user@example.com", "password123")
      if result.get("requires2FA"):
          code = input("Enter 2FA code: ")
          final_result = auth.login("user@example.com", "password123", code)
          print(f"Logged in: {final_result['user']}")
      else:
          print(f"Logged in: {result['user']}")
  except Exception as e:
      print(f"Login failed: {e}")

  # Get profile
  try:
      profile = auth.get_profile()
      print(f"Profile: {profile['user']}")
  except Exception as e:
      print(f"Failed to get profile: {e}")
  ```
</CodeGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="API Reference" icon="book" href="/api-reference/auth/register">
    Browse all authentication endpoints
  </Card>

  <Card title="Quickstart" icon="rocket" href="/quickstart">
    Follow our step-by-step integration guide
  </Card>
</CardGroup>
