Skip to content

Commit

Permalink
FR-14342 - SDK enhancements
Browse files Browse the repository at this point in the history
  • Loading branch information
frontegg-david committed Dec 18, 2023
1 parent c398012 commit b9188c0
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 10 deletions.
2 changes: 1 addition & 1 deletion FronteggSwift.podspec
Original file line number Diff line number Diff line change
@@ -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'
Expand Down
53 changes: 53 additions & 0 deletions Sources/FronteggSwift/FronteggApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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 ){
Expand Down
6 changes: 6 additions & 0 deletions Sources/FronteggSwift/FronteggAuth.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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)

Expand Down Expand Up @@ -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)
Expand All @@ -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",
Expand Down
6 changes: 3 additions & 3 deletions Sources/FronteggSwift/embedded/CustomWebView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
20 changes: 15 additions & 5 deletions Sources/FronteggSwift/embedded/FronteggWebView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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;
Expand Down
43 changes: 43 additions & 0 deletions Sources/FronteggSwift/utils/PlistHelper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
]
}

}

2 changes: 1 addition & 1 deletion Sources/FronteggSwift/utils/generateErrorPage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@
import Foundation

func generateErrorPage(message:String, url:String, status: Int) -> String {
return "<html lang=\"en\"><head><title>Fatal Error</title> <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no\" /> <style> body { display: flex; justify-content: center; margin: 2rem; flex-direction: column; font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\"; background-color: rgba(255, 100, 100, .05); } .title { font-size: 24px; color: red; font-weight: 600; margin-bottom: 2rem; } .message { color: #333; font-size: 16px; margin-top: 0.5rem; word-break: break-all; } </style></head><body><div class=\"title\">\(message)</div><div class=\"message\"><b>Status Code:</b>\(status)</div><div class=\"message\"><b>Url:</b><br/>\(url)</div></body></html>"
return "<html lang=\"en\"><head><title>Fatal Error</title> <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no\" /> <style> body { display: flex; justify-content: center; margin: 2rem; flex-direction: column; font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\"; background-color: rgba(255, 100, 100, .05); } .title { font-size: 24px; color: red; font-weight: 600; margin-bottom: 2rem; } .message { color: #333; font-size: 16px; margin-top: 0.5rem; word-break: break-all; } </style></head><body><div class=\"title\">\(message)</div><div class=\"message\"><b>Status Code:</b>\(status)</div></body></html>"
}

0 comments on commit b9188c0

Please sign in to comment.