Skip to content
tomteman edited this page Dec 23, 2014 · 7 revisions

What is INGA?

INGA stands for Intermediate Node.js Gateway Application.

WatchDox's web application is used by numerous organizations. Some of these organizations use WatchDox's oAuth server, while some opt to use their own oAuth server. Each of them might be set up a bit differently (for instance - some support refresh tokens, some don't).

In order to simplify our frontend, and to refrain from adding that logic to our API (it doesn't really concern the API, data-wise), INGA was born. It is a Node.js server which handles authentication requests and redirects the client as needed.

INGA is configured via a properties.json file, which allows easier development (for instance - most oAuth servers aren't too fond of 'localhost' as a redirect_uri) as well as robust multiple and sub domain support.

Due to the numerous edge cases we had to support, INGA makes a lot of parameters dynamic.

For example, INGA cannot assume it has access to a DNS which can reach child/sibling subdomains (some organizations have very strict policies). It does assume it can reach the fqdn, and that a server will always have either only children or only siblings. So INGA figures out what the child/sibling name is from the request and passes it as a header to our fqdn (configured in the properties.json file).

Refresh tokens can be maintained in a stateless manner, by encrypting them inside INGA before sending them to the client. They will be decrypted if the client sends them to be used. The encryption keys are also saved in the properties.json file.

Since state values sent from clients can get pretty complicated in terms of URL safety - requiring careful nested encoding and decoding (redirect URLs, containing their own redirect URLs as a GET parameter. Not to mentions the state value which might include stringified jsons with non-Ascii values. Bah.). Also, some client automatically decode the url when they read it, requiring double-encoding, which in turn leads to a bigger mess.

INGA circumvents all of that by requiring clients to send their payloads encrypted in base64, using the web safe final chars (using $ and _ instead of + and /, respectively).

Example flow

The client will figure out which Identity Provider (IDP) it will use. It redirects the user to the IDP's url, setting the redirect_uri in the request to {INGA domain}/process/{web-safe-base64-encoded json}.

The web-safe-base64-encoded json will be in the form of:

    {
        state: {
            ...
        },
        client_return_uri: ...
    }

This state object can include whatever you'll want back in the client after completing the authentication flow. It will usually include the user's last location inside the application. This value will not be modified by INGA. In order to adhere to oAuth's security measures, it should also include a nonce, which will be verified by the client when completing the authentication flow.

Once INGA has has generated the credentials from the IDP, it will redirect them to the client_return_uri. It will also be base64 encoded, and will be in the following form:

client_return_uri + (? or &, depending on the contents of client_return_uri) + access_token={base64 encoded access_token from the IDP}&refresh_token={aes-256 encrypted and then base64 encoded refresh_token}&state={original base64 encoded state object sent from the client}

Clone this wiki locally