http-permission-injection
v1.1.6
Published
Inject and verify a users permissions coming form an http request, using local or remote resources for verification.
Downloads
19
Maintainers
Readme
Introduction
This module is intended to provide a role based access architecture for back-end http services. A username and user permissions object can be passed to the module, and it will inject an encrypted account permission cookie in the http client.
- The username can be passed either directly throught the backed function or via and encrypted http cookie.
- Account permissions can be set via a module variable or fetched from a remote API secured by a "Beared token" header.
Changelog
v 1.1.6
- Changed Access denied return code from 401 to 302.
v 1.1.5
- Minor bug fix.
v 1.1.3
- Allow cookie prefix to be passed to set/get event, allowing multiple permissions to be handled.
Requirements
The only pre-requirement that is separate to the module itself is, it you choose to use a cookie to pass the username of the account that requires authorization, this needs to be sent in the http request.
- auth_username cookie: The perfix can be set using the cookie_prefix variable of the module, but a default value will already be set to "auth_" meaning the default name for the username cookie will be "auth_username". This is only required if using a session cookie to retreive the username to be authorised, otherwise the module will expect a username to be passed when calling
injectPermissions()
.
Module Setup
Below is a list of variables that can be used to set-up the module. Please ensure you read them carefuly and perform the setup before invoking any of the module functions.
- is_source_remote:
- Description: Boolean variable, sets if a remote API should be used to fetch the user permission list.
- Default:
false
- Options:
true
,false
- Required:
no
- remote_token:
- Description: If the "is_source_remote" value is set to
true
, use this token to pass theBearer Token
header to the remote API. - Default:
changeme
- Options:
any string containing a token for your remote api
- Required:
yes, if is_source_remote is set to true
- Description: If the "is_source_remote" value is set to
- remote_endpoint:
- Description: The URL of the remote API used to pull the user permission object.
- Default:
http://localhost/get_user_permissions
- Options:
any valid url
- Required:
yes, if is_source_remote is set to true
- user_data:
- Description: A JSON object containing the relevant user permissions, the format will be detailed later.
- Default:
null
- Options:
check the dedicated section to see the structure, must be a JSON object
- Required:
yes
- use_global_user_data:
- Description: Boolean variable that sets wether a user_data valriable will be passed during injection or if the global variable is to be used. Useful if you are grabbing new data on the fly.
- Default:
true
- Options:
true, false
- Required:
no
- cookie_encryption_key:
- Description: Encryption key used to encrypt & decrypt cookies.
- Default:
changeme
- Options:
any valid string, it's recommended that this is as complex as possible to improve security
- Required:
yes
- cookie_expiry_minutes:
- Description: A integer value, used to set the expiry time in minutes of the authorization cookie.
- Default:
60
- Options:
any integer > 0
- Required:
no
- cookie_prefix:
- Description: A prefix for input / output cookie naming.
- Default:
auth_
- Options:
any valid string,
- Required:
no
- use_global_cookie_prefix:
- Description: Boolean the allow you to either set a global cookie prefix or user a per-event cookie prefix. This can be useful if you need to handle multiple permission sets.
- Default:
true
- Options:
true, false
- Required:
no
- user_secure_username_cookie:
- Description: Boolean to be used to choose if username for the session is passed directly or should be pulled from an encrypted username cookie.
- Default:
false
- Options:
true
,false
- Required:
no
- cookie_path:
- Description: Path validity for the cookie, by default it will be valid across all the site.
- Default:
/
- Options:
any valid url path
- Required:
no
Module Functions
Below is a list of functions that are exposed by the module and represent it's core functionality.
fetchRemoteUsers(callback
):
This function is to be used in the event that permissions are fetched from a remote resource and not stored locally.
- Inputs: callback, a function to execute when the action is completed, the permission object will be passed to this function.
- Outputs: The JSON permission object returned and parsed from the API response.
injectPermissions(event
):
This is the core function of the module, it is used to, given a username, get user permissions and redirect to a success or fail page provided in the inputs.
- Inputs: event, this object must contain the following variables:
- request: The source http request.
- response: The source http response.
- success_url: A string containing a url to be redirected to if the operation is succesful.
- denied_url: A string containing a url to be redirected to if the operation fails.
- Outputs: no outputs are generated as a result to this function, either of the URLs speified in the input object will be called, according to the result of the operation; if the user is found, the permissions cookie will be sent to the remote client and stored for future use, otherwise, the client will be sent a redirect to the failure page if the account being verified does not exist.
getPermissions(event
):
This function fetches and decrypts user permissions, allowing for role base access logic to be performed elswhere in the application. The permissions are then passed to a callback function specified, as a JSON object.
- Inputs: event, containing the following:
- request: The source http request.
- callback: Callback function to execute and send the permission data to.
- Outputs: permissions, a JSON object containing the account permissions, decrypted from the cookie sent by the remote client.
Permission Object Structure
Below is an example of the user permission object. The only constraints required by the application is that each object within the array contains the "username" variable, that is then used to match with the username provided when creating the permissions cookie.
Any other structure is free to be customised and, one account object will be stored in the secure cookie and only if there is a match, when the getPermissions()
function is called, the signle object will be returned to the callback function specified.
[
{
"username":"test.user.1",
"other_details": "This could be anything, even what the person likes to have for lunch.",
"permissions": [
"read",
"write"
]
},
{
"username":"test.user.2",
"some_other_detail":"In this case, this is all that's here!"
}
]
Examples
Local Permission Data
Below is an example that uses a local object for permissions.
// Modules used for the example.
var http = require('http');
var url = require('url');
//Import the module.
const http_auth = require('http-permission-injection');
// Demo user object.
http_auth.user_data = [
{
"username":"test.user.1",
"other_details": "This could be anything, even what the person likes to have for lunch.",
"permissions": [
"read"
],
"superuser": false
},
{
"username":"test.user.2",
"some_other_detail":"In this case, this is all that's here!",
"superuser": true
}
]
http_auth.cookie_encryption_key = "UwwkFapH9wCZNnQRRybgPg427u2VZRS9sCvaLGArRzrp5md6sTMtDcVQTKuDJ7S6Ftp5N7XMnEAKfxa5tLmFrVzEgw3Yh25EebbeSV2DWmqT6yxkM7UWYDsCmZsxmZUT";
http_auth.cookie_expiry_minutes = 5;
var server = http.createServer(function(request, response) {
var pathName = url.parse(request.url).pathname;
var url_path = pathName.replace(/\/$/, "");
switch (url_path){
// Perform authorization.
case "/auth":
http_auth.injectPermissions({
request: request,
response: response,
success_url: "/success",
denied_url: "/denied",
username: "test.user.1"
});
break;
// Return auth data if it's a success.
case "/success":
console.log("Permission Success.");
http_auth.getPermissions({
request: request,
callback: function(permissions){
console.log("Permissions:" + JSON.stringify(permissions));
response.writeHeader(200, {"Content-Type": "text/plain"});
response.write(JSON.stringify(permissions));
response.end();
}
});
break;
case "/denied":
console.log("Permission Denied.");
response.writeHeader(200, {"Content-Type": "text/plain"});
response.write(JSON.stringify(permissions));
response.end();
break;
}
});
var port = process.env.PORT || 8080;
server.listen(port);
Remote Permission Data
Below is an example that uses a local remote api to fetch the permissions object used to perform the verification. Because the process is very similar to the above example, I will only provide the differences in the below code snippet:
http_auth.is_source_remote = true;
http_auth.remote_token = "7XMnEAKfxa5tLmFrVzEg";
http_auth.remote_endpoint = "https://some-url-to-api/get_users";
http_auth.fetchRemoteUsers(function(permission){
http_auth.user_data = permission;
});
The essential difference is that we call fetchRemoteUsers()
before performing other actions, that way we can reteive a list of current permissions. This call can be repeated at any point to refresh the list.