---
updatedAt: 2026-05-13T09:28:10.000Z
agentTools:
  projectIndex: https://docs.glb.osl.com/llms.txt
---

# WebSocket Authentication

* **Authentication timing:** Send the authentication command after the WebSocket connection is established.
* **Authentication fields:**
  * `apiKey`: Unique user identifier used for API calls. The user must apply for this.
  * `passphrase`: Password for the API Key. If there is no passphrase, pass an empty string (`""`).
  * `timestamp`: Unix millisecond timestamp. The timestamp expires after 30 seconds.
  * `sign`: Signature string. The signature rule is described below.

<br />

### Signature Rule

The message to be signed is:

```text
timestamp + method + requestPath
```

Where:

```java
Long timestamp = System.currentTimeMillis();
```

* `method` is always `GET`
* `requestPath` is always `/user/verify`

### Signature Generation Steps

**Step 1:** Encrypt the message using HMAC-SHA256 with the private key `secretKey`.

```text
Signature = hmac_sha256(secretKey, Message)
```

**Step 2:** Base64 encode the signature.

```text
Signature = base64.encode(Signature)
```

### Authentication Example Code

The authentication data structure follows the format of **subscribing to a stream** in the public market data API. For private data, the parameter passed in `params` is the Base64 string of the authentication object.

```java
import com.alibaba.fastjson.JSON;
import okhttp3.*;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.HashMap;

public class WssExample {
    // Replace with your own credentials
    static final String BASE_URL = "wss://stream-api.osl.com/openapi/v1/ws/user";
    static final String ACCESS_KEY = "<your-access-key>";
    static final String SECRET_KEY = "<your-secret-key>";
    static final String PASSPHRASE = "<your-passphrase>";

    public static void main(String[] args) {
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url(BASE_URL)
                .build();
        WebSocket webSocket = client.newWebSocket(request, new WebSocketListener() {
            @Override
            public void onOpen(WebSocket webSocket, Response response) {
                Long timestamp = System.currentTimeMillis();
                HashMap<Object, Object> loginParams = new HashMap<>();
                loginParams.put("apiKey", ACCESS_KEY);
                loginParams.put("passphrase", PASSPHRASE);
                loginParams.put("timestamp", timestamp);
                loginParams.put("sign", sign(timestamp));
                String loginBase64 = Base64.getEncoder().encodeToString(JSON.toJSONString(loginParams).getBytes(StandardCharsets.UTF_8));
                String text = "{\"method\":\"SUBSCRIBE\",\"params\":[\"" + loginBase64 + "\"],\"binary\":false}";
                webSocket.send(text);
            }
            @Override
            public void onMessage(WebSocket webSocket, String text) {
                System.out.println(text);
            }
            @Override
            public void onClosing(WebSocket webSocket, int code, String reason) {
                webSocket.close(1000, null);
            }
            @Override
            public void onFailure(WebSocket webSocket, Throwable t, Response response) {
                System.out.println(t.getMessage());
            }
        });
        client.dispatcher().executorService().shutdown();
    }

    static String sign(Long timestamp) {
        try {
            Mac mac = Mac.getInstance("HmacSHA256");
            mac.init(new SecretKeySpec(SECRET_KEY.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
            mac.update(String.format("%sGET/user/verify", timestamp).getBytes(StandardCharsets.UTF_8));
            return Base64.getEncoder().encodeToString(mac.doFinal());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}
```

<br />