Embedding Web phone
General
When the webphone is embedded inside another web application, it can be done in two ways:
Load the code in the parent page and render the custom
<webrtc-client-ui />
directlyRender an
<iframe />
containing the phone on the parent page
The first approach is used in the stand-alone webphone https://phone.enreachvoice.com
When embedding to the other external system, the second method is usually used.
Note that refreshing page having webphone embedded, will disconnect all ongoing calls and forces re-login.
Check https://gitlab.com/benemen/public/webrtc-samples for tampermonkey demo scripts for how to use webphone JavaScript API, including how to use different login methods.
Authentication
Webphone can authenticate user with following methods:
Classic username & password authentication
Modern OAuth2/OpenId Connect based authentication. Recommended!
Impersonation token authentication
Classic username and password authentication
The default option is to display a login form in which the user enters a username and password. Webphone does authentication to REST API with entered details.
This is the easiest option to get started with embedding webphone development, but is not often usable in real production use.
Username and password authentication can also be done using Javascript API method loginUsingUsernameAndPassword()
Â
Modern authentication
The preferred option for authentication is to use OAuth2/OpenIdConnect based authentication via Enreach Identity.
Enreach Identity works in two modes:
Local identity provider mode
The password of the user is stored in Enreach Identity
When a user is authenticating, login form is shown from https://id.enrachvoice.com
External identity Provider mode
Identity is integrated with an external Identity provider
When a user is authenticating, the login form is shown from the external IdP
Currently, Enreach Identity can be linked to Microsoft Entra ID (formerly known as Azure AD). This enables a seamless Single Sign-On experience for organizations using Microsoft 365 services.
Â
Â
Impersonation token-based authentication
There is also an option to use https://doc.enreachvoice.com/beneapi/#impersonation. In this scenario, a separate backend integration is required. This backend service must have a separate API account with impersonation permission for all agents. When a user needs to log in to the webphone, the backend service retrieves an impersonation token for a user, and the webphone uses this token to access EnreachVoice core services as an end user.
Impersonation permissions are very powerful. Extra caution must be taken when securing the backend API account and authenticating users.
This approach is not recommended for new implementation.
Modern authentication requirements
In all embedding cases, proper ClientId must be provisioned on the Enreach Identity.
By convention, clientId is the fully qualified domain name (FQDN) of the web application.
ClientId configuration to Enreach Identity is done by the Enreach Delivery team.
Authentication flow handling
The simple way to log in is to use webrtc.loginUsingSSO("user.name@anything.com")
. This is, however, usually undesirable in embedding context, because:
The phone sits in the iframe and cannot do a full page redirect
Redirecting inside the iframe does not work when the customer is using an external IdP (Azure) that does not allow rendering the Azure login form inside an iframe for security reasons.
Supposedly, we don’t want to do a full page redirect to Enreach Identity on login even if we rendered the phone in the parent context
The solution is to handle the authentication flow explicitly in the parent page (CRM Frontend) context.
Â
Enreach Identity is backed by Keycloak and the phone uses the keycloak-js Javascript adapter. The phone also supports passing in a pre-authenticated keycloak.js
object.
This enables the parent page to use for example a pop-up window to log in.
High-level flow
Retrieve user authentication information from discovery service
If
authority
is null -> user is not enabled for Modern AuthenticationOtherwise, it points to the authentication realm of the user
If
authorityIdPHint
is null → user is using local IdP.Otherwise user is configured to use an external IdP such as Azure
Create keycloak object based on discovery results
Check if SSO-session is already ok
If ok → pass it to the webphone
If not → Open IdP-specific authentication dialog
See reference implementations below
Reference Implementations for Modern Authentication
Voice for D365
The steps of authentication on code level:
Set up Keycloak object:
Query user’s context info from discovery service, to get identity url and idpHint:
var discoUrl = 'https://discover.enreachvoice.com/api/user/?user=' + username; var discoResponse = await fetch(discoUrl); if (!discoResponse.ok) { var errData = await discoResponse.json(); var errorMsg = ''; for (const key in errData.errors) { errorMsg += errData.errors[key].message; errorMsg += ' '; } throw new Error(`Login process failed with username: ${username}. ${errorMsg}`); } else { discoResponse = await discoResponse.json(); } const data = discoResponse[0]; if (!Object.hasOwn(data, 'authority') || !data.authority) { throw new Error(`Login with SSO not supported. User "${username}" not migrated to Enreach Identity.`); } const identityUrl = new URL(data.authority);
Create Keycloak object
This snippet creates loginParams and Keycloak objects based on the data received from discovery.
loginParams object is not used by Keycloak initialization now, but login flow later on.loginParams = { loginHint: username, redirectUri: "https://appname.azurwebsites.net/authproxy" }; if (data.authorityIdPHint) { loginParams.idpHint = data.authorityIdPHint; } keycloak = new Keycloak({ url: identityUrl.origin, realm: identityUrl.pathname.split('/')[2], clientId: window.location.host });
Attempt login with check-sso
Initialize Keycloak and do a silent check (check-sso) if a user session is active atm.
var authenticated = await keycloak.init({ onLoad: ('check-sso'), scope: 'beneapi' });
Pass Keycloak object to WebRTC (see step 6), or open auth dialog if not authenticated
Authenticate within pop-up
The reason for the need for pop-up (instead of carrying out auth flow in an embedded iframe) is that AzureAD (for security reasons) can’t be loaded within an iframe.Open pop-up
Keycloak object returned the login Url in the previous code snippet. It contains the redirect Url as well, passed in the first snippet. The Url returned by keycloak.createLoginUrl() will point to Keycloak server.Receive response
Keycloak manages the authentication flow: redirects the user to AzureAD (if necessary), then redirects back to the value pointed by redircetUri param (see first snippet).Validate response
The response received in the query string on redirect page needs to be checked: code parameter being present means successful authentication.
Send a signal to opener page about the outcome of authentication using postMessage mechanism.
Receive postMessage in the parent window
The parent (opener) window hooks up an event listener when initializing:If embedded opener page received info about successful authentication (
event.data.ok == true
), steps 3 and 4 are repeated. Carrying out check-sso again will now returnauthenticated=true
Pass Keycloak object to WebRTC
Voice for SalesForce
In Salesforce the system controls the iframes (connector iframe, login iframe) from process perspective so the login process with keycloak needs to be handled in it’s own iframe.
In Connector iframe, signal SF to load the login iframe.
Get the Keycloak client-id and username from SF.
Do the discovery to EnreachVoice API and setup Keycloak object
Init Keycloack object with check-sso.
If uthenticated session found => jump to step 5.
If no session found
Show login button which opens popup onclick with login url defined in Keycloak object.
After login the Keycloak redirects user to redirect page defined in Keyclock object.
In redirect page signal Login iframe.
Execute Keycloak init again in Login iframe (step 4).
Signal Connector iframe that user has an active authenticated session.
Connector iframe tells WebRTC (hosted in Connector) to login with SSO.
Signal SF that WebRTC is authenticated when ‘logged-in' event is received in Connector.
Â
Â
© Enreach, Mannerheimintie 117, 00280 Helsinki, Finland
+358 40 450 3000, www.enreach.fi