diff --git a/.changeset/pre.json b/.changeset/pre.json new file mode 100644 index 000000000..d7e973974 --- /dev/null +++ b/.changeset/pre.json @@ -0,0 +1,30 @@ +{ + "mode": "pre", + "tag": "hotfix", + "initialVersions": { + "@powersync/lib-service-mongodb": "0.6.0", + "@powersync/lib-service-postgres": "0.4.3", + "@powersync/lib-services-framework": "0.6.0", + "@powersync/service-module-core": "0.1.1", + "@powersync/service-module-mongodb": "0.9.1", + "@powersync/service-module-mongodb-storage": "0.9.5", + "@powersync/service-module-mysql": "0.6.5", + "@powersync/service-module-postgres": "0.13.1", + "@powersync/service-module-postgres-storage": "0.7.5", + "@powersync/service-jpgwire": "0.19.0", + "@powersync/service-jsonbig": "0.17.10", + "@powersync/service-rsocket-router": "0.1.0", + "@powersync/service-schema": "1.12.1", + "@powersync/service-core": "1.12.1", + "@powersync/service-core-tests": "0.9.5", + "@powersync/service-errors": "0.3.0", + "@powersync/service-sync-rules": "0.27.0", + "@powersync/service-types": "0.11.0", + "@powersync/service-image": "1.12.1", + "test-client": "0.1.40" + }, + "changesets": [ + "wild-llamas-melt", + "witty-cougars-build" + ] +} diff --git a/.changeset/wild-llamas-melt.md b/.changeset/wild-llamas-melt.md new file mode 100644 index 000000000..1cf607fd1 --- /dev/null +++ b/.changeset/wild-llamas-melt.md @@ -0,0 +1,5 @@ +--- +'@powersync/service-core': patch +--- + +Improve diagnostics in logs for JWKS timeouts. diff --git a/.changeset/witty-cougars-build.md b/.changeset/witty-cougars-build.md new file mode 100644 index 000000000..bfd72014c --- /dev/null +++ b/.changeset/witty-cougars-build.md @@ -0,0 +1,6 @@ +--- +'@powersync/service-core': patch +'@powersync/service-image': patch +--- + +Fix websocket auth errors not correctly propagating the details, previously resulting in generic "[PSYNC_S2106] Authentication required" messages. diff --git a/modules/module-core/CHANGELOG.md b/modules/module-core/CHANGELOG.md index e8211d609..22e5e0275 100644 --- a/modules/module-core/CHANGELOG.md +++ b/modules/module-core/CHANGELOG.md @@ -1,5 +1,13 @@ # @powersync/service-module-core +## 0.1.2-hotfix.0 + +### Patch Changes + +- Updated dependencies [2b8fb0e] +- Updated dependencies [2d3f10f] + - @powersync/service-core@1.12.2-hotfix.0 + ## 0.1.1 ### Patch Changes diff --git a/modules/module-core/package.json b/modules/module-core/package.json index 82f2eadcb..145c4a6a7 100644 --- a/modules/module-core/package.json +++ b/modules/module-core/package.json @@ -2,7 +2,7 @@ "name": "@powersync/service-module-core", "repository": "https://github.com/powersync-ja/powersync-service", "types": "dist/index.d.ts", - "version": "0.1.1", + "version": "0.1.2-hotfix.0", "main": "dist/index.js", "license": "FSL-1.1-Apache-2.0", "type": "module", diff --git a/modules/module-mongodb-storage/CHANGELOG.md b/modules/module-mongodb-storage/CHANGELOG.md index a34f6338c..1f81f3d4e 100644 --- a/modules/module-mongodb-storage/CHANGELOG.md +++ b/modules/module-mongodb-storage/CHANGELOG.md @@ -1,5 +1,13 @@ # @powersync/service-module-mongodb-storage +## 0.9.6-hotfix.0 + +### Patch Changes + +- Updated dependencies [2b8fb0e] +- Updated dependencies [2d3f10f] + - @powersync/service-core@1.12.2-hotfix.0 + ## 0.9.5 ### Patch Changes diff --git a/modules/module-mongodb-storage/package.json b/modules/module-mongodb-storage/package.json index 819594bdb..63dcbd407 100644 --- a/modules/module-mongodb-storage/package.json +++ b/modules/module-mongodb-storage/package.json @@ -2,7 +2,7 @@ "name": "@powersync/service-module-mongodb-storage", "repository": "https://github.com/powersync-ja/powersync-service", "types": "dist/index.d.ts", - "version": "0.9.5", + "version": "0.9.6-hotfix.0", "main": "dist/index.js", "license": "FSL-1.1-Apache-2.0", "type": "module", diff --git a/modules/module-mongodb/CHANGELOG.md b/modules/module-mongodb/CHANGELOG.md index db4745064..bc4c50492 100644 --- a/modules/module-mongodb/CHANGELOG.md +++ b/modules/module-mongodb/CHANGELOG.md @@ -1,5 +1,13 @@ # @powersync/service-module-mongodb +## 0.9.2-hotfix.0 + +### Patch Changes + +- Updated dependencies [2b8fb0e] +- Updated dependencies [2d3f10f] + - @powersync/service-core@1.12.2-hotfix.0 + ## 0.9.1 ### Patch Changes diff --git a/modules/module-mongodb/package.json b/modules/module-mongodb/package.json index 92e8ed848..a9b204046 100644 --- a/modules/module-mongodb/package.json +++ b/modules/module-mongodb/package.json @@ -2,7 +2,7 @@ "name": "@powersync/service-module-mongodb", "repository": "https://github.com/powersync-ja/powersync-service", "types": "dist/index.d.ts", - "version": "0.9.1", + "version": "0.9.2-hotfix.0", "main": "dist/index.js", "license": "FSL-1.1-Apache-2.0", "type": "module", diff --git a/modules/module-mysql/CHANGELOG.md b/modules/module-mysql/CHANGELOG.md index eb7530fce..d1806e30b 100644 --- a/modules/module-mysql/CHANGELOG.md +++ b/modules/module-mysql/CHANGELOG.md @@ -1,5 +1,13 @@ # @powersync/service-module-mysql +## 0.6.6-hotfix.0 + +### Patch Changes + +- Updated dependencies [2b8fb0e] +- Updated dependencies [2d3f10f] + - @powersync/service-core@1.12.2-hotfix.0 + ## 0.6.5 ### Patch Changes diff --git a/modules/module-mysql/package.json b/modules/module-mysql/package.json index 77783da80..ec9b0ca21 100644 --- a/modules/module-mysql/package.json +++ b/modules/module-mysql/package.json @@ -2,7 +2,7 @@ "name": "@powersync/service-module-mysql", "repository": "https://github.com/powersync-ja/powersync-service", "types": "dist/index.d.ts", - "version": "0.6.5", + "version": "0.6.6-hotfix.0", "license": "FSL-1.1-Apache-2.0", "main": "dist/index.js", "type": "module", diff --git a/modules/module-postgres-storage/CHANGELOG.md b/modules/module-postgres-storage/CHANGELOG.md index de3d61b56..aac419961 100644 --- a/modules/module-postgres-storage/CHANGELOG.md +++ b/modules/module-postgres-storage/CHANGELOG.md @@ -1,5 +1,14 @@ # @powersync/service-module-postgres-storage +## 0.7.6-hotfix.0 + +### Patch Changes + +- Updated dependencies [2b8fb0e] +- Updated dependencies [2d3f10f] + - @powersync/service-core@1.12.2-hotfix.0 + - @powersync/service-core-tests@0.9.6-hotfix.0 + ## 0.7.5 ### Patch Changes diff --git a/modules/module-postgres-storage/package.json b/modules/module-postgres-storage/package.json index e0697b15f..93b361dec 100644 --- a/modules/module-postgres-storage/package.json +++ b/modules/module-postgres-storage/package.json @@ -2,7 +2,7 @@ "name": "@powersync/service-module-postgres-storage", "repository": "https://github.com/powersync-ja/powersync-service", "types": "dist/@types/index.d.ts", - "version": "0.7.5", + "version": "0.7.6-hotfix.0", "main": "dist/index.js", "type": "module", "publishConfig": { diff --git a/modules/module-postgres/CHANGELOG.md b/modules/module-postgres/CHANGELOG.md index 7f805dc08..931008d58 100644 --- a/modules/module-postgres/CHANGELOG.md +++ b/modules/module-postgres/CHANGELOG.md @@ -1,5 +1,13 @@ # @powersync/service-module-postgres +## 0.13.2-hotfix.0 + +### Patch Changes + +- Updated dependencies [2b8fb0e] +- Updated dependencies [2d3f10f] + - @powersync/service-core@1.12.2-hotfix.0 + ## 0.13.1 ### Patch Changes diff --git a/modules/module-postgres/package.json b/modules/module-postgres/package.json index 824e8bdad..b56d0ef51 100644 --- a/modules/module-postgres/package.json +++ b/modules/module-postgres/package.json @@ -5,7 +5,7 @@ "publishConfig": { "access": "public" }, - "version": "0.13.1", + "version": "0.13.2-hotfix.0", "main": "dist/index.js", "license": "FSL-1.1-Apache-2.0", "type": "module", diff --git a/packages/schema/CHANGELOG.md b/packages/schema/CHANGELOG.md index 111fa6ec1..411ac4864 100644 --- a/packages/schema/CHANGELOG.md +++ b/packages/schema/CHANGELOG.md @@ -1,5 +1,7 @@ # @powersync/service-schema +## 1.12.2-hotfix.0 + ## 1.12.1 ## 1.12.0 diff --git a/packages/schema/package.json b/packages/schema/package.json index 521f16f70..5f1b05a32 100644 --- a/packages/schema/package.json +++ b/packages/schema/package.json @@ -1,6 +1,6 @@ { "name": "@powersync/service-schema", - "version": "1.12.1", + "version": "1.12.2-hotfix.0", "main": "dist/index.js", "types": "dist/index.d.ts", "license": "FSL-1.1-Apache-2.0", diff --git a/packages/service-core-tests/CHANGELOG.md b/packages/service-core-tests/CHANGELOG.md index a524835b6..57a43960e 100644 --- a/packages/service-core-tests/CHANGELOG.md +++ b/packages/service-core-tests/CHANGELOG.md @@ -1,5 +1,13 @@ # @powersync/service-core-tests +## 0.9.6-hotfix.0 + +### Patch Changes + +- Updated dependencies [2b8fb0e] +- Updated dependencies [2d3f10f] + - @powersync/service-core@1.12.2-hotfix.0 + ## 0.9.5 ### Patch Changes diff --git a/packages/service-core-tests/package.json b/packages/service-core-tests/package.json index d61c51838..c5f2bb338 100644 --- a/packages/service-core-tests/package.json +++ b/packages/service-core-tests/package.json @@ -5,7 +5,7 @@ "publishConfig": { "access": "public" }, - "version": "0.9.5", + "version": "0.9.6-hotfix.0", "main": "dist/index.js", "license": "FSL-1.1-Apache-2.0", "type": "module", diff --git a/packages/service-core/CHANGELOG.md b/packages/service-core/CHANGELOG.md index d2d454b74..743c2d3d0 100644 --- a/packages/service-core/CHANGELOG.md +++ b/packages/service-core/CHANGELOG.md @@ -1,5 +1,12 @@ # @powersync/service-core +## 1.12.2-hotfix.0 + +### Patch Changes + +- 2b8fb0e: Improve diagnostics in logs for JWKS timeouts. +- 2d3f10f: Fix websocket auth errors not correctly propagating the details, previously resulting in generic "[PSYNC_S2106] Authentication required" messages. + ## 1.12.1 ### Patch Changes diff --git a/packages/service-core/package.json b/packages/service-core/package.json index 521b264d8..d382e37d1 100644 --- a/packages/service-core/package.json +++ b/packages/service-core/package.json @@ -5,7 +5,7 @@ "publishConfig": { "access": "public" }, - "version": "1.12.1", + "version": "1.12.2-hotfix.0", "main": "dist/index.js", "license": "FSL-1.1-Apache-2.0", "type": "module", diff --git a/packages/service-core/src/auth/CachedKeyCollector.ts b/packages/service-core/src/auth/CachedKeyCollector.ts index 6ef0a67dc..fd45889a0 100644 --- a/packages/service-core/src/auth/CachedKeyCollector.ts +++ b/packages/service-core/src/auth/CachedKeyCollector.ts @@ -3,7 +3,7 @@ import timers from 'timers/promises'; import { KeySpec } from './KeySpec.js'; import { LeakyBucket } from './LeakyBucket.js'; import { KeyCollector, KeyResult } from './KeyCollector.js'; -import { AuthorizationError } from '@powersync/lib-services-framework'; +import { AuthorizationError, ErrorCode, logger } from '@powersync/lib-services-framework'; import { mapAuthConfigError } from './utils.js'; /** @@ -70,8 +70,21 @@ export class CachedKeyCollector implements KeyCollector { // e.g. in the case of waiting for error retries. // In the case of very slow requests, we don't wait for it to complete, but the // request can still complete in the background. - const timeout = timers.setTimeout(3000); - await Promise.race([this.refreshPromise, timeout]); + const WAIT_TIMEOUT_SECONDS = 3; + const timeout = timers.setTimeout(WAIT_TIMEOUT_SECONDS * 1000).then(() => { + throw new AuthorizationError(ErrorCode.PSYNC_S2204, `JWKS request failed`, { + cause: { message: `Key request timed out in ${WAIT_TIMEOUT_SECONDS}s`, name: 'AbortError' } + }); + }); + try { + await Promise.race([this.refreshPromise, timeout]); + } catch (e) { + if (e instanceof AuthorizationError) { + return { keys: this.currentKeys, errors: [...this.currentErrors, e] }; + } else { + throw e; + } + } } return { keys: this.currentKeys, errors: this.currentErrors }; @@ -102,7 +115,16 @@ export class CachedKeyCollector implements KeyCollector { this.currentErrors = errors; this.keyTimestamp = Date.now(); this.error = false; + + // Due to caching and background refresh behavior, errors are not always propagated to the request handler, + // so we log them here. + for (let error of errors) { + logger.error(`Soft key refresh error`, error); + } } catch (e) { + // Due to caching and background refresh behavior, errors are not always propagated to the request handler, + // so we log them here. + logger.error(`Hard key refresh error`, e); this.error = true; // No result - keep previous keys this.currentErrors = [mapAuthConfigError(e)]; diff --git a/packages/service-core/src/auth/KeySpec.ts b/packages/service-core/src/auth/KeySpec.ts index d6941b877..84ce6ee10 100644 --- a/packages/service-core/src/auth/KeySpec.ts +++ b/packages/service-core/src/auth/KeySpec.ts @@ -40,6 +40,20 @@ export class KeySpec { return this.source.kid; } + get description(): string { + let details: string[] = []; + details.push(`kid: ${this.kid ?? '*'}`); + details.push(`kty: ${this.source.kty}`); + if (this.source.alg != null) { + details.push(`alg: ${this.source.alg}`); + } + if (this.options.requiresAudience != null) { + details.push(`aud: ${this.options.requiresAudience.join(', ')}`); + } + + return `<${details.filter((x) => x != null).join(', ')}>`; + } + matchesAlgorithm(jwtAlg: string): boolean { if (this.source.alg) { return jwtAlg === this.source.alg; diff --git a/packages/service-core/src/auth/KeyStore.ts b/packages/service-core/src/auth/KeyStore.ts index aed06e799..6e48159c5 100644 --- a/packages/service-core/src/auth/KeyStore.ts +++ b/packages/service-core/src/auth/KeyStore.ts @@ -1,4 +1,4 @@ -import { logger, errors, AuthorizationError, ErrorCode } from '@powersync/lib-services-framework'; +import { AuthorizationError, ErrorCode, logger } from '@powersync/lib-services-framework'; import * as jose from 'jose'; import secs from '../util/secs.js'; import { JwtPayload } from './JwtPayload.js'; @@ -169,7 +169,7 @@ export class KeyStore { ErrorCode.PSYNC_S2101, 'Could not find an appropriate key in the keystore. The key is missing or no key matched the token KID', { - configurationDetails: `Known kid values: ${keys.map((key) => key.kid ?? '*').join(', ')}` + configurationDetails: `Known keys: ${keys.map((key) => key.description).join(', ')}` // tokenDetails automatically populated later } ); diff --git a/packages/service-core/src/auth/RemoteJWKSCollector.ts b/packages/service-core/src/auth/RemoteJWKSCollector.ts index 9a1d0fd8e..34984c8f2 100644 --- a/packages/service-core/src/auth/RemoteJWKSCollector.ts +++ b/packages/service-core/src/auth/RemoteJWKSCollector.ts @@ -49,9 +49,10 @@ export class RemoteJWKSCollector implements KeyCollector { private async getJwksData(): Promise { const abortController = new AbortController(); + const REQUEST_TIMEOUT_SECONDS = 30; const timeout = setTimeout(() => { abortController.abort(); - }, 30_000); + }, REQUEST_TIMEOUT_SECONDS * 1000); try { const res = await fetch(this.url, { @@ -71,11 +72,14 @@ export class RemoteJWKSCollector implements KeyCollector { return (await res.json()) as any; } catch (e) { + if (e instanceof Error && e.name === 'AbortError') { + e = { message: `Request timed out in ${REQUEST_TIMEOUT_SECONDS}s`, name: 'AbortError' }; + } throw new AuthorizationError(ErrorCode.PSYNC_S2204, `JWKS request failed`, { configurationDetails: `JWKS URL: ${this.url}`, // This covers most cases of FetchError // `cause: e` could lose the error message - cause: { message: e.message, code: e.code } + cause: { message: e.message, code: e.code, name: e.name } }); } finally { clearTimeout(timeout); diff --git a/packages/service-core/src/routes/configure-rsocket.ts b/packages/service-core/src/routes/configure-rsocket.ts index c40f161d8..b7c14b67c 100644 --- a/packages/service-core/src/routes/configure-rsocket.ts +++ b/packages/service-core/src/routes/configure-rsocket.ts @@ -38,7 +38,9 @@ export function configureRSocket(router: ReactiveSocketRouter, options: const extracted_token = getTokenFromHeader(token); if (extracted_token != null) { const { context, tokenError } = await generateContext(options.service_context, extracted_token); - if (context?.token_payload == null) { + if (tokenError != null) { + throw tokenError; + } else if (context?.token_payload == null) { throw new errors.AuthorizationError(ErrorCode.PSYNC_S2106, 'Authentication required'); } @@ -46,7 +48,6 @@ export function configureRSocket(router: ReactiveSocketRouter, options: token, user_agent, ...context, - token_error: tokenError, service_context: service_context as RouterServiceContext, logger: connectionLogger }; diff --git a/packages/service-core/src/routes/router.ts b/packages/service-core/src/routes/router.ts index cd4d58ab6..3298c6e6b 100644 --- a/packages/service-core/src/routes/router.ts +++ b/packages/service-core/src/routes/router.ts @@ -17,7 +17,6 @@ export type Context = { service_context: RouterServiceContext; token_payload?: JwtPayload; - token_error?: ServiceError; /** * Only on websocket endpoints. */ diff --git a/service/CHANGELOG.md b/service/CHANGELOG.md index 5d4917eea..22b21f2ee 100644 --- a/service/CHANGELOG.md +++ b/service/CHANGELOG.md @@ -1,5 +1,20 @@ # @powersync/service-image +## 1.12.2-hotfix.0 + +### Patch Changes + +- 2d3f10f: Fix websocket auth errors not correctly propagating the details, previously resulting in generic "[PSYNC_S2106] Authentication required" messages. +- Updated dependencies [2b8fb0e] +- Updated dependencies [2d3f10f] + - @powersync/service-core@1.12.2-hotfix.0 + - @powersync/service-module-core@0.1.2-hotfix.0 + - @powersync/service-module-mongodb@0.9.2-hotfix.0 + - @powersync/service-module-mongodb-storage@0.9.6-hotfix.0 + - @powersync/service-module-mysql@0.6.6-hotfix.0 + - @powersync/service-module-postgres@0.13.2-hotfix.0 + - @powersync/service-module-postgres-storage@0.7.6-hotfix.0 + ## 1.12.1 ### Patch Changes diff --git a/service/package.json b/service/package.json index 827615da2..52ffd5219 100644 --- a/service/package.json +++ b/service/package.json @@ -1,6 +1,6 @@ { "name": "@powersync/service-image", - "version": "1.12.1", + "version": "1.12.2-hotfix.0", "private": true, "license": "FSL-1.1-Apache-2.0", "type": "module", diff --git a/test-client/CHANGELOG.md b/test-client/CHANGELOG.md index f01486d57..3c9fd4548 100644 --- a/test-client/CHANGELOG.md +++ b/test-client/CHANGELOG.md @@ -1,5 +1,13 @@ # test-client +## 0.1.41-hotfix.0 + +### Patch Changes + +- Updated dependencies [2b8fb0e] +- Updated dependencies [2d3f10f] + - @powersync/service-core@1.12.2-hotfix.0 + ## 0.1.40 ### Patch Changes diff --git a/test-client/package.json b/test-client/package.json index baf192dda..8c54a73ef 100644 --- a/test-client/package.json +++ b/test-client/package.json @@ -2,7 +2,7 @@ "name": "test-client", "repository": "https://github.com/powersync-ja/powersync-service", "private": true, - "version": "0.1.40", + "version": "0.1.41-hotfix.0", "main": "dist/index.js", "bin": "dist/bin.js", "license": "Apache-2.0",