oauth2-mock-serverOAuth 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.
/jwks endpoint, without mocking the verification layer.beforeAll/afterAll) or run it as a standalone process for Java, .NET, Python, and other non-JS projects.server.service.once(Events.xxx, ...) to alter token claims, simulate errors, or modify responses for a single test — without reconfiguring the server.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-server
The server can be run from the command line.
npx oauth2-mock-server --help
The 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');
Typed signature: (token: MutableToken, req: TokenRequestIncomingMessage) => void
js
// 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;
});
```js 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; }); ```
Typed signature: (tokenEndpointResponse: MutableResponse, req: TokenRequestIncomingMessage) => void
js
// 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;
});
Typed signature: (userInfoResponse: MutableResponse, req: IncomingMessage) => void
js
// 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;
});
Typed signature: (revokeResponse: StatusCodeMutableResponse, req: IncomingMessage) => void
js
// Simulates a custom token revocation result code
server.service.once(Events.BeforeRevoke, (revokeResponse, req) => {
revokeResponse.statusCode = 418;
});
Typed signature: (authorizeRedirectUri: MutableRedirectUri, req: IncomingMessage) => void
js
// Modify the uri and query parameters
// before the authorization redirect
server.service.once(Events.BeforeAuthorizeRedirect, (authorizeRedirectUri, req) => {
authorizeRedirectUri.url.searchParams.set('foo', 'bar');
});
Typed signature: (postLogoutRedirectUri: MutableRedirectUri, req: IncomingMessage) => void
js
// 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');
});
Typed signature: (introspectResponse: MutableResponse, req: IncomingMessage) => void
js
// 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
});
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.
$ claude mcp add oauth2-mock-server \
-- python -m otcore.mcp_server <graph>