This site contains the documentation that is relevant to older WSO2 product versions and offerings.
For the latest WSO2 documentation, visit https://wso2.com/documentation/.

Saving Access Tokens in Separate Tables

This feature is deprecated in Identity Server 5.3.0 release. The alternative to this is using database level table partitioning. Since all commercial databases support table partitioning as a first class feature, it is recommended to use table partitioning to partition required tables including IDN_ACCESS_TOKEN table.

You can configure the Identity Server instances to store access tokens in different tables according to their user store domain. This is referred to as user token partitioning and it ensures better security when there are multiple user stores configured in the system. For information on configuring user stores other than the default one, see Configuring Secondary User Stores.

To enable user token partitioning, you should change the <EnableAssertions> and <AccessTokenPartitioning> elements in the <IS_HOME>/repository/conf/identity/identity.xml file. A brief description of each element is given below:

ElementDescription

<EnableAssertions>

Assertions are used to embed parameters into tokens in order to generate a strong access token. You can also use these parameters later for various other processing functionality. At the moment, the Identity Server only supports UserName as an assertion. By default, assertions are set to false in identity.xml file.

<EnableAssertions>
        <UserName>false</UserName>
</EnableAssertions>

You can enable it by setting the <UserName> element to 'true'. You can add a user name to an access token when generating the key, and verify it by Base64-decoding for the retrieved access token.

<AccessTokenPartitioning>

This parameter implies whether you need to store the keys in different tables or not. It can be used only if <UserName> assertion is enabled. If it is, set the <EnableAccessTokenPartitioning> element to 'true' in <IS_HOME>/repository/conf/identity/identity.xml to store the keys in different tables.

<EnableAccessTokenPartitioning>true</EnableAccessTokenPartitioning>

Also set the user store domain names and mappings to new table names. For example,

  • if userId = foo.com/admin where 'foo.com' is the user store domain name, then a 'mapping:domain' combo can be defined as 'A:foo.com'.
  • 'A' is the mapping for the table that stores tokens relevant to users coming from 'foo.com' user store.

You can provide multiple mappings separated by commas as follows. Note that the domain names need to be specified in upper case.

<AccessTokenPartitioningDomains>A:FOO.COM, B:BAR.COM</AccessTokenPartitioningDomains>

According to the information given above, change the <OAuth> element in the identity.xml file as shown in the following example:

identity.xml
<!-- Assertions can be used to embedd parameters into access token.-->
<EnableAssertions>
     <UserName>true</UserName>
</EnableAssertions>

<!-- This should be set to true when using multiple user stores and keys should saved into different tables according to the user store. By default all the application keys are saved in to the same table. UserName Assertion should be 'true' to use this.-->
<AccessTokenPartitioning>
     <EnableAccessTokenPartitioning>true</EnableAccessTokenPartitioning>
     <!-- user store domain names and mappings to new table names. eg: if you provide 'A:foo.com', foo.com should be the user store domain   
     name and 'A' represent the relavant mapping of token storing table, i.e. tokens relevant to the users comming from foo.com user store     
     will be added to a table called IDN_OAUTH2_ACCESS_TOKEN_A. --> 
     <AccessTokenPartitioningDomains>A:foo.com, B:bar.com</AccessTokenPartitioningDomains>
</AccessTokenPartitioning>

Note that, it cannot add mapping for primary user store. So tokens for primary userstore will always stored in IDN_OAUTH2_ACCESS_TOKEN table. And if there there is a secondary user store which don't have a mapping, it use the domain name itself as it mapped alias.


Table creation

Once you configure the file for enable access token partitioning, you can create separate tables to store access tokens. These tables should be created in the database which is pointed in <DataSource> element under <JDBCPersistenceManager> in the identity.xml.

Since the IDN_OAUTH2_ACCESS_TOKEN_SCOPE has a foreign key reference to the IDN_OAUTH2_ACCESS_TOKEN table, when using access token partitioning feature, not only IDN_OAUTH2_ACCESS_TOKEN but also IDN_OAUTH2_ACCESS_TOKEN_SCOPE table should be created per each domain mapping configured in <AccessTokenPartitioningDomains> element.

