Authenticators

There are many ways a Salesforce Session can be started :
  1. User login with username and password
  2. Passwordless authentication (email, sms, ...)
  3. Third party authentication providers
  4. Connected Apps access_tokens with web scope
Community Authenticators allow you to control which ones could be used with CYM-Identity.
By default, onboarding a community will create the Password authenticator and all Auth. Providers/SAML providers defined in the Salesforce Community setup pages.
You can visit our Github repo for a sample authenticator which uses Twilio Verify

Salesforce Authenticators

The package has all the authenticators required to manage standard Salesforce authenticators
  1. Password
  2. Passwordless Email
  3. Identity Verification with the default Salesforce Email
  4. Passwordless SMS
  5. Identity Verification with the default Salesforce SMS
  6. Identity Verification with TOTP
  7. Identity Verification with Salesforce Authenticator Push Notification
  8. Login with Third Party Identity Providers ( Auth. Providers and SAML providers )
  9. Web Sessions initiated by Connected Apps (using the frontdoor.jsp mechanism)
Note that Certificate based authentication is currently not supported

CYM Authenticators

CYM Identity also adds an extra authenticator leveraging WebAuthn.
WebAuthn brings strong customer authentication to the Web using platform specific authenticators (Touch ID (iOS, iPadOS, macOS), Screen Lock (Android) or Windows Hello) in addition to cross platform authenticators (Security Keys like Yubikeys).
You can visit our Github repo for a sample experience which uses WebAuthn to challenge users with Touch ID and Screen Lock.

Create your own

While we try to cover most use cases, you are in control of your business and we give you the necessary tools to build your own Authenticators

Declare an authenticator provider

The first object to create is an authenticator provider. It's created as a record in the cym__Authenticator__mdt metadata Object.
cym__Authenticator.MyOwnProvider.md-meta.xml
<?xml version="1.0" encoding="UTF-8"?>
<CustomMetadata xmlns="http://soap.sforce.com/2006/04/metadata" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<label>My Own Provider Label</label>
<protected>false</protected>
<values>
<field>cym__config_ui__c</field>
<value xsi:type="xsd:string">myProviderConfig</value>
</values>
</CustomMetadata>
Besides the DeveloperName which must be unique, it only provides the name of a LWC component which captures the configuration data of each authenticator which uses this provider.
The DeveloperName for each authenticator provider links to the class which handles the authenticator runtime, meaning it's the class which will be used to initialize and verify user authentication.
The DeveloperName must be in the form ClassName_InnerClassName where :
ClassName: The apex class name of the authenticator provider
InnerClassName: The InnerClassName of the authenticator provider. If it doesn't apply, then the name is just ClassName
If your org has a namespace then you must use it as a prefix namespace_ClassName_InnerClassName
You can visit our Github repo for a Twilio Verify sample.

Configuration LWC

As per the section above, you'll have to create an LWC which captures the authenticator data.
It's up to you to define what data is required. You can skip this section if your authenticator doesn't need any data to execute.
You can read and save an authenticator configuration data using AdministrationContext Apex class.
myProviderConfig.js
import { LightningElement, api } from 'lwc';
import getAuthenticatorConfig from '@salesforce/apex/MyAuthenticator.getAuthenticatorConfig';
import saveAuthenticatorConfig from '@salesforce/apex/MyAuthenticator.saveAuthenticatorConfig';
export default class MyProviderConfig extends LightningElement {
@api recordId; // The recordId of the current Authenticator
config = {};
loading = true;
// Read the existing configuration of the authenticator
connectedCallback() {
getAuthenticatorConfig({authenticator_id : this.recordId})
.then((config) => {
this.config = config || {};
this.loading = false;
})
.catch((_) => {
this.loading = false;
this.notifyUser('Error', `An error occured while loading the authenticator information.`, 'error');
});
}
handleSomeAttributeChange(e) {
this.config = Object.assign({}, this.config, {someAttribute: e.target.value});
}
handleSave() {
this.loading = true;
saveAuthenticatorConfig({authenticator_id : this.recordId, config: this.config})
.then(config => {
this.loading = false;
this.config = config || {};
this.notifyUser('Success', 'Configuration Saved', 'success');
})
.catch((_) => {
this.loading = false;
this.notifyUser('Error', `An error occured while saving.`, 'error');
});
}
}

The below Apex class shows how to read and save an authenticator's configuration
MyAuthenticator.cls
public with sharing class AuthenticatorConfigController {
@AuraEnabled
public static Map<String,Object> getAuthenticatorConfig(Id authenticator_id){
return (Map<String,Object>) cym.AdministrationContext.getContext().getCommunityAuthenticatorConfig(authenticator_id);
}
@AuraEnabled
public static Map<String, Object> saveAuthenticatorConfig(Id authenticator_id, Map<String, Object> config){
cym.AdministrationContext.getContext().saveCommunityAuthenticatorConfig(authenticator_id, config);
return config;
}
}

Creating an Authenticator Provider

The next step is to create an Apex class which handles the authenticator runtime.
This class must extend AuthenticatorProvider base class.
This class must be marked as global
MyAuthenticatorProvider.cls
global class MyAuthenticatorProvider extends cym.Community.AuthenticatorProvider {
global Object initRegistration (cym.Browser.Session session, Map<String, Object> param) { return null; }
global Object verifyRegistration(cym.Browser.Session session, Map<String, Object> param) { return null; }
global Object initVerification (cym.Browser.Session session, Map<String, Object> param) { return null; }
global Object verifyVerification(cym.Browser.Session session, Map<String, Object> param) { return null; }
}

Add an authenticator to your community

Now that you have created your provider, you can add the authenticator to your community.
See Community Reference for details

Integrate the new authenticator into the UI

It's up to you to define how users are challenged with your authenticator.
Once the user completed the challenge successfully, you can add this information to the CYM Identity session
public with sharing class ChallengeController {
public static Object verifyMyProvider() {
cym.Community.Authenticator authenticator = (cym.Community.Authenticator) cym.Community.getCurrent().authenticators.find('name', 'authenticator_name');
cym.Browser.Session session = (cym.Browser.Session) cym.Browser.getCurrent().sessions.find('ownerId', UserInfo.getUserId());
return authenticator.provider.verifyVerification(session, someParameters);
}
}