Skip to content

Export a shared Session type for authenticate/refresh result payloads #1584

@mjdavidson

Description

@mjdavidson

Context

When building an app that stores the authenticated session in its own state (e.g. a Hono context variable, a request-scoped store, or a React provider), I want a single named type that describes "the user-facing payload from a successful `session.authenticate()` or `session.refresh()`" — i.e. the fields it's safe and useful to expose to my app code.

Today the SDK exports:

  • `SessionCookieData` — Pick<AuthenticationResponse, 'accessToken' | 'authenticationMethod' | 'impersonator' | 'organizationId' | 'refreshToken' | 'user'>. This is the sealed-cookie shape and intentionally omits role, permissions, roles, entitlements, featureFlags.
  • `AuthenticateWithSessionCookieSuccessResponse` — includes authenticated: true, accessToken, sessionId, authenticationMethod alongside the user-facing fields. Useful as a return type, but heavyweight for app state.
  • `RefreshSessionSuccessResponse` — Omit<AuthenticateWithSessionCookieSuccessResponse, 'accessToken'> & { ... session?: AuthenticationResponse }.

There's no single exported type that says "this is the session payload your app should hold onto." Today, consumers either roll their own:

interface SessionData {
  user: User;
  organizationId?: string;
  role?: string;
  permissions?: string[];
  impersonator?: Impersonator | null;
}

…or write a hand-rolled Omit<AuthenticateWithSessionCookieSuccessResponse, 'authenticated' | 'accessToken' | 'sessionId' | 'authenticationMethod'>, which is fragile and drifts as the SDK grows new claims (e.g. roles, entitlements, featureFlags).

Proposal

Export a Session interface (name TBD — SessionPayload, AuthenticatedSession, etc. also fine) representing the user-facing claims:

export interface Session {
  user: User;
  organizationId?: string;
  role?: string;
  roles?: string[];
  permissions?: string[];
  entitlements?: string[];
  featureFlags?: string[];
  impersonator?: Impersonator;
}

Both AuthenticateWithSessionCookieSuccessResponse and RefreshSessionSuccessResponse would extend it (or compose it via intersection), keeping their existing extra fields. Consumers could then write:

import type { Session } from '@workos-inc/node';

type AppEnv = {
  Variables: {
    session: Session;
  };
};

…and assign authResult / refreshResult directly with no casts and no risk of drift when new JWT claims land in the SDK.

Why this is worth doing

  • One fewer paper-cut for SDK consumers — most non-trivial apps that hold session state will benefit
  • The "right" shape is centralized in the SDK rather than re-derived by every consumer
  • New claims (e.g. entitlements, featureFlags) automatically flow into consumer apps without TS errors
  • Pairs naturally with SessionCookieData (the sealed-cookie shape) — they're two clearly-distinguished concerns

References

Came up while reviewing a custom-UI example app for impersonation support — landed at workos/workos-custom-ui-authkit-example#9, where the original code used as unknown as SessionData to bridge the gap. Turns out the cast wasn't strictly required because the success response is structurally compatible with a hand-rolled interface, but having an officially-exported type would make the pattern obvious and resilient to future SDK changes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions