Giter Site home page Giter Site logo

axa-group / oauth2-mock-server Goto Github PK

View Code? Open in Web Editor NEW
159.0 12.0 48.0 1.64 MB

A development and test oriented OAuth2 mock server

License: MIT License

JavaScript 5.35% TypeScript 94.65%
oauth2-server mock-server testing nodejs hacktoberfest oauth2

oauth2-mock-server's Introduction

oauth2-mock-server

npm package Node.js version

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 teared down at will, and can be programmatically run while performing automated tests.

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.

Development prerequisites

How to use

Installation

Add it to your Node.js project as a development dependency:

With yarn...

yarn add -D oauth2-mock-server

...or with npm

npm install --save-dev oauth2-mock-server

Quickstart

Here is an example for creating and running a server instance with a single random RSA key:

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 be built programmatically:

const request = require('request');

// Build a new token
let token = await server.issuer.buildToken();

// Call a remote API with the token
request.get(
  'https://server.example.com/api/endpoint',
  { auth: { bearer: token } },
  function callback(err, res, body) {
    /* ... */
  }
);

Supported JWK formats

Algorithm kty alg
RSASSA-PKCS1-v1_5 RSA RS256, RS384, RS512
RSASSA-PSS RSA PS256, PS384, PS512
ECDSA EC ES256, ES256K, ES384, ES512
Edwards-curve DSA OKP EdDSA (Ed25519 / Ed448)

Customization hooks

It also 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 on one single test:

  • The JWT access token

    // Modify the expiration time on next token produced
    service.once('beforeTokenSigning', (token, req) => {
      const timestamp = Math.floor(Date.now() / 1000);
      token.payload.exp = timestamp + 400;
    });
    // Add the client ID to a token
    const basicAuth = require('basic-auth');
    service.once('beforeTokenSigning', (token, req) => {
      const credentials = basicAuth(req);
      const clientId = credentials ? credentials.name : req.body.client_id;
      token.payload.client_id = clientId;
    });
  • The token endpoint response body and status

    // Force the oidc service to provide an invalid_grant response
    // on next call to the token endpoint
    service.once('beforeResponse', (tokenEndpointResponse, req) => {
      tokenEndpointResponse.body = {
        error: 'invalid_grant',
      };
      tokenEndpointResponse.statusCode = 400;
    });
  • The userinfo endpoint response body and status

    // Force the oidc service to provide an error
    // on next call to userinfo endpoint
    service.once('beforeUserinfo', (userInfoResponse, req) => {
      userInfoResponse.body = {
        error: 'invalid_token',
        error_message: 'token is expired',
      };
      userInfoResponse.statusCode = 401;
    });
  • The revoke endpoint response body and status

    // Simulates a custom token revocation body
    service.once('beforeRevoke', (revokeResponse, req) => {
      revokeResponse.body = {
        result: 'revoked',
      };
    });
  • The authorization endpoint redirect uri and query parameters

    // Modify the uri and query parameters
    // before the authorization redirect
    service.once('beforeAuthorizeRedirect', (authorizeRedirectUri, req) => {
      authorizeRedirectUri.url.searchParams.set('foo', 'bar');
    });
  • The end session endpoint post logout redirect uri

    // Modify the uri and query parameters
    // before the post_logout_redirect_uri redirect
    service.once('beforePostLogoutRedirect', (postLogoutRedirectUri, req) => {
      postLogoutRedirectUri.url.searchParams.set('foo', 'bar');
    });
  • The introspect endpoint response body

    // Simulate a custom token introspection response body
    service.once('beforeIntrospect', (introspectResponse, req) => {
      introspectResponse.body = {
        active: true,
        scope: 'read write email',
        client_id: '<client_id>',
        username: 'dummy',
        exp: 1643712575,
      };
    });

HTTPS support

It also provides basic HTTPS support, 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',
  'test-assets/mock-auth/cert.pem'
);

NOTE: Enabling HTTPS will also update the issuer URL to reflect the current protocol.

Supported endpoints

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. Currently, this endpoint is limited to:

  • No authentication
  • Client Credentials grant
  • Resource Owner Password Credentials grant
  • Authorization code grant
  • Refresh token grant

