@interopio/gateway-server
v0.23.1
Published
[](https://www.npmjs.com/package/@interopio/gateway-server)
Readme
io.Gateway Server
Overview
The @interopio/gateway-server package is the web server used to run the gateway as a standalone server app accessible via WebSocket.
The server is general purpose http server with support for:
- HTTP and HTTPS
- CORS configuration
- Basic, mTLS, and OAuth2 authentication
- Custom API routes (both for HTTP and WebSocket)
npm install @interopio/gateway-serverTable of Contents
Getting Started
CLI:
npx @interopio/gateway-server run --port 8385 --gatewayAPI:
import GatewayServer, { type Server } from '@interopio/gateway-server';
const server: Server = await GatewayServer({
port: 8385,
gateway: {
route: '/gw',
authorize: { access: 'authenticated' },
ping: {
interval: 30000, // 30 seconds
data: 'timestamp'
}
}
});
server.address; // Bound address info
server.gateway; // Gateway instance
await server.close();Configure HTTPS
SSL/TLS configuration supports PEM-formatted certificates. Two modes are available:
1. Explicit certificates - Provide your own key and certificate files (both must exist):
const server = await GatewayServer({
port: 8443,
ssl: {
key: "./ssl/gateway-server.key",
cert: "./ssl/gateway-server.crt",
passphrase: "secret" // optional, if key is encrypted
}
});Recommended for production: Generate your own server certificates using a trusted CA or create your own CA infrastructure. See Generating Server Certificates with OpenSSL below.
2. Auto-generated server certificates - Provide a CA key via auth.x509.key to auto-generate server certificates:
⚠️ Development only: Auto-generated certificates are intended for development and testing. For production environments, use explicit certificates (mode 1) with proper certificate management.
Note: The CA private key is stored under
auth.x509.keysince its primary purpose is generating client certificates for X.509 authentication. It is incidentally used to generate self-signed server certificates when no explicit server cert is provided and ssl is enabled.
// Option A: Specify custom CA paths
await GatewayServer({
port: 8443,
host: "example.com", // optional: used in generated certificate's CN and SAN
ssl: {
ca: "./ssl/gateway-ca.crt", // CA certificate for client verification (optional)
key: "./ssl/gateway-server.key", // optional: save generated server key to file
cert: "./ssl/gateway-server.crt", // optional: save generated server cert to file
passphrase: undefined // optional, if key is encrypted
},
auth: {
type: 'x509',
x509: {
key: "./ssl/gateway-ca.key", // CA private key (auto-generates CA if missing)
passphrase: undefined, // optional, if CA key is encrypted
}
}
});
// Option B: Use default development CA (simplest for development)
await GatewayServer({
port: 8443,
ssl: {},
auth: {
type: 'x509',
x509: {
key: "./ssl/gateway-ca.key" // ca cert derives to ./ssl/gateway-ca.crt
}
}
});
// Option C: Minimal mode (uses gateway-ca.key and gateway-ca.crt)
await GatewayServer({
port: 8443,
ssl: {},
auth: {
type: 'x509',
x509: {
key: undefined // defaults to gateway-ca.key in current directory
}
}
});Client Configuration: For mode 2, distribute the Root CA certificate (
.crtfile) to clients. Clients must import this CA into their trust store. Server certificates are regenerated on each startup (in memory or saved to disk if key/cert paths specified) and are automatically trusted by clients who trust the Root CA.Auto-generation: If CA files don't exist (specified in
auth.x509.key), they are automatically generated and saved to disk. The CA certificate path is derived from the key path by replacing the extension with.crt(if not explicitly specified viassl.ca). The CA is valid for 10 years and uses ECDSA secp384r1. Server certificates are regenerated on startup with 7-day validity.Hostname in certificates: When auto-generating server certificates (mode 2), the
hostparameter (if specified) is used as the Common Name (CN) and in the Subject Alternative Name (SAN) of the certificate. Ifhostis not specified, defaults tolocalhost.Note: When both
ssl.keyandssl.crtfiles exist, mode 1 is used (explicit certificates). Otherwise mode 2 is used (auto-generated from CA key inauth.x509.key). For production deployments, always use mode 1 with properly managed certificates.
Generating Server Certificates with OpenSSL
To generate your own server certificates for mode 1 (explicit certificates) using OpenSSL:
Production Best Practice: Use this approach to create properly signed certificates for your production environment. Ensure certificates are renewed before expiration and follow your organization's certificate management policies.
# Set the domain name for the server certificate
DOMAIN=gateway.localhost
# Set paths to your CA certificate and key
CA_CERT=./ssl/gateway-ca.crt
CA_KEY=./ssl/gateway-ca.key
# Generate server private key (ECDSA secp256r1)
openssl ecparam -name prime256v1 -genkey -noout -out ./ssl/gateway-server.key
# Create a certificate signing request (CSR) with extensions
openssl req -new -key ./ssl/gateway-server.key -out ./ssl/gateway-server.csr \
-subj "/CN=${DOMAIN}" \
-addext "basicConstraints=CA:FALSE" \
-addext "keyUsage=critical,digitalSignature,keyEncipherment" \
-addext "extendedKeyUsage=serverAuth" \
-addext "subjectAltName=DNS:${DOMAIN},DNS:*.${DOMAIN}"
# Sign the CSR with your Root CA
openssl x509 -req -in ./ssl/gateway-server.csr \
-CA ${CA_CERT} -CAkey ${CA_KEY} \
-out ./ssl/gateway-server.crt -days 365 -sha256 \
-copy_extensions copyallImportant: The
subjectAltNamewith DNS entries is required for server certificates. Modern browsers and clients reject certificates without SAN, even if the Common Name (CN) matches the hostname.
Mutual TLS (Client Certificate Authentication)
Enable client certificate verification for mutual TLS authentication:
const server = await GatewayServer({
port: 8443,
ssl: {
key: "./ssl/gateway-server.key", // Server private key
cert: "./ssl/gateway-server.crt", // Server certificate
ca: "./ssl/gateway-client-ca.crt", // CA that signed client certificates
requestCert: true, // Ask clients to send certificates
rejectUnauthorized: true // Reject clients without valid certs
}
});Configuration options:
requestCert: false(default) - Server does not request client certificatesrequestCert: true, rejectUnauthorized: false- Client certs optional (allow anonymous)requestCert: true, rejectUnauthorized: true- Client certs required (enforce mutual TLS)
Note: When
requestCertisfalse, clients will not send certificates even if they have them. The server must explicitly request them during the TLS handshake.
Generating Client Certificates with OpenSSL
To generate client certificates for mutual TLS authentication using OpenSSL:
# Set paths to your CA certificate and key
CA_CERT=./ssl/gateway-ca.crt
CA_KEY=./ssl/gateway-ca.key
# Generate client private key (ECDSA secp256r1)
openssl ecparam -name prime256v1 -genkey -noout -out ./ssl/gateway-client.key
# Create a certificate signing request (CSR) with extensions
openssl req -new -key ./ssl/gateway-client.key -out ./ssl/gateway-client.csr \
-subj "/CN=dev-user" \
-addext "basicConstraints=CA:FALSE" \
-addext "keyUsage=critical,digitalSignature,keyEncipherment" \
-addext "extendedKeyUsage=clientAuth" \
-addext "subjectAltName=email:[email protected]"
# Sign the CSR with your Root CA
openssl x509 -req -in ./ssl/gateway-client.csr \
-CA ${CA_CERT} -CAkey ${CA_KEY} \
-out ./ssl/gateway-client.crt -days 365 -sha256 \
-copy_extensions copyall
openssl pkcs12 -export -out ./ssl/gateway-client.p12 \
-inkey ./ssl/gateway-client.key -in ./ssl/gateway-client.crt \
-passout pass:changeitImportant: The
extendedKeyUsage=clientAuthis critical for client certificates. Without it, the certificate may be rejected during mutual TLS authentication.
Full Example with Authentication
import GatewayServer, {type Server} from '@interopio/gateway-server';
const server: Server = await GatewayServer({
port: 8443,
// Enable HTTPS with Development CA
ssl: {
ca: './ssl/gateway-ca.crt', // CA cert for client verification
rejectUnauthorized: false, // allow anonymous if no client cert
requestCert: true, // request client certificates for mutual TLS
},
auth: {
type: 'oauth2', // or 'basic' or 'x509'
oauth2: {
jwt: {
issuerUri: 'https://auth.example.com',
audience: 'https://api.example.com',
principalClaimName: 'sub', // claim to use as principal
}
},
x509: {
principalAltName: 'email', // extract principal from certificate email SAN (default: uses subject)
key: './ssl/gateway-ca.key' // CA key for generating certs
},
basic: {
realm: 'My Gateway'
},
},
app: async ({handle}) => {
handle(
{
request: {method: 'GET', path: '/api/metrics'},
options: {cors: true, authorize: {access: 'authenticated'}},
handler: async ({response}) => {
response.setStatusCode({value: 200}); // OK
await response.end();
}
},
{
request: {method: 'POST', path: '/api/metrics'},
options: {cors: true, authorize: {access: 'authenticated'}},
handler: async ({request, response}) => {
response.statusCode({value: 202}); // Accepted
await response.end();
try {
const update = await request.json();
console.log(`${JSON.stringify(update)}`);
} catch (e) {
console.error('Error processing metrics:', e);
}
}
});
},
});
await server.close();
Management
The gateway server supports a management interface for remote administration via named pipes (Windows) or Unix sockets. This allows external tools to send commands like info (get server status) or shutdown (gracefully stop the server).
CLI
Use the manage command to send management commands to a running gateway server:
# Get server info
npx @interopio/gateway-server manage --path \\.\pipe\glue42-gateway-xxx info
# Shutdown the server
npx @interopio/gateway-server manage --path \\.\pipe\glue42-gateway-xxx shutdownAPI
import { manage } from '@interopio/gateway-server/tools';
// Send a command to a running gateway server
const result = await manage.sendCommand(
{ path: '\\\\.\\pipe\\glue42-gateway-xxx' },
{ command: 'info' }
);Server Configuration
function getPath() {
const prefix = `glue42-gateway`;
const env = process.env['GLUE-ENV'] || 'DEMO';
const region = process.env['GLUE-REGION'] || 'INTEROP.IO';
return process.platform === 'win32'
? `\\\\.\\pipe\\glue42-gateway-${env}-${region}-${process.env.USERNAME}`
: `${tmpdir()}/${prefix}-${env}-${region}-${process.env.USERNAME}.sock`;
}
const server: GatewayServer.Server = await GatewayServerFactory({
management: {
server: {
path: getPath()
},
commands: {
shutdown: { enabled: false },
}
}
});@glue42/gateway-ent Compatibility
This package aims to provide compatibility with @glue42/gateway-ent proprietary package used in Glue42 Desktop (now io.Connect Desktop)
import * as gw from '@interopio/gateway-server/gateway-ent';Changelog
See changelog
