Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .changeset/pre.json
Original file line number Diff line number Diff line change
@@ -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"
]
}
5 changes: 5 additions & 0 deletions .changeset/wild-llamas-melt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@powersync/service-core': patch
---

Improve diagnostics in logs for JWKS timeouts.
6 changes: 6 additions & 0 deletions .changeset/witty-cougars-build.md
Original file line number Diff line number Diff line change
@@ -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.
8 changes: 8 additions & 0 deletions modules/module-core/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# @powersync/service-module-core

## 0.1.2-hotfix.0

### Patch Changes

- Updated dependencies [2b8fb0e]
- Updated dependencies [2d3f10f]
- @powersync/[email protected]

## 0.1.1

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion modules/module-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
8 changes: 8 additions & 0 deletions modules/module-mongodb-storage/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# @powersync/service-module-mongodb-storage

## 0.9.6-hotfix.0

### Patch Changes

- Updated dependencies [2b8fb0e]
- Updated dependencies [2d3f10f]
- @powersync/[email protected]

## 0.9.5

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion modules/module-mongodb-storage/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
8 changes: 8 additions & 0 deletions modules/module-mongodb/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# @powersync/service-module-mongodb

## 0.9.2-hotfix.0

### Patch Changes

- Updated dependencies [2b8fb0e]
- Updated dependencies [2d3f10f]
- @powersync/[email protected]

## 0.9.1

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion modules/module-mongodb/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
8 changes: 8 additions & 0 deletions modules/module-mysql/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# @powersync/service-module-mysql

## 0.6.6-hotfix.0

### Patch Changes

- Updated dependencies [2b8fb0e]
- Updated dependencies [2d3f10f]
- @powersync/[email protected]

## 0.6.5

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion modules/module-mysql/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
9 changes: 9 additions & 0 deletions modules/module-postgres-storage/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# @powersync/service-module-postgres-storage

## 0.7.6-hotfix.0

### Patch Changes

- Updated dependencies [2b8fb0e]
- Updated dependencies [2d3f10f]
- @powersync/[email protected]
- @powersync/[email protected]

## 0.7.5

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion modules/module-postgres-storage/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": {
Expand Down
8 changes: 8 additions & 0 deletions modules/module-postgres/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# @powersync/service-module-postgres

## 0.13.2-hotfix.0

### Patch Changes

- Updated dependencies [2b8fb0e]
- Updated dependencies [2d3f10f]
- @powersync/[email protected]

## 0.13.1

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion modules/module-postgres/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
2 changes: 2 additions & 0 deletions packages/schema/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# @powersync/service-schema

## 1.12.2-hotfix.0

## 1.12.1

## 1.12.0
Expand Down
2 changes: 1 addition & 1 deletion packages/schema/package.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
8 changes: 8 additions & 0 deletions packages/service-core-tests/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# @powersync/service-core-tests

## 0.9.6-hotfix.0

### Patch Changes

- Updated dependencies [2b8fb0e]
- Updated dependencies [2d3f10f]
- @powersync/[email protected]

## 0.9.5

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/service-core-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
7 changes: 7 additions & 0 deletions packages/service-core/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion packages/service-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
28 changes: 25 additions & 3 deletions packages/service-core/src/auth/CachedKeyCollector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';

/**
Expand Down Expand Up @@ -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 };
Expand Down Expand Up @@ -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)];
Expand Down
14 changes: 14 additions & 0 deletions packages/service-core/src/auth/KeySpec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions packages/service-core/src/auth/KeyStore.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -169,7 +169,7 @@ export class KeyStore<Collector extends KeyCollector = KeyCollector> {
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
}
);
Expand Down
8 changes: 6 additions & 2 deletions packages/service-core/src/auth/RemoteJWKSCollector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,10 @@ export class RemoteJWKSCollector implements KeyCollector {

private async getJwksData(): Promise<any> {
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, {
Expand All @@ -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);
Expand Down
5 changes: 3 additions & 2 deletions packages/service-core/src/routes/configure-rsocket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,16 @@ export function configureRSocket(router: ReactiveSocketRouter<Context>, 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');
}

return {
token,
user_agent,
...context,
token_error: tokenError,
service_context: service_context as RouterServiceContext,
logger: connectionLogger
};
Expand Down
1 change: 0 additions & 1 deletion packages/service-core/src/routes/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ export type Context = {
service_context: RouterServiceContext;

token_payload?: JwtPayload;
token_error?: ServiceError;
/**
* Only on websocket endpoints.
*/
Expand Down
Loading