### Run Example Go Application Source: https://github.com/hertz-contrib/jwt/blob/main/README.md This command executes the basic JWT example Go application. Ensure you have Go installed and the necessary dependencies downloaded. ```sh go run example/basic/main.go ``` -------------------------------- ### Install Hertz-JWT Middleware Source: https://github.com/hertz-contrib/jwt/blob/main/README.md Use this command to download and install the Hertz-JWT middleware. Ensure GO111MODULE is set to on. ```sh export GO111MODULE=on go get github.com/hertz-contrib/jwt ``` -------------------------------- ### Login Request Example Source: https://context7.com/hertz-contrib/jwt/llms.txt This curl command demonstrates how to log in to the server by sending a POST request with JSON payload containing username and password. ```bash curl -X POST http://localhost:8888/login \ -H "Content-Type: application/json" \ -d '{"username":"admin","password":"admin"}' ``` -------------------------------- ### Complete Server Setup with JWT Authentication Source: https://context7.com/hertz-contrib/jwt/llms.txt This Go code sets up a Hertz server with JWT middleware for authentication. It includes configurations for login, token validation, identity handling, authorization, and response formatting. Ensure correct import paths and dependencies are met. ```go package main import ( "context" "log" "net/http" "time" "github.com/cloudwego/hertz/pkg/app" "github.com/cloudwego/hertz/pkg/app/server" "github.com/cloudwego/hertz/pkg/protocol" "github.com/hertz-contrib/jwt" ) type login struct { Username string `form:"username,required" json:"username,required"` Password string `form:"password,required" json:"password,required"` } type User struct{ UserName string } var identityKey = "id" func main() { h := server.Default() authMiddleware, err := jwt.New(&jwt.HertzJWTMiddleware{ Realm: "test zone", SigningAlgorithm: "HS256", Key: []byte("secret key"), Timeout: time.Hour, MaxRefresh: time.Hour, IdentityKey: identityKey, Authenticator: func(ctx context.Context, c *app.RequestContext) (interface{}, error) { var l login if err := c.BindAndValidate(&l); err != nil { return "", jwt.ErrMissingLoginValues } if (l.Username == "admin" && l.Password == "admin") || (l.Username == "test" && l.Password == "test") { return &User{UserName: l.Username}, nil } return nil, jwt.ErrFailedAuthentication }, PayloadFunc: func(data interface{}) jwt.MapClaims { if v, ok := data.(*User); ok { return jwt.MapClaims{identityKey: v.UserName} } return jwt.MapClaims{} }, IdentityHandler: func(ctx context.Context, c *app.RequestContext) interface{} { claims := jwt.ExtractClaims(ctx, c) return &User{UserName: claims[identityKey].(string)} }, Authorizator: func(data interface{}, ctx context.Context, c *app.RequestContext) bool { v, ok := data.(*User) return ok && v.UserName == "admin" }, Unauthorized: func(ctx context.Context, c *app.RequestContext, code int, message string) { c.JSON(code, map[string]interface{}{"code": code, "message": message}) }, LoginResponse: func(ctx context.Context, c *app.RequestContext, code int, token string, expire time.Time) { c.JSON(http.StatusOK, map[string]interface{}{ "code": code, "token": token, "expire": expire.Format(time.RFC3339), }) }, TokenLookup: "header: Authorization, query: token, cookie: jwt", TokenHeadName: "Bearer", SendCookie: true, CookieName: "jwt", CookieSameSite: protocol.CookieSameSiteDefaultMode, TimeFunc: time.Now, }) if err != nil { log.Fatal("JWT Error: " + err.Error()) } h.POST("/login", authMiddleware.LoginHandler) h.POST("/logout", authMiddleware.LogoutHandler) auth := h.Group("/auth") auth.GET("/refresh_token", authMiddleware.RefreshHandler) auth.Use(authMiddleware.MiddlewareFunc()) { auth.GET("/ping", func(ctx context.Context, c *app.RequestContext) { claims := jwt.ExtractClaims(ctx, c) c.JSON(200, map[string]interface{}{ "user": claims[identityKey], "ping": "pong", }) }) } h.Spin() // listens on :8888 by default } ``` -------------------------------- ### Login API Response Source: https://github.com/hertz-contrib/jwt/blob/main/README.md Example of a successful response from the login API, including a JWT token and expiration time. ```shell POST /login HTTP/1.1 Accept: application/json, */*;q=0.5 Accept-Encoding: gzip, deflate Connection: keep-alive Content-Length: 42 Content-Type: application/json Host: localhost:8888 User-Agent: HTTPie/3.2.1 { "password": "admin", "username": "admin" } HTTP/1.1 200 OK Content-Length: 212 Content-Type: application/json; charset=utf-8 Date: Sun, 05 Jun 2022 04:49:20 GMT Server: hertz { "code": 200, "expire": "2022-06-05T13:49:20+08:00", "token": "**" } ``` -------------------------------- ### Access Protected Route Example Source: https://context7.com/hertz-contrib/jwt/llms.txt This curl command shows how to access a protected route by including the JWT token in the Authorization header. ```bash curl -H "Authorization: Bearer eyJ..." http://localhost:8888/auth/ping ``` -------------------------------- ### Hertz JWT Middleware Setup and Usage Source: https://github.com/hertz-contrib/jwt/blob/main/README.md This Go code sets up the Hertz JWT middleware, configuring realm, secret key, timeouts, and various handlers for authentication, authorization, and token extraction. It then integrates this middleware into a Hertz server to protect routes and handle login requests. ```go package main import ( "context" "log" "time" "github.com/cloudwego/hertz/pkg/app" "github.com/cloudwego/hertz/pkg/app/server" "github.com/hertz-contrib/jwt" ) type login struct { Username string `form:"username,required" json:"username,required"` Password string `form:"password,required" json:"password,required"` } var identityKey = "id" func PingHandler(c context.Context, ctx *app.RequestContext) { ctx.JSON(200, map[string]string{ "ping": "pong", }) } // User demo type User struct { UserName string FirstName string LastName string } func main() { h := server.Default() // the jwt middleware authMiddleware, err := jwt.New(&jwt.HertzJWTMiddleware{ Realm: "test zone", Key: []byte("secret key"), Timeout: time.Hour, MaxRefresh: time.Hour, IdentityKey: identityKey, PayloadFunc: func(data interface{}) jwt.MapClaims { if v, ok := data.(*User); ok { return jwt.MapClaims{ identityKey: v.UserName, } } return jwt.MapClaims{} }, IdentityHandler: func(ctx context.Context, c *app.RequestContext) interface{} { claims := jwt.ExtractClaims(ctx, c) return &User{ UserName: claims[identityKey].(string), } }, Authenticator: func(ctx context.Context, c *app.RequestContext) (interface{}, error) { var loginVals login if err := c.BindAndValidate(&loginVals); err != nil { return "", jwt.ErrMissingLoginValues } userID := loginVals.Username password := loginVals.Password if (userID == "admin" && password == "admin") || (userID == "test" && password == "test") { return &User{ UserName: userID, LastName: "Hertz", FirstName: "CloudWeGo", }, nil } return nil, jwt.ErrFailedAuthentication }, Authorizator: func(data interface{}, ctx context.Context, c *app.RequestContext) bool { if v, ok := data.(*User); ok && v.UserName == "admin" { return true } return false }, Unauthorized: func(ctx context.Context, c *app.RequestContext, code int, message string) { c.JSON(code, map[string]interface{}{ "code": code, "message": message, }) }, // TokenLookup is a string in the form of ":" that is used // to extract token from the request. // Optional. Default value "header:Authorization". // Possible values: // - "header:" // - "query:" // - "cookie:" // - "param:" TokenLookup: "header: Authorization, query: token, cookie: jwt", // TokenLookup: "query:token", // TokenLookup: "cookie:token", // TokenHeadName is a string in the header. Default value is "Bearer". If you want empty value, use WithoutDefaultTokenHeadName. TokenHeadName: "Bearer", // TimeFunc provides the current time. You can override it to use another time value. This is useful for testing or if your server uses a different time zone than your tokens. TimeFunc: time.Now, }) if err != nil { log.Fatal("JWT Error:" + err.Error()) } // When you use jwt.New(), the function is already automatically called for checking, // which means you don't need to call it again. errInit := authMiddleware.MiddlewareInit() if errInit != nil { log.Fatal("authMiddleware.MiddlewareInit() Error:" + errInit.Error()) } h.POST("/login", authMiddleware.LoginHandler) h.NoRoute(authMiddleware.MiddlewareFunc(), func(ctx context.Context, c *app.RequestContext) { claims := jwt.ExtractClaims(ctx, c) log.Printf("NoRoute claims: %#v\n", claims) c.JSON(404, map[string]string{"code": "PAGE_NOT_FOUND", "message": "Page not found"}) }) auth := h.Group("/auth") // Refresh time can be longer than token timeout auth.GET("/refresh_token", authMiddleware.RefreshHandler) auth.Use(authMiddleware.MiddlewareFunc()) { auth.GET("/ping", PingHandler) } h.Spin() } ``` -------------------------------- ### RSA Asymmetric Signing Configuration Source: https://context7.com/hertz-contrib/jwt/llms.txt Configuration example for using RSA asymmetric signing algorithms (RS256/RS384/RS512) with JWT. It specifies the use of private and public key files. ```APIDOC ## RSA asymmetric signing (RS256/RS384/RS512) Use `PrivKeyFile`/`PrivKeyBytes` and `PubKeyFile`/`PubKeyBytes` (with optional `PrivateKeyPassphrase`) instead of `Key` when using RSA signing algorithms. ### Configuration Example ```go authMiddleware, err := jwt.New(&jwt.HertzJWTMiddleware{ Realm: "secure zone", SigningAlgorithm: "RS256", PrivKeyFile: "./testdata/jwtRS256.key", PubKeyFile: "./testdata/jwtRS256.key.pub", // PrivateKeyPassphrase: "passphrase", // if the key is encrypted Timeout: time.Hour, MaxRefresh: 6 * time.Hour, Authenticator: func(ctx context.Context, c *app.RequestContext) (interface{}, error) { // ... credential check return &User{UserName: "alice"}, nil }, PayloadFunc: func(data interface{}) jwt.MapClaims { if u, ok := data.(*User); ok { return jwt.MapClaims{"id": u.UserName} } return jwt.MapClaims{} }, }) if err != nil { log.Fatal(err) } ``` ``` -------------------------------- ### Refresh Token API Request Source: https://github.com/hertz-contrib/jwt/blob/main/README.md Send a GET request to the refresh token endpoint with the Authorization header. ```bash http -v -f GET localhost:8888/auth/refresh_token "Authorization:Bearer xxxxxxxxx" "Content-Type: application/json" ``` -------------------------------- ### Refresh Token Example Source: https://context7.com/hertz-contrib/jwt/llms.txt This curl command demonstrates how to refresh an expired JWT token by sending a GET request to the refresh token endpoint with the current token. ```bash curl -H "Authorization: Bearer eyJ..." http://localhost:8888/auth/refresh_token ``` -------------------------------- ### Refresh Token API Response Source: https://github.com/hertz-contrib/jwt/blob/main/README.md Example of a successful response after refreshing a token, providing a new token and expiration time. ```shell GET /auth/refresh_token HTTP/1.1 Accept: */* Accept-Encoding: gzip, deflate Authorization: Bearer ** Connection: keep-alive Content-Type: application/json Host: localhost:8888 User-Agent: HTTPie/3.2.1 HTTP/1.1 200 OK Content-Length: 212 Content-Type: application/json; charset=utf-8 Date: Sun, 05 Jun 2022 04:50:40 GMT Server: hertz { "code": 200, "expire": "2022-06-05T13:50:41+08:00", "token": "**" } ``` -------------------------------- ### Unauthorized Access Example Source: https://context7.com/hertz-contrib/jwt/llms.txt This curl command illustrates an unauthorized access attempt to a protected route with an invalid or insufficient token, resulting in a 403 Forbidden response. ```bash curl -H "Authorization: Bearer " http://localhost:8888/auth/ping ``` -------------------------------- ### Custom TimeoutFunc for Dynamic Expiry Source: https://context7.com/hertz-contrib/jwt/llms.txt Override `TimeoutFunc` to compute a token-specific timeout based on claims. For example, grant longer sessions for premium users. ```go authMiddleware, err := jwt.New(&jwt.HertzJWTMiddleware{ Key: []byte("secret"), Timeout: time.Hour, // fallback default TimeoutFunc: func(claims jwt.MapClaims) time.Duration { if role, ok := claims["role"].(string); ok && role == "premium" { return 7 * 24 * time.Hour } return time.Hour }, Authenticator: func(ctx context.Context, c *app.RequestContext) (interface{}, error) { return map[string]string{"role": "premium", "user": "alice"}, nil }, PayloadFunc: func(data interface{}) jwt.MapClaims { if m, ok := data.(map[string]string); ok { return jwt.MapClaims{"id": m["user"], "role": m["role"]} } return jwt.MapClaims{} }, }) ``` -------------------------------- ### Configure RSA Asymmetric Signing (RS256) Source: https://context7.com/hertz-contrib/jwt/llms.txt For RSA signing algorithms like RS256, use `PrivKeyFile`/`PrivKeyBytes` and `PubKeyFile`/`PubKeyBytes` instead of the generic `Key`. Provide `PrivateKeyPassphrase` if the key is encrypted. ```go authMiddleware, err := jwt.New(&jwt.HertzJWTMiddleware{ Realm: "secure zone", SigningAlgorithm: "RS256", PrivKeyFile: "./testdata/jwtRS256.key", PubKeyFile: "./testdata/jwtRS256.key.pub", // PrivateKeyPassphrase: "passphrase", // if the key is encrypted Timeout: time.Hour, MaxRefresh: 6 * time.Hour, Authenticator: func(ctx context.Context, c *app.RequestContext) (interface{}, error) { // ... credential check return &User{UserName: "alice"}, nil }, PayloadFunc: func(data interface{}) jwt.MapClaims { if u, ok := data.(*User); ok { return jwt.MapClaims{"id": u.UserName} } return jwt.MapClaims{} }, }) if err != nil { log.Fatal(err) } ``` -------------------------------- ### Create and Initialize JWT Middleware Source: https://context7.com/hertz-contrib/jwt/llms.txt Create a new JWT middleware instance by providing a configuration struct. This includes setting up authentication, payload functions, identity handling, authorization, and error responses. The `Key` is required for HMAC algorithms. ```go authMiddleware, err := jwt.New(&jwt.HertzJWTMiddleware{ Realm: "my api", SigningAlgorithm: "HS256", // default; also HS384, HS512, RS256, RS384, RS512 Key: []byte("secret"), // required for HMAC algorithms Timeout: time.Hour, // token validity window MaxRefresh: time.Hour, // how long after expiry a refresh is still allowed Authenticator: func(ctx context.Context, c *app.RequestContext) (interface{}, error) { var creds struct { Username string `json:"username,required"` Password string `json:"password,required"` } if err := c.BindAndValidate(&creds); err != nil { return nil, jwt.ErrMissingLoginValues } if creds.Username == "admin" && creds.Password == "secret" { return &User{UserName: creds.Username}, nil } return nil, jwt.ErrFailedAuthentication }, PayloadFunc: func(data interface{}) jwt.MapClaims { if u, ok := data.(*User); ok { return jwt.MapClaims{"id": u.UserName} } return jwt.MapClaims{} }, IdentityKey: "id", IdentityHandler: func(ctx context.Context, c *app.RequestContext) interface{} { claims := jwt.ExtractClaims(ctx, c) return &User{UserName: claims["id"].(string)} }, Authorizator: func(data interface{}, ctx context.Context, c *app.RequestContext) bool { u, ok := data.(*User) return ok && u.UserName == "admin" }, Unauthorized: func(ctx context.Context, c *app.RequestContext, code int, message string) { c.JSON(code, map[string]interface{}{"code": code, "message": message}) }, }) if err != nil { log.Fatal("JWT init error: " + err.Error()) } ``` -------------------------------- ### Validate and Apply Defaults to JWT Middleware Source: https://context7.com/hertz-contrib/jwt/llms.txt Use `MiddlewareInit` to automatically set defaults and validate the configuration of the JWT middleware. This is typically called by `jwt.New`. ```go mw := &jwt.HertzJWTMiddleware{ Realm: "zone", Key: []byte("secret"), Authenticator: func(ctx context.Context, c *app.RequestContext) (interface{}, error) { return "user", nil }, } if err := mw.MiddlewareInit(); err != nil { log.Fatal(err) // e.g. ErrMissingSecretKey } ``` -------------------------------- ### jwt.New - Create and initialize the middleware Source: https://context7.com/hertz-contrib/jwt/llms.txt Creates and initializes the JWT middleware by accepting a configuration struct, validating it, and returning the middleware or an error. This is the primary function for setting up JWT authentication. ```APIDOC ## jwt.New — Create and initialize the middleware `New` accepts a pointer to a `HertzJWTMiddleware` configuration struct, calls `MiddlewareInit()` to validate and apply defaults, and returns the ready-to-use middleware or an error. ```go authMiddleware, err := jwt.New(&jwt.HertzJWTMiddleware{ Realm: "my api", SigningAlgorithm: "HS256", // default; also HS384, HS512, RS256, RS384, RS512 Key: []byte("secret"), // required for HMAC algorithms Timeout: time.Hour, // token validity window MaxRefresh: time.Hour, // how long after expiry a refresh is still allowed Authenticator: func(ctx context.Context, c *app.RequestContext) (interface{}, error) { var creds struct { Username string `json:"username,required"` Password string `json:"password,required"` } if err := c.BindAndValidate(&creds); err != nil { return nil, jwt.ErrMissingLoginValues } if creds.Username == "admin" && creds.Password == "secret" { return &User{UserName: creds.Username}, nil } return nil, jwt.ErrFailedAuthentication }, PayloadFunc: func(data interface{}) jwt.MapClaims { if u, ok := data.(*User); ok { return jwt.MapClaims{"id": u.UserName} } return jwt.MapClaims{} }, IdentityKey: "id", IdentityHandler: func(ctx context.Context, c *app.RequestContext) interface{} { claims := jwt.ExtractClaims(ctx, c) return &User{UserName: claims["id"].(string)} }, Authorizator: func(data interface{}, ctx context.Context, c *app.RequestContext) bool { u, ok := data.(*User) return ok && u.UserName == "admin" }, Unauthorized: func(ctx context.Context, c *app.RequestContext, code int, message string) { c.JSON(code, map[string]interface{}{"code": code, "message": message}) }, }) if err != nil { log.Fatal("JWT init error: " + err.Error()) } ``` ``` -------------------------------- ### Ping API Request Source: https://github.com/hertz-contrib/jwt/blob/main/README.md Use this command to ping the server after logging in. Requires a valid Authorization token. ```bash http -f GET localhost:8888/auth/ping "Authorization:Bearer xxxxxxxxx" "Content-Type: application/json" ``` -------------------------------- ### Import Hertz-JWT Middleware Source: https://github.com/hertz-contrib/jwt/blob/main/README.md Import the Hertz-JWT package into your Go project to use its functionalities. ```go import "github.com/hertz-contrib/jwt" ``` -------------------------------- ### Login API Request Source: https://github.com/hertz-contrib/jwt/blob/main/README.md Use this command to send a POST request to the login endpoint with username and password. ```sh http -v --json POST localhost:8888/login username=admin password=admin ``` -------------------------------- ### Login API Source: https://github.com/hertz-contrib/jwt/blob/main/README.md Authenticates a user with provided credentials and returns a JWT token upon success. ```APIDOC ## POST /login ### Description Authenticates a user with username and password. Returns a JWT token and expiration time upon successful login. ### Method POST ### Endpoint /login ### Parameters #### Request Body - **username** (string) - Required - The username for authentication. - **password** (string) - Required - The password for authentication. ### Request Example ```json { "username": "admin", "password": "admin" } ``` ### Response #### Success Response (200) - **code** (integer) - The status code, expected to be 200. - **expire** (string) - The expiration time of the token in ISO 8601 format. - **token** (string) - The generated JWT token. #### Response Example ```json { "code": 200, "expire": "2022-06-05T13:49:20+08:00", "token": "**" } ``` ``` -------------------------------- ### HertzJWTMiddleware.MiddlewareInit - Validate and apply defaults Source: https://context7.com/hertz-contrib/jwt/llms.txt Validates the JWT middleware configuration and applies default settings. This method is automatically called by `New` and ensures required fields are present and sensible defaults are set. ```APIDOC ## HertzJWTMiddleware.MiddlewareInit — Validate and apply defaults `MiddlewareInit` is called automatically by `New`. It sets defaults (`HS256`, 1-hour timeout, `header:Authorization` token lookup, `Bearer` head name, etc.) and validates that required fields such as `Key` (HMAC) or key files (RSA) are present. ```go mw := &jwt.HertzJWTMiddleware{ Realm: "zone", Key: []byte("secret"), Authenticator: func(ctx context.Context, c *app.RequestContext) (interface{}, error) { return "user", nil }, } if err := mw.MiddlewareInit(); err != nil { log.Fatal(err) // e.g. ErrMissingSecretKey } ``` ``` -------------------------------- ### Configure Cookie-Based Token Delivery Source: https://context7.com/hertz-contrib/jwt/llms.txt Enable `SendCookie` to deliver the JWT as an HTTP cookie on login and refresh. Set `TokenLookup` to `cookie:` to allow the middleware to read it back. ```go authMiddleware, err := jwt.New(&jwt.HertzJWTMiddleware{ Realm: "web app", Key: []byte("secret"), SendCookie: true, CookieName: "jwt", CookieMaxAge: time.Hour, SecureCookie: false, // set true in production (HTTPS only) CookieHTTPOnly: true, // JS cannot access CookieDomain: "localhost:8888", CookieSameSite: protocol.CookieSameSiteDefaultMode, TokenLookup: "cookie:jwt", // read token from cookie Authenticator: func(ctx context.Context, c *app.RequestContext) (interface{}, error) { return &User{UserName: "alice"}, nil }, }) ``` -------------------------------- ### Custom KeyFunc for Token Verification Logic Source: https://context7.com/hertz-contrib/jwt/llms.txt Set `KeyFunc` to bypass built-in key selection and provide custom signing key resolution, such as JWKS lookup by kid. ```go authMiddleware, err := jwt.New(&jwt.HertzJWTMiddleware{ Realm: "jwks zone", KeyFunc: func(token *jwt.Token) (interface{}, error) { if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) } kid, _ := token.Header["kid"].(string) return lookupPublicKey(kid) // your JWKS lookup }, Authenticator: func(ctx context.Context, c *app.RequestContext) (interface{}, error) { return "user", nil }, }) ``` -------------------------------- ### Custom KeyFunc - Custom token verification logic Source: https://context7.com/hertz-contrib/jwt/llms.txt Allows for custom token verification logic by setting a `KeyFunc`. This is useful for implementing advanced key selection mechanisms like JWKS lookup. ```APIDOC ## Custom `KeyFunc` — Custom token verification logic Set `KeyFunc` to bypass all built-in key selection and provide your own signing key resolution (e.g., JWKS lookup by kid). ### Configuration Example ```go authMiddleware, err := jwt.New(&jwt.HertzJWTMiddleware{ Realm: "jwks zone", KeyFunc: func(token *jwt.Token) (interface{}, error) { if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) } kid, _ := token.Header["kid"].(string) return lookupPublicKey(kid) // your JWKS lookup }, Authenticator: func(ctx context.Context, c *app.RequestContext) (interface{}, error) { return "user", nil }, }) ``` ``` -------------------------------- ### GetToken - Retrieve Raw JWT String Source: https://context7.com/hertz-contrib/jwt/llms.txt Demonstrates how to retrieve the raw JWT string from the Hertz context. This is useful for accessing the token directly within your handlers. ```APIDOC ## `GetToken` — Retrieve the raw JWT string from the context `GetToken` returns the raw JWT string stored under `JWT_TOKEN` in the Hertz context (set by `MiddlewareFunc` for HMAC algorithms). Returns an empty string if not present. ### Usage Example ```go func EchoTokenHandler(ctx context.Context, c *app.RequestContext) { raw := jwt.GetToken(ctx, c) c.JSON(200, map[string]string{"raw_token": raw}) } ``` ``` -------------------------------- ### JWT Cookie Configuration Source: https://github.com/hertz-contrib/jwt/blob/main/README.md Configure JWT cookie options, including secure and HttpOnly settings. Adjust CookieDomain and CookieSameSite as needed for your environment. ```go SendCookie: true, SecureCookie: false, //non HTTPS dev environments CookieHTTPOnly: true, // JS can't modify CookieDomain: "localhost:8888", CookieName: "token", // default jwt TokenLookup: "cookie:token", CookieSameSite: http.SameSiteDefaultMode, //SameSiteDefaultMode, SameSiteLaxMode, SameSiteStrictMode, SameSiteNoneMode ``` -------------------------------- ### MiddlewareFunc: Protect Routes with JWT Validation Source: https://context7.com/hertz-contrib/jwt/llms.txt MiddlewareFunc returns a handler to validate tokens, populate context with payload and identity, and authorize access. Aborts with 401/403 on failure. ```go auth := h.Group("/api") auth.Use(authMiddleware.MiddlewareFunc()) { auth.GET("/profile", func(ctx context.Context, c *app.RequestContext) { claims := jwt.ExtractClaims(ctx, c) user, _ := c.Get("id") // IdentityKey value set by IdentityHandler c.JSON(200, map[string]interface{}{ "user": user, "claims": claims, }) }) } // curl -H "Authorization: Bearer " http://localhost:8888/api/profile // 200: {"user":"admin","claims":{"exp":...,"id":"admin","orig_iat":...}} // 401: {"code":401,"message":"auth header is empty"} // 403: {"code":403,"message":"you don't have permission to access this resource"} ``` -------------------------------- ### Login Handler for JWT Issuance Source: https://context7.com/hertz-contrib/jwt/llms.txt Mount the `LoginHandler` on a POST route to issue JWTs upon successful credential verification. It uses the configured `Authenticator` and `PayloadFunc`. ```go h.POST("/login", authMiddleware.LoginHandler) // Request // POST /login {"username":"admin","password":"secret"} // Default response (200 OK) // {"code":200,"expire":"2024-06-01T13:00:00+00:00","token":"eyJ..."} ``` -------------------------------- ### Custom JWT Login Response Source: https://context7.com/hertz-contrib/jwt/llms.txt Customize the response format for successful JWT issuance by providing a custom `LoginResponse` function. ```go LoginResponse: func(ctx context.Context, c *app.RequestContext, code int, token string, expire time.Time) { c.JSON(http.StatusOK, map[string]interface{}{ "code": code, "token": token, "expire": expire.Format(time.RFC3339), }) }, ``` -------------------------------- ### Ping Endpoint (Protected) Source: https://github.com/hertz-contrib/jwt/blob/main/README.md A sample protected endpoint that requires a valid JWT for access. ```APIDOC ## GET /auth/ping ### Description An example endpoint that requires JWT authentication. Returns a simple pong message if authenticated successfully. ### Method GET ### Endpoint /auth/ping ### Parameters #### Header Parameters - **Authorization** (string) - Required - The JWT token in the format "Bearer ". - **Content-Type** (string) - Required - Should be "application/json". ### Response #### Success Response (200) - **ping** (string) - A confirmation message, typically "pong". #### Response Example ```json { "ping": "pong" } ``` #### Error Response (403 Forbidden) - **code** (integer) - The status code, expected to be 403. - **message** (string) - A message indicating lack of permission. #### Error Response Example ```json { "code": 403, "message": "you don't have permission to access this resource" } ``` ``` -------------------------------- ### Retrieve Raw JWT Token from Context Source: https://context7.com/hertz-contrib/jwt/llms.txt Use `GetToken` to retrieve the raw JWT string from the Hertz context. It returns an empty string if the token is not present. ```go func EchoTokenHandler(ctx context.Context, c *app.RequestContext) { raw := jwt.GetToken(ctx, c) c.JSON(200, map[string]string{"raw_token": raw}) } ``` -------------------------------- ### MiddlewareFunc Source: https://context7.com/hertz-contrib/jwt/llms.txt `MiddlewareFunc` provides JWT validation for route groups, populating context with user claims and identity. ```APIDOC ## GET /api/profile ### Description Protects a route group with JWT validation. Parses and validates the token, populates JWT_PAYLOAD and the identity key in the context, runs Authorizator, and aborts with 401/403 on failure. ### Method GET ### Endpoint /api/profile ### Parameters #### Header Parameters - **Authorization** (string) - Required - Bearer token (e.g., "Bearer ") ### Response #### Success Response (200) - **user** (string) - The identity key value set by IdentityHandler. - **claims** (object) - The JWT payload claims. #### Error Response (401 Unauthorized) - **code** (int) - 401 - **message** (string) - "auth header is empty" #### Error Response (403 Forbidden) - **code** (int) - 403 - **message** (string) - "you don't have permission to access this resource" ``` -------------------------------- ### TokenGenerator Source: https://context7.com/hertz-contrib/jwt/llms.txt `TokenGenerator` programmatically creates a JWT without an HTTP request. ```APIDOC ## TokenGenerator ### Description Programmatically creates a JWT. It calls `PayloadFunc` with supplied data, signs a new token, and returns the token string and expiry time. Ideal for tests or server-to-server token issuance. ### Usage ```go tokenString, expire, err := authMiddleware.TokenGenerator(&User{UserName: "service-account"}) if err != nil { log.Fatal(err) } fmt.Printf("token: %s\nexpires: %s\n", tokenString, expire.Format(time.RFC3339)) ``` ``` -------------------------------- ### ParseToken / ParseTokenString: Validate and Parse JWT Source: https://context7.com/hertz-contrib/jwt/llms.txt ParseToken extracts and validates a token from the request, while ParseTokenString parses a raw token string. Both return a *jwt.Token with accessible claims. ```go // From request (inside a handler) token, err := authMiddleware.ParseToken(ctx, c) if err != nil { c.JSON(401, map[string]string{"error": err.Error()}) return } claims := jwt.ExtractClaimsFromToken(token) // From a raw string token2, err := authMiddleware.ParseTokenString("eyJ...") if err != nil { log.Println(err) // e.g. jwt.ErrInvalidSigningAlgorithm } ``` -------------------------------- ### LoginHandler - Issue a JWT on successful credential verification Source: https://context7.com/hertz-contrib/jwt/llms.txt A handler function that issues a JWT upon successful credential verification. It calls the `Authenticator`, builds a signed token using `PayloadFunc`, optionally sets a cookie, and then calls `LoginResponse`. This handler should be mounted on a POST route. ```APIDOC ## LoginHandler — Issue a JWT on successful credential verification `LoginHandler` is an `app.HandlerFunc` that calls `Authenticator`, builds a signed token with claims from `PayloadFunc`, optionally sets a cookie, then calls `LoginResponse`. Mount it directly on a POST route. ```go h.POST("/login", authMiddleware.LoginHandler) // Request // POST /login {"username":"admin","password":"secret"} // Default response (200 OK) // {"code":200,"expire":"2024-06-01T13:00:00+00:00","token":"eyJ..."} ``` Custom `LoginResponse`: ```go LoginResponse: func(ctx context.Context, c *app.RequestContext, code int, token string, expire time.Time) { c.JSON(http.StatusOK, map[string]interface{}{ "code": code, "token": token, "expire": expire.Format(time.RFC3339), }) }, ``` ``` -------------------------------- ### TokenGenerator: Programmatically Create JWT Source: https://context7.com/hertz-contrib/jwt/llms.txt TokenGenerator creates a new signed JWT using PayloadFunc, returning the token string and expiry time. Ideal for tests or server-to-server authentication. ```go tokenString, expire, err := authMiddleware.TokenGenerator(&User{UserName: "service-account"}) if err != nil { log.Fatal(err) } fmt.Printf("token: %s\nexpires: %s\n", tokenString, expire.Format(time.RFC3339)) // token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... // expires: 2024-06-01T13:00:00Z ``` -------------------------------- ### RefreshHandler: Issue New Token Before or After Expiry Source: https://context7.com/hertz-contrib/jwt/llms.txt RefreshHandler validates the token's orig_iat against MaxRefresh and issues a new token. It can be placed outside protected groups to accept expired-but-refreshable tokens. ```go auth.GET("/refresh_token", authMiddleware.RefreshHandler) // curl -H "Authorization: Bearer " http://localhost:8888/auth/refresh_token // 200: {"code":200,"expire":"2024-06-01T14:00:00+00:00","token":"eyJ...new..."} // 401: {"code":401,"message":"token is expired"} ``` ```go RefreshResponse: func(ctx context.Context, c *app.RequestContext, code int, token string, expire time.Time) { c.JSON(http.StatusOK, map[string]interface{}{ "code": code, "token": token, "expire": expire.Format(time.RFC3339), }) }, ``` -------------------------------- ### Ping API Success Response Source: https://github.com/hertz-contrib/jwt/blob/main/README.md A successful response from the ping endpoint, indicating the server is reachable and the token is valid. ```shell HTTP/1.1 200 OK Content-Length: 15 Content-Type: application/json; charset=utf-8 Date: Sun, 05 Jun 2022 04:53:59 GMT Server: hertz { "ping": "pong" } ``` -------------------------------- ### Custom TimeoutFunc - Per-token dynamic expiry Source: https://context7.com/hertz-contrib/jwt/llms.txt Overrides the default token timeout by implementing a custom `TimeoutFunc`. This allows for dynamic expiry durations based on token claims. ```APIDOC ## Custom `TimeoutFunc` — Per-token dynamic expiry Override `TimeoutFunc` to compute a token-specific timeout based on the token's own claims (e.g., grant longer sessions for premium users). ### Configuration Example ```go authMiddleware, err := jwt.New(&jwt.HertzJWTMiddleware{ Key: []byte("secret"), Timeout: time.Hour, // fallback default TimeoutFunc: func(claims jwt.MapClaims) time.Duration { if role, ok := claims["role"].(string); ok && role == "premium" { return 7 * 24 * time.Hour } return time.Hour }, Authenticator: func(ctx context.Context, c *app.RequestContext) (interface{}, error) { return map[string]string{"role": "premium", "user": "alice"}, nil }, PayloadFunc: func(data interface{}) jwt.MapClaims { if m, ok := data.(map[string]string); ok { return jwt.MapClaims{"id": m["user"], "role": m["role"]} } return jwt.MapClaims{} }, }) ``` ``` -------------------------------- ### ParseToken / ParseTokenString Source: https://context7.com/hertz-contrib/jwt/llms.txt `ParseToken` and `ParseTokenString` validate and parse JWTs from requests or raw strings. ```APIDOC ## ParseToken / ParseTokenString ### Description Validates and parses a JWT. `ParseToken` extracts the token from various parts of the HTTP request (header, query, cookie, etc.), while `ParseTokenString` accepts the token string directly. Both return a `*jwt.Token`. ### Usage ```go // From request (inside a handler) token, err := authMiddleware.ParseToken(ctx, c) if err != nil { c.JSON(401, map[string]string{"error": err.Error()}) return } claims := jwt.ExtractClaimsFromToken(token) // From a raw string token2, err := authMiddleware.ParseTokenString("eyJ...") if err != nil { log.Println(err) // e.g. jwt.ErrInvalidSigningAlgorithm } ``` ``` -------------------------------- ### Cookie-based Token Delivery Source: https://context7.com/hertz-contrib/jwt/llms.txt Enables JWT delivery as an HTTP cookie on login and refresh. Configures the middleware to send and read tokens from cookies. ```APIDOC ## Cookie-based token delivery Enable `SendCookie` to also deliver the JWT as an HTTP cookie on login and refresh, and set `TokenLookup` to include `cookie:` so the middleware can read it back. ### Configuration Example ```go authMiddleware, err := jwt.New(&jwt.HertzJWTMiddleware{ Realm: "web app", Key: []byte("secret"), SendCookie: true, CookieName: "jwt", CookieMaxAge: time.Hour, SecureCookie: false, // set true in production (HTTPS only) CookieHTTPOnly: true, // JS cannot access CookieDomain: "localhost:8888", CookieSameSite: protocol.CookieSameSiteDefaultMode, TokenLookup: "cookie:jwt", // read token from cookie Authenticator: func(ctx context.Context, c *app.RequestContext) (interface{}, error) { return &User{UserName: "alice"}, nil }, }) ``` ``` -------------------------------- ### ExtractClaimsFromToken: Read Claims Directly from Parsed Token Source: https://context7.com/hertz-contrib/jwt/llms.txt ExtractClaimsFromToken converts a *jwt.Token into a MapClaims map without requiring a request context. Useful for tokens obtained via ParseToken or ParseTokenString. ```go token, err := authMiddleware.ParseTokenString("eyJ...") if err != nil { log.Println("invalid token:", err) return } claims := jwt.ExtractClaimsFromToken(token) fmt.Println("subject:", claims["id"]) ``` -------------------------------- ### RefreshHandler Source: https://context7.com/hertz-contrib/jwt/llms.txt `RefreshHandler` issues a new JWT if the token's `orig_iat` is within the `MaxRefresh` window. ```APIDOC ## GET /refresh_token ### Description Issues a new signed token if the provided token's `orig_iat` is still within the `MaxRefresh` window. Can be placed outside protected groups. ### Method GET ### Endpoint /refresh_token ### Parameters #### Header Parameters - **Authorization** (string) - Required - Bearer token (e.g., "Bearer ") ### Response #### Success Response (200 OK) - **code** (int) - 200 - **expire** (string) - The expiration time of the new token in RFC3339 format. - **token** (string) - The newly issued JWT. #### Error Response (401 Unauthorized) - **code** (int) - 401 - **message** (string) - "token is expired" ``` -------------------------------- ### ExtractClaims Source: https://context7.com/hertz-contrib/jwt/llms.txt `ExtractClaims` retrieves the JWT payload claims from the request context. ```APIDOC ## ExtractClaims ### Description Retrieves the `JWT_PAYLOAD` map stored in the Hertz context by `MiddlewareFunc`. Returns an empty `MapClaims` if the payload is not present. ### Usage ```go claims := jwt.ExtractClaims(ctx, c) userID := claims["id"].(string) exp := int64(claims["exp"].(float64)) c.JSON(200, map[string]interface{}{ "user_id": userID, "expires": time.Unix(exp, 0).Format(time.RFC3339), }) ``` ``` -------------------------------- ### ExtractClaimsFromToken Source: https://context7.com/hertz-contrib/jwt/llms.txt `ExtractClaimsFromToken` reads JWT claims directly from a parsed token. ```APIDOC ## ExtractClaimsFromToken ### Description Converts a `*jwt.Token` into a `MapClaims` map without needing a request context. Useful for inspecting tokens obtained through other means. ### Usage ```go token, err := authMiddleware.ParseTokenString("eyJ...") if err != nil { log.Println("invalid token:", err) return } claims := jwt.ExtractClaimsFromToken(token) fmt.Println("subject:", claims["id"]) ``` ``` -------------------------------- ### Refresh Token API Source: https://github.com/hertz-contrib/jwt/blob/main/README.md Refreshes an existing JWT token, providing a new token with an updated expiration time. ```APIDOC ## GET /auth/refresh_token ### Description Refreshes the JWT token. Requires a valid Authorization header with a Bearer token. ### Method GET ### Endpoint /auth/refresh_token ### Parameters #### Header Parameters - **Authorization** (string) - Required - The JWT token in the format "Bearer ". - **Content-Type** (string) - Required - Should be "application/json". ### Response #### Success Response (200) - **code** (integer) - The status code, expected to be 200. - **expire** (string) - The expiration time of the new token in ISO 8601 format. - **token** (string) - The new generated JWT token. #### Response Example ```json { "code": 200, "expire": "2022-06-05T13:50:41+08:00", "token": "**" } ``` ``` -------------------------------- ### Ping API Forbidden Response Source: https://github.com/hertz-contrib/jwt/blob/main/README.md Response indicating forbidden access, likely due to an invalid or expired token. ```shell HTTP/1.1 403 Forbidden Content-Length: 74 Content-Type: application/json; charset=utf-8 Date: Sun, 05 Jun 2022 04:57:06 GMT Server: hertz Www-Authenticate: JWT realm=test zone { "code": 403, "message": "you don't have permission to access this resource" } ``` -------------------------------- ### LogoutHandler Source: https://context7.com/hertz-contrib/jwt/llms.txt `LogoutHandler` clears the JWT cookie on logout and calls `LogoutResponse`. ```APIDOC ## POST /logout ### Description Clears the JWT cookie and logs out the user. ### Method POST ### Endpoint /logout ### Request Example ```json {} ``` ### Response #### Success Response (200 OK) - **code** (int) - Status code, expected to be 200. ``` -------------------------------- ### ExtractClaims: Read JWT Payload Claims from Request Context Source: https://context7.com/hertz-contrib/jwt/llms.txt ExtractClaims retrieves the JWT_PAYLOAD map from the Hertz context populated by MiddlewareFunc. Returns an empty MapClaims if the payload is absent. ```go func ProfileHandler(ctx context.Context, c *app.RequestContext) { claims := jwt.ExtractClaims(ctx, c) userID := claims["id"].(string) // the IdentityKey claim exp := int64(claims["exp"].(float64)) // expiry Unix timestamp c.JSON(200, map[string]interface{}{ "user_id": userID, "expires": time.Unix(exp, 0).Format(time.RFC3339), }) } ``` -------------------------------- ### LogoutHandler: Clear JWT Cookie on Logout Source: https://context7.com/hertz-contrib/jwt/llms.txt Use LogoutHandler to delete the JWT cookie and call LogoutResponse. Ensure SendCookie is true to enable cookie deletion. ```go h.POST("/logout", authMiddleware.LogoutHandler) // Response (200 OK) // {"code":200} ``` ```go LogoutResponse: func(ctx context.Context, c *app.RequestContext, code int) { c.JSON(http.StatusOK, map[string]interface{}{"code": code}) }, ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.