CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-pusher-js

Pusher Channels JavaScript library for browsers, React Native, NodeJS and web workers

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

authentication.mddocs/

Authentication

Authentication and authorization system for private channels, presence channels, and user authentication with customizable auth handlers.

Capabilities

Channel Authorization Options

Configuration for private and presence channel authentication.

/**
 * Channel authorization configuration
 */
interface ChannelAuthorizationOptions {
  transport: 'ajax' | 'jsonp';
  endpoint: string;
  params?: any;
  headers?: any;
  paramsProvider?: () => any;
  headersProvider?: () => any;
  customHandler?: ChannelAuthorizationHandler;
}

/**
 * Channel authorization request parameters
 */
interface ChannelAuthorizationRequestParams {
  socketId: string;
  channelName: string;
}

/**
 * Channel authorization response data
 */
interface ChannelAuthorizationData {
  auth: string;
  channel_data?: string;
  shared_secret?: string;
}

/**
 * Channel authorization callback function
 */
type ChannelAuthorizationCallback = (
  error: Error | null,
  authData: ChannelAuthorizationData | null
) => void;

/**
 * Custom channel authorization handler
 */
interface ChannelAuthorizationHandler {
  (params: ChannelAuthorizationRequestParams, callback: ChannelAuthorizationCallback): void;
}

Channel Authorization Examples:

// Basic endpoint authorization
const pusher = new Pusher("app-key", {
  cluster: "us2",
  channelAuthorization: {
    endpoint: "/pusher/auth",
    transport: "ajax"
  }
});

// Authorization with custom headers and parameters
const pusher = new Pusher("app-key", {
  cluster: "us2",
  channelAuthorization: {
    endpoint: "/api/pusher/auth",
    transport: "ajax",
    headers: {
      "X-CSRF-Token": "csrf-token",
      "Authorization": "Bearer token"
    },
    params: {
      userId: "123"
    }
  }
});

// Dynamic headers and parameters
const pusher = new Pusher("app-key", {
  cluster: "us2",
  channelAuthorization: {
    endpoint: "/pusher/auth",
    transport: "ajax",
    headersProvider: () => ({
      "Authorization": `Bearer ${getCurrentToken()}`,
      "X-User-ID": getCurrentUserId()
    }),
    paramsProvider: () => ({
      timestamp: Date.now(),
      nonce: generateNonce()
    })
  }
});

// Custom authorization handler
const pusher = new Pusher("app-key", {
  cluster: "us2",
  channelAuthorization: {
    endpoint: "/pusher/auth", // Still required but not used
    transport: "ajax",
    customHandler: (params, callback) => {
      // Custom authorization logic
      fetch("/api/custom-auth", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          socket_id: params.socketId,
          channel_name: params.channelName,
          user_id: getCurrentUserId()
        })
      })
      .then(response => response.json())
      .then(data => callback(null, data))
      .catch(error => callback(error, null));
    }
  }
});

User Authentication Options

Configuration for user authentication in presence channels.

/**
 * User authentication configuration
 */
interface UserAuthenticationOptions {
  transport: 'ajax' | 'jsonp';
  endpoint: string;
  params?: any;
  headers?: any;
  paramsProvider?: () => any;
  headersProvider?: () => any;
  customHandler?: UserAuthenticationHandler;
}

/**
 * User authentication request parameters
 */
interface UserAuthenticationRequestParams {
  socketId: string;
}

/**
 * User authentication response data
 */
interface UserAuthenticationData {
  auth: string;
  user_data: string;
}

/**
 * User authentication callback function
 */
type UserAuthenticationCallback = (
  error: Error | null,
  authData: UserAuthenticationData | null
) => void;

/**
 * Custom user authentication handler
 */
interface UserAuthenticationHandler {
  (params: UserAuthenticationRequestParams, callback: UserAuthenticationCallback): void;
}

User Authentication Examples:

// Basic user authentication
const pusher = new Pusher("app-key", {
  cluster: "us2",
  userAuthentication: {
    endpoint: "/pusher/user-auth",
    transport: "ajax"
  }
});

// User authentication with custom data
const pusher = new Pusher("app-key", {
  cluster: "us2",
  userAuthentication: {
    endpoint: "/api/pusher/user-auth",
    transport: "ajax",
    headers: {
      "Authorization": "Bearer user-token"
    },
    params: {
      user_id: "user-123"
    }
  }
});

// Custom user authentication handler
const pusher = new Pusher("app-key", {
  cluster: "us2",
  userAuthentication: {
    endpoint: "/pusher/user-auth",
    transport: "ajax",
    customHandler: (params, callback) => {
      const userData = {
        id: getCurrentUserId(),
        name: getCurrentUserName(),
        avatar: getCurrentUserAvatar()
      };

      // Generate auth signature and user data
      generateUserAuth(params.socketId, userData)
        .then(authData => callback(null, authData))
        .catch(error => callback(error, null));
    }
  }
});

// Sign in user for presence channels
pusher.signin();

Deprecated Authorization (Backward Compatibility)

Legacy authorization options maintained for backward compatibility.

/**
 * Deprecated authorization options (for backward compatibility)
 */
interface DeprecatedAuthOptions {
  params?: any;
  headers?: any;
}

/**
 * Deprecated channel authorizer interface
 */
interface DeprecatedChannelAuthorizer {
  authorize(socketId: string, callback: ChannelAuthorizationCallback): void;
}

/**
 * Deprecated authorizer generator function
 */
interface ChannelAuthorizerGenerator {
  (channel: Channel, options: DeprecatedAuthorizerOptions): DeprecatedChannelAuthorizer;
}

interface DeprecatedAuthorizerOptions {
  authTransport: 'ajax' | 'jsonp';
  authEndpoint: string;
  auth?: DeprecatedAuthOptions;
}

