This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

OAuth 2.0 authentication

Rather than with a username and password, users can authenticate to Vertica by first verifying their identity with an identity provider, receiving an OAuth token, and then passing the token to Vertica.

Rather than with a username and password, users can authenticate to Vertica by first verifying their identity with an identity provider, receiving an OAuth token, and then passing the token to Vertica.

OAuth in Vertica is tested with Keycloak, Okta, and OTDS but other providers should work if they support the RFC 7662 Token Introspection standard.

1 - Configuring OAuth authentication

For a list of ODBC OAuth connection properties, see ODBC OAuth Connection Properties.

The following procedure performs the following actions:

  1. Configures an identity provider for OAuth integration with Vertica (either Okta or Keycloak).

  2. Creates an OAuth authentication record.

  3. Retrieves an access token from the identity provider with a POST request.

  4. Passes the access token to a sample application, which then authenticates to Vertica.

Configure the identity provider

Vertica officially tests and supports OAuth integration with Keycloak and Okta. Other identity providers should also work as long as they implement the RFC 7662 Token Introspection standard. The following example configurations are provided for reference:

Create an authentication record

In Vertica, create an authentication record for OAuth. This uses the client ID, client secret, and either the discovery (Keycloak) or introspect (Okta) endpoint used by your identity provider.

The following authentication record v_oauth authenticates users from any IP address by contacting the identity provider to validate the OAuth token (rather than a username and password) and uses the following parameters:

  • validate_type: The method used to validate the OAuth token. This should be set to IDP (default) to validate the OAuth token for confidential clients.

  • client_id: The client in the identity provider.

  • client_secret: The client secret generated by the identity provider. This is required if validate_type is IDP.

  • discovery_url: Also known as the OpenID Provider Configuration Document, Vertica uses this endpoint to retrieve information about the identity provider's configuration and other endpoints (Keycloak only).

  • introspect_url: Used by Vertica to introspect (validate) access tokens. You must specify the introspect_url if you do not specify the discovery_url and are not using JWT validation.

If discovery_url and introspect_url are both set, discovery_url takes precedence. The following example sets both for demonstration purposes; in general, you should prefer to set the discovery_url:

=> CREATE AUTHENTICATION v_oauth METHOD 'oauth' HOST '0.0.0.0/0';
=> ALTER AUTHENTICATION v_oauth SET validate_type = 'IDP';
=> ALTER AUTHENTICATION v_oauth SET client_id = 'vertica';
=> ALTER AUTHENTICATION v_oauth SET client_secret = 'client_secret';
=> ALTER AUTHENTICATION v_oauth SET discovery_url = 'https://203.0.113.1:8443/realms/myrealm/.well-known/openid-configuration';
=> ALTER AUTHENTICATION v_oauth SET introspect_url = 'https://203.0.113.1:8443/realms/myrealm/protocol/openid-connect/token/introspect';

Alternatively, if your identity provider supports the OpenID Connect protocol and your client is public, Vertica can use JWT validation, where Vertica validates OAuth tokens by verifying that it was signed by the identity provider's private key.

Vertica does not contact the identity provider for JWT validation.

JWT validation requires the following parameters:

  • validate_type: The method used to validate the OAuth token. This should be set to JWT to validate the OAuth token for public clients.

  • jwt_rsa_public_key: In PEM format, the public key used to sign the client's OAuth token. Vertica uses this to validate the OAuth token. If your identity provider does not natively provide PEM-formatted public keys, you must convert them to PEM format. For example, keys retrieved from an Okta endpoint are in JWK format and must be converted.

  • jwt_issuer: The issuer of the OAuth token. For Keycloak, this is the token endpoint.

  • jwt_user_mapping: The name of the Vertica user.

You can also specify the following parameters to define a whitelist based on fields of the OAuth token:

  • jwt_accepted_audience_list: Optional, a comma-delimited list of values to accept from the client JWT's aud field. If set, tokens must include in aud one of the accepted audiences to authenticate.

  • jwt_accepted_scope_list: Optional, a comma-delimited list of values to accept from the client JWT's scope field. If set, tokens must include in scope at least one of the accepted scopes to authenticate.

