For WebSocket-based subscriptions, authentication typically happens during the connection initialization phase. You can use transport.WebsocketInitFunc within the AddTransport method to process the connection's initial payload.
- Define an InitFunc: Create a function matching the
transport.WebsocketInitFunc signature. This function receives the transport.InitPayload (a map of values sent by the client). - Extract Credentials: Access the payload (e.g.,
initPayload["authToken"]) to verify the user. - Handle Failures: If authentication fails, use
transport.WithWebsocketCloseCode and transport.AppendCloseReason to set a specific close code (e.g., 1008 for policy violation) and a reason before returning an error. - Inject into Context: If successful, return a new context containing the user data.
- Register the Transport: Add the
transport.Websocket to your server and provide the InitFunc.
func webSocketInit(ctx context.Context, initPayload transport.InitPayload) (context.Context, *transport.InitPayload, error) {
any := initPayload["authToken"]
token, ok := any.(string)
if !ok || token == "" {
// Set close code and reason before returning error
ctx = transport.WithWebsocketCloseCode(ctx, int(coderws.StatusPolicyViolation)) // 1008
ctx = transport.AppendCloseReason(ctx, "missing or invalid authToken")
return ctx, nil, errors.New("authToken not found in transport payload")
}
// ... verify token ...
userId := "john.doe"
ctxNew := context.WithValue(ctx, "username", userId)
return ctxNew, nil, nil
}
// Registering the transport
srv.AddTransport(transport.Websocket{
KeepAlivePingInterval: 10 * time.Second,
Implementation: transport.CoderWebsocketImplementation{
AcceptOptions: coderws.AcceptOptions{
InsecureSkipVerify: true,
},
},
InitFunc: transport.WebsocketInitFunc(webSocketInit),
})