Skip to content

Verify tokens

Per the specification:

JSON Web Signature (JWS) represents content secured with digital signatures or Message Authentication Codes (MACs) using JSON-based data structures. Cryptographic algorithms and identifiers for use with this specification are described in the separate JSON Web Algorithms (JWA) specification and an IANA registry defined by that specification. Related encryption capabilities are described in the separate JSON Web Encryption (JWE) specification.

Every signature algorithm is based on a private/public key pair. Most algorithms use asymmetric keys (where the public key only contains a subset of the private key information): the private key is kept secret to the producer, while the recipients can only access the public key. Some algorithms, however, use symmetric keys (like HMAC): in this case, the same key is shared by the producer and recipient, and both can either sign or verify tokens.

go
package main

import (
	"context"
	"github.com/a-novel-kit/jwt"
	"github.com/a-novel-kit/jwt/jws"
)

func main() {
	// HMAC Signatures validation require a symmetric HMAC key.
	// This secret key should be shared by the producer.
	var secretKey []byte

	// The raw token received from the producer.
	var token string

	verifier := jws.NewHMACVerifier(secretKey, jws.HS256)
	recipient := jwt.NewRecipient(jwt.RecipientConfig{
		Plugins: []jwt.RecipientPlugin{verifier},
	})

	var claims map[string]any
	_ := recipient.Consume(context.Background(), token, &claims)
}

Available presets for HMAC signatures are:

PresetTarget "alg"
jws.HS256HS256
jws.HS384HS384
jws.HS512HS512

Using auto-sourcing

Passing keys manually and creating a new verifier for each secret key can be cumbersome. To avoid this, you can use an alternate version that relies on a dynamic source of keys.

go
package main

import (
	"context"
	"github.com/a-novel-kit/jwt"
	"github.com/a-novel-kit/jwt/jwk"
	"github.com/a-novel-kit/jwt/jws"
)

func main() {
	// See JWK documentation for how to configure the source.
	// Preset for the source MUST match those of the verifier.
	source := jwk.NewHMACSource(config, jwk.HS256)

	// The raw token received from the producer.
	var token string

	verifier := jws.NewSourcedHMACVerifier(source, jws.HS256)
	recipient := jwt.NewRecipient(jwt.RecipientConfig{
		Plugins: []jwt.RecipientPlugin{verifier},
	})

	var claims map[string]any
	_ := recipient.Consume(context.Background(), token, &claims)
}

Available presets for HMAC signatures are:

PresetTarget "alg"Source preset
jws.HS256HS256jwk.HS256
jws.HS384HS384jwk.HS384
jws.HS512HS512jwk.HS512

You may also simply decode a token without verifying its signature, when you trust such signature or want to extract the claims for other purposes.

go
package main

import (
	"context"
	"github.com/a-novel-kit/jwt"
	"github.com/a-novel-kit/jwt/jwk"
	"github.com/a-novel-kit/jwt/jws"
)

func main() {
	// The raw token received from the producer.
	var token string

	verifier := jws.NewInsecureVerifier()
	recipient := jwt.NewRecipient(jwt.RecipientConfig{
		Plugins: []jwt.RecipientPlugin{verifier},
	})

	// This will not fail and extract the claims successfully, no matter the signature.
	// Encoding errors can still occur if the token is malformed.
	var claims map[string]any
	_ := recipient.Consume(context.Background(), token, &claims)
}