Offline Fallback⚓︎
This feature was made available in v2.0.0 (Android) of the nextAuth Mobile SDK and v2.5.0 of the nextAuth Server.
In some use cases, the user's mobile device cannot be assumed to be online. As a fallback, nextAuth allows for the generation of an account-specific One Time Password (OTP) on the device for logging in with. Using the otpLogin API call, the OTP can be verified. The returned LoginStatus
object also contains an otplogin
field that indicates whether or not this session has been authenticated using the OTP fallback method. Note that this field will also be set in the getSession response.
Attention
You can only make use of this fallback mechanism when it is explicitly allowed by the server configuration, i.e. the serverFlag ENABLE_OTP
needs to be set. The following API calls allow you to check and update the server configuration.
Limitations and Security Implications⚓︎
The user is not asked for their second factor (as this cannot be verified online). This means that with this fallback only single factor authentication is provided, being the cryptographic keys stored by the nextAuth Mobile SDK (possession).
OTPs are based on symmetric key cryptography, meaning that both the mobile device and the server need to have a copy of the symmetric key. This obviously impacts your ability to prove afterwards that the user logged in as the key needed to verify the "proof" is the same as the one to generate it. If you need non-repudiable logins, this fallback cannot be used.
Our OTPs are based on the session you want to login for (data from the login QR code), account you login with, and the current time. Time is divided in intervals of 2 minutes, and the server verifies with respect to both the current and previous time interval. This implies that a user will always have at least 2 minutes to transfer the OTP code, and an attacker will have at most 4 minutes to pull of a brute-force attack.
Our OTP codes are standard encoded as 12 crock32 characters (Crockford's encoding which reduces confusion between numbers and letters), with the 6 first characters containing a reference to the account and the latter 6 containing the actual OTP. This gives you 30 bits of brute-force security. If you require another type of encoding or security level, please get in touch with nextAuth.
Implementation⚓︎
Directly after scanning the QR code, the session lifecycle is in the STARTING
state. Before fetching additional session information from the server, the Mobile SDK will issue an OTPAvailable
callback on Android or call the nextAuth(_:didGenerate:for:with:)
delegate method on iOS (if enabled).
@Override
public void onCallback(Callback callback) {
if (callback instanceof OTPAvailable){
// TODO: Trigger OTP user interaction logic
}
}
func nextAuth(_ nextAuth: NextAuth, canGenerateOTPFor session: Session, with accounts: [Account]) {
// TODO: Trigger OTP user interaction logic
}
In the background, the Mobile SDK will also fetch the session information from the server, and upon receiving it, move the session lifecycle to the USER_INTERACTION
state. It will now either send a login confirmation request or request the user's second factor. Upon receiving either of these callbacks, your app should proceed to ask the user for their confirmation or second factor and no longer offer the option of displaying the OTP.
In most cases, these callbacks follow almost immediately after the OTPAvailable
callback or nextAuth(_:didGenerate:for:with:)
invocation. However, in cases where server is not reachable, the Mobile SDK will try to reconnect with an exponential backoff. It is up to you to determine on how long you want to wait for this. A possible strategy would be to implement a countdown timer of 1 minute, which is bypassed when you can reliably establish there is no network connection or can be interrupted by the user itself, e.g., by providing a dialog with a "Get OTP Now" button.
Tip
When the Mobile SDK cannot connect to the nextAuth server, a UserErrorMessage
callback with errorCode 70 (Server Connection Error) is returned. When there is no network connection on the user's mobile device, this error comes almost immediately.
The OTPAvailable
callback contains the session
and list of accounts that are associated with the server where the user wants to login (QR code). If there is more than one account, the user will have to select the account they want to login with.
Tip
Session
objects now also contain two booleans otpAvailable
and connectionError
, indicating whether or not an OTP can (still) be computed for the session and whether or not the connection to the backend server failed. It is recommended to update the session just before displaying the UI.
You can request an OTP by calling generateOTP()
with the session and selected account, which returns an OTP that is of the form 2XPP7Q R5BDD0. It is only at this time that the OTP is computed by the Mobile SDK. To avoid inconsistent UI flows (when the server connection is reestablished after requesting an OTP), the Mobile SDK also ends the session, resulting in a SessionStop
callback.
String otp = NextAuth.getNextAuth().getSessionManager().generateOTP(session, account);
let otp = NextAuth.default.generateOTP(for: session, and: account)