Deprecated Authorization Examples:

// Legacy auth configuration (still supported)
const pusher = new Pusher("app-key", {
  cluster: "us2",
  authEndpoint: "/pusher/auth",
  authTransport: "ajax",
  auth: {
    params: { user_id: "123" },
    headers: { "X-CSRF-Token": "token" }
  }
});

// Legacy custom authorizer
const pusher = new Pusher("app-key", {
  cluster: "us2",
  authEndpoint: "/pusher/auth",
  authorizer: (channel, options) => {
    return {
      authorize: (socketId, callback) => {
        // Custom authorization logic
        customAuthRequest(socketId, channel.name, callback);
      }
    };
  }
});

Authentication Request Types

Enumeration of authentication request types.

/**
 * Authentication request type enumeration
 */
enum AuthRequestType {
  UserAuthentication = "user-authentication",
  ChannelAuthorization = "channel-authorization"
}

Authentication Transport

Shared callback type for both channel and user authentication.

/**
 * Generic authentication transport callback
 */
type AuthTransportCallback = ChannelAuthorizationCallback | UserAuthenticationCallback;

/**
 * Internal authentication options interface
 */
interface InternalAuthOptions {
  transport: 'ajax' | 'jsonp';
  endpoint: string;
  params?: any;
  headers?: any;
  paramsProvider?: () => any;
  headersProvider?: () => any;
}

Authentication Flow Examples

Private Channel Authentication

// Server endpoint should return JSON like:
// { "auth": "app_key:signature" }

const pusher = new Pusher("app-key", {
  cluster: "us2",
  channelAuthorization: {
    endpoint: "/pusher/auth",
    transport: "ajax"
  }
});

// Subscribe to private channel
const privateChannel = pusher.subscribe("private-user-messages");

privateChannel.bind("pusher:subscription_succeeded", () => {
  console.log("Successfully authenticated and subscribed");
});

privateChannel.bind("pusher:subscription_error", (error) => {
  console.error("Authentication failed:", error);
});

Presence Channel Authentication

// Server endpoint should return JSON like:
// {
//   "auth": "app_key:signature",
//   "channel_data": "{\"user_id\":\"123\",\"user_info\":{\"name\":\"Alice\"}}"
// }

const pusher = new Pusher("app-key", {
  cluster: "us2",
  channelAuthorization: {
    endpoint: "/pusher/auth",
    transport: "ajax",
    headers: {
      "Authorization": "Bearer user-token"
    }
  }
});

// Subscribe to presence channel
const presenceChannel = pusher.subscribe("presence-chat-room");

presenceChannel.bind("pusher:subscription_succeeded", (members) => {
  console.log("Joined presence channel");
  console.log("Current members:", members);
});

User Authentication for Presence

// Server endpoint should return JSON like:
// {
//   "auth": "app_key:user_signature", 
//   "user_data": "{\"id\":\"123\",\"name\":\"Alice\",\"avatar\":\"url\"}"
// }

const pusher = new Pusher("app-key", {
  cluster: "us2",
  userAuthentication: {
    endpoint: "/pusher/user-auth",
    transport: "ajax"
  }
});

// Sign in user (enables presence without channel_data)
pusher.signin();

// Now presence channels work without channel_data in auth response
const presenceChannel = pusher.subscribe("presence-general");

Error Handling

Authentication Errors

/**
 * HTTP authentication error
 */
class HTTPAuthError extends Error {
  status: number;
  constructor(status: number, msg?: string);
}

Error Handling Examples:

// Handle authentication errors
pusher.bind("error", (error) => {
  if (error instanceof HTTPAuthError) {
    console.error(`Auth failed with status ${error.status}:`, error.message);
    
    switch (error.status) {
      case 401:
        // Redirect to login
        window.location.href = "/login";
        break;
      case 403:
        // Show access denied message
        showError("Access denied to this channel");
        break;
      default:
        showError("Authentication error occurred");
    }
  }
});

// Channel-specific error handling
channel.bind("pusher:subscription_error", (error) => {
  console.error("Channel subscription failed:", error);
  // Handle channel-specific auth failure
});

Server-Side Implementation Examples

Express.js Channel Authorization

// Example Express.js endpoint for channel authorization
app.post('/pusher/auth', express.json(), (req, res) => {
  const { socket_id, channel_name } = req.body;
  const user = authenticateUser(req); // Your auth logic
  
  if (!user) {
    return res.status(401).json({ error: 'Unauthorized' });
  }
  
  // For private channels
  if (channel_name.startsWith('private-')) {
    const auth = pusher.authenticate(socket_id, channel_name);
    res.json(auth);
  }
  
  // For presence channels
  else if (channel_name.startsWith('presence-')) {
    const presenceData = {
      user_id: user.id,
      user_info: {
        name: user.name,
        avatar: user.avatar
      }
    };
    
    const auth = pusher.authenticate(socket_id, channel_name, presenceData);
    res.json(auth);
  } else {
    res.status(400).json({ error: 'Invalid channel' });
  }
});

User Authentication Endpoint

// Example user authentication endpoint
app.post('/pusher/user-auth', express.json(), (req, res) => {
  const { socket_id } = req.body;
  const user = authenticateUser(req);
  
  if (!user) {
    return res.status(401).json({ error: 'Unauthorized' });
  }
  
  const userData = {
    id: user.id,
    name: user.name,
    avatar: user.avatar,
    role: user.role
  };
  
  const auth = pusher.authenticateUser(socket_id, userData);
  res.json(auth);
});

Install with Tessl CLI

npx tessl i tessl/npm-pusher-js

docs

authentication.md

channel-communication.md

client-management.md

connection-management.md

index.md

tile.json