Skip to content

fix: Updated discriminator to take application name along with sign o…#469

Open
sagar-okta wants to merge 3 commits intomasterfrom
sv-bug-fix-OKTA-1100279
Open

fix: Updated discriminator to take application name along with sign o…#469
sagar-okta wants to merge 3 commits intomasterfrom
sv-bug-fix-OKTA-1100279

Conversation

@sagar-okta
Copy link
Copy Markdown
Contributor

@sagar-okta sagar-okta commented Feb 3, 2026

PR Checklist

Please check if your PR fulfills the following requirements:

  • The commit message follows our guidelines
  • Tests for the changes have been added (for bug fixes / features)
  • Docs have been added / updated (for bug fixes / features)

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Adding Tests
  • Build related changes
  • CI related changes
  • Documentation changes
  • Other... Please describe:

What is the current behavior?

Issue Number: https://oktainc.atlassian.net/browse/OKTA-1100279

What is the new behavior?

In the current implementation the discriminator uses only the sign on mode, however for some cases we need to consider name of the application as well for discriminator. This change enables it to take the application name as discriminator.

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

Reviewers

@sagar-okta sagar-okta marked this pull request as ready for review February 24, 2026 05:16
@sagar-okta
Copy link
Copy Markdown
Contributor Author

Issue: During serialization the params were getting stripped which do not have signon mode as SAML type. This resulted in error during create application for application types other than signon mode SAML

Fix: Added application type as discriminator along with signon mode. So that the params are not stripped.

Copy link
Copy Markdown

@aniket-okta aniket-okta left a comment

Choose a reason for hiding this comment

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

Review: fix: Updated discriminator to take application name along with sign on mode

The root cause analysis is correct — OIN apps with signOnMode: SAML_2_0 were resolving to SamlApplication instead of their concrete subtype, causing app-specific fields to be stripped before serialization and producing the Okta API domain validation error. The name-based secondary discriminator is the right approach.

However there are 3 blocking issues and several significant concerns that need to be addressed before this can merge. See inline comments for details.

Blocking

  • ZoomUsApplication is missing from both the typeMap and oinAppMappings — same bug will remain for ZoomUs apps
  • fixGenerated.cjs targets ObjectSerializer.ts but the runtime file is .js — the patch will silently skip on next codegen, causing the bug to silently reappear
  • No tests added for the bug fix; the existing type-safety test was weakened instead of updated

Significant

  • Name-based discriminator check runs before the OAS spec-defined mapping check — ordering should be inverted
  • Spurious /// <reference types="node" /> line added to http.d.ts with no justification
  • Fragile regex in fixGenerated.cjs will silently no-op if generator whitespace changes

'salesforce': 'SalesforceApplication',
'slack': 'SlackApplication',
'trendmicroapexoneservice': 'TrendMicroApexOneServiceApplication',
'zscaler_byz': 'ZscalerbyzApplication'
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[Blocking] ZoomUsApplication is missing from oinAppMappings.

ZoomUsApplication.js receives the id/lastUpdated/_links attribute additions in this PR, but 'zoomus' is never added here. Users creating a ZoomUs application with signOnMode: 'SAML_2_0' will hit the exact same stripping bug.

Add the missing entry:

'zoomus': 'ZoomUsApplication'

};

// Read the ObjectSerializer.ts file
const objSerializerPath = 'src/generated/models/ObjectSerializer.ts';
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[Blocking] Wrong file extension — this fix will silently no-op on the next code regeneration.

The target path is ObjectSerializer.ts, but the generated runtime file in this SDK is ObjectSerializer.js. The fs.existsSync guard on line 265 will evaluate to false after a fresh codegen run, log a warning that is easy to miss, and return { modified: false, skipped: true } — silently leaving the bug in place for every future consumer who regenerates the SDK.

Change to:

const objSerializerPath = 'src/generated/models/ObjectSerializer.js';

}

// 2. Modify findCorrectType to check 'name' property for Application types with SAML signOnMode
const findCorrectTypeRegex = /(if \(mapping != undefined && mapping\[discriminatorType\]\) \{\s+return mapping\[discriminatorType\];[^\}]+\})/;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[Significant] This regex is fragile and will silently fail on generator whitespace changes.

