Skip to content

[W-23059473] Introduce SFOAuthErrorCode enum for token endpoint error responses - #4094

Merged
wmathurin merged 3 commits into
forcedotcom:devfrom
wmathurin:oauth-error-code-enum
Jul 7, 2026
Merged

[W-23059473] Introduce SFOAuthErrorCode enum for token endpoint error responses#4094
wmathurin merged 3 commits into
forcedotcom:devfrom
wmathurin:oauth-error-code-enum

Conversation

@wmathurin

Copy link
Copy Markdown
Contributor

Summary

  • Introduces SFOAuthErrorCode.swift — a typed @objc Swift enum mirroring the ~42 distinct wire values from the server-side OauthErrorCode.java (core/identity-common-api), plus an .unknown fallback
  • Adds errorCode: NSInteger (typed as SFOAuthErrorCode) property to SFSDKOAuthTokenEndpointErrorResponse, populated at init time
  • Updates SFOAuthCoordinator -handleResponse: to compare errorCode enum instead of string-comparing against kSFOAuthErrorTypeUnsupportedGrantType
  • Adds client_blocked and client_blocked_retry to the +errorWithType:description: integer code mapping (previously fell through to kSFOAuthErrorUnknown = 666)
  • Deprecates all kSFOAuthErrorType* constants in SFSDKOAuthConstants.h with a pointer to the new enum
  • Groundwork for App Attestation error handling (W-22699715)

Files Changed

  • SFOAuthErrorCode.swift (new) — 42 enum cases + .unknown + wireValue + from() factory + SFOAuthErrorCodeHelper ObjC bridge class
  • SFSDKOAuth2.herrorCode property on SFSDKOAuthTokenEndpointErrorResponse
  • SFSDKOAuth2.m — populate _errorCode; add client_blocked/client_blocked_retry int codes
  • SFOAuthCoordinator.m — enum comparison for isUnsupportedGrantType
  • SFSDKOAuthConstants.h — deprecate 18 kSFOAuthErrorType* constants
  • SFOAuthErrorCodeTests.swift (new) — 6 unit tests (known values, nil, empty, unknown, round-trip)
  • SFOAuthCoordinatorLightningURLTests.swift — derive test wire values from enum wireValue
  • SalesforceSDKCore.xcodeproj/project.pbxproj — add new files to project/test target

Test Plan

  • xcodebuild build -scheme SalesforceSDKCore -sdk iphonesimulator — succeeds
  • SFOAuthErrorCodeTests — 6/6 passed
  • SFOAuthCoordinatorLightningURLTests — 5/5 passed
  • Full SalesforceSDKCore suite — 706 tests, 0 failures

…-23059473)

Replaces raw kSFOAuthErrorType* string comparisons with a typed @objc Swift enum
mirroring the server-side OauthErrorCode.java wire values (~42 distinct strings). Adds
errorCode property to SFSDKOAuthTokenEndpointErrorResponse, updates SFOAuthCoordinator
to switch on the enum, adds client_blocked/client_blocked_retry to the NSError integer
code mapping, and deprecates all kSFOAuthErrorType* constants in SFSDKOAuthConstants.h.
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
1 Warning
⚠️ Static Analysis found an issue with one or more files you modified. Please fix the issue(s).

Clang Static Analysis Issues

File Type Category Description Line Col
SFOAuthCoordinator Nullability Memory error nil assigned to a pointer which is expected to have non-null value 120 19
SFOAuthCoordinator Nullability Memory error nil assigned to a pointer which is expected to have non-null value 244 15

Generated by 🚫 Danger

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
TestsPassed ✅SkippedFailed
SalesforceSDKCore iOS ^18 Test Results708 ran708 ✅
TestResult
No test annotations available

@codecov

codecov Bot commented Jul 7, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.20779% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 68.70%. Comparing base (ab84f31) to head (bfadb2c).

Files with missing lines Patch % Lines
...lesforceSDKCore/Classes/OAuth/SFOAuthCoordinator.m 16.66% 5 Missing ⚠️
...KCore/SalesforceSDKCore/Classes/Util/SFSDKOAuth2.m 94.44% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##              dev    #4094      +/-   ##
==========================================
- Coverage   70.79%   68.70%   -2.10%     
==========================================
  Files         246      247       +1     
  Lines       21633    21687      +54     
