diff --git a/libs/SalesforceSDKCore/SalesforceSDKCore/Classes/Extensions/UserAccountManager.swift b/libs/SalesforceSDKCore/SalesforceSDKCore/Classes/Extensions/UserAccountManager.swift index 20fb3ed2a5..f4ae4baf44 100644 --- a/libs/SalesforceSDKCore/SalesforceSDKCore/Classes/Extensions/UserAccountManager.swift +++ b/libs/SalesforceSDKCore/SalesforceSDKCore/Classes/Extensions/UserAccountManager.swift @@ -39,6 +39,14 @@ public enum UserAccountManagerError: Error { extension UserAccountManager { + public func login(reason: SFLoginReason, _ completionBlock: @escaping (Result<(UserAccount, AuthInfo), UserAccountManagerError>) -> Void) -> Bool { + return __login(with: reason, completion: { (authInfo, userAccount) in + completionBlock(Result.success((userAccount,authInfo))) + }, failure: { (authInfo, error) in + completionBlock(Result.failure(.loginFailed(underlyingError: error, authInfo: authInfo))) + }) + } + /// Kick off the login process for credentials that's previously configured. /// - Parameter completionBlock: completion block to invoke with a success tuple (UserAccount, AuthInfo) or UserAccountManagerError for failure wrapped in a Result type. public func login(_ completionBlock: @escaping (Result<(UserAccount, AuthInfo), UserAccountManagerError>) -> Void) -> Bool { diff --git a/libs/SalesforceSDKCore/SalesforceSDKCore/Classes/OAuth/SFSDKAuthRequest.h b/libs/SalesforceSDKCore/SalesforceSDKCore/Classes/OAuth/SFSDKAuthRequest.h index e886007652..60c6bdabfa 100644 --- a/libs/SalesforceSDKCore/SalesforceSDKCore/Classes/OAuth/SFSDKAuthRequest.h +++ b/libs/SalesforceSDKCore/SalesforceSDKCore/Classes/OAuth/SFSDKAuthRequest.h @@ -22,6 +22,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWIS WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import +#import NS_ASSUME_NONNULL_BEGIN @class SFSDKLoginViewControllerConfig; @@ -44,6 +45,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nullable, nonatomic, strong) UIScene *scene; @property (nonatomic, copy) NSString *jwtToken; @property (nonatomic, copy, nullable) NSString *userAgentForAuth; +@property (nonatomic) SFLoginReason loginReason; // TODO //IDP flow related properties (SPApp related properties) @property (nonatomic, readonly, assign) BOOL idpEnabled; diff --git a/libs/SalesforceSDKCore/SalesforceSDKCore/Classes/UserAccount/SFUserAccountManager.h b/libs/SalesforceSDKCore/SalesforceSDKCore/Classes/UserAccount/SFUserAccountManager.h index 35d4387139..22fbc40c50 100644 --- a/libs/SalesforceSDKCore/SalesforceSDKCore/Classes/UserAccount/SFUserAccountManager.h +++ b/libs/SalesforceSDKCore/SalesforceSDKCore/Classes/UserAccount/SFUserAccountManager.h @@ -488,6 +488,10 @@ NS_SWIFT_NAME(UserAccountManager) - (BOOL)loginWithCompletion:(nullable SFUserAccountManagerSuccessCallbackBlock)completionBlock failure:(nullable SFUserAccountManagerFailureCallbackBlock)failureBlock NS_REFINED_FOR_SWIFT; +- (BOOL)loginWithReason:(SFLoginReason)reason + completion:(nullable SFUserAccountManagerSuccessCallbackBlock)completionBlock + failure:(nullable SFUserAccountManagerFailureCallbackBlock)failureBlock NS_REFINED_FOR_SWIFT; + /** Kick off the refresh process for the specified credentials. @param credentials SFOAuthCredentials to be refreshed. diff --git a/libs/SalesforceSDKCore/SalesforceSDKCore/Classes/UserAccount/SFUserAccountManager.m b/libs/SalesforceSDKCore/SalesforceSDKCore/Classes/UserAccount/SFUserAccountManager.m index 5d3d458b3d..a2b6615174 100644 --- a/libs/SalesforceSDKCore/SalesforceSDKCore/Classes/UserAccount/SFUserAccountManager.m +++ b/libs/SalesforceSDKCore/SalesforceSDKCore/Classes/UserAccount/SFUserAccountManager.m @@ -100,6 +100,7 @@ //keys used in notifications NSString * const kSFNotificationUserInfoAccountKey = @"account"; +NSString * const kSFNotificationUserInfoLoginReasonKey = @"loginReason"; NSString * const kSFNotificationUserInfoLogoutReasonKey = @"logoutReason"; NSString * const kSFNotificationUserInfoCredentialsKey = @"credentials"; NSString * const kSFNotificationUserInfoAuthTypeKey = @"authType"; @@ -396,15 +397,25 @@ - (void)kickOffIDPInitiatedLoginFlowForSP:(SFSDKSPConfig *)config statusUpdate:( } - (BOOL)loginWithCompletion:(SFUserAccountManagerSuccessCallbackBlock)completionBlock failure:(SFUserAccountManagerFailureCallbackBlock)failureBlock { + return [self loginWithReason:SFLoginReasonUnknown completion:completionBlock failure:failureBlock]; +} + +- (BOOL)loginWithReason:(SFLoginReason)reason completion:(nullable SFUserAccountManagerSuccessCallbackBlock)completionBlock failure:(nullable SFUserAccountManagerFailureCallbackBlock)failureBlock { + [SFSDKCoreLogger i:[self class] format:@"[%@ %@]", NSStringFromClass([self class]), NSStringFromSelector(_cmd)]; BOOL result = NO; for (UIScene *scene in [SFApplicationHelper sharedApplication].connectedScenes) { - result |= [self loginWithCompletion:completionBlock failure:failureBlock scene:scene]; + result |= [self loginWithReason:reason scene:scene completion:completionBlock failure:failureBlock]; } return result; } - (BOOL)loginWithCompletion:(SFUserAccountManagerSuccessCallbackBlock)completionBlock failure:(SFUserAccountManagerFailureCallbackBlock)failureBlock scene:(UIScene *)scene { - return [self authenticateWithCompletion:completionBlock failure:failureBlock scene:scene]; + return [self loginWithReason:SFLoginReasonUnknown scene:scene completion:completionBlock failure:failureBlock]; +} + +- (BOOL)loginWithReason:(SFLoginReason)reason scene:(UIScene *)scene completion:(SFUserAccountManagerSuccessCallbackBlock)completionBlock failure:(SFUserAccountManagerFailureCallbackBlock)failureBlock { + [SFSDKCoreLogger i:[self class] format:@"[%@ %@]", NSStringFromClass([self class]), NSStringFromSelector(_cmd)]; + return [self authenticateWithReason:reason scene:scene completion:completionBlock failure:failureBlock]; } - (BOOL)refreshCredentials:(SFOAuthCredentials *)credentials completion:(SFUserAccountManagerSuccessCallbackBlock)completionBlock failure:(SFUserAccountManagerFailureCallbackBlock)failureBlock { @@ -476,7 +487,7 @@ - (void)stopCurrentAuthentication:(void (^)(BOOL))completionBlock { } } -- (BOOL)authenticateWithCompletion:(SFUserAccountManagerSuccessCallbackBlock)completionBlock failure:(SFUserAccountManagerFailureCallbackBlock)failureBlock scene:(UIScene *)scene { +- (BOOL)authenticateWithReason:(SFLoginReason)reason scene:(UIScene *)scene completion:(SFUserAccountManagerSuccessCallbackBlock)completionBlock failure:(SFUserAccountManagerFailureCallbackBlock)failureBlock { SFSDKAuthSession *authSession = self.authSessions[scene.session.persistentIdentifier]; if (authSession && authSession.isAuthenticating) { [SFSDKCoreLogger e:[self class] format:@"Login has already been called. Stop current authentication using SFUserAccountManager::stopCurrentAuthentication and then retry."]; @@ -490,6 +501,7 @@ - (BOOL)authenticateWithCompletion:(SFUserAccountManagerSuccessCallbackBlock)com request = [self defaultAuthRequest]; } + request.loginReason = reason; if (scene) { request.scene = scene; } @@ -827,12 +839,19 @@ - (void)oauthCoordinatorDidFetchAuthCode:(SFOAuthCoordinator *)coordinator authI } - (void)oauthCoordinator:(SFOAuthCoordinator *)coordinator didBeginAuthenticationWithView:(WKWebView *)view { - SFLoginViewController *loginViewController = [self createLoginViewControllerInstance:coordinator]; loginViewController.oauthView = view; SFSDKAuthViewHolder *viewHolder = [SFSDKAuthViewHolder new]; viewHolder.loginController = loginViewController; viewHolder.scene = coordinator.authSession.oauthRequest.scene; + + SFLoginReason reason = coordinator.authSession.oauthRequest.loginReason; + [SFSDKCoreLogger i:[self class] format:@"Showing auth view, login reason: %@", reason]; // TODO string value + NSDictionary *userInfo = @{ kSFNotificationUserInfoCredentialsKey: coordinator.credentials, + kSFNotificationUserInfoAuthTypeKey: coordinator.authInfo, + kSFNotificationUserInfoLoginReasonKey: @(coordinator.authSession.oauthRequest.loginReason)}; + [[NSNotificationCenter defaultCenter] postNotificationName:kSFNotificationUserWillShowAuthView object:self userInfo:userInfo]; + // Ensure this runs on the main thread. Has to be sync, because the coordinator expects the auth view // to be added to a superview by the end of this method. if (![NSThread isMainThread]) { diff --git a/libs/SalesforceSDKCore/SalesforceSDKCore/Classes/Util/SFSDKOAuth2.h b/libs/SalesforceSDKCore/SalesforceSDKCore/Classes/Util/SFSDKOAuth2.h index f47100b36c..027597cc1d 100644 --- a/libs/SalesforceSDKCore/SalesforceSDKCore/Classes/Util/SFSDKOAuth2.h +++ b/libs/SalesforceSDKCore/SalesforceSDKCore/Classes/Util/SFSDKOAuth2.h @@ -78,6 +78,13 @@ typedef NS_ENUM(NSInteger, SFLogoutReason) { SFLogoutReasonRefreshTokenRotated // "Refresh token rotated" }; +typedef NS_ENUM(NSInteger, SFLoginReason) { + SFLoginReasonUnknown, + SFLoginReasonRestAPI, + SFLoginReasonSwitchToNewUser, + SFLoginReasonBiometricLock, +}; + NS_ASSUME_NONNULL_BEGIN @class SFOAuthCredentials; @interface SFSDKOAuthTokenEndpointErrorResponse : NSObject