The following authentication record v_oauth_jwt authenticates users from any IP address by verifying that the client's OAuth token was signed by the identity provider's private key. It also requires the user to provide the proper values in the token's aud and scope fields:

=> CREATE AUTHENTICATION v_oauth_jwt METHOD 'oauth' HOST '0.0.0.0/0';
=> ALTER AUTHENTICATION v_oauth_jwt SET validate_type = 'JWT';
=> ALTER AUTHENTICATION v_oauth_jwt SET jwt_rsa_public_key = '-----BEGIN PUBLIC KEY-----public-key-value-----END PUBLIC KEY-----';
=> ALTER AUTHENTICATION v_oauth_jwt SET jwt_issuer = 'http://10.20.30.40:8080/realms/realm_name';
=> ALTER AUTHENTICATION v_oauth_jwt SET jwt_user_mapping = 'preferred_username';
=> ALTER AUTHENTICATION v_oauth_jwt SET jwt_accepted_audience_list = 'vertica,local';
=> ALTER AUTHENTICATION v_oauth_jwt SET jwt_accepted_scope_list = 'email,profile,user';

Setting the required parameters automatically enables the authentication record. To manually enable the authentication record:

=> ALTER AUTHENTICATION v_oauth ENABLE;

For a full list of OAuth authentication parameters, see OAuth authentication parameters.

Create a Vertica user

Vertica users map to the identity provider's users with the same username. You can either create the user manually or enable just-in-time (JIT) user provisioning in the authentication record to automatically create users with valid tokens.

To manually create the user:

  1. To map to the user oauth_user in the identity provider, create a Vertica user with the same name. You do not need to specify a password because authentication is performed by the identity provider:

    => CREATE USER oauth_user;
    
  2. Grant the OAuth authentication record to the user (or their role):

    => GRANT AUTHENTICATION v_oauth TO oauth_user;
    => GRANT ALL ON SCHEMA PUBLIC TO oauth_user;
    

To enable JIT user provisioning:

=> ALTER AUTHENTICATION v_oauth SET oauth2_jit_enabled = 'yes';

If the user already exists and JIT user provisioning is enabled and you use Keycloak as your IDP, Vertica automatically assigns the roles associated with the user as specified by the IDP if the roles also exist in Vertica. For details, see Just-in-time user provisioning.

Retrieve an access token

To authenticate to Vertica, you must retrieve an access token from the identity provider.

Programmatic method

A simple way to get an OAuth access token and refresh token is to send a POST request to the token endpoint, providing the credentials of the user. You can then use the returned access token, refresh token, and scope with the connection properties for your client. For details, see JDBC connection properties and ODBC DSN connection properties.

For example, to get an access token for oauth_user from Keycloak:

$ curl --location --request POST 'http://203.0.113.1:8080/realms/master/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'username=oauth_user' \
--data-urlencode 'password=oauth_user_password' \
--data-urlencode 'client_id=vertica' \
--data-urlencode 'client_secret=client_secret' \
--data-urlencode 'grant_type=password'

Keycloak responds with a JSON string containing the access_token and refresh_token if you authenticated correctly:

{
   "access_token":"access_token",
   "expires_in":60,
   "refresh_expires_in":1800,
   "refresh_token":"refresh_token",
   "token_type":"Bearer",
   "not-before-policy":0,
   "session_state":"6745892a-aa74-452f-b6b9-c45637193859",
   "scope":"profile email"
}

Similarly, to retrieve an access token for oauth_user from Okta:

$ curl --insecure -d "client_id=0oa5cgdga1fb812rW697" -d "client_secret=aq22wRl3Z3mmtuoB13omRo6Ql03Ltafet4xYi77p" \
-d "username=oauth_user" -d "password=oauth_user_password" \
-d "grant_type=password" -d "scope=offline_access%20openid" https://example.okta.com/oauth2/default/v1/introspect

{"token_type":"Bearer","expires_in":3600,"access_token":"access_token","id_token":"id_token"}

Single-sign on (SSO)

An alternative to manually retrieving the access token is using SSO through the ODBC client driver. With this method, the ODBC driver opens the default web browser to the IDP's authentication endpoint where the user can enter their credentials. If the user successfully authenticates to the IDP, the ODBC driver automatically retrieves the token and authenticates to Vertica.