GET /authorize

It simulates the user authentication. It will automatically redirect to the callback endpoint sent as parameter. It currently supports only 'code' response_type.

GET /userinfo

It provides extra userinfo claims.

POST /revoke

It simulates a token revocation. This endpoint should always return 200 as stated by RFC 7009.

GET /endsession

It simulates the end session endpoint. It will automatically redirect to the post_logout_redirect_uri sent as parameter.

POST /introspect

It simulates the token introspection endpoint.

Command-Line Interface

The server can be run from the command line. You can either install it globally:

npm install -g oauth2-mock-server
oauth2-mock-server --help

or run it directly:

npx oauth2-mock-server --help

Attributions

oauth2-mock-server's People

Contributors

acasella avatar andtem avatar cfman avatar dependabot[bot] avatar hashimoto-takafumi avatar henriquels25 avatar jirutka avatar jjbooth74 avatar kadams54 avatar lbestftr avatar markwallsgrove avatar nulltoken avatar poveden avatar roskh avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

oauth2-mock-server's Issues

'aud' attribute missing in Authorization Code flow

Summary

When I request a token using the authorization code flow, I am receiving an id_token without the 'aud' attribute.

This is happening because the request is being made with the client_id in the body of the request, using the 'x-www-form-urlencoded' content type.

This type of request is documented in the OAuth 2.0 specification: https://tools.ietf.org/html/rfc6749#section-4.1.3
In my project (a single page application), I shouldn't use the BASIC authentication scheme because I am not sending the client_secret in the request.

The authorization server could support both situations, looking at the Authorization header and at the client_id attribute in the request body.

Steps to Reproduce

