Setup⚓︎
In this section, we will explain how to access the Mobile SDK, import it into your project and initialise it. Furthermore, since the Mobile SDK works asynchronously, you will need to set up listening for callbacks from it. After these steps, you can proceed to enrol your first account.
Minimal Requirements⚓︎
The Mobile SDKs require Android 6.0 (or above) and iOS 15.0 (or above).
Access to the Mobile SDKs & Docs⚓︎
The Android and iOS Mobile SDKs are available through our GitLab instance at https://git.nextauth.com/. If you do not have access, please contact support.
Each Mobile SDK comes with a full reference of their public APIs. For Android, this is in the form of Javadoc, which is distributed inside a Maven package, together with the SDK. For iOS, these docs are part of the Git repository under the docs directory.
Both SDKs work with releases, where you can also find the release notes. Through the GitLab interface, you can subscribe to email notification for new releases.
Importing the Mobile SDK⚓︎
Android⚓︎
First, in our GitLab interface, generate a personal access token with the read_api scope. Next, create a file ~/.gradle/gradle.properties with the following content.
gitLabPrivateToken={PERSONAL_ACCESS_TOKEN}
Then, add the following to your project's build.gradle script.
allprojects {
repositories {
...
maven {
url "https://git.nextauth.com/api/v4/projects/3/packages/maven"
name "GitLab"
credentials(HttpHeaderCredentials) {
name = 'Private-Token'
value = gitLabPrivateToken
}
authentication {
header(HttpHeaderAuthentication)
}
}
...
}
}
Continue by declaring the nextAuth android SDK dependency in your module's build.gradle script.
dependencies {
...
implementation 'com.nextauth.android:nextauth:3.0.0'
...
}
Finally, add the following features and permissions in the AndroidManifest.xml of your app.
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
// needed for scanning QR codes
<uses-feature
android:name="android.hardware.camera"
android:required="false" />
<uses-feature
android:name="android.hardware.camera.front"
android:required="false" />
<uses-permission android:name="android.permission.CAMERA" />
// needed for biometrics
<uses-feature
android:name="android.hardware.fingerprint"
android:required="false" />
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
// needed for notifications
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
iOS⚓︎
Our iOS Mobile SDK is distributed as a CocoaPod. First, you should generate a personal access token with scope read_api. Next, create a .netrc file with the following contents in your home directory. We also strongly recommend changing the permissions so that it can only be accessed by its owner.
machine git.nextauth.com login {USERNAME} password {PERSONAL_ACCESS_TOKEN}
Finally, you can import the NAKit module after adding the following snippet to your project's Podfile.
def pod_nakit
def http(version)
"https://git.nextauth.com/api/v4/projects/4/packages/generic" \
"/NAKit/#{version}/NAKit_v#{version}.zip"
end
pod 'NAKit', :http => http('{VERSION}'), :type => :zip
end
Alternatively, you can also include the Mobile SDK as a Swift Package. Place the following contents in a Package.swift file in a NAKit directory and add the Package to your project.
// swift-tools-version:5.3
import PackageDescription
let package = Package(
name: "NAKit",
platforms: [.iOS(.v15)],
products: [
.library(name: "NAKit", targets: ["NAKit"])
],
targets: [
.binaryTarget(
name: "NAKit",
url: "https://git.nextauth.com/api/v4/projects/4/packages/generic/NAKit/{VERSION}/NAKit_v{VERSION}.zip",
checksum: ""
)
]
)
Initialising the Mobile SDK⚓︎
Android⚓︎
Before initialising the SDK, make sure to have a nextauth.json file in the assets folder of the app. This file should at least contain the signed configuration string provided by nextAuth. See here for other optional configuration parameters that can be added to this file.
{
"config": ""
}
The SDK operates as a singleton and should thus be initialised at the application level. Create your custom MyApplication extending android.app.Application and initialise the SDK by calling the NextAuth.init(Context) function passing the application context.
import com.nextauth.android.NextAuth;
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
// Initialise nextAuth Mobile SDK
NextAuth.init(getApplicationContext());
}
}
Info
Alternatively (instead of working with the constants file), one can define Constants programmatically and pass it along to the init function:
Constants constants = new Constants();
constants.config = "";
...
NextAuth.init(getApplicationContext(), constants);
iOS⚓︎
Once the Pod or Package has been installed, the Mobile SDK should be configured before any other interaction takes place.
Warning
Don't forget to set the values of the config parameter. This is critical for the app to operate correctly. The other parameters allow you to customise the app's behaviour.
Warning
When you want to run the app on-device, you have to create an App Group in Apple's Developer portal, it will typically have the form group.com.nextauth.Authenticator. Once it has been created, don't forget to grant the app's Bundle ID the capability to access this group, update your provisioning profiles, and set the appGroup parameter.
The final task to take care of on the iOS side, is to configure the Mobile SDK.
let constants = NextAuth.Constants(
config: "",
appGroup: "",
)
guard NextAuth.default.canBeConfigured else {
return
}
NextAuth.default.configure(withConstants: constants)
Setting up Callback Listeners⚓︎
There are two type of callbacks: callbacks to handle errors (e.g. error, panic) and those for updating the UI (e.g. flow updates, session updates, account updates, an account that was deleted...).
When it comes to callbacks to handle errors, we distinguish between non-fatal errors that should be displayed to the user and panics. The latter can be logged both locally and remotely before crashing the app.
The general idea is to listen for those that require user interaction at the top level (application on Android, top level view controller on iOS) and start specific activities (Android) / views (iOS) for capturing the user's input. Listening for UI updates happens in the specific activities/views.
Android⚓︎
To listen for callbacks, your class need to implement the NextAuthObserver, add itself as an observer NextAuth.addObserver(this), and implement the onCallback(Callback callback) function.
Callbacks to Handle Errors⚓︎
You can implement the top level user interaction by extending myApplication as follows:
import com.nextauth.android.callback.Callback;
import com.nextauth.android.callback.Error;
import com.nextauth.android.callback.Panic;
import com.nextauth.android.NextAuth;
public class MyApplication extends Application implements NextAuthObserver {
@Override
public void onCreate() {
super.onCreate();
// Initialise nextAuth Mobile SDK
NextAuth nextAuth = NextAuth.init(getApplicationContext());
// Register observer
nextAuth.addObserver(this);
}
// Handle global callbacks
@Override
public void onCallback(Callback callback) {
if (callback instanceof Error) {
// TODO: Handle errors not associated with a flow
}
if (callback instanceof Panic) {
// TODO: log panic
// crash the app, as a panic indicates an unrecoverable state in the nextAuth Mobile SDK
throw new RuntimeException(((Panic) callback).nextAuthException);
}
}
}
Callbacks to Update the UI⚓︎
When starting a flow, you will need to listen for flow updates. On Android, you can always request the current flow, which will either return a Flow or null if there is no active flow:
NextAuth.getNextAuth().getFlowManager().getFlow();
Tip
Android apps typically have multiple entry points. We recommend calling the NextAuth.getFlow() function in every entry point's onResume() to check for an ongoing flow that needs user interaction.
Tip
You can also add a nextAuthObserver to the QR code scanner/camera activity and finish this activity when receiving a FlowUpdate callback.
iOS⚓︎
On iOS, we rely on two different update mechanisms to inform you about the different types of state changes. First, you should implement the methods defined by the NextAuthDelegate protocol which is part of our Mobile SDK. We suggest conforming to this protocol in a high-level class which has the ability to add and remove view controllers to and from the view hierarchy. Second, the Mobile SDK also issues local notifications you can subscribe to in order to receive account and sessions updates and trigger relevant actions (e.g., updating a view showing all active sessions).
After implementing the protocol, don't forgot to assign an instance of the conforming class to the delegate property of the Mobile SDK's singleton.
// MARK: - UIViewController
override func viewDidLoad() {
super.viewDidLoad()
NextAuth.default.delegate = self
}
Callbacks to Handle Errors⚓︎
Add the following to the class where you are implementing the NextAuthDelegate protocol in order to handle any asynchronous errors returned by the Mobile SDK.
// MARK: - NextAuthDelegate
func nextAuth(_ nextAuth: NextAuth, didReturn error: Session.Error) {
// TODO: Present alert to user
}
func nextAuth(_ nextAuth: NextAuth, didThrow panic: String) {
// TODO: Optionally log the passed panic reason
fatalError()
}
Callbacks to Update the UI⚓︎
Since you might want to trigger multiple actions based on session or account updates, we opted to have the Mobile SDK post local notifications to the NotificationCenter. The names of all notifications have been made available through the NotificationNames struct. While in some cases you simply want to know that either a session or account changed, note that we also attach the Session or Account instance that triggered the notification to the posted notification. The code snippet below will get you started on subscribing to these notifications.
// MARK: - Observers
@objc func handleAccountUpdateNotification(_ notification: NSNotification) {
guard let account = notification.object as? Account else {
return
}
// TODO: Implement required logic to process account update
}
@objc func handleAccountDeleteNotification(_ notification: NSNotification) {
guard let account = notification.object as? Account else {
return
}
// TODO: Implement required logic to process account delete
}
@objc func handleSessionUpdateNotification(_ notification: NSNotification) {
guard let session = notification.object as? Session else {
return
}
// TODO: Implement required logic to process session update
}
// MARK: - UIViewController
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(handleAccountUpdateNotification(_:)), name: NextAuth.NotificationNames.accountUpdate, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(handleAccountDeleteNotification(_:)), name: NextAuth.NotificationNames.accountDelete, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(handleSessionUpdateNotification(_:)), name: NextAuth.NotificationNames.sessionUpdate, object: nil)
}