To configure and use the ODBC driver for SSO:

  1. For clients that use the confidential access type, set the oauthclientsecret.
  2. In the authentication record, set the following parameters:
    • The discovery_url (Keycloak only) or the following:
      • auth_url
      • token_url
    • client_id
  3. Connect to Vertica with the ODBC driver. The default web browser opens to your IDP's sign-in page.
  4. Enter your credentials to authenticate to the IDP.

Run the sample applications

The OAuth sample applications, at a minimum, take an access token as an argument to authenticate to the database until the token expires. This token is retrieved by the client application and then set as a connection property in the driver.

ODBC

  1. Follow the instructions in the README.

  2. Run the sample application, passing the OAuth parameters as arguments:

    • To authenticate until the token expires:

      $ ./a.out --access-token OAuthAccessToken
      
    • To authenticate and silently refresh the access token when it expires:

      $ ./a.out --access-token OAuthAccessToken
          --refresh-token OAuthRefreshToken
          --client-secret OAuthClientSecret
      

For a list of all ODBC OAuth parameters, see ODBC DSN connection properties.

JDBC

  1. Follow the instructions in the README.

  2. Run the sample application, passing the OAuth parameters as arguments:

    • To authenticate until the token expires:

      $ mvn compile exec:java -Dexec.mainClass=OAuthSampleApp -Dexec.args="vertica_host database_name --access-token oauthaccesstoken"
      
    • To authenticate and silently refresh the access token when it expires:

      $ mvn compile exec:java -Dexec.mainClass=OAuthSampleApp -Dexec.args="vertica_host database_name --access-token oauthaccesstoken
          --refresh_token oauthrefreshtoken
          --client-secret oauthclientsecret
      

ADO.NET

The ADO.NET driver uses a simplified configuration scheme with a single connection property: OAuthAccessToken. Other flows like token refresh should be handled externally by the driver. The sample application in the following example demonstrates how to pass an access token to the ADO.NET driver and how to handle token refresh:

  1. Follow the instructions in the README.

  2. Run the sample application.

Troubleshooting

To get debugging information for TLS, use the -Djavax.net.debug=ssl flag.

Custom CA certificates

A truststore is a container for trusted certificate authority (CA) certificates. These CA certificates are used to verify the identities of other systems when establishing a TLS connection. When your JDBC client connects to the identity provider through an HTTPS endpoint, the JDBC client verifies the identity provider's certificate by making sure that it was issued by a CA in the truststore.

If you configure your identity provider with TLS (that is, if you use HTTPS endpoints for your token or refresh URLs) and its certificate is not issued by a well-known CA, you must either specify a custom truststore or import the issuer's CA certificate into the system truststore with keytool.

To specify a custom truststore, set the JDBC connection properties oauthtruststorepath and oauthtruststorepassword:

connProps = new Properties(connProps);
connProps.setProperty("oauthtruststorepath", "/path/to/truststore/customoauth.truststore");
connProps.setProperty("oauthtruststorepassword", "password");

To add the certificate keycloak/cert.crt to the Java truststore:

$ keytool -trustcacerts -keystore /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.261-2.6.22.2.el7_8.x86_64/jre/lib/security/cacerts -storepass changeit -importcert -alias keycloak -file /keycloak/cert.crt

1.1 - Configure Keycloak

The following procedure configures a Keycloak 18.0.0 server on 203.0.113.1.

The following procedure configures a Keycloak 18.0.0 server on 203.0.113.1 for integration with Vertica. For details, see Configuring OAuth authentication.

The goals of this procedure are to configure Keycloak and obtain the following information:

  • Client ID: The ID used to identify the Vertica database. This is configured by the user and set to vertica in the example procedure.
  • Client secret: A Keycloak-generated string used to refresh the OAuth token when it expires.
  • Discovery endpoint: The endpoint that serves information for all other endpoints as a JSON string. The endpoint for a Keycloak server on 203.0.113.1 is one of the following:
    • https://203.0.113.1:8443/realms/myrealm/.well-known/openid-configuration (if TLS is configured)
    • http://203.0.113.1:8443/realms/myrealm/.well-known/openid-configuration

Configure TLS (optional)

