Gathering detailed insights and metrics for visa-js
Gathering detailed insights and metrics for visa-js
Gathering detailed insights and metrics for visa-js
Gathering detailed insights and metrics for visa-js
react-fancy-visa-card
React js implementation for visa credit card - Payment Form
@visa/nova-react
Visa Product Design System Nova React library
@illgrenoble/visa-print-client
[](https://badge.fury.io/js/%40illgrenoble%2Fvisa-print-client)
@illgrenoble/visa-guacamole-common-js
Guacamole Common JS, used by the VISA platform, as an NPM module
Simple and flexible Access Control Manager that works well with Express and Passport or independently.
npm install visa-js
Typescript
Module System
Node Version
NPM Version
JavaScript (100%)
Total Downloads
0
Last Day
0
Last Week
0
Last Month
0
Last Year
0
23 Stars
106 Commits
3 Forks
3 Watchers
5 Branches
2 Contributors
Updated on Jul 05, 2025
Latest Version
1.0.25
Package Id
visa-js@1.0.25
Unpacked Size
28.37 kB
Size
8.07 kB
File Count
9
NPM Version
10.9.2
Node Version
22.14.0
Published on
Apr 15, 2025
Cumulative downloads
Total Downloads
Last Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year
1
Simple and flexible Access Control Manager based on Attribute Based Access Control (ABAC) paradigm that works well with Express and Passport or independently.
Get a travel Visa, take your Passport and grab next Express train.
npm install visa-js -S
1const visa = require("visa-js"); 2 3visa.policy({ 4 objects: { 5 account: { 6 mapRefsToObjects: (refs) => Account.find({ _id: { $in: refs } }), 7 operations: { 8 open: (subject) => subject.role == "teller", 9 read: (subject, account) => account && subject.id === account.ownerId, 10 }, 11 }, 12 }, 13}); 14 15app.post( 16 "/api/account", 17 passport.authenticate("local"), 18 visa.authorize(visa.user.can.open.account), 19 (req, res) => { 20 // authorized to open account 21 } 22); 23 24app.get( 25 "/api/account/:id", 26 passport.authenticate("local"), 27 visa.authorize(visa.user.can.read.account), 28 (req, res) => { 29 // authorized to read specific account 30 } 31);
When talking about WEB app security, Node.js has great Passport module that takes care of user authentication - process of actually confirming user identity. It is simple and flexible and already supports multiple strategies. In case strategy is missing it is easy to add one.
Visa.js tries to follow same principles for another security aspect - authorization - process to actually confirming identified user has access rights to resources provided by WEB app. Visa.js implements Attribute Based Access Control (ABAC) paradigm that is a flexible way to control access based on policies. Policy is a set of rules that evaluate attributes of identified user (subject), accessed resource (object) and environment (context) to grant/deny access. There are few initiatives such as node-abac or abac, however, they only cover some very specific cases.
Role Based Access Control (RBAC) is another popular paradigm. There are popular Node.js modules based on RBAC such as acl or accesscontrol. However, RBAC is user-centric and do not take into account additional parameters such as resource information, relationship between the user (the requesting entity) and the resource, and dynamic information e.g. time of the day or user IP. RBAC is in some ways special case of ABAC in terms of the attributes used. RBAC works on the attribute of “role”. The key difference with ABAC is the concept of policies that express a complex Boolean rule set that can evaluate many different attributes.
A human user or non-person entity (NPE), such as other systems or bots. Assume that subject and user are synonymous.
A system resource for which access is managed, such as files, API endpoints or processes.
The execution of a function at the request of a subject upon an object, such as read, write, edit, delete, copy, execute, or modify.
Operational or situational context in which access requests occur. Environment characteristics are independent of subject or object, and may include the current time, day of the week, location of a user, or the current threat level.
Policy is the representation of rules or relationships that makes it possible to determine if a requested access should be allowed, given the values of the attributes of the subject, object, and possibly environment conditions.
Assembles authorization information, which may include information about the object being protected, the subject requesting access, the policies governing access to the resource, and any contextual information needed to make a decision regarding access.
Use visa.policy()
function to define policies (function can be called multiple times for multiple policies):
1visa.policy({ 2 objects: { 3 'object1': { 4 mapRefsToObjects: refs => // resolve object references to objects 5 operations: { 6 'operation1': (subject, object, context) => // rule 7 'operation2': (subject, object, context) => // rule 8 } 9 }, 10 'object2': { 11 // mapping and operations 12 } 13 } 14});
true
in case permission is granted and false
in case denied (Promise
, callback and sync return are supported).mapRefsToObjects
is a function that receives an array of references to objects and returns an array of objects (Promise
, callback and sync return are supported). Each object should contain attributes (properties) required to evaluate rules. The function is called when access to object by reference is checked.Use visa.check()
function to check permission. The outcome is a Promise
that is resolved if access is granted and rejected with visa.Unauthorized
error if access is denied.
Check for subject
permission to perform operation1
on any instance of object1
:
1visa.check(subject).can.operation1.object1();
Check for subject
permission to perform operation1
on specific object1
:
1visa.check(subject).can.operation1.object1({object: object1);
Check for subject
permission to perform operation1
on specific instances of object1
:
1visa.check(subject).can.operation1.object1({objects: [object1_1, object1_2]);
Check for subject
permission to perform operation1
on specific object1
with reference 1
(to resolve reference to object mapRefsToObjects
function must be defined for object1
in policy):
1visa.check(subject).can.operation1.object1({ ref: 1 });
Check for subject
permission to perform operation1
on specific instances of object1
with references 1
and 2
(to resolve references to objects mapRefsToObjects
function must be defined for object1
in policy):
1visa.check(subject).can.operation1.object1({ refs: [1, 2] });
Context can optionally be passed in case it is required to evaluate policy rules. For instance, Express req
object is passed as context:
1visa.check(subject).can.operation1.object1({ context: req });
Use visa.ask()
function to ask if user has permission. The outcome is a Promise
that is resolved to true
if access is granted, false
if access is denied.
visa.ask()
function follows the same structure as visa.check()
function. For example, ask subject
if he has permission to perform operation1
on any instance of object1
:
1visa.ask(subject).can.operation1.object1();
Use can.not
structure in visa.check()
or visa.ask()
function to check/ask if user does NOT have permission:
1visa.check(subject).can.not.operation1.object1();
1visa.ask(subject).can.not.operation1.object1();
Use visa.authorize()
as an Express middleware. Middleware use subject as req.user
property, therefore, passport.authenticate()
middleware should be used before visa.authorize()
:
1app.get( 2 "/api/object", 3 passport.authenticate(/* strategy and options */), 4 visa.authorize(visa.user.can.operation1.object1), 5 (req, res) => { 6 // authorized to perform operation1 on any object1 7 } 8);
visa.authorize()
function takes permission check as an argument that starts with visa.user
and follows the same structure as visa.check()
function.req
object is passed to policy rule as context
argument.visa.authorize()
middleware also use req.params.id
Express parameter if present to validate rule against object referenced by req.params.id
:
1app.get( 2 "/api/object/:id", 3 passport.authenticate(/* strategy and options */), 4 visa.authorize(visa.user.can.operation1.object1), 5 (req, res) => { 6 // authorized to perform operation1 on specific object1 referenced by :id 7 } 8);
req.params.id
is passed as refs
array item to mapRefsToObjects
function defined in policy for object
.req
object is passed to policy rule as context
argument.visa.authorize()
middleware also accepts second argument as function that gets Express req
object as argument and should return reference to object:
1app.get( 2 "/api/object/:objectId", 3 passport.authenticate(/* strategy and options */), 4 visa.authorize( 5 visa.user.can.operation1.object1, 6 (req) => req.params.objectId 7 ), 8 (req, res) => { 9 // authorized to perform operation1 on specific object1 referenced by :objectId parameter 10 } 11);
req.params.objectId
is passed as refs
array item to mapRefsToObjects
function defined in policy for object
.req
object is passed to policy rule as context
argument.Use visa.unauthorizedErrorHandler
middleware to handle visa.Unauthorized
error and to return HTTP status 401:
1app.use(visa.unauthorizedErrorHandler); // client receives HTTP status 401 in case access is denied
visa.unauthorizedErrorHandler
usage is declared AFTER all the routes where authorization is used.Let's define policy for sample bank app.
1visa.policy({ 2 objects: { 3 account: { 4 mapRefsToObjects: (refs) => Account.find({ _id: { $in: refs } }), 5 operations: { 6 open: (user) => user.role == "teller", 7 read: (user, account) => account && user.id === account.ownerId, 8 }, 9 }, 10 transaction: { 11 mapRefsToObjects: (refs) => Transaction.find({ _id: { $in: refs } }), 12 operations: { 13 create: async (user, _, req) => { 14 if (user.role === "manager") { 15 return true; 16 } 17 const fromAccount = Account.find({ _id: req.body.fromAccountId }); 18 return fromAccount.ownerId === user.id; 19 }, 20 revert: (user, transaction, req) => 21 user.role === "cfo" && 22 transaction.date > moment().subtract(1, "day") && 23 req.ip === "10.0.0.99", 24 }, 25 }, 26 }, 27});
account
can only be open
ed by teller
account
can only be read
by ownertransaction
can only be create
d by manager
OR by owner of account money are transferred fromtransaction
that was created less than 1 day ago can only be revert
ed by CFO from specific machineLet's secure the sample bank app API:
1app.post( 2 '/api/account', 3 passport.authenticate('test', { session: false }), 4 visa.authorize(visa.user.can.open.account), 5 (req, res) => // authorized to open account 6); 7app.get( 8 '/api/account/:id', 9 passport.authenticate('test', { session: false }), 10 visa.authorize(visa.user.can.read.account), 11 (req, res) => // authorized to read account referenced by :id parameter 12); 13app.post( 14 '/api/transaction', 15 passport.authenticate('test', { session: false }), 16 visa.authorize(visa.user.can.create.transaction), 17 (req, res) => // authorized to create transaction 18); 19app.delete( 20 '/api/transaction/:id', 21 passport.authenticate('test', { session: false }), 22 visa.authorize(visa.user.can.revert.transaction), 23 (req, res) => // authorized to revert transaction referenced by :id parameter 24);
Let's check for permissions somewhere in the code of app:
1visa.check(req.user).can.open.account() 2 .then(() => { 3 /* authorized to open account */ 4 }) 5 .catch(error => { 6 if (error instanceof visa.Unauthorized) { 7 /* unauthorized to open account */ 8 } else { 9 /* handle error */ 10 } 11 };
1await visa.check(req.user).can.read.account({ ref: req.params.id });
1await visa.check(req.user).can.create.transaction({ context: req });
1await visa.check(req.user).can.revert.transaction({ 2 ref: req.params.id, 3 context: req, 4});
Let's ask if user has permissions somewhere in the code of app:
1visa.ask(req.user).can.open.account() 2 .then(answer => { 3 if (answer) { 4 /* authorized to open account */ 5 } else { 6 /* unauthorized to open account */ 7 } 8 }) 9 .catch(error => { 10 /* handle error */ 11 };
1const answer = await visa 2 .ask(req.user) 3 .can.read.account({ ref: req.params.id });
1const answer = await visa 2 .ask(req.user) 3 .can.create.transaction({ context: req });
1const answer = await visa.ask(req.user).can.revert.transaction({ 2 ref: req.params.id, 3 context: req, 4});
Please note that in order to avoid unhandled promise rejection error in Express routes when using visa.check()
function, it is recommended to use middleware such as express-async-errors to support Promise
.
visa.js by default use single global Access Control Mechanism (ACM). In some cases multiple ACMs within same application might be useful. Use visa.buildACM()
function to build new ACM. ACM instance returned by the function has same functions as visa
module, except for: visa.authorize()
, visa.reset()
, visa.Unauthorized
and visa.unauthorizedErrorHandler
(these are not coupled with specific ACM instance).
No vulnerabilities found.
Reason
no dangerous workflow patterns detected
Reason
no binaries found in the repo
Reason
4 existing vulnerabilities detected
Details
Reason
dependency not pinned by hash detected -- score normalized to 3
Details
Reason
3 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 2
Reason
Found 1/26 approved changesets -- score normalized to 0
Reason
detected GitHub workflow tokens with excessive permissions
Details
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
security policy file not detected
Details
Reason
project is not fuzzed
Details
Reason
license file not detected
Details
Reason
branch protection not enabled on development/release branches
Details
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
Score
Last Scanned on 2025-07-07
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More