Authentication

By default, Finsemble applications do not require authentication (i.e., user sign-on), but hooks are available for you to add an authentication component to match your specific application's needs. The Authentication Client API and underlying Authentication Service allow developers to add a custom authentication component which obliges end users to authenticate before proceeding. This API does not define a specific authentication protocol. It deals strictly with integration of authentication into the UX.

Finsemble itself is agnostic about which type of authentication a developer may choose to implement—the only requirement is to pass back to Finsemble the results using publishAuthorization(). If your authentication model requires handing control off to an external authentication server, then the "redirect page" you've specified to the external server must be the one to invoke publishAuthorization. Finsemble doesn't define what happens on authentication failure; it is up to the authentication component to determine how to handle failures (e.g., retry, terminate application, display error). Finsemble will simply not proceed with its start-up sequence until a successful authentication.

Background: The authentication start-up sequence

First, to define our terms:

  • Authentication - Checking a user’s credentials to allow access to a system

  • Authorization - Asking another system whether a user has been authenticated

When a Finsemble application with authentication enabled launches, the following authentication sequence occurs:

  1. The Authentication Service reads the defaultAuthentication property from the configs/components.json file to identify the authentication component.
  2. The Authentication Service spawns the authentication component and waits for a response.
  3. The spawned authentication component runs developer code to authenticate the user. When complete, the developer invokes FSBL.Clients.AuthenticationClient.publishAuthorization(username, credentials) with the authenticated username and credentials. Credentials can be any object. The credentials will be available to Finsemble components that need access to it. Note that in cases where your authentication model requires handing control off to an authentication server (such as OAuth 2.0), then the "redirect page" from the authentication server should invoke publishAuthorization.
  4. Upon receiving the authentication response from the component (i.e., when publishAuthorization is invoked), the service publishes the authenticated username and credentials to all listeners on SubPub topic "Authorization" (see below).

Any Finsemble component or service can be an "authorization listener" to receive the authorization results by using the following SubPub subscription:

    RouterClient.subscribe("Authorization", function (err, response) {
        // do something with auth data contained in "response.data"
    } );

Enabling authentication

You can have your users log in to Finsemble using a user name by password by using an authentication profile.

To do this, configure an authentication profile called "startup" and give it an adapter of "PASSWORD":

"authentication": {
   "startup:"{
        "adapter":"PASSWORD",
        "component":"defaultAuthentication"
    }
}

The specified component will launch at start. You can use the existing defaultAuthentication component, which asks for username and password, or you can write your own. You must code that component to collect credentials and authenticate against your back end. Finsemble will block access to the overall application until your authentication dialog completes the process by calling AuthenticationClient.publishAuthorization. Once that function is called, the start-up process resumes.

The form of credentials required would typically be username/password, but this could be coded in any way that meets your security requirements. For instance, you can use SAML, HTTP authentication (Digest, NTLM, Negotiate, etc.), two-factor authentication, or any other schema.


Authorization through an external authentication website

OAuth 2.0/OpenID

With OAuth, applications (such as your Finsemble app) can defer authentication to an external "identity provider" (IP). On the web, firms like Google and Facebook play the role of IP. Your firm may have its own identity service that supports OAuth. OAuth is made possible through a "shared secret" between the identity provider and the application. Behind the scenes, it is affected through a series of redirects.

Note: Finsemble’s implementation uses OAuth2 server flow (not implicit flow).

Set an authentication config. We call this an authentication profile:

startup: {
    adapter: "OAUTH2",

// The url of your identity provider’s login page. You can add additional query string parameters to this if necessary. 
// For instance, MS ADFS sometimes requires a non-standard "resource" parameter. 
// Another example would be https://accounts.google.com/o/oauth2/v2/auth?prompt=consent which controls how Google presents its OAuth page.
authorization_endpoint: "https://openid.c2id.com/login", 

// The type of OAuth request
scope: "openid",

// This will be provided by your identity provider
client_id: "XYZABC",

// Your OAuth server side script
"backchannel_endpoint": "https://yoursite/authenticate",

// Your redirect_uri. Use the provided oauthResponse.html unless you need to modify behavior. 
// In this case make a copy and fill in your business logic.
"Redirect_uri": "$applicationRoot/components/authentication/oauthResponse.html",

// Optionally specify which component to use to spawn this profile
"component": "defaultAuthentication"
}

