Tutorial: Authentication state

Serverless Authentication Authentication state

The Webcom Authentication Service basically maintains an authentication state that identifies the end-user currently signed in to a given Webcom application on a given device (where the Webcom client application is executed).

The Webcom SDK provides with proper APIs to:

Authentication model

graph LR AuthState --1--> AccountUid AuthState --1--> Token AuthState --1--> ExpirationDate AuthState --1--> SignedInIdentity SignedInIdentity --1--> CreationDate SignedInIdentity --0..1--> DisplayName SignedInIdentity --0..1--> ProviderProfile SignedInIdentity --0..1--> ExtraProviderData SignedInIdentity --1--> Provider SignedInIdentity --1--> ProviderUid AuthState --1--> Context Context --0..*--> AuthFactor AuthFactor --1--> Provider AuthFactor --1--> ProviderUid AuthFactor --1--> SignInDate classDef common fill:grey class Provider common class ProviderUid common classDef optional stroke-dasharray:5,5 class DisplayName optional class ProviderProfile optional class ExtraProviderData optional class AuthFactor optional

The authentication state (AuthState) gathers the following attributes about the currently signed in end-user:

  • AccountUid: unique identifier of the Webcom “account” associated with the end-user. This id is unique across all users of the Webcom application whatever the authentication method used to sign in. This id should be used within the application data to refer to the end-user.

  • Token: Webcom authentication token that encodes the current authentication state. If your application uses a specific backend, this token may be passed along to requests that require user privileges.

  • ExpirationDate: date that the authentication state (and hence the token) is valid until.

  • SignedInIdentity: “identity” used by the end-user to sign in (that is, the data recognized by some identity provider to identify the user). In Webcom model, identities in turn gather the following attributes:

    • Provider: gives the authentication method used to sign the user in. Each identity is associated to a unique and specific authentication method. Each authentication method corresponds to a specific “identity provider”, which can be external to Webcom platform. The complete list of available authentication methods or identity providers is given in the “Signing in and out” chapter.

    • ProviderUid: identifier representing the identity used to sign in. This identifier is unique relatively to the authentication method, that is, unique across all users that are authenticated by a given identity provider. However, the same identifier may refer to distinct users relatively to distinct providers. That's why this identifier is strongly discouraged to identify end-users within an application.

    • CreationDate: date/time when the identity was first associated to the Webcom account of the user. In other words, it is the creation date of the identity from the Webcom viewpoint (and not from the identity provider one).

    • DisplayName: optionally indicates (depending on the identity provider) a friendly display name for the signed-in user.

    • ProviderProfile: gives some optional additional information about the signed-in user, which is provided by the identity provider. This piece of information is completely specific to the authentication method.

    • ExtraProviderData: some optional sensible data, which are also provided by the identity provider. In contrary to the ProviderProfile, these are not stored persistently within the authentication state and are excluded from the Webcom authentication token. They typically include the user Access Token in case of an OAuth2-based authentication method.

  • Context: gives the list of other identities used by the end-user to authenticate within this authentication session. In other words, a user may authenticate with several identities. The Webcom Authentication Service actually implements multi-factor authentication using multi-identity authentication. Each authentication factor corresponds to an identity of the user. Each factor contained in the authentication “context” provides in turn the following pieces of information:

    • Provider: identity provider associated with the authentication factor,
    • ProviderUid: identifier of the user (relatively to the identity provider) associated with the authentication factor,
    • SignInDate: date when the user authenticated with this factor. It is useful for example to control that a secondary factor is not too old wrt. the main one.

    Thus, when the authentication context is empty, the user is authenticated with a single factor and this “main factor” is described by the Provider and ProviderUid attributes at the first level of the authentication state. When the authentication context contains n factors (n > 0), the user is authenticated with n+1 factors. The most recent factor is the one described by the Provider and ProviderUid attributes at the first level of the authentication sate, the second-to-last one is described by the first element of the Context attribute... and the oldest factor is described by the last element of the context attribute.

