Chat
Ask me anything
Ithy Logo

Sending JWT in Response Headers with GoFiber

express - Sending JWT token in the headers with Postman - Stack Overflow

When developing a web application using GoFiber in Golang, sending a JSON Web Token (JWT) in the response headers and ensuring the client automatically includes it in subsequent requests as a Bearer token is a common authentication pattern. This approach avoids the use of cookies, relying solely on headers for token management. While the browser doesn't automatically persist headers across requests like cookies, client-side JavaScript can be used to achieve the desired behavior.

Server-Side Implementation (GoFiber)

The server-side implementation involves generating a JWT upon successful user authentication (e.g., login) and setting it in the Authorization header of the response. Here's a detailed breakdown:

1. JWT Generation

First, you need a function to generate the JWT. This function typically takes user-identifying information (e.g., user ID, username) and an expiration time as input. It uses a secret key to sign the token, ensuring its integrity. The github.com/golang-jwt/jwt/v5 library is commonly used for this purpose. Make sure to install it using: go get github.com/golang-jwt/jwt/v5

Here's an example of a generateToken function:


import (
    "time"
    "github.com/golang-jwt/jwt/v5"
)

var secretKey = []byte("your_secret_key") // Replace with a strong, randomly generated key

func generateToken(userID string) (string, error) {
    claims := jwt.MapClaims{
        "user_id": userID,
        "exp":     time.Now().Add(time.Hour * 1).Unix(), // Token expires in 1 hour
    }
    token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
    return token.SignedString(secretKey)
}
  

Important: Replace "your_secret_key" with a strong, randomly generated secret key. Never hardcode this in production; use environment variables or a secure configuration management system.

2. Login Handler

The login handler is responsible for authenticating the user (e.g., verifying username and password) and, upon successful authentication, generating a JWT and setting it in the response header. Here's an example using GoFiber:


import (
    "github.com/gofiber/fiber/v2"
)

func login(c *fiber.Ctx) error {
    // Authentication logic here (e.g., verify username/password)
    userID := "12345" // Replace with actual user ID

    token, err := generateToken(userID)
    if err != nil {
        return c.Status(fiber.StatusInternalServerError).SendString("Could not generate token")
    }

    c.Set("Authorization", "Bearer "+token) // Set JWT in Authorization header

    return c.JSON(fiber.Map{
        "message": "Login successful",
    })
}
  

In this example, the c.Set("Authorization", "Bearer "+token) line sets the JWT in the Authorization header with the Bearer scheme. This is the standard way to send JWTs in HTTP headers.

3. Setting up the GoFiber App

Here's how you would set up your GoFiber application to use the login handler:


func main() {
    app := fiber.New()

    app.Post("/login", login)

    app.Listen(":3000")
}
  

4. JWT Middleware (Optional)

For protected routes, you can use a JWT middleware to validate the token in the Authorization header. This middleware will extract the token, verify its signature, and potentially attach user information to the context. Here's an example of a basic middleware:


import (
    "strings"
    jwtware "github.com/gofiber/contrib/jwt"
)

func JWTMiddleware(c *fiber.Ctx) error {
    authHeader := c.Get("Authorization")
    if authHeader == "" {
        return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "Missing authorization token"})
    }

    token := strings.TrimPrefix(authHeader, "Bearer ")
    claims, err := validateToken(token) // Implement validateToken function
    if err != nil {
        return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "Invalid token"})
    }

    c.Locals("user", claims) // Attach claims to context
    return c.Next()
}

func validateToken(tokenString string) (jwt.MapClaims, error) {
    token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
        return secretKey, nil
    })
    if err != nil {
        return nil, err
    }

    if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
        return claims, nil
    }
    return nil, jwt.ErrTokenMalformed
}
  

You can then apply this middleware to protected routes:


app.Use(JWTMiddleware)
app.Get("/restricted", func(c *fiber.Ctx) error {
    return c.SendString("You are authenticated and can access this route")
})
  

Alternatively, you can use the github.com/gofiber/contrib/jwt middleware:


app.Use(jwtware.New(jwtware.Config{
    SigningKey: secretKey,
}))
  

This middleware automatically handles token verification.

Client-Side Implementation (JavaScript)

While the server sends the JWT in the response header, the browser doesn't automatically include it in subsequent requests. You need client-side JavaScript to handle this. Here's how:

1. Retrieving the JWT

After a successful login, you need to retrieve the JWT from the Authorization header of the response. You can do this using the fetch API or a library like Axios:


fetch('/login', {
  method: 'POST',
  // ... your login data ...
})
.then(response => {
    if (!response.ok) {
        throw new Error('Login failed');
    }
    return response.json();
})
.then(data => {
  const token = response.headers.get('Authorization');
  if (token) {
    localStorage.setItem('jwt', token); // Store the JWT
    // ... redirect to the appropriate page ...
  }
})
.catch(error => {
    console.error('Error during login:', error);
});
  

This code snippet retrieves the Authorization header, extracts the JWT, and stores it in localStorage. Note: For highly sensitive data, consider using sessionStorage or a more secure storage mechanism instead of localStorage.

2. Including the JWT in Subsequent Requests

For subsequent requests to protected routes, you need to include the JWT in the Authorization header. Here's how you can do it:


fetch('/protected-route', {
  headers: {
    'Authorization': localStorage.getItem('jwt')
  }
})
// ... rest of your fetch call ...
  

This code snippet retrieves the JWT from localStorage and includes it in the Authorization header of the request.

3. Using a Library (e.g., Axios)

If you're using a library like Axios, you can configure it to automatically include the JWT in all requests. Here's an example:


import axios from 'axios';

axios.interceptors.request.use(config => {
  const token = localStorage.getItem('jwt');
  if (token) {
    config.headers.Authorization = token;
  }
  return config;
});

// Example request
axios.get('/protected-route')
  .then(response => {
    // ... handle response ...
  });
  

This code snippet uses an Axios interceptor to add the JWT to the Authorization header of every request.

Key Considerations

  • Security: Ensure your secret key is securely stored and not hardcoded. Use environment variables or a secure configuration management system.
  • Token Expiration: Implement token expiration and refresh mechanisms for better security.
  • Error Handling: Handle potential errors (e.g., token expiration, invalid tokens) gracefully in both your server and client code.
  • Storage: Choose the appropriate storage mechanism for the JWT on the client-side. Avoid localStorage for highly sensitive data.
  • Middleware: Use a JWT middleware on the server-side to validate tokens on protected routes.
  • Client-Side Libraries: Consider using a dedicated library for managing JWTs on the client-side.

By implementing these steps, you can effectively send a JWT in the response headers and ensure that the client automatically includes it in subsequent requests, avoiding the use of cookies and providing a secure and seamless authentication experience.

This approach ensures that the client sets the Bearer header automatically when making subsequent requests, without requiring any manual intervention from the user.

Additional resources:


Last updated January 6, 2025
Ask Ithy AI
Download Article
Delete Article