# How to Implement JWT Authentication in Gorig: A Complete Guide

> Learn to implement JWT authentication in Gorig with our complete guide. Utilize the built-in tokenx middleware and jwt-go library for secure HS-256 token generation and validation.

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

---

**Gorig provides a built-in tokenx middleware package that leverages the jwt-go library to generate and validate JWT tokens using HS-256 signing, configurable via a simple secret key.**

Gorig is a Go web framework that simplifies building secure APIs with its integrated authentication layer. To implement JWT authentication in Gorig, you utilize the framework's built-in `tokenx` package, which wraps the popular `github.com/dgrijalva/jwt-go` library and provides ready-to-use generators and validators wired into the configuration system.

## Architecture of Gorig's JWT System

### Core Components

The JWT implementation in Gorig is modular and consists of several key files:

- **`jwtGenerator`** – The concrete implementation in [[`mid/tokenx/jwt.generator.go`](https://github.com/jom-io/gorig/blob/main/mid/tokenx/jwt.generator.go)](https://github.com/jom-io/gorig/blob/master/mid/tokenx/jwt.generator.go) that creates and parses JWT strings using HS-256 signing and the `JwtKey` value from global configuration.
- **`CustomClaims`** – Extends `jwt.StandardClaims` with application-specific fields like `UserID` and `Roles`, defined in [[`mid/tokenx/claims.go`](https://github.com/jom-io/gorig/blob/main/mid/tokenx/claims.go)](https://github.com/jom-io/gorig/blob/master/mid/tokenx/claims.go).
- **`mem.manager`** – An optional in-memory store for token revocation and refresh-token tracking, located in [[`mid/tokenx/mem.manager.go`](https://github.com/jom-io/gorig/blob/main/mid/tokenx/mem.manager.go)](https://github.com/jom-io/gorig/blob/master/mid/tokenx/mem.manager.go).
- **Service Factory** – Returns a ready-to-use `jwtGenerator` instance, pulling the secret key from the configuration system via [[`global/variable/variable.go`](https://github.com/jom-io/gorig/blob/main/global/variable/variable.go)](https://github.com/jom-io/gorig/blob/master/global/variable/variable.go), implemented in [[`mid/tokenx/serv.go`](https://github.com/jom-io/gorig/blob/main/mid/tokenx/serv.go)](https://github.com/jom-io/gorig/blob/master/mid/tokenx/serv.go).

### Request Flow

1. **Configuration** – Define the `jwt.key` secret in your configuration file.
2. **Startup** – The `tokenx` service instantiates during application boot (see [[`bootstrap/startup.go`](https://github.com/jom-io/gorig/blob/main/bootstrap/startup.go)](https://github.com/jom-io/gorig/blob/master/bootstrap/startup.go)), reading `JwtKey` to create the generator.
3. **Generate** – After successful authentication, call `Generate` to create a signed token with custom claims.
4. **Validate** – In protected handlers, call `ParseToken` to verify signatures, expiration, and structural integrity.
5. **Optional Revocation** – Use the memory manager to invalidate tokens before natural expiry.

## Configuring the JWT Secret

Before generating tokens, configure the signing secret in your [`config.yaml`](https://github.com/jom-io/gorig/blob/main/config.yaml) or any source that the configuration system reads:

```yaml
jwt:
  key: "your-super-secret-string-min-32-characters"

```

The factory in [[`mid/tokenx/serv.go`](https://github.com/jom-io/gorig/blob/main/mid/tokenx/serv.go)](https://github.com/jom-io/gorig/blob/master/mid/tokenx/serv.go) retrieves this value via `configure.GetString("jwt.key", "")` and initializes the generator.

## Generating JWT Tokens

### Defining Custom Claims

First, extend the standard claims with your application data in [[`mid/tokenx/claims.go`](https://github.com/jom-io/gorig/blob/main/mid/tokenx/claims.go)](https://github.com/jom-io/gorig/blob/master/mid/tokenx/claims.go):

```go
type CustomClaims struct {
    UserID string `json:"uid,omitempty"`
    Role   string `json:"role,omitempty"`
    
    jwt.StandardClaims
}

```

### Creating the Token

The `jwtGenerator` in [[`mid/tokenx/jwt.generator.go`](https://github.com/jom-io/gorig/blob/main/mid/tokenx/jwt.generator.go)](https://github.com/jom-io/gorig/blob/master/mid/tokenx/jwt.generator.go) provides the `Generate` method:

```go
func (j *jwtGenerator) Generate(userId string, 
    userInfo map[string]interface{}, expireAt int64) (string, *errors.Error) {
    
    claims := CustomClaims{
        UserID: userId,
        Role:   fmt.Sprint(userInfo["role"]),
        StandardClaims: jwt.StandardClaims{
            ExpiresAt: expireAt,
            IssuedAt:  time.Now().Unix(),
            Issuer:    "gorig",
        },
    }

    token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
    signed, err := token.SignedString(j.secret)
    if err != nil {
        return "", errors.Sys("jwt sign string error", err)
    }
    return signed, nil
}

```

### Login Handler Example

Wire the generator into your authentication flow:

```go
func LoginHandler(c *gin.Context) {
    var req struct {
        Username string `json:"username"`
        Password string `json:"password"`
    }
    if err := c.BindJSON(&req); err != nil {
        c.JSON(http.StatusBadRequest, gin.H{"error": "invalid payload"})
        return
    }

    // ... verify credentials against database ...
    userID := "12345"
    roles := "admin"

    expiresAt := time.Now().Add(time.Hour).Unix()
    token, err := tokenx.NewJwtService().Generate(userID,
        map[string]interface{}{"role": roles}, expiresAt)
    if err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{"error": "token generation failed"})
        return
    }

    c.JSON(http.StatusOK, gin.H{"token": token})
}

```

## Validating and Parsing Tokens

### Token Verification

The `ParseToken` method in [[`mid/tokenx/jwt.generator.go`](https://github.com/jom-io/gorig/blob/main/mid/tokenx/jwt.generator.go)](https://github.com/jom-io/gorig/blob/master/mid/tokenx/jwt.generator.go) validates signatures, expiration, and structural integrity:

```go
func (j *jwtGenerator) ParseToken(tokenString string) (*CustomClaims, *errors.Error) {
    token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{},
        func(t *jwt.Token) (interface{}, error) {
            if _, ok := t.Method.(*jwt.SigningMethodHMAC); !ok {
                return nil, fmt.Errorf("unexpected signing method")
            }
            return j.secret, nil
        })

    if err != nil {
        if ve, ok := err.(*jwt.ValidationError); ok {
            switch {
            case ve.Errors&jwt.ValidationErrorMalformed != 0:
                return nil, errors.BadRequest("malformed token")
            case ve.Errors&jwt.ValidationErrorExpired != 0:
                return nil, errors.Unauthorized("token expired")
            case ve.Errors&jwt.ValidationErrorNotValidYet != 0:
                return nil, errors.Unauthorized("token not valid yet")
            default:
                return nil, errors.Unauthorized("invalid token")
            }
        }
        return nil, errors.Sys("jwt parse error", err)
    }

    if claims, ok := token.Claims.(*CustomClaims); ok && token.Valid {
        // Optional revocation check
        if memManager.IsRevoked(claims.Id) {
            return nil, errors.Unauthorized("token revoked")
        }
        return claims, nil
    }
    return nil, errors.Unauthorized("invalid token")
}

```

### Middleware Implementation

Protect routes using a Gin middleware that extracts the Bearer token:

```go
func JwtAuthMiddleware() gin.HandlerFunc {
    return func(c *gin.Context) {
        authHeader := c.GetHeader("Authorization")
        if !strings.HasPrefix(authHeader, "Bearer ") {
            c.AbortWithStatusJSON(http.StatusUnauthorized,
                gin.H{"error": "missing token"})
            return
        }
        tokenStr := strings.TrimPrefix(authHeader, "Bearer ")

        claims, err := tokenx.NewJwtService().ParseToken(tokenStr)
        if err != nil {
            c.AbortWithStatusJSON(http.StatusUnauthorized,
                gin.H{"error": err.Message()})
            return
        }

        c.Set("jwtClaims", claims)
        c.Next()
    }
}

// Application setup
router := gin.Default()
router.POST("/login", LoginHandler)

protected := router.Group("/api")
protected.Use(JwtAuthMiddleware())
{
    protected.GET("/profile", ProfileHandler)
}

```

## Managing Token Revocation

For scenarios requiring immediate token invalidation (logout or security breaches), Gorig includes an in-memory token manager in [[`mid/tokenx/mem.manager.go`](https://github.com/jom-io/gorig/blob/main/mid/tokenx/mem.manager.go)](https://github.com/jom-io/gorig/blob/master/mid/tokenx/mem.manager.go). You can store revoked token IDs and check against them during the `ParseToken` validation phase.

## Summary

- **Gorig's tokenx package** provides a complete JWT implementation built on `jwt-go` with HS-256 signing.
- **Configuration** requires only a `jwt.key` entry in your config file, accessed via [[`global/variable/variable.go`](https://github.com/jom-io/gorig/blob/main/global/variable/variable.go)](https://github.com/jom-io/gorig/blob/master/global/variable/variable.go).
- **Token generation** uses `jwtGenerator.Generate()` in [[`mid/tokenx/jwt.generator.go`](https://github.com/jom-io/gorig/blob/main/mid/tokenx/jwt.generator.go)](https://github.com/jom-io/gorig/blob/master/mid/tokenx/jwt.generator.go), supporting custom claims via [[`mid/tokenx/claims.go`](https://github.com/jom-io/gorig/blob/main/mid/tokenx/claims.go)](https://github.com/jom-io/gorig/blob/master/mid/tokenx/claims.go).
- **Validation** occurs through `ParseToken()`, which returns detailed error types for expired, malformed, or revoked tokens.
- **Middleware integration** follows standard Gin patterns, extracting Bearer tokens and storing claims in the request context.

## Frequently Asked Questions

### What signing algorithm does Gorig use for JWT tokens?

Gorig uses **HS-256** (HMAC with SHA-256) as the default signing method. The `jwtGenerator` struct in [[`mid/tokenx/jwt.generator.go`](https://github.com/jom-io/gorig/blob/main/mid/tokenx/jwt.generator.go)](https://github.com/jom-io/gorig/blob/master/mid/tokenx/jwt.generator.go) explicitly calls `jwt.NewWithClaims(jwt.SigningMethodHS256, claims)` and validates the signing method during parsing to prevent algorithm confusion attacks.

### How do I access JWT claims inside a protected handler?

After the `JwtAuthMiddleware` validates the token, it stores the `*CustomClaims` pointer in the Gin context using `c.Set("jwtClaims", claims)`. Inside your handler, retrieve them with `claims := c.MustGet("jwtClaims").(*tokenx.CustomClaims)`, then access custom fields like `claims.UserID` or `claims.Role` defined in [[`mid/tokenx/claims.go`](https://github.com/jom-io/gorig/blob/main/mid/tokenx/claims.go)](https://github.com/jom-io/gorig/blob/master/mid/tokenx/claims.go).

### Can I implement refresh tokens with Gorig's tokenx package?

Yes, though the package provides the building blocks rather than a complete refresh flow. You can generate long-lived refresh tokens using the same `Generate()` method with extended expiration times, store them in the in-memory manager ([[`mid/tokenx/mem.manager.go`](https://github.com/jom-io/gorig/blob/main/mid/tokenx/mem.manager.go)](https://github.com/jom-io/gorig/blob/master/mid/tokenx/mem.manager.go)), and validate them against the store before issuing new access tokens. For production systems, replace the in-memory store with Redis or database persistence.

### Where is the JWT secret configured in a Gorig application?

The secret is defined in your configuration file (e.g., [`config.yaml`](https://github.com/jom-io/gorig/blob/main/config.yaml)) under the `jwt.key` path. The factory function in [[`mid/tokenx/serv.go`](https://github.com/jom-io/gorig/blob/main/mid/tokenx/serv.go)](https://github.com/jom-io/gorig/blob/master/mid/tokenx/serv.go) retrieves this value via `configure.GetString("jwt.key", "")` from the global configuration system defined in [[`global/variable/variable.go`](https://github.com/jom-io/gorig/blob/main/global/variable/variable.go)](https://github.com/jom-io/gorig/blob/master/global/variable/variable.go). The secret is then injected into the `jwtGenerator` struct as a byte slice for HMAC signing.