The Webcom SDK for JavaScript for JavaScript represents the authentication state using a JSON object with the following properties and correspondence to the authentication state attributes:

JSON property Mandatory
Optional
Type Authentication state attribute
uid M string AccountUid
webcomAuthToken M string Token
expires M number ExpirationDate expressed in seconds since Unix Epoch
provider M string SignedInIdentity / Provider
providerUid M string SignedInIdentity / ProviderUid
createdAt M number SignedInIdentity / CreationDate expressed in milliseconds since Unix Epoch
displayName O string SignedInIdentity / DisplayName
providerProfile O object SignedInIdentity / ProviderProfile given as a JSON object specific to the identity provider
extra O object SignedInIdentity / ExtraProviderData given as a JSON object specific to the identity provider
context M array Context
context[i].provider M string Context / Provider
context[i].providerUid M string Context / ProviderUid
context[i].signedInAt M number Context / SignInDate expressed in seconds since Unix Epoch

Only the displayName, providerProfile and extra properties are optional. The context property is mandatory but may be an empty array when the user is signed in with a single factor.

Note that this JSON object (without the webcomAuthToken and extra properties) is also embedded within the Webcom authentication token and is therefore passed to security rules.
Consequently, security rules can accommodate the authentication method or the available additional authentication factors used to sign in, as shown in this complete example.

The Webcom SDK for Android represents the authentication state using the AuthenticationDetails class with the following properties and correspondence to the authentication state attributes:

Attribute Type Authentication state attribute
uid String AccountUid
authenticationToken String Token
expirationDate java.util.Date ExpirationDate
provider AuthenticationFactor.Provider SignedInIdentity / Provider
providerUID String SignedInIdentity / ProviderUid
creationDate java.util.Date SignedInIdentity / CreationDate
displayName String? SignedInIdentity / DisplayName
providerProfile Map<String,String>? SignedInIdentity / ProviderProfile
extra ExtraIdentityDetails SignedInIdentity / ExtraProviderData
previousFactors List<AuthenticationFactor> Context

The Webcom SDK for iOS represents the authentication state using the AuthenticationDetails struct with the following properties and correspondence to the authentication state attributes:

AuthenticationDetails property Type Authentication state attribute
uid String AccountUid
authenticationToken String Token
expirationDate Date ExpirationDate
provider AuthenticationProvider SignedInIdentity / Provider
providerUID String SignedInIdentity / ProviderUid
creationDate Date SignedInIdentity / CreationDate
displayName String? SignedInIdentity / DisplayName
providerProfile [String: Any] SignedInIdentity / ProviderProfile
previousProviderIdentities [AuthenticationProviderIdentity] Context

Authentication callbacks

The main way to watch the current authentication state maintained by the Webcom Authentication Service is to register authentication callbacks. These functions are called each time the authentication state changes and are passed the authentication state.

If an authentication operation is performed but doesn't change the current authentication state, the callbacks are not called. If an authentication operation fails, then the current authentication state is unchanged (it remains in the previous state) and callbacks are called with the failure error.

Authentication callbacks in JavaScript are passed two parameters:

  • error: it is not null if the authentication operation that triggers the callback has failed. In this case, it is a JSON object with 2 mandatory properties: code (the error code, see the Error messages) and message (a non-localized human-readable message).
  • authState: it must be considered only if the error parameter is null. If so, it is either null if no user is currently signed in, or the JSON object representing the authenticated user if a user is currently signed in.

Authentication callback functions may be registered or unregistered using the subscribe() and unsubsribe() methods of the Authentication Service instance associated with your Webcom application instance. The following snippet shows a complete example (replace “<your-app>” with your actual application identifier):

