diff --git a/README.md b/README.md index b14beeb..7e90c6b 100644 --- a/README.md +++ b/README.md @@ -47,25 +47,30 @@ const client = mqtt.connect('ws://localhost:8883/ws') Backbone can be configured using environment variables: -| Variable | Description | Default | -| -------------------- | ---------------------------------------- | ----------- | -| `ADMIN_TOKEN` | Admin token for API requests | `undefined` | -| `JWT_SECRET` | JWT signing secret for authentication | `undefined` | -| `K8S_ENABLED` | Enable Kubernetes operator mode | `false` | -| `WS_ENABLED` | Enable WebSocket MQTT server | `false` | -| `API_ENABLED` | Enable HTTP API | `false` | -| `HTTP_PORT` | HTTP server port | `8883` | -| `TCP_ENABLED` | Enable TCP MQTT server | `false` | -| `TCP_PORT` | TCP server port | `1883` | -| `OIDC_ENABLED` | OIDC discovery URL | `false` | -| `OIDC_DISCOVERY` | OIDC discovery URL | `undefined` | -| `OIDC_CLIENT_ID` | OIDC client ID | `undefined` | -| `OIDC_CLIENT_SECRET` | OIDC client secret | `undefined` | -| `OIDC_CLIENT_SECRET` | OIDC client secret | `undefined` | -| `OIDC_GROUP_FIELD` | JWT field for reading groups | `'groups'` | -| `OIDC_ADMIN_GROUP` | JWT group for admins | `undefined` | -| `OIDC_WRITER_GROUP` | JWT group with publish access to queue | `undefined` | -| `OIDC_READER_GROUP` | JWT group with read-only access to queue | `undefined` | +| Variable | Description | Default | +| -------------------- | ---------------------------------------- | ------------ | +| `ADMIN_TOKEN` | Admin token for API requests | `undefined` | +| `JWT_SECRET` | JWT signing secret for authentication | `undefined` | +| `K8S_ENABLED` | Enable Kubernetes operator mode | `false` | +| `WS_ENABLED` | Enable WebSocket MQTT server | `false` | +| `API_ENABLED` | Enable HTTP API | `false` | +| `HTTP_PORT` | HTTP server port | `8883` | +| `TCP_ENABLED` | Enable TCP MQTT server | `false` | +| `TCP_PORT` | TCP server port | `1883` | +| `OIDC_ENABLED` | OIDC discovery URL | `false` | +| `OIDC_DISCOVERY` | OIDC discovery URL | `undefined` | +| `OIDC_CLIENT_ID` | OIDC client ID | `undefined` | +| `OIDC_CLIENT_SECRET` | OIDC client secret | `undefined` | +| `OIDC_CLIENT_SECRET` | OIDC client secret | `undefined` | +| `OIDC_GROUP_FIELD` | JWT field for reading groups | `'groups'` | +| `OIDC_ADMIN_GROUP` | JWT group for admins | `undefined` | +| `OIDC_WRITER_GROUP` | JWT group with publish access to queue | `undefined` | +| `OIDC_READER_GROUP` | JWT group with read-only access to queue | `undefined` | +| `REDIS_ENABLED` | Enable redis persistance | `false` | +| `REDIS_HOST` | Redis hostname | `'localhost` | +| `REDIS_PORT` | Redis port | `6379` | +| `REDIS_PASSWORD` | Redis password | `undefined` | +| `REDIS_DB` | Redis database | `0` | ### Example Configuration diff --git a/docker-compose.yaml b/docker-compose.yaml index 09cb54b..e38c66d 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,12 +1,16 @@ name: backbone services: - app: - build: - context: . - environment: - HTTP_ENABLED: 'true' - TCP_ENABLED: 'true' - TOKEN_SECRET: 'test' + redis: + image: redis ports: - - 1883:1883 - - 8883:8883 + - 6379:6379 + # app: + # build: + # context: . + # environment: + # HTTP_ENABLED: 'true' + # TCP_ENABLED: 'true' + # TOKEN_SECRET: 'test' + # ports: + # - 1883:1883 + # - 8883:8883 diff --git a/package.json b/package.json index d155511..817a809 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "aedes": "^0.51.3", "aedes-packet": "^3.0.0", "aedes-persistence": "^10.2.2", + "aedes-persistence-redis": "^11.2.2", "ajv": "^8.17.1", "better-sqlite3": "^12.4.1", "fastify": "^5.6.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ce77a76..f8f32ae 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -32,6 +32,9 @@ importers: aedes-persistence: specifier: ^10.2.2 version: 10.2.2 + aedes-persistence-redis: + specifier: ^11.2.2 + version: 11.2.2 ajv: specifier: ^8.17.1 version: 8.17.1 @@ -394,6 +397,9 @@ packages: resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} engines: {node: '>=18.18'} + '@ioredis/commands@1.4.0': + resolution: {integrity: sha512-aFT2yemJJo+TZCmieA7qnYGQooOS7QfNmYrzGtsYd3g9j5iDP8AimYYAesf79ohjbLG12XxC4nG5DyEnC88AsQ==} + '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} @@ -911,6 +917,10 @@ packages: resolution: {integrity: sha512-swASey0BxGs4/npZGWoiVDmnEyPvVFIRY6l2LVKL4rbiW8IhcIGDLfnb20Qo8U20itXlitAKPQ3MVTEbOGG5ZA==} engines: {node: '>=14'} + aedes-persistence-redis@11.2.2: + resolution: {integrity: sha512-kJRHG6FiykSdkniWJYDNYW892buif3D8iu5FrkgXsVuoF7A7rX3I1n4w6BV4Ocvz8thFaKBjWe3EAtOzOdEPIA==} + engines: {node: '>=20'} + aedes-persistence@10.2.2: resolution: {integrity: sha512-lbiViUGXxOyUakU01xvD758LGOLJ8T7PzpT3q2q8enMSMFSigy0dYQc0b7bgHcz96AYJjEraQSfVpXH7L546TA==} engines: {node: '>=20'} @@ -1204,6 +1214,10 @@ packages: resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} engines: {node: '>=0.8'} + cluster-key-slot@1.1.2: + resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==} + engines: {node: '>=0.10.0'} + color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} @@ -1318,6 +1332,10 @@ packages: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} + denque@2.1.0: + resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==} + engines: {node: '>=0.10'} + depd@2.0.0: resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} engines: {node: '>= 0.8'} @@ -1506,6 +1524,9 @@ packages: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} + event-lite@0.1.3: + resolution: {integrity: sha512-8qz9nOz5VeD2z96elrEKD2U433+L3DWdUdDkOINLGOJvx1GsMBbMn0aCeu28y8/e85A6mCigBiFlYMnTBEGlSw==} + event-target-shim@5.0.1: resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} engines: {node: '>=6'} @@ -1766,6 +1787,9 @@ packages: resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} engines: {node: '>= 0.4'} + hashlru@2.3.0: + resolution: {integrity: sha512-0cMsjjIC8I+D3M44pOQdsy0OHXGLVz6Z0beRuufhKa0KfaD2wGwAev6jILzXsd3/vpnNQJmWyZtIILqM1N+n5A==} + hasown@2.0.2: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} @@ -1823,6 +1847,9 @@ packages: resolution: {integrity: sha512-it4HyVAUTKBc6m8e1iXWvXSTdndF7HbdN713+kvLrymxTaU4AUBWrJ4vEooP+V7fexnVD3LKcBshjGGPefSMUQ==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + int64-buffer@0.1.10: + resolution: {integrity: sha512-v7cSY1J8ydZ0GyjUHqF+1bshJ6cnEVLo9EnjB8p+4HDRPZc9N5jjmvUV7NvEsqQOKyH0pmIBFWXVQbiS0+OBbA==} + internal-slot@1.1.0: resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} engines: {node: '>= 0.4'} @@ -1831,6 +1858,10 @@ packages: resolution: {integrity: sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==} engines: {node: '>= 0.10'} + ioredis@5.8.1: + resolution: {integrity: sha512-Qho8TgIamqEPdgiMadJwzRMW3TudIg6vpg4YONokGDudy4eqRIJtDbVX72pfLBcWxvbn3qm/40TyGUObdW4tLQ==} + engines: {node: '>=12.22.0'} + ip-address@10.0.1: resolution: {integrity: sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==} engines: {node: '>= 12'} @@ -1962,6 +1993,9 @@ packages: resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} engines: {node: '>=0.10.0'} + isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + isarray@2.0.5: resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} @@ -2118,9 +2152,15 @@ packages: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} + lodash.defaults@4.2.0: + resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==} + lodash.includes@4.3.0: resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==} + lodash.isarguments@3.1.0: + resolution: {integrity: sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==} + lodash.isboolean@3.0.3: resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==} @@ -2250,6 +2290,10 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + msgpack-lite@0.1.26: + resolution: {integrity: sha512-SZ2IxeqZ1oRFGo0xFGbvBJWMp3yLIY9rlIJyxy8CGrwZn1f0ZK4r6jV/AM1r0FZMDUkWkglOk/eeKIL9g77Nxw==} + hasBin: true + nanoid@3.3.11: resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -2602,6 +2646,14 @@ packages: resolution: {integrity: sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==} engines: {node: '>= 10.13.0'} + redis-errors@1.2.0: + resolution: {integrity: sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==} + engines: {node: '>=4'} + + redis-parser@3.0.0: + resolution: {integrity: sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==} + engines: {node: '>=4'} + reflect.getprototypeof@1.0.10: resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} engines: {node: '>= 0.4'} @@ -2799,6 +2851,9 @@ packages: stacktracey@2.1.8: resolution: {integrity: sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw==} + standard-as-callback@2.1.0: + resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==} + statuses@2.0.1: resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} engines: {node: '>= 0.8'} @@ -3482,6 +3537,8 @@ snapshots: '@humanwhocodes/retry@0.4.3': {} + '@ioredis/commands@1.4.0': {} + '@isaacs/cliui@8.0.2': dependencies: string-width: 5.1.2 @@ -4137,6 +4194,16 @@ snapshots: transitivePeerDependencies: - supports-color + aedes-persistence-redis@11.2.2: + dependencies: + aedes-persistence: 10.2.2 + hashlru: 2.3.0 + ioredis: 5.8.1 + msgpack-lite: 0.1.26 + qlobber: 8.0.1 + transitivePeerDependencies: + - supports-color + aedes-persistence@10.2.2: dependencies: aedes-packet: 3.0.0 @@ -4480,6 +4547,8 @@ snapshots: clone@1.0.4: {} + cluster-key-slot@1.1.2: {} + color-convert@2.0.1: dependencies: color-name: 1.1.4 @@ -4580,6 +4649,8 @@ snapshots: delayed-stream@1.0.0: {} + denque@2.1.0: {} + depd@2.0.0: {} dequal@2.0.3: {} @@ -4871,6 +4942,8 @@ snapshots: esutils@2.0.3: {} + event-lite@0.1.3: {} + event-target-shim@5.0.1: {} events-universal@1.0.1: @@ -5151,6 +5224,8 @@ snapshots: dependencies: has-symbols: 1.1.0 + hashlru@2.3.0: {} + hasown@2.0.2: dependencies: function-bind: 1.1.2 @@ -5198,6 +5273,8 @@ snapshots: ini@3.0.1: {} + int64-buffer@0.1.10: {} + internal-slot@1.1.0: dependencies: es-errors: 1.3.0 @@ -5206,6 +5283,20 @@ snapshots: interpret@2.2.0: {} + ioredis@5.8.1: + dependencies: + '@ioredis/commands': 1.4.0 + cluster-key-slot: 1.1.2 + debug: 4.4.3 + denque: 2.1.0 + lodash.defaults: 4.2.0 + lodash.isarguments: 3.1.0 + redis-errors: 1.2.0 + redis-parser: 3.0.0 + standard-as-callback: 2.1.0 + transitivePeerDependencies: + - supports-color + ip-address@10.0.1: {} ipaddr.js@2.2.0: {} @@ -5332,6 +5423,8 @@ snapshots: is-windows@1.0.2: {} + isarray@1.0.0: {} + isarray@2.0.5: {} isexe@2.0.0: {} @@ -5495,8 +5588,12 @@ snapshots: dependencies: p-locate: 5.0.0 + lodash.defaults@4.2.0: {} + lodash.includes@4.3.0: {} + lodash.isarguments@3.1.0: {} + lodash.isboolean@3.0.3: {} lodash.isinteger@4.0.4: {} @@ -5629,6 +5726,13 @@ snapshots: ms@2.1.3: {} + msgpack-lite@0.1.26: + dependencies: + event-lite: 0.1.3 + ieee754: 1.2.1 + int64-buffer: 0.1.10 + isarray: 1.0.0 + nanoid@3.3.11: {} nanoid@5.1.5: {} @@ -5967,6 +6071,12 @@ snapshots: dependencies: resolve: 1.22.10 + redis-errors@1.2.0: {} + + redis-parser@3.0.0: + dependencies: + redis-errors: 1.2.0 + reflect.getprototypeof@1.0.10: dependencies: call-bind: 1.0.8 @@ -6204,6 +6314,8 @@ snapshots: as-table: 1.0.55 get-source: 2.0.12 + standard-as-callback@2.1.0: {} + statuses@2.0.1: {} std-env@3.10.0: {} diff --git a/src/backbone.ts b/src/backbone.ts index 7436380..9336f62 100644 --- a/src/backbone.ts +++ b/src/backbone.ts @@ -49,7 +49,7 @@ class Backbone { const http = await this.server.getHttpServer(); http.listen({ port: this.config.http.port, host: '0.0.0.0' }); } - if (this.config.tcp) { + if (this.config.tcp.enabled) { const tcp = this.server.getTcpServer(); tcp.listen(this.config.tcp.port); } diff --git a/src/config/config.ts b/src/config/config.ts index 1bf6035..29fc08a 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -30,6 +30,21 @@ class Config { }; } + public get redis() { + const enabled = process.env.REDIS_ENABLED === 'true'; + const host = process.env.REDIS_HOST; + const port = process.env.REDIS_PORT ? parseInt(process.env.REDIS_PORT) : 6379; + const password = process.env.REDIS_PASSWORD; + const db = process.env.REDIS_DB ? parseInt(process.env.REDIS_DB) : 0; + return { + enabled, + host, + port, + password, + db, + }; + } + public get k8s() { const enabled = process.env.K8S_ENABLED === 'true'; return { diff --git a/src/dev.ts b/src/dev.ts index e3a2e63..1e4d15a 100644 --- a/src/dev.ts +++ b/src/dev.ts @@ -2,6 +2,8 @@ import { Backbone } from './backbone.ts'; process.env.JWT_SECRET = 'test'; process.env.ADMIN_TOKEN = 'admin'; process.env.API_ENABLED = 'true'; +process.env.WS_ENABLED = 'true'; +process.env.TCP_ENABLED = 'true'; const backbone = new Backbone(); await backbone.start(); diff --git a/src/global.d.ts b/src/global.d.ts index 2590397..1456d38 100644 --- a/src/global.d.ts +++ b/src/global.d.ts @@ -1,2 +1,14 @@ +// import 'aedes-persistence'; + // eslint-disable-next-line declare type ExplicitAny = any; + +declare module 'aedes-persistence-redis' { + // eslint-disable-next-line + export default any; +} + +declare module 'aedes-persist' { + // eslint-disable-next-line + export default any; +} diff --git a/src/server/server.ts b/src/server/server.ts index e88d01e..fb60e1a 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -16,6 +16,8 @@ import fastify, { type FastifyInstance } from 'fastify'; import fastifyWebSocket from '@fastify/websocket'; import { createWebSocketStream } from 'ws'; import fastifySensible from '@fastify/sensible'; +import redis from 'aedes-persistence-redis'; +import memory from 'aedes-persistence'; import { api } from '../api/api.ts'; @@ -49,6 +51,7 @@ class MqttServer { constructor(services: Services) { this.#services = services; this.#server = aedes.createBroker({ + persistence: this.#getPersistance(), authenticate: this.#authenticate, authorizePublish: this.#authorizePublish, authorizeSubscribe: this.#authorizeSubscribe, @@ -61,6 +64,19 @@ class MqttServer { return this.#server; } + #getPersistance = () => { + const config = this.#services.get(Config); + if (config.redis.enabled) { + return redis({ + host: config.redis.host, + port: config.redis.port, + password: config.redis.password, + db: config.redis.db, + }); + } + return (memory as ExplicitAny)(); + }; + #authenticate: AuthenticateHandler = async (client, username, password, callback) => { try { if (!username || !password) { diff --git a/tests/utils/utils.world.ts b/tests/utils/utils.world.ts index 1853c9a..0d80285 100644 --- a/tests/utils/utils.world.ts +++ b/tests/utils/utils.world.ts @@ -43,6 +43,13 @@ const createWorld = async (options: WorldOptions) => { enabled: false, port: 1883, }, + redis: { + enabled: false, + host: undefined, + password: undefined, + db: 0, + port: 0, + }, }); const accessTokens = backbone.services.get(JwtAuth); backbone.sessionProvider.register('token', accessTokens);