If you want to use TLS, you must obtain a certificate and key for Keycloak signed by a trusted CA. This example uses a self-signed CA for convenience. The following example creates a certificate and key in Vertica:

  1. Generate the CA certificate:

    => CREATE KEY SSCA_key TYPE 'RSA' LENGTH 2048;
    CREATE KEY
    
    => CREATE CA CERTIFICATE SSCA_cert
    SUBJECT '/C=US/ST=Massachusetts/L=Cambridge/O=Micro Focus/OU=Vertica/C N=Vertica Root CA'
    VALID FOR 3650
    EXTENSIONS 'nsComment' = 'Self-signed root CA cert'
    KEY SSCA_key;
    CREATE CERTIFICATE
    
  2. Generate a server key and certificate, signed by your CA, setting the subjectAltName of the certificate to the DNS server and/or IP address of your Keycloak server:

    => CREATE KEY keycloak_key TYPE 'RSA' LENGTH 2048;
    CREATE KEY
    
    => CREATE CERTIFICATE keycloak_cert
    SUBJECT '/C=US/ST=Massachussets/L=Cambridge/O=Micro Focus/OU=Vertica/CN=Vertica Server'
    SIGNED BY SSCA_cert
    EXTENSIONS 'nsComment' = 'Keycloak CA', 'extendedKeyUsage' = 'serverAuth', 'subjectAltName' = 'DNS.1:dnsserver,IP:203.0.113.1'
    KEY keycloak_key;
    CREATE CERTIFICATE
    
  3. Create the file keycloak_directory/conf/keyfile.pem with the content from the key column for the generated key:

    => SELECT key FROM cryptographic_keys WHERE name = 'keycloak_key';
    
  4. Create the file keycloak_directory/conf/certfile.pem with the content from the certificate_text column for the generated certificate:

    => SELECT certificate_text FROM certificates WHERE name = 'keycloak_cert';
    
  5. Append to your system's CA bundle the content from the certificate_text column for the generated CA certificate. The default CA bundle path and format varies between distributions; for details, see SystemCABundlePath:

    => SELECT certificate_text FROM certificates WHERE name = 'SSCA_cert';
    
  6. Set the SystemCABundlePath configuration parameter:

    => ALTER DATABASE DEFAULT SET SystemCABundlePath = 'path/to/ca_bundle';
    

Start Keycloak

  1. Enter the following commands for a minimal configuration to create the Keycloak admin and to start Keycloak in start-dev mode:

    $ KEYCLOAK_ADMIN=kcadmin
    $ export KEYCLOAK_ADMIN
    $ KEYCLOAK_ADMIN_PASSWORD=password
    $ export KEYCLOAK_ADMIN_PASSWORD
    $ cd keycloak_directory/bin/
    $ ./kc.sh start-dev --hostname 203.0.113.1 --https-certificate-file ../conf/certfile.pem --https-certificate-key-file=../conf/keyfile.pem
    
  2. Open the Keycloak console with your browser (these examples use the default ports):

    • For HTTP: http://203.0.113.1:8080

    • For HTTPS: http://203.0.113.1:8443

  3. Sign in as the admin.

  4. Go to Client scopes > Client scope details > Mapper details, and toggle Full group path to Off. Vertica does not support subgroups.

  5. (Optional) To make testing OAuth more convenient, go to Realm Settings > Tokens and increase Access Token Lifespan to a greater value (the default is 5 minutes).

Create the Vertica client

  1. Go to Clients and select on Create. The Add Client page appears.

  2. In Client ID, enter vertica.

  3. Select Save. The client configuration page appears.

  4. On the Settings tab, use the Access Type dropdown to select confidential.

  5. On the Credentials tab, copy the Secret. This is the client secret used to refresh the token when it expires.

Create a Keycloak user

Keycloak users map to Vertica users with the same name. This example creates a the Keycloak user oauth_user.

  1. On the Users tab, select Add user. The Add user page appears.

  2. In Username, enter oauth_user.

  3. On the Credentials tab, enter a password.

1.2 - Configure Okta

The following procedure configures Okta for integration with Vertica.

The following procedure configures Okta for integration with Vertica and requires administrator privileges. For details, see Configuring OAuth authentication.

