jwtmock

package module
v1.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 21, 2022 License: MIT Imports: 11 Imported by: 0

README

main docker

JWT Mock

JWT Mock is a web server that is used to mock out a JWT-based authorization server for a protected API. The protected API typically requires a JWT header in requests which is then validated by verifying the signture of the JWT. The authorization server provides a JWKS (JSON Web Key Set) which is consumed by the API for JWT verification.

protected-api

Mocking out an authorization server is especially helpful in end-to-end/smoke testing to see how different handlers and middleware respond to JWTs representing various levels of access and identities.

Mock JWTs can help you cover various testing scenarios.

  • Create tokens for various user identities.
  • Create tokens with various scopes/permissions for testing access control.

Quick Start

Follow these 3 simple steps to use JWT Mock in your tests:

  1. Start JWT Mock server
  • Via Docker image if using a docker ecosystem
  • Via jwtmocktest.NewServer in Go tests
  1. Configure the API under test to use JWT Mock server as the authorization server. The server provides an endpoint to retrieves the JSON Web Key Set (JWKS) at ./well-known/jwks.json

  2. Generate JWTs for use in tests

  • Via Docker image, use the POST /jwtmock/generate-jwt endpoint to generate a JWT from a set of claims.
  • Via jwtmocktest.Server in Go tests, use GenerateJWT method on the test server.

API Documentation

The JWT Mock API is documented using Open API and available on SwaggerHub here. Be sure to reference it for any questions about the API endpoints.

You will also find helpful examples using curl here.

Go Tests

The jwtmocktest package provides an HTTP test server similar to the httptest package. It can be used as the authorization server for a microservice using JWTs.

import (
  "github.com/nayyara-cropsey/jwtmock/jwtmocktest"
  "github.com/nayyara-cropsey/jwtmock"
)

// setup server
server, err := jwtmocktest.NewServer()

// wire to as an authorization server to a dependent microservice's config
appConfig.AuthZServer = server.URL

// generate a JWT for use in Authorization header
token, err := server.GenerateJWT(jwtmock.Claims{
  "sub": "test-user",  // subject
  "iat": 1646451994 // issued-at epoch time
  "exp": 1646451994 // expiration epoch time 
})

// use JWT in microservice API 
req = req.WithHeader("Authorization", "Bearer: " + token)
...

// shutdown server 
server.Close()

Alternatively you can also use the jwtmocktest.Client to connect to a running JWT Mock server.

import (  
  "github.com/nayyara-cropsey/jwtmock"
)

// create client 
client, err := jwtmock.NewClient(mockJWTServerURL)

// generate a JWT for use in Authorization header
token, err := client.GenerateJWT(jwtmock.Claims{
  "sub": "test-user",  // subject
  "iat": 1646451994 // issued-at epoch time
  "exp": 1646451994 // expiration epoch time 
})

Docker

This image is pushed to nayyaracropsey/jwtmock repository. Follow these steps to get it running:

docker pull nayyaracropsey/jwtmock:latest
docker run -p 80:80 nayyaracropsey/jwtmock:latest

The Docker repo also have various other immutable release tags pushed that match Git tags on this repo with the format v*.

Config

The default config for this service is as follows:

port: 80
key_length: 1024
cert_life_days: 1
log_level: debug

You can override any of these through environment variables using the prefix JWT_MOCK. For example override key length using:

docker run -p 80:80 --env JWT_MOCK_KEY_LENGTH=2048 --env nayyaracropsey/jwtmock:latest

Client Credentials

An API under test might also be a consumer of another service and might use machine-to-machine workflow to access another service. Sometimes the request to obtain a client's JWT is coded into the microservice and must be fulfilled by some service during end-to-end testing.

client

JWT Mock can be used in such a workflow as well to allow credentials to be obtained. JWT Mock requires a client to be registered in anticipation for such a call to succeed. It provides the POST /jwtmock/clients endpoint.

NOTE: During tests the external service will likely be mocked out and how that is handled is outside the scope of the usefulness of JWT Mock.

To use JWT mock in this workflow

  1. Start JWT Mock server
  • Via Docker image if using a docker ecosystem
  • Via jwtmocktest.NewServer in Go tests
  1. Configure the API under test to use JWT Mock server as the authorization server.

  2. Register a client with the mock server to whitelist accepted clients. The server provides an endpoint to register clients at POST /jwtmock/clients. For Go code, both jwttestmock.Server and jwtmock.Client have a RegisterClient() method to allow client registration.

  3. Internal calls to obtain client JWTs will now work as expected - JWT Mock expects such calls to use the endpoint /oauth/token with grant_type=client_credentials.

