Skip to content

Commit a44082f

Browse files
authored
Merge branch 'main' into peter/eng-8578-ensure-best-practices-with-log-masking-redaction
2 parents 75a9cbc + 8980fa8 commit a44082f

File tree

23 files changed

+922
-511
lines changed

23 files changed

+922
-511
lines changed

.github/workflows/protographic.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ jobs:
4141
- name: Lint
4242
run: pnpm run --filter ./protographic lint
4343

44-
- name: Upload integration results to Codecov
44+
- name: Upload test results to Codecov
4545
uses: ./.github/actions/codecov-upload-pr
4646
with:
4747
artifact-name: protographic-tests-coverage

cli/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ Binaries are attached to the github release otherwise all images can be found [h
44
All notable changes to this project will be documented in this file.
55
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
66

7+
## [0.102.6](https://github.com/wundergraph/cosmo/compare/[email protected]@0.102.6) (2025-12-16)
8+
9+
### Bug Fixes
10+
11+
* resolve js-yaml vulnerabilities ([#2415](https://github.com/wundergraph/cosmo/issues/2415)) ([7734754](https://github.com/wundergraph/cosmo/commit/7734754c098a7b85ada9f78771610ebd2754cffe)) (@pepol)
12+
713
## [0.102.5](https://github.com/wundergraph/cosmo/compare/[email protected]@0.102.5) (2025-12-15)
814

915
**Note:** Version bump only for package wgc

cli/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "wgc",
3-
"version": "0.102.5",
3+
"version": "0.102.6",
44
"description": "The official CLI tool to manage the GraphQL Federation Platform Cosmo",
55
"type": "module",
66
"main": "dist/src/index.js",
@@ -66,7 +66,7 @@
6666
"graphql": "16.9.0",
6767
"https-proxy-agent": "7.0.5",
6868
"inquirer": "9.2.7",
69-
"js-yaml": "4.1.0",
69+
"js-yaml": "4.1.1",
7070
"jwt-decode": "3.1.2",
7171
"lodash-es": "4.17.21",
7272
"log-symbols": "5.1.0",

codecov.yaml

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,25 +14,33 @@ coverage:
1414
flags:
1515
router:
1616
paths:
17-
- router
17+
- router/
1818
carryforward: true
1919
cli:
2020
paths:
21-
- cli
21+
- cli/
2222
carryforward: true
2323
studio:
2424
paths:
25-
- studio
25+
- studio/
2626
carryforward: true
2727
graphqlmetrics:
2828
paths:
29-
- graphqlmetrics
29+
- graphqlmetrics/
3030
carryforward: true
3131
controlplane:
3232
paths:
33-
- controlplane
33+
- controlplane/
3434
carryforward: true
3535
composition:
3636
paths:
37-
- composition
38-
carryforward: true
37+
- composition/
38+
carryforward: true
39+
40+
comment:
41+
layout: "diff, flags, files"
42+
behavior: default
43+
require_changes: false
44+
require_base: no
45+
require_head: yes
46+
show_carryforward_flags: true

controlplane/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ Binaries are attached to the github release otherwise all images can be found [h
44
All notable changes to this project will be documented in this file.
55
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
66

7+
# [0.182.0](https://github.com/wundergraph/cosmo/compare/[email protected]@0.182.0) (2025-12-16)
8+
9+
### Features
10+
11+
* validate session cookie ([#2406](https://github.com/wundergraph/cosmo/issues/2406)) ([13ec2dd](https://github.com/wundergraph/cosmo/commit/13ec2dd5240e52c7774d251db5fd79e23905f6c2)) (@wilsonrivera)
12+
713
# [0.181.0](https://github.com/wundergraph/cosmo/compare/[email protected]@0.181.0) (2025-12-15)
814

915
### Bug Fixes

controlplane/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "controlplane",
3-
"version": "0.181.0",
3+
"version": "0.182.0",
44
"private": true,
55
"description": "WunderGraph Cosmo Controlplane",
66
"type": "module",

controlplane/src/core/auth-utils.ts

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import axios from 'axios';
44
import { eq } from 'drizzle-orm';
55
import { PostgresJsDatabase } from 'drizzle-orm/postgres-js';
66
import { EnumStatusCode } from '@wundergraph/cosmo-connect/dist/common/common_pb';
7+
import { addSeconds } from 'date-fns';
78
import { PKCECodeChallenge, UserInfoEndpointResponse, UserSession } from '../types/index.js';
89
import * as schema from '../db/schema.js';
910
import { sessions } from '../db/schema.js';
@@ -38,7 +39,7 @@ export type AuthUtilsOptions = {
3839
};
3940
};
4041

41-
const tokenExpirationWindowSkew = 60 * 5;
42+
const tokenExpirationWindowSkew = 60 * 5; // 5 minutes
4243
const pkceMaxAgeSec = 60 * 15; // 15 minutes
4344
const pkceCodeAlgorithm = 'S256';
4445
const scope = 'openid profile email';
@@ -298,6 +299,18 @@ export default class AuthUtils {
298299
};
299300
}
300301

302+
public static isSessionExpired(session: { createdAt: Date; updatedAt: Date | null; expiresAt: Date }): boolean {
303+
const now = new Date();
304+
if (session.expiresAt <= now) {
305+
// Session reached end-of-life
306+
return true;
307+
}
308+
309+
const sessionLastUpdatedOrCreation = session.updatedAt ?? session.createdAt;
310+
const sessionExpiresAt = addSeconds(sessionLastUpdatedOrCreation, DEFAULT_SESSION_MAX_AGE_SEC);
311+
return sessionExpiresAt <= now;
312+
}
313+
301314
/**
302315
* renewSession renews the user session if the access token is expired.
303316
* If the refresh token is expired, an error is thrown.
@@ -327,30 +340,27 @@ export default class AuthUtils {
327340
throw new AuthenticationError(EnumStatusCode.ERROR_NOT_AUTHENTICATED, 'Refresh token expired');
328341
}
329342

330-
// The session expiration is relative to the creation time
331-
const baseMs = userSession.createdAt.getTime();
332-
const expiresAtMs = baseMs + DEFAULT_SESSION_MAX_AGE_SEC * 1000;
333-
const sessionExpiresDate = new Date(expiresAtMs);
334-
const remainingSeconds = Math.max(0, Math.floor((expiresAtMs - Date.now()) / 1000));
335-
336-
if (remainingSeconds <= 0) {
343+
// The session expiration is relative
344+
if (AuthUtils.isSessionExpired(userSession)) {
337345
// Absolute session lifetime has elapsed; do not renew.
338346
throw new AuthenticationError(EnumStatusCode.ERROR_NOT_AUTHENTICATED, 'Session expired');
339347
}
340348

341349
// Refresh the access token with the refresh token
342350
// The method will throw an error if the request fails
351+
const now = new Date();
343352
const { accessToken, refreshToken, idToken } = await this.refreshToken(userSession.refreshToken);
344353

345354
// Update active session
355+
const expiresAt = addSeconds(now, DEFAULT_SESSION_MAX_AGE_SEC);
346356
const updatedSessions = await this.db
347357
.update(sessions)
348358
.set({
349359
accessToken,
350360
refreshToken,
351-
expiresAt: sessionExpiresDate,
361+
expiresAt,
352362
idToken,
353-
updatedAt: new Date(),
363+
updatedAt: now,
354364
})
355365
.where(eq(sessions.id, sessionId))
356366
.returning()
@@ -363,7 +373,7 @@ export default class AuthUtils {
363373
const newUserSession = updatedSessions[0];
364374

365375
const jwt = await encrypt<UserSession>({
366-
maxAgeInSeconds: remainingSeconds,
376+
maxAgeInSeconds: DEFAULT_SESSION_MAX_AGE_SEC,
367377
token: {
368378
iss: userSession.userId,
369379
sessionId: newUserSession.id,
@@ -372,7 +382,7 @@ export default class AuthUtils {
372382
});
373383

374384
// Update the session cookie
375-
this.createSessionCookie(res, jwt, sessionExpiresDate);
385+
this.createSessionCookie(res, jwt, expiresAt);
376386

377387
return newUserSession;
378388
}

controlplane/src/core/build-server.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ export default async function build(opts: BuildConfig) {
246246
const apiKeyAuth = new ApiKeyAuthenticator(fastify.db, organizationRepository);
247247
const userRepo = new UserRepository(logger, fastify.db);
248248
const apiKeyRepository = new ApiKeyRepository(fastify.db);
249-
const webAuth = new WebSessionAuthenticator(opts.auth.secret, userRepo);
249+
const webAuth = new WebSessionAuthenticator(fastify.db, opts.auth.secret, userRepo);
250250
const graphKeyAuth = new GraphApiTokenAuthenticator(opts.auth.secret);
251251
const accessTokenAuth = new AccessTokenAuthenticator(organizationRepository, authUtils);
252252
const authenticator = new Authentication(webAuth, apiKeyAuth, accessTokenAuth, graphKeyAuth, organizationRepository);

0 commit comments

Comments
 (0)