Docs

  • Channels Channels
  • Beams Beams
  • Developers
  • Support
  • Blog
  • Sign up
    • Search powered by Algolia
    • Sign in
    • Sign up
    • Channels
    • Getting started
      • SDK quick starts
        • JavaScript quick start
        • iOS quick start
        • Android quick start
        • Flutter quick start
        • React Native quick start
      • Use case quick starts
        • Javascript realtime chart
        • Javascript realtime user list
      • Debugging
    • Using channels
      • Client API overview
      • Connection
      • User authentication
      • Watchlist events
      • Authorized connections
      • Channels
      • Public channels
      • Private channels
      • Encrypted channels
      • Presence channels
      • Cache channels
      • Events
      • Global configuration
      • Websocket fallbacks
      • Device compatibility
    • Server api
      • Overview
      • HTTP API interaction
      • Webhooks
      • Authenticating users
      • Authorizing users
      • Sending events to authenticated users
      • Terminating user connections
      • Excluding event recipients
    • Channels libraries
      • API libraries
    • Pusher cli
      • Overview
      • Installation
      • Documentation
    • Miscellaneous
      • Clusters
      • Integrations
      • Resources
    • Library auth reference
      • Authentication and authorization signatures
      • HTTP API reference
      • Pusher Channels Protocol
      • Server library reference specification
      • Logging
    • Beams
    • Pusher lab

    Authenticating users

    Pusher provides mechanisms for both authenticating and authorizing users. Our definition of this is that the former identifies who a user is, while the latter controls access by a given user to certain resources.

    Since your servers are the authority on who your users are, and what they can access, our client libraries are able to make calls to endpoints of your choice to supply signed authentication and authorization tokens for the bearing user.

    This page discusses implementing a user authentication endpoint using the Pusher Channels server libraries. If you’re looking for information on implementing a user authorization endpoint, check the Authorizing users page.

    ∞ User authentication

    We authenticate a user once per connection session. Authenticating a user gives your application access to user based features such as sending events to a user based on user id on terminating a user’s connections immediately.

    When your client calls the signin method on a established connection, the Channels client library requests an authentication token from your server. By default, the Pusher Channels client library expects this endpoint to be at /pusher/user-auth, but this can be configured by the client.

    You can start with an authentication endpoint that authenticates every request it receives. Do so by copy-pasting one of the examples below. Note, however, that in order to make this useful, you’ll need to change the example to use the actual user id and information of the correct user. The user object passed to the authenticateUser method must include an id field with a non-empty string. Other possible optional fields are:

    • user_info in which you can provide more information about the user (e.g. name). This information will be shared with other members of presence channels that this user is authorized to join. Read more on that in Presence Channels
    • watchlist which is an array of user IDs. These user IDs represent a circle of interest (e.g., friends or followers) whose online/offline presence can be exposed to the user. Read more on that in Watchlist events. Each user can have a default maximum of 100 user IDs in their Watchlist. If you’d like to request an increase for these limits, contact support.

    User id values should only include lower and uppercase letters, numbers and the following punctuation _ - = @ , . ; As an example this is a valid user id:

    foo-bar_1234@=,.;

    If you don’t see your language listed, you can implement your own authentication endpoint or get in touch.

    // First install the dependencies:
    // npm install pusher express cors

    const express = require("express");
    const cors = require("cors");
    const Pusher = require("pusher");
    const pusher = new Pusher({
    appId: "APP_ID",
    key: "APP_KEY",
    secret: "APP_SECRET",
    cluster: "APP_CLUSTER",
    useTLS: true,
    });
    const app = express();

    app.use(express.json());
    app.use(express.urlencoded({ extended: false }));
    app.use(cors());
    app.post("/pusher/user-auth", (req, res) => {
    const socketId = req.body.socket_id;

    // Replace this with code to retrieve the actual user id and info
    const user = {
    id: "some_id",
    user_info: {
    name: "John Smith",
    },
    watchlist: ['another_id_1', 'another_id_2']
    };
    const authResponse = pusher.authenticateUser(socketId, user);
    res.send(authResponse);
    });

    const port = process.env.PORT || 5000;
    app.listen(port);
    global $user;
    if ($user->uid) {
    $user_data = [
    'id' => (string) $user->uid,
    'user_info' => [
    'name': $user->name,
    ],
    'watchlist': $user->watchlist
    ];
    echo $pusher->authenticateUser($_POST['socket_id'], $user_data);
    } else {
    header('', true, 403);
    echo "Forbidden";
    }
    if ( is_user_logged_in() ) {
    $user_data = [
    'id' => (string) get_current_user_id(),
    'user_info' => [
    'name': (string) get_current_user()->name
    ],
    'watchlist' => get_current_user()->watchlist
    ];
    echo $pusher->authorizeChannel($_POST['socket_id'], $user_data);
    } else {
    header('', true, 403);
    echo "Forbidden";
    }

    ∞ Response

    • Unsuccessful responses from an authentication endpoint should serve a 403 Forbidden HTTP status.
    • Successful responses from an authentication endpoint should carry a 200 OK HTTP status and a body of the form
      { "auth": "$AUTHORIZATION_STRING", "user_data": "$USER_DATA" }

    ∞ Client-side: setting the authentication endpoint

    The destination of the authentication requests can be configured.

    new Pusher("app_key", { userAuthentication: { endpoint: "/pusher_user_auth.php"}});

    The default value for this is /pusher/user-auth,

    ∞ CSRF-protected authentication endpoint

    If the endpoint is protected by a CSRF filter, then you can pass in a CSRF token via the userAuthentication hash under headers.

    var pusher = new Pusher("app_key", {
    userAuthentication: {
    endpoint: "/pusher_auth.php",
    headers: { "X-CSRF-Token": "SOME_CSRF_TOKEN" },
    },
    });

    Note that you should change the name of the CSRF token key to the convention you prefer.

    As an example, in Rails, you can inject the CSRF token into Javascript like this using ERB

    <script>
    var pusher = new Pusher("app_key", {
    userAuthentication: {
    endpoint: "/pusher/user-auth",
    headers: { "X-CSRF-Token": "<%= form_authenticity_token %>" },
    },
    });
    </script>

    ∞ Using JSONP in pusher-js

    In the browser, if your authentication endpoint is on a different domain to the web application, you need to work around the browser’s same-origin policy. For modern browsers, you should use Cross-Origin Resource Sharing (CORS) ; however, for older clients, pusher-js also supports JSONP. To enable this, set userAuthentication.transport: 'jsonp':

    <script src="//js.pusher.com/8.0.1/pusher.min.js"></script>
    <script>
    var pusher = new Pusher("MY_PUSHER_KEY", {
    userAuthentication: {
    transport: "jsonp",
    endpoint: "http://myserver.com/pusher_jsonp_user_auth",
    },
    });
    </script>

    With this set, the authentication request parameters are passed in the query string, and an additional parameter called callback will be passed to the authentication endpoint. The authentication response must then be JavaScript that calls the named callback function with the authentication response. Here are some examples of generating this response for private channels:

    // Express.js setup
    // http://expressjs.com/

    ...

    app.get("/pusher/user-auth", (req, res) => {
    const query = req.query;
    const socketId = query.socket_id;
    const callback = query.callback;

    const user = {
    id: "some_id",
    user_info: {
    name: "John Smith",
    },
    watchlist: ['another_id_1', 'another_id_2']
    };

    const auth = JSON.stringify(
    pusher.authenticateUser(socketId, user)
    );
    const cb = callback.replace(/\\"/g,"") + "(" + auth + ");";

    res.set({
    "Content-Type": "application/javascript"
    });

    res.send(cb);
    });

    Contents

    • User authentication
    • Response
    • Client-side: setting the authentication endpoint
      • CSRF-protected authentication endpoint
    • Using JSONP in pusher-js

    Spotted something that isn’t quite right? Create an issue on GitHub.

    Copyright © 2023 Pusher Ltd. All rights reserved.

    • Support,
    • Status
    • Follow Pusher on Twitter Twitter
    • Subscribe to Pusher’s channel on YouTube
    • Follow Pusher on LinkedIn
    • Follow Pusher on Github GitHub
    • Follow Pusher on Twitch Twitch
    • Follow Pusher on Discord Discord