@onehilltech/blueprint-gatekeeper

4.76.1 • Public • Published

Gatekeeper

OAuth 2.0 token server and module for Blueprint.js

npm version Build Status Dependencies Coverage Status

Installation

yarn add @onehilltech/blueprint-gatekeeper

or

npm install @onehilltech/blueprint-gatekeeper --save

Getting Started

Defining the configuration

Gatekeeper uses JSON Web Tokens to manage authorization of authenticated users. To get started, you must first configure the options for token generation. The options supported are the same as those in node-jsonwebtoken.

// app/configs/gatekeeper.js

module.exports = {
 tokens: {
     // This is the base options for all token generators.
     $: {
       issuer: '[your-issuer-name-here]',
       expiresIn: '1h',
       algorithm: 'HS256',
       secret: 'ssshhh'
     }
 },
};

The jwtid option is not supported since Gatekeeper uses it to generate a unique id for each token.

Mount Gatekeeper router endpoint

Next, we need to import (or mount) the Gatekeeper router into our application. This will expose routes for managing and authenticating accounts and clients.

// app/routers/endpoint.js

const blueprint = require ('@onehilltech/blueprint');
const { Router } = blueprint;

module.exports = Router.extend ({
  specification: {
    '/gatekeeper': blueprint.mount ('@onehilltech/blueprint-gatekeeper:v1')    
  }
});

In the example above, we are mounting the v1 router to the /gatekeeper endpoint. This means that all routers in v1 will be accessible at http://[hostname]/gatekeeper/.

Protecting routes

The last step is to define what routes require authorization (i.e., are protected) using the gatekeeper.auth.bearer Blueprint policy.

// app/routers/endpoint.js

const blueprint = require ('@onehilltech/blueprint');
const { Router } = blueprint;

module.exports = Router.extend ({
  specification: {
    '/gatekeeper': blueprint.mount ('@onehilltech/blueprint-gatekeeper:v1'),
    
    // Let's protect the /v1 routes.
    '/v1': {
      policy: 'gatekeeper.auth.bearer'
    }  
  }
});

In the example above, the router will protect all routes under the /v1 path, which also includes all routers located in app/routers/v1 directory. The client will need to define the Authorization header and include a generated token.

Accessing the Authorized User

The req.user property contains the account models for an authorized user making the request to access a protected route. For example, here is an example of setting the user making the request as the owner of a created resource.

const { model } = require ('@onehilltech/blueprint');
const { ResourceController } = require ('@onehilltech/blueprint-mongodb');

module.exports = ResourceController.extend ({
  Model: model ('tweet'),
  
  create () {
    return this._super (this, ...arguments).extend ({
      prepareDocument (req, doc) {
        // Make the authorized user the owner of the created resource.
        doc.user = req.user._id;
        return doc;
      }
    });
  }
});

Gatekeeper has a UserResourceController that automatically adds the authorized user making the request as the owner of the resource being created.

Cross-Origin Resource Sharing (CORS)

Cross-Origin Resource Sharing (CORS) is a mechanism that allows a client from one domain to access resources from another domain. This typically occurs when you have a web browser accessing an API protected by Gatekeeper. If you need to enable CORS support for your Blueprint application, then use the gatekeeper.cors() middleware:

// app/routes/v1.js

const { env } = require ('@onehilltech/blueprint');
const { cors } = require ('@onehilltech/blueprint-gatekeeper');

module.exports = {
  '/v1': {
    use: [cors ({
      origin: env !== 'production' ? true : null
    })]
  }
};

Now, any request for a route that begins with /v1 will support CORS. The gatekeeper.cors() middleware is a wrapper around Express CORS. It will check if the origin in the request matches any registered client only when running in production. All other times, CORS is enabled by default regardless of the origin in the request.

Third-party Authentication

Third-party authentication is when you use another service to authenticate the user, and then issues an access token for authenticated user on the host system/service. For example, you use Facebook to authenticate a user and then issue an access token from the host service for the authenticated user. The rationale for such capabilities is you want to use the host service authorization mechanism to control access, but do not want to require users to manage authentication (i.e., username and passwords) on either system.

To account for this scenario, Gatekeeper provides a session service that can be used to issue access tokens for accounts/users against a client. It is the host system's responsibility to ensure the generated access tokens are for authenticated users. To use the service, just inject the session service into your controller. Then, define an authenticate() method to authenticate a user using the third-party service. This means the user will submit their username and password to the host service, and the host service will forward the information along to the third-party service.

module.exports = Controller.extend ({
  /// Inject the session service into the controller.
  session: service (),
  
  authenticate () {
    return Action.extend ({
      execute (req, res) {
        return this.authenticateUsingThirdParty ();
          .then (result => {
            //
          });
      }
    });
  }
})

Once the user is authenticated, you then use information about the authenticated user to issue an access token. As shown in the example below, you will first use findAccountByEmail or findAccountByUsername to lookup the corresponding account for the user.

findAccountByEmail and findAccountByUsername does not create an account if it does not exist. If the account does not exist, you will have to create one.

Then use issueToken to issue a token for the account on the corresonding client. Lastly, use serializeToken to convert the token from an object to a JSON object. The JSON object can then be sent as a response to the client.

module.exports = Controller.extend ({
  /// Inject the session service into the controller.
  session: service (),
  
  authenticate () {
    return Action.extend ({
      execute (req, res) {
        const { client_id } = req.body;
        
        return this.authenticateUsingThirdParty (req)
          .then (result => this.session.findAccountByEmail (result.email))
          .then (account => this.session.issueToken (client_id, account))
          .then (token => this.session.serializeToken (token))
          .then (token => res.json (token));
      }
    });
  },
  
  authenticateUsingThirdParty () {
    // Perform the remote authentication.
  }
})

Gatekeeper Client Libraries

Next Steps

See the Wiki for more information.

Readme

Keywords

Package Sidebar

Install

npm i @onehilltech/blueprint-gatekeeper

Weekly Downloads

5

Version

4.76.1

License

Apache-2.0

Unpacked Size

193 kB

Total Files

87

Last publish

Collaborators

  • onehilltech