Skip to content

Preserve sso context in authentication event deserialisation#1487

Open
smorimoto wants to merge 2 commits intoworkos:mainfrom
smorimoto:fix-authentication-event-sso-field
Open

Preserve sso context in authentication event deserialisation#1487
smorimoto wants to merge 2 commits intoworkos:mainfrom
smorimoto:fix-authentication-event-sso-field

Conversation

@smorimoto
Copy link
Contributor

Summary

  • Adds AuthenticationEventSso / AuthenticationEventSsoResponse interfaces for the nested sso object present in SSO authentication events
  • Adds deserializeAuthenticationEventSso helper to map connection_id, organization_id, and session_id
  • Updates deserializeAuthenticationEvent to preserve the sso context

The Events API documentation for authentication events includes an sso object (with connection_id, organization_id, and optionally session_id) in authentication.sso_* event data, but the deserialiser was silently dropping it.

Design note

deserializeAuthenticationEventSso takes a non-optional AuthenticationEventSsoResponse argument and is called via the spread pattern at the call site:

...(authenticationEvent.sso && {
  sso: deserializeAuthenticationEventSso(authenticationEvent.sso),
}),

This ensures that when the sso object is absent (non-SSO events), the sso key is not present in the deserialised output at all, rather than being set to undefined. The same approach is applied to the optional sessionId field within the sso object, which is only present on successful SSO authentications. This avoids polluting the output with keys that carry no value, keeping it consistent with what the Events API actually returns.

This follows the existing deserializeOauthTokens pattern used in the codebase for nested optional objects that require snake_case → camelCase conversion.

Test plan

  • TypeScript type check passes (npx tsc --noEmit)
  • All existing tests pass (npm test)
  • Linter and formatter pass

@smorimoto smorimoto requested a review from a team as a code owner February 13, 2026 18:11
@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 13, 2026

Greptile Overview

Greptile Summary

Preserves SSO context (connection_id, organization_id, session_id) in authentication events by adding proper deserialization support.

Changes:

  • Added AuthenticationEventSso and AuthenticationEventSsoResponse interfaces to represent the nested SSO object
  • Created deserializeAuthenticationEventSso helper to transform snake_case API fields to camelCase
  • Updated deserializeAuthenticationEvent to conditionally include SSO data using the spread pattern
  • The implementation ensures absent sso objects remain absent (not undefined) in the output, matching API behavior

Pattern consistency:
The spread pattern ...(authenticationEvent.sso && { sso: ... }) matches existing codebase conventions (e.g., organization-membership.serializer.ts:20). This approach keeps the deserialized output clean by omitting keys entirely when the source data doesn't include them.

Confidence Score: 5/5

  • Safe to merge with no issues found
  • The implementation correctly preserves SSO context from authentication events using established patterns from the codebase (spread operator with conditional inclusion). The type definitions are properly structured with separate Response and deserialized interfaces. The code follows existing conventions seen in other serializers like organization-membership.serializer.ts.
  • No files require special attention

Important Files Changed

Filename Overview
src/user-management/interfaces/authentication-event.interface.ts Added type-safe interfaces for SSO context (AuthenticationEventSso and AuthenticationEventSsoResponse) with proper snake_case to camelCase mappings
src/user-management/serializers/authentication-event.serializer.ts Added deserializeAuthenticationEventSso helper and integrated it into deserializeAuthenticationEvent using the spread pattern to conditionally include SSO data

Sequence Diagram

sequenceDiagram
    participant API as WorkOS Events API
    participant Deserializer as deserializeEvent
    participant AuthEvent as deserializeAuthenticationEvent
    participant SSOHelper as deserializeAuthenticationEventSso
    participant Client as SDK Consumer

    API->>Deserializer: AuthenticationEventResponse (snake_case)
    Deserializer->>AuthEvent: event.data (snake_case)
    
    alt SSO authentication event with sso object
        AuthEvent->>SSOHelper: authenticationEvent.sso
        SSOHelper->>SSOHelper: Transform connection_id → connectionId
        SSOHelper->>SSOHelper: Transform organization_id → organizationId
        SSOHelper->>SSOHelper: Conditionally include session_id → sessionId
        SSOHelper-->>AuthEvent: AuthenticationEventSso
        AuthEvent->>AuthEvent: Conditionally spread sso object
    else Non-SSO event (no sso object)
        AuthEvent->>AuthEvent: Skip sso field entirely
    end
    
    AuthEvent-->>Deserializer: AuthenticationEvent (camelCase)
    Deserializer-->>Client: Fully deserialized Event
Loading

Last reviewed commit: 84c4670

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 files reviewed, no comments

Edit Code Review Agent Settings | Greptile

The Events API includes an sso object (with connection_id,
organization_id, and optionally session_id) in authentication.sso_*
event data, but the deserialiser was silently dropping it.

Adds AuthenticationEventSso and AuthenticationEventSsoResponse
interfaces, and a deserializeAuthenticationEventSso helper that
follows the existing deserializeOauthTokens pattern for nested
optional objects with snake_case conversion.
Switch from truthy checks (&&) to explicit !== undefined checks so
that falsy values like empty strings are not incorrectly omitted.
@smorimoto smorimoto force-pushed the fix-authentication-event-sso-field branch from a726c31 to 9541927 Compare February 13, 2026 19:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant