Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 99e4b43
Showing
14 changed files
with
1,885 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
# Logs | ||
logs | ||
*.log | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
# Runtime data | ||
pids | ||
*.pid | ||
*.seed | ||
*.pid.lock | ||
|
||
# Directory for instrumented libs generated by jscoverage/JSCover | ||
lib-cov | ||
|
||
# Coverage directory used by tools like istanbul | ||
coverage | ||
|
||
# nyc test coverage | ||
.nyc_output | ||
|
||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) | ||
.grunt | ||
|
||
# Bower dependency directory (https://bower.io/) | ||
bower_components | ||
|
||
# node-waf configuration | ||
.lock-wscript | ||
|
||
# Compiled binary addons (https://nodejs.org/api/addons.html) | ||
build/Release | ||
|
||
# Dependency directories | ||
node_modules/ | ||
jspm_packages/ | ||
|
||
# Typescript v1 declaration files | ||
typings/ | ||
|
||
# Optional npm cache directory | ||
.npm | ||
|
||
# Optional eslint cache | ||
.eslintcache | ||
|
||
# Optional REPL history | ||
.node_repl_history | ||
|
||
# Output of 'npm pack' | ||
*.tgz | ||
|
||
# Yarn Integrity file | ||
.yarn-integrity | ||
|
||
# dotenv environment variables file | ||
.env | ||
|
||
# next.js build output | ||
.next |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
{ | ||
// Use IntelliSense to learn about possible Node.js debug attributes. | ||
// Hover to view descriptions of existing attributes. | ||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 | ||
"version": "0.2.0", | ||
"configurations": [ | ||
{ | ||
"type": "node", | ||
"request": "attach", | ||
"name": "Attach by Process ID", | ||
"processId": "${command:PickProcess}" | ||
}, | ||
{ | ||
"type": "node", | ||
"request": "launch", | ||
"name": "Debug", | ||
"program": "${workspaceRoot}/node_modules/moleculer/bin/moleculer-runner.js", | ||
"cwd": "${workspaceRoot}", | ||
"args": [ | ||
"services" | ||
] | ||
}, | ||
{ | ||
"type": "node", | ||
"request": "launch", | ||
"name": "Jest", | ||
"program": "${workspaceRoot}/node_modules/jest-cli/bin/jest.js", | ||
"args": ["--runInBand"], | ||
"cwd": "${workspaceRoot}", | ||
"runtimeArgs": [ | ||
"--nolazy" | ||
] | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
[![Moleculer](https://img.shields.io/badge/Powered%20by-Moleculer-green.svg?colorB=0e83cd)](https://moleculer.services) | ||
|
||
# moleculer-protect-services | ||
This repo demonstrates how to use JWT token to protect service actions. It contains a `ServiceGuard` middleware and a `guard` service which implement this feature. | ||
|
||
## Setup | ||
|
||
1. Generate JWT token for every service. Use the `call guard.generate --service myService` command in REPL to generate a JWT for a service. The received token put into `authToken` property in service schema: | ||
|
||
```js | ||
module.exports = { | ||
name: "users", | ||
|
||
authToken: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzZXJ2aWNlIjoidXNlcnMiLCJpYXQiOjE1NDE4NTU0ODl9.td1P27_xpFv1P5_j0HLtMwyz-aRF9xQqjLHYIIHcKPE", | ||
|
||
... | ||
} | ||
``` | ||
> In production you had better place it into environment variables like `USERS_AUTH_TOKEN` and use `authToken: process.env.USERS_AUTH_TOKEN` in schema | ||
2. Define restriction in action definition. If `restricted` property is `null` or not defined it means the action can be called from every service. | ||
|
||
```js | ||
actions: { | ||
create: { | ||
// It can be called by "api" service | ||
restricted: [ | ||
"api" | ||
], | ||
handler(ctx) {} | ||
}, | ||
|
||
list: { | ||
// It can be called by everyone. | ||
restricted: null, | ||
handler(ctx) {} | ||
}, | ||
|
||
posts: { | ||
// It can be called by "api" & "posts" service. | ||
restricted: [ | ||
"api", | ||
"posts" | ||
], | ||
handler(ctx) {} | ||
} | ||
}, | ||
``` | ||
|
||
3. Add `ServiceGuard` middleware to `moleculer.config.js` | ||
|
||
```js | ||
module.exports = { | ||
logger: true, | ||
logLevel: "info", | ||
|
||
middlewares: [ | ||
ServiceGuard | ||
] | ||
}; | ||
``` | ||
|
||
## Try | ||
|
||
**Try the following command in REPL:** | ||
- `call users.create` - throw error because it is called directly, not from the `api` service | ||
- `call users.list` - returns "OK" because it is not restricted | ||
- `call users.posts` - throw error because it is called directly, not from `api` or `posts` service | ||
|
||
- `call posts.createUser` - throw error because it is called from `posts` service and not from `api` service | ||
- `call posts.userPosts` - returns "OK" because it is called from `posts` service. | ||
|
||
- open http://localhost:3000/api/users/create in the browser - returns "OK" because it is called from the `api` service. | ||
|
||
|
||
## Start | ||
|
||
``` bash | ||
# Install dependencies | ||
npm install | ||
|
||
# Start with REPL | ||
npm run dev | ||
|
||
``` | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
const { MoleculerClientError } = require("moleculer").Errors; | ||
|
||
module.exports = { | ||
|
||
// Wrap local action handlers (legacy middleware handler) | ||
localAction(next, action) { | ||
// If this feature enabled | ||
if (action.restricted) { | ||
|
||
// Create new handler | ||
return async function ServiceGuardMiddleware(ctx) { | ||
// Check the service auth token in Context meta | ||
const token = ctx.meta.$authToken; | ||
if (!token) | ||
throw new MoleculerClientError("Service token is missing", 401, "TOKEN_MISSING"); | ||
|
||
// Verify token & restricted services | ||
await ctx.call("guard.check", { token, services: action.restricted }) | ||
|
||
// Call the original handler | ||
return await next(ctx); | ||
|
||
}.bind(this); | ||
} | ||
|
||
// Return original handler, because feature is disabled | ||
return next; | ||
}, | ||
|
||
// Wrap broker.call method | ||
call(next) { | ||
// Create new handler | ||
return async function(actionName, params, opts = {}) { | ||
// Put the service auth token in the meta | ||
if (opts.parentCtx) { | ||
const service = opts.parentCtx.service; | ||
const token = service.schema.authToken; | ||
|
||
if (!opts.meta) | ||
opts.meta = {}; | ||
|
||
opts.meta.$authToken = token; | ||
} | ||
|
||
// Call the original handler | ||
return await next(actionName, params, opts); | ||
|
||
}.bind(this); | ||
}, | ||
|
||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
"use strict"; | ||
|
||
const ServiceGuard = require("./middlewares/ServiceGuard"); | ||
|
||
// More info about options: https://moleculer.services/docs/0.13/broker.html#Broker-options | ||
module.exports = { | ||
logger: true, | ||
logLevel: "info", | ||
|
||
middlewares: [ | ||
ServiceGuard | ||
] | ||
}; |
Oops, something went wrong.