Sample request:
curl 'http://localhost:8083/token' -H 'Connection: keep-alive' -H 'Pragma: no-cache' -H 'Cache-Control: no-cache' -H 'Origin: http://localhost:3000' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36' -H 'Content-Type: application/x-www-form-urlencoded' -H 'Accept: */*' -H 'Sec-Fetch-Site: same-site' -H 'Sec-Fetch-Mode: cors' -H 'Referer: http://localhost:3000/callback?code=b5f4ff31-2745-4d92-a74d-b1c15b526d0b&scope=openid&state=d785b4d2116e48169afdfba16f6a5f81' -H 'Accept-Encoding: gzip, deflate, br' -H 'Accept-Language: en,pt-BR;q=0.9,pt;q=0.8' --data 'client_id=client_id_sample&code=b5f4ff31-2745-4d92-a74d-b1c15b526d0b&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fcallback&code_verifier=7ac9958f77384255b5449fd77d35e8ba3788f0d88fa14ea6b6d782adf9ea12ff10ea725d9f2b4367bd63af6117d89eab&grant_type=authorization_code' --compressed

Customization hooks are not working

Summary

beforeTokenSigning hook does not allow state to be changed.

Steps to Reproduce

  1. run
const { OAuth2Server } = require('oauth2-mock-server');

(async () => {
    let server = new OAuth2Server();
    // Generate a new RSA key and add it to the keystore
    await server.issuer.keys.generate('RS256');
    server.service.once('beforeTokenSigning', (token, req) => {
      token.payload.exp = token.payload.iat + 400;
    });

    // Start the server
    await server.start(8080);

    console.log(`OAuth 2 issuer is ${server.issuer.url}`);

})();
  1. run
curl 'http://localhost:8080/authorize?response_type=code&redirect_uri=http://localhost:8081/callback&scope=dummy_scope&state=state123&client_id=abcecedf&nonce=21ba8e4a-26af-4538-b98a-bccf031f6754' \
  -H 'Accept: text/html,application/xhtml+xml'

Found. Redirecting to http://localhost:8081/callback?code=8fcbdb52-f2ad-4f43-aaf3-501d45cc7723&state=state123

  1. get token by code
curl -X POST http://localhost:8080/token \
 -H "Content-Type: application/x-www-form-urlencoded" \
 -d "grant_type=authorization_code&client_id=abcecedf&code=8fcbdb52-f2ad-4f43-aaf3-501d45cc7723"
  1. decode id_token
npx jwt-cli --output=json eyJraWQiOiIxNDljYjRiZmJmZDQxZGM2ZGEwMzcxZTFjZjdmODU0Y2UxNDZkMTZkOGRkNjRhMTAwODYwMjE4YjE3NDdkZGFjZmNiYjg3MDBlMjY5MmUwMCIsInR5cCI6IkpXVCIsImFsZyI6IlJTMjU2In0.eyJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAiLCJpYXQiOjE2OTY1NDUwNjcsImV4cCI6MTY5NjU0ODY2NywibmJmIjoxNjk2NTQ1MDU3LCJzdWIiOiJqb2huZG9lIiwiYXVkIjoiYWJjZWNlZGYifQ.pSxO_m8BCuM5lMWgHV9Vs9omKahTylitPA8nEn_VOjeyBdqZGV2C0EI_x2qCjCkMqS4Dc9fyP25BHinAUJ9X613Tw1t4_wzaYQVdLIKZxBBYAVOzvOOiosY6jYLDtz6jKFd6kecjR57u8WurxnP-msQK4D5_tYhrLhH9xBAcjcXMIIgjX4SN9etaiksaHwkucpSDqxTWs9aNJfb67k0sWOL5lwGuFKIgLKgcFiBwwaPyTk5h4LCmOY-dobWBFDXTSUFcOqZjmMWIbSLaFuWvEmaLHJyucLKc9IIQW-wbwGgTSsccTaQXINdKbinhy1WxB2T0Bazh2ANQsh7Sl6v26g
  1. check that payload.exp is not changed

Expected Behavior

payload.exp is changed

Screenshots

Environment

  • oauth2-mock-server version: (7.0.0)
  • Noje.JS version: (v19.8.1)
  • NPM version: (9.5.1)
  • Operating System: (Windows 11)

Additional Context

cannot load is-plain-obj with 7.1.0

After upgrade to 7.1.0 from 7.0.0 we encounter the following error:

2023-10-23 14:18:57 /app/node_modules/oauth2-mock-server/dist/lib/helpers.js:9
2023-10-23 14:18:57 const is_plain_obj_1 = __importDefault(require("is-plain-obj"));
2023-10-23 14:18:57                                        ^
2023-10-23 14:18:57 
2023-10-23 14:18:57 Error [ERR_REQUIRE_ESM]: require() of ES Module /app/node_modules/is-plain-obj/index.js from /app/node_modules/oauth2-mock-server/dist/lib/helpers.js not supported.
2023-10-23 14:18:57 Instead change the require of index.js in /app/node_modules/oauth2-mock-server/dist/lib/helpers.js to a dynamic import() which is available in all CommonJS modules.
2023-10-23 14:18:57     at Object.<anonymous> (/app/node_modules/oauth2-mock-server/dist/lib/helpers.js:9:40)
2023-10-23 14:18:57     at Object.<anonymous> (/app/node_modules/oauth2-mock-server/dist/lib/oauth2-issuer.js:7:19)
2023-10-23 14:18:57     at Object.<anonymous> (/app/node_modules/oauth2-mock-server/dist/index.js:20:23) {
2023-10-23 14:18:57   code: 'ERR_REQUIRE_ESM'
2023-10-23 14:18:57 }
2023-10-23 14:18:57 
2023-10-23 14:18:57 Node.js v20.8.0

as shown above, we use node 20.8.0 and type: "module" in our package.json

{
    "name": "mock-oauth",
    "version": "1.0.0",
    "description": "",
    "main": "index.js",
    "type": "module",
    "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
    },
    "author": "",
    "license": "ISC",
    "volta": {
        "node": "20.8.0"
    },
    "dependencies": {
        "oauth2-mock-server": "7.1.0"
    }
}

Add support for x5c field in /jwks

Summary

A production server we're integrating with has an x5c field in the /jwks key entries, which is being used to validate tokens. It would be amazing to understand how to alllow this to work in the mock server as well :)

Desired solution

Support an x5c key within the /jwks list.

Alternative solutions

I'm really new to oauth2/openid, so I'm just barely grasping this first option. Sorry!

Additional Context

https://curity.io/resources/learn/self-contained-jwts/#x5c

Add Management API to set/unset subject

Summary

I would like to use this tool without the need to write NodeJS and/or create some duplicated code in different projects.

Desired solution

I would like to have a simple REST API where I can set/unset what username will be set to sub.

Alternative solutions

?

Additional Context

Eventually, I would like to bake a docker image from this tool.
My proposed implementation: master...utamas:master.

Is the sub hardcoded?

Summary

I'm trying to change the sub but always returns johndoe

Steps to Reproduce

Try to change the sub in beforeTokenSigning
Like

 server.service.once('beforeTokenSigning', (token, req) => {   
     token.payload.sub = '123';                                                              
 });                                                           

Expected Behavior

The sub is updated

Environment

  • oauth2-mock-server version: 4.3.0
  • Noje.JS version: 16

Additional Context

As far as I can see this is actually hardcoded in 4.3.0 because in https://github.com/axa-group/oauth2-mock-server/blob/master/src/lib/oauth2-service.ts#L255-L257 object.assign will always patch the payload with sub.
I am right?

Replace Assertion Errors with user-friendlier http bad requests

Following #141 (and #142), it's been put under the light that when the library is incorrectly used, it doesn't communicate the issue in a very user friendly manner

  <html lang=\"en\">
    <head>
    <meta charset=\"utf-8\">
    <title>Error</title>
    </head>
    <body>
    <pre>AssertionError [ERR_ASSERTION]: Invalid &#39;grant_type&#39; type<br> &nbsp; &nbsp;at new AssertionError (node:internal/assert/assertion_error:466:5)<br> &nbsp; &nbsp;at assertIsString (C:\\_work\\oauth2-mock-server\\src\\lib\\helpers.ts:33:11)<br> &nbsp; &nbsp;at assertIsValidTokenRequest (C:\\_work\\oauth2-mock-server\\src\\lib\\helpers.ts:64:3)<br> &nbsp; &nbsp;at fn (C:\\_work\\oauth2-mock-server\\src\\lib\\oauth2-service.ts:186:7)<br> &nbsp; &nbsp;at Layer.handle_request (C:\\_work\\oauth2-mock-server\\node_modules\\express\\lib\\router\\layer.js:95:5)<br> &nbsp; &nbsp;at next (C:\\_work\\oauth2-mock-server\\node_modules\\express\\lib\\router\\route.js:137:13)<br> &nbsp; &nbsp;at fn (C:\\_work\\oauth2-mock-server\\node_modules\\body-parser\\lib\\types\\urlencoded.js:100:7)<br> &nbsp; &nbsp;at Layer.handle_request (C:\\_work\\oauth2-mock-server\\node_modules\\express\\lib\\router\\layer.js:95:5)<br> &nbsp; &nbsp;at next (C:\\_work\\oauth2-mock-server\\node_modules\\express\\lib\\router\\route.js:137:13)<br> &nbsp; &nbsp;at Route.dispatch (C:\\_work\\oauth2-mock-server\\node_modules\\express\\lib\\router\\route.js:112:3)</pre>
    </body>
</html>

Rather than throwing AssertionErrors and letting Express default error handler deal with them, it might be cleaner to return 400 responses with a meaningful error message.

Interactive/Customisable ID Tokens

Summary

While executing a browser test it is desirable to test different situations which are triggered by the content within the id token. Providing the facility for the browser test to override the claims within the id token is very powerful. Essentially rather than asking for a username and password, we would ask who would you like to be?

Desired solution

While iterating through the authorization flow it is possible for the test to interact with the fake IDP by submitting data to the server. I have appended a example of this functionality to provide a center piece to discuss, but this solution is far from ideal due to the framework's current limitations.

It would be fantastic if this functionality could be built in and turned on by a feature flick switch, but I would like to hear suggestions from the authors before investing in a solution.

import { request, Request } from 'express';
import { urlencoded } from 'body-parser';
import { OAuth2Server } from 'oauth2-mock-server';
import session from 'express-session';
import createMemoryStore from 'memorystore';
import { MutableAuthorizeRedirectUri, MutableToken } from 'oauth2-mock-server/dist/lib/types';
import { IncomingMessage } from 'http';
import querystring from 'querystring';

const MemoryStore = createMemoryStore(session);

declare module 'express-session' {
  interface SessionData {
    [key: string]: string;
  }
}

async function startServer(): Promise<OAuth2Server> {
  const server = new OAuth2Server();
  await server.issuer.keys.generateRSA();
  return server;
}

interface Authorizations {
  [key: string]: string;
}

const checkPeriod = 86400000; // prune expired entries every 24h;
const maxAge = 86400000;
const authorizations: Authorizations = {};

startServer()
  .then((server) => {
    const requestHandler = server.service.requestHandler;

    // logger
    requestHandler.use((req, res, next) => {
      console.log(JSON.stringify({ path: req.path, method: req.method }));
      next();
    });

    // form post decoding
    requestHandler.use(urlencoded({ extended: false }));

    // session cookie handling
    requestHandler.use(
      session({
        cookie: { maxAge, secure: false },
        store: new MemoryStore({ checkPeriod }),
        resave: false,
        secret: 'keyboard cat',
        saveUninitialized: true,
      }),
    );

    /**
     * Intercept the call to the authorize endpoint to provide the opportunity to customise the
     * resulting JWT. The customisation comes in the form of providing a json blob that includes
     * the desired JWT claims. This data is then mixed with the standard JWT claims.
     */
    requestHandler.use('/authorize', (req, res, next) => {
      if (!req.session.userdata && req.method === 'GET') {
        const [path, query = ''] = req.url.split('?', 2);
        req.session.authQuery = query;
        req.session.save();

        res.writeHead(200, { 'Content-Type': 'text/html' });
        res.write(
          '<form method="POST" action="/authorize"><textarea id="userdata" name="userdata" rows="4" cols="50">{}</textarea><input type="submit"></form>',
        );
        res.end();
      } else {
        next();
      }
    });

    /**
     * Take the data submitted within the text area that represents a set of custom JWT claims
     * and store it within the session. As we don't know the related authorization code yet we
     * need to wait until it's known to associate the data with the key.
     */
    requestHandler.post('/authorize', (req, res) => {
      const userdata = JSON.parse(req.body.userdata);
      req.session.userdata = userdata;
      req.session.save();

      // use the original query string to restart the authorize flow now that we have the
      // required data
      res.redirect(`/authorize?${req.session.authQuery}`);
    });

    // just don't ask.. You are going to ask aren't you.. OK.. When we added the middleware
    // above it was added as the last "layer" within express' routing configuration. Because
    // of this it means it never gets executed. As we don't control the order of when the
    // routers vs the middleware are added, here we are. I bet you wish you didn't ask now.
    const authPostHandler = requestHandler._router.stack.pop();
    const authMiddleware = requestHandler._router.stack.pop();
    const sessionStorageMiddleware = requestHandler._router.stack.pop();
    const urlencodedDecoder = requestHandler._router.stack.pop();
    const loggerMiddleware = requestHandler._router.stack.pop();
    requestHandler._router.stack.splice(2, 0, loggerMiddleware);
    requestHandler._router.stack.splice(3, 0, urlencodedDecoder);
    requestHandler._router.stack.splice(4, 0, sessionStorageMiddleware);
    requestHandler._router.stack.splice(5, 0, authMiddleware);
    requestHandler._router.stack.splice(6, 0, authPostHandler);

    /**
     * Listen for the beforeAuthorizeRedirect event. If we have a authorization code & a set of user
     * data which represents the custom JWT claims, save it for later. This data will be used within
     * the beforeTokenSigning event to customise the JWT.
     */
    server.service.on('beforeAuthorizeRedirect', (uri: MutableAuthorizeRedirectUri, req: Request) => {
      const code = uri.url.searchParams.get('code');
      const userdata = req.session.userdata;
      if (code && userdata) {
        authorizations[code] = userdata;

        // clean the memory
        req.session.userdata = undefined;
        req.session.save();
      }
    });

    /**
     * Listen for the beforeTokenSigning event. When this event occurs inject in
     * the custom claims into the token which was provided when authorizing the
     * flow.
     */
    server.service.on('beforeTokenSigning', (token: MutableToken, req: Request) => {
      const code = req.body.code;
      if (authorizations[code]) {
        const userdata = authorizations[code];
        token.payload = Object.assign({}, token.payload, userdata);
      }
    });

    return server.start(8080, '0.0.0.0');
  })
  .catch((e) => console.log('Something went wrong starting the server: ', e));

