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

# Server-Side Token Generation

> Generate authentication tokens for the ContactsManager SDK

# Server-Side Token Generation

To securely authenticate users with the ContactsManager SDK, you need to generate JWT tokens on your server. This guide explains how to create a secure token generation endpoint.

## Authentication Flow

1. Your app requests a token from your server
2. Your server generates a signed JWT token using your API secret
3. The server returns the token to your app
4. Your app initializes the ContactsManager SDK with the token

This approach keeps your API secret secure by never exposing it in client code.

## Token Structure

The JWT token contains the following claims:

| Claim     | Description                        |
| --------- | ---------------------------------- |
| `org_id`  | Your organization ID               |
| `api_key` | Your ContactsManager API key       |
| `user_id` | The unique identifier for the user |
| `jti`     | A unique token identifier (UUID)   |
| `iat`     | Token issued at timestamp          |
| `exp`     | Token expiration timestamp         |

## Implementation Examples

<Tabs>
  <Tab title="Python">
    <Tip>
      Install the `contactsmanager` package for easy token generation.
    </Tip>

    ```bash theme={null}
    pip install contactsmanager
    ```

    ```python theme={null}
    from contactsmanager import ContactsManagerClient

    # Initialize the client with your API credentials
    client = ContactsManagerClient(
        api_key="your-api-key",
        api_secret="your-api-secret",
        org_id="your-org-id"
    )

    # Generate a token for a user
    token_data = client.generate_token(
        user_id="user-123",
        device_info={"device_name": "iPhone 15", "os_version": "iOS 17.5"},
        expiration_seconds=86400  # 24 hours
    )

    # The token to be used in client SDK initialization
    token = token_data["token"]

    # Example of Flask endpoint that generates tokens
    from flask import Flask, request, jsonify

    app = Flask(__name__)

    @app.route("/generate-token", methods=["POST"])
    def token_endpoint():
        if request.method != "POST":
            return jsonify({
                "message": "Method not allowed",
                "success": False
            }), 405
        
        try:
            # Parse request body
            payload = request.json
            
            # Validate required fields
            if not payload.get("userId"):
                raise ValueError("Missing required field: userId")
            
            # Generate token using the SDK
            token_data = client.generate_token(
                user_id=payload["userId"],
                device_info=payload.get("deviceInfo", {}),
                expiration_seconds=86400  # 24 hours
            )
            
            # Prepare response
            response_data = {
                "token": token_data["token"],
                "expiresAt": token_data["expires_at"],
                "message": f"Token generated for user {payload['userId']}",
                "success": True
            }
            
            return jsonify(response_data), 200
        
        except Exception as e:
            return jsonify({
                "message": f"Error: {str(e)}",
                "success": False
            }), 400

    if __name__ == "__main__":
        app.run(debug=True)
    ```
  </Tab>

  <Tab title="Node.js">
    <Tip>
      Install the `@contactsmanager/server` package for easy token generation.
    </Tip>

    ```bash theme={null}
    npm install @contactsmanager/server
    ```

    ```javascript theme={null}
    const { ContactsManagerClient } = require('@contactsmanager/server');

    // Initialize the client with your API credentials
    const client = new ContactsManagerClient({
      apiKey: 'your-api-key',
      apiSecret: 'your-api-secret',
      orgId: 'your-org-id'
    });

    // Generate a token for a user
    async function generateUserToken(userId, deviceInfo = {}) {
      const tokenData = await client.generateToken({
        userId,
        deviceInfo,
        expirationSeconds: 86400 // 24 hours
      });
      
      // The token to be used in client SDK initialization
      return tokenData.token;
    }

    // Example Express.js endpoint
    const express = require('express');
    const app = express();
    app.use(express.json());

    app.post('/generate-token', async (req, res) => {
      try {
        // Parse request body
        const payload = req.body;
        
        // Validate required fields
        if (!payload.userId) {
          return res.status(400).json({
            message: 'Missing required field: userId',
            success: false
          });
        }
        
        // Generate JWT token using the SDK
        const tokenData = await client.generateToken({
          userId: payload.userId,
          deviceInfo: payload.deviceInfo || {},
          expirationSeconds: 86400 // 24 hours
        });
        
        // Prepare response
        const responseData = {
          token: tokenData.token,
          expiresAt: tokenData.expiresAt,
          message: `Token generated for user ${payload.userId}`,
          success: true
        };
        
        return res.status(200).json(responseData);
      } catch (error) {
        return res.status(400).json({
          message: `Error: ${error.message}`,
          success: false
        });
      }
    });

    const PORT = process.env.PORT || 3000;
    app.listen(PORT, () => {
      console.log(`Server running on port ${PORT}`);
    });
    ```
  </Tab>

  <Tab title="TypeScript (Deno)">
    <Tip>
      The TypeScript (Deno) example can be deployed as a Supabase Edge Function. This serverless approach provides a secure and scalable way to generate tokens without managing traditional server infrastructure.
    </Tip>

    ```typescript theme={null}
    import * as jose from "https://deno.land/x/jose@v4.14.4/index.ts";

    /**
     * Generates a JWT token for user authentication
     * @param userId The user's unique identifier
     * @param deviceInfo Optional device information
     * @returns A signed JWT token
     */
    async function generateToken(userId, deviceInfo = {}) {
      // Get secrets from environment
      const apiKey = Deno.env.get("CM_API_KEY");
      const apiSecret = Deno.env.get("CM_API_SECRET");
      const orgId = Deno.env.get("CM_ORGANIZATION_ID");
      
      if (!apiKey || !apiSecret || !orgId) {
        throw new Error('Missing required environment variables');
      }
      
      // Create a JWT payload
      const now = Math.floor(Date.now() / 1000);
      const payload = {
        org_id: orgId,
        api_key: apiKey,
        user_id: userId,
        device_info: deviceInfo,
        jti: crypto.randomUUID(),
        iat: now,
        exp: now + 86400 // Token valid for 24 hours
      };
      
      // Sign the JWT
      const secretKey = new TextEncoder().encode(apiSecret);
      const token = await new jose.SignJWT(payload)
        .setProtectedHeader({ alg: 'HS256' })
        .sign(secretKey);
        
      return {
        token,
        expires_at: payload.exp
      };
    }

    // Example of a Deno server handler
    Deno.serve(async (req) => {
      // Only allow POST requests
      if (req.method !== 'POST') {
        return new Response(JSON.stringify({
          message: 'Method not allowed',
          success: false
        }), {
          status: 405,
          headers: {
            'Content-Type': 'application/json'
          }
        });
      }
      
      try {
        // Parse the request body
        const payload = await req.json();
        
        // Validate required fields
        if (!payload.userId) {
          throw new Error('Missing required field: userId');
        }
        
        // Generate JWT token
        const tokenData = await generateToken(
          payload.userId, 
          payload.deviceInfo || {}
        );
        
        // Prepare response
        const responseData = {
          token: tokenData.token,
          expires_at: tokenData.expires_at,
          message: `Token generated for user ${payload.userId}`,
          success: true
        };
        
        // Return successful response
        return new Response(JSON.stringify(responseData), {
          status: 200,
          headers: {
            'Content-Type': 'application/json'
          }
        });
      } catch (error) {
        // Handle errors
        return new Response(JSON.stringify({
          message: `Error: ${error.message}`,
          success: false
        }), {
          status: 400,
          headers: {
            'Content-Type': 'application/json'
          }
        });
      }
    });
    ```
  </Tab>
