Tutorial: Custom login

Serverless AuthenticationSigning in and out Custom login

The custom login method makes it possible to use an external trusted and managed system (or custom provider) to authenticate a user within a Webcom application.

More precisely, the client application authenticates the user with the custom provider following a process specific to this provider. The provider replies with a signed identity token, which contains the identity details of the authenticated user, but which is not a Webcom authentication token (i.e. it cannot be used to authenticate on a Webcom application). The client application then requests the Webcom authentication service for exchanging this identity token against a regular Webcom authentication token.

sequenceDiagram participant P as External Provider participant A as Application participant B as Webcom Back End A ->> P: Authenticate the user P ->> A: Identity token A ->> B: Request authentication API with identity token B ->> A: Webcom authentication token

Configuring a custom provider

First of all, in the Webcom developer console, you must enable the "custom login" method within the "authentication" tab.

Then you can add a new custom provider assigning it a unique name (identifier). When created, it is assigned a secret key by the Webcom authentication service, which is intended to be shared with the custom provider. You can't read it in the Webcom developer console UI (as it is secret), but you can copy it to the clipboard using the dedicated button.

You will then have to paste it within the code of your custom provider, so that the generated identity tokens are signed with this secret key.

The Webcom developer console UI makes it possible to generate a new secret for a given custom provider at anytime. In this case, don't forget to update accordingly the part of the code of your custom provider that signs the generated identity tokens.

Generating an identity token

The identity tokens expected by the Webcom authentication service are JSON Web Tokens (JWT). They can be easily forged using one of the many available libraries (you can start from Wikipedia for a quick overview).

Identity tokens must be signed with the SHA-256 HMAC algorithm and include the following claims:

Claim Mandatory
Optional
Type Description
iat M number Date the token was issued, expressed in seconds since the Unix epoch.
exp M number Date until which the token is valid, expressed in seconds since the Unix epoch. Login will fail with an expired token.
nbf O number Date from which the token is valid, expressed in seconds since the Unix epoch. If not set, it defaults to iat.
d M object Identity details about the authenticated end user (see below).

Even if identity tokens can freely include any data, they shall be less than 1024 characters.

The data claim d:

  • must include:
    • the provider property that equals the customer provider identifier assigned within the Webcom developer console (as a string),
    • the providerUid property that uniquely identifies the user from the customer provider viewpoint (as a string).
  • may optionally include:
    • the providerProfile property that represents any profile data about the identified user. Any other properties are ignored by Webcom.

Login with an identity token

If the identity used to log in is not bound to any Webcom account, then a new account is automatically created (its id can be retrieved with the uid field) and the identity is bound to it.

Use the following snippet to authenticate an end user with an identity token (replace “<your-app>” with your actual application identifier). If the identity used to sign in is not bound to any Webcom account, then a new account is automatically created and the identity is bound to it (see Signing up using third-party login).

var ref = new Webcom("<your-app>");
// Authenticate the user with the custom provider
var idToken = getAnIdentityTokenFromMyCustomProvider(mycredentials); 
// Sign in using the returned idToken
ref.authWithCustomProvider("<your-provider-name>", idToken)
   .then(auth => console.log("Authentication succeeded", auth))
   .catch(error => {
      switch (error.code) {
        case "INVALID_TOKEN":
          console.log("Authentication failed, check your credentials!");
          break;
        default:
          console.log("An unexpected error occurs, please retry and contact your administrator.", error);
      }
    });

The auth parameter returned in the promise of the authWithCustomProvider() method is a JSON object representing the signed in identity, which directly feeds the current authentication state. The following properties are specialized this way:

Property Type Description
provider string Equals "custom.<your-provider-name>", where <your-provider-name> is the custom provider identifier defined in the Webcom developer console.
providerUid string The internal user identifier provided by the custom provider within the identity token.
providerProfile object (optional) The user profile provided by the custom provider within the identity token (if any).
displayName string (optional) A human-readable description of the authenticated end user extracted from the previous profile data. It can be missing if no description can be found.
Webcom ref = new Webcom(new WebcomApp("<your-app>"));
String idToken = getAnIdentityTokenFromMyCustomProvider(mycredentials);
ref.authWithCustomProvider("<your-provider-name>", idToken, new OnAuth(){
  @Override
  public void onComplete(@Nullable AuthResponse response) {
    // End user authenticated
  }
  @Override
  public void onError(WebcomError error) {
    // End user not authenticated
  }
});
let authenticationService = Webcom.defaultApplication.authenticationService
let credentials = credentialsForMyCustomProvider(...)
let customMethod = AuthenticationMethodCustom(providerIdentifier: "<your-provider-name>", credentials: credentials)
authenticationService.authenticate(with: customMethod) { result in
    switch result {
    case let .success(details):
        print("Logged in with the account:", details.uid)
    case let .failure(error):
        print("Error:", error)
    }
}