Support specifying custom endpoints paths

Summary

It would be useful to specify different paths for the endpoints other than the current ones since some OAuth2 clients
use hardcoded paths which can be different from the ones in this library (such as the Auth0 FE & BE clients)

Desired solution

A way to specify the endpoints paths when starting server, e.g.:

server.start(PORT, '0.0.0.0', {
  paths: {
    token_path: '/oauth/token'
  }
});

Alternative solutions

N/A

Additional Context

Auth0 first party client libraries use hard-coded paths for some OAuth2 endpoints, despite what the well know document might say, such as the token endpoint which is /oauth/token in Auth0 but just /token here.

Support for Cross-Origin Resource Sharing (CORS)

Summary

I have a single page application that uses the authorization code flow to authenticate with the authorization server.
Right now, it is not possible to use this mock server because the request is blocked by CORS policy.

Error: Access to XMLHttpRequest at 'http://localhost:8083/.well-known/openid-configuration' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Desired solution

It would be good if the mock authorization server supported CORS, or if there was a client argument to enable it.

This project mandates JWTs for tokens, whilst OAuth 2.0 does not

Summary

The OAuth 2.0 specifications do not mandate JWTs for access tokens and ID tokens (only OIDC does that, though there are OAuth 2.0 specifications that define JWTs for tokens). It might be worth clarifying whether you mean this project as an OIDC mock server or an OAuth 2.0 mock server.

