@W-22917500 Add diagnostic warning when OAuth code exchange fails against Lightning URL#4059
Conversation
…inst Lightning URL Detect when the token endpoint returns unsupported_grant_type and the login server URL contains .lightning. — log a detailed developer warning and surface a localized user-facing alert instead of the generic error. Port of Android PR forcedotcom/SalesforceMobileSDK-Android/pull/2921.
Testing DetailsThe Lightning URL diagnostic fires when both conditions are met:
Why this can't be triggered in the standard iOS flow: During testing against This 302 behavior is undocumented and not guaranteed by Salesforce (see KB articles 000386369 and 000385751). Android's How we verified the implementation: We temporarily injected a synthetic This response was generated by an AI agent on behalf of @JohnsonEricAtSalesforce. |
Clang Static Analysis Issues
Generated by 🚫 Danger |
|
||||||||||||||||
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## dev #4059 +/- ##
==========================================
- Coverage 71.00% 68.47% -2.53%
==========================================
Files 246 246
Lines 21477 21489 +12
==========================================
- Hits 15250 14715 -535
- Misses 6227 6774 +547
🚀 New features to boost your workflow:
|
|
||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
CI Test Failure AnalysisThe single test failure ( The test uses a 0.2-second This response was generated by an AI agent on behalf of @JohnsonEricAtSalesforce. |
Danger Static Analysis ResponseThe two Clang nullability warnings are pre-existing issues at lines 120 and 244 of These warnings exist on the This response was generated by an AI agent on behalf of @JohnsonEricAtSalesforce. |
| [self stopAuthentication]; | ||
| } | ||
| [self notifyDelegateOfFailure:response.error.error authInfo:self.authInfo]; | ||
| BOOL isUnsupportedGrantType = [response.error.tokenEndpointErrorCode isEqualToString:@"unsupported_grant_type"]; |
There was a problem hiding this comment.
I think we have an existing const for this, kSFOAuthErrorTypeUnsupportedResponseType
There was a problem hiding this comment.
Good catch. The existing kSFOAuthErrorTypeUnsupportedResponseType is actually unsupported_response_type (not the same value), so I added a new kSFOAuthErrorTypeUnsupportedGrantType constant to SFSDKOAuthConstants.h following the same pattern and reference it here.
See commit: 2b8ced275
This response was generated by an AI agent on behalf of @JohnsonEricAtSalesforce.
| BOOL isUnsupportedGrantType = [response.error.tokenEndpointErrorCode isEqualToString:@"unsupported_grant_type"]; | ||
| BOOL isLightningURL = [self.credentials.domain containsString:@".lightning."]; | ||
| if (isUnsupportedGrantType && isLightningURL) { | ||
| [SFSDKCoreLogger w:[self class] format:@"Code exchange failed with unsupported_grant_type against Lightning URL: %@. Lightning URLs do not support authorization_code grant type. Use a My Domain login server URL instead.", self.credentials.domain]; |
There was a problem hiding this comment.
What do you think about error instead of warning?
There was a problem hiding this comment.
Agreed — this is a misconfiguration that will always fail, not a transient condition. Changed to error level.
See commit: b0a096a83
This response was generated by an AI agent on behalf of @JohnsonEricAtSalesforce.
| "authAlertVersionMismatchError" = "Your app has been updated, and you will need to log in again to continue using the app."; | ||
| "authAlertBrowserFlowTitle" = "Log In"; | ||
| "authAlertFrontdoorLoginUrlConsumerKeyMismatch" = "Cannot use another app's login QR Code. Please log in to this app."; | ||
| "lightningUrlCodeExchangeError" = "Lighting URLs (.lightning.) are not supported for OAuth code exchange. Use your My Domain (.my.) URL instead."; |
There was a problem hiding this comment.
Good eye — fixed.
See commit: 3b7c14a6b
This response was generated by an AI agent on behalf of @JohnsonEricAtSalesforce.
| // MARK: - SC-3: User-facing alert string is localized | ||
|
|
||
| func test_givenLightningURLError_whenHandleResponse_thenErrorDescriptionMatchesLocalizedString() throws { | ||
| XCTAssertNotNil(lightningMessage, "Localized string key 'lightningUrlCodeExchangeError' must be defined") |
There was a problem hiding this comment.
I don't think this will ever fail because the util will return the key even if the message isn't defined
There was a problem hiding this comment.
You're right — SFSDKResourceUtils.localizedString: returns the key itself when the string isn't defined, so those assertions will always pass. The XCTAssertEqual on the next line is the real guard. Removed the redundant checks.
See commit: cef352839
This response was generated by an AI agent on behalf of @JohnsonEricAtSalesforce.
Additional CI Test FailuresTwo more pre-existing failures reported by CI, both unrelated to this PR: iOS ^26:
AuthFlowTester UI:
None of these tests touch This response was generated by an AI agent on behalf of @JohnsonEricAtSalesforce. |
…ls against Lightning URL (Use constant for unsupported_grant_type)
…ls against Lightning URL (Use error log level instead of warning)
…ls against Lightning URL (Fix typo: Lighting -> Lightning)
…ls against Lightning URL (Remove redundant assertions on localized string)
bdeba0b
into
forcedotcom:dev

Summary
unsupported_grant_typeand login server URL contains.lightning.Details
Work Link: W-22917500
Port of Android PR: forcedotcom/SalesforceMobileSDK-Android#2921
Spec: SalesforceMobileSDK-Workspace PR 20 (approved and merged)
Changes
SFOAuthCoordinator.mhandleResponse:Localizable.stringsSFOAuthCoordinatorLightningURLTests.swiftSalesforceSDKCoreTests-Bridging-Header.hhandleResponse:andinitWithDictionary:for testingproject.pbxprojTest Plan
Verification Checklist
Deviations from Plan
None — implementation followed plan exactly.
Requirements
Testing Methodology
This diagnostic cannot be triggered through the standard iOS auth flow because iOS
NSURLSessionautomatically follows the HTTP 302 redirect that Lightning URL token endpoints return. The redirect transparently routes to the My Domain token endpoint, so theunsupported_grant_typeerror never reaches the SDK.To verify the diagnostic end-to-end, we injected a synthetic
unsupported_grant_typeresponse inSFSDKOAuth2.mwhen the token endpoint URL contains.lightning., simulating what Android's OkHttpClient receives (OkHttp does not follow 302 on POST per HTTP spec). The resulting alert was confirmed visually on an iPhone 17 Pro simulator (screenshot below).Code Review Notes
The following refinements were applied during development review:
XCTUnwrap+throwsfor graceful test failurehandleTokenResponse(domain:errorCode:)helper