User registration
This document explains adding user registration to your application. The SDK uses the OAuth 2.0 protocol to authorize the device to access protected resources. To support this protocol the SDK acts as an OAuth 2.0 client.
Prerequisites
To initialize authentication, the client credentials are required. These credentials are received via Dynamic Client Registration (DCR). As an app developer, there is no need to initialize DCR as it is part of the default implementations in the SDK.
As a timestamp is used within the DCR protocol, it is mandatory that the time on the device is equal to the time on the IDAAS-core, independent of time zones. In case of a wrong time, the SDK will return an error.
Start registration
User registration begins with enrolling a user on a device using a selected identity provider (IdP). The list of all possible IdPs for an app is configured in the IDAAS-core admin panel. The IDAAS-core also configures a default (primary) IdP that is used for backward compatibility.
To start user registration, you have to call the registerUser
method. This method will return a URL that must be opened in a browser where the registration can be continued. Which browser or webview to open for this is up to the developer.
interface OnewelcomeSdk {
registerUser(
identityProviderId: string | null,
scopes: String[],
): Promise<Types.Profile>;
// ...
}
OneWelcomeSdk.registerUser(providerId, ['read'])
.then(authData => {
console.log('Registration success! ')
})
.catch(err => {
console.error('Registration failed: ', err)
})
If registration in the browser is successful, the browser will return a link that has to be caught by React Native and passed to the SDK (for example, with React Native Linking). Resolve will be called when the whole flow is successfully finished and the PIN creation is handled successfully. This flow can differ depending on the IDP that you have chosen.
Registering the user
There are two distinct flows that can be done to register on a device:
- Browser-based registration
- Custom registration
To select an identity provider that will be used during the registration process, you need to pass its ID in the identityProviderId
parameter. To choose an identity provider, first you need to get all available providers. Call the method getIdentityProviders
to get a list with the available provider's ID. If this parameter isn’t specified, or if its value is null, the default identity provider set on the IDAAS-core will be used.
In some situations, you want to cancel the registration flow, restart it, or start a different one. You can cancel registration using cancelBrowserRegistration
and cancelCustomRegistration
.
Cancelling registration is only possible through these methods when PIN creation has not yet started. When it has, use the cancelPinCreation
method instead.
Registering with browser IdP
If the user tries to register with an identity provider (IdP) that is browser-based, the SDK needs to ask for an access grant to the IDAAS-core using the browser.
Opening a browser or webview
After starting registration, the app will receive a URL from the SDK. This URL will have to be opened in a browser, and authentication will have to be completed there to continue the registration. This URL is sent to the application in the form of an event that has to be listened to.
A simple implementation can be done using the ReactNative Linking library to open up a browser, handled by the system, where the registration can be handled.
import { Linking } from 'react-native';
const handleRegistrationURLEvent = useCallback(
async (event: Events.RegistrationURLEvent) => {
Linking.openURL(event.url);
},
[],
);
useEffect(() => {
const listener = OneWelcomeSdk.addEventListener(
Events.SdkNotification.Registration,
handleRegistrationURLEvent,
);
return () => {
listener.remove();
};
}, [handleRegistrationURLEvent]);
Handling the URL
After successfully authenticating in the browser on the supplied IdP, the browser will be redirected to a URL with a custom schema URL based on the provided schema URL in the SDK config. This URL will be treated by the operating system as a DeepLink
. The application will have to catch this and pass it back to the SDK using the handleRegistrationCallback
method.
To receive this DeepLink
, you will first have to enable DeepLinks in your application.
Note
You can easily add the required configuration for your info.plist
for iOS and AndroidManifest.xml
for Android with the uri-scheme package built by Expo.
You will also be able to use this package to test DeepLinks in your application.
import { Linking } from 'react-native';
useEffect(() => {
const handleOpenURL = (event: any) => {
if (event.url.substr(0, event.url.indexOf(':')) === linkUri) {
OneWelcomeSdk.handleRegistrationCallback(event.url)
}
}
Linking.addListener('url', handleOpenURL)
return () => Linking.removeListener('url', handleOpenURL)
}, [])
Registering with custom IdP
When a user tries to register with an identity provider (IdP) that has a custom API type, it has to be enabled and configured on the IDAAS-core side, and implemented in the app itself. Usually when the custom IdP is created on the server side, you will also provide the server side script for handling the registration process on both client and server side.
The MSP platform expects that the registration process can have either one or two steps.
One-step registration
In case of one-step registration, the SDK asks the app for optional registration data. The data is sent to the IDAAS-core, where the custom registration script is executed. The result of the custom script (status code and optional data) is sent back to the SDK and the registration result is propagated to the app in the form of an event.
Two-step registration
In case of two-step registration, the SDK asks the app for optional initial registration data. The data is sent to the IDAAS-core where the custom registration is initialized. The optional initialization result is sent back to the SDK. Then the SDK asks the app for a registration data, providing the optional initialization data provided by the IDAAS-core. The registration data is sent to the IDAAS-core, where the custom registration script is executed. The result of the custom script (status code and optional data) is sent back to the SDK and the registration result is propagated to the app.
Note
To use the custom identity providers, they need to be registered as a one or two-step IdP during initialization of the SDK.
Start registration
To start registration with a custom IDP, you should call the OneWelcomeSdk.registerUser
function, similar to registration with a browser IDP, with the custom identity provider ID string.
Handling events
The SDK will communicate back to React Native about the current steps of the custom registration. You will need to listen for the Events.SdkNotification.CustomRegistration
event and handle the initRegistration
and finishRegistration
actions appropriately.
const [codeFromOnegini, setCodeFromOnegini] = useState<string | null>(null);
const IdProvider = '2-way-otp-api';
// two-step registration
const listener = OneWelcomeSdk.addEventListener(Events.SdkNotification.CustomRegistration, (event: events.CustomRegistrationNotificationEvent) => {
if (event.identityProviderId === IdProvider) {
switch (event.action) {
case Events.CustomRegistration.InitRegistration:
// for a TwoWayOTP the initialization request doesn't contain data
OneWelcomeSdk.submitCustomRegistrationAction(
event.identityProviderId,
null,
);
break;
case Events.CustomRegistration.FinishRegistration:
// for a TwoWayOTP the initialization result contains the challenge code
if (event.customInfo) {
setCodeFromOnegini(event.customInfo.data);
}
setVisible(true);
break;
}
}
});
export type finishRegistrationEvent = {
action: CustomRegistrationNotification.FinishRegistration;
identityProviderId: string;
customInfo?: {
data: string;
status: number;
};
};
Communication back to the SDK is done through the OneWelcomeSdk.submitCustomRegistrationAction
method. This method has the following signature.
interface NativeMethods {
submitCustomRegistrationAction(
identityProviderId: string,
token: string | null,
): void;
//...
}
The example above does not require any initialization data, so calls the submitCustomRegistrationAction
method with a null token. After that, the SDK will send a FinishRegistration
event with a customInfo
object.
The CustomInfo
object contains a status code and an optional data provided by the backend script. The first step of the registration flow will always return null CustomInfo
. This means that the object will be null in the finishRegistration
method of the one-step registration flow and in the initRegistration
event of the two-step registration. The only exception to this rule is a retry of the registration step: in case of a recoverable error returned by the SDK, the CustomInfo
object in the retried step will contain the error info. There are three groups of status codes that can be returned in the CustomInfo
object:
- success status (2XXX) - when the status code is in the rage of 2000 - 2999, the registration step has been finished successfully.
- recoverable errors (4XXX) - when the status code is in the range 4000 - 4999, the flow can be recovered and the SDK send an event with the
initRegistration
orfinishRegistration
action depending on the step that has caused the error. - unrecoverable errors (5XXX) - when the status code is in the range 5000 - 5999, the flow cannot be recovered.
After responding to the FinishRegistration
event with a submitCustomRegistrationAction
, the SDK will send a PIN event which has to be handled to create a PIN and finish the registration.
Create PIN
After completing the flow for browser based or custom registration, you register a PIN to complete the registration. This is communicated by the SDK to React Native through events. The app will have to listen to these events and respond to them accordingly.
Example - listening for PIN events
const handleCreateNotification = useCallback(
async (event: Events.PinCreateEvent) => {
console.log('handle PIN notification event: ', event);
switch (event.action) {
case Events.PinCreate.Open:
await handleCreateOpen(event);
break;
case Events.PinCreate.Close:
setInitialState();
break;
case Events.PinCreate.PinNotAllowed:
handlePinNotAllowed(event);
break;
}
},
[handleCreateOpen, setInitialState, handlePinNotAllowed],
);
useEffect(() => {
const createListener = OnewelcomeSdk.addEventListener(
Events.SdkNotification.PinCreate,
handleCreateNotification,
);
return () => {
createListener.remove();
};
}, [handleCreateNotification]);
After receivingEvents.PinCreate.Open
, the SDK expects the app to supply a PIN. You can provide this PIN with the submitPin
method.
Example - submitting the user PIN
interface OnewelcomeSdk {
submitPin(
flow: Events.PinFlow,
pin: string | null,
): void;
// ...
}
OnewelcomeSdk.submitPin(Events.PinFlow.Create, '12345');
If everything completes, registerUser
will resolve with an AuthData
object containing the profile ID and optional custom info string.
After receivingEvents.PinCreate.Open
, the SDK expects the app to supply a PIN. You can provide this PIN with the submitPin
method.
Choosing an identity provider
To select an identity provider that will be used during the registration process, you need to pass its ID in the identityProviderId
parameter. To choose an identity provider, first you need to get all available providers. Call the method getIdentityProviders
to get a list with available provider IDs. If this parameter isn’t specified, or if its value is null, the default identity provider set on the IDAAS-core will be used.
Cancel registration
In some situations, you want to cancel the registration flow, restart it, or start a different one. You can cancel browser registration and custom registration by their corresponding cancel methods, cancelBrowserRegistration
and cancelCustomRegistration
.
Canceling registration is only possible through these methods when PIN creation has not yet started. When it has, use the cancelPinCreation
method instead.
Deregistering users
The React Native SDK exposes the deregisterUser
function to deregister a user.
Deregistering a user implies the removal of all of their data (including access tokens and refresh tokens) from the device. The SDK will also send a request to the IDAAS-core to revoke all tokens associated with the user. The client credentials will remain stored on the device.
Example code to deregister a user
OneWelcomeSdk.deregisterUser(profileId)
.then(() => console.log('Deregister succeed!'))
.catch(error => console.error('Deregister failed: ', error.message))
Note that any existing user can be deregistered. They do not necessarily have to be logged in.