Security News
GitHub Removes Malicious Pull Requests Targeting Open Source Repositories
GitHub removed 27 malicious pull requests attempting to inject harmful code across multiple open source repositories, in another round of low-effort attacks.
@entur-partner/permission-client-node
Advanced tools
Permission Client is a Javascript module for Node and is an SDK for Entur Permission Store providing local cache of user permissions. A similar SDK also exists for Java called Permission Client for Java.
Using Permission Client will help you satisfy Enturs Application Security Requirements related to Authorisation. If you have any questions about how to use Permission Store please use the Slack channel #work-tilgangstyring.
Other more general questions related to authentication and/or authorization can be directed to #talk-sikkerhet.
Requirement | Functionality | Comment |
---|---|---|
ES2020 | All |
Requirement | Functionality | Comment |
---|---|---|
typescript | All | |
@stomp/stompjs + websocket | In Memory Cache | Used to save network traffic and faster refresh rates. |
In this getting started guide we will describe how to set up a Node application with authorisation delivered by Permission Client for Node.
Links to other frameworks and services that are mentioned/relevant for this guide:
Permission Client for Node is provided as a standalone javascript module, but in this getting started guide we will be using it along with the Express framework.
Verify your Express setup:
yarn add @entur-partner/permission-client-node
In this chapter we will show how to use Permission Client to secure a REST endpoint.
Permissions for the application will be defined in typescript to be used in Setup Permission Client for Node chapter.
Permissions defined by applications must be in line with the guidelines described in Confluence here.
Here is an example file myPermissions.ts:
import { ApplicationPermission, BusinessCapability } from '@entur-partner/permission-client-node'
export const APPLICATION_PERMISSIONS : ApplicationPermission[] = [];
// Define Business Capabilities
export const OPERATION1_CREATE : BusinessCapability = {operation: 'operation1', access: 'OPPRETT'};
APPLICATION_PERMISSIONS.push(OPERATION1_CREATE);
export const OPERATION1_READ : BusinessCapability = {operation: 'operation1', access: 'LES'};
APPLICATION_PERMISSIONS.push(OPERATION1_READ);
// Define Responsibility Sets
export const OPERATION2_READ : ApplicationPermission = {operation: 'operation2', access: 'LES', responsibilityType: 'name1.attributt1'};
APPLICATION_PERMISSIONS.push(OPERATION2_READ);
Setup of Permission Client in your Node application involves initialisation of TokenFactory and AuthorizeCache. Here is an example:
import { TokenOptions, TokenFactory } from '@entur-partner/permission-client-node'
import { AuthorizeCacheType, Application, PermissionDeliverRepository } from '@entur-partner/permission-client-node'
import PermissionClient from '@entur-partner/permission-client-node'
import { APPLICATION_PERMISSIONS } from './myPermissions'
// Define values for Auth0 internal client to be used when calling Permission Store
const clientTokenOptions : TokenOptions = {
domain: 'internal.dev.entur.org', // Changes to match environment.
clientId: '<MNG_AUTH0_INT_CLIENT_ID>', // Client ID from Google Secret Manager.
clientSecret: '<MNG_AUTH0_INT_CLIENT_SECRET>', // Client secret from Google Secret Manager.
audience: 'https://api.dev.entur.io', // Changes to match environment.
refreshBeforeMinValidSeconds: 600 // Refresh token when valid to is less than 10 minutter.
}
const application : Application = {
name : 'MyApplication', // Name of this application.
refreshRate : 300 // Refresh rate in seconds for in memory cache.
}
let permissionClient: AuthorizeCache;
const initPermissionClient = async () => {
try {
// TokenFactory will be used to get access tokens from Auth0
const accessTokenFactory = new TokenFactory(clientTokenOptions);
const permissionStoreUrl = new URL('permission-store URL'); // for local development: https://api.dev.entur.io/permission-store/v1
const repository = new PermissionDeliverRepository(application, accessTokenFactory, permissionStoreUrl);
permissionClient = await PermissionClient(AuthorizeCacheType.IN_MEMORY, APPLICATION_PERMISSIONS, repository);
// Optional to use WebSocket when running in Google Kubernetes Engine (GKE)
// const permissionClient = await PermissionClient(AuthorizeCacheType.IN_MEMORY, APPLICATION_PERMISSIONS, repository, { communicationType: CommunicationType.SocketJS });
permissionClient.setScheduleErrorHandler((error) => {
logger.warning('PermissionClient scheduler failed', error);
});
logger.info('PermissionClient initialized');
} catch (error) {
logger.error('Failed to initialize PermissionClient', error);
throw Error('Failed to initialize PermissionClient. Please make sure permission store cache configurations are correct and try again.');
}
};
export { initPermissionClient, permissionClient };
Defining and implementing permissions checks in the application is a central part of using Permission Client. Permission Client supports two types of permissions:
Business Capability Permissions is typically used for securing REST endpoints. And Responsibility Permissions is a good candidate when you want you securely share data between partners.
Permissions can be:
Business capability is a right typically used to control access to endpoints.
Business Capability are defined in code and used when creating PermissionClient. Example:
export const OPERATION_CREATE : BusinessCapability = {operation: 'operation', access: 'OPPRETT'};
Responsibility Set is a right designed to control access to data through permissions and agreements. This permission works similar to Business Capability, but in addition an agreement must be registered that the users organisation is allowed to access target data element.
Responsibility Sets are defined in code and used when creating PermissionClient. Example:
export const OPERATION_READ : ApplicationPermission = {operation: 'operation', access: 'LES', responsibilityType: 'name.attributt'};
Agreements are used in tandem with responsibility sets to restrict access to data based on which organisation the user/client belongs to. I.e. an agreement is used to describe the relationship between an organisation and some data element.
An application using Responsibility Sets will also normally maintain Agreements in its UI or delegates this to a related UI.
Note: Agreements can only be changed by the same application that created it.
To administrate agreements using Permission Client, applications can use the following methods on PermissionDeliverRepository:
An Agreement is defined from:
Permission Client for Node only supports one cache type: IN_MEMORY cache.
Cache type IN-MEMORY is for production.
Optional: Push notifications
When the application is running in one of the internal GKE environments (dev, tst/staging, prd), you can tell Permission Client to use Permission Store push notifications through websockets, rather than polling the Store directly at a regular interval. To do this, add websocket dependencies:
yarn add @stomp/stompjs websocket
In addition, the following code needs to be run when starting the service:
Object.assign(global, { WebSocket: require('websocket').w3cwebsocket });
And when you create PermissionClient pass the parameter typescript{ communicationType: CommunicationType.SocketJS }
const permissionClient = await PermissionClient(AuthorizeCacheType.IN_MEMORY, APPLICATION_PERMISSIONS, repository, { communicationType: CommunicationType.SocketJS });
LOCAL_TEST_CACHE is a cache type for running automatic tests. LOCAL_TEST_CACHE is not implemented for Permission Client for Node. It's expected that mock functionality in Jest will be used in automatic tests.
Starting from version 3.0.0 of Permission Client, each instance of your running service will receive a unique instance ID. This ID is used to track the permissions required by your service, allowing Permission Store to calculate the total permission requirements for your application.
When introducing new permissions, it's sometimes necessary to add them to application.yaml before using them in your code. This ensures that role management can be performed before the corresponding restrictions are enforced during code execution.
Clone module from GitHub with:
git clone https://github.com/entur/permission-client.git
Install dependencies:
yarn install
Run Jest tests:
yarn test
Create a NPM user account on https://www.npmjs.com/signup. Send your user to tech-lead in Entur Partner and ask to be added to Entur Partner organisation.
Upgrade version with:
yarn version [--major | --minor | --patch]
Publishing with:
yarn publish
FAQs
Node client library for Permission Store
The npm package @entur-partner/permission-client-node receives a total of 271 weekly downloads. As such, @entur-partner/permission-client-node popularity was classified as not popular.
We found that @entur-partner/permission-client-node demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 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
GitHub removed 27 malicious pull requests attempting to inject harmful code across multiple open source repositories, in another round of low-effort attacks.
Security News
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.
Security News
Node.js will be enforcing stricter semver-major PR policies a month before major releases to enhance stability and ensure reliable release candidates.