The goals of this procedure are to configure Okta and obtain the following information:

  • Client ID: The ID used to identify the Vertica database. This is generated by Okta.
  • Client secret: An Okta-generated string used to refresh the OAuth token when it expires.
  • Token endpoint: Used by the client to retrieve the OAuth token.
  • Introspection endpoint: Used by Vertica to validate the OAuth token.

These values are used to create the oauth authentication record in Vertica and act as instructions for Vertica to communicate with Okta when a user attempts to authenticate.

Create an OIDC application

  1. From the Okta dashboard, go to Applications > Applications and select Create App Integration. The Create a new app integration dialog box appears.
  2. For the Sign-in method, select OIDC - OpenID Connect. The Application type section appears.
  3. For the Application type, select Native Application.
  4. Select Next. The New Native App Integration window opens.
  5. In the App integration name, enter a name for your application. This example uses Demo_Vertica.
  6. For the Grant Type, select Authorization Code, Refresh Token, and Resource Owner Password.
  7. For Controlled access, select the option applicable to your organization. This example uses Allow everyone in your organization to access.
  8. Select Save to save your application.

Retrieve the client ID and client secret

  1. From the Okta dashboard, go to Applications > Applications and select the name of your OIDC application.
  2. In the General tab in the Client Credentials section, select Edit.
  3. For Client authentication, select Client secret and select Save. This generates a new client secret.
  4. Copy the client ID and client secret.

Set the authentication policy

  1. From the Okta dashboard, go to Applications > Applications and select the name of your OIDC application.
  2. In the Sign On tab in the User authentication section, select Edit.
  3. Select Password only.
  4. Select Save to save the new policy.

Retrieve Okta endpoints

  1. From the Okta dashboard, go to Security > API.
  2. In the Authorization Servers tab, select the name of your authorization server. By default, the name of this server is default.
  3. Select the Metadata URI to get a list of all endpoints for your authorization server as a json string.
  4. Copy the values for the token_endpoint and introspection_endpoint.

Test the configuration

  1. Verify that you can retrieve an OAuth token from the token endpoint. If successful, Okta respond with an access_token and refresh_token:

    $ curl --insecure -d "client_id=client_id" -d "client_secret=client_secret" -d "username=okta_username" -d "password=okta_password" -d "grant_type=password" -d "scope=offline_access%20openid" token_endpoint
    
  2. Verify that the tokens are valid with the introspection endpoint. If successful, Okta responds with a json string containing "active":true:

    To verify the access token:

    $ curl --insecure -d "client_id=client_id" -d "client_secret=client_secret" -d "token=access_token" introspection_endpoint
    

    Similarly, to verify the refresh token:

    $ curl --insecure -d "client_id=client_id" -d "client_secret=client_secret" -d "token=refresh_token" introspection_endpoint
    

    The access_token and refresh_token can then be used for the oauthaccesstoken and oauthrefreshtoken parameters. For details, see JDBC connection properties and ODBC DSN connection properties.

2 - Just-in-time user provisioning

To use this feature, you must use Keycloak as your identity provider.

Just-in-time (JIT) user provisioning is the act of automatically configuring an authenticated user and their roles based on information provided by the identity provider (IdP).

When a client uses an OAuth authentication record that enables JIT user provisioning, Vertica automatically performs the following actions:

  1. Creates the user if they do not exist in the database. The username must conform to conventions described in Identifiers.

  2. If you configure automatic role assignment, Vertica identifies roles that exist in both the user or group identity and the database and grants each role to the Vertica database user as a default role.

  3. Grants to the user the authentication record that is associated with the IdP if the user or role does not already have a grant on that authentication record.

You can view all JIT-provisioned users and their authentication record with the USERS system table. If the user was JIT-provisioned, then the managed_by_oauth2_auth_id column lists the JIT-enabled authentication record:

=> SELECT user_name, managed_by_oauth2_auth_id FROM users;
 user_name |  managed_by_oauth2_auth_id
-----------+-----------------------------
 dbadmin   |
 Bob       | 45035996273853300
 Margie    |
 Alice     | 45035996273866484
(4 rows)

Enable JIT provisioning

When Vertica authenticates a JIT-provisioned user, it loops through all existing OAuth authentication records for a record that can authenticate the OAuth token in the client request. If Vertica locates the authentication record, it assigns the record to the JIT-provisioned user.

