Generic OAuth Authentication

You can configure many different OAuth2 authentication services with SmartCollect SC² using the generic OAuth2 feature. Examples:

This callback URL must match the full HTTP address that you use in your browser to access SmartCollect SC², but with the prefix path of /login/generic_oauth.

You may have to set the root_url option of [server] for the callback URL to be correct. For example in case you are serving SmartCollect SC² behind a proxy.

Example config:

[auth.generic_oauth]
enabled = true
client_id = YOUR_APP_CLIENT_ID
client_secret = YOUR_APP_CLIENT_SECRET
scopes =
auth_url =
token_url =
api_url =
allowed_domains = mycompany.com mycompany.org
allow_sign_up = true
tls_skip_verify_insecure = false
tls_client_cert =
tls_client_key =
tls_client_ca =

Set api_url to the resource that returns OpenID UserInfo compatible information.

You can also specify the SSL/TLS configuration used by the client.

  • Set tls_client_cert to the path of the certificate.
  • Set tls_client_key to the path containing the key.
  • Set tls_client_ca to the path containing a trusted certificate authority list.

tls_skip_verify_insecure controls whether a client verifies the server’s certificate chain and host name. If it is true, then SSL/TLS accepts any certificate presented by the server and any host name in that certificate. You should only use this for testing, because this mode leaves SSL/TLS susceptible to man-in-the-middle attacks.

SmartCollect SC² will attempt to determine the user’s e-mail address by querying the OAuth provider as described below in the following order until an e-mail address is found:

  1. Check for the presence of an e-mail address via the email field encoded in the OAuth id_token parameter.
  2. Check for the presence of an e-mail address using the JMESPath specified via the email_attribute_path configuration option. The JSON used for the path lookup is the HTTP response obtained from querying the UserInfo endpoint specified via the api_url configuration option. Note: Only available in SmartCollect SC² v6.4+.
  3. Check for the presence of an e-mail address in the attributes map encoded in the OAuth id_token parameter. By default SmartCollect SC² will perform a lookup into the attributes map using the email:primary key, however, this is configurable and can be adjusted by using the email_attribute_name configuration option.
  4. Query the /emails endpoint of the OAuth provider’s API (configured with api_url) and check for the presence of an e-mail address marked as a primary address.
  5. If no e-mail address is found in steps (1-4), then the e-mail address of the user is set to the empty string.

SmartCollect SC² will also attempt to do role mapping through OAuth as described below.

Only available in SmartCollect SC² v6.5+.

Check for the presence of a role using the JMESPath specified via the role_attribute_path configuration option. The JSON used for the path lookup is the HTTP response obtained from querying the UserInfo endpoint specified via the api_url configuration option. The result after evaluating the role_attribute_path JMESPath expression needs to be a valid SmartCollect SC² role, i.e. Viewer, Editor or Admin.

See JMESPath examples for more information.

Only available in SmartCollect SC² v7.2+.

Customize user login using login_attribute_path configuration option. Order of operations is as follows:

  1. SmartCollect SC² evaluates the login_attribute_path JMESPath expression against the ID token.
  2. If SmartCollect SC² finds no value, then SmartCollect SC² evaluates expression against the JSON data obtained from UserInfo endpoint. The UserInfo endpoint URL is specified in the api_url configuration option.

You can customize the attribute name used to extract the ID token from the returned OAuth token with the id_token_attribute_name option.

Set up OAuth2 with Auth0

  1. Create a new Client in Auth0

    • Name: SmartCollect SC²
    • Type: Regular Web Application
  2. Go to the Settings tab and set:

    • Allowed Callback URLs: https://<smartcollect domain>/login/generic_oauth
  3. Click Save Changes, then use the values at the top of the page to configure SmartCollect SC²:

    [auth.generic_oauth]
    enabled = true
    allow_sign_up = true
    team_ids =
    allowed_organizations =
    name = Auth0
    client_id = <client id>
    client_secret = <client secret>
    scopes = openid profile email
    auth_url = https://<domain>/authorize
    token_url = https://<domain>/oauth/token
    api_url = https://<domain>/userinfo
    

