A Go implementation of JSON Web Tokens (JWT) with support for multiple signing algorithms and comprehensive validation options
This document covers creating and signing JWT tokens using the jwt library.
func New(method SigningMethod, opts ...TokenOption) *TokenCreates a new Token with the specified signing method and an empty MapClaims. Additional options can be specified for future extensibility.
func NewWithClaims(method SigningMethod, claims Claims, opts ...TokenOption) *TokenCreates a new Token with the specified signing method and claims. This is the recommended way to create tokens with custom claims.
Parameters:
method - The signing method to use (e.g., jwt.SigningMethodHS256)claims - Claims to embed in the token (can be RegisteredClaims, MapClaims, or custom)opts - Optional token options (currently unused but reserved for future use)type Token struct {
Raw string
Method SigningMethod
Header map[string]any
Claims Claims
Signature []byte
Valid bool
}Fields:
Raw - The raw token string (populated when parsing)Method - The signing method used or to be usedHeader - The first segment of the token in decoded form (typically contains "typ" and "alg")Claims - The second segment of the token in decoded formSignature - The third segment of the token in decoded form (populated when parsing)Valid - Specifies if the token is valid (populated when parsing/verifying)func (t *Token) SignedString(key any) (string, error)Creates and returns a complete, signed JWT string. The token is signed using the SigningMethod specified in the token. The key type must match the signing method:
[]byte*rsa.PrivateKey*ecdsa.PrivateKeyed25519.PrivateKeyReturns the complete JWT string in format: header.payload.signature
func (t *Token) SigningString() (string, error)Generates the signing string without the signature. This is used internally by SignedString but can be useful for custom signing implementations. Returns the string in format: header.payload
func (*Token) EncodeSegment(seg []byte) stringEncodes a JWT segment using base64url encoding with padding stripped, as required by the JWT specification.
type TokenOption func(*Token)A reserved type for future token creation options. Currently unused but allows for forward compatibility.
import (
"fmt"
"time"
"github.com/golang-jwt/jwt/v5"
)
// Create claims
claims := jwt.MapClaims{
"sub": "user123",
"name": "John Doe",
"iat": time.Now().Unix(),
"exp": time.Now().Add(24 * time.Hour).Unix(),
}
// Create token
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
// Sign with secret key
secretKey := []byte("your-256-bit-secret")
tokenString, err := token.SignedString(secretKey)
if err != nil {
panic(err)
}
fmt.Println("Token:", tokenString)import (
"crypto/rsa"
"time"
"github.com/golang-jwt/jwt/v5"
)
// Load RSA private key (example - in practice load from file)
var privateKey *rsa.PrivateKey
// Create registered claims
claims := jwt.RegisteredClaims{
Issuer: "my-service",
Subject: "user456",
Audience: jwt.ClaimStrings{"client-app"},
ExpiresAt: jwt.NewNumericDate(time.Now().Add(1 * time.Hour)),
IssuedAt: jwt.NewNumericDate(time.Now()),
ID: "token-id-123",
}
// Create and sign token
token := jwt.NewWithClaims(jwt.SigningMethodRS256, claims)
tokenString, err := token.SignedString(privateKey)
if err != nil {
panic(err)
}import (
"time"
"github.com/golang-jwt/jwt/v5"
)
// Define custom claims
type CustomClaims struct {
Username string `json:"username"`
Roles []string `json:"roles"`
jwt.RegisteredClaims
}
// Create custom claims
claims := CustomClaims{
Username: "johndoe",
Roles: []string{"admin", "user"},
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Now().Add(2 * time.Hour)),
IssuedAt: jwt.NewNumericDate(time.Now()),
},
}
// Create and sign token
token := jwt.NewWithClaims(jwt.SigningMethodHS512, claims)
secretKey := []byte("your-secret-key")
tokenString, err := token.SignedString(secretKey)import (
"crypto/ecdsa"
"time"
"github.com/golang-jwt/jwt/v5"
)
// Load ECDSA private key
var ecPrivateKey *ecdsa.PrivateKey
// Create claims
claims := jwt.RegisteredClaims{
Subject: "user789",
ExpiresAt: jwt.NewNumericDate(time.Now().Add(30 * time.Minute)),
}
// Create and sign token with ES256
token := jwt.NewWithClaims(jwt.SigningMethodES256, claims)
tokenString, err := token.SignedString(ecPrivateKey)import (
"github.com/golang-jwt/jwt/v5"
)
// Create token
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"sub": "user123",
})
// Add custom header fields
token.Header["kid"] = "key-id-1" // Key ID
token.Header["cty"] = "JWT" // Content Type
// Sign token
secretKey := []byte("secret")
tokenString, err := token.SignedString(secretKey)exp) to limit token validityiat (issued at) claim for token age verificationaud) to prevent token reuse across servicesAlways check for errors when signing tokens:
tokenString, err := token.SignedString(key)
if err != nil {
// Handle errors appropriately
// Common errors: invalid key type, signing failure
return fmt.Errorf("failed to sign token: %w", err)
}Install with Tessl CLI
npx tessl i tessl/golang-github-com-golang-jwt--jwt--v5