Tutorial: Authentication

Step by step Authentication

The authentication component makes it possible to reliably identify application users, in order to finely control their access to data. It additionally retrieves user identity details, which can then be used by applications to customize their behavior (user experience, specific configuration...).

Four authentication methods are currently available:

  • anonymous login, which associates a temporary (virtual) user to each connection,
  • basic email/password login, based on an internally managed base of emails and passwords,
  • implicit login of mobile devices (only for Orange customers), based on the mobile data network and the SIM card of the device,
  • standard authentication delegation, based on the OAuth2.0 standard for authorisation (including OIDC and Mobile Connect),
  • custom authentication delegation for platforms that have their own specific authentication mechanism.

Each method returns:

  • an identity (or providerUid), which is a user identifier unique within each authentication method,
  • a [[service]] account (or uid), which is a user identifier unique across all authentication methods for a given application.

Several identities may be bound to the same [[service]] account. For example, the same end user can log in using either her/his email (with the email/password method) or her/his facebook login (with the standard authentication delegation method). Applications should therefore rely on accounts/uid rather than identities/providerUid.

Use the best suited authentication method

Here are the detailed step by step guides for each available authentication method. Choose the one that best fits your needs:

Method Description
Anonymous login Authentication without creating an actual account. This method allows to protect users' data for the duration of a "guest" session only.
Email login [[service]] own authentication, based on email & password.
Implicit mobile login (for Orange customers only) Authentication based on the mobile device and the mobile data network used.
OAuth2 login Authentication delegation to an OAuth2.0 compliant third-party identity provider.
Custom login Authentication delegation to an existing specific third-pary authentication system. It allows to integrate with any other authentication component.

Each authentication method can be enabled (or disabled) and setup in the "authentication" tab of the [[console]].

Authentication information

In a [[service]] application, you can register an authentication callback, and later unregister it, using the following snippet [[snippet]]:

// Create a connection to the back-end
var ref = new Webcom("[[baseUrl]]/base/<your-app>");
// Define an authentication callback
var authCb = function(error, auth) {
  if (error) {
    switch (error.code) {
      case "INVALID_CREDENTIALS":
        console.log("The email or password is incorrect.");
        break;
      case "PROVIDER_DISABLED":
        console.log("The email/password method is disabled in the application. It must be enabled in the [[console]].");
        break;
      default:
        console.log("An unexpected error occurs, please retry and contact your administrator.", error);
    }
  } else {
    console.log("Authentication succeeded", auth);
  }
};
// Register it
ref.registerAuthCallback(authCb);
// { ...
// Within this fragment, 'authCb' is called each time the authentication state changes
// ... }
// Unregister it
ref.unregisterAuthCallback(authCb)
// Create a connection to the back-end
try {
    Webcom ref = new Webcom("[[baseUrl]]/base/<your-app>");
    OnAuth listener = new OnAuth() {
        @Override
        public void onComplete(@Nullable AuthResponse response) {
            if(response == null){ // Successfull Logout
                System.out.println("Logout succeeded");
            } else{ // Successfull login
                System.out.println("Authentication succeeded");
            }
        }
        @Override
        public void onError(WebcomError error) {
            System.out.println(error.getMessage());
        }
    };
    ref.registerAuthCallback(listener);
    // { ...
    // Within this fragment, 'listener' is called each time the authentication state changes
    // ... }
} catch (WebcomException e) {
    e.printStackTrace();
}

The authentication callback is called each time the authentication state changes (typically when a user is logged in or out or the user session expires).

When a login operation fails, the error parameter receives a JSON structure describing the encountered failure with two mandatory attributes: code and message (the table at the end of this page gives the most usual error codes):

{
  "code": "INVALID_TOKEN",
  "message": "The requested operation cannot be fulfilled because the content or privilege of the provided token is invalid."
}

When a user is successfully logged in, the auth parameter receives a JSON structure representing the identity used to log in with the following fields:

Field Type Description
webcomAuthToken String The [[service]]-signed authentication token for this session.
expires Number Expiration date of the session token (in seconds since the Unix epoch).
provider String The authentication method used to log in (e.g. password, facebook...).
providerUid String The ID of the identity used to log in. It is unique within a given authentication method.
createdAt Number The date (expressed in seconds since the Unix epoch) of creation of the identity used to log in (warning: this is not the creation date of the user account).
uid String The user account ID. It is unique across all authentication methods.
displayName String (optional) a human-readable description of the logged in user.

Depending on the authentication method, some additional fields may be provided, see the documentation of each available authentication method for more details.

The generated authentication token contains itself a subset of the above JSON structure, with at least the provider, providerUid and uid fields. It may contains additional fields specific to the authentication method used. This structure is passed to security rules within the auth variable (which is different from the auth parameter of the authentication callback) when a user is logged in (or null if no user is logged in). Security rules can therefore be easily adapted to the authentication method used or the [[service]] account uid associated to the logged in end user, as shown in this complete example.

When a login operation fails, the onError method is called.The WebcomError contains a message with the root cause of the error.

When a user is successfully logged in, the onComplete method is called with a non null response.

When a user is successfully logged out, the onComplete method is called with a null response.

Resume

When starting an application or an activity, it is often useful to resume the authentication state, that is, refresh it from the last authentication token stored within the local (or app) storage. Typically, if it is still valid, it can be reused for authentication without requiring the user to re-authenticate explicitly.

If some authentication callbacks are registered before resuming, then they are invoked with the resumed state.

