# How to Implement JWT Authentication Middleware in Kratos

> Implement JWT authentication middleware in Kratos easily. Discover Kratos advanced JWT middleware for secure server-side token validation and client-side generation.

- Repository: [Kratos/kratos](https://github.com/go-kratos/kratos)
- Tags: how-to-guide
- Published: 2026-03-02

---

**Kratos provides a production-ready JWT middleware in [`middleware/auth/jwt/jwt.go`](https://github.com/go-kratos/kratos/blob/main/middleware/auth/jwt/jwt.go) that handles both server-side token validation and client-side token generation.**

The go-kratos/kratos framework ships with a complete JSON Web Token (JWT) authentication solution that plugs directly into the middleware chain. Located in the standard library at [`middleware/auth/jwt/jwt.go`](https://github.com/go-kratos/kratos/blob/main/middleware/auth/jwt/jwt.go), this implementation supports **HS256**, **RS256**, and other signing algorithms while maintaining compatibility with Kratos' transport abstraction and error handling conventions.

## Understanding the Kratos JWT Middleware Architecture

The JWT middleware follows Kratos' standard **middleware pattern**, allowing you to attach authentication logic to HTTP and gRPC transports uniformly.

### Core Components and File Structure

The implementation spans several key files:

- [`middleware/auth/jwt/jwt.go`](https://github.com/go-kratos/kratos/blob/main/middleware/auth/jwt/jwt.go) – Contains `Server()` and `Client()` constructors, option functions, and context helpers
- [`middleware/auth/jwt/jwt_test.go`](https://github.com/go-kratos/kratos/blob/main/middleware/auth/jwt/jwt_test.go) – Unit tests covering claim factories and error scenarios
- [`errors/errors.go`](https://github.com/go-kratos/kratos/blob/main/errors/errors.go) – Defines `errors.Unauthorized` constructors used for JWT failures

The middleware uses the `github.com/golang-jwt/jwt/v5` library internally and exposes configuration through functional options.

## Implementing Server-Side JWT Validation

Use the `jwt.Server()` function to validate incoming **Bearer tokens** from the `Authorization` header. According to the source code in lines 78-123, the server middleware:

1. Extracts the token from the transport context
2. Parses it using `jwt.ParseWithClaims` (when a claim factory is provided) or `jwt.Parse`
3. Maps validation failures to Kratos-specific errors like `ErrTokenInvalid`, `ErrTokenExpired`, and `ErrUnSupportSigningMethod`
4. Stores verified claims in the request context via `NewContext`

### Server Configuration Example

Define a custom claim type and configure the validation middleware:

```go
import (
    "github.com/go-kratos/kratos/v2/middleware"
    "github.com/go-kratos/kratos/v2/transport/http"
    "github.com/go-kratos/kratos/v2/middleware/auth/jwt"
    "github.com/golang-jwt/jwt/v5"
)

type MyClaims struct {
    jwt.RegisteredClaims
    Role string `json:"role"`
}

func keyFunc(token *jwt.Token) (any, error) {
    return []byte("my-secret-key"), nil
}

srv := http.NewServer(
    http.Address(":8080"),
    http.Middleware(
        jwt.Server(keyFunc,
            jwt.WithSigningMethod(jwt.SigningMethodHS256),
            jwt.WithClaims(func() jwt.Claims { return &MyClaims{} }),
        ),
    ),
)

```

## Configuring Client-Side JWT Generation

The `jwt.Client()` middleware (implemented in lines 30-64) automatically generates and signs JWTs for outgoing requests. It:

- Creates a new token with `jwt.NewWithClaims(o.signingMethod, o.claims())`
- Injects custom headers via `WithTokenHeader`
- Signs the token using your provided **keyProvider** function
- Adds the resulting Bearer token to the `Authorization` header using `transport.FromClientContext`

### Client Middleware Setup

Configure the client to attach a signed JWT to every request:

```go
func keyProvider(token *jwt.Token) (any, error) {
    return []byte("my-secret-key"), nil
}

customHeader := map[string]any{"kid": "my-key-id"}

client := http.NewClient(
    http.Target("http://localhost:8080"),
    http.Middleware(
        jwt.Client(keyProvider,
            jwt.WithSigningMethod(jwt.SigningMethodHS256),
            jwt.WithTokenHeader(customHeader),
        ),
    ),
)

```

## Accessing JWT Claims in Handlers

After the server middleware validates a token, retrieve the claims inside your service handlers using `FromContext`. This helper (defined in lines 68-76) returns the `jwt.Claims` interface and a boolean indicating success.

### Retrieving Claims in Service Methods

```go
func (s *MyService) Hello(ctx context.Context, req *pb.HelloReq) (*pb.HelloResp, error) {
    if claims, ok := jwt.FromContext(ctx); ok {
        if myClaims, ok := claims.(*MyClaims); ok {
            // Access custom fields
            fmt.Printf("User role: %s\n", myClaims.Role)
        }
    }
    return &pb.HelloResp{Message: "Hello, world!"}, nil
}

```

## Customizing JWT Options

The middleware exposes three primary **Option** functions for configuration:

- **`WithSigningMethod(method jwt.SigningMethod)`** – Sets the algorithm (HS256, RS256, etc.)
- **`WithClaims(f func() jwt.Claims)`** – Supplies a factory function returning a fresh claim instance for type-safe parsing
- **`WithTokenHeader(header map[string]any)`** – Adds custom JWT header entries (useful for Key ID or algorithm variants) on the client side

These options apply to both server and client middleware constructors.

## Summary

- The Kratos JWT implementation resides in [`middleware/auth/jwt/jwt.go`](https://github.com/go-kratos/kratos/blob/main/middleware/auth/jwt/jwt.go) and supports both server validation and client generation.
- Use `jwt.Server()` with a **Keyfunc** to validate incoming Bearer tokens and map errors to `errors.Unauthorized`.
- Use `jwt.Client()` with a **keyProvider** to automatically sign and inject tokens into outgoing requests.
- Configure signing algorithms, custom claims, and headers via functional options: `WithSigningMethod`, `WithClaims`, and `WithTokenHeader`.
- Access validated claims in handlers using `jwt.FromContext()` after storing them with `NewContext`.

## Frequently Asked Questions

### How do I change the signing algorithm in Kratos JWT middleware?

Pass the desired algorithm via `jwt.WithSigningMethod()`. The middleware accepts any `jwt.SigningMethod` implementation, including `jwt.SigningMethodHS256` for HMAC or `jwt.SigningMethodRS256` for RSA. Ensure your **Keyfunc** or **keyProvider** returns the appropriate key type (byte slice for HS256, *rsa.PublicKey/*rsa.PrivateKey for RS256).

### Where does Kratos store JWT claims after validation?

The server middleware stores claims in the request context using `context.WithValue` through the internal `NewContext` helper. Service handlers retrieve them with `jwt.FromContext(ctx)`, which returns the claims and a boolean indicating whether a valid token was present.

### Can I use custom JWT claims with the Kratos middleware?

Yes. Define a struct embedding `jwt.RegisteredClaims` (or implementing `jwt.Claims`), then pass a factory function to `jwt.WithClaims(func() jwt.Claims { return &MyCustomClaims{} })`. This ensures `jwt.ParseWithClaims` populates your custom fields during validation.

### How do I handle JWT validation errors in Kratos?

The middleware automatically converts standard JWT validation errors into Kratos-specific errors such as `ErrTokenInvalid`, `ErrTokenExpired`, and `ErrUnSupportSigningMethod`. These are constructed using `errors.Unauthorized` from [`errors/errors.go`](https://github.com/go-kratos/kratos/blob/main/errors/errors.go), allowing you to handle authentication failures uniformly across HTTP and gRPC transports.