
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
Authorization framework for implementing Relation-based Access Control (ReBAC) with the Resolver (Inspired by [GraphQL](https://graphql.org))
Authorization framework for implementing Relation-based Access Control (ReBAC) with the Resolver (Inspired by GraphQL)
ReBAC is a method to check whether the current user has permission to a resource by using information about the relationship between the user and the resource. In order to do this, it is necessary to be able to traverse the relationship information between each resource, which is similar to graph traversal. For more information, see the document.
Once you've completed the setup, checking permissions is very easy. No more cascading if statement.
/**
* Do `req.user` and `page` have a `can_edit` relationship?
*/
const isAuthorized = await check({
user: req.user,
object: page,
relation: "can_edit",
context,
});
if (!isAuthorized) {
throw new Error("You are not authorized");
}
To configure a simple relationship-based authorization procedure like the above, a schema declaration is required first.
/**
* 1. For type autocompletion, you need to pass a type map for the entities currently existing in the system, like this:
*/
type MyTypeMap = {
user: User,
folder: Folder,
page: Page,
}
/**
* 2. And declare what kind of relationships these entities have as follows:
*/
import { parse } from "graplix";
const schema = parse<MyTypeMap>(`
model
schema 1.1
type user
type folder
relations
define owner: [user]
define editor: [user]
define viewer: [user]
type page
relations
define parent: [folder]
define owner: [user]
define editor: [user]
define viewer: [user]
`)
/**
* 3. If there are other relationships that connect the relationship, add them.
*/
export const schema = parse<MyTypeMap>(`
model
schema 1.1
type user
type folder
relations
define owner: [user]
define editor: [user]
define viewer: [user]
define can_view: owner or editor or viewer
define can_edit: owner or editor
define can_delete: owner
type page
relations
define parent: [folder]
define owner: [user]
define editor: [user]
define viewer: [user]
# If you add a "from" clause, graplix will look at the relationship up to the relationship.
# In this case, "page" --parent--> "folder" --owner--> "user"
define can_view: owner or editor or viewer or can_view from parent
define can_edit: owner or editor or can_edit from parent
define can_delete: owner or can_delete from parent
`);
Once the schema declaration is complete, we now need to implement how to actually connect the relationships declared in the schema. The function that finds and returns the next entity that has a relationship is called a "resolver".
import { GraplixResolvers } from "graplix";
/**
* The type for the global Context required for the function to operate. It may include declarations such as DataLoader to prevent N+1 operation, or DB instances.
*/
type MyContext = {
// ...
};
/**
* 1. Implements what relationships each entity has with other entities.
*/
export const resolvers: GraplixResolvers<MyContext, MyTypeMap> = {
user: {
// takes an entity object as an argument and returns entity identifier.
identify: (entity) => entity.id,
},
folder: {
// ...
},
page: {
// ...
relations: {
async parent(entity, context) {
// The Resolver function takes the object and Context as arguments and returns the next object pointed to by the relationship.
return folder;
// If there is no corresponding object, it returns null.
return null;
// If there are multiple corresponding objects, multiple objects are returned.
return [
folder1,
folder2,
folder3,
// ...
]
},
}
},
};
Entities returned from resolvers for type branching must contain a
$typefield.
{
"$type": "user",
// ...
}
Important If multiple small resolvers are executed simultaneously, there is a high possibility that the N+1 problem will occur. This problem can be solved by utilizing DataLoader, a representative library for GraphQL.
check() functionOnce everything is ready, you can create the check() function using graplix()
import { graplix } from "graplix";
import { schema } from "./schema";
import { resolvers } from "./resolvers";
export const { check } = graplix({
schema,
resolvers,
});
Write authorization logic using the check() function in your endpoint.
/**
* Do `req.user` and `page` have a `can_edit` relationship?
*/
const isAuthorized = await check({
user: req.user,
object: page,
relation: "can_edit",
context,
}); // boolean
if (!isAuthorized) {
throw new Error("Not Authorized!");
}
FAQs
Authorization framework for implementing Relation-based Access Control (ReBAC) with the Resolver (Inspired by [GraphQL](https://graphql.org))
The npm package graplix receives a total of 126 weekly downloads. As such, graplix popularity was classified as not popular.
We found that graplix demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.