Tomcat OAuth2 authentication

Providers

The following table indicates OAuth2/OpenIDConnect providers supports per Simplicité version:

Provider 3.1(1) 3.2 4.0
OpenIDConnect No No Yes
Google Yes Yes Yes
Microsoft No Yes Yes
LinkedIn No Yes Yes
FranceConnect Yes Yes Yes (2)

(1) version 3.1 allows only one unique OAuth2 provider to be configured. For subsequent versions multiple providers can be configured at the same time.

(2) FranceConnect being an OpenIDConnect-compliant provider, starting with version 4.0 it should thus be configured as an OpenIDConnect provider instead.

Webapp prerequisites

The changes to be done (if not already done) are :

Notes:

  • If you are using our standard Docker images or our instance tempates these changes are already done
  • Your application's URL must be exposed over HTTPS, SSL encryption is mandatory for any OAuth2/OpenIDConnect based authentication.

Warning: Before doing these changes, make sure that you will still be able to login with a user having at least a responsibility on the ADMIN group.

Common settings

The callback URL (redirect URI) to configure in your OAuth2/OpenIDConnect IdP for your instance is <base URL>/oauth2callback.

All OAuth2/OpenIDConnect providers requires at least the following system parameters:

As of version 4.0 a global system parameter AUTH_PROVIDERS contains the description of the various providers you configure. Ex:

[
    { "name": "google", "type": "oauth2", "sync": true },
    { "name": "microsoft", "type": "oauth2", "sync": false },
    { "name": "linkedin", "type": "oauth2", "sync": false },
    { "name": "myoidc", "type": "oauth2", "label": "Sign in with your private IdP", "sync": true }
    (...)
]

See this document for details.

Note: in 3.x versions you have a unique provider so the <provider name> suffix must not be used, nor the AUTH_PROVIDERS system parameter, but instead a OAUTH2_PROVIDER system parameter must be configured with the name of your unique provider

Generic OpenIDConnect provider settings

As of version 4.0 it is possible to configure generic OpenIDConnect (OIDC) providers (see this specification for details on the OIDC standards).

Beyond the above common system parameters, for the OIDC providers there are some additional system parameters that needs to be configured:

Note: By default the OIDC OAuth2 implementation uses by default the openid and profile scopes when calling user info endpoint. Only additional and/or custom scopes need to be configured using the OAUTH2_SCOPES system parameter if needed.

By default, the relevant user info fields defined by the OIDC standards are used to update corresponding user field (e.g. given_name for first name, family_name, etc.). As for any OAuth2 provider it is possible to do a custom parsing of user info response in the postLoadGrant grant hook as described above.

Note: The FranceConnect provider is a OIDC-compliant provider, its management as a dedicated provider has been kept in version 4.0 for backward compatibility but it should now be rather configured as a generic OIDC provider.

Google provider

Register a new client ID on the Google Developers Console for the application:

Client ID

Activate the required Google+ API on Google Developers Console and, optionally, activate any other Google API that you would like to call with the auth token your users get from Google authentication.

Optionaly set OAUTH2_SCOPES <Google provider name> with additional OAuth2 scopes you may need (e.g. drive scopes, calendar scopes, ...) see Google documentation for the values of the possible scopes, if you have several scopes use space as separator.

Notes:

  • By default the Google OAuth2 implementation uses the profile and email scopes when calling the user info endpoint. Only additional scopes needs to be configured.
  • In 3.x versions you have a unique provider so the <Google provider name> suffix must not be set

Microsoft LiveID provider

Register a new client ID on the Microsoft LiveID application portal for the application (the OAuth2 callback URL will be <url>/oauth2callback):

Client ID

Activate the required User.Read on the portal and, optionally, activate any other Microsoft API that you would like to call with the auth token your users get from Microsoft authentication.

Optionaly set OAUTH2_SCOPES <Microsoft LiveID provider name> with additional OAuth2 scopes you may need see Microsoft LiveID documentation for the values of the possible scopes, if you have several scopes use space as separator.

Grant hooks

If needed you can implement additional business logic in the GrantHooks Java class or Rhino script.

The Rhino script example below checks and removes the domain part of the account name in parseAuth and creates/updates the corresponding application user (with responsibilities on MYAPP_GROUP1 and MYAPP_GROUP2 groups on the fly in pre/postLoadGrant.

GrantHooks.parseAuth = function(g, auth) {
    if (Globals.useOAuth2()) {
        // Example of domain verification
        var domain = Grant.getSystemAdmin().getParameter("MY_OAUTH2_DOMAIN", "");
        if (!Tool.isEmpty(domain)) {
            console.log("OAuth2 account = " + auth);
            if (Tool.isEmpty(auth) || !auth.matches("^.*@" + domain + "$")) {
                console.log("OAuth2 error: Invalid domain for " + auth);
                return ""; // ZZZ must return empty string, not null, to tell the auth is rejected
            }
            console.log("OAuth2 valid domain for " + auth + " = " + domain);
        }
        /* and/or
        // Example of user verification
        var uid = Grant.getSystemAdmin().simpleQuery("select row_id from m_user where usr_login = '" + auth + "' and usr_active = '1'");
        if (Tool.isEmpty(uid)) {
            console.log("OAuth2 error: No active user for " + auth);
            return ""; // ZZZ must return empty string, not null, to tell the auth is rejected
        }
        console.log("OAuth2 active user ID for " + auth + " = " + uid);
        */
        return auth;
    }
    return auth;
};

GrantHooks.preLoadGrant = function(g) {
    if (Globals.useOAuth2()) {
        // Example of business logic to create users on the fly
        if (!Grant.exists(g.getLogin(), false)) {
            try {
                // Create user if not exists
                var usr = Grant.getSystemAdmin().getTmpObject("User");
                usr.setRowId(ObjectField.DEFAULT_ROW_ID);
                usr.resetValues(true);
                usr.setStatus(Grant.USER_ACTIVE);
                usr.getField("usr_login").setValue(g.getLogin());
                new BusinessObjectTool(usr).validateAndCreate();

                // Get module in which user has been created (default module for users)
                var module = usr.getFieldValue("row_module_id.mdl_name");
                console.log("OAuth2 user " + g.getLogin() + " created in module " + module);

                // Force a random password to avoid the change password popup
                usr.resetPassword();

                // Add responsibilities on designated groups
                var groups = [ "MYAPP_GROUP1", "MYAPP_GROUP2" ];
                for (var i = 0; i < groups.length; i++) {
                    var group = groups[i];
                    Grant.addResponsibility(usr.getRowId(), group, Tool.getCurrentDate(-1), "", true, module);
                    console.log("Added user " + group + " responsibility for OAuth2 user " + g.getLogin());
                }
            } catch (e) {
                console.error(e.javaException ? e.javaException.getMessage() : e);
            }
        }
    }   
};

Customizing the login screen

If you want to change the top logo you can create a OAUTH2_LOGO image resource (ideal type = SVG and ideal dimension = 120x120 px)

If you wat to change some of the styles of the login screen you can add a OAUTH2_STYLES CSS resource, for instance for a dark scheme:

.auth-signin { background-color: #152935; }
.auth-signin-with img, .auth-signin button { border: none 0; box-shadow: 5px 5px 10px #3A3A3A; }
.auth-signin-form { background-color: #394b54; box-shadow: 5px 5px 10px #131b21; border: solid 1px #152935; }
.auth-signin-version { color: #C0C0C0; }
.auth-signin-fp a { color: #D0D0D0; }

For each OAuth2 provider you can create a custom OAUTH2_SIGNIN_<uppercase provider name, e.g. MYPROVIDER> image resource.