The jwt package provides comprehensive JWT (JSON Web Token) parsing, validation, and management capabilities for the Kinde Go SDK. This package is designed to work seamlessly with OAuth2 flows and provides flexible validation options.
To better understand JSON Web Tokens, their structure, security features, and use cases, check out our comprehensive guide:
A complete guide to JSON Web Tokens (JWTs)
This guide covers:
- What JSON Web Tokens are and how they work
- JWT structure (header, payload, signature)
- Security considerations and best practices
- Common use cases for authentication and authorization
- JWT benefits compared to other token types
- Multiple Parsing Methods: Parse JWT tokens from HTTP headers, strings, session storage, or OAuth2 tokens
- Flexible Validation: Configurable validation options for algorithm, audience, issuer, claims, and more
- JWKS Support: Built-in support for JSON Web Key Sets for token signature validation
- Comprehensive Token Access: Easy access to token claims, subject, issuer, audience, and other standard JWT fields
- Error Handling: Detailed validation error reporting
import (
"github.com/kinde-oss/kinde-go/jwt" // required
)import "github.com/kinde-oss/kinde-go/jwt"
// Parse and validate a JWT token
token, err := jwt.ParseFromString(
"your.jwt.token.here",
jwt.WillValidateWithJWKSUrl("https://your-domain.kinde.com/.well-known/jwks.json"),
jwt.WillValidateAlgorithm("RS256"),
jwt.WillValidateAudience("your-api-audience"),
)
if err != nil {
// Handle error
}
// Check if token is valid
if token.IsValid() {
// Token is valid, extract information
subject := token.GetSubject()
issuer := token.GetIssuer()
// ... use token
}Important: All validation options (e.g., WillValidateWithJWKSUrl, WillValidateAlgorithm, WillValidateAudience) are applied once during token parsing, not every time the token is read. The validation results are cached in the token object, so subsequent calls to GetSubject(), GetIssuer(), GetAudience(), etc. do not re-validate the token.
Note for OAuth2 Flows: When using the JWT package with OAuth2 flows (authorization_code or client_credentials), tokens are re-validated every time they are retrieved from the token source. This ensures that tokens remain valid throughout their lifecycle and any validation errors are caught when tokens are refreshed or retrieved from session storage.
Parse a JWT token from a raw string:
token, err := jwt.ParseFromString(
rawTokenString,
jwt.WillValidateWithJWKSUrl("https://your-domain.kinde.com/.well-known/jwks.json"),
)Parse a JWT token from an HTTP Authorization header:
// Expects: Authorization: Bearer <token>
token, err := jwt.ParseFromAuthorizationHeader(
httpRequest,
jwt.WillValidateWithJWKSUrl("https://your-domain.kinde.com/.well-known/jwks.json"),
)Parse a JWT token from session storage (JSON string):
// Session storage contains JSON representation of oauth2.Token
token, err := jwt.ParseFromSessionStorage(
sessionStorageString,
jwt.WillValidateWithJWKSUrl("https://your-domain.kinde.com/.well-known/jwks.json"),
)Parse a JWT token from an OAuth2 token:
oauth2Token := &oauth2.Token{AccessToken: "your.jwt.token.here"}
token, err := jwt.ParseOAuth2Token(
oauth2Token,
jwt.WillValidateWithJWKSUrl("https://your-domain.kinde.com/.well-known/jwks.json"),
)Validate token signature using a JWKS endpoint:
jwt.WillValidateWithJWKSUrl("https://your-domain.kinde.com/.well-known/jwks.json")Validate token signature using a specific public key:
jwt.WillValidateWithPublicKey(func(rawToken string) (*rsa.PublicKey, error) {
// Return your public key
return publicKey, nil
})Use a custom function for key validation:
jwt.WillValidateWithKeyFunc(func(token *golangjwt.Token) (interface{}, error) {
// Custom key validation logic
return key, nil
})Validate the token's signing algorithm:
// Default: RS256
jwt.WillValidateAlgorithm()
// Custom algorithms
jwt.WillValidateAlgorithm("RS256", "ES256")Ensure the token contains the expected audience:
jwt.WillValidateAudience("your-api-audience")Validate the token issuer:
jwt.WillValidateIssuer("https://your-domain.kinde.com")Custom validation for token claims:
jwt.WillValidateClaims(func(claims golangjwt.MapClaims) (bool, error) {
// Custom validation logic
if customClaim, exists := claims["custom_field"]; exists {
// Validate custom claim
return true, nil
}
return false, fmt.Errorf("missing required claim")
})Allow for clock skew between servers:
jwt.WillValidateWithClockSkew(30 * time.Second)Use a custom time function (useful for testing):
jwt.WillValidateWithTimeFunc(func() time.Time {
return time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC)
})Once you have a parsed token, you can access various properties:
// Check if token is valid
isValid := token.IsValid()
// Get raw OAuth2 token
rawToken := token.GetRawToken()
// Get validation errors
errors := token.GetValidationErrors()// Access token
accessToken, exists := token.GetAccessToken()
// ID token
idToken, exists := token.GetIdToken()
// Refresh token
refreshToken, exists := token.GetRefreshToken()// Get subject (sub claim)
subject := token.GetSubject()
// Get issuer (iss claim)
issuer := token.GetIssuer()
// Get audience (aud claim)
audience := token.GetAudience()
// Get all claims
claims := token.GetClaims()
// Get specific claim
if customValue, exists := claims["custom_field"]; exists {
// Use custom value
}// Convert token to JSON string
jsonString, err := token.AsString()func protectedHandler(w http.ResponseWriter, r *http.Request) {
token, err := jwt.ParseFromAuthorizationHeader(
r,
jwt.WillValidateWithJWKSUrl("https://your-domain.kinde.com/.well-known/jwks.json"),
jwt.WillValidateAlgorithm("RS256"),
jwt.WillValidateAudience("your-api-audience"),
)
if err != nil || !token.IsValid() {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
// Token is valid, proceed with request
subject := token.GetSubject()
// ... handle request
}Note: You can also use the Authorization Code Middleware to automatically validate JWTs for protected routes in your application. This middleware streamlines the process of securing endpoints by handling token extraction and validation for you.
func validateSession(sessionData string) (*jwt.Token, error) {
return jwt.ParseFromSessionStorage(
sessionData,
jwt.WillValidateWithJWKSUrl("https://your-domain.kinde.com/.well-known/jwks.json"),
jwt.WillValidateAlgorithm("RS256"),
jwt.WillValidateIssuer("https://your-domain.kinde.com"),
)
}func validateFavoriteColorIsBlue(token *jwt.Token) error {
claims := token.GetClaims()
if color, exists := claims["favorite_color"]; exists {
if colorStr, ok := color.(string); ok {
if colorStr == "blue" {
return nil // Valid favorite color
}
}
}
return fmt.Errorf("favorite color is not blue")
}// In your OAuth2 flow configuration
kindeAuthFlow, err := authorization_code.NewAuthorizationCodeFlow(
"https://your-domain.kinde.com",
"client_id",
"client_secret",
"callback_url",
authorization_code.WithTokenValidation(
true,
jwt.WillValidateAlgorithm("RS256"),
jwt.WillValidateAudience("your-api-audience"),
jwt.WillValidateClaims(func(claims golangjwt.MapClaims) (bool, error) {
// Custom validation logic
return true, nil
}),
),
)The package provides comprehensive error handling:
token, err := jwt.ParseFromString(rawToken, options...)
if err != nil {
// Handle parsing/validation errors
log.Printf("Token validation failed: %v", err)
// Check specific validation errors
if token != nil {
for _, validationError := range token.GetValidationErrors() {
log.Printf("Validation error: %v", validationError)
}
}
return
}- Always Validate Signatures: Use JWKS or public key validation to ensure token authenticity
- Validate Algorithm: Explicitly specify allowed algorithms (default is RS256)
- Check Audience: Validate that tokens are intended for your application
- Handle Errors Gracefully: Check both parsing errors and validation errors
- Use Appropriate Clock Skew: Allow reasonable time differences between servers
- Validate Custom Claims: Implement business logic validation for custom claims
github.com/golang-jwt/jwt/v5- Core JWT functionalitygithub.com/MicahParks/jwkset- JWKS client supportgithub.com/MicahParks/keyfunc/v3- Key function utilitiesgolang.org/x/oauth2- OAuth2 token support
See the jwt_test.go file for comprehensive usage examples and test cases that demonstrate various validation scenarios and token handling patterns.