If it's the latter, then supporting non-JWT tokens would be a good idea (as well as disabling the .well-known/openid-configuration endpoint and potentially supporting RFC8414 which is similar but different.

Also, OAuth 2.0 doesn't mandate that servers must support token introspection, so being able to disable that would be good.

Note: Filed this as a bug, as it's unclear the intent of this project because of the discrepancy between its name and the functionality implemented.

If this project were to support non-JWT access tokens, it could be used by folks developing services/apps for Mastodon and similar federated social media software, which tends to use OAuth 2.0 specs but not implement OIDC.

Ability to modify authorize redirect url

Summary

It is currently not possible to modify the target redirection url used within the authorize handler to a customise the query parameters.

Desired solution

Emitting a event with the url components to optionally provide the ability to customise the target redirection before the redirect would be amazing.

Alternative solutions

Possibility supplying a fixed configuration before executing the server could work, but it wouldn't be as flexible.

Additional Context

I am attempting to mimic the behavior of Salesforce auth, but the callback query string includes two custom keys (sfdc_community_url, sfdc_community_id) which we require.

npm install fails for version 3.0.0

Summary

Running npm install on latest version fails. Install of older version works (npm install [email protected])

Steps to Reproduce

  1. Using a blank nodejs project, type npm install oauth2-mock-server
  2. See error below

