Reference Source

js/security/authentication_wrapper.js

// NPM IMPORTS
import assert from 'assert'

// COMMON IMPORTS
import T            from 'devapt-core-common/dist/js/utils/types'
import Settingsable from 'devapt-core-common/dist/js/base/settingsable'

// SERVER IMPORTS
import runtime from '../base/runtime'


let context = 'server/security/authentication_wrapper'



/**
 * @file Authentication wrapper class to interact with authentication plugins.
 * @author Luc BORIES
 * @license Apache-2.0
 */
export default class AuthenticationWrapper extends Settingsable
{
	/**
	 * Create an Authentication wrapper class to interact with authentication plugins.
	 * @extends Settingsable
	 * 
	 * @param {string|undefined} arg_log_context - optional.
	 * @param {LoggerManager} arg_logger_manager - logger manager instance.
	 * 
	 * @returns {nothing}
	 */
	constructor(arg_log_context=context, arg_logger_manager)
	{
		super(undefined, arg_log_context, arg_logger_manager)
		
		this.is_authentication_wrapper = true
		this.authentication_is_enabled = true
		this.authentication_plugins = []
	}
	
	
	
	/**
	 * Load security settings.
	 * 
	 * @param {object} arg_settings - authentication settings (Immutable object).
	 * 
	 * @returns {nothing}
	 */
	load(arg_settings)
	{
		// console.log(arg_settings, context + ':load:arg_settings')
		
		const self = this
		assert(T.isObject(arg_settings), context + ':bad settings object')
		assert(T.isFunction(arg_settings.has), context + ':bad settings immutable')
		assert(arg_settings.has('enabled'), context + ':bad settings.enabled')
		assert(arg_settings.has('plugins'), context + ':bad settings.plugins')
		
		const auth_mgr = runtime.security().get_authentication_manager()
		
		
		// LOAD AUTHENTICATION SETTINGS
		this.authentication_is_enabled = arg_settings.get('enabled')
		this.authentication_plugins = []
		const plugins = arg_settings.get('plugins')
		
		// SEARCH PLUGINS
		plugins.forEach(
			(plugin_name) => {
				const plugin = auth_mgr.registered_plugins.find_by_name(plugin_name)
				if ( T.isObject(plugin) && plugin.is_authentication_plugin )
				{
					self.authentication_plugins.push(plugin)
					return
				}
				self.info('plugin not found for name [' + plugin_name + ']')
			}
		)
	}
	
	
	
	/**
	 * Apply all plugins authentication middleware on a Server instance.
	 * 
	 * @param {Server} arg_server - server instance.
	 * 
	 * @returns {boolean}
	 */
	apply_middlewares(arg_server)
	{
		this.enter_group('apply_middlewares')
		// assert( T.isObject(arg_server) && T.isObject(arg_server.server), context + ':apply_middlewares:bad arg_server.server object')
		// assert( T.isFunction(arg_server.server.use), context + ':apply_middlewares:bad arg_server.server.user function')
		
		// DEBUG
		// debugger
		// console.log(context + ':apply_middlewares')

		// CHECK SERVER
		if (! arg_server || ! arg_server.server || ! T.isFunction(arg_server.server.use) )
		{
			this.leave_group('apply_middlewares:bad server')
			return false
		}
		
		const plugins = this.authentication_plugins
		const auth_mgr = runtime.security().get_authentication_manager()
		
		// LAST MIDDLEWARE
		const last_mw = (req, res, next) => {
			// AUTHENTICATION IS VALID
			if ( ! this.authentication_is_enabled || auth_mgr.check_request_authentication(req) )
			{
				// console.log('apply_middlewares:last_mw:auth success')
				next()
				return
			}
			
			// SEND ERROR OUTPUT
			res.status(401)
			res.contentType = 'json'
			res.send({ message: 'Authentication failure' })
			
			// console.log('apply_middlewares:last_mw:auth failure', req.originalUrl)
			next('Authentication failure')
		}
		
		
		// LOOP ON PLUGINS
		const should_send_error_on_failure = false
		for(let plugin of plugins)
		{
			if ( T.isFunction(plugin.create_middleware) )
			{
				// self.debug('apply_middlewares:get_mw:call plugin.create_middleware()')
				// console.log(context + ':apply_middlewares:loop on plugin:' + plugin.get_name())
				
				const mw = plugin.create_middleware(should_send_error_on_failure)
				arg_server.server.use(mw)
			}
		}
		
		// ADD LAST MIDDLEWARE
		arg_server.server.use(last_mw)
		
		this.leave_group('apply_middlewares')
		return true
	}
}