Suppose, for the user store domain 'foo.com' it has defined the mapping as 'A', then it is needed to create IDN_OAUTH2_ACCESS_TOKEN_A table and IDN_OAUTH2_ACCESS_TOKEN_SCOPE_A table. Refer below example for the mysql script which creates two tables, indexes and relevant constraints:

CREATE TABLE IF NOT EXISTS IDN_OAUTH2_ACCESS_TOKEN_A (
            TOKEN_ID VARCHAR (255),
            ACCESS_TOKEN VARCHAR(255),
            REFRESH_TOKEN VARCHAR(255),
            CONSUMER_KEY_ID INTEGER,
            AUTHZ_USER VARCHAR (100),
            TENANT_ID INTEGER,
            USER_DOMAIN VARCHAR(50),
            USER_TYPE VARCHAR (25),
            GRANT_TYPE VARCHAR (50),
            TIME_CREATED TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
            REFRESH_TOKEN_TIME_CREATED TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
            VALIDITY_PERIOD BIGINT,
            REFRESH_TOKEN_VALIDITY_PERIOD BIGINT,
            TOKEN_SCOPE_HASH VARCHAR(32),
            TOKEN_STATE VARCHAR(25) DEFAULT 'ACTIVE',
            TOKEN_STATE_ID VARCHAR (128) DEFAULT 'NONE',
            SUBJECT_IDENTIFIER VARCHAR(255),
            PRIMARY KEY (TOKEN_ID),
            FOREIGN KEY (CONSUMER_KEY_ID) REFERENCES IDN_OAUTH_CONSUMER_APPS(ID) ON DELETE CASCADE,
            CONSTRAINT CON_APP_KEY_A UNIQUE (CONSUMER_KEY_ID,AUTHZ_USER,TENANT_ID,USER_DOMAIN,USER_TYPE,TOKEN_SCOPE_HASH,
                                           TOKEN_STATE,TOKEN_STATE_ID)
)ENGINE INNODB;

CREATE INDEX IDX_AT_CK_AU_A ON IDN_OAUTH2_ACCESS_TOKEN_A(CONSUMER_KEY_ID, AUTHZ_USER, TOKEN_STATE, USER_TYPE);

CREATE INDEX IDX_TC_A ON IDN_OAUTH2_ACCESS_TOKEN_A(TIME_CREATED);

CREATE INDEX IDX_AT_A ON IDN_OAUTH2_ACCESS_TOKEN_A(ACCESS_TOKEN);


CREATE TABLE IF NOT EXISTS IDN_OAUTH2_ACCESS_TOKEN_SCOPE_A (
            TOKEN_ID VARCHAR (255),
            TOKEN_SCOPE VARCHAR (60),
            TENANT_ID INTEGER DEFAULT -1,
            PRIMARY KEY (TOKEN_ID, TOKEN_SCOPE),
            FOREIGN KEY (TOKEN_ID) REFERENCES IDN_OAUTH2_ACCESS_TOKEN_A(TOKEN_ID) ON DELETE CASCADE
)ENGINE INNODB;

If you are using any other database server, you can use the sql script related to your database server, from sql scripts located at <IS_HOME>/dbscripts/identity/directory. These scripts contains all the tables related to identity data (not specific to this feature). You need to extract queries creating detault IDN_OAUTH2_ACCESS_TOKEN table and IDN_OAUTH2_ACCESS_TOKEN_SCOPE tables and indexes and relevant constraints. Then update table names of two tables, relavent indexes, and relevant constraints to append user store domain mapping as in the above example.

 Click here to see how to test this feature,

The following example describes how to test this feature.

Limitations

  • Since the user store to table mapping is configured as a static mapping in identity.xml, this feature cannot used if you have more user stores getting created at runtime.
  • All tenants use the same mapping configured as per above configurations, it cannot define mappings differenly for each tenants.