Expected Behavior

The npm install completes and modules is installed in my node_modules

Error Behavior

โžœ  npm install oauth2-mock-server

npm ERR! code ENOENT
npm ERR! syscall chmod
npm ERR! path /Users/user/Projects/test-oauth/node_modules/oauth2-mock-server/dist/oauth2-mock-server.js
npm ERR! errno -2
npm ERR! enoent ENOENT: no such file or directory, chmod '/Users/user/Projects/test-oauth/node_modules/oauth2-mock-server/dist/oauth2-mock-server.js'
npm ERR! enoent This is related to npm not being able to find a file.
npm ERR! enoent 

If applicable, add screenshots to help explain your problem.

Environment

  • oauth2-mock-server version: 3.0.0
  • Noje.JS version: v12.18.3
  • NPM version: v6.14.8
  • Operating System: macOS 10.15.7 (Catalina)

Additional Context

None

Adding end_session_endpoint support

Summary

For testing my custom oidc provider I need an end_session_endpoint support.

Desired solution

I will create a pull request that will add end_session_endpoint support.

Typescript type definitions

Summary

I'd like to use this from tests written in TypeScript

Desired solution

TypeScript type defs being part of the published package.

Additional Context

I can think of three ways to make this happen:

  • Either maintain the types here as a .d.ts file
  • Maintain them in DefinitelyTyped repo
  • Port the whole code to TypeScript and let tsc generate the type defs

