Authenticating users
This topic explains all the steps required to add user authentication to your app. In case you didn't add user registration functionality to your application project, follow the steps in user registration.
Retrieving registered users
The React Native SDK provides a getUserProfiles
function to get all registered profiles on the device. You will need to use these to authenticate a profile with the SDK.
OneWelcomeSdk.getUserProfiles()
.then(profiles => {
console.log('User profiles registered on this device: ', profiles)
})
.catch(error => {
console.error('Error:', error.message)
})
Authenticate a registered user
After a user has been registered, they can be logged in using the authenticateUser
method. This method takes the profileId
of an already registered user and an optional authenticatorId
, returning a promise. You can find out which authenticators are available by calling the getRegisteredAuthenticators
method passing in the profileId
. After starting user authentication, the app needs to handle certain events sent by the SDK. Event listeners will need to be set up for PinAuthenticationEvent
before starting authentication, using the addEventListener
method. The SDK expects certain input depending on what kind of authentication was started before it will resolve or reject. The events sent by the SDK indicate what kind of input it is expecting.
OneWelcomeSdk.authenticateUser(profileId, null)
.then(authData => {
console.log('User authentication succeed!')
})
.catch(error => {
console.log('User authentication failed!: ', error.message)
})
interface OneWelcomeSDK {
authenticateUser(
profileId: string,
authenticatorId: string | null,
): Promise<Types.AuthData>;
// ...
}
Authenticating with PIN
When authenticating with a PIN, you will need to handle the PinAuthenticationEvent
. You can listen for this event and handle it as follows.
During PIN authentication, you should communicate the PIN to the SDK using the submitPin
method or cancel it using the cancelPinAuthentication
method. The submitPin
method expects you to specify for what kind of flow you are submitting the PIN. Canceling the PIN authentication will result in the promise from authenticateUser()
rejecting. You can use that to handle any logic for your app.
If authentication was successful, the SDK will resolve the promise from authenticateUser()
. It will also send a PinAuthenticationCloseEvent
event.
PinAuthenticationEvent | Description |
---|---|
PinAuthenticationOpenEvent | Sent when the SDK is ready to receive a PIN for authentication. |
PinAuthenticationCloseEvent | Sent by the SDK when it has finished authentication. |
IncorrectPinEvent | Sent by the SDK when it has received an incorrect PIN. |
const handleAuthNotification = useCallback(
async (event: Events.PinAuthenticationEvent) => {
console.log('handle PIN notification event: ', event);
switch (event.action) {
case Events.PinAuthentication.Open:
await handleAuthOpen(event);
break;
case Events.PinAuthentication.Close:
setInitialState();
break;
case Events.PinAuthentication.IncorrectPin:
handleIncorrectPin(event);
break;
}
},
[handleAuthOpen, setInitialState, handleIncorrectPin],
);
const authListener = OnewelcomeSdk.addEventListener(
Events.SdkNotification.PinAuth,
handleAuthNotification,
);
Authenticating with biometrics
The React Native SDK allows you to authenticate users with the system biometric authenticators. These authenticators are provided by the device's operating system (iOS uses Touch ID and Face ID, Android uses fingerprint) if they are available on the device. System biometric authenticators can be used for both regular and mobile authentication. Users will be able to retry system biometric authentication as many times as the OS allows. If the OS system's biometric authenticator's API returns an error for any reason (for example in case of too many failed attempts), the React Native SDK will revoke the system biometric authenticator and will perform a fallback to PIN authentication.
It should be noted that there are significant differences between fingerprint on Android and Touch ID on iOS. As a result, some methods may be available on only one of the operating systems. This will be specified where applicable.
Requirements
FaceID
iOS needs to have configured message displayed on FaceID alert. It's configurable by adding NSFaceIDUsageDescription
in your Info.plist
file.
Example configuration
<key>NSFaceIDUsageDescription</key>
<string>FaceID is used as a authenticator to login to application.</string>
Not specifying this property in your configuration will crash your application when you will try to use Face ID authentication.
Enabling system biometric authenticator authentication
To enable fingerprint authenticator authentication for a user, the React Native SDK provides the registerAuthenticator
to which you need to pass the authenticatorId
. This function requires the user to authenticate with a PIN.
Example code for registering the system biometric authenticator
OneWelcomeSdk
.registerAuthenticator(authenticatorId)
.then(() => {
console.error("Register authenticator succeed!");
})
.catch(error => {
console.error("Register authenticator failed: " + error);
});
You also have to listen for PIN events in case of fallback.
Fingerprint authentication may not be available on every device. In this case, or if the authenticator has already been registered, the above method will reject with an error.
To request a list of available authenticators, the plugin exposes the getAllAuthenticators
function. If the device does not meet the fingerprint requirements, the fingerprint authenticator will not be present in the returned array of authenticators.
Registering a new authenticator does not set it as the preferred authenticator for the user, which is PIN by default. To change the preferred authenticator, setPreferredAuthenticator
can be used.
Example code to set fingerprint as the preferred authenticator
OneWelcomeSdk.setPreferredAuthenticator(authenticatorId)
.then(()) => {
console.log('setPreferredAuthenticator succeed!')
}
.catch(error => {
console.log('setPreferredAuthenticator failed!: ', error.message)
})
Authenticating with fingerprint
There are two ways to start a fingerprint authentication flow.
- You register a fingerprint as the preferred authenticator using
setPreferredAuthenticator
and callauthenticateUser
with null as the second argument. - You get the
authenticatorId
for fingerprint authentication and pass that into the second argument ofauthenticateUser
.
Authenticating with fingerprint on Android
For authentication with fingerprint, similar to PIN, you will need to handle the FingerprintNotificationEvent
. See addEventListener
for more details. You can listen for this event and handle it as follows.
const handleNotification = useCallback(
(event: Events.FingerprintNotificationEvent) => {
console.log('handle FINGERPRINT notification event: ', event);
switch (event.action) {
case Events.Fingerprint.StartAuthentication:
onStart();
break;
case Events.Fingerprint.OnNextAuthenticationAttempt:
onNextAuthAttempt();
break;
case Events.Fingerprint.OnFingerprintCaptured:
onCaptured();
break;
case Events.Fingerprint.FinishAuthentication:
onFinish();
break;
}
},
[onStart, onNextAuthAttempt, onCaptured, onFinish],
);
const listener = OnewelcomeSdk.addEventListener(
Events.SdkNotification.Fingerprint,
handleNotification,
);
The SDK fires four event actions that notify you about the status of the fingerprint authentication.
Fingerprint Event | Description |
---|---|
StartAuthentication | Fired when a new fingerprint authentication request is made, providing a UserProfile object containing the profileId |
OnNextAuthenticationAttempt | Fired when a user provided an incorrect fingerprint but still hasen't reach the failed attempts limit |
OnFingerprintCaptured | Fired when a user scanned their fingerprint and the fingerprint validation is performed. That's a good moment to show an update on the UI informing the user about the received attempt. |
FinishAuthentication | Fired when fingerprint scanning finished either with success or an error. |
There are three methods to communicate the fingerprint flow to the SDK after fingerprint authentication has started.
SDK method | Description |
---|---|
OnewelcomeSdk.submitFingerprintAcceptAuthenticationRequest() | Should be called when a user accepts a fingerprint authentication request. |
OnewelcomeSdk.submitFingerprintDenyAuthenticationRequest() | Should be called when a user denies the fingerprint authentication request. |
OnewelcomeSdk.submitFingerprintFallbackToPin() | Should be called when a user decides to resign from fingerprint authentication and wants to enter their PIN to finish authentication. |
Note
In order to start the fingerprint authentication, you need to call submitFingerprintAcceptAuthenticationRequest()
. This can be done when you receive the startAuthentication
event action.
If the user fails to authenticate using fingerprint too many times (this limit is set by the OS), the fingerprint authenticator is automatically deregistered and the relevant tokens are revoked by the React Native SDK. At this point, a fallback to PIN is performed, and the user is requested to enter PIN.
Authenticating with biometrics on iOS
When starting biometric authentication on iOS, the user will be prompted to authenticate with TouchId or FaceId with a native prompt from the OS. Due to differences between how biometric authentication works on Android and iOS, we do not need any event listeners for iOS. The flow is handled by the promise from authenticateUser
resolving. The user can press the cancel button on the native biometric prompt, which will perform a fallback to PIN.