Set up OAuth2 with Bitbucket

[auth.generic_oauth]
name = BitBucket
enabled = true
allow_sign_up = true
client_id = <client id>
client_secret = <client secret>
scopes = account email
auth_url = https://bitbucket.org/site/oauth2/authorize
token_url = https://bitbucket.org/site/oauth2/access_token
api_url = https://api.bitbucket.org/2.0/user
team_ids =
allowed_organizations =

Set up OAuth2 with Centrify

  1. Create a new Custom OpenID Connect application configuration in the Centrify dashboard.

  2. Create a memorable unique Application ID, e.g. “smartcollect”, “smartcollect_aws”, etc.

  3. Put in other basic configuration (name, description, logo, category)

  4. On the Trust tab, generate a long password and put it into the OpenID Connect Client Secret field.

  5. Put the URL to the front page of your SmartCollect SC² instance into the “Resource Application URL” field.

  6. Add an authorized Redirect URI like https://your-smartcollect-server/login/generic_oauth

  7. Set up permissions, policies, etc. just like any other Centrify app

  8. Configure SmartCollect SC² as follows:

    [auth.generic_oauth]
    name = Centrify
    enabled = true
    allow_sign_up = true
    client_id = <OpenID Connect Client ID from Centrify>
    client_secret = <your generated OpenID Connect Client Secret"
    scopes = openid profile email
    auth_url = https://<your domain>.my.centrify.com/OAuth2/Authorize/<Application ID>
    token_url = https://<your domain>.my.centrify.com/OAuth2/Token/<Application ID>
    api_url = https://<your domain>.my.centrify.com/OAuth2/UserInfo/<Application ID>
    

Set up OAuth2 with OneLogin

  1. Create a new Custom Connector with the following settings:

    • Name: SmartCollect SC²
    • Sign On Method: OpenID Connect
    • Redirect URI: https://<smartcollect domain>/login/generic_oauth
    • Signing Algorithm: RS256
    • Login URL: https://<smartcollect domain>/login/generic_oauth

    then:

  2. Add an App to the SmartCollect SC² Connector:

    • Display Name: SmartCollect SC²

    then:

  3. Under the SSO tab on the SmartCollect SC² App details page you’ll find the Client ID and Client Secret.

    Your OneLogin Domain will match the URL you use to access OneLogin.

    Configure SmartCollect SC² as follows:

    [auth.generic_oauth]
    name = OneLogin
    enabled = true
    allow_sign_up = true
    client_id = <client id>
    client_secret = <client secret>
    scopes = openid email name
    auth_url = https://<onelogin domain>.onelogin.com/oidc/2/auth
    token_url = https://<onelogin domain>.onelogin.com/oidc/2/token
    api_url = https://<onelogin domain>.onelogin.com/oidc/2/me
    team_ids =
    allowed_organizations =
    

JMESPath examples

To ease configuration of a proper JMESPath expression, you can test/evaluate expressions with custom payloads at http://jmespath.org/.

Role mapping

Basic example:

In the following example user will get Editor as role when authenticating. The value of the property role will be the resulting role if the role is a proper SmartCollect SC² role, i.e. Viewer, Editor or Admin.

Payload:

{
    ...
    "role": "Editor",
    ...
}

Config:

role_attribute_path = role

Advanced example:

In the following example user will get Admin as role when authenticating since it has a group admin. If a user has a group editor it will get Editor as role, otherwise Viewer.

Payload:

{
    ...
    "info": {
        ...
        "groups": [
            "engineer",
            "admin",
        ],
        ...
    },
    ...
}

Config:

role_attribute_path = contains(info.groups[*], 'admin') && 'Admin' || contains(info.groups[*], 'editor') && 'Editor' || 'Viewer'