How do I rotate JWT signing keys in Go?

In Go, rotating JWT signing keys is essential for maintaining security. This process involves generating a new signing key and updating the JWT creation process to use the new key, while still allowing validation of tokens signed with the old key during a transition period.

Here is an example of how to implement JWT signing key rotation in Go:

// Import necessary packages import ( "crypto/rsa" "github.com/dgrijalva/jwt-go" "time" "sync" ) var ( currentKey *rsa.PrivateKey previousKey *rsa.PrivateKey mu sync.RWMutex ) // Function to generate a new RSA key func generateKey() (*rsa.PrivateKey, error) { return rsa.GenerateKey(rand.Reader, 2048) } // Function to rotate the signing key func rotateKeys() error { mu.Lock() defer mu.Unlock() newKey, err := generateKey() if err != nil { return err } // Assign the current key to previous key before rotating previousKey = currentKey currentKey = newKey return nil } // Function to sign a JWT func signToken(userID string) (string, error) { mu.RLock() defer mu.RUnlock() // Use the current key for signing token := jwt.NewWithClaims(jwt.SigningMethodRS256, jwt.MapClaims{ "userID": userID, "exp": time.Now().Add(time.Hour * 72).Unix(), }) return token.SignedString(currentKey) } // Function to validate a JWT func validateToken(tokenString string) (*jwt.Token, error) { mu.RLock() defer mu.RUnlock() token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { // Ensure the token is signed with the expected method if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok { return nil, fmt.Errorf("unexpected signing method") } // Return the current key or the previous key for validation if token.Claims.(jwt.MapClaims)["exp"].(int64) > time.Now().Unix() { return currentKey.Public(), nil } return previousKey.Public(), nil }) return token, err }

JWT Go security key rotation JWT signing keys