// Create a connection to the back-end
var ref = new Webcom("[[baseUrl]]/base/<your-app>");
// Register an authentication callback
ref.registerAuthCallback(myAuthCb);
// Resume
ref.resume();
// 'myAuthCb' will be called with the resumed authentication state
try {
    // Create a connection to the back-end
    Webcom ref = new Webcom("[[baseUrl]]/base/<your-app>");
    // Register an authentication callback
    ref.registerAuthCallback(myOnAuthListener);
    // Resume
    ref.resume();
    // 'myOnAuthListener' will be called with the resumed authentication state
} catch (WebcomException e) {
    e.printStackTrace();
}

Login & logout

The login procedure directly depends on the authentication method. For example, with email/password authentication method, use the following snippet [[snippet]]:

// Create a connection to the back-end
var ref = new Webcom("[[baseUrl]]/base/<your-app>");
// Log in
ref.authWithPassword({
  email    : "macadamia@webcom.com",
  password : "my-password"},
  function(error, auth) {
    if (error) {
      switch (error.code) {
        case "INVALID_CREDENTIALS":
          console.log("The email or password is incorrect.");
          break;
        case "PROVIDER_DISABLED":
          console.log("The email/password method is disabled in the application. It must be enabled in the [[console]].");
          break;
        default:
          console.log("An unexpected error occurs, please retry and contact your administrator.", error);
      }
    } else {
      console.log("Authentication succeeded", auth);
    }
  });
try{
    // Create a connection to the back-end
    final Webcom ref = new Webcom("[[baseUrl]]/base/<your-app>");
    final OnAuth listener = new OnAuth(){
        @Override
        public void onComplete(@Nullable AuthResponse authResponse) {
            Log.v(TAG,"onComplete");
            Log.v(TAG,"uid :" + authResponse.getUid());
        }
        @Override
        public void onError(WebcomError webcomError) {
            Log.v(TAG,"onError");
            Log.v(TAG,"Error : " + webcomError.getMessage());
        }
    };    
    ref.authWithPassword("macadamia@webcom.com", "my-password", listener);
} catch (Exception e) {
    Log.e(TAG, e.getMessage(), e);
}
// Create a connection to the back-end
let ref = WCWebcom(url: "file://io./base/<your-app>")
ref?.auth(withMail: "macadamia@webcom.com", andPassword: "my-password", andRememberMe: false, onComplete: { (error, auth) in
            if (error != nil){
                print(error.debugDescription)
            }else {
               print("Authentication succeeded  Token  : , \(auth!.authToken)");
               print("Authentication succeeded  Email  : , \(auth!.email)");
            }

        })

The logout procedure is common to all authentication methods, simply use the following snippet [[snippet]]:

// Create a connection to the back-end
var ref = new Webcom("[[baseUrl]]/base/<your-app>");
// Log out
ref.logout(function (error) {
   if (error) {
     console.log("The log-out failed: " + error.message);
   } else {
     console.log("Logged out successfully!");
   }
});
try{
    // Create a connection to the back-end
    final Webcom ref = new Webcom("[[baseUrl]]/base/<your-app>");
    ref.logout(new OnComplete(){
       @Override
       public void onComplete() {
            Log.v(TAG,"logout complete ");
       }
       @Override
       public void onError(WebcomError error){
            Log.v(TAG,"onError : " + error.getMessage());
       }       
    });
} catch (Exception e) {
    Log.e(TAG, e.getMessage(), e);
}
let ref = WCWebcom(url: "file://io./base/<your-app>")
ref?.logout(callback: { (error) in
            if (error != nil){
                print("The log-out failed: \(error.debugDescription) ")
            }else {
                print("Logged out successfully!")
            }
        })

Automatic reconnection

When the Internet connection is lost and returns, the [[service]] clients will automatically re-authenticate to the server.

Multiple authentications

Several authentications on the same [[service]] database with different credentials simultaneously is not possible, even on different [[service]] references. The authentication state is global and applies to all references to a given [[service]] database. However, references to different [[service]] databases can authenticate independently.

Authentication errors

This table gives the most common error codes passed to the error parameter of the authentication callback (the list is not exhaustive):

Error Code Authentication
Methods
Description
UNKNOWN_APPLICATION all The authentication request was on an nonexistent [[service]] application.
PROVIDER_DISABLED all The authentication method is disabled for the application. You must enable it in the "authentication" tab of the [[console]].
INVALID_PROVIDER_SETTINGS all The settings of the authentication method to update are invalid.
INVALID_CREDENTIALS
INVALID_PASSWORD (sdk≤1.3.2)
email The given email or password are incorrect.
IDENTITY_TEMPORARILY_LOCKED email There have been too much signin failure with this identity. It will be locked down in a while.
MISSING_EMAIL_OR_PASSWORD email The authentication request is missing email or password.
EXISTING_IDENTITY
EMAIL_TAKEN (sdk≤1.3.2)
email The identity to create cannot be created because an identity with the same email already exists.
UNVERIFIED_IDENTITY
UNVERIFIED_ACCOUNT (sdk≤1.3.2)
email The identity used to log in has not been verified.
TOO_WEAK_PASSWORD email The provided password is not strong enough (when creating an email/password identity or updating a password).
UNSUPPORTED_PROVIDER OAuth2 The OAuth2.0 identity provider is not supported by [[service]].
MISSING_PARAMETER OAuth2 The authentication request is missing some parameter.
UNAUTHORIZED_REQUEST_ORIGIN OAuth2 The authentication request was emitted from a non approved web origin. Authorized origins can be set in the "authentication" tab of the [[console]].
INVALID_STATE OAuth2 The state parameter of the authentication request is invalid (maybe the request was intercepted by some unwanted people).
INVALID_TOKEN custom The token used to authenticate is invalid (may be bad-signed, expired or with wrong information).