Skip to content

Authenticating

Once a client receives a CONNECTED frame, it must authenticate the session, using the scheme specified in the authenticate header. Authentication is performed by sending a SEND frame with a destination header value of /setup/authenticate and an authorization header with the appropriate credentials, the syntax of which depends on the scheme used. The only supported scheme at this time is SNS.

Note

The scheme might require additional headers, some of which may be provided on the CONNECTED frame. Consult the scheme documentation for more details.

After publishing the SEND authentication frame, if the authentication is successful nothing will happen and the client application can move on to subscribing to the setup topic to start interacting with the STOMP Server. If the authentication fails, the server will send an ERROR frame to the client and close the connection.

SNS authentication scheme

The SNS scheme uses an HMAC+SHA256 digest of various parts of the STOMP frame, signed using a secret key derived from the SolarNode user's hashed password. SolarNode does not store a plain-text version of a user's password, so that is why the hashed password is used for the signing key.

The required SEND headers for SNS authentication are:

Header Description
authorization The SNS authorization value, e.g. SNS Credential=me@example.com,SignedHeaders=date,Signature=168365....
date The request date, e.g. Mon, 16 Aug 2021 02:27:39 GMT.
Example SEND frame for authentication
SEND
destination:/setup/authenticate
date:Mon, 16 Aug 2021 02\c27\c39 GMT
authorization: SNS Credential=me@example.com,SignedHeaders=date,Signature=168365...

Escaping the date header for STOMP

When encoding the date header, be sure to escape the : character in the date value with \c, per the STOMP specification. This encoding is only needed in the STOMP header, not in the SNS signature calculation.

The canonical request message of the signing message must use the following values:

Component Description
Verb Must be SEND.
Path Must be /setup/authenticate.
Signed header names Only date is required.

SNS authentication example

Here is a basic example in Java that uses the SnsAuthorizationBuilder class to generate the required authorization and date headers required by the SNS scheme:

String secret = "value-derived-from-password"; // depends on `auth-hash` CONNECTED header
SnsAuthorizationBuilder authBuilder = new SnsAuthorizationBuilder("me@example.com")
    .date(now)
    .verb("SEND")
    .path("/setup/authenticate");
String authHeader = authBuilder.build(secret);
String dateHeader = authBuilder.headerValue("date");

BCrypt secret derivation

The auth-hash:bcrypt CONNECTED header indicates that the BCrypt digest algorithm must be used to derive the SNS secret value used to sign the request, that in turn converted into by a hex-encoded SHA-256 digest. At a high level the algorithm in pseudo-code looks like this:

secret := Hex(Sha256(BCrypt(password, salt)))

The auth-hash-param-salt header value from the CONNECTED frame will determine the BCrypt salt that must be used to digest the user's plain-text password. The salt will take the form of

$2a$10$1234567890123456789012

Here $2a indicates the version of BCrypt used, $10 indicates the number of iterations used, and everything after the final $ is the Base64 encoded salt used.

BCrypt secret example

The SnsAuthorizationBuilder class can be used to generate the required authorization header value. See this example for more details; here is that example distilled:

String salt = "$2a$10$upVbEZHge9Iph1NN3L6ENO"; // from auth-hash-param-salt CONNECTED header
String secret = DigestUtils.sha256Hex(BCrypt.hashpw("password123", salt));
SnsAuthorizationBuilder authBuilder = new SnsAuthorizationBuilder("me@example.com")
        .date(now)
        .verb("SEND")
        .path("/setup/authenticate");
String authHeader = authBuilder.build(secret);
String dateHeader = authBuilder.headerValue("date");