// const app = Webcom.App("<your-app>"); // UNCOMMENT if you haven't yet an instance of your app!
// Get an instance of the authentication service
const auth = app.authentication;
// Define an authentication callback
const authCb = (error, authState) => {
  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 Webcom developer console.");
        break;
      default:
        console.log("An unexpected error occurs, please retry and contact your administrator.", error);
    }
  } else {
    console.log("Authentication succeeded");
    console.log("Authentication state", authState.state);  // "none"|"some"|"required"
    console.log("Authentication details", authState.details);
  }
};
// Register it
auth.subscribe(authCb);
// 'authCb' is called a first time with the current authentication state
// { ...
//     Within this fragment, 'authCb' is called each time the authentication state changes
// ... }
// Unregister it
auth.unsubscribe(authCb);

Authentication callbacks in Android are implemented by Kotlin lambdas of type (AuthenticationEvent> -> Unit. AuthenticationEvent event is a sealed class with the following subtypes:

They can be registered using the AuthenticationService.subscribe() method, and further unregistered using the cancel() method on the previously returned object.

val myApp = WebcomApplication.default // the app defined by the 'webcom.properties' asset file
val authenticator = myApp.authenticationService

val subscription = authenticator.subscribe { // it: AuthenticationEvent
    when (it) {
        is AuthenticationState.Authenticated ->
            print("${it.details.displayName} has logged in")
        is AuthenticationState.Unauthenticated ->
            print("The user has logged out")
        is AuthenticationState.Invalid ->
            print("The previous authentication has expired, waiting for logging in or out")
        is AuthenticationEvent.Rejected ->
            print("An authentication attempt has failed: ${it.data.error.errorCode}")
    }
}
// ...and then later...
subscription.cancel()

In Swift, authentication callbacks are functions receiving an AuthenticationEvent parameter.

This type is an enum with two cases:

  • .change indicates that the authentication state changed. This case has an AuthenticationState associated value.
  • .failure indicates that an authentication process failed. This case has a WebcomError associated value giving the cause of this failure.

The AuthenticationState enum has three cases:

  • .authenticated indicates that an end user has signed in. This case has an AuthenticationDetails associated value.
  • .invalid indicates that the end user authentication has expired, or it could not be restored when changing from offline to online. This case does not have an associated value.
  • .unauthenticated indicates that the end user has signed out. This case does not have an associated value.

Registering (resp. unregistering) an authentication callback consists in subscribing to (resp. unsubscribing from) an event corresponding to the change of the authentication state. Subscribing is done with the subscribe() method of an AuthenticationService object. Unsubscribing is done with the cancel() method of the AuthenticationSubscription object returned by the subscription.

The following snippet shows an example:

let authenticationService = Webcom.defaultApplication.authenticationService // application is configured in the `Info.plist` file
authenticationService.subscribe { event in
    // This code is called each time the authentication state changes.
    switch event {
    case let .change(state: .authenticated(details: details)):
        print("successfully authenticated as:", details.uid)
    case .change(state: .invalid):
        print("authentication expired")
    case .change(state: .unauthenticated):
        print("logout succeeded")
    case let .failure(reason: error):
        print("authentication failed:", error)
    }
}

Limitations

  1. The authentication state is purely local to the client device where the Authentication Service is executed, there is no central state (or session) maintained at the Webcom application level by the back end.
    For example, if the same user is signed in to your app both on a mobile phone and on a desktop web interface, then signing out from the mobile phone doesn't sign s/he out from the web interface.

  2. Only one end-user can sign in at a time to a given Webcom application instance on the same device.
    For example, if Mary signs in first to app A on a tablet, and then Peter signs in to the same instance of app A on the same tablet (within the same user session from the tablet OS viewpoint), then Mary is eventually signed out from app A and Paul signed in to app A.

  3. However, the same end-user can sign in to various application instances at a time on the same device.
    For example, Mary can sign in to both apps A and B on her tablet, or to two different instances of app A on her tablet.

  4. The authentication state of a given user for a given Webcom application instance on a given device is valid until:

    • either the user signs out from this application on this device,
    • or the corresponding authentication token expires.