@drmhse/authos-node 0.1.4 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -6
- package/dist/express.d.mts +2 -0
- package/dist/express.d.ts +2 -0
- package/dist/express.js +64 -1
- package/dist/express.mjs +64 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -192,6 +192,33 @@ app.get('/org/:slug/data',
|
|
|
192
192
|
);
|
|
193
193
|
```
|
|
194
194
|
|
|
195
|
+
### requireService(slug, options?)
|
|
196
|
+
|
|
197
|
+
Requires the user's JWT to have a matching service claim. Use this for service-scoped endpoints.
|
|
198
|
+
|
|
199
|
+
```ts
|
|
200
|
+
app.get('/services/:slug/data',
|
|
201
|
+
requireAuth(),
|
|
202
|
+
requireService((req) => req.params.slug),
|
|
203
|
+
(req, res) => { ... }
|
|
204
|
+
);
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### requireTenant(orgSlug, serviceSlug, options?)
|
|
208
|
+
|
|
209
|
+
Requires the user to belong to a specific org AND service. Provides complete tenant isolation.
|
|
210
|
+
|
|
211
|
+
```ts
|
|
212
|
+
app.get('/orgs/:org/services/:service/data',
|
|
213
|
+
requireAuth(),
|
|
214
|
+
requireTenant(
|
|
215
|
+
(req) => req.params.org,
|
|
216
|
+
(req) => req.params.service
|
|
217
|
+
),
|
|
218
|
+
(req, res) => { ... }
|
|
219
|
+
);
|
|
220
|
+
```
|
|
221
|
+
|
|
195
222
|
## Understanding JWT Context
|
|
196
223
|
|
|
197
224
|
The middleware functions check claims embedded in the JWT by the client SDK during login:
|
|
@@ -199,7 +226,8 @@ The middleware functions check claims embedded in the JWT by the client SDK duri
|
|
|
199
226
|
| SDK Initialization | JWT Claims | Middleware to Use |
|
|
200
227
|
|-------------------|-----------|------------------|
|
|
201
228
|
| Platform-level (`baseURL` only) | `is_platform_owner: true` | `requirePlatformOwner()` |
|
|
202
|
-
|
|
|
229
|
+
| Org-level (`baseURL` + `org`) | `org: 'slug'` | `requireOrganization()` |
|
|
230
|
+
| Service-level (`baseURL` + `org` + `service`) | `org: 'slug'`, `service: 'app'` | `requireTenant()` or `requireService()` |
|
|
203
231
|
| With permissions | `permissions: ['users:write', ...]` | `requirePermission()` |
|
|
204
232
|
|
|
205
233
|
### How It Works
|
|
@@ -209,13 +237,19 @@ The middleware functions check claims embedded in the JWT by the client SDK duri
|
|
|
209
237
|
3. **Server-side**: This package verifies the JWT and middleware checks the claims
|
|
210
238
|
|
|
211
239
|
```ts
|
|
212
|
-
// Example: Route for
|
|
213
|
-
app.get('/org/:
|
|
240
|
+
// Example: Route for tenant-specific data
|
|
241
|
+
app.get('/orgs/:org/services/:service/data',
|
|
214
242
|
requireAuth(), // 1. Verify JWT signature
|
|
215
|
-
|
|
243
|
+
requireTenant( // 2. Check org + service claims
|
|
244
|
+
(req) => req.params.org,
|
|
245
|
+
(req) => req.params.service
|
|
246
|
+
),
|
|
216
247
|
(req, res) => {
|
|
217
|
-
// User is authenticated AND belongs to this org
|
|
218
|
-
res.json({
|
|
248
|
+
// User is authenticated AND belongs to this org+service
|
|
249
|
+
res.json({
|
|
250
|
+
org: req.auth?.claims.org,
|
|
251
|
+
service: req.auth?.claims.service
|
|
252
|
+
});
|
|
219
253
|
}
|
|
220
254
|
);
|
|
221
255
|
|
package/dist/express.d.mts
CHANGED
|
@@ -19,6 +19,8 @@ declare function createAuthMiddleware(options: AuthOSNodeOptions): {
|
|
|
19
19
|
requireAllPermissions: (permissions: string[], permOptions?: RequirePermissionOptions) => RequestHandler;
|
|
20
20
|
requirePlatformOwner: (permOptions?: RequirePermissionOptions) => RequestHandler;
|
|
21
21
|
requireOrganization: (getOrgSlug: string | ((req: Request) => string), permOptions?: RequirePermissionOptions) => RequestHandler;
|
|
22
|
+
requireService: (getServiceSlug: string | ((req: Request) => string), permOptions?: RequirePermissionOptions) => RequestHandler;
|
|
23
|
+
requireTenant: (getOrgSlug: string | ((req: Request) => string), getServiceSlug: string | ((req: Request) => string), permOptions?: RequirePermissionOptions) => RequestHandler;
|
|
22
24
|
};
|
|
23
25
|
|
|
24
26
|
export { createAuthMiddleware };
|
package/dist/express.d.ts
CHANGED
|
@@ -19,6 +19,8 @@ declare function createAuthMiddleware(options: AuthOSNodeOptions): {
|
|
|
19
19
|
requireAllPermissions: (permissions: string[], permOptions?: RequirePermissionOptions) => RequestHandler;
|
|
20
20
|
requirePlatformOwner: (permOptions?: RequirePermissionOptions) => RequestHandler;
|
|
21
21
|
requireOrganization: (getOrgSlug: string | ((req: Request) => string), permOptions?: RequirePermissionOptions) => RequestHandler;
|
|
22
|
+
requireService: (getServiceSlug: string | ((req: Request) => string), permOptions?: RequirePermissionOptions) => RequestHandler;
|
|
23
|
+
requireTenant: (getOrgSlug: string | ((req: Request) => string), getServiceSlug: string | ((req: Request) => string), permOptions?: RequirePermissionOptions) => RequestHandler;
|
|
22
24
|
};
|
|
23
25
|
|
|
24
26
|
export { createAuthMiddleware };
|
package/dist/express.js
CHANGED
|
@@ -382,13 +382,76 @@ function createAuthMiddleware(options) {
|
|
|
382
382
|
next();
|
|
383
383
|
};
|
|
384
384
|
}
|
|
385
|
+
function requireService(getServiceSlug, permOptions = {}) {
|
|
386
|
+
const { message = "Service access required" } = permOptions;
|
|
387
|
+
return (req, res, next) => {
|
|
388
|
+
if (!req.auth) {
|
|
389
|
+
res.status(401).json({
|
|
390
|
+
error: "Unauthorized",
|
|
391
|
+
message: "Authentication required",
|
|
392
|
+
code: "NOT_AUTHENTICATED"
|
|
393
|
+
});
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
const requiredService = typeof getServiceSlug === "function" ? getServiceSlug(req) : getServiceSlug;
|
|
397
|
+
const userService = req.auth.claims.service;
|
|
398
|
+
if (!userService || userService !== requiredService) {
|
|
399
|
+
res.status(403).json({
|
|
400
|
+
error: "Forbidden",
|
|
401
|
+
message,
|
|
402
|
+
code: "WRONG_SERVICE",
|
|
403
|
+
required: requiredService
|
|
404
|
+
});
|
|
405
|
+
return;
|
|
406
|
+
}
|
|
407
|
+
next();
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
function requireTenant(getOrgSlug, getServiceSlug, permOptions = {}) {
|
|
411
|
+
const { message = "Tenant access required" } = permOptions;
|
|
412
|
+
return (req, res, next) => {
|
|
413
|
+
if (!req.auth) {
|
|
414
|
+
res.status(401).json({
|
|
415
|
+
error: "Unauthorized",
|
|
416
|
+
message: "Authentication required",
|
|
417
|
+
code: "NOT_AUTHENTICATED"
|
|
418
|
+
});
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
const requiredOrg = typeof getOrgSlug === "function" ? getOrgSlug(req) : getOrgSlug;
|
|
422
|
+
const requiredService = typeof getServiceSlug === "function" ? getServiceSlug(req) : getServiceSlug;
|
|
423
|
+
const userOrg = req.auth.claims.org;
|
|
424
|
+
const userService = req.auth.claims.service;
|
|
425
|
+
if (!userOrg || userOrg !== requiredOrg) {
|
|
426
|
+
res.status(403).json({
|
|
427
|
+
error: "Forbidden",
|
|
428
|
+
message,
|
|
429
|
+
code: "WRONG_ORGANIZATION",
|
|
430
|
+
required: { org: requiredOrg, service: requiredService }
|
|
431
|
+
});
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
if (!userService || userService !== requiredService) {
|
|
435
|
+
res.status(403).json({
|
|
436
|
+
error: "Forbidden",
|
|
437
|
+
message,
|
|
438
|
+
code: "WRONG_SERVICE",
|
|
439
|
+
required: { org: requiredOrg, service: requiredService }
|
|
440
|
+
});
|
|
441
|
+
return;
|
|
442
|
+
}
|
|
443
|
+
next();
|
|
444
|
+
};
|
|
445
|
+
}
|
|
385
446
|
return {
|
|
386
447
|
requireAuth,
|
|
387
448
|
requirePermission,
|
|
388
449
|
requireAnyPermission,
|
|
389
450
|
requireAllPermissions,
|
|
390
451
|
requirePlatformOwner,
|
|
391
|
-
requireOrganization
|
|
452
|
+
requireOrganization,
|
|
453
|
+
requireService,
|
|
454
|
+
requireTenant
|
|
392
455
|
};
|
|
393
456
|
}
|
|
394
457
|
|
package/dist/express.mjs
CHANGED
|
@@ -360,13 +360,76 @@ function createAuthMiddleware(options) {
|
|
|
360
360
|
next();
|
|
361
361
|
};
|
|
362
362
|
}
|
|
363
|
+
function requireService(getServiceSlug, permOptions = {}) {
|
|
364
|
+
const { message = "Service access required" } = permOptions;
|
|
365
|
+
return (req, res, next) => {
|
|
366
|
+
if (!req.auth) {
|
|
367
|
+
res.status(401).json({
|
|
368
|
+
error: "Unauthorized",
|
|
369
|
+
message: "Authentication required",
|
|
370
|
+
code: "NOT_AUTHENTICATED"
|
|
371
|
+
});
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
const requiredService = typeof getServiceSlug === "function" ? getServiceSlug(req) : getServiceSlug;
|
|
375
|
+
const userService = req.auth.claims.service;
|
|
376
|
+
if (!userService || userService !== requiredService) {
|
|
377
|
+
res.status(403).json({
|
|
378
|
+
error: "Forbidden",
|
|
379
|
+
message,
|
|
380
|
+
code: "WRONG_SERVICE",
|
|
381
|
+
required: requiredService
|
|
382
|
+
});
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
next();
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
function requireTenant(getOrgSlug, getServiceSlug, permOptions = {}) {
|
|
389
|
+
const { message = "Tenant access required" } = permOptions;
|
|
390
|
+
return (req, res, next) => {
|
|
391
|
+
if (!req.auth) {
|
|
392
|
+
res.status(401).json({
|
|
393
|
+
error: "Unauthorized",
|
|
394
|
+
message: "Authentication required",
|
|
395
|
+
code: "NOT_AUTHENTICATED"
|
|
396
|
+
});
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
const requiredOrg = typeof getOrgSlug === "function" ? getOrgSlug(req) : getOrgSlug;
|
|
400
|
+
const requiredService = typeof getServiceSlug === "function" ? getServiceSlug(req) : getServiceSlug;
|
|
401
|
+
const userOrg = req.auth.claims.org;
|
|
402
|
+
const userService = req.auth.claims.service;
|
|
403
|
+
if (!userOrg || userOrg !== requiredOrg) {
|
|
404
|
+
res.status(403).json({
|
|
405
|
+
error: "Forbidden",
|
|
406
|
+
message,
|
|
407
|
+
code: "WRONG_ORGANIZATION",
|
|
408
|
+
required: { org: requiredOrg, service: requiredService }
|
|
409
|
+
});
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
if (!userService || userService !== requiredService) {
|
|
413
|
+
res.status(403).json({
|
|
414
|
+
error: "Forbidden",
|
|
415
|
+
message,
|
|
416
|
+
code: "WRONG_SERVICE",
|
|
417
|
+
required: { org: requiredOrg, service: requiredService }
|
|
418
|
+
});
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
next();
|
|
422
|
+
};
|
|
423
|
+
}
|
|
363
424
|
return {
|
|
364
425
|
requireAuth,
|
|
365
426
|
requirePermission,
|
|
366
427
|
requireAnyPermission,
|
|
367
428
|
requireAllPermissions,
|
|
368
429
|
requirePlatformOwner,
|
|
369
|
-
requireOrganization
|
|
430
|
+
requireOrganization,
|
|
431
|
+
requireService,
|
|
432
|
+
requireTenant
|
|
370
433
|
};
|
|
371
434
|
}
|
|
372
435
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@drmhse/authos-node",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "Node.js server adapter for AuthOS authentication - Express middleware and token verification",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
}
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
|
-
"@drmhse/sso-sdk": "^0.3.
|
|
61
|
+
"@drmhse/sso-sdk": "^0.3.13"
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
64
|
"@types/express": "^5.0.0",
|