UNPKG

@interopio/gateway

Version:

[![npm version](https://img.shields.io/npm/v/@interopio/gateway.svg)](https://www.npmjs.com/package/@interopio/gateway)

249 lines (190 loc) 8.32 kB
# io.Gateway [![npm version](https://img.shields.io/npm/v/@interopio/gateway.svg)](https://www.npmjs.com/package/@interopio/gateway) ## Overview The `@interopio/gateway` package is the gateway for io.Connect Desktop/Browser. ## Table of Contents - [Installation](#installation) - [Requirements](#requirements) - [Usage Examples](#usage-examples) - [Change Token TTL](#change-token-ttl) - [OAuth 2.0 Authenticator](#oauth-20-authenticator) - [Custom Authenticator](#custom-authenticator) - [Client Authentication](#client-authentication) - [Visibility](#visibility) - [Changelog](#changelog) - [License](#license) ## Installation ```shell npm install @interopio/gateway@beta ``` ## Requirements - WebCrypto - [WebCrypto](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API) is a standard API for performing cryptographic operations in web applications. It is supported in most modern browsers and Node.js environments. If running Node.js 18, you need to enable the `--experimental-global-webcrypto` flag, or set `globalThis.crypto` your self. For example `const { webcrypto } = require('crypto'); globalThis.crypto = webcrypto;` - WebSocket - [WebSocket](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) is a protocol for full-duplex communication channels over a single TCP connection. It is supported in most modern browsers and Node.js environments. If running Node.js 18, you need to install the `ws` package. For example `npm install ws`. - fetch - [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) is a modern interface for making HTTP requests in web applications. It is supported in most modern browsers and Node.js environments. If running Node.js 16, you need to enable the `--experimental-fetch` flag, or set `globalThis.fetch` your self. ## API docs See [`gateway.md`](./gateway.md) ## Usage Examples ### Change Token TTL ```typescript import Gateway from '@interopio/gateway' const gateway = Gateway({ token: { ttl: 1 * 24 * 60 * 60 // expiry of access tokens in seconds. 86400 is 1 day. } }); await gateway.start(); ``` ### OAuth 2.0 Authenticator To secure io.Gateway with OAuth 2.0 authentication services like auth0 or okta you need to configure ```typescript import Gateway from '@interopio/gateway' const gateway = Gateway({ authentication: { default: 'oauth2', available: ['basic', 'oauth2'], // remove basic if want oauth2 only oauth2: {issuerBaseURL: 'https://<your-issuer-domain>', audience: 'https://<myapi>'} } }); const client = gateway.client((msg) => console.log(msg)); const token = '<authorizationToken>'; client.send({type: 'hello', identity: {application: 'test'}, authentication: {method: 'access-token', token}}); ``` ### Custom Authenticator To secure io.Gateway with a custom authenticator, you can add a subsection with `authenticator` property in the `authentication` option. Then list it in the `available` array. The custom authenticator is a function that takes an `authentication` object and returns a promise that resolves to an object with either a `type` of `success` or `continue`. - If the authentication is successful, resolve the result with `type: 'success'` and optionally a `user` property. - If the authentication requires further user interaction, return an object with `type: 'continue'`. - If the authentication fails, you can throw an error or return a rejected promise. ```typescript // no-user.ts import {AuthenticationRequest, AuthenticationResponse} from '@interopio/gateway/auth/api'; export default async function none({authentication}: AuthenticationRequest): Promise<AuthenticationResponse> { if (authentication.method === 'none') { // No authentication required return {type: 'success'}; } return {type: 'error', message: 'Authentication method not supported'}; } // os-user.ts import {AuthenticationRequest, AuthenticationResponse} from '@interopio/gateway/auth/api'; export default async function node({authentication}: AuthenticationRequest): Promise<AuthenticationResponse> { if (authentication.method === 'none') { return {type: 'success', user: process.env['USER'] ?? process.env['USERNAME']}; } return {type: 'error', message: 'Authentication method not supported'}; } // myauth.ts import {AuthenticationRequest, AuthenticationResponse} from '@interopio/gateway/auth/api'; export default async function myauth({authentication}: AuthenticationRequest): Promise<AuthenticationResponse> { if (authentication.method === 'access-token') { // Custom authentication logic // For example, check a token or perform some validation if (authentication.token === 'my-secret-token') { return {type: 'success', user: 'myuser'}; } return {type: 'error', message: 'Invalid token'}; } return {type: 'error', message: 'Authentication method not supported'}; } // index.ts import Gateway from '@interopio/gateway'; const gateway = Gateway({ authentication: { default: 'myauth', available: ['basic', 'myauth'], myauth: { authenticator: none } } }); ``` ### Client Authentication ```typescript import {IOGateway} from '@interopio/gateway' const gateway = IOGateway.Factory({}); await gateway.start(); const opts: IOGateway.GatewayClientOptions = { // this callback is invoked when authentication method 'gateway-client' is requested on hanshake (hello) onAuthenticate: async (request: IOGateway.Auth.AuthenticationRequest): Promise<IOGateway.Auth.AuthenticationSuccess> => { // throw Error to reject the request return {type: 'success', user: 'client'}; } }; const client: IOGateway.GatewayClient = gateway.client((msg) => { if (msg.type === 'welcome') { console.log(`authenticated with user: ${msg.resolved_identity.user}`); } }, opts); // handshake with authentication method 'gateway-client' client.send({type: 'hello', identity: {application: 'demo'}, authentication: {method:'gateway-client'}}); client.close(); await gateway.close(); ``` ### Metrics Publisher ```typescript import Gateway from '@interopio/gateway' const gateway = Gateway({ metrics: { publishers: ['rest'], rest: { endpoint: 'http://localhost:8084/api/metrics', authentication: false } } }); ``` ### Visibility ```typescript import Gateway from '@interopio/gateway' const gateway = Gateway({ contexts: { visibility: [ {context: /'___channel___.+'/, restrictions: 'cluster'}, // all context starting with '___channel___' are with 'cluster' visibility {context: /T42\..+/, restrictions: 'local', identity: {application: 'io.Connect Desktop'}}, // all context starting with T42. created by 'io.Connect Desktop' are with 'local' visibility {context: /.+/, restrictions: 'cluster'} // all other contexts are with cluster visibility ] }, methods: { visibility: [ {method: /T42\..+/, restrictions: 'local'}, // all methods and streams starting with T42. are with 'local' visibility {method: /.+/, restrictions: 'cluster'} // all other methods and streams are with 'cluster' visibility ] }, peers: { visibility: [ // {domain: 'context', restrictions: 'cluster'}, does nothing {domain: 'interop', restrictions: 'local'}, // interop domain is with 'local' visibility {domain: 'interop', restrictions: 'cluster'}, {domain: 'bus', restrictions: 'local'} ] } }); ``` ### Context Lifetime ```typescript import Gateway from '@interopio/gateway' const gateway = Gateway({contexts: {lifetime: 'retained'}}); ``` ### Cluster You can use the `cluster` option to configure the cluster settings. For example, to configure the cluster to use an io.Bridge instance running on `localhost:8084`, you can do the following: ```typescript import Gateway from '@interopio/gateway'; const gateway = await IOGateway.Gateway({ cluster: { // io.Bridge url endpoint: 'http://localhost:8084', } }); ``` ## Changelog See [changelog](./changelog.md) ## License [MIT](license.md)