The two first options have great chances to not be always kept in sync
I'd be open to submit a PR to help making the third solution happen.

Is it possible to modify the id_token?

Hi I know that it's possible to edit the content of the access_token through
service.once('beforeTokenSigning', (token, req) => {
but is it possible to edit the id_token aswell?

Token requests can trigger a "UnhandledPromiseRejectionWarning" in version 4.0.0+

Summary

It is possible to trigger an UnhandledPromiseRejectionWarning: AssertionError [ERR_ASSERTION]: Invalid 'grant_type' type warning for invalid requests in version 4.0.0 and later.

Steps to Reproduce

  1. Start the following server in 4.0.0 or 4.1.0:
const { OAuth2Server } = require('oauth2-mock-server');

async function startServer() {
    let server = new OAuth2Server();
    await server.issuer.keys.generate('RS256');
    await server.start(8080, 'localhost');
}

startServer();
  1. Run curl --request POST --url http://localhost:8080/token --header 'Content-Type: multipart/form-data;'

Expected Behavior

An assertion failure message. The equivalent code in version 3.2.0 works as expected:

const { OAuth2Server } = require('oauth2-mock-server');

async function startServer() {
    let server = new OAuth2Server();
    await server.issuer.keys.generateRSA();
    await server.start(8080, 'localhost');
}

startServer();

Environment

  • oauth2-mock-server version: 4.1.0
  • Noje.JS version: 14.15.0
  • NPM version: 6.14.8
  • Operating System: macOS 11.6

Ability to modify URL issuer

Summary

Some frameworks are requiring OAuth URLs to have a prefix of /oauth before the actual OAuth endpoints, e.g. /oauth/authorize or /oauth/token.

Desired solution

It would be nice to have a configuration file for endpoints, rather than fixed ones, in order to support flexibility in testing.

Add support of Authentication Method "Post"

Summary

Currently, the Basic authentication is working fine, but some Authentication Server authorized also the "Post" feature (ex: Auth0 ).

The RFC mention the support of this method.

The support of the "Post" authentication will help to simulate Authorization Server.

Example:

curl --location --request POST 'https://localhost:6666/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'scope=<scope>' \
--data-urlencode 'client_id=<client_id>' \
--data-urlencode 'client_secret=<client_secret>'

How to run the CLI?

in the repo you have an instruction that says "The server can be run from the command line. Run oauth2-mock-server --help for details on its utilization." but there is no info on how to install the CLI.

Creation of a new release

Summary

I need the creation of a new release in order to use the authorization server with a single page application.

Desired solution

A new release created (could be 1.4.0).

How to return a profile to callback

How would I return profile object to an OAuth2Strategy callback.

const strategy = new OAuth2Strategy(
  {
    state: true,
    authorizationURL: `${process.env.MOCK_AUTH_SERVER_URL}/authorize`,
    tokenURL: `${process.env.MOCK_AUTH_SERVER_URL}/token`,
    clientID: "xxx",
    clientSecret: "xxx",
    callbackURL: `${process.env.SERVER_URL}/callback`,
    passReqToCallback: true,
  },
  async (accessToken, refershToken, profile, done) => {
    console.log("profile = ", profile);
    if (profile) {
      return done(null, profile);
    }

}
);

I tried updating the tokenEndpointResponse int the beforeResponse emitter but that didn't work.

let server = new OAuth2Server();
await server.issuer.keys.generate("RS256");
await server.start(3003, "localhost");
server.service.once("beforeResponse", (tokenEndpointResponse, req) => {
    tokenEndpointResponse.profile = {
      ...tokenEndpointResponse.body,
      id: tokenEndpointResponse.body.id_token,
    };
  });

Anyone any idea how I might be able to send back profile, accessToken and a refershToken ?
Currently I get back a hash string from profile. example: 0edd82bc-a48c-4a59-8bd6-e79cccc8b2d8

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.