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
      • Functions
      • 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

    Generating authentication and authorization strings

    This guide is designed for library makers who wish to implement the signing mechanism in use for user authentication and by private channels. Visit those pages for information about integration and an overview of the technique.

    For both user authentication and private channel authorization, auth strings have the following format

    <pusher-key>:<signature>
    

    The signature is a HMAC SHA256 hex digest. This is generated by signing a string with your Channels secret.

    • For user authentication, the string should be the following, where user_data is a JSON-encoded object containing at least an id property set to a non-empty string containing the user id.
    <socket_id>::user::<user_data>
    
    • For private channel authorization, the string should be:
    <socket_id>:<channel_name>
    

    ∞ Worked examples

    Suppose that you have the following Channels credentials

    key = '278d425bdf160c739803' secret = '7ad3773142a6692b25b8'
    

    And the user has connected and Channels has assigned that user with a socket_id with the value 1234.1234.

    ∞ User authentication

    Given that your application receives a POST request to /pusher/user-auth with the parameters

    (socket_id = 1234.1234)
    

    You would retrieve the user information according to your application and create a string containing a JSON encoded object with at least the id property set to a non-empty string.

    {"id":"12345"}

    Then you would create a HMAC SHA256 hex digest of the following string using your secret key

    1234.1234::user::{"id":"12345"}
    

    Using Ruby as an example

    require "openssl"

    digest = OpenSSL::Digest::SHA256.new
    secret = "7ad3773142a6692b25b8"
    string_to_sign = "1234.1234::user::{\"id\":\"12345\"}"

    signature = OpenSSL::HMAC.hexdigest(digest, secret, string_to_sign)

    puts auth = "278d425bdf160c739803:#{signature}"
    # => 278d425bdf160c739803:4708d583dada6a56435fb8bc611c77c359a31eebde13337c16ab43aa6de336ba

    The authentication response should be a JSON object with

    • an auth property with a value composed of the application key and the authentication signature separated by a colon ‘:’ as follows
    • a user_data property with a string containing the JSON encoded object. It should be exactly the same as the one included in the authentication signature
    {
    "auth": "278d425bdf160c739803:4708d583dada6a56435fb8bc611c77c359a31eebde13337c16ab43aa6de336ba",
    "user_data": "{\"id\":\"12345\"}",
    }

    ∞ Private channel

    Given that your application receives a POST request to /pusher/auth with the parameters

    (channel_name = (private - foobar) & socket_id = 1234.1234)
    

    You would first check that the user (authenticated via cookies or whatever) has permission to access channel private-foobar. If she has permission you would create a HMAC SHA256 hex digest of the following string using your secret key

    1234.1234:private-foobar
    

    Using Ruby as an example

    require "openssl"

    digest = OpenSSL::Digest::SHA256.new
    secret = "7ad3773142a6692b25b8"
    string_to_sign = "1234.1234:private-foobar"

    signature = OpenSSL::HMAC.hexdigest(digest, secret, string_to_sign)

    puts auth = "278d425bdf160c739803:#{signature}"
    # => 278d425bdf160c739803:58df8b0c36d6982b82c3ecf6b4662e34fe8c25bba48f5369f135bf843651c3a4

    The authorization response should be a JSON string with a an auth property with a value composed of the application key and the authentication signature separated by a colon ‘:’ as follows:

    {
    "auth": "278d425bdf160c739803:58df8b0c36d6982b82c3ecf6b4662e34fe8c25bba48f5369f135bf843651c3a4"
    }

    ∞ User authentication

    For user authentication, as outlined in the example above, the response from the server must include a user_data property. The user_data property must contain the exact same JSON-encoded string that was used to build the auth string.

    {
    "auth": "278d425bdf160c739803:4708d583dada6a56435fb8bc611c77c359a31eebde13337c16ab43aa6de336ba",
    "user_data": "{\"id\":\"12345\"}",
    }

    ∞ Encrypted channels

    Encrypted channels require an additional shared_secret key in the authorization response, which is populated with the per-channel shared key to use for decryption. The key is base64 encoded, it must be decoded before use.

    This value is not part of the signature for the authorization token, it is independent of the value in the auth key.

    For example:

    {
    "auth": "...", // as above for private channels
    "shared_secret": "<channel secret derived from master secret>"
    }

    ∞ Presence channels

    Presence channels require extra user data to be passed back to the client along with the authorization string. These data need to be part of the signature as a valid JSON string. For presence channels, the signature is a HMAC SHA256 hex digest of the following string:

    <socket_id>:<channel_name>:<JSON encoded user data>

    Ruby example for presence channels:

    require "json"
    require "openssl"

    json_user_data = JSON.generate({
    :user_id => 10,
    :user_info => {:name => "Mr. Channels"} })
    # NB: written as double-escaped JSON!
    # => "{\"user_id\":10,\"user_info\":{\"name\":\"Mr. Channels\"}}"

    digest = OpenSSL::Digest::SHA256.new

    secret = "7ad3773142a6692b25b8"
    string_to_sign = "1234.1234:presence-foobar:#{json_user_data}"
    signature = OpenSSL::HMAC.hexdigest(digest, secret, string_to_sign)

    puts auth = "278d425bdf160c739803:#{signature}"
    # => 278d425bdf160c739803:afaed3695da2ffd16931f457e338e6c9f2921fa133ce7dac49f529792be6304c

    The authorization response should be a JSON string with a an auth property with a value composed of the application key and the authentication signature separated by a colon ‘:’. A channel_data property should also be present composed of the data for the channel as a string (note: double-encoded JSON):

    {
    "auth": "278d425bdf160c739803:afaed3695da2ffd16931f457e338e6c9f2921fa133ce7dac49f529792be6304c",
    "channel_data": "{\"user_id\":10,\"user_info\":{\"name\":\"Mr. Channels\"}}"
    }

    Note: The whole response must be JSON-encoded before returning it to the client, even if channel_data inside it is already JSON-encoded.

    Contents

    • Worked examples
      • User authentication
      • Private channel
    • User authentication
    • Encrypted channels
    • Presence channels

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

    Copyright © 2024 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
    OSZAR »