After you create an OAuth authentication record, you must alter its authentication record to enable JIT. To enable JIT, set the oauth2_jit_enabled OAuth authentication parameter to yes:

=> ALTER AUTHENTICATION v_oauth SET oauth2_jit_enabled = 'yes';
ALTER AUTHENTICATION

To confirm that JIT authentication is enabled on the authentication record, query the CLIENT_AUTH_PARAMS table:

=> SELECT * FROM CLIENT_AUTH_PARAMS WHERE auth_name = 'v_oauth' AND auth_parameter_name = 'oauth2_jit_enabled';
     auth_oid      | auth_name | auth_parameter_name | auth_parameter_value
-------------------+-----------+---------------------+----------------------
 45035996273859012 | v_oauth   | oauth2_jit_enabled  | yes
(1 row)

Automatic role assignment

Vertica can automatically assign a role to a JIT-provisioned user if the OAuth token contains the following:

  • Client identity role that exactly matches a Vertica database role
  • Group identity role that exactly matches a Vertica database role
  • Group identity name that exactly matches a Vertica database role

Vertica updates the role assignment each time a JIT-provisioned user authenticates with the OAuth token. For example, if Vertica automatically assigned a role using the group identity name and then that group identity is removed from the IdP, Vertica revokes that role the next time that JIT-provisioned user authenticates to Vertica. In addition, you can add a role to a blocklist that prevents Vertica from automatically granting that role during JIT provisioning. These features ensure that Vertica reflects up-to-date role assignments so that you can manage your database user identities from a single, secure location.

Prerequisites

Configure role assignment

An IdP manages Vertica as a client identity. An IdP client can have zero or more roles, where each role has specific privileges in the client environment. IdPs also manage group identities, where each group identity is a collection of user identities that share attributes and roles.

During automatic role assignment, Vertica treats each IdP client role, group role, and group name the same. If the JIT-provisioned user has a client role, group role, or group name that maps to a Vertica role, Vertica automatically assigns that role to the JIT-provisioned user. A single OAuth token can contain both client and group identities.

To associate a database with an IdP client or group identity, set the corresponding security parameter:

  • OAuth2JITRolesClaimName identifies the Vertica client identity in an IdP that contains the role mappings:
    => ALTER DATABASE DEFAULT SET OAuth2JITRolesClaimName = 'resource_access.IdPClientName.roles';
    
  • OAuth2JITGroupsClaimName identifies a group identity that contains Vertica client role mappings:
    => ALTER DATABASE DEFAULT SET OAuth2JITGroupsClaimName = 'IdPGroupClaimName';
    

Vertica automatically assigns a role only if the database security parameter setting exactly matches an IdP client or group claim name. If there is a match, then Vertica looks at the match in the IdP. If there is a client role, group name, or group role that exactly matches an existing Vertica database role, then Vertica grants the database role to the JIT-provisioned user. Vertica ignores any roles or groups that do not have exact matches in Vertica.

Restrict role assignment

Vertica can assign any role to a JIT-provisioned user, including DBADMIN and PSEUDOSUPERUSER. Because granting unrestricted privileges might raise security concerns, you can restrict Vertica role assignments with the OAuth2JITForbiddenRoles security parameter:

=> ALTER DATABASE DEFAULT SET OAuth2JITForbiddenRoles = 'dbadmin,pseudosuperuser'

When an IdP user has a role or group mapping that matches a role in OAuth2JITForbiddenRoles, Vertica does not grant the JIT-provisioned user that role.

Verify role assignments

To verify which roles were automatically assigned to JIT-provisioned users, you can query the vs_users table. The num_jit_roles column lists the number of roles that were assigned with JIT provisioning, and oauth2_jit_roles list the names of each role:

=> \x
Expanded display is on.
=> SELECT num_default_roles, default_roles, num_jit_roles, oauth2_jit_roles, managed_by_oauth2_auth_id
   FROM vs_users 
   WHERE name = 'username';
-[ RECORD 1 ]-------------+----------------------------------------------------------
num_default_roles         | 2
default_roles             | vertica-admin, vertica-user
num_jit_roles             | 2
oauth2_jit_roles          | vertica-admin, vertica-user
managed_by_oauth2_auth_id | 45035996273851314

