Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
589b6ad
feat: OAuth middleware with module loaders for identity/secrets/auth …
pyramation May 23, 2026
c6e6a43
feat(oauth): integrate DB settings for state cookie and error redirect
theothersideofgod May 26, 2026
317f9c4
fix(loaders): use config_secrets_org_module for encryptedSecrets loader
theothersideofgod May 26, 2026
ebe0daf
feat(express-context): add sessionCredentialsSchemaName to userAuth l…
theothersideofgod May 26, 2026
c310328
feat(express-context): add connectedAccounts loader
theothersideofgod May 26, 2026
496ed7a
feat(graphql-server): handle PgInterval in session cookie config
theothersideofgod May 26, 2026
b450bd0
feat(graphql-server): identity pre-check via connectedAccounts query
theothersideofgod May 26, 2026
2de79a9
fix(oauth): use JOIN to fetch client_secret instead of non-existent g…
theothersideofgod May 26, 2026
f0b1be4
fix(express-context): use config_secrets_user_module for app_secrets …
theothersideofgod May 26, 2026
58f153e
fix(express-context): use user_secrets instead of app_secrets
theothersideofgod May 29, 2026
fce5a68
feat(express-context): add identityProviderConfig loader
theothersideofgod May 29, 2026
f5be21a
refactor(oauth): use identityProviderConfig loader and remove duplicates
theothersideofgod May 29, 2026
3087ab4
fix: use platform_secrets instead of user_secrets for OAuth
theothersideofgods Jun 5, 2026
8c4a382
refactor: use loader function names for sign_in/sign_up_identity
theothersideofgods Jun 5, 2026
f19bc7b
fix(oauth): check identity existence before sign_in/sign_up
theothersideofgods Jun 5, 2026
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
1 change: 1 addition & 0 deletions graphql/server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
"@constructive-io/express-context": "workspace:^",
"@constructive-io/graphql-env": "workspace:^",
"@constructive-io/graphql-types": "workspace:^",
"@constructive-io/oauth": "workspace:^",
"@constructive-io/s3-utils": "workspace:^",
"@constructive-io/upload-names": "workspace:^",
"@constructive-io/url-domains": "workspace:^",
Expand Down
27 changes: 22 additions & 5 deletions graphql/server/src/middleware/cookie.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,28 @@
import type { Request, Response } from 'express';
import type { AuthSettings } from '../types';
import type { AuthSettings, PgInterval } from '../types';

export const SESSION_COOKIE_NAME = 'constructive_session';
export const DEVICE_TOKEN_COOKIE_NAME = 'constructive_device_token';

const DEVICE_TOKEN_MAX_AGE = 90 * 24 * 60 * 60; // 90 days in seconds

export const parseIntervalToSeconds = (interval: string | PgInterval | null | undefined): number | null => {
if (!interval) return null;
if (typeof interval === 'string') {
const parsed = parseInt(interval, 10);
return isNaN(parsed) ? null : parsed;
}
let totalSeconds = 0;
if (interval.years) totalSeconds += interval.years * 365 * 24 * 60 * 60;
if (interval.months) totalSeconds += interval.months * 30 * 24 * 60 * 60;
if (interval.days) totalSeconds += interval.days * 24 * 60 * 60;
if (interval.hours) totalSeconds += interval.hours * 60 * 60;
if (interval.minutes) totalSeconds += interval.minutes * 60;
if (interval.seconds) totalSeconds += interval.seconds;
if (interval.milliseconds) totalSeconds += interval.milliseconds / 1000;
return totalSeconds > 0 ? totalSeconds : null;
};

export interface CookieConfig {
secure: boolean;
sameSite: 'strict' | 'lax' | 'none';
Expand All @@ -25,11 +42,11 @@ export const getSessionCookieConfig = (
const DEFAULT_MAX_AGE = 86400; // 24 hours
let maxAge = DEFAULT_MAX_AGE;
if (rememberMe && authSettings?.rememberMeDuration) {
const parsed = parseInt(authSettings.rememberMeDuration, 10);
if (!isNaN(parsed)) maxAge = parsed;
const parsed = parseIntervalToSeconds(authSettings.rememberMeDuration);
if (parsed !== null) maxAge = parsed;
} else if (authSettings?.cookieMaxAge) {
const parsed = parseInt(authSettings.cookieMaxAge, 10);
if (!isNaN(parsed)) maxAge = parsed;
const parsed = parseIntervalToSeconds(authSettings.cookieMaxAge);
if (parsed !== null) maxAge = parsed;
}

return {
Expand Down
Loading
Loading