Documentation

Index

Constants

View Source
const (
	// Bearer is a constant for the bearer token
	Bearer = "Bearer"

	// ClientCredentials is a constant for the client credentials grant type
	ClientCredentials = "client_credentials"
)

Variables

View Source
var (
	// ErrExpiredToken means the JWT token has expired.
	ErrExpiredToken = errors.New("token has expired (seconds)")

	// ErrBadTokenFuture means the JWT token was issued in the future.
	ErrBadTokenFuture = errors.New("token was issued in the future (seconds)")

	// ErrSubMissing means the JWT token has missing subject
	ErrSubMissing = errors.New("token subject is missing")
)

Functions

This section is empty.

Types

type Claims

type Claims map[string]interface{}

Claims represents the type for JWT claims

func ClaimsFrom added in v1.1.1

func ClaimsFrom(v interface{}) (Claims, error)

ClaimsFrom generates a claims object form the given struct

func (Claims) CreateJWT

func (c Claims) CreateJWT(signingKey *SigningKey) (string, error)

CreateJWT generates a JWT token using the provided claims and signing key.

func (Claims) Valid

func (c Claims) Valid() error

Valid returns an error if this token is invalid

type Client added in v1.0.1

type Client struct {
	*http.Client

	URL string
}

Client is a wrapper for an existing JWT mock server

func NewClient added in v1.0.1

func NewClient(url string, options ...ClientOption) *Client

NewClient creates a new client with the base URL and given options

func (*Client) GenerateJWT added in v1.0.1

func (c *Client) GenerateJWT(ctx context.Context, claims Claims) (string, error)

GenerateJWT generates a JWT token for use in authorization header.

func (*Client) RegisterClient added in v1.1.1

func (c *Client) RegisterClient(ctx context.Context, registration ClientRegistration) error

RegisterClient register a new client

type ClientOption added in v1.0.1

type ClientOption func(*Client)

ClientOption allows setting options on the client

func WithHTTPClient added in v1.0.1

func WithHTTPClient(hc *http.Client) ClientOption

WithHTTPClient option is used to set the http client

type ClientRegistration added in v1.1.1

type ClientRegistration struct {
	ID     string `json:"client_id"`
	Secret string `json:"client_secret"`
	Scope  string `json:"scope"`
}

ClientRegistration is used to register a new client for machine-to-machine auth.

type ClientTokenClaims added in v1.1.1

type ClientTokenClaims struct {
	Issuer          string `mapstructure:"iss"`
	Subject         string `mapstructure:"sub"`
	Audience        string `mapstructure:"aud"`
	IssuedAt        int64  `mapstructure:"iat"`
	Expires         int64  `mapstructure:"exp"`
	AuthorizedParty string `mapstructure:"azp"`
	Scope           string `mapstructure:"scope"`
	GrantType       string `mapstructure:"gty"`
}

ClientTokenClaims are claims in the JWT for the client

type ClientTokenRequest added in v1.1.1

type ClientTokenRequest struct {
	ClientID     string `mapstructure:"client_id"`
	ClientSecret string `mapstructure:"client_secret"`
	GrantType    string `mapstructure:"grant_type"`
	Audience     string `mapstructure:"audience"`
}

ClientTokenRequest is a request to obtain a JWT token for the given client - passed as form-URL encoded

type ClientTokenResponse added in v1.1.1

type ClientTokenResponse struct {
	AccessToken string `json:"access_token"`
	Scope       string `json:"scope"`
	ExpiresIn   int64  `json:"expires_in"`
	TokenType   string `json:"token_type"`
}

ClientTokenResponse is the response for token endpoint

type SigningKey

type SigningKey struct {
	ID        string
	Key       interface{}
	Algorithm jwa.SignatureAlgorithm
	PublicKey interface{}
}

SigningKey represents a generic key used to sign JWTs.

Directories

Path Synopsis
Package cmd contains CLI commands.
Package cmd contains CLI commands.
internal
handlers
Package handlers contains handlers for the JWT Mock server.
Package handlers contains handlers for the JWT Mock server.
jwks
Package jwks contains code for dealing with JSON Web Key Sets.
Package jwks contains code for dealing with JSON Web Key Sets.
service
Package service contains services used by code here.
Package service contains services used by code here.
Package jwtmocktest provides a test server for use in end-to-end HTTP tests.
Package jwtmocktest provides a test server for use in end-to-end HTTP tests.
Package log contains a logger used by this library
Package log contains a logger used by this library

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL