OAuth2 Authentication Support

Prev Next

OAuth2 is an authorization protocol that provides a secure way to access protected data from an application. The PIP Service can be configured to use OAuth 2.0 to securely access API based data sources, such as SCIM, Azure AD, OData, and REST.

To support OAuth authentication, pre-configuration is required. Individual websites typically provide developer-facing REST-based APIs for accessing their content and ways to register custom applications on users' behalf. The first step is to register the custom application on the website and collect consumer/API keys and secrets.

OAuth Configuration For PAA

After you get your service client credentials, you need to set them up in the PIP Auth configuration. Currently, the Auth configuration for external services is done in an auth XML file containing general setup that you don’t need to change and security policy sections that need to be added for each service using OAuth.

Environment Variables

Before configuring the sample code below, note that any module-option name can be set using an environment variable by enclosing it in ${env:<module-option>}. The variable name can be any valid string.

For example: <module-option name=“client-secret”> ${env: CLIENT_SECRET} </module-option>

Using Secret Annotations in OAuth Configuration

In OAuth authentication, you can reference a secret from a secret store within the OAuth XML configuration file. The following example demonstrates how to use a secret annotation for the client-secret field:

<application-policy name="ps-auth2-massive">
    <authentication>
        <login-module code="com.plainid.pip.auth.oauth.clientcredential.OAuth20ClientCredentialLoginModule" flag="required">
            <module-option name="access-token-uri">https://login.microsoftonline.com/cd6168ed-fe82-4528-b2eb-4e030d322878/oauth2/v2.0/token</module-option>
            <module-option name="client-id">19f4ef6c-d0dd-42f0-844c-b529b609a171</module-option>
            <module-option name="client-secret">{{ printf "{{store=AWS_SECRETS_MANAGER_STORE,key=path1/path2/key}}" }}</module-option>
            <module-option name="scope">https://graph.microsoft.com/.default</module-option>
        </login-module>
    </authentication>
</application-policy>

Refer to Using Secrets for PIP Data Sources for more information.

Sample auth-config.xml file:

<?xml version='1.0'?>
<policy xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:jboss:security-config:5.0" xmlns="urn:jboss:security-config:5.0" xmlns:jbxb="urn:jboss:security-config:5.0">
  <application-policy name="teiid-security-file">
    <authentication>
      <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule" flag="required">
        <!-- https://access.redhat.com/documentation/en-us/jboss_enterprise_application_platform/5/html/security_guide/ch12#Using_JBoss_Login_Modules-Password_Hashing -->
        <module-option name="usersProperties">users.properties</module-option>
        <module-option name="rolesProperties">roles.properties</module-option>
        <module-option name="unauthenticatedIdentity">nobody</module-option>
        <module-option name="hashAlgorithm">MD5</module-option>
        <module-option name="hashEncoding">base64</module-option>
      </login-module>
    </authentication>
  </application-policy>

  <application-policy name="oauth2-azure-ad-staging">
    <authentication>
      <login-module code="com.plainid.pip.auth.oauth.clientcredential.OAuth20ClientCredentialLoginModule" flag="required">
        <module-option name="scope">https://graph.microsoft.com/.default</module-option>
        <module-option name="access-token-uri">https://login.microsoftonline.com/********-****-****-****-************/oauth2/v2.0/token</module-option>
        <module-option name="client-id">client-id</module-option>
        <module-option name="client-secret">{{ printf "{{store=AWS_SECRETS_MANAGER_STORE,key=path1/path2/key}}" }}</module-option>
      </login-module>
    </authentication>
  </application-policy>

  <!-- Add application credentials. Details below -->
</policy>

For each service using OAuth, you need to add an <application policy> section with the relevant service credentials.

Sample <application-policy> Settings for Azure AD OAuth Configuration

<application-policy name="oauth2-azure-ad-staging">
  <authentication>
    <login-module code="com.plainid.pip.auth.oauth.clientcredential.OAuth20ClientCredentialLoginModule" flag="required">
      <module-option name="scope">https://graph.microsoft.com/.default</module-option>
      <module-option name="access-token-uri">https://login.microsoftonline.com/********-****-****-****-************/oauth2/v2.0/token</module-option>
        <module-option name="client-id">${env:AAD_CLIENT_ID}</module-option>
        <module-option name=“client-secret”>${env:AAD_CLIENT_SECRET}</module-option>
    </login-module>
  </authentication>
</application-policy>

The application-policy name (in the above example is oauth2-azure-ad-staging) is used to set the Security Domain field in the PIP Settings screen when configuring the Data Source.

Module Options Properties Table

The OAuth jar (pip-auth-extensions-#.jar) and auth-config.xml configuration file should be set in all PAAs.

Property Description Mandatory
scope OAuth2 scope No
access-token-uri Access token URL from IDP Yes
client-id Client ID of the application Yes
client-secret Client Secret of the application Yes
setAuthorizationHeader Indicates how client credentials will be sent to the token endpoint (True - ClientID and Secret passed as authorization header, False - ClientID and Secret passed in the form payload) No

Assertion Flow OAuth Configuration

Some services may require the OAuth 2.0 assertion flow instead of the standard client credentials flow. The PIP Service supports this using the OAuth20AssertionCCLoginModule, which exchanges a signed JWT for an access token at the token endpoint.

This module signs a JWT using a private key and submits it to the token endpoint to obtain an access token. Unlike standard OAuth flows that use a client secret, the assertion flow is required when the identity provider enforces key-based authentication.

Example

Below is an Okta Assertion Flow example:

<application-policy name="Acme1">
  <authentication>
    <login-module code="com.plainid.pip.auth.oauth.assertion.OAuth20AssertionCCLoginModule" flag="required">
      <module-option name="client-id">0oav0ftbpiwt38hgf697</module-option>
      <module-option name="scope">okta.users.read okta.users.manage</module-option>
      <module-option name="access-token-uri">https://integrator-143235553242307.okta.com/oauth2/v1/token</module-option>
      <module-option name="private-key">-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiGew0BAQ2FAASCBKgwggSkAjhgfhAoIBfQCttJR5P6cE71A8
...
psu+yfpqVRsUy0yaJnNR7jeu
-----END PRIVATE KEY-----</module-option>
    </login-module>
  </authentication>
</application-policy>

Module Options for Assertion Flow

Property Description Mandatory
client-id Application Client ID registered in the IdP Yes
scope Space-separated OAuth scopes for access Yes
access-token-uri Identity provider token endpoint URL Yes
private-key Private key used to sign the JWT for assertion Yes
Secret Manager Support

Secret Manager (SM) support: Only the client-id and private-key can reference secrets using the store format described in the Secret Management documentation:
{{store=<storeName>,key=<keyName>,jsonpath=$.<path>}}


User-Password login through Token configuration

This module supports calling a REST API endpoint for authentication and retrieving a token that can be used for requests to services using User/Password Login Tokens (not by OAuth standard), like the Saviynt API.

To support this general User/Password flow, use the login module called TokenRestLoginModule. Instead of exchanging a Client ID and Secret in a token endpoint as done in a standard OAuth 2.0 client credential flow, it makes a REST call to a login API, sends the required credentials as parameters or in the request body, and extracts a token from the response.

Saviynt Note

For example, Saviynt uses the /ECM/api/login endpoint to authenticate API calls. This requires users to send a user/password, they receive a token from the login response, and then using that token to authenticate subsequent Saviynt API requests and fetch data.

The new TokenRestLoginModule supports two configuration flows using configurable credentials in:

  • The Login call as request params.
  • The params to generate a Login call payload if the login endpoint expects a request body.
Secret Manager Support

The credentials defined in the username and password parameters can be obtained through Secret Manager support by configuring a secret key syntax. like{{store=,key=,jsonpath=$.}}, instead of entering clear text credentials. See the Secret Management
{target=_blank} documentation for more information.

Examples

Credentials Params Example

<application-policy name="saviynt1">
  <authentication>
    <login-module code="com.plainid.pip.auth.oauth.custom.TokenRestLoginModule" flag="required">
      <module-option name="url">https://<saviynt-base-url>/ECM/api/login</module-option>
      <module-option name="param:username">admin</module-option>
      <module-option name="param:password">adminpass123</module-option>
      <module-option name="header:Content-Type">application/json</module-option>
      <module-option name="method">POST</module-option>
      <module-option name="body">{}</module-option>
      <module-option name="credential-flow">Basic</module-option>
    </login-module>
  </authentication>
</application-policy>

Parameterized Body Example

In this option the username and password are declared as params and defined in the config and than referenced by the syntax ${param} in the body template.

<application-policy name="saviynt1">
  <authentication>
    <login-module code="com.plainid.pip.auth.oauth.custom.TokenRestLoginModule" flag="required">
      <module-option name="url">https://<saviynt-base-url>/ECM/api/login</module-option>
      <module-option name="param:username">admin</module-option>
      <module-option name="param:password">adminpass123</module-option>
      <module-option name="header:Content-Type">application/json</module-option>
      <module-option name="method">POST</module-option>
      <module-option name="body">{"username": "${username}","password": "${password}"}</module-option>
    </login-module>
  </authentication>
</application-policy>

Module Options

These are Module options for Saviynt:

Property Description Mandatory
url Saviynt login API endpoint (e.g., https://<saviynt-base-url>/ECM/api/login) Yes
param:username Username for authentication. Can use Secret Manager variables with the format {{store=<storeName>,key=<keyName>,jsonpath=$.<path>}} Yes
param:password Password for authentication. Can use Secret Manager variables with the format {{store=<storeName>,key=<keyName>,jsonpath=$.<path>}} Yes
header:Content-Type Content type header (usually application/json) Yes
method HTTP method used for authentication, usually POST Yes
body Any text (e.g., JSON) sent to the login endpoint. Supports parameterization with ${} placeholders for dynamic values (username, password, etc.) Yes
credential-flow When set to Basic, the param:username and param:password values are automatically encoded as Basic Auth using Base64 on <user>:<password>.

If omitted or left empty, Basic Auth is not applied and the user must manually include the username and password as needed, like within the JSON payload in body.
No

Additional Information

  • Environment variables: Any module-option can be overridden with environment variable syntax (${env:VAR_NAME}). Tags in between are processed through an Environment Variable translation.

Containerized PAA

In Containerized PAA, the auth-config.xml file is located at app/conf/auth-config.xml.

PlainID PAA Helm Chart includes two configuration files:

  • values.yaml - Stores all potential setting parameters, and the default values for the PAA.
  • custom-values.yaml - Used to set only the parameters/settings that are modified. As a best practice, we recommend using this file for setting the relevant parameter values by adding configuration values from the values.yaml to the values-custom.yaml file.

You can use the above custom-values.yaml mechanism to inject your auth-config.xml file. You need to add all the XML content, not just your application policies sections, to your custom-values.yaml under this key:

pipOperator:
  plainIDConfig:
    auth-config.xml: |
      <?xml version='1.0'?>
      <policy xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:jboss:security-config:5.0"
        xmlns="urn:jboss:security-config:5.0">
        <!-- Add your XML content here -->
      </policy>

Following is an example:

tenantId: "ENTER_TENANT_ID" # Tenant Id (can be found in the Hybrid Agent Keys tab)
agentSecretKey: "ENTER_AGENT_SECRET_KEY" # Agent Secret key (can be found in the Hybrid Agent Keys tab)
paaId: "ENTER_PAA_ID" # Policy Authorization Agent Id (can be found in the Policy Authorization Agents tab)

pipOperator:
  plainIDConfig:
    auth-config.xml: |
      <?xml version='1.0'?>
      <policy xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:jboss:security-config:5.0"
        xmlns="urn:jboss:security-config:5.0">
        <!-- Add your XML content here -->
      </policy>

Standalone/VM PAA

In a Standalone/VM PAA, the auth-config.xml file is located at $PLAINID_HOME/pip-operator/conf/auth-config.xml. Add OAuth services as application policies, as described above.

OAuth Logging

Additional logging for OAuth can be configured by adding the following section to the auth-config.xml via the custom-values.yaml mechanism:

<logger name="org.teiid.jboss.oauth" level="detail" additivity="false">
    <appender-ref ref="RollingFile" />
</logger>

OAuth Setting For PIP Data Sources

After completing the OAuth configuration, you will be able to configure PIP data sources accessible by OAuth authentication.

In the PIP settings UI, when creating a data source with adapters that allow/require the usage of OAuth (e.g., Azure Active Directory, SCIM, REST, or OData v4.0), you will need to reference the auth-config.xml file and the specific application-policy name as the Security Domain:

  1. In the Policy Authorization Agent section(s), under the Security Type field, choose None.

  2. In the Translator Properties section, add two new properties with these key-value pairs:

    • Key = authConf, Value = "<path of the auth-config.xml file as described above.>"
    • Key = securityDomain, Value = "<name of the application-policy you added in the XML for your service>"

Using Secrets for PIP Data Source Connections

When configuring databases and other data sources in the UI, you can use secrets to manage authentication credentials securely. Instead of storing credentials in plain text, you can reference them from a secret store, enabling seamless secret rotation and enhanced security.