</Tabs>

## Environment Variables

For all implementations, set these environment variables on your server:

| Variable             | Description                     |
| -------------------- | ------------------------------- |
| `CM_API_KEY`         | Your ContactsManager API key    |
| `CM_API_SECRET`      | Your ContactsManager API secret |
| `CM_ORGANIZATION_ID` | Your organization ID            |

## Security Considerations

1. **Keep Your API Secret Secure**: Never expose your API secret in client-side code
2. **Set a Reasonable Expiration Time**: Balance security and user experience
3. **Use HTTPS**: Always use HTTPS for all API endpoints
4. **Validate User ID**: Ensure the user ID is valid before generating a token
5. **Implement Rate Limiting**: Protect your token endpoint from abuse

## Using the Token in your App

Once you have the token from your server, you can use it to initialize the ContactsManager SDK:

<CodeGroup>
  ```swift Swift theme={null}
  // Request token from your server
  let token = await yourApiClient.getToken(for: userId)

  // Initialize the SDK with the token
  try await ContactsService.shared.initialize(
      withAPIKey: "your-api-key",
      token: token,
      userInfo: userInfo
  )
  ```

  ```kotlin Kotlin theme={null}
  // Coming Soon
  ```

  ```objectivec Objective-C theme={null}
  // Coming Soon
  ```

  ```jsx React Native theme={null}
  // Coming Soon
  ```
</CodeGroup>
