节点权限客户端
权限客户端是用于节点.js的JavaScript模块,用作Entur的SDK 权限存储。 。 。 . 它为用户权限提供了本地缓存,改善了性能并减少了后端的负载.
Java 也有类似的 SDK : 权限客户端 为爪哇.
使用权限客户端帮助您遵守 Entur 的应用程序安全要求.
关于使用权限存储的问题, 请加入 Slack 频道 # 工作刺激 #。 。 。 . 一般性认证或授权讨论,访问 {\fn方正黑体简体\fs18\b1\bord1\shad1\3ch2f2f2f}(英语:。 。 。 .
所需资源
最低要求
| 所需经费 | 职能 | 注释 |
|---|---|---|
| ES2020 (英语) | 全体 | |
| 节点21 | 允许交付仓库 |
可选要求
| 所需经费 | 职能 | 注释 |
|---|---|---|
| 类型标记 | 全体 | |
| @stomp/stompjs + websocket (英语) | 内存缓存 | 用于节省网络流量和更快的刷新率. |
开始
在此开始的指南中,我们将描述如何在节点许可客户端的授权下建立节点应用程序.
与本指南提及/相关的其他框架和服务的联系:
设置
节点授权客户端是一个独立的JavaScript模块,用于授权.
在使用前,确保:
- 您的应用程序正在运行 .
- 您的应用程序验证 JWTs :
- 对于快递,您可以使用诸如 快捷键, (中文(简体) ), 特快- oauth2- jwt 携带器 或你选择的另一包.
- 或者用手动验证 JWTs jwks - rsa (英语) 财务报告和审定财务报表 jsonwebt 键。 。 。 .
- 您的应用程序有内部/ 合作伙伴 Auth0 M2M( 机器对机器) 客户端 . 内部客户端可按《DevOps手册》所述提供 如何实施认证。 。 。 .
- 您已经建立了测试框架, 例如 欢乐安全测试.
[大 权限 存储不验证 JWTs 。 为确保安全服务,您的应用程序必须处理JWT验证.
添加权限客户端软件包
yarn add @entur-partner/permission-client-node
定义权限
应用程序权限将在 TypeScript 中定义, 并在此使用 开始 节.
应用程序定义的权限必须遵循 Congress 中概述的准则 这里。 。 。 .
示例 myPermissions.ts (英语)
以下示例定义了应用程序中使用的应用程序权限:
import { ApplicationPermission, BusinessCapability } from '@entur-partner/permission-client-node'
export const APPLICATION_PERMISSIONS : ApplicationPermission[] = [];
// Define Business Capabilities, typically used to secure endpoints.
export const OPERATION1_CREATE : BusinessCapability = {operation: 'operation1', access: 'opprett', description: '<description>'};
APPLICATION_PERMISSIONS.push(OPERATION1_CREATE);
export const OPERATION1_READ : BusinessCapability = {operation: 'operation1', access: 'les', description: '<description>'};
APPLICATION_PERMISSIONS.push(OPERATION1_READ);
// Define Responsibility Sets, typically used to secure data.
export const OPERATION2_READ : ApplicationPermission = {operation: 'operation2', access: 'les', responsibilityType: 'name1.attributt1', description: '<description>'};
APPLICATION_PERMISSIONS.push(OPERATION2_READ);
初始化权限客户端
在您的 Node.js 应用程序中设置许可客户端涉及初始化一个 TokenFactory 和一个授权缓存 . 以下例子说明如何在使用前配置:
示例 myPermission Client Factory.ts (英语)
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'
import { logger } from './myLogger'
// 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 encountered an error', 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 };
使用权限客户端
示例 服务器.ts
启动应用程序启动时的许可客户端 。 在您的主要应用程序文件中( 例如 ), 服务器.ts 或者说 应用程序:
import express from 'express';
import { initPermissionClient, permissionClient } from './myPermissionClientFactory';
const app = express();
// Initialize Permission Client before starting the server
initPermissionClient()
.then(() => {
console.log('Permission Client initialized successfully');
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
})
.catch((error) => {
console.error('Failed to initialize Permission Client:', error);
process.exit(1); // Exit if initialization fails
});
示例 需要许可( T)
在 Express Middle 软件中检查权限并使用权限Client 在 API 路由中执行访问控制 :
import { Request, Response, NextFunction } from 'express';
import { permissionClient } from './myPermissionClientFactory';
import { BusinessCapability, JwtDecoder } from '@entur-partner/permission-client-node';
// Middleware to check if a user has the required permission
const requirePermission = (requiredPermission: BusinessCapability) => {
return async (req: Request, res: Response, next: NextFunction) => {
try {
if (!permissionClient) {
return res.status(500).json({ error: 'Permission Client is not initialized' });
}
const userJwt = req.headers.authorization?.split(' ')[1]; // Extract JWT from Authorization header
if (!userJwt) {
return res.status(401).json({ error: 'Unauthorized: Missing token' });
}
const authoritySubject = JwtDecoder.getAuthoritySubject(userJwt);
const hasAccess = await permissionClient.checkBusinessCapabilityPermission(authoritySubject, requiredPermission);
if (!hasAccess) {
return res.status(403).json({ error: 'Forbidden: Insufficient permissions' });
}
next(); // Proceed if authorized
} catch (error) {
console.error('Permission check failed:', error);
return res.status(500).json({ error: 'Internal Server Error' });
}
};
};
export default requirePermission;
示例 我的鲁特尔特
以权限获取 REST 端点 。 使用需要的 Permission 中间软件来保护您的快递路线 :
import express from 'express';
import requirePermission from './requirePermission';
import { OPERATION1_READ } from './myPermissions';
const router = express.Router();
router.get('/secure-data', validateBearerToken(req, res), requirePermission(OPERATION1_READ), (req, res) => {
res.json({ message: 'You have access to this secure data' });
});
export default router;
权限
在应用程序中定义和执行权限检查是使用权限客户端的核心部分. 权限客户端支持两种权限:
- 业务能力
- 责任设定
业务能力许可通常用于保障REST终点。 责任权限是一个很好的候选者, 当你想要你安全地在合作伙伴之间分享数据.
权限可以是:
- 仅限于一个或每一个组织.
- 与超用户旗相限制.
业务能力
经营能力是一种通常用于控制端点接入的权利.
业务能力在代码中被定义,在创建LivenClient时被使用. 示例
export const OPERATION_CREATE : BusinessCapability = {operation: 'operation', access: 'opprett', description: '<description>'};
责任设定
责任 Set是一种通过权限和协议控制数据访问的权利. 这种许可工作类似于业务能力,但除此之外,必须登记一项协议,允许用户组织访问 目标数据元素.
"责任集"在代码中被定义,在创建"权限集中"时被使用. 示例
export const OPERATION_READ : ApplicationPermission = {operation: 'operation', access: 'les', responsibilityType: 'name.attributt', description: '<description>'};
协议
协议与责任组合一起使用,以限制用户/客户所属组织获得数据。 也就是说,协议被用来描述一个组织与某些数据要素之间的关系.
使用责任套件的应用程序通常也会在其UI中保持协议,或者将协议委托给相关的UI.
注:协议只能通过创建协议的同一应用程序来更改.
为了管理使用权限客户端的协议,应用程序可以在权限交付存储器上使用下列方法:
- 同步获取协议( 责任组合: 责任组合): 承诺 < 协议 >
- 协议(协议):承诺
- aync 删除协议(协议:大意):承诺
- aync 删除对象(objectKey:objectKey):承诺 // 类似于删除协议,区别是它将删除所有与一个对象有关的协议.
协定的定义来自:
- 操作
- 访问
- 责任类型
- 责任键
- 组织
缓存类型
节点权限客户端只支持一个缓存类型: IN MEmory缓存.
记忆
缓存类型 IN-MEmory 用于生产.
可选: 按下通知
当应用程序运行在内部的GKE环境之一(dev, tst/staging, pd)时, 您可以通过websockets告诉权限客户端使用权限存储推取通知, 而不是在正常间隔时间直接投票. 要做到这一点,请添加websocket依赖性:
yarn add @stomp/stompjs websocket
当你创建权限库时通过参数 typescript{ communicationType: CommunicationType.SocketJS }
const permissionClient = await PermissionClient(AuthorizeCacheType.IN_MEMORY, APPLICATION_PERMISSIONS, repository, { communicationType: CommunicationType.SocketJS });
地点 TEST CACHE
LOCAL TEST CACHE是运行自动测试的缓存类型. LOCAL TEST CACHE 对于节点的许可客户端没有执行. 预计杰斯的模拟功能会被用在自动测试上.
杂项
使用权限存储而不中断
从许可客户端的3.0.0版本开始,您运行服务的每个实例都会收到一个独特的实例ID. 此ID 用于跟踪您服务所需的权限, 允许权限存储计算您的应用程序的全部许可要求.
在引入新权限时,有时需要将其添加到应用程序中. 在你密码里用到它们之前是的. 这确保在代码执行过程中执行相应限制之前,可以进行角色管理.
获取来源
克隆模块来自 GitHub 图像 改为:
git clone https://github.com/entur/permission-client.git
安装依赖性 :
yarn install
运行 欢乐 测试 :
yarn test
出版
在寄存器上发布新版本时,通过GitHub Actions完成发布.
GitHub 发布
在 GitHub 上发布一出新版本是很容易的,用几下就完成了.
- 转到右上角释放标签并点击“ 草稿新发布 ”
- 点击“ 选择标签 ”
- 如果尚未为发行版本制作标记,请创建新的标记.
- 按“ Generate 释放注释” 并在需要时更改内容
- 如果这不是预放, 请选择“ 设置为最新放出” 复选框 .
- 新闻稿