If you’re familiar with OAuth, Finsemble is automatically generating the following fields: state, response_type, and redirect_uri.

startup is a special authentication profile which causes Finsemble to wait for authentication before proceeding. You can create additional profiles, and call them using AuthenticationClient.beginAuthentication(), such as when you have a third-party component which requires OAuth.

Stage 1:

With this configuration in place, Finsemble display the page at authorization_endpoint as a modal when it’s launched. The user will log in to this modal. Upon successful login, the identity provider will redirect to Finsemble’s built in OAuth component. This component will validate and process the response for the next stage.

Stage 2:

Finsemble’s OAuth component will then make a post request to the URL you specified in backchannel_endpoint. This request will contain client_id, grant_type, code and redirect_url. backchannel_endpoint should point to a server page that you host which should add the client_secret, and then forward this information via a /token request to your identity provider’s token_endpoint. The results should be returned back to the Finsemble request.

Note: The client_id and client_secret should be encoded based on the specifications of your identity provider. Some require that these be base64 encoded into an HTTP header. Some can accept them as post parameters

Finsemble will receive the results. It will process and publish the results as "credentials" via FSBL.Clients.Authentication.publishAuthorization. If the results include an id_token then it will be decoded and parsed. The parsed variables will be made available in the credentials object. If those results include a "sub" field, then that will be set as the Finsemble user. Otherwise, the access_token will be set as the Finsemble user.

The application will start and your components can use the contents of the credentials object where needed.

Currently credentials are available to all components. Future revisions will allow developers to restrict credential broadcast to only components on the same domain or by a whitelist of domains associated with a specific profile.

During development, you can skip the server stage by including client_secret in your authentication config. This can make development easier but should not be done in production.

Using OAuth to retrieve an access_token for API usage

OAuth can be used to access third-party resources. In this scenario, the user is presented with login credentials from the third party. Once authenticated through a series of redirects, the client application is provided with an access_token which it can use to access the third-party resources.

Create an OAuth2 profile as described above but with a specific name. You can then use AuthenticationClient#beginAuthentication to kick off the process of retrieving an access_token. When that process is complete, the callback will be returned with the access_token and other credentials. See AuthenticationClient#completeOAUTH for implementation details.

Session-based authentication

Typically, session-based authentication uses a browser cookie to store a session token. Each request back to the webserver includes the token cookie, which the webserver checks against its internal map of authenticated sessions.

When you log in through the authentication dialog, any cookies will be set for the domain where that dialog is hosted. Other components that Finsemble accesses which are hosted on that domain will automatically use that cookie. Session authentication will thus behave the way you would expect a normal web page to behave.

If you need the same session cookie to be used across domains then you should create a distributed store to share the cookie across domains.

Automatically authenticate with the user's Windows login credentials

When your infrastructure is configured correctly, you automatically authenticate Finsemble using the user’s Windows login credentials. When using Windows credentials, Finsemble does not actually play a role in authentication; you can turn off the Authentication Service (do not create a "startup" authentication profile from your config).

The process is as follows:

1) A component requests content from your server.

2) Your server should respond with a request to authenticate with the "Negotiate" protocol specified. This is very similar to how HTTP basic authorization works, but "Negotiate" is a protocol that is used for Windows authentication or Kerberos.

3) Chromium (in your component) will automatically respond with the windows credentials if the server is on a trusted network. Chromium works the same way Internet Explorer does. If your server is on the same LAN (same IP network/submask), or if your server is configured as a trusted server, then credentials will be sent. Your network administrator will likely configure your users' machines to trust your server through group policy management.

4) The server validates the credentials by making its own connection to the Windows LAN/Kerberos server. If validated, the content will be delivered; otherwise a 503 Unauthorized message will appear.

5) Other components connecting to this server will get their content immediately because Chromium will return valid credentials for any window that connects to the same, already authorized, domain.

Further reading

The Authentication Client documentation provides additional context.

For more information on how Finsemble handles start-up, check out Finsemble's Lifecycle Events.

The following sources are useful as references for the authentication process:

This document describes the browser authentication protocols in more detail: