Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion external/SalesforceMobileSDK-iOS
Submodule SalesforceMobileSDK-iOS updated 27 files
+1 −1 SalesforceSDKCore.podspec
+14 −2 libs/SalesforceSDKCore/SalesforceSDKCore.xcodeproj/project.pbxproj
+0 −1 libs/SalesforceSDKCore/SalesforceSDKCore/Classes/Common/SFSDKAppConfig.h
+0 −4 libs/SalesforceSDKCore/SalesforceSDKCore/Classes/Common/SFSDKAppConfig.m
+0 −59 libs/SalesforceSDKCore/SalesforceSDKCore/Classes/Common/SFSDKWebViewStateManager.h
+0 −117 libs/SalesforceSDKCore/SalesforceSDKCore/Classes/Common/SFSDKWebViewStateManager.m
+1 −0 libs/SalesforceSDKCore/SalesforceSDKCore/Classes/Common/SalesforceSDKManager.m
+4 −13 libs/SalesforceSDKCore/SalesforceSDKCore/Classes/Common/WebViewStateManager.swift
+6 −0 libs/SalesforceSDKCore/SalesforceSDKCore/Classes/Identity/SFIdentityCoordinator.m
+6 −0 libs/SalesforceSDKCore/SalesforceSDKCore/Classes/OAuth/SFOAuthCoordinator+Internal.h
+12 −7 libs/SalesforceSDKCore/SalesforceSDKCore/Classes/OAuth/SFOAuthCoordinator.m
+1 −0 libs/SalesforceSDKCore/SalesforceSDKCore/Classes/OAuth/SFOAuthCredentials+Internal.h
+7 −11 libs/SalesforceSDKCore/SalesforceSDKCore/Classes/OAuth/SFOAuthCredentials.h
+13 −2 libs/SalesforceSDKCore/SalesforceSDKCore/Classes/OAuth/SFOAuthCredentials.m
+190 −0 libs/SalesforceSDKCore/SalesforceSDKCore/Classes/OAuth/ScopeParser.swift
+1 −1 libs/SalesforceSDKCore/SalesforceSDKCore/Classes/PushNotification/SFSDKPushNotificationDecryption.m
+287 −0 libs/SalesforceSDKCore/SalesforceSDKCoreTests/BootconfigTests.swift
+2 −0 libs/SalesforceSDKCore/SalesforceSDKCoreTests/SFOAuthCredentialsTests.m
+3 −7 libs/SalesforceSDKCore/SalesforceSDKCoreTests/SFSDKEncryptedPushNotificationTests.m
+2 −0 libs/SalesforceSDKCore/SalesforceSDKCoreTests/SFSDKOAuthTokenEndpointResponseTests.m
+73 −0 libs/SalesforceSDKCore/SalesforceSDKCoreTests/SalesforceOAuthUnitTests.m
+3 −19 libs/SalesforceSDKCore/SalesforceSDKCoreTests/SalesforceSDKManagerTests.m
+94 −0 libs/SalesforceSDKCore/SalesforceSDKCoreTests/ScopeParserTests.swift
+3 −18 libs/SalesforceSDKCore/SalesforceSDKCoreTests/WebViewStateManagerTests.swift
+0 −5 native/SampleApps/MobileSyncExplorer/MobileSyncExplorer/bootconfig.plist
+8 −13 native/SampleApps/RestAPIExplorer/RestAPIExplorer/bootconfig.plist
+0 −1 shared/resources/SalesforceSDKResources.bundle/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
4F06AFC61C49A89900F70798 /* SalesforceHybridSDKTests-Prefix.pch in Headers */ = {isa = PBXBuildFile; fileRef = 4F06AFC51C49A89900F70798 /* SalesforceHybridSDKTests-Prefix.pch */; };
4F06AFEB1C49D35B00F70798 /* test_credentials.json in Resources */ = {isa = PBXBuildFile; fileRef = 82EFF33D16E8063700A63CDF /* test_credentials.json */; };
4F0C192F18AAFE54000FD4E9 /* cordova.js in Copy files to www/ */ = {isa = PBXBuildFile; fileRef = 4F0C192D18AAFE41000FD4E9 /* cordova.js */; };
4F2462E82E9EF36600373302 /* SalesforceWebViewCookieManagerTestSuite.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F2462E72E9EF36600373302 /* SalesforceWebViewCookieManagerTestSuite.swift */; };
4F37EB0F1DA324130049992D /* force.js in Copy sfdc libs */ = {isa = PBXBuildFile; fileRef = 4F37EB0A1DA323AF0049992D /* force.js */; };
4F37EB121DA3247F0049992D /* SFForceJSTestSuite.js in Copy test lib */ = {isa = PBXBuildFile; fileRef = 4F37EB101DA3246B0049992D /* SFForceJSTestSuite.js */; };
4F458AEE1911CF4C00545F86 /* mobilesync.js in Copy sfdc libs */ = {isa = PBXBuildFile; fileRef = 4FBFFAF1177A715300D1E36E /* mobilesync.js */; };
Expand Down Expand Up @@ -133,7 +134,6 @@
CE4CE4651C0E5B2A009F6029 /* SFHybridViewConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = CEF4FFAF170CC748001AA255 /* SFHybridViewConfig.m */; };
CE4CE4A71C0E60A4009F6029 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 82EFF2D316E7C57100A63CDF /* Foundation.framework */; };
CE65C23A1C0FD52F00319E68 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = CE65C2391C0FD52F00319E68 /* libz.tbd */; };
CE6839431FFEE5220011DA0A /* Cordova.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEEF966C1EB7CBF50059CA79 /* Cordova.framework */; };
CE7BA1571D89F9EE000B91D7 /* SFNetworkPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = CE7BA1551D89F9EE000B91D7 /* SFNetworkPlugin.h */; settings = {ATTRIBUTES = (Public, ); }; };
CE7BA1581D89F9EE000B91D7 /* SFNetworkPlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = CE7BA1561D89F9EE000B91D7 /* SFNetworkPlugin.m */; };
CE7BA1EF1D8CB388000B91D7 /* com.salesforce.plugin.network.js in Copy Salesforce plugin */ = {isa = PBXBuildFile; fileRef = CE7BA1E31D8CA3E7000B91D7 /* com.salesforce.plugin.network.js */; };
Expand All @@ -143,7 +143,6 @@
CEA2A8922214C114009D923B /* SmartStore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEA2A8572214C0CB009D923B /* SmartStore.framework */; };
CEA2A8932214C114009D923B /* MobileSync.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEA2A8372214C0A6009D923B /* MobileSync.framework */; };
CEEF96721EB7CC190059CA79 /* Cordova.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEEF966C1EB7CBF50059CA79 /* Cordova.framework */; };
CEEF96731EB7CD050059CA79 /* Cordova.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEEF966C1EB7CBF50059CA79 /* Cordova.framework */; };
FDCEC28E410DD8D98D826A33 /* SalesforceHybridSDKManager.m in Sources */ = {isa = PBXBuildFile; fileRef = FDCEC47AE59418FFDB4C61C2 /* SalesforceHybridSDKManager.m */; };
FDCECEB8C12C6043E1BD488B /* SalesforceHybridSDKManager.h in Headers */ = {isa = PBXBuildFile; fileRef = FDCEC934C681C14971B0C5E3 /* SalesforceHybridSDKManager.h */; settings = {ATTRIBUTES = (Public, ); }; };
/* End PBXBuildFile section */
Expand Down Expand Up @@ -459,6 +458,8 @@
4F22155619DF480100FF2D26 /* SFForcePlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SFForcePlugin.h; path = SFForcePlugin/SFForcePlugin.h; sourceTree = "<group>"; };
4F22155719DF480100FF2D26 /* SFForcePlugin.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SFForcePlugin.m; path = SFForcePlugin/SFForcePlugin.m; sourceTree = "<group>"; };
4F22159619DF60A200FF2D26 /* ImageIO.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ImageIO.framework; path = System/Library/Frameworks/ImageIO.framework; sourceTree = SDKROOT; };
4F2462E72E9EF36600373302 /* SalesforceWebViewCookieManagerTestSuite.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SalesforceWebViewCookieManagerTestSuite.swift; sourceTree = "<group>"; };
4F2462E92E9EF36A00373302 /* SalesforceHybridSDKTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SalesforceHybridSDKTests-Bridging-Header.h"; sourceTree = "<group>"; };
4F37EB0A1DA323AF0049992D /* force.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = force.js; sourceTree = "<group>"; };
4F37EB101DA3246B0049992D /* SFForceJSTestSuite.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = SFForceJSTestSuite.js; sourceTree = "<group>"; };
4F5B96661DAD9D09001627F2 /* com.salesforce.plugin.smartstore.client.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = com.salesforce.plugin.smartstore.client.js; sourceTree = "<group>"; };
Expand Down Expand Up @@ -583,7 +584,6 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
CEEF96731EB7CD050059CA79 /* Cordova.framework in Frameworks */,
CE0AB0A51C10D60400BFAEED /* SalesforceHybridSDK.framework in Frameworks */,
CE0AB09C1C10D5E400BFAEED /* libxml2.tbd in Frameworks */,
CE0AB09F1C10D5E400BFAEED /* libz.tbd in Frameworks */,
Expand Down Expand Up @@ -614,7 +614,6 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
CE6839431FFEE5220011DA0A /* Cordova.framework in Frameworks */,
CE4CE2E81C0E465B009F6029 /* SalesforceHybridSDK.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -744,6 +743,7 @@
822272A219C39F4500FC537E /* SalesforceHybridSDKTests */ = {
isa = PBXGroup;
children = (
4F2462E72E9EF36600373302 /* SalesforceWebViewCookieManagerTestSuite.swift */,
4F06AFA61C49A77200F70798 /* ForceJSTestSuite.m */,
4F06AFA81C49A77200F70798 /* SDKInfoTestSuite.m */,
82AB22641F9EB9C100A754C8 /* SFHybridViewConfigTestSuite.m */,
Expand All @@ -754,6 +754,7 @@
4F06AFAE1C49A77200F70798 /* SmartStoreTestSuite.m */,
4F06AFB01C49A77200F70798 /* MobileSyncTestSuite.m */,
4F06AFC31C49A87F00F70798 /* Supporting Files */,
4F2462E92E9EF36A00373302 /* SalesforceHybridSDKTests-Bridging-Header.h */,
);
path = SalesforceHybridSDKTests;
sourceTree = "<group>";
Expand Down Expand Up @@ -1242,6 +1243,7 @@
ORGANIZATIONNAME = salesforce.com;
TargetAttributes = {
8222729C19C39F4500FC537E = {
LastSwiftMigration = 1640;
TestTargetID = 82EFF2FE16E8049500A63CDF;
};
82EFF2FE16E8049500A63CDF = {
Expand Down Expand Up @@ -1511,6 +1513,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
4F2462E82E9EF36600373302 /* SalesforceWebViewCookieManagerTestSuite.swift in Sources */,
4F06AFC11C49A7BF00F70798 /* SmartStoreTestSuite.m in Sources */,
4F924C5D24BD4BA700D2F6DC /* SFHybridViewControllerTestSuite.m in Sources */,
4F06AFBD1C49A7BF00F70798 /* ForceJSTestSuite.m in Sources */,
Expand Down Expand Up @@ -1635,6 +1638,9 @@
"@loader_path/Frameworks",
);
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "SalesforceHybridSDKTests/SalesforceHybridSDKTests-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 6.0;
TEST_HOST = "$(BUNDLE_LOADER)";
WRAPPER_EXTENSION = xctest;
};
Expand Down Expand Up @@ -1666,6 +1672,9 @@
"@loader_path/Frameworks",
);
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "SalesforceHybridSDKTests/SalesforceHybridSDKTests-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 6.0;
TEST_HOST = "$(BUNDLE_LOADER)";
WRAPPER_EXTENSION = xctest;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,52 @@

import Foundation
import WebKit
import SalesforceSDKCore

@objc(SFSDKSalesforceWebViewCookieManager)
public class SalesforceWebViewCookieManager: NSObject {

// MARK: - Public Methods

/**
* Sets cookies for the provided user account (Objective-C compatible version).
* This method delegates to the Swift-only version with default implementations.
*/
@MainActor @objc public func setCookies(userAccount: UserAccount, completion: @escaping () -> Void) {
let creds = userAccount.credentials
setCookies(
userAccount: userAccount,
setCookieValue: { [weak self] cookieType, domain, setDomain, name, value in
guard let self = self else { return }
self.setCookieValue(cookieStore: WKWebsiteDataStore.default().httpCookieStore,
cookieType: cookieType,
domain: domain,
name: name,
value: value)
},
completion: completion
)
}

/**
* Sets cookies for the provided user account (Swift version with testable parameters).
* Internal access for testing purposes only.
*
* - Parameters:
* - userAccount: The user account for which to set cookies
* - setCookieValue: Optional lambda to set cookie values (for testing)
* - completion: Completion block called when cookie setting is finished
*/
@MainActor internal func setCookies(
userAccount: UserAccount,
setCookieValue: @escaping (String, String?, Bool, String?, String?) -> Void = { _, _, _, _, _ in },
completion: @escaping () -> Void
) {
let creds = userAccount.credentials
SFSDKHybridLogger.i(Self.self, message: "[\(Self.self) \(#function)]: setting cookies for \(String(describing: creds.userId)).")
let cookieStore = WKWebsiteDataStore.default().httpCookieStore

// Warn if expected scopes are missing
inspectScopes(creds.scopes)

let instanceUrl = creds.instanceUrl
let lightningDomain = creds.lightningDomain
let lightningSid = creds.lightningSid
Expand All @@ -51,25 +90,28 @@ public class SalesforceWebViewCookieManager: NSObject {
let orgId = userAccount.accountIdentity.orgId
let mainDomain = getDomainFromUrl(instanceUrl)

// Determine setDomain flag based on community URL presence
let hasCommunityUrl = creds.communityUrl != nil

// Main domain cookies
setCookieValue(cookieStore: cookieStore, cookieType: "sid for main", domain: mainDomain, name: sidCookieName, value: mainSid)
setCookieValue(cookieStore: cookieStore, cookieType: Self.CLIENT_SRC, domain: mainDomain, name: Self.CLIENT_SRC, value: clientSrc)
setCookieValue(cookieStore: cookieStore, cookieType: Self.SID_CLIENT, domain: mainDomain, name: Self.SID_CLIENT, value: sidClient)
setCookieValue(cookieStore: cookieStore, cookieType: Self.ORG_ID, domain: mainDomain, name: Self.ORG_ID, value: orgId)
setCookieValue(cookieStore: cookieStore, cookieType: Self.csrfTokenCookieName, domain: mainDomain, name: Self.csrfTokenCookieName, value: csrfToken)
setCookieValue("sid for main", mainDomain, hasCommunityUrl, sidCookieName, mainSid)
setCookieValue(Self.CLIENT_SRC, mainDomain, hasCommunityUrl, Self.CLIENT_SRC, clientSrc)
setCookieValue(Self.SID_CLIENT, mainDomain, hasCommunityUrl, Self.SID_CLIENT, sidClient)
setCookieValue(Self.ORG_ID, mainDomain, hasCommunityUrl, Self.ORG_ID, orgId)
setCookieValue(Self.csrfTokenCookieName, mainDomain, hasCommunityUrl, Self.csrfTokenCookieName, csrfToken)

// Lightning domain cookies
setCookieValue(cookieStore: cookieStore, cookieType: "sid for lightning", domain: lightningDomain, name: sidCookieName, value: lightningSid)
setCookieValue(cookieStore: cookieStore, cookieType: Self.csrfTokenCookieName, domain: lightningDomain, name: Self.csrfTokenCookieName, value: csrfToken)
setCookieValue("sid for lightning", lightningDomain, hasCommunityUrl, sidCookieName, lightningSid)
setCookieValue(Self.csrfTokenCookieName, lightningDomain, hasCommunityUrl, Self.csrfTokenCookieName, csrfToken)

// Content domain cookies
setCookieValue(cookieStore: cookieStore, cookieType: "sid for content", domain: contentDomain, name: sidCookieName, value: contentSid)
setCookieValue("sid for content", contentDomain, hasCommunityUrl, sidCookieName, contentSid)

// Vf domain cookies
setCookieValue(cookieStore: cookieStore, cookieType: "sid for vf", domain: vfDomain, name: sidCookieName, value: vfSid)
setCookieValue(cookieStore: cookieStore, cookieType: Self.CLIENT_SRC, domain: vfDomain, name: Self.CLIENT_SRC, value: clientSrc)
setCookieValue(cookieStore: cookieStore, cookieType: Self.SID_CLIENT, domain: vfDomain, name: Self.SID_CLIENT, value: sidClient)
setCookieValue(cookieStore: cookieStore, cookieType: Self.ORG_ID, domain: vfDomain, name: Self.ORG_ID, value: orgId)
setCookieValue("sid for vf", vfDomain, hasCommunityUrl, sidCookieName, vfSid)
setCookieValue(Self.CLIENT_SRC, vfDomain, hasCommunityUrl, Self.CLIENT_SRC, clientSrc)
setCookieValue(Self.SID_CLIENT, vfDomain, hasCommunityUrl, Self.SID_CLIENT, sidClient)
setCookieValue(Self.ORG_ID, vfDomain, hasCommunityUrl, Self.ORG_ID, orgId)

SFSDKHybridLogger.i(Self.self, message: "[\(Self.self) \(#function)]: done setting cookies for \(String(describing: creds.userId)).")
completion()
Expand Down Expand Up @@ -99,6 +141,34 @@ public class SalesforceWebViewCookieManager: NSObject {
private func getDomainFromUrl(_ url: URL?) -> String {
return url?.host ?? ""
}

internal func inspectScopes(_ scopes: [String]?, warn: ((String) -> Void)? = nil) {
let warnFunction = warn ?? { message in
SFSDKHybridLogger.w(Self.self, message: message)
}

let scopeParser = ScopeParser(scopes: scopes)

// full encompasses all other scopes except for refresh
if !scopeParser.hasScope("full") {
if !scopeParser.hasScope("web") {
warnFunction("Missing web scope: will not be able to access web content.")

// web encompasses visualforce scope
if !scopeParser.hasScope("visualforce") {
warnFunction("Missing visualforce scope: will not be able to access Visualforce pages.")
}
}

if !scopeParser.hasScope("lightning") {
warnFunction("Missing lightning scope: will not be able to access Lightning applications.")
}

if !scopeParser.hasScope("content") {
warnFunction("Missing content scope: will not be able to access Content resources.")
}
}
}

static let CLIENT_SRC = "clientSrc"
static let SID_CLIENT = "sid_Client"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//

Loading
Loading