Middleware Extensibility
Middleware extensibility allows developers to implement new middleware handlers to both MPS or RPS. By adding custom functions, MPS and RPS will process and load these during server startup. The loadCustomMiddleware
function that executes on startup can be found in mps/src/server/webserver.ts
or rps/src/index.ts
.
Example use-cases:
- Multitenancy
- Handling Custom Authentication Tokens
- Adding Trace IDs
- Debugging Requests
To demonstrate the execution, we'll use an example. Let's say a custom auth token handler was implemented across all API endpoints. When a call is then made against an API endpoint, the custom handler will execute first. This handler might process the token. After executing the custom function and calling next()
, API execution will then continue as normal.
Add a Custom Middleware Function¶
To add a new function, create a new typescript file in /src/middleware/custom/
. An example.ts
file is already provided in this directory.
The file must have two key parts in order to successfully load:
- The desired function must be exported as a default. Only the single, default function will be what is loaded into MPS or RPS. Additional functions that need to be loaded will need their own separate
.ts
files. - Must call
next()
. This will allow execution to continue after processing the custom function.
Multitenancy Code Example¶
Implementation might vary depending on cloud provider or other 3rd party solutions. This specific example implements against Microsoft Azure and the default Open AMT components.
The following code might not be a final solution, but provides a starting point and template example.
The example implementation has a tenantId that is passed as part of the JWT token header when an API is called. The token is decoded and its tenantId is checked against the available tenants in MPS or RPS. This verifies that the user has the correct access to the MPS or RPS data being added, modified, or deleted.
Multitenancy Example Code
import { Request, Response } from 'express'
import { devices } from '../../server/mpsserver'
import { Environment } from '../../utils/Environment'
const tenantMiddleware = (req: Request, res: Response, next): void => {
const jwtTokenHeader = Environment.Config.jwt_token_header ?? 'x-id-token'
const token = req.headers[jwtTokenHeader]
req.tenantId = ''
if (token != null && token !== '') {
try {
const decodedToken = Buffer.from(token as string, 'base64'). toString ()
if (decodedToken != null && decodedToken !== '') {
const dt = JSON.parse(decodedToken)
const tenantProp = Environment.Config.jwt_tenant_property ?? ''
req.tenantId = dt[tenantProp] ?? ''
}
} catch (err) {
console.error(err)
}
}
next()
}
export default tenantMiddleware
After implementing the multitenancy code changes and starting the services, profiles and configs can be created by providing a tenantID
as part of the API calls.
Then when activating and configuring the AMT device using RPC, provide the -tenant
flag with the tenantID
of the profile. Find all RPC flags in the RPC CLI docs. See example command below.
sudo ./rpc activate -u wss://server/activate -n -profile profilename -tenant profileTenantID
.\rpc activate -u wss://server/activate -n -profile profilename -tenant profileTenantID