From b9188c08167a645c3a58e9342deb4c45c8967ae1 Mon Sep 17 00:00:00 2001 From: David Antoon Date: Mon, 18 Dec 2023 16:17:39 +0200 Subject: [PATCH] FR-14342 - SDK enhancements --- FronteggSwift.podspec | 2 +- Sources/FronteggSwift/FronteggApp.swift | 53 +++++++++++++++++++ Sources/FronteggSwift/FronteggAuth.swift | 6 +++ .../embedded/CustomWebView.swift | 6 +-- .../embedded/FronteggWebView.swift | 20 +++++-- Sources/FronteggSwift/utils/PlistHelper.swift | 43 +++++++++++++++ .../utils/generateErrorPage.swift | 2 +- 7 files changed, 122 insertions(+), 10 deletions(-) diff --git a/FronteggSwift.podspec b/FronteggSwift.podspec index 1553166..c4d217b 100644 --- a/FronteggSwift.podspec +++ b/FronteggSwift.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'FronteggSwift' - s.version = '1.2.1' + s.version = '1.2.2' s.summary = 'A swift library for easy integrating iOS application with Frontegg Services' s.description = 'Frontegg is an end-to-end user management platform for B2B SaaS, powering strategies from PLG to enterprise readiness. Easy migration, no credit card required' s.homepage = 'https://github.com/frontegg/frontegg-ios-swift' diff --git a/Sources/FronteggSwift/FronteggApp.swift b/Sources/FronteggSwift/FronteggApp.swift index c205e90..2eb548c 100644 --- a/Sources/FronteggSwift/FronteggApp.swift +++ b/Sources/FronteggSwift/FronteggApp.swift @@ -16,6 +16,9 @@ public class FronteggApp { public var baseUrl: String = "" public var clientId: String = "" public var bundleIdentifier: String = "" + public var embeddedMode: Bool = true + public var handleLoginWithSocialLogin:Bool = true + public var handleLoginWithSSO:Bool = false public var regionData: [RegionConfig] = [] let credentialManager: CredentialManager @@ -24,6 +27,31 @@ public class FronteggApp { init() { + self.embeddedMode = PlistHelper.isEmbeddedMode() + let keychainService = PlistHelper.getKeychainService() + self.credentialManager = CredentialManager(serviceKey: keychainService) + self.bundleIdentifier = PlistHelper.bundleIdentifier() + + let bridgeOptions = PlistHelper.getNativeBridgeOptions() + self.handleLoginWithSocialLogin = bridgeOptions["loginWithSocialLogin"] ?? true + self.handleLoginWithSSO = bridgeOptions["loginWithSSO"] ?? false + + /** + lateInit used for react-native and ionic-capacitor initialization + */ + if(PlistHelper.isLateInit()){ + self.auth = FronteggAuth( + baseUrl: self.baseUrl, + clientId: self.clientId, + credentialManager: self.credentialManager, + isRegional: false, + regionData: self.regionData, + embeddedMode: self.embeddedMode, + isLateInit: true + ) + return + } + if let data = try? PlistHelper.fronteggRegionalConfig() { logger.info("Regional frontegg initialization") self.bundleIdentifier = data.bundleIdentifier @@ -84,6 +112,31 @@ public class FronteggApp { logger.info("Frontegg baseURL: \(self.baseUrl)") } + public func manualInit( + baseUrl: String, + cliendId: String, + handleLoginWithSocialLogin: Bool = true, + handleLoginWithSSO:Bool = false + ) { + self.baseUrl = baseUrl + self.clientId = cliendId + + self.handleLoginWithSocialLogin = handleLoginWithSocialLogin + self.handleLoginWithSSO = handleLoginWithSSO + + self.auth.manualInit(baseUrl: baseUrl, clientId: cliendId) + } + public func manualInitRegions(regions: [RegionConfig], + handleLoginWithSocialLogin: Bool = true, + handleLoginWithSSO:Bool = false) { + self.regionData = regions + self.handleLoginWithSocialLogin = handleLoginWithSocialLogin + self.handleLoginWithSSO = handleLoginWithSSO + self.auth.manualInitRegions(regions: regions) + self.baseUrl = self.auth.baseUrl + self.clientId = self.auth.clientId + } + public func initWithRegion( regionKey:String ){ if ( self.regionData.count == 0 ){ diff --git a/Sources/FronteggSwift/FronteggAuth.swift b/Sources/FronteggSwift/FronteggAuth.swift index cbe2aa5..e528aec 100644 --- a/Sources/FronteggSwift/FronteggAuth.swift +++ b/Sources/FronteggSwift/FronteggAuth.swift @@ -225,6 +225,8 @@ public class FronteggAuth: ObservableObject { setIsLoading(true) Task { + + print("Going to exchange token") let (responseData, error) = await api.exchangeToken( code: code, redirectUrl: redirectUri, @@ -244,6 +246,7 @@ public class FronteggAuth: ObservableObject { } do { + print("Going to load user data") let user = try await self.api.me(accessToken: data.access_token) await setCredentials(accessToken: data.access_token, refreshToken: data.refresh_token) @@ -352,6 +355,8 @@ public class FronteggAuth: ObservableObject { let oauthCallback = createOauthCallbackHandler(completion) self.webAuthentication.webAuthSession?.cancel() self.webAuthentication = WebAuthentication() + self.webAuthentication.ephemeralSesion = true + self.webAuthentication.window = getRootVC()?.view.window let (authorizeUrl, codeVerifier) = AuthorizeUrlGenerator.shared.generate(loginHint: email) CredentialManager.saveCodeVerifier(codeVerifier) @@ -367,6 +372,7 @@ public class FronteggAuth: ObservableObject { let oauthCallback = createOauthCallbackHandler(completion) self.webAuthentication.webAuthSession?.cancel() self.webAuthentication = WebAuthentication() + self.webAuthentication.window = getRootVC()?.view.window let directLogin: [String: Any] = [ "type": "direct", diff --git a/Sources/FronteggSwift/embedded/CustomWebView.swift b/Sources/FronteggSwift/embedded/CustomWebView.swift index 705a257..8469b72 100644 --- a/Sources/FronteggSwift/embedded/CustomWebView.swift +++ b/Sources/FronteggSwift/embedded/CustomWebView.swift @@ -40,9 +40,9 @@ class CustomWebView: WKWebView, WKNavigationDelegate { case .SocialOauthPreLogin: do { return self.setSocialLoginRedirectUri(webView, url) } - case .Unknown: do { - return self.openExternalBrowser(webView, url) - } +// case .Unknown: do { +// return self.openExternalBrowser(webView, url) +// } default: return .allow } diff --git a/Sources/FronteggSwift/embedded/FronteggWebView.swift b/Sources/FronteggSwift/embedded/FronteggWebView.swift index 7a6b25b..6af98bd 100644 --- a/Sources/FronteggSwift/embedded/FronteggWebView.swift +++ b/Sources/FronteggSwift/embedded/FronteggWebView.swift @@ -26,6 +26,16 @@ public struct FronteggWebView: UIViewRepresentable { userContentController.add(controller, name: "FronteggNativeBridge") + let fronteggApp = FronteggApp.shared + let jsObject = String(data: try! JSONSerialization.data(withJSONObject: [ + "loginWithSocialLogin": fronteggApp.handleLoginWithSocialLogin, + "loginWithSSO": fronteggApp.handleLoginWithSSO, + ]), encoding: .utf8) + + let jsScript = WKUserScript(source: "window.FronteggNativeBridgeFunctions = \(jsObject ?? "{}");", injectionTime: .atDocumentEnd, forMainFrameOnly: false) + userContentController.addUserScript(jsScript) + + let conf = WKWebViewConfiguration() conf.userContentController = userContentController conf.websiteDataStore = WKWebsiteDataStore.default() @@ -35,11 +45,11 @@ public struct FronteggWebView: UIViewRepresentable { controller.webView = webView -// if #available(iOS 16.4, *) { -// webView.isInspectable = true -// } else { -// // Fallback on earlier versions -// } + if #available(iOS 16.4, *) { + webView.isInspectable = true + } else { + // Fallback on earlier versions + } let url: URL let codeVerifier: String; diff --git a/Sources/FronteggSwift/utils/PlistHelper.swift b/Sources/FronteggSwift/utils/PlistHelper.swift index 632b836..8a58035 100644 --- a/Sources/FronteggSwift/utils/PlistHelper.swift +++ b/Sources/FronteggSwift/utils/PlistHelper.swift @@ -121,5 +121,48 @@ struct PlistHelper { return true } + + public static func isLateInit() -> Bool { + let bundle = Bundle.main; + if let path = bundle.path(forResource: "Frontegg", ofType: "plist"), + let values = NSDictionary(contentsOfFile: path) as? [String: Any], + let lateInit = values["lateInit"] as? Bool { + + return lateInit + } + return false + } + + + public static func getKeychainService() -> String { + let bundle = Bundle.main; + if let path = bundle.path(forResource: "Frontegg", ofType: "plist"), + let values = NSDictionary(contentsOfFile: path) as? [String: Any], + let keychainService = values["keychainService"] as? String { + + return keychainService + } + return "frontegg" + } + + public static func getNativeBridgeOptions() -> [String: Bool] { + let bundle = Bundle.main; + + var loginWithSocialLogin:Bool = true + var loginWithSSO:Bool = false + + if let path = bundle.path(forResource: "Frontegg", ofType: "plist"), + let values = NSDictionary(contentsOfFile: path) as? [String: Any] { + + loginWithSocialLogin = (values["loginWithSocialLogin"] as? Bool) ?? true + loginWithSSO = (values["loginWithSSO"] as? Bool) ?? false + + } + return [ + "loginWithSocialLogin": loginWithSocialLogin, + "loginWithSSO": loginWithSSO + ] + } + } diff --git a/Sources/FronteggSwift/utils/generateErrorPage.swift b/Sources/FronteggSwift/utils/generateErrorPage.swift index d27e947..b4f6f3f 100644 --- a/Sources/FronteggSwift/utils/generateErrorPage.swift +++ b/Sources/FronteggSwift/utils/generateErrorPage.swift @@ -8,5 +8,5 @@ import Foundation func generateErrorPage(message:String, url:String, status: Int) -> String { - return "Fatal Error
\(message)
Status Code:\(status)
Url:
\(url)
" + return "Fatal Error
\(message)
Status Code:\(status)
" }