OAuth 2 mock server. Intended to be used for development or testing purposes.
When developing an application that exposes or consumes APIs that are secured with an OAuth 2 authorization scheme, a mechanism for issuing access tokens is needed. Frequently, a developer needs to create custom code that fakes the creation of tokens for testing purposes, and these tokens cannot be properly verified, since there is no actual entity issuing those tokens.
The purpose of this package is to provide an easily configurable OAuth 2 server, that can be set up and torn down at will, and can be programmatically run while performing automated tests.
- Real cryptography. Tokens are signed with actual JWK key pairs. Consuming applications can verify them using the
/jwksendpoint, without mocking the verification layer. - OIDC-conformant. Exposes all the endpoints a real provider would: discovery, JWKS, authorization code flow with PKCE, userinfo, token introspection, revocation, and end session.
- Programmatic and CLI. Embed it in a JavaScript or TypeScript test suite (
beforeAll/afterAll) or run it as a standalone process for Java, .NET, Python, and other non-JS projects. - Per-test customization via event hooks. Use
server.service.once(Events.xxx, ...)to alter token claims, simulate errors, or modify responses for a single test — without reconfiguring the server. - TypeScript-first. Full type definitions ship with the package. The entire codebase is written in strict TypeScript.
Warning: This tool is not intended to be used as an actual production grade OAuth 2 server. It lacks many features that would be required in a proper implementation.
Add it to your Node.js project as a development dependency:
npm install --save-dev oauth2-mock-serverThe server can be run from the command line.
npx oauth2-mock-server --helpThe server and its components can also be leveraged as a library, allowing finer control and configuration.
Here is an example for creating and running a server instance with a single random RSA key:
import { OAuth2Server } from 'oauth2-mock-server';
// ...or in CommonJS style:
// const { OAuth2Server } = require('oauth2-mock-server');
let server = new OAuth2Server();
// Generate a new RSA key and add it to the keystore
await server.issuer.keys.generate('RS256');
// Start the server
await server.start(8080, 'localhost');
console.log('Issuer URL:', server.issuer.url); // -> http://localhost:8080
// Do some work with the server
// ...
// Stop the server
await server.stop();Any number of existing JSON-formatted keys can be added to the keystore.
// Add an existing JWK key to the keystore
await server.issuer.keys.add({
kid: 'some-key',
alg: 'RS256',
kty: 'RSA',
// ...
});JSON Web Tokens (JWT) can also be built programmatically:
import axios from 'axios';
// Build a new token
let token = await server.issuer.buildToken();
// Call a remote API with the token
const response = await axios.get('https://server.example.com/api/endpoint', {
headers: {
authorization: `Bearer ${token}`,
},
});To support HTTPS, an optional cert and key can be supplied to start the server with SSL/TLS using the in-built NodeJS HTTPS module.
We recommend using a package to create a locally trusted certificate, like mkcert.
let server = new OAuth2Server(
'test-assets/mock-auth/key.pem', // Path to private key file
'test-assets/mock-auth/cert.pem', // Path to public SSL/TLS certificate
);Note: Enabling HTTPS will also update the issuer URL to reflect the current protocol.
The library provides a convenient way, through event emitters, to programmatically customize the server processing. This is particularly useful when expecting the OIDC service to behave in a specific way for a single test.
The list of supported events is exported by the library for a guided usage.
import { Events } from 'oauth2-mock-server';
// ...or in CommonJS style:
// const { Events } = require('oauth2-mock-server');-
Events.BeforeTokenSigning
Typed signature:
(token: MutableToken, req: TokenRequestIncomingMessage) => void// Modify the expiration time on next produced token server.service.once(Events.BeforeTokenSigning, (token, req) => { const timestamp = Math.floor(Date.now() / 1000); token.payload.exp = timestamp + 400; });
import basicAuth from 'basic-auth'; // Add the client ID to a token server.service.once(Events.BeforeTokenSigning, (token, req) => { const credentials = basicAuth(req); const clientId = credentials ? credentials.name : req.body.client_id; token.payload.client_id = clientId; });
-
Events.BeforeResponse
Typed signature:
(tokenEndpointResponse: MutableResponse, req: TokenRequestIncomingMessage) => void// Force the oidc service to provide an invalid_grant response // on next call to the token endpoint server.service.once(Events.BeforeResponse, (tokenEndpointResponse, req) => { tokenEndpointResponse.body = { error: 'invalid_grant', }; tokenEndpointResponse.statusCode = 400; });
-
Events.BeforeUserinfo
Typed signature:
(userInfoResponse: MutableResponse, req: IncomingMessage) => void// Force the oidc service to provide an error // on next call to userinfo endpoint server.service.once(Events.BeforeUserinfo, (userInfoResponse, req) => { userInfoResponse.body = { error: 'invalid_token', error_description: 'token is expired', }; userInfoResponse.statusCode = 401; });
-
Events.BeforeRevoke
Typed signature:
(revokeResponse: StatusCodeMutableResponse, req: IncomingMessage) => void// Simulates a custom token revocation result code server.service.once(Events.BeforeRevoke, (revokeResponse, req) => { revokeResponse.statusCode = 418; });
-
Events.BeforeAuthorizeRedirect
Typed signature:
(authorizeRedirectUri: MutableRedirectUri, req: IncomingMessage) => void// Modify the uri and query parameters // before the authorization redirect server.service.once(Events.BeforeAuthorizeRedirect, (authorizeRedirectUri, req) => { authorizeRedirectUri.url.searchParams.set('foo', 'bar'); });
-
Events.BeforePostLogoutRedirect
Typed signature:
(postLogoutRedirectUri: MutableRedirectUri, req: IncomingMessage) => void// Modify the uri and query parameters // before the post_logout_redirect_uri redirect server.service.once(Events.BeforePostLogoutRedirect, (postLogoutRedirectUri, req) => { postLogoutRedirectUri.url.searchParams.set('foo', 'bar'); });
-
Events.BeforeIntrospect
Typed signature:
(introspectResponse: MutableResponse, req: IncomingMessage) => void// Simulate a custom token introspection response body server.service.once(Events.BeforeIntrospect, (introspectResponse, req) => { introspectResponse.body = { active: true, scope: 'read write email', client_id: '<client_id>', username: 'dummy', exp: 1643712575, }; });
| Endpoint | Description |
|---|---|
GET /.well-known/openid-configuration |
Returns the OpenID Provider Configuration Information for the server. |
GET /jwks |
Returns the JSON Web Key Set (JWKS) of all the keys configured in the server. |
POST /token |
Issues access tokens. |
GET /authorize |
Simulates user authentication. Automatically redirects to the callback endpoint. Supports only the code response type. |
GET /userinfo |
Provides extra userinfo claims. |
POST /revoke |
Simulates token revocation. Always returns 200 per RFC 7009. |
GET /endsession |
Simulates the end session endpoint. Redirects to post_logout_redirect_uri; returns state in the redirect URI if provided. |
POST /introspect |
Simulates the token introspection endpoint. |
All endpoint paths can be overridden via the endpoints option. Handy when willing to mimic some vendors default configuration.
All fields are optional; any omitted path falls back to its default.
const oAuth2Service = new OAuth2Service(oauth2Issuer, {
// As 'wellKnownDocument' is purposefully omitted, it will be set to its default,
token: '/oauth/token',
jwks: '/oauth/jwks',
authorize: '/oauth/authorize',
userinfo: '/oauth/userinfo',
revoke: '/oauth/revoke',
endSession: '/oauth/logout',
introspect: '/oauth/introspect',
});Additional routes can be registered via addRoute(). This may be useful when willing to stub vendor specific management routes, for instance
oAuth2Service.addRoute('POST', '/api/v2/clients', (req, res) => {
// Your custom implementation goes here
});- No authentication
- Client Credentials grant
- Resource Owner Password Credentials grant
- Authorization Code grant, with Proof Key for Code Exchange (PKCE) support
- Refresh token grant
- JWT Bearer token grant (
urn:ietf:params:oauth:grant-type:jwt-bearer)
| Crypto scheme | kty |
alg |
|---|---|---|
| RSASSA-PKCS1-v1_5 | RSA | RS256, RS384, RS512 |
| RSASSA-PSS | RSA | PS256, PS384, PS512 |
| ECDSA | EC | ES256, ES384, ES512 |
| EdDSA | OKP | EdDSA, Ed25519 |
Tokens issued by this server are signed with real cryptographic keys and can be verified by any standard JWT library. However, the server performs no validation of incoming requests — any client ID, secret, username, or password is accepted. This is intentional for testing purposes.
This library is not safe for production use.
Review the Security Policy in SECURITY.md for more details.
Contributions are welcome! See CONTRIBUTING.md for setup instructions, coding conventions, and the pull request process.
AI coding agents working in this repository should read AGENTS.md before making any changes.