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.
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.
Follow these 3 simple steps to use JWT Mock in your tests:
- Start JWT Mock server
- Via Docker image if using a docker ecosystem
- Via
jwtmocktest.NewServer
in Go tests
-
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
-
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, useGenerateJWT
method on the test server.
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.
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
})
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*
.
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
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.
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
- Start JWT Mock server
- Via Docker image if using a docker ecosystem
- Via
jwtmocktest.NewServer
in Go tests
-
Configure the API under test to use JWT Mock server as the authorization server.
-
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, bothjwttestmock.Server
andjwtmock.Client
have aRegisterClient()
method to allow client registration. -
Internal calls to obtain client JWTs will now work as expected - JWT Mock expects such calls to use the endpoint
/oauth/token
withgrant_type=client_credentials
.