==========================================
- Hits        15316    14900     -416     
- Misses       6317     6787     +470     
Components Coverage Δ
Analytics 70.78% <ø> (ø)
Common 70.79% <ø> (-0.19%) ⬇️
Core 62.50% <92.20%> (-3.20%) ⬇️
SmartStore 73.60% <ø> (ø)
MobileSync 88.82% <ø> (ø)
Files with missing lines Coverage Δ
...sforceSDKCore/Classes/OAuth/SFOAuthErrorCode.swift 100.00% <100.00%> (ø)
...KCore/SalesforceSDKCore/Classes/Util/SFSDKOAuth2.m 76.08% <94.44%> (-2.25%) ⬇️
...lesforceSDKCore/Classes/OAuth/SFOAuthCoordinator.m 53.92% <16.66%> (-10.67%) ⬇️

... and 21 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
TestsPassed ✅SkippedFailed
AuthFlowTester UI Test Results all1 ran1 ✅
TestResult
No test annotations available

wmathurin added 2 commits July 6, 2026 18:50
client_blocked and client_blocked_retry should be handled via the new
SFOAuthErrorCode enum, not by extending the legacy NSError integer code
mapping. Callers switch on response.error.errorCode, not error.code.
…useDpopNonce

Names now match server-side OauthErrorCode.java (core-264 main):
  clientBlocked      → appAttestationFailed      (wire: client_blocked)
  clientBlockedRetry → appAttestationFailedRetry (wire: client_blocked_retry)
Also add two missing distinct wire values from core-264:
  invalidDpopProof (invalid_dpop_proof)
  useDpopNonce     (use_dpop_nonce)
} else if ([type isEqualToString:@"invalid_request"]) {
code = kSFOAuthErrorInvalidRequest;
} else if ([type isEqualToString:kSFOAuthErrorTypeInactiveUser]) {
} else if ([type isEqualToString:@"inactive_user"]) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I was wondering why inactive_user wasn't in the new code set but then I saw on the server side it falls under "invalid_grant". Is there a way to get the sub-category too?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes — sub-categories are accessible via error_description. The server populates that field from OauthErrorCode.getDescription(), which is the human-readable description string in the server enum (e.g. "inactive user", "inactive organization", "expired access/refresh token", etc.). The SDK already parses and exposes this as tokenEndpointErrorDescription on SFSDKOAuthTokenEndpointErrorResponse, so callers can combine an errorCode == SFOAuthErrorCodeInvalidGrant check with a string comparison on errorDescription to distinguish sub-cases if needed.

if (![json isKindOfClass:[NSDictionary class]]) {
NSString *errorDesc = [NSString stringWithFormat:@"Expected NSDictionary for JWT token response, received %@ instance.", NSStringFromClass([json class])];
NSError *error = [SFSDKOAuth2 errorWithType:kSFOAuthErrorTypeJWTLaunchFailed
NSError *error = [SFSDKOAuth2 errorWithType:@"jwt_launch_failed"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is hardcoded now because the client-side is creating the error?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Correct — this is a client-side error, not a server wire value. The JWT response is malformed (wrong type), so the SDK generates the error locally rather than receiving it from the server. jwt_launch_failed was previously held in the kSFOAuthErrorTypeJWTLaunchFailed constant (now deprecated), but since this error string is not a server-defined wire value it isn't in SFOAuthErrorCode. The raw string is used directly here since the deprecated constant is no longer the preferred reference.

@wmathurin
wmathurin merged commit 6993d6b into forcedotcom:dev Jul 7, 2026
23 checks passed
JohnsonEricAtSalesforce added a commit to JohnsonEricAtSalesforce/SalesforceMobileSDK-iOS that referenced this pull request Jul 20, 2026
… unit 38/49)

Replace brittle OAuth error string comparisons with a typed enum.
NEW SFOAuthErrorCode.swift (45 server error values + .unknown, from(_:)
parser, wireValue mapping, + SFOAuthErrorCodeHelper ObjC bridge) added
verbatim and wired into the SDKCore target.

SFSDKOAuthTokenEndpointErrorResponse (Swift twin) gains an errorCode
property set via SFOAuthErrorCode.from(errorType); SFOAuthCoordinator's
Lightning-URL diagnostic now branches on errorCode == .unsupportedGrantType.
Legacy kSFOAuthErrorType* constants marked __deprecated_msg (retained).

De-ref .m/.h ref-synced (SFSDKOAuthConstants.h verbatim; SFOAuthCoordinator.m
+ SFSDKOAuth2.m hunks surgical). SFSDKOAuth2.h is a migration tombstone
(property lives in the Swift twin).

Tests: new SFOAuthErrorCodeTests.swift (8) + SFOAuthCoordinatorLightningURLTests
+4 hunk. SDKCore builds green (0 new warnings); 13 tests pass.

Escalation: OAuth error-handling surface -> PR-flag.

Advances upstream-sync marker ab84f31 -> 6993d6b.
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