iOS Swift SDK
Frontegg and iOS Swift
Frontegg's Mobile SDKs are officially here for you to explore and utilize. Our powerful and simple-to-implements SDKs are designed to empower you to create extraordinary mobile experiences. Whether you're developing for iOS, Android, React Native, or Ionic, we've got you covered.
Get ready to jump into the app development world with Swift and Frontegg. The following guide will walk you through integrating Frontegg's capabilities into iOS applications.
Table of Contents
- Project Requirements
- Getting Started
Project Requirements
Supported Languages
Swift: The minimum supported Swift version is now 5.3.
Supported Platforms
Major platform versions are supported, starting from:
- iOS > 14
Getting Started
Prepare Frontegg Workspace
Navigate to your Frontegg Portal Settings; if you don't have the application
follow the integration steps after signing up.
Copy FronteggDomain to future steps from Frontegg Portal Domain
Setup Hosted Login
- Navigate to your Login Method Settings
- Toggle on your Hosted login method.
- Add
{{IOS_BUNDLE_IDENTIFIER}}://{{FRONTEGG_BASE_URL}}/ios/oauth/callback
. - Replace
IOS_BUNDLE_IDENTIFIER
with your application identifier. - Replace
FRONTEGG_BASE_URL
with your frontegg base url.
Add frontegg package to the project
- Open your project.
- Choose File -> Add Packages.
- Enter
https://github.com/frontegg/frontegg-ios-swift
in your search field. - Press
Add Package
.
Create a Frontegg plist file
To setup your SwiftUI application for communication with Frontegg, you need to create a new file with the name Frontegg.plist
under your root project's directory. This file will store values to be used as variables by Frontegg's SDK:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN">
<plist version="1.0">
<dict>
<key>baseUrl</key>
<string>https://[DOMAIN_HOST_FROM_PREVIOUS_STEP]</string>
<key>clientId</key>
<string>[CLIENT_ID_FROM_PREVIOUS_STEP]</string>
</dict>
</plist>
SwiftUI integration
-
Add Frontegg Wrapper
-
To use Frontegg's SDK. wrap your Application Scene with
FronteggWrapper
, like so:import SwiftUI import FronteggSwift @main struct demoApp: App { var body: some Scene { WindowGroup { FronteggWrapper { MyApp() } } } }
-
Modify the
MyApp.swift
file to render content if a user is authenticated:- Add the
@EnvironmentObject var fronteggAuth: FronteggAuth
as shown below. - Render your entire application based on the
fronteggAuth.isAuthenticated
struct MyApp: View { @EnvironmentObject var fronteggAuth: FronteggAuth var body: some View { ZStack { if fronteggAuth.isAuthenticated { [YOU APPLICATION TABS / ROUTER / VIEWS] } else { Button { fronteggAuth.login() } label: { Text("Login Button") } } } } }
- Add the
-
Add a Custom Loading Screen
To use your own
LoadingView
/SplashScreen
, do as follows:- Build your loading view in a separated file.
- Pass
LoadingView
as AnyView to the FronteggWrapperFronteggWrapper(loaderView: AnyView(LoaderView())) { MyApp() }
-
UIKit integration
-
Add Frontegg UIKit Wrapper
-
Add Frontegg to the AppDelegate file
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. FronteggApp.shared.didFinishLaunchingWithOptions() return true }
-
Create FronteggController class that extends AbstractFronteggController from FronteggSwift
// // FronteggController.swift // import UIKit import FronteggSwift class FronteggController: AbstractFronteggController { override func navigateToAuthenticated(){ // This function will be called when the user is authenticated // to navigate your application to the authenticated screen let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil) let viewController = mainStoryboard.instantiateViewController(withIdentifier: "authenticatedScreen") self.view.window?.rootViewController = viewController self.view.window?.makeKeyAndVisible() } }
-
Create a new ViewController and set your FronteggController as a custom class (the custom class created in the previous step):
-
Mark FronteggController as Storyboard Entry Point
-
Setup SceneDelegate for Frontegg universal links:
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) { if let url = URLContexts.first?.url, url.startAccessingSecurityScopedResource() { defer { url.stopAccessingSecurityScopedResource() } if url.absoluteString.hasPrefix( FronteggApp.shared.baseUrl ) { if(FronteggApp.shared.auth.handleOpenUrl(url)){ // Display your own Authentication View Controller // to handle after oauth callback window?.rootViewController = AuthenticationController() window?.makeKeyAndVisible() return } } } } func scene(_ scene: UIScene, continue userActivity: NSUserActivity) { if let url = userActivity.webpageURL { if(FronteggApp.shared.auth.handleOpenUrl(url)){ // Display your own Authentication View Controller // to handle after oauth callback window?.rootViewController = AuthenticationController() window?.makeKeyAndVisible() return } } }
-
Access authenticated user by
FronteggApp.shared.auth
// // ExampleViewController.swift // import UIKit import SwiftUI import FronteggSwift import Combine class ExampleViewController: UIViewController { // Label to display logged in user's email @IBOutlet weak var label: UILabel! var showLoader: Boolean = true override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. // subscribe to isAuthenticated and navigate to login page // if the user is not authenticated let fronteggAuth = FronteggApp.shared.auth let sub = AnySubscriber<Bool, Never>( receiveSubscription: {query in query.request(.unlimited) }, receiveValue: { showLoader in self.showLoader = showLoader self.label.text = fronteggAuth.user?.email ?? "Unknown" if(!showLoader && !fronteggAuth.isAuthenticated){ // Display your own Authentication View Controller // to handle after oauth callback window?.rootViewController = AuthenticationController() window?.makeKeyAndVisible() return .none } return .unlimited }) FronteggApp.shared.auth.$showLoader.subscribe(sub) } @IBAction func logoutButton (){ FronteggApp.shared.auth.logout() } }
-
Embedded Webview vs ASWebAuthenticationSession
Frontegg SDK supports two authentication methods:
- Embedded Webview
- ASWebAuthenticationSession
By default, Frontegg SDK will use Embedded Webview. to use ASWebAuthenticationSession you will need to set the embeddedMode
to NO
in your Frontegg.plist
file:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN">
<plist version="1.0">
<dict>
<key>baseUrl</key>
<string>https://[DOMAIN_HOST_FROM_PREVIOUS_STEP]</string>
<key>clientId</key>
<string>[CLIENT_ID_FROM_PREVIOUS_STEP]</string>
<!-- START -->
<key>embeddedMode</key>
<true/>
<!-- END -->
</dict>
</plist>
Configuring an iOS-associated Domain
Configuring your iOS-associated domain is required for Magic Link Authentication / Reset Password / Activate Account.
To add your iOS-associated domain to your Frontegg application, you will need to update in each of your integrated Frontegg Environments the iOS-associated domain that you would like to use for that Environment. Send a POST request to https://api.frontegg.com/vendors/resources/associated-domains/v1/ios
with the following payload:
{
“appId”:[YOUR_ASSOCIATED_DOMAIN]
}
To use our API’s, follow this guide and generate a Vendor Token.
Next, you must add your associated domain to your iOS application. To do so, follow the steps below:
- Open your project in Xcode.
- Select your project in the Project Navigator.
- Select your target.
- Select the Signing & Capabilities tab.
- Expand the Associated Domains section.
- Click the + button.
- Enter your associated domain in the following format
applinks:[YOUR_ASSOCIATED_DOMAIN]
. - Enter your associated domain in the following format
webcredentials:[YOUR_ASSOCIATED_DOMAIN]
. - Press Done.
[YOUR_ASSOCIATED_DOMAIN]
is the associated domain you want to use with your iOS application.
For example, if you would like to use https://example.com
as your associated domain, you would enter applinks:example.com
and webcredentials:example.com
.
Multi-Region Support
This guide outlines how to configure your iOS application to support multiple regions.
Step 1: Modify the Frontegg.plist File
First, adjust your Frontegg.plist file to handle multiple regions:
Modifications:
- Remove the existing
baseUrl
andclientId
keys. - Add a new array key named
regions
. This array will hold dictionaries for each region.
Example Frontegg.plist Structure:
<key>regions</key>
<array>
<dict>
<key>key</key>
<string>us-region</string>
<key>baseUrl</key>
<string>https://us-region-api.frontegg.com</string>
<key>clientId</key>
<string>your-client-id-for-us-region</string>
</dict>
<!-- Add additional regions in a similar format -->
</array>
Step 2: Add Associated Domains for Each Region
For each region, configure the associated domains in your application's settings. This is vital for proper API routing and authentication.
Example Associated Domain Configuration:
demo-multi-region.entitlements
Follow Config iOS associated domain to add your iOS-associated domain to your Frontegg application.
Step 3: Implement Region Selection UI
The final step would be to implement a UI for users to select their region. This can be done in any way you see fit.
The example application uses a simple picker view to allow the user to select their region.
Important Considerations
- Switching Regions: To switch regions, update the selection in UserDefaults. If issues arise, a re-installation of the application might be necessary.
- Data Isolation: Ensure data handling and APIs are region-specific to prevent data leakage between regions.
Select EU Region | Select US Region |
---|---|
Example Region Selection UI:
import SwiftUI
import FronteggSwift
struct SelectRegionView: View {
@EnvironmentObject var fronteggAuth: FronteggAuth
var body: some View {
VStack(alignment: .leading) {
Text("Welcome to MyApp")
.font(.largeTitle)
Text("Select your region:")
.padding(.top, 8)
.padding(.bottom, 20)
.font(.title2)
ForEach(fronteggAuth.regionData, id: \.key.self) { item in
Button(action: {
FronteggApp.shared.initWithRegion(regionKey: item.key)
}) {
VStack(alignment: .leading) {
Text("Region - \(item.key.uppercased())")
.font(.title2)
.padding(.bottom, 1)
Text("\(item.baseUrl)")
.font(.caption)
.tint(.black)
.padding(.bottom, 8)
}
}
.frame(maxWidth: .infinity, alignment: .leading)
.contentShape(Rectangle())
}
Spacer()
}
.padding()
.navigationTitle("Region")
}
}
Updated 3 months ago