The [^\}]+ atom does not account for nested braces inside the matched block. If the code generator changes indentation, adds a log statement, or nests another conditional inside the target if block, this regex will silently fail to match. Because modifications is only incremented on a successful match, a failed patch won't throw — it will just leave the discriminator logic unpatched with no visible error.

Consider either:

  1. Anchoring on a more stable, unique surrounding string (e.g. the comment block you own), or
  2. Throwing explicitly if findCorrectTypeMatch is null:
if (!findCorrectTypeMatch) {
  throw new Error('fixApplicationDiscriminator: could not find findCorrectType target — ObjectSerializer structure may have changed');
}

'__salesforce': SalesforceApplication_1.SalesforceApplication,
'__slack': SlackApplication_1.SlackApplication,
'__trendmicroapexoneservice': TrendMicroApexOneServiceApplication_1.TrendMicroApexOneServiceApplication,
'__zscaler_byz': ZscalerbyzApplication_1.ZscalerbyzApplication,
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[Blocking] ZoomUsApplication is missing from the typeMap.

ZoomUsApplication.js is updated in this PR but '__zoomus' is never registered in the typeMap. Without this entry, ObjectSerializer cannot resolve zoomus apps to ZoomUsApplication and will fall back to SamlApplication, preserving the original bug.

Add after this line:

'__zoomus': ZoomUsApplication_1.ZoomUsApplication,

const prefixedDiscriminatorType = `__${discriminatorType}`;
const manuallyDiscriminatedType = typeMap[prefixedTypeDiscriminatorType] || typeMap[prefixedDiscriminatorType];
// For Application type, also check 'name' property for OIN apps
if (expectedType === 'Application' && data['name']) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[Significant] The name-based check runs before the OAS spec-defined discriminator mapping, inverting the intended priority.

As written, any Application whose name field matches a key in typeMap will always resolve via name — even if the spec's authoritative mapping[discriminatorType] provides a more specific or different answer. The name check should act as a tiebreaker for the ambiguous SAML_2_0 case only, not unconditionally override the spec mapping.

Consider restructuring:

// Check OAS spec mapping first (authoritative)
if (mapping != undefined && mapping[discriminatorType]) {
    return mapping[discriminatorType];
}
// Fall back to name-based lookup for OIN apps where signOnMode is ambiguous
if (expectedType === 'Application' && data['name']) {
    const nameMapping = typeMap[`__${data['name']}`];
    if (nameMapping) {
        return `__${data['name']}`;
    }
}

expect(app).to.be.instanceOf(Application);
// Application objects can be either base Application type or specific OIN app types
// (GoogleApplication, Office365Application, etc.) which have their own schemas
expect(app).to.exist;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[Blocking] The instanceof Application assertion was removed instead of updated, weakening type-safety coverage.

The original expect(app).to.be.instanceOf(Application) was catching deserialization regressions (e.g. plain objects returned instead of typed instances). The replacement (expect(app).to.exist) only checks for truthiness — it would pass even if the serializer returned a raw {} object.

The correct fix is to assert against the expected concrete type. Since OIN apps now resolve to their subclasses, use a union check:

const knownAppTypes = [
  Application, GoogleApplication, Office365Application,
  Org2OrgApplication, SalesforceApplication, SlackApplication,
  TrendMicroApexOneServiceApplication, ZoomUsApplication, ZscalerbyzApplication
];
expect(knownAppTypes.some(T => app instanceof T)).to.be.true;

This preserves the original intent while accommodating the new subtype resolution.

/// <reference types="node" />
/// <reference types="node" />
/// <reference types="node" />
/// <reference types="node" />
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[Minor] Spurious duplicate /// <reference types="node" /> directive.

There are now 5 identical triple-slash directives where 3 existed before. This looks like a code-generation artifact that was accidentally committed. It has no functional impact but inflates the diff, making it harder to review genuine changes. Please revert this file to its pre-PR state.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants