First Account⚓︎
In this first scenario, we will walk you through the required steps to enrol the first account. After scanning the enrol QR code, you need to start a session and handle callbacks from the Mobile SDK. After these steps, you can proceed to do a QR based login or move directly to AppLogin.
Scanning the (Enrol) QR Code⚓︎
The QR codes generated by the nextAuth server contain binary data. While this is can be configured for iOS's built-in QR code scanner, many Android libraries for scanning QR codes do not support this format. That is why the nextAuth Mobile SDK also contains a secure QR code scanner that works directly on the input of the camera. Note though that this built-in QR code scanner only handles binary QR codes.
You are however free to use any QR code scanner as long as you can recover the raw binary data, as received from the nextAuth server.
Warning
If you decide to use a third party library for scanning QR codes, make sure that it is maintained and has no unpatched vulnerabilities.
Android⚓︎
Using androidx.camera, you can use the output of the ImageAnalysis
as input for the NextAuth.processQR()
function that will return a byte array containing the binary QR data, if it detected a valid binary QR code in the input.
...
ImageAnalysis imageAnalysis =
new ImageAnalysis.Builder()
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.build();
imageAnalysis.setAnalyzer(cameraExecutor, image -> {
// Use nextAuth's built-in QR code scanner
final byte[] result = NextAuth.getNextAuth().processQR(image);
image.close();
if (result != null && result.length > 0) {
// TODO: Handle the result (e.g., start a session)
}
});
...
For a complete example, we refer to the QrScannerActivity.java
and PrepareCameraActivity.java
classes of the Android Acme app.
iOS⚓︎
While Apple's Vision framework implements the QR detection logic, it does not natively support decoding binary QR codes. We therefore need the following snippet to process the raw QR code descriptor.
...
func decode(barcodeDescriptor: CIQRCodeDescriptor) -> Data? {
enum Mode: UInt8 {
case byte = 0x04
}
guard let mode = Mode(rawValue: barcodeDescriptor.errorCorrectedPayload[0] >> 4), mode == .byte else {
return nil
}
var location: Int
var length: Int
switch barcodeDescriptor.symbolVersion {
case 1...9:
location = 1
length = Int((UInt16(barcodeDescriptor.errorCorrectedPayload[0] & 0x0f) << 4) | (UInt16(barcodeDescriptor.errorCorrectedPayload[1] & 0xf0) >> 4))
case 10...40:
location = 2
length = Int((UInt16(barcodeDescriptor.errorCorrectedPayload[0] & 0x0f) << 12) | (UInt16(barcodeDescriptor.errorCorrectedPayload[1]) << 4) | (UInt16(barcodeDescriptor.errorCorrectedPayload[2] & 0xf0) >> 4))
default:
return nil
}
var data = Data()
for i in location..<(location + length) {
data.append((barcodeDescriptor.errorCorrectedPayload[i] << 4) | (barcodeDescriptor.errorCorrectedPayload[i+1] >> 4))
}
return data
}
...
We refer to the implementation in ScanViewController.swift
of the Acme app for a reference on how to wire up Apple's AVFoundation and Vision frameworks.
Starting a Session⚓︎
The Mobile SDK is built around the concept of sessions. For the Mobile SDK to perform actions such as creating an account or logging in, you need to start a session. This subsection describes how to start a session based on the scanned QR code. Note that it is also possible to start a session, based on an incoming push message or deep link.
Android⚓︎
You start a session by passing the raw binary data (byte array) from scanning the QR code as input. The second argument, i.e. whether or not the session was started from the mobile device (e.g., when using an app-to-app link) should be set to false.
byte[] data;
NextAuth.getNextAuth().getSessionManager().start(data, false);
Info
There is also a convenience function that takes a URL-safe base64-encoded string of the raw binary data as the first input.
// base64 (url safe) encoded string
String data;
NextAuth.getNextAuth().getSessionManager().start(data, false);
iOS⚓︎
Similar to the approach discussed for Android, you should pass the decoded binary data from the QR code to the Mobile SDK. This is done by invoking the following method.
var data: Data? = nil
NextAuth.default.start(with: data)
Handle Callbacks⚓︎
The expected sequence of callbacks/delegates/notifications to be handled is as follows:
ConfirmEnrol
-- asking the user to confirm creating a new account. See here for more information.SecondFactor
withFIRST_SET
as its context -- asking the user to set a second factor. See here for more information, and here for more specific information.SecondFactor
withSUCCESS
as its result -- acknowledging that the second factor has been set.SessionLogin
-- acknowledging that the account has been created and that the user is now logged in.
willConfirmEnrolFor
-- asking the user to confirm creating a new account. See here for more information.didStartSecondFactorWith
withFIRST_SET
as its context -- asking the user to set a second factor. See here for more information, and here for more specific information.didUpdateSecondFactorWith
withSUCCESS
as its result -- acknowledging that the second factor has been set.sessionUpdate
-- acknowledging that the account has been created and that the user is now logged in.
Info
The SecondFactor
callbacks are conditional on the server (for which the account is created) being configured to require a second factor.