# How to Implement API Request Signing Verification in Gorig

> Learn to implement API request signing verification in Gorig. This guide shows how to use Gorig's middleware to validate JWT tokens, verify signatures, and inject user context into your Gin handlers.

- Repository: [Jom/gorig](https://github.com/jom-io/gorig)
- Tags: how-to-guide
- Published: 2026-03-04

---

**Gorig provides a ready-to-use signing middleware that validates JWT tokens from HTTP headers, verifies signatures using the tokenx service, and injects authenticated user context into Gin handlers.**

The `jom-io/gorig` framework includes a complete API request signing verification system built on Gin middleware. This implementation handles JWT extraction, signature validation, and user context injection without requiring custom security logic in your handlers. The architecture cleanly separates token generation, storage, and request-time verification, allowing you to swap between in-memory and Redis backends without modifying business logic.

## How API Request Signing Verification Works

The verification flow in [`httpx/mid.sign.go`](https://github.com/jom-io/gorig/blob/main/httpx/mid.sign.go) executes seven distinct operations for every protected request.

1. **Extract the token.** The `GetTokenByCtx` function retrieves the JWT from the `Authorization: Bearer <token>` header. Missing or malformed headers trigger `response.ErrorTokenBaseInfo`.

2. **Locate the token manager.** The middleware accepts a `tokenx.ManagerType` (Memory or Redis) and invokes `tokenx.Get` to retrieve a `TokenService` containing a **generator** and a **manager**.

3. **Validate token existence.** The `TokenManager.GetUserID` method checks the token's presence in the selected store. Unknown tokens return `ErrorTokenAuthFail`.

4. **Parse and verify the JWT.** The `TokenGenerator` (implemented in [`mid/tokenx/jwt.generator.go`](https://github.com/jom-io/gorig/blob/main/mid/tokenx/jwt.generator.go)) validates the token's signature and claims. Errors map to specific `ErrorToken*` responses.

5. **Apply optional user filters.** If a `userFilter` map is supplied, `filterUserInfo` validates that the token's user payload contains required fields (e.g., `consts.NotNull`). Failures result in a `403 Forbidden` response.

6. **Set request context.** On success, the middleware stores the raw token (`consts.TokenKey`) and decoded user data using `apix.SetUserID` and `apix.SetUserInfo` for downstream handlers.

7. **Continue processing.** Finally, `c.Next()` passes control to the actual API handler.

## Core Components for Request Signing

- **[`httpx/mid.sign.go`](https://github.com/jom-io/gorig/blob/main/httpx/mid.sign.go)**: Contains the Gin middleware that orchestrates token extraction, validation, and context injection.

- **[`mid/tokenx/serv.go`](https://github.com/jom-io/gorig/blob/main/mid/tokenx/serv.go)**: Factory that assembles a `TokenService` with the configured generator and manager implementations.

- **[`mid/tokenx/jwt.generator.go`](https://github.com/jom-io/gorig/blob/main/mid/tokenx/jwt.generator.go)**: Implements JWT creation and signature verification through the `Generate` and `Parse` methods.

- **[`mid/tokenx/mem.manager.go`](https://github.com/jom-io/gorig/blob/main/mid/tokenx/mem.manager.go)**: In-memory token manager that handles token recording, expiration, and user-ID lookups.

- **[`apix/handle.go`](https://github.com/jom-io/gorig/blob/main/apix/handle.go)**: Provides `SetUserID` and `SetUserInfo` helpers for injecting user data into the Gin context.

- **[`global/consts/consts.go`](https://github.com/jom-io/gorig/blob/main/global/consts/consts.go)**: Defines token status codes (`JwtTokenOK`, `JwtTokenExpired`) and special filter values like `NotNull`.

## Implementing API Request Signing Verification

### Configuring the Signing Middleware

Attach the middleware to your Gin router using `httpx.SignDef()` for in-memory storage or `httpx.SignRedis()` for Redis-backed sessions. For role-based access control, use `httpx.SignUserDef()` with a filter map that specifies required user claims.

```go
package main

import (
    "github.com/gin-gonic/gin"
    "github.com/jom-io/gorig/httpx"
    "github.com/jom-io/gorig/global/consts"
)

func main() {
    r := gin.Default()

    // Basic memory-based verification
    r.Use(httpx.SignDef())

    // Or with Redis backend
    // r.Use(httpx.SignRedis())

    // Or with user filtering: require role="admin" and non-empty dept
    adminFilter := map[string]interface{}{
        "role": "admin",
        "dept": consts.NotNull,
    }
    r.Use(httpx.SignUserDef(adminFilter))

    r.GET("/protected", protectedHandler)
    r.Run(":8080")
}

```

### Issuing and Recording Tokens

In your authentication endpoint, generate a JWT using the `TokenGenerator` and record it with the `TokenManager` so subsequent requests can validate against it.

```go
package auth

import (
    "github.com/gin-gonic/gin"
    "github.com/jom-io/gorig/mid/tokenx"
    "github.com/jom-io/gorig/utils/configure"
)

func LoginHandler(c *gin.Context) {
    // ... validate credentials ...
    
    userID := "user-123"
    userInfo := map[string]interface{}{
        "role": "admin",
        "dept": "engineering",
    }

    // Get default memory service (or configure for Redis)
    svc := tokenx.GetDef()
    
    // Generate token with 7-day expiration
    expire := int64(configure.GetInt("Jwt.TokenExpireAt", 604800))
    token, err := svc.Generator.Generate(userID, userInfo, expire)
    if err != nil {
        c.JSON(500, gin.H{"error": "token generation failed"})
        return
    }

    // Record in manager for future validation
    svc.Manager.Record(token, userInfo)
    
    c.JSON(200, gin.H{"token": token})
}

```

### Accessing Authenticated User Data

Retrieve the validated user ID and metadata from the Gin context using the `apix` helpers. The signing middleware has already verified the token and injected this data before your handler executes.

```go
package handler

import (
    "github.com/gin-gonic/gin"
    "github.com/jom-io/gorig/apix"
)

func ProtectedHandler(c *gin.Context) {
    // Extract user data injected by Sign middleware
    userID := apix.GetUserID(c)
    userInfo := apix.GetUserInfo(c).(map[string]interface{})
    
    c.JSON(200, gin.H{
        "userId":   userID,
        "userInfo": userInfo,
        "message":  "Access granted to protected resource",
    })
}

```

## Summary

- **Gorig's signing middleware** in [`httpx/mid.sign.go`](https://github.com/jom-io/gorig/blob/main/httpx/mid.sign.go) automates JWT extraction and validation for Gin routers through a seven-step pipeline.
- The **tokenx service** separates token generation ([`jwt.generator.go`](https://github.com/jom-io/gorig/blob/main/jwt.generator.go)) from storage ([`mem.manager.go`](https://github.com/jom-io/gorig/blob/main/mem.manager.go) or Redis), allowing backend swaps without code changes.
- **User filtering** via `SignUserDef` enforces role-based access control by validating claims against required fields like `consts.NotNull`.
- **Context injection** through `apix.GetUserID` and `apix.GetUserInfo` makes authenticated data available to downstream handlers without repetitive validation logic.

## Frequently Asked Questions

### How do I switch from memory to Redis storage for tokens?

Change the middleware function from `httpx.SignDef()` to `httpx.SignRedis()` in your router configuration. The `tokenx.Get` function in [`mid/tokenx/serv.go`](https://github.com/jom-io/gorig/blob/main/mid/tokenx/serv.go) automatically returns a `TokenService` configured with the appropriate manager implementation, so your token generation and validation code remains identical.

### What happens when a JWT token expires?

When the `TokenGenerator.Parse` method in [`mid/tokenx/jwt.generator.go`](https://github.com/jom-io/gorig/blob/main/mid/tokenx/jwt.generator.go) detects an expired token, it returns an error that maps to `ErrorTokenExpired`. The signing middleware catches this and returns an HTTP 401 response with the appropriate error code, preventing the request from reaching your handler.

### Can I implement custom claim validation beyond the built-in user filter?

Yes. While `httpx.SignUserDef` handles basic field presence validation using `consts.NotNull`, you can implement custom logic by wrapping the standard middleware or by validating `apix.GetUserInfo` inside your handlers. For global custom validation, modify the `filterUserInfo` function in [`httpx/mid.sign.go`](https://github.com/jom-io/gorig/blob/main/httpx/mid.sign.go) to implement your specific business rules.

### How do I retrieve the raw JWT string in my handler?

The signing middleware stores the original token string in the Gin context using the key `consts.TokenKey`. Access it using `c.GetString(consts.TokenKey)` if you need to pass the token to downstream microservices or include it in audit logs.