2.0.0 • Published 8 days ago

@essential-projects/auth v2.0.0

Weekly downloads
13
License
-
Repository
-
Last release
8 days ago

Auth

Passport-based module to authorize user-requests, for example with google.

Features

  • Provides a simple to use middleware, that handles all the sessioning and authorizing
  • Automatically refreshes the access-token if it expired, before calling the next middleware
  • Provides the necessary routes to completely handle the login-process
  • Provides event-based-auth-hooks so you can dely/reject authorization

Configuration

  1. Copy the demo-config from doc/auth.json to config/ENVIRONMENT/auth/auth.json in your project
  2. Replace all the upper-case strings with your corresponding config
  3. Replace other configurations if necessary (in the demo-config, http://localhost:8000 is the backend, and http://localhost:9000 is the frontend)
  4. Delete all the strategies that you don't need from the config

Setup

  1. In your http-extension-module in your application run npm install @5minds/auth --save
  2. In your http-extensions ioc_module.js
  3. Require the module with const auth = require('@5minds/auth/ioc_module');
  4. Register the module at the IoC-Container with: auth.registerInContainer(container);

Usage

  • Let the IoC-Container inject the auth-module into the classes, that register the routes that need authorization

  • add the auth-modules middleware to the routes that need authorization, like so:

this.router.get('/tasks/:smartlistId', this.auth.middleware, YOUR_NEXT_MIDDLEWARE_GOES_HERE);
  • If the authorization failed for some reason, the middleware will redirect to the failRedirect-route provided in the config, and no other middleware will be called

  • If the authorization succeeded, the request now has a session-object and a user-object. The user-object has the following structure:

    for google-auth

    req.user = {
      credentials: {
        access_token: 'SOME_OAUTH_ACCESS_TOKEN',
        refresh_token: 'SOME_OAUTH_REFRESH_TOKEN',
        refresh_after: 'THE_ACCESS_TOKEN_EXPIRATION_TIME',
      },
      profile: {
        name: {
          first: 'Heiko',
          last: 'Mathes',
          display: 'Heiko Mathes',
        },
        language: 'de',
        image: 'https://someUrl',
        email: 'heiko.mathes@5minds.de',
      },
      userToken: 'SOME_TOKEN_THAT_IDENTIFIES_THE_USER',
      strategy: 'google',
    }

    for local password-auth:

    req.user = {
      profile: THE_USER_PROFILE_OBJECT_FROM_YOUR_APP,
      strategy: 'password',
    }

local password-strategy

For the local password-strategy to work, you need to listen to the auth-modules userLogin-event at some point in your application.
This event will get fired, everytime a user wants to login. A Demo-implementation could look like this:

this.auth.on('userLogin', (userParams) => {

  this.user.getUserByMailAddress(userParams.username)
    .then((userInfo) => {

      if (!userInfo.password === this.hash(userParams.password)) {
        logger.debug(`${userParams.username} tried to login with a wrong password`);
        return Promise.reject(new Error('password mismatch'));
      }

      return userParams.resolve(userInfo);
    })
    .catch((error) => {
      userParams.reject(error);
    });
});

The userParams-Object looks like this:

{
  username: 'SOMEUSERNAME',
  password: 'SOMEPASSWORD',
  resolve: FUNCTION,
  reject: FUNCTION,
}

You need to call resolve, when the user could be verified, or reject if something went wrong.
Whatever you give it as parameter in the userParams.reject-method will be in req.user.profile in later requests

Events

For all auth-medthods, the following events can be listened on:

requestAuthorized

This event gets called, every time a request is about to get authorized. Every listener gets a userParams-Object that looks like this:

{
  request: SOMEREQUEST,
  user: USER\_OBJECT,
  resolve: FUNCTION,
  reject: FUNCTION,
}
  • Only when all listeners have called the resolve-function will the request
    be allowed to the next middleware (the one after the auth.middleware)
  • When any one of the listeners rejects, the whole request will be rejected
    with a 403 - Forbidden
  • Every listener must call resolve or reject (but not both) exactly once!