OpenVeo Core server

API Docs for: 7.0.0
Show:

File: app/server/controllers/OAuthController.js

'use strict';

/**
 * @module core-controllers
 */

var util = require('util');
var openVeoApi = require('@openveo/api');
var pathUtil = process.require('app/server/path.js');
var errors = process.require('app/server/httpErrors.js');
var storage = process.require('app/server/storage.js');
var Controller = openVeoApi.controllers.Controller;

/**
 * Retrieves, from list of scopes, the scope corresponding to the couple url / http method.
 *
 * @method getScopeByUrl
 * @private
 * @static
 * @param {String} url An url
 * @param {String} httpMethod The http method (POST, GET, PUT, DELETE)
 * @return {String} The scope id if found, null otherwise
 */
function getScopeByUrl(url, httpMethod) {
  var scopes = storage.getWebServiceScopes();

  for (var i = 0; i < scopes.length; i++) {
    var scope = scopes[i];

    // Got paths associated to the scope
    if (scope.paths) {

      // Iterate through the list of paths
      for (var j = 0; j < scope.paths.length; j++) {
        var path = scope.paths[j];

        if (pathUtil.validate(httpMethod + ' ' + url, path))
          return scope.id;
      }

    }
  }

  return null;
}

/**
 * Retrieves, recursively, the id of all permissions.
 *
 * @example
 *     var permissions = [
 *       {
 *         label: 'Permissions group',
 *         permissions: [
 *           {
 *             id: 'perm-1',
 *             name: 'Name of the first permission',
 *             description: 'Description of the first permission',
 *             paths: [ 'get /path1' ]
 *           }
 *         ]
 *       },
 *       {
 *         id: 'perm-2',
 *         name: 'Name of the second permission',
 *         description: 'Description of the second permission',
 *         paths: [ 'get /path2' ]
 *       }
 *     ];
 *     getPermissionIds(permissions); // ["perm-1", "perm-2"]
 *
 * @method getPermissionIds
 * @private
 * @static
 * @param {Array} permissions The list of permissions to search in
 * @return {Array} The list of permission ids
 */
function getPermissionIds(permissions) {
  var permissionsList = [];
  for (var i = 0; i < permissions.length; i++) {

    if (permissions[i].id) {

      // Single permission
      permissionsList.push(permissions[i].id);

    } else if (permissions[i].label) {

      // Group of permissions
      var permissionIds = getPermissionIds(permissions[i].permissions);

      if (permissionIds && permissionIds.length > 0)
        permissionsList = permissionsList.concat(permissionIds);
    }
  }

  return permissionsList;
}

/**
 * Defines a controller to handle requests relative to Web Service authentication.
 *
 * @class OauthController
 * @extends Controller
 * @constructor
 */
function OauthController() {
  OauthController.super_.call(this);
}

module.exports = OauthController;
util.inherits(OauthController, Controller);

/**
 * Validates scopes for the given token depending on requested url.
 *
 * Revoke access to the service if client does not have permission.
 *
 * @method validateScopesAction
 * @param {Request} request ExpressJS HTTP Request
 * @param {Object} request.oauth2 Request's OAuth information
 * @param {Object} request.oauth2.accessToken The connected client's token
 * @param {String} request.url The request's url
 * @param {String} request.method The request's method
 * @param {Response} response ExpressJS HTTP Response
 * @param {Function} next Function to defer execution to the next registered middleware
 */
OauthController.prototype.validateScopesAction = function(request, response, next) {

  // An access token has been delivered to this client
  if (request.oauth2.accessToken) {

    // Checks if the client has access to the given api by looking
    // at scopes
    var scope = getScopeByUrl(request.url, request.method);

    if (scope && request.oauth2.accessToken.scopes.indexOf(scope) > -1) {

      // Access granted

      // OpenVeo and plugins may define two kinds of permissions:
      // - scope permissions for the Web Service
      // - internal permissions
      // OAuth authentication validates requests based on URLs using scope permissions but it doesn't validate the
      // internal permissions. As Core and plugins may validate internal permissions based on authenticated user
      // permissions, a user has to be created for an authenticated Web Service client. This user has full
      // privileges on internal permissions.
      request.user = {
        id: request.oauth2.accessToken.clientId,
        permissions: getPermissionIds(storage.getPermissions()),
        type: 'oAuthClient'
      };

      next();
    } else {

      // Access refused
      process.logger.warn(
        'Access refused for client ' + request.oauth2.accessToken.clientId + ' for path ' + request.url +
        ' with method ' + request.method);
      next(errors.WS_FORBIDDEN);

    }

  } else {
    next(errors.WS_UNAUTHORIZED);
  }
};