How to Implement JWT Authentication in Gorig: A Complete Guide
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/master/mid/tokenx/jwt.generator.go) that creates and parses JWT strings using HS-256 signing and theJwtKeyvalue from global configuration.CustomClaims– Extendsjwt.StandardClaimswith application-specific fields likeUserIDandRoles, defined in [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/master/mid/tokenx/mem.manager.go).- Service Factory – Returns a ready-to-use
jwtGeneratorinstance, pulling the secret key from the configuration system via [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/master/mid/tokenx/serv.go).
Request Flow
- Configuration – Define the
jwt.keysecret in your configuration file. - Startup – The
tokenxservice instantiates during application boot (see [bootstrap/startup.go](https://github.com/jom-io/gorig/blob/master/bootstrap/startup.go)), readingJwtKeyto create the generator. - Generate – After successful authentication, call
Generateto create a signed token with custom claims. - Validate – In protected handlers, call
ParseTokento verify signatures, expiration, and structural integrity. - 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 or any source that the configuration system reads:
jwt:
key: "your-super-secret-string-min-32-characters"
The factory in [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/master/mid/tokenx/claims.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/master/mid/tokenx/jwt.generator.go) provides the Generate method:
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:
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/master/mid/tokenx/jwt.generator.go) validates signatures, expiration, and structural integrity:
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:
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/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-gowith HS-256 signing. - Configuration requires only a
jwt.keyentry in your config file, accessed via [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/master/mid/tokenx/jwt.generator.go), supporting custom claims via [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/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/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/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) under the jwt.key path. The factory function in [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/master/global/variable/variable.go). The secret is then injected into the jwtGenerator struct as a byte slice for HMAC signing.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →