@infomaker/service-authorization-lib
Version:
IMID Service Authorization Library
168 lines (147 loc) • 5 kB
JavaScript
/* eslint-env node */
'use-strict'
const jwt = require('jsonwebtoken')
/**
* Module with helper functions for the Tokens.
* @module TokenUtils
*/
/**
* Extracts and decodes a service token from a raw request
* @function
* @param {http.IncomingMessage} request
* @returns {Object} serviceToken - The service token
*/
const extractServiceTokenFromRequest = (request) => {
if (request.auth && request.auth.credentials && request.auth.credentials.serviceToken) {
return request.auth.credentials.serviceToken
}
// Get raw request to normalize handling between express and hapi
const rawRequest = (request.raw && request.raw.req) ? request.raw.req : request
let rawServiceToken = null
Object.keys(rawRequest.headers).forEach(header => {
if (header.toLowerCase() === 'authorization') { rawServiceToken = rawRequest.headers[header].replace(/bearer /i, '') }
})
if (rawServiceToken) {
return jwt.decode(rawServiceToken)
}
throw new Error('Service token not present in request')
}
/**
* Extracts IMID token from a raw request if present
* @function
* @param {http.IncomingMessage} request
* @returns {String|null} imidToken - The IMID token if present
*/
const extractImidTokenFromRequest = (request) => {
if (request.auth && request.auth.credentials && request.auth.credentials.imidToken) {
return request.auth.credentials.imidToken
}
// Get raw request to normalize handling between express and hapi
const rawRequest = (request.raw && request.raw.req) ? request.raw.req : request
let imidToken = null
Object.keys(rawRequest.headers).forEach(header => {
if (header.toLowerCase() === 'x-imid-token') { imidToken = rawRequest.headers[header] }
})
return imidToken
}
/**
* Get the subject from the service token
* @function
* @param {http.IncomingMessage} request
* @returns {String} organization - The subject identifier set on the service token
*/
const getSubject = (request) => {
const serviceToken = extractServiceTokenFromRequest(request)
return serviceToken.sub
}
/**
* Get the subject's organization
* @function
* @param {http.IncomingMessage} request
* @returns {String} organization - The organization the subject belongs to
*/
const getOrganization = (request) => {
const serviceToken = extractServiceTokenFromRequest(request)
return serviceToken.org
}
/**
* Get the subject's mapped units
* @function
* @param {http.IncomingMessage} request
* @returns {Array<String>} units - An array of all units the subject belongs to
*/
const getUnits = (request) => {
const serviceToken = extractServiceTokenFromRequest(request)
return Object.keys(serviceToken.permissions.units)
}
/**
* Get the subject's selected unit
* @function
* @param {http.IncomingMessage} request
* @returns {(null|String)} unit - The subject's selected unit, null if no unit selected
*/
const getSelectedUnit = (request) => {
const serviceToken = extractServiceTokenFromRequest(request)
return serviceToken.unit
}
/**
* Get the subject's organization permissions
*
* Organization permissions are located under permissions.org
* @function
* @param {http.IncomingMessage} request
* @returns {Array<String>}} permissions - The subject's org permissions
*/
const getOrgPermissions = (request) => {
const serviceToken = extractServiceTokenFromRequest(request)
return serviceToken.permissions.org
}
/**
* Get the subject's permissions for the specified unit
*
* Unit permissions are located under permissions.units[unit]
* @function
* @param {http.IncomingMessage} request
* @param {String} unit - The unit permissions should be checked in
* @returns {Array<String>} permissions - The subject's permissions for the specified unit
*/
const getUnitPermissions = (request, unit) => {
const serviceToken = extractServiceTokenFromRequest(request)
const unitPermissions = serviceToken.permissions.units[unit]
if (!Array.isArray(unitPermissions)) { return [] }
const permissions = new Set(serviceToken.permissions.org)
unitPermissions.forEach(permission => permissions.add(permission))
return Array.from(permissions)
}
/**
* Checks if a token belogs to an admin for the service
* @function
* @param {http.IncomingMessage} request
* @returns {Boolean} isServiceAdmin - True if the token belongs to an admin for the service
*/
const isServiceAdmin = (request) => {
const serviceToken = extractServiceTokenFromRequest(request)
return serviceToken.service_admin === true
}
/**
* Get the subject's userinfo
* @function
* @param {http.IncomingMessage} request
* @returns {Object} userinfo - The userinfo object set on the subject
*/
const getUserinfo = (request) => {
const serviceToken = extractServiceTokenFromRequest(request)
return serviceToken.userinfo
}
module.exports = {
extractServiceTokenFromRequest,
getSubject,
getOrganization,
getUnits,
getSelectedUnit,
getOrgPermissions,
getUnitPermissions,
isServiceAdmin,
getUserinfo,
extractImidTokenFromRequest
}