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

# API Link User Token Auth

> Authenticate users directly into Nudj Platform using JWT tokens that encode user metadata

<Info>
  This guide explains how to authenticate users directly into the Nudj Platform using JWT tokens that encode user metadata. This method is suitable for scenarios where users are already authenticated in your platform and you want to pass them into Nudj seamlessly.
</Info>

## Quick Start ✅

<Steps>
  <Step title="Verify Prerequisites">
    Ensure users are already authenticated in your platform and you want to pass them into Nudj without showing a login screen.
  </Step>

  <Step title="Get Credentials">
    Retrieve your credentials from [Developer Settings](https://admin.nudj.cx/admin/settings/organisation?tab=developer):

    * Client ID
    * Client Secret
    * API Token (for alternative method)
  </Step>

  <Step title="Generate User Token">
    Generate a signed JWT containing the user's details (userId, email, locale, etc.) using your clientSecret.
  </Step>

  <Step title="Build Auto-Login URL">
    Create the authentication URL:

    ```
    https://${yourDomain}/api/link?userToken=${userToken}&clientId=${clientId}
    ```
  </Step>

  <Step title="Redirect User">
    Share the link with the user or redirect them to it for instant Nudj login.
  </Step>
</Steps>

## When to Use This Method

<CardGroup cols={2}>
  <Card title="Use This Method" icon="check" color="#0ea5e9">
    * Users are already authenticated in your platform
    * You want seamless session continuation in Nudj
    * No login screen should be shown
    * Single sign-on (SSO) experience required
  </Card>

  <Card title="Don't Use This Method" icon="xmark" color="#ef4444">
    * Users arrive directly at Nudj without authentication
    * Users need to create new accounts
    * OAuth integration is more appropriate
  </Card>
</CardGroup>

<Note>
  If users arrive directly at Nudj without being authenticated, use [OAuth Integration Setup](/enterprise/oauth-authentication) instead.
</Note>

## Detailed Implementation Guide

## 1. Retrieve Your Credentials

Navigate to **Admin Panel → Settings → Organization → Developer Settings** tab and copy your:

<ParamField body="clientId" type="string" required>
  Your unique client identifier
</ParamField>

<ParamField body="clientSecret" type="string" required>
  Your secret key for signing tokens (keep this secure!)
</ParamField>

<ParamField body="apiToken" type="string">
  API token for alternative authentication method (optional)
</ParamField>

<Warning>
  Never expose your Client Secret in client-side code or public repositories. Always generate tokens on your backend server.
  Note: Nudj stores organization-level credentials. In your application, load secrets securely (e.g., environment variables or a secret manager), never from client code.
</Warning>

## 2. Generate the User Token

<CodeGroup>
  ```javascript JavaScript theme={null}
  import { sign } from "jsonwebtoken";
  import { randomUUID } from "crypto";

  const userData = {
    userId: "abc123", // Unique identifier for the user
    email: "abc123@example.com", // User's email
    locale: "en", // Optional locale, defaults to "en" if not provided
    username: "John Doe", // Optional display name
    points: 100, // Optional initial points (only for new users)
  };

  function signUserToken(input) {
    const clientSecret = process.env.NUDJ_CLIENT_SECRET;
    if (!clientSecret) {
      throw new Error("NUDJ_CLIENT_SECRET is not set");
    }
    
    const now = Math.floor(Date.now() / 1000);
    const claims = {
      ...input,
      iss: "your-app", // Issuer
      aud: "nudj", // Audience
      iat: now, // Issued at
      nbf: now, // Not before
      jti: randomUUID(), // JWT ID for tracking
    };
    
    return sign(claims, clientSecret, { 
      algorithm: "HS256",
      expiresIn: "1h"
    });
  }

  const userToken = signUserToken(userData);
  // Never log tokens in production - store or use securely
  ```

  ```python Python theme={null}
  import jwt
  from datetime import datetime, timedelta
  import os
  import uuid

  user_data = {
      "userId": "abc123",  # Unique identifier for the user
      "email": "abc123@example.com",  # User's email
      "locale": "en",  # Optional locale, defaults to "en"
      "username": "John Doe",  # Optional display name
      "points": 100,  # Optional initial points
  }

  def sign_user_token(payload):
      client_secret = os.environ.get('NUDJ_CLIENT_SECRET')
      if not client_secret:
          raise ValueError("NUDJ_CLIENT_SECRET is not set")
      
      now = datetime.utcnow()
      claims = {
          **payload,
          "iss": "your-app",  # Issuer
          "aud": "nudj",  # Audience
          "iat": now,  # Issued at
          "nbf": now,  # Not before
          "exp": now + timedelta(hours=1),  # Expiry
          "jti": str(uuid.uuid4()),  # JWT ID for tracking
      }
      
      return jwt.encode(claims, client_secret, algorithm='HS256')

  user_token = sign_user_token(user_data)
  # Never log tokens in production - store or use securely
  ```

  ```typescript TypeScript theme={null}
  import { sign } from "jsonwebtoken";
  import { randomUUID } from "node:crypto";

  interface UserData {
    userId: string;
    email?: string;
    locale?: string;
    username?: string;
    anonymousAccountId?: string;
    points?: number; // Initial points for new users
  }

  function signUserToken(input: UserData): string {
    const clientSecret = process.env.NUDJ_CLIENT_SECRET;
    if (!clientSecret) {
      throw new Error("NUDJ_CLIENT_SECRET is not set");
    }
    
    const now = Math.floor(Date.now() / 1000);
    const claims = {
      ...input,
      iss: "your-app", // Issuer
      aud: "nudj", // Audience
      iat: now, // Issued at
      nbf: now, // Not before
      jti: randomUUID(), // JWT ID for tracking
    };
    
    return sign(claims, clientSecret, { 
      algorithm: "HS256",
      expiresIn: "1h",
      keyid: process.env.NUDJ_CLIENT_KID, // Optional key ID
    });
  }

  const userData: UserData = {
    userId: "abc123",
    email: "abc123@example.com",
    locale: "en",
    points: 100, // Optional initial points
  };

  const userToken = signUserToken(userData);
  // Never log tokens in production - store or use securely
  ```
</CodeGroup>

## 3. Build the Auto-Login URL

You can use either the **User Token method** (recommended) or the **API Token method**:

<Tabs>
  <Tab title="User Token Method (Recommended)">
    ```javascript theme={null}
    const domain = "yourcompany.nudj.cx"; // Your Nudj domain
    const clientId = process.env.NUDJ_CLIENT_ID; // Your Client ID

    // Use URL constructor for proper encoding
    const url = new URL(`https://${domain}/api/link`);
    url.searchParams.set('userToken', userToken);
    url.searchParams.set('clientId', clientId);

    // Optional: Add callback path (must be a relative path starting with /)
    url.searchParams.set('callbackPath', '/dashboard');

    const linkUrl = url.toString();

    // Server-side redirect (REQUIRED for security)
    res.redirect(linkUrl);
    ```
  </Tab>

  <Tab title="API Token Method (Alternative)">
    ```javascript theme={null}
    const domain = "yourcompany.nudj.cx"; // Your Nudj domain
    const apiToken = process.env.NUDJ_API_TOKEN; // Your API Token

    // Build URL with individual parameters
    const params = new URLSearchParams({
      apiToken: apiToken,
      userId: "abc123",
      email: "user@example.com",
      locale: "en",
      username: "John Doe"
    });

    const linkUrl = `https://${domain}/api/link?${params.toString()}`;

    // Server-side redirect (REQUIRED for security)
    res.redirect(linkUrl);
    ```
  </Tab>
</Tabs>

<Warning>
  **Critical Security Warning**: Never put JWTs or API tokens in frontend redirects using `window.location.href` as this exposes sensitive credentials in browser history, logs, and referrer headers. Always use server-side redirects (`res.redirect()`) to transmit signed tokens. If client-side navigation is absolutely required, implement a secure token exchange flow using short-lived authorization codes instead of exposing JWTs directly.
</Warning>

<Note>
  **Security Note**: The `callbackPath` parameter must be a relative path starting with `/` and will be validated against an allowlist on the server to prevent open-redirect vulnerabilities. Full URLs or paths missing the leading slash will be rejected.
</Note>

## 4. User Property Requirements

<ResponseField name="userId" type="string" required>
  Unique identifier for the user. This is stored as `externalId` in Nudj and used for account identification.
</ResponseField>

<ResponseField name="email" type="string">
  User's email address. Must be unique per user. If omitted, Nudj generates a placeholder email in the format `${userId}@${organisationId}.com` and the user can only log in via direct links (no magic link/self-login).
</ResponseField>

<ResponseField name="locale" type="string">
  Language/region code (e.g., `en`, `fr`, `es`). Defaults to `en` if not provided.
</ResponseField>

<ResponseField name="username" type="string">
  Display name shown in Nudj UI. Defaults to "anonymous" until updated by the user.
</ResponseField>

<ResponseField name="anonymousAccountId" type="string">
  Special identifier provided by Nudj to merge an anonymous session with the authenticated user account. Used for preserving user progress before authentication. This ID is typically available in the session or URL parameters when anonymous login features are enabled.
</ResponseField>

<ResponseField name="points" type="number">
  Initial points to award the user upon account creation. Only applied for new users, not updates. Creates a points transaction record automatically.
</ResponseField>

## How It Works

## Account Creation & Management

<Tabs>
  <Tab title="New Users">
    When a user doesn't exist in Nudj:

    1. Nudj receives the signed JWT token
    2. Validates the token signature using your Client Secret
    3. Creates a new account with provided details
    4. Awards initial points if specified (creates transaction record)
    5. Automatically signs the user in
    6. User lands in Nudj fully authenticated
  </Tab>

  <Tab title="Existing Users">
    When a user already exists:

    1. Nudj identifies the user by `userId` (externalId)
    2. Updates any changed properties (locale, username)
    3. Signs the user into their existing account
    4. Preserves all user progress and data
  </Tab>

  <Tab title="Anonymous Merge">
    When merging anonymous sessions:

    1. User starts as anonymous visitor (requires `AnonymousLogin` feature flag)
    2. Nudj provides `anonymousAccountId` in session/URL
    3. Include this ID when authenticating
    4. Nudj merges anonymous progress with authenticated account
    5. User retains all activity from before login

    <Note>
      Anonymous account merging requires the `AnonymousLogin` and `anonymous-account-conversion` feature flags to be enabled for your organization.
    </Note>
  </Tab>
</Tabs>

## Example Implementation Flow

<Steps>
  <Step title="User Login">
    User logs into your platform using your existing authentication system.
  </Step>

  <Step title="Token Generation">
    Your backend generates a signed JWT with the user's information.
  </Step>

  <Step title="URL Construction">
    Your system builds the Nudj authentication URL with the token and client ID.
  </Step>

  <Step title="Redirect">
    User is redirected to the Nudj URL either automatically or via a button/link.
  </Step>

  <Step title="Seamless Access">
    User lands in Nudj fully signed in with no login screen shown.
  </Step>
</Steps>

## Environment Configuration

The API Link authentication works across multiple Nudj applications:

<Tabs>
  <Tab title="Production">
    ```javascript theme={null}
    const config = {
      domain: "yourcompany.nudj.cx",
      endpoint: "/api/link",
      protocol: "https"
    };
    ```
  </Tab>

  <Tab title="Staging">
    ```javascript theme={null}
    const config = {
      domain: "yourcompany-staging.nudj.cx",
      endpoint: "/api/link",
      protocol: "https"
    };
    ```
  </Tab>

  <Tab title="Development">
    ```javascript theme={null}
    const config = {
      domain: "localhost:3000", // or localhost:4000 for admin
      endpoint: "/api/link",
      protocol: "http"
    };
    ```
  </Tab>
</Tabs>

<Note>
  The `/api/link` endpoint is available in multiple Nudj applications:

  * **user** app (port 3000)
  * **admin** app (port 4000)
  * **creator-frontend** app
  * **api** service

  All applications share the same authentication logic and user database.
</Note>

## Complete Integration Example

Here's a full example of implementing API Link authentication in an Express.js application:

```javascript theme={null}
import express from 'express';
import { sign } from 'jsonwebtoken';

const app = express();

// Middleware to check if user is authenticated in your system
function requireAuth(req, res, next) {
  if (!req.session.user) {
    return res.redirect('/login');
  }
  next();
}

// Route to redirect authenticated users to Nudj
app.get('/nudj-redirect', requireAuth, (req, res) => {
  const { user } = req.session;
  
  // Prepare user data for Nudj
  const nudjUserData = {
    userId: user.id,
    email: user.email,
    username: user.displayName,
    locale: user.preferredLanguage || 'en'
  };
  
  // Sign the token
  const userToken = sign(
    nudjUserData,
    process.env.NUDJ_CLIENT_SECRET,
    { expiresIn: '1h' }
  );
  
  // Build the Nudj URL
  const nudjDomain = process.env.NUDJ_DOMAIN; // e.g., "yourcompany.nudj.cx"
  const clientId = process.env.NUDJ_CLIENT_ID;
  const nudjUrl = `https://${nudjDomain}/api/link?userToken=${userToken}&clientId=${clientId}`;
  
  // Redirect user to Nudj
  res.redirect(nudjUrl);
});

app.listen(3000, () => {
  console.log('Server running on port 3000');
});
```

## Error Responses

The `/api/link` endpoint returns specific HTTP status codes for different error conditions:

| Status Code | Error                 | Description                              |
| ----------- | --------------------- | ---------------------------------------- |
| `401`       | Unauthorized          | Missing or invalid token/credentials     |
| `403`       | Forbidden             | Valid token but insufficient permissions |
| `404`       | Not Found             | Domain or organization not found         |
| `422`       | Unprocessable Entity  | Invalid user data or parameters          |
| `500`       | Internal Server Error | Server-side processing error             |

Example error response:

```json theme={null}
{
  "error": "Invalid token",
  "message": "The provided user token could not be validated",
  "code": "INVALID_TOKEN"
}
```

## Security Best Practices

<Warning>
  Always follow these security guidelines when implementing API Link authentication:
</Warning>

<AccordionGroup>
  <Accordion title="Token Security">
    * Generate tokens only on your backend server
    * Never expose Client Secret in client-side code
    * Use environment variables for sensitive credentials
    * Set appropriate token expiration times (1 hour recommended)
    * Rotate Client Secrets periodically
    * Note: Organizations can have multiple Client Secrets configured
  </Accordion>

  <Accordion title="Data Validation">
    * Validate user data before token generation
    * Ensure userId is unique and consistent
    * Sanitize email addresses and usernames
    * Handle missing optional fields gracefully
    * Verify email format if provided
  </Accordion>

  <Accordion title="Error Handling">
    * Implement proper error handling for token generation failures
    * Provide fallback authentication methods
    * Log authentication attempts for security monitoring
    * Handle expired tokens gracefully
    * Implement retry logic with exponential backoff
  </Accordion>

  <Accordion title="CORS & Security Headers">
    * Configure CORS to allow your domains
    * Implement CSRF protection for session management
    * Use HTTPS for all authentication requests
    * Set appropriate security headers
  </Accordion>
</AccordionGroup>

## Troubleshooting

<AccordionGroup>
  <Accordion title="Token Generation Fails">
    **Problem**: JWT signing throws an error

    **Solutions**:

    * Verify Client Secret is correctly set in environment variables
    * Check that the jsonwebtoken library is properly installed
    * Ensure user data object has all required fields
    * Validate that expiration time is properly formatted
  </Accordion>

  <Accordion title="User Not Authenticated in Nudj">
    **Problem**: User is redirected but sees login screen

    **Solutions**:

    * Verify the token is properly URL-encoded in the link
    * Check that clientId matches your Nudj configuration
    * Ensure token hasn't expired (check expiration time)
    * Validate domain matches your Nudj instance
  </Accordion>

  <Accordion title="User Data Not Updated">
    **Problem**: Changes to user properties don't reflect in Nudj

    **Solutions**:

    * Ensure userId remains consistent (it's the primary identifier)
    * Check that updated fields are included in the token
    * Verify token signature is valid
    * Clear browser cache and try again
  </Accordion>

  <Accordion title="Anonymous Session Not Merged">
    **Problem**: User loses progress after authentication

    **Solutions**:

    * Include the anonymousAccountId provided by Nudj
    * Ensure the ID is passed correctly in the token
    * Check timing - merge must happen during authentication
    * Contact Nudj support if issue persists
  </Accordion>
</AccordionGroup>

## API Reference

For detailed API documentation and additional authentication methods, see:

<CardGroup cols={2}>
  <Card title="Authentication Guide" icon="lock" href="/api-reference/authentication">
    Complete guide to all Nudj authentication methods
  </Card>

  <Card title="OAuth Integration" icon="shield" href="/enterprise/oauth-authentication">
    Set up OAuth providers for direct login
  </Card>

  <Card title="API Authentication" icon="key" href="/api-reference/authentication">
    Get API tokens and pick an auth method
  </Card>

  <Card title="Integration API Docs" icon="code" href="/api-reference/integration/overview">
    Full Integration API reference
  </Card>
</CardGroup>

## Support

If you encounter any issues or need assistance with implementation:

* **Technical Support**: Contact your Nudj account manager
* **Documentation**: Visit [docs.nudj.cx](https://docs.nudj.cx)
* **API Status**: Check [status.nudj.cx](https://status.nudj.cx)
* **Community**: Join the Nudj Developer Community
