Sling Academy
Home/Golang/Using Middleware for Authentication in WebSocket Connections in Go

Using Middleware for Authentication in WebSocket Connections in Go

Last updated: November 26, 2024

In modern web applications, real-time communication is an essential feature. WebSockets serve this purpose well by facilitating full-duplex communication channels over a single TCP connection. When working with WebSockets in Go, adding authentication is a crucial step to ensure that only authorized users can establish connections. Middleware provides a graceful approach to repeatedly apply pre-request checks like authentication.

What is Middleware?

Middleware is a way of adding layers to request handling. Each layer can perform its own processing and then call the next middleware in stack. This modular design makes it easy to address cross-cutting concerns such as logging, authentication, and more.

Integrating Middleware for Authentication

When using the Go language to handle WebSocket connections, you'll typically utilize a package like gorilla/websocket. We'll create a middleware function that checks authentication status before a WebSocket handshake is completed. Let's dive into the implementation.

Step 1: Install Required Packages

You'll need the following Go package to manage WebSocket connections. Run this command:

go get -u github.com/gorilla/websocket

Step 2: Setup WebSocket and Middleware

Let's create an authentication middleware for handling WebSocket connection requests. This function will check for a valid token before letting the request proceed to the WebSocket upgrader.


package main

import (
    "net/http"
    "github.com/gorilla/websocket"
)

var upgrader = websocket.Upgrader{
    CheckOrigin: func(r *http.Request) bool {
        return true
    },
}

func authMiddleware(next http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        token := r.Header.Get("Authorization")
        if token != "expected-secret-token" {
            http.Error(w, "Unauthorized", http.StatusUnauthorized)
            return
        }
        next.ServeHTTP(w, r) // Call the next handler
    }
}

func wsHandler(w http.ResponseWriter, r *http.Request) {
    conn, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        http.Error(w, "Could not open websocket connection", http.StatusBadRequest)
        return
    }
    defer conn.Close()

    // Handle WebSocket connection
    for {
        _, message, err := conn.ReadMessage()
        if err != nil {
            break
        }
        // Echo the message back
        if err = conn.WriteMessage(websocket.TextMessage, message); err != nil {
            break
        }
    }
}

func main() {
    http.HandleFunc("/ws", authMiddleware(wsHandler))
    http.ListenAndServe(":8080", nil)
}

Explanation

  • websocket.Upgrader is used to upgrade an HTTP connection to a WebSocket connection.
  • The authMiddleware function checks if the incoming request contains a valid authorization token.
  • If the token is valid, it calls the next handler; otherwise, it returns a 401 Unauthorized error.
  • The wsHandler manages the WebSocket traffic once authorized.

Testing the Secure WebSocket Server

Start the server using:

go run main.go

Then, connect to the WebSocket server with a tool like websocat:

websocat ws://localhost:8080/ws -H "Authorization: expected-secret-token"

If the token is correct, the server will establish a WebSocket connection and echo back any messages sent to it.

Conclusion

Using middleware for WebSocket authentication is efficient, as it cleanly separates concerns without duplicating code across multiple handlers. Integrated securely within your Go application using Gorilla WebSocket and middleware, you can ensure verified client connections, enhancing both security and usability.

Next Article: Handling WebSocket Errors and Reconnection Strategies in Go

Previous Article: Implementing Ping-Pong for WebSocket Health Checks in Go

Series: Websocket & Chat Programs in Go

Golang

Related Articles

You May Also Like

  • How to remove HTML tags in a string in Go
  • How to remove special characters in a string in Go
  • How to remove consecutive whitespace in a string in Go
  • How to count words and characters in a string in Go
  • Relative imports in Go: Tutorial & Examples
  • How to run Python code with Go
  • How to generate slug from title in Go
  • How to create an XML sitemap in Go
  • How to redirect in Go (301, 302, etc)
  • Using Go with MongoDB: CRUD example
  • Auto deploy Go apps with CI/ CD and GitHub Actions
  • Fixing Go error: method redeclared with different receiver type
  • Fixing Go error: copy argument must have slice type
  • Fixing Go error: attempted to use nil slice
  • Fixing Go error: assignment to constant variable
  • Fixing Go error: cannot compare X (type Y) with Z (type W)
  • Fixing Go error: method has pointer receiver, not called with pointer
  • Fixing Go error: assignment mismatch: X variables but Y values
  • Fixing Go error: array index must be non-negative integer constant