API Security Best Practices with Go

Hi there! I’m Maneshwar. Right now, I’m building LiveAPI, a first-of-its-kind tool that helps you automatically index API endpoints across all your repositories. LiveAPI makes it easier to discover, understand, and interact with APIs in large infrastru…


This content originally appeared on DEV Community and was authored by Athreya aka Maneshwar

Hi there! I'm Maneshwar. Right now, I’m building LiveAPI, a first-of-its-kind tool that helps you automatically index API endpoints across all your repositories. LiveAPI makes it easier to discover, understand, and interact with APIs in large infrastructures.

Securing your API is non-negotiable. Whether you're building public or internal services, unprotected endpoints can expose your system to data theft, misuse, or even total compromise.

This guide outlines essential API security principles, with practical Go code snippets using the Echo web framework where applicable.

1. Use Proper HTTP Methods

Only allow HTTP methods appropriate for each endpoint. Respond with 405 Method Not Allowed for disallowed methods.

e := echo.New()

// Proper usage
e.GET("/users/:id", getUser)
e.POST("/users", createUser)
e.PUT("/users/:id", updateUser)
e.DELETE("/users/:id", deleteUser)

// Middleware to handle unsupported methods
e.Use(func(next echo.HandlerFunc) echo.HandlerFunc {
    return func(c echo.Context) error {
        allowedMethods := map[string][]string{
            "/users":     {"POST"},
            "/users/:id": {"GET", "PUT", "DELETE"},
        }
        route := c.Path()
        method := c.Request().Method

        for path, methods := range allowedMethods {
            if echo.NewRouter().Find(method, path, c) != nil {
                return next(c)
            }
            if path == route {
                return echo.NewHTTPError(http.StatusMethodNotAllowed, "Method Not Allowed")
            }
        }
        return next(c)
    }
})

2. Content-Type Validation

Validate the Content-Type header. Expect application/json for JSON APIs.

e.Use(func(next echo.HandlerFunc) echo.HandlerFunc {
    return func(c echo.Context) error {
        if c.Request().Method == http.MethodPost || c.Request().Method == http.MethodPut {
            if c.Request().Header.Get(echo.HeaderContentType) != echo.MIMEApplicationJSON {
                return echo.NewHTTPError(http.StatusUnsupportedMediaType, "Only application/json allowed")
            }
        }
        return next(c)
    }
})

3. Validate User Input

Use input validation to prevent injection attacks and ensure data integrity.

type CreateUserInput struct {
    Name  string `json:"name" validate:"required,min=3"`
    Email string `json:"email" validate:"required,email"`
}

func createUser(c echo.Context) error {
    var input CreateUserInput
    if err := c.Bind(&input); err != nil {
        return echo.NewHTTPError(http.StatusBadRequest, "Invalid request")
    }

    if err := c.Validate(&input); err != nil {
        return echo.NewHTTPError(http.StatusBadRequest, err.Error())
    }

    // Proceed safely
    return c.JSON(http.StatusOK, map[string]string{"status": "user created"})
}

To enable validation:

import "github.com/go-playground/validator/v10"

type CustomValidator struct {
    validator *validator.Validate
}

func (cv *CustomValidator) Validate(i interface{}) error {
    return cv.validator.Struct(i)
}

e.Validator = &CustomValidator{validator: validator.New()}

4. Use Authorization Header for Tokens

Tokens should be sent in the standard Authorization: Bearer <token> header—not in query parameters.

func tokenAuthMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
    return func(c echo.Context) error {
        auth := c.Request().Header.Get("Authorization")
        if auth == "" || !strings.HasPrefix(auth, "Bearer ") {
            return echo.NewHTTPError(http.StatusUnauthorized, "Missing or invalid Authorization header")
        }

        token := strings.TrimPrefix(auth, "Bearer ")
        if !validateToken(token) {
            return echo.NewHTTPError(http.StatusUnauthorized, "Invalid token")
        }

        return next(c)
    }
}

Avoid this:

GET /api/data?token=abc123  ❌

5. Avoid Client-Side Encryption

Don’t rely on client-side encryption for sensitive data. Encrypt on the server side using robust libraries.

// Example: AES encryption
func encryptAES(plaintext, key string) (string, error) {
    block, err := aes.NewCipher([]byte(key))
    if err != nil {
        return "", err
    }
    plaintextBytes := []byte(plaintext)
    ciphertext := make([]byte, aes.BlockSize+len(plaintextBytes))
    iv := ciphertext[:aes.BlockSize]
    if _, err := io.ReadFull(rand.Reader, iv); err != nil {
        return "", err
    }
    stream := cipher.NewCFBEncrypter(block, iv)
    stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintextBytes)
    return base64.URLEncoding.EncodeToString(ciphertext), nil
}

Keep keys and secrets on the server, never in the client-side code.

6. Use an API Gateway

Use tools like Kong, Traefik, or AWS API Gateway for enhanced security features:

  • JWT validation
  • IP whitelisting
  • Rate limiting
  • Request logging
  • TLS termination

Example: Kong Rate Limiting (declarative config)

services:
  - name: my-api
    url: http://myapi:8000
    routes:
      - name: my-api-route
        paths:
          - /v1/
        plugins:
          - name: rate-limiting
            config:
              minute: 100
              policy: local

Final Tips

  • Always use HTTPS (TLS) to encrypt data in transit.
  • Enable logging and alerting for abnormal traffic.
  • Keep dependencies updated to patch known vulnerabilities.
  • Run security headers like X-Content-Type-Options: nosniff.

TL;DR Checklist

Security Feature Status
Proper HTTP methods
Content-Type validation
Input validation
Token via Authorization
No client-side encryption
API gateway used

API security is not a luxury — it’s a baseline. Build secure by default, and save yourself from firefighting later.

LiveAPI helps you get all your backend APIs documented in a few minutes.

With LiveAPI, you can generate interactive API docs that allow users to search and execute endpoints directly from the browser.

LiveAPI Demo

If you're tired of updating Swagger manually or syncing Postman collections, give it a shot.


This content originally appeared on DEV Community and was authored by Athreya aka Maneshwar


Print Share Comment Cite Upload Translate Updates
APA

Athreya aka Maneshwar | Sciencx (2025-08-01T18:19:18+00:00) API Security Best Practices with Go. Retrieved from https://www.scien.cx/2025/08/01/api-security-best-practices-with-go/

MLA
" » API Security Best Practices with Go." Athreya aka Maneshwar | Sciencx - Friday August 1, 2025, https://www.scien.cx/2025/08/01/api-security-best-practices-with-go/
HARVARD
Athreya aka Maneshwar | Sciencx Friday August 1, 2025 » API Security Best Practices with Go., viewed ,<https://www.scien.cx/2025/08/01/api-security-best-practices-with-go/>
VANCOUVER
Athreya aka Maneshwar | Sciencx - » API Security Best Practices with Go. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2025/08/01/api-security-best-practices-with-go/
CHICAGO
" » API Security Best Practices with Go." Athreya aka Maneshwar | Sciencx - Accessed . https://www.scien.cx/2025/08/01/api-security-best-practices-with-go/
IEEE
" » API Security Best Practices with Go." Athreya aka Maneshwar | Sciencx [Online]. Available: https://www.scien.cx/2025/08/01/api-security-best-practices-with-go/. [Accessed: ]
rf:citation
» API Security Best Practices with Go | Athreya aka Maneshwar | Sciencx | https://www.scien.cx/2025/08/01/api-security-best-practices-with-go/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.