Example

In this example scenario, an organization uses the Keycloak IdP to manage user identities across their organization. The Keycloak implementation has a client identity named vertica and a group identity named groups. The following table lists the client roles, IdP groups, and group roles:

vertica client roles groups name groups roles

dbadmin

orders_user

view_realm

realm_admin

user_admin

Vertica configuration

Vertica has a database named orders with the following security parameter settings that define the roles claim, group claim, and restricted roles:

=> SELECT parameter_name, current_value FROM configuration_parameters
   WHERE parameter_name = 'OAuth2JITRolesClaimName'
   OR parameter_name = 'OAuth2JITGroupsClaimName'
   OR parameter_name = 'OAuth2JITForbiddenRoles';
      parameter_name      |            current_value
--------------------------+-------------------------------------
 OAuth2JITForbiddenRoles  | dbadmin,pseudosuperuser
 OAuth2JITGroupsClaimName | groups
 OAuth2JITRolesClaimName  | resource_access.vertica.roles
(3 rows)

Vertica has the following users:

=> SELECT USER_NAME FROM USERS;
 USER_NAME
-----------
 dbadmin
(1 row)

Vertica has the following assigned roles:

=> SELECT NAME, ASSIGNED_ROLES FROM ROLES;
      NAME       | ASSIGNED_ROLES
-----------------+----------------
 public          |
 dbduser         |
 dbadmin         | dbduser*
 pseudosuperuser | dbadmin*
 ...
 orders_user     |
 user_admin      |

Role assignment process

A client authenticates to the orders database as a user named Alice, but the Alice user does not exist in Vertica. The authentication record associated with the orders database uses IDP validation and has oauth2_jit_enabled set to yes, so Vertica can JIT provision the Alice user and then assign roles that exist in both the IdP and Vertica.

When Alice authenticates to the orders database, Vertica performs the following steps:

  1. Provisions the Alice user.
  2. Sends a request to the IdP to retrieve roles using the OAuth2JITRolesClaimName and OAuth2JITGroupsClaimName security parameter settings. In this case, Vertica requests roles for a client identity named vertica and a group identity named groups.
  3. Compares all client and group roles in the IdP response to the roles in Vertica and performs the following:
    • Grants the orders_user role to the JIT-provisioned Alice user, and sets it as a default role.
    • Grants the user_admin role to the JIT-provisioned Alice user, and sets it as a default role.
    • Does not grant the dbadmin role to Alice because it is specified by the OAuth2JITForbiddenRoles security parameter.
    • Ignores the realm_admin group name and view_admin group role because there is no corresponding role in Vertica.

After the automatic role assignment process completes, Alice has default roles that reflect the IdP configuration:

=> SELECT user_name, default_roles FROM users 
   WHERE user_name = 'Alice';
 user_name |      default_roles
-----------+-------------------------
 Alice     | orders_user, user_admin
(1 row)

The automatic role assignment workflow occurs each time a client authenticates as the Alice user. This ensures that Vertica role assignments reflect the current role assignments in the IdP.

Automatic user pruning

You can enable automatic user pruning to periodically drop users created by JIT user provisioning if they do not log in after a certain period of time. This cleanup service is managed by the following database-level configuration parameters:

  • EnableOAuthJITCleanup: Whether to enable cleanup (disabled by default).

    => ALTER DATABASE DEFAULT SET EnableOAuthJITCleanup = 1; --enables the pruning service
    => ALTER DATABASE DEFAULT SET EnableOAuthJITCleanup = 0; --disables the pruning service
    
  • OAuth2UserExpiredInterval: The number of days a user must be inactive before it is dropped (14 by default). This is calculated based on the current date and the LAST_LOGIN_TIME in the USERS system table.

    => ALTER DATABASE DEFAULT SET OAuth2UserExpiredInterval = 20;
    
  • GlobalHeirUsername: The user to reassign objects to if the owner is a JIT-provisioned (or LDAP) user that got dropped by the pruning service. If set to <auto>, objects are reassigned to the dbadmin.

    => ALTER DATABASE DEFAULT SET GlobalHeirUsername = <auto>
    

The cleanup service runs daily and there can be a delay of up to 24 hours for dropping an expired user.

3 - OAuth authentication parameters

Vertica OAuth authentication records use the following parameters to determine how to validate client OAuth tokens and how to contact the identity provider during the validation process.

Vertica OAuth authentication records uses parameters to determine how to validate client OAuth tokens and how to contact the identity provider during the validation process. These parameters should be set with ALTER AUTHENTICATION.

Just-in-time provisioning parameters

The following parameters configure just-in-time user provisioning (JIT):

groups_claim_name
Sets the group claim name for the authentication record. This setting overrides the OAuth2JITGroupsClaimName security parameter.
oauth2_jit_enabled
Whether to enable just-in-time user provisioning. This parameter accepts the following values:
oauth2_jit_authorized_roles
When set, the OAuth user specifies roles that can use JIT user provisioning. When omitted, any OAuth user can use JIT provisioning.

This parameter accepts one or more roles as a comma-separated list.

role_group_suffix
OpenText Directory Service (OTDS) only.

Appends a value to the role or group name associated with the OAuth record. Vertica uses this value to identify users during authorization. Vertica recommends that you append your subscription ID in the following format: @subscriptionID.

roles_claim_name
Sets the roles claim name for the authentication record. This setting overrides the OAuth2JITRolesClaimName security parameter.

Validation modes

OAuth authentication records have two modes for validating OAuth tokens, each specified with the authentication parameter validate_type.

validate_type accepts one of the following values:

  • IDP (default): Validate OAuth tokens by contacting the identity provider. This validation type requires the client to specify their client secret. This should be used with confidential clients (set for each client by the identity provider).

  • JWT: Validate OAuth tokens by verifying that it was signed by the identity provider's private key. This does not require Vertica to contact the identity provider for validation and should be used for public clients (set for each client by the identity provider).

Each validation mode uses a different set of parameters, which are detailed in the sections below.

IDP validation parameters

The following parameters configure OAuth authentication records that use the IDP validation mode:

client_id
Required. The ID of the confidential client application registered in the identity provider. Vertica uses this ID to call the introspection API to retrieve user grants.
client_secret
Required. The secret of the confidential client application registered in the identity provider. This value is not shared with other clients.
discovery_url
Required for IDP validation if introspect_url is not specified.

Also known as the OpenID Provider Configuration Document or the well-known configuration endpoint, this endpoint contains information about the configuration and endpoints of the identity provider.

If you set the discovery_url, you do not have to set any other endpoint parameters. If you specify discovery_url and other endpoints, the discovery_url takes precedence.

introspect_url
Required if discovery_url is not specified. Used by Vertica to introspect (validate) access tokens. You must specify this parameter if you do not specify the discovery_url. For examples, see the Keycloak and Okta documentation.
auth_url
Required for single-sign on (SSO). The authorization endpoint for your identity provider.
token_url
Required for single-sign on (SSO). The token endpoint for your identity provider.
scope
Optional. The requested OAuth scopes, delimited with spaces. These scopes define the extent of access to the resource server (in this case, Vertica) granted to the client by the access token. For details, see the OAuth documentation.
validate_hostname
Optional. Boolean, whether Vertica verifies the subjectAltName of the identity provider host when establishing a connection. If enabled, the IP address or hostname of the identity provider must be set as the subjectAltName in its certificate. This parameter only applies to connections made by JDBC clients.

Hostname verification is enabled by default.

JWT validation parameters

The following parameters configure OAuth authentication records that use the JWT validation mode:

jwt_rsa_public_key
Required. In PEM format, the public key that corresponds to the private key used to sign the client's OAuth token. Vertica uses this to validate the OAuth token. If your identity provider does not natively provide PEM-formatted public keys, you must convert them to PEM format. For example, keys retrieved from an Okta endpoint are in JWK format and must be converted.
jwt_issuer
Required. The issuer of the OAuth token. This value is set by the identify provider.
jwt_user_mapping
Required. The name of the Vertica user.
jwt_accepted_audience_list
Optional. A comma-delimited list of values to accept from the client OAuth token's aud field. If set, tokens must include in aud one of the accepted audiences to authenticate.
jwt_accepted_scope_list
Optional. A comma-delimited list of values to accept from the client OAuth token's scope field. If set, tokens must include in scope at least one of the accepted scopes to authenticate.