appleboy/gin-jwt: JWT authentication middleware for Gin, with refresh tokens and Redis-backed storage
JWT Middleware for Gin framework
At a glance
- What is it?
- gin-jwt wraps golang-jwt/jwt in Gin middleware and adds login, refresh and logout handlers, a pluggable refresh-token store and cookie support. It suits Go teams that already run Gin and want token auth without writing the plumbing themselves.
- Who is it for?
- Adopt gin-jwt if you already run Gin and want token issuance, refresh and authorization behind a middleware you configure rather than write. Do not adopt it if you need an identity provider, session management, or a framework that is not Gin: this is a token layer, and the README's security notice puts the secret and algorithm choices on you.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 9 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The gap gin-jwt fills between Gin and golang-jwt/jwt
Gin gives you routing and middleware chaining. golang-jwt/jwt gives you signing and parsing. Neither gives you the part in between: where does the token come from, how is it refreshed, where do you keep the refresh token so it can be revoked, and how does a route check that the caller is allowed in. gin-jwt is that in-between layer. It is a middleware package for Gin built on top of golang-jwt/jwt, and its feature list names login, refresh and logout handlers, customizable authentication, authorization and claims, cookie and header token support, and pluggable refresh token storage. The intended reader is a Go developer who has a Gin service and wants token auth as configuration rather than as a subsystem they own. If your service is not Gin, the package is the wrong shape entirely, because the handlers are wired into Gin's context and route registration.
How the middleware, handlers and refresh store fit together
The repository layout shows the split. auth_jwt.go holds the main middleware, auth_jwt_redis.go adds the Redis path, and core/ and store/ hold the pieces those files depend on. The README describes three handler roles: a login handler that validates credentials and issues a token, a refresh handler that exchanges a refresh token for a new one, and a logout handler that invalidates it. Requests then pass through MiddlewareFunc, which parses the token from either the Authorization header or a cookie, depending on configuration.
The refresh token is where the design gets interesting. The README states the refresh tokens are RFC 6749 compliant, which is the OAuth 2.0 standard, and that storage is pluggable: in-memory, or Redis with client-side caching. That choice matters more than it looks. An in-memory store lives inside one process, so a refresh token issued by one instance is unknown to the next instance behind a load balancer. Redis moves that state out of the process, and the go.mod pulls in github.com/redis/rueidis as the client. The README also documents a fallback behavior for the Redis configuration, which is worth reading before you assume a Redis outage degrades gracefully.
Authorization is a separate hook. The README documents an Authorizer function that receives the request context and the parsed claims and decides whether the request continues, with examples for role-based, path-based and method-plus-path rules. That is deliberately thin: gin-jwt does not ship a policy language, so any nontrivial rule set ends up as Go code you maintain.
Installing gin-jwt and issuing a first token
The package is a Go module at github.com/appleboy/gin-jwt/v3, so it is fetched with go get. The go.mod in the repository declares go 1.26.0 and requires Gin v1.12.0 and golang-jwt/jwt/v5 v5.3.1, so a project on an older Go toolchain will need to move before it can depend on this version.
go get github.com/appleboy/gin-jwt/v3After that, the middleware is configured with a realm name, a signing key and the handlers. The README's quick start example is the reference to copy from, since it also shows the refresh route and the authorization example. The security notice is explicit that the key should be at least 256 bits (32 bytes) and never a dictionary word or predictable pattern. What you should see after starting the server is a login endpoint that returns a token on valid credentials, and a protected route that rejects requests without one. The _example/ directory in the repository holds the fuller variants, including the Redis store and the authorization examples, and those are the ones worth reading before you write your own handler bodies.
Where gin-jwt stops being the right tool
The security notice is the most honest part of the README, and it also points at the main limitation. gin-jwt does not manage your secrets. It asks for a key of at least 256 bits and warns against simple passwords and predictable patterns, and it suggests RS256 as the alternative. Nothing in the middleware generates, rotates or stores that secret for you. If your team has no answer for where the signing key lives, gin-jwt will not supply one.
The second boundary is scope. This is authentication and authorization for a Gin service. It is not an identity provider, so there is no user directory, no password reset flow, no multi-factor step, and no consent screen. The README's OAuth material is about accepting tokens from providers such as Azure AD through a dynamic key function, not about running the provider. Teams that need those features are usually better served by putting an identity provider in front and treating gin-jwt, if they use it at all, as a token verifier.
Third, the refresh store choice is a deployment decision, not a library detail. The README documents an in-memory store and a Redis store. A single-instance service can use memory. Anything scaled horizontally needs the Redis path, which means the go.mod dependency on github.com/redis/rueidis and an operational dependency on Redis availability. The README describes a fallback behavior for the Redis configuration; read that section before assuming the failure mode matches your expectations.
gin-jwt against hand-rolling gin middleware over golang-jwt/jwt
The realistic alternative is not another middleware package. It is writing the middleware yourself on top of golang-jwt/jwt/v5, which gin-jwt already depends on. The difference is what you inherit. Hand-rolled, you control the token claims, the header and cookie parsing, and the refresh semantics exactly, and you carry the maintenance for all of it, including the parts that are easy to get subtly wrong, such as clock skew and required-claim validation.
gin-jwt has opinions in those places. The README documents a leeway option for clock skew tolerance, options for JSON number handling, and required claims validation, plus a section on combining multiple parsing options. It also documents a token generator for creating tokens directly without going through HTTP middleware, which is useful for tests or for issuing tokens from a job. None of this is impossible to write yourself. The question is whether you want to, and whether you want to keep it current as golang-jwt/jwt releases change. The cost of the library is that its handler signatures and configuration struct define your route wiring, and moving off it later means rewriting that layer.
Maintenance, licensing and what a version bump costs
The repository is not archived, and the last push was on 2026-09-21, with v3.5.3 released the same day and v3.5.2 on 2026-09-05. That is a short gap between releases, and the release history shows v3.5.1 in April 2026, so the cadence over the past months has been uneven rather than steady. The project is MIT licensed, which permits commercial use, modification and redistribution provided the copyright notice and permission notice are included; that is a summary of the licence text, not legal advice, and your own counsel should review how it interacts with your distribution model.
The upgrade cost is mostly the Go toolchain. The go.mod declares go 1.26.0 and pins Gin v1.12.0, golang-jwt/jwt/v5 v5.3.1 and rueidis v1.0.76. A service on an older Go release cannot simply add this module without upgrading, and a service pinned to an older Gin or golang-jwt/jwt major version may hit conflicts during resolution. The major version in the module path, /v3, means v2 and v3 imports can coexist during a migration, which softens the move but does not remove it. The Makefile gives the project's own workflow: make test runs go test with the race detector and a coverage profile, make lint runs golangci-lint, and make vet runs go vet. Running those against your fork is the cheapest way to see whether your toolchain is compatible.
Editorial conclusion
Adopt gin-jwt if you already run Gin and want token issuance, refresh and authorization behind a middleware you configure rather than write. Do not adopt it if you need an identity provider, session management, or a framework that is not Gin: this is a token layer, and the README's security notice puts the secret and algorithm choices on you. Before wiring it into a service, check that your Gin and golang-jwt/jwt versions satisfy the go.mod requirements, and read the security notice's minimum secret length of 256 bits against how you actually plan to generate and rotate that secret.
Frequently asked questions
What does JWT stand for in gin-jwt?
JWT stands for JSON Web Token, the token format the middleware issues and parses. gin-jwt builds on the golang-jwt/jwt library to handle signing and parsing for Gin routes.
Can a JWT issued by gin-jwt never expire?
The middleware is configured with a Timeout value for the token and a MaxRefresh value for how long it can be refreshed, so expiry is part of the configuration rather than something the library leaves open. The README does not describe an option for a token that never expires.
Why use JWT instead of a session with gin-jwt?
The README does not compare JWT against server-side sessions. What it does document is the mechanism it provides: login, refresh and logout handlers, plus a pluggable refresh token store in memory or Redis, which is the state a token-based setup keeps instead of a session store.
Is the JWT token deprecated in gin-jwt?
No. The README describes gin-jwt as a JWT authentication middleware built on golang-jwt/jwt, and the current release line is v3.5.3, so JWT is the mechanism the project is built around.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/appleboy-gin-jwt)