Skip to main content

Resource Server Adapter for OIDC

The OIDC version of the Resource Server Adapter (RSA) is built on top of RSA-SDK/RSA-core and enables an access- and identity- conscious gateway relationship to a true Resource Server that must be an OIDC Provider.

The RSA-OIDC Admin API is used to administer the application's database.

Overview of steps to configure RSA-OIDC

  1. Configure an OAuth relationship with a federated OIDC provider (serving as the real Resource Server) using static and dynamic database configuration. Refer to Configure Federated OIDC Provider.

  2. Configure an OAuth relationship with a Wallet (as a Provider to the Wallet) and select a Resource Owner Token (ROT) issuance and creation strategy. Refer to Configure OAuth Relationship with a Wallet.

  3. Configure an Authorization Server (as a client to the Authorization Server). Refer to Configure an Authorization Server.

    Note: Wallet must be registered as an OAuth Client and Provider to the same Authorization Server to which the RSA-OIDC Adapter is being registered against.

  4. Configure Protected Resources using static and dynamic database configuration. Refer to Configure a Protected Resource.

Prerequisites and Assumptions

This section of the guide is meant for the people who will be operating and administering the RSA-OIDC. It assumes the reader is familiar with the FPX solution and its components.

To use the RSA-OIDC Admin API:

  1. The RSA-OIDC's database must be accessible.
    • The RSA-OIDC application should have been run at least once to initialize the database.
  2. The RSA-OIDC Admin API server must be accessible at some URI, represented in this guide as {{RSA_ADMIN_URI}}.
    • The Admin API should also have access to the application database.
  3. The administrator must have a valid authorization token.
  4. Requests to the Admin API should include the desired API version in a ApiVersion header. The default is v1.0, and this value is represented in this guide as {{RSA_ADMIN_VERSION}}.
  5. Requests to the Admin API should include a Content-Type header with the value application/vnd.api+json. The requests shown in this guide provide all required headers.

Additionally, both the Wallet Server and Authorization Server should have been configured as shown in previous sections of this guide, and their respective Admin APIs should be running and accessible.

How to define and use the Authorization Token

All Admin API endpoints require the use of the Authorization HTTP header. The RSA-OIDC Admin API currently uses a static access token to authorize all requests.

The value of the Authorization Token can be defined in application config section of the Helm chart, using the property rsa-admin.staticToken. The value of this token will be represented in the following pages as {{RSA_ADMIN_STATIC_TOKEN}}.

Environment variables

For a given FPX deployment, there will be a number of values that are common across components and across API calls. The API calls shown in the following sections represent these values as variables surround by two pairs of curly braces. These variables should be defined beforehand and recorded for easy reference as you go through this guide.

The variables are as follows:

  • {{RSA_ADMIN_STATIC_TOKEN}} - as explained above
  • {{RSA_ADMIN_VERSION}} - this is the version of the API to make a request to, which defaults to "v1.0"
  • {{RSA_ADMIN_URI}} - this is the URI of the RSA-OIDC Admin API, and should match the host name of the RSA-OIDC Admin API defined in the RSA-OIDC Admin Helm chart, but with “/json-api” appended
  • {{RSA_URI}} - this is the URI of the RSA-OIDC itself, and should match the host name of the RSA-OIDC defined in the RSA-OIDC Helm chart

Additionally, there are requests used to register the RSA at the Wallet and Authorization Server. Therefore, there is a similar set of variables for each of these components.

For the Authorization Server:

  • {{AS_ADMIN_STATIC_TOKEN}} - Defined in the application config of the Authorization Server using the property as-admin.staticToken
  • {{AS_ADMIN_VERSION}} - this is the version of the API to make a request to, which defaults to "v1.0"
  • {{AS_ADMIN_URI}} - this is the URI of the AS Admin API, and should match the host name of the AS Admin API defined in the AS Admin Helm chart, but with “/json-api” appended
  • {{AUTH_SERVER_URI}} - this is the URI of the Authorization Server, and should match the host name of the Authorization Server in its respective Helm chart

For the Wallet:

  • {{WS_ADMIN_STATIC_TOKEN}} - Defined in the application config of the Wallet using the property wallet-admin.staticToken
  • {{WS_ADMIN_VERSION}} - this is the version of the API to make a request to, which defaults to "v1.0"
  • {{WALLET_ADMIN_URI}} - this is the URI of the Wallet Admin API, and should match the host name of the Wallet Admin API defined in the Wallet Admin Helm chart, but with “/json-api” appended
  • {{WALLET_SERVER_URI}} - this is the URI of the Wallet Server, and should match the host name of the Wallet Server in its respective Helm chart

Testing a Successful Configuration

When using the RSA-OIDC Admin API, there are a few ways to check if the attempted operation was successful:

  • A 2XX http response. All APIs return a 2XX type http status code on success. The response body should be checked against the OpenAPI specification.
  • A subsequent GET request can be used to confirm what was stored by the API.
  • If the application server is not running, this can also be verified by inspecting the appropriate table in the application database.
  • Test the front-end application. If successfully configured, the front-end client should be able to see and interact with the configured RSA.

API Response Filtering

The API Response Filtering feature provides administrators with the ability to limit the amount of information that a Resource Server Adapter (RSA) returns when an API call is made against a particular endpoint. This feature can be used to filter out, append or swap information from an endpoint response to ensure that the client receives only those elements that they are authorized to access.

Most OAuth 2.0 endpoints return a standardized array of information related to the authenticated user. However, not all information returned from these endpoints may be relevant to the business need of the client making the call. Furthermore, delegated users may also need access to only a subset of the fields returned by a given endpoint. Restrictions are applied based on the scopes granted to clients. Scopes are mapped to resource locations that are configured in the database.

Configuring API Response Filtering

note

API Response Filtering is configured exclusively from the database. There are no YAML parameters that need modifications to enable this feature. Refer to the table below for a list of relevant database tables that need to be modified to support this feature.

Tables that need to be configured and their purpose is as below:

TablesPurposeColumns
authorityThis table is used to define the authorities (i.e. email_authority). These authorities can be mapped to corresponding API filters. When a user with the proper authority accesses a resource through the API, the corresponding filter is triggered and filtering functionality is activated. Authority names can be defined by the administrators and are exclusive to the RSA. However, the exact same name should be used when making subsequent API calls to populate other tables. Any variation in the authority name may result in an error.ID, Version, Authority_Value
resource_authority_mappingMaps a scope to an authority to be granted. The value of resource doesn't affect the table and can be set to any appropriate value or can even be set to "null". In order to avoid duplication of granted authorities, it is recommended to have only one instance of similar scope + resource.Resource, Scope, Authority
authority_filtering_api_pathDefines paths that will have filtering functionality enabled on them.ID, Version, API, Method
api_filter_mappingDefines the filter that is enabled on the paths defined in the authority_filtering_api_path table by specifying the filter name. Refer to the table provided below to see the filters that are available and how they work.ID, Version, Filter_Type, Order_Priority, Authority_Filtering_API_Path
authority_claim_filter_configIf the api_filter_mapping table has the claim_key_swap_filter and/or restrict_to_authorized_claims_filter enabled, then this table defines the JSON keys that need to be converted to new key names and/or the keys that are permitted to be present in the final response. Additionally, this table facilitates specifying the API path to which each rule is applicable.ID, Version, Incoming_Claim_Name, Outgoing_Claim_Name, Priority, Authority, API_Path
api_path_required_authorityDefines required authorities (resources + scopes) to access specific endpoints. An API path can be configured to have multiple authorities assigned to it.API_Path_ID, Authority_ID
authority_claim_combiner_configThis table is used to configure the filters that combine and transform claims into an outgoing claim name.

The following steps relate to the tables listed above and need to be executed in sequence to set up OAuth 2.0 endpoints to filter/swap/append data from their responses.

  1. Define Authorities
  2. Map Resources to Authorities
  3. Define the path and method of the API that needs to be customized
  4. Define the type of filter to apply (Restrict/Swap/Combine/Related)

Defining Authorities

The API Response Filtering feature uses 'Authority' definitions at the backend to perform the required operations. An 'Authority' is essentially a logical grouping of a Resource and a Scope that feeds into the filtering process as a single entity instead of multiple items. For example, the resource "userinfo-profile" + a scope "read" is granted the authority "self-personal-information-access". The administrator can then use "self-personal-information-access" to configure the server's filters to include "address", "email", "firstName", "lastName" within the user's userInfo response, instead of needing to repeat "userinfo"+"read" multiple times. This grouping into authorities also makes it easier to change if additional Resource + Scope combinations trigger existing filters. For example, if the administrator needs "ldap-profile+read" to trigger the same functionality, then this LDAP authority can be mapped to "self-personal-information-access" instead of individually defining "ldap-profile+read" for each filter that's needed. This not only streamlines the set up of API response filtering but also eliminates the chances of human error creeping in.

The authority mapping allows administrators to group resources and scopes together without needing to repeat the resource and the scope whenever they want to specify that a filter requires them.

As a first step of setting up API response filtering, authorities need to be defined in the authority table. The following is a sample API call to populate the authority table with new authorities. Each authority is given a numeric ID which is referenced in subsequent tables.

curl --location -g --request PATCH '{{rsa_admin_uri}}/' \
--header 'User-Agent: agent' \
--header 'Content-Type: application/vnd.api+json; ext=jsonpatch' \
--header 'ApiVersion: {{rsa_admin_version}}' \
--header 'Authorization: {{rsa_admin_static_token}}' \
--data-raw '[
{
"op": "add",
"path": "/authority",
"value": {
"type": "authority",
"id": 1,
"attributes": {
"authorityValue": "email_authority"
}
}
},
{
"op": "add",
"path": "/authority",
"value": {
"type": "authority",
"id": 2,
"attributes": {
"authorityValue": "profile_authority"
}
}
},
{
"op": "add",
"path": "/authority",
"value": {
"type": "authority",
"id": 3,
"attributes": {
"authorityValue": "openid_authority"
}
}
}
,
{
"op": "add",
"path": "/authority",
"value": {
"type": "authority",
"id": 4,
"attributes": {
"authorityValue": "read_authority"
}
}
}
]'

note

If the authority table is not populated, the request made against the selected endpoint (e.g. userInfo) will be rejected due to insufficient permissions.

Map Resources to Authorities

Within the resource_authority_mapping table, administrators can set up resource - authority mappings. This table establishes the relationship between a resource, scope and an authority that is created in the previous step.

To add a resource authority mapping, execute the following API call:

curl --location -g --request PATCH '{{rsa_admin_uri}}/' \
--header 'User-Agent: agent' \
--header 'Content-Type: application/vnd.api+json; ext=jsonpatch' \
--header 'ApiVersion: {{rsa_admin_version}}' \
--header 'Authorization: {{rsa_admin_static_token}}' \
--data-raw '[
{
"op": "add",
"path": "/resource-authority-mapping",
"value": {
"type": "resource-authority-mapping",
"id": "{{rsa_resource_1_id}} email",
"attributes": {
"authorityString": "email_authority"
}
}
},
{
"op": "add",
"path": "/resource-authority-mapping",
"value": {
"type": "resource-authority-mapping",
"id": "{{rsa_resource_1_id}} profile",
"attributes": {
"authorityString": "profile_authority"
}
}
},
{
"op": "add",
"path": "/resource-authority-mapping",
"value": {
"type": "resource-authority-mapping",
"id": "{{rsa_resource_1_id}} openid",
"attributes": {
"authorityString": "openid_authority"
}
}
},
{
"op": "add",
"path": "/resource-authority-mapping",
"value": {
"type": "resource-authority-mapping",
"id": "{{rsa_resource_1_id}} read",
"attributes": {
"authorityString": "read_authority"
}
}
}
]'

It is important to note that if a client does not have all the required authorities for a given resource, they will not be authorized to access the endpoint and will receive a 401 error. For example, if a client has read authority and doesn't have write authority where both read and write authorities are required, they will receive a 401 Unauthorized error (even if everything else is set correctly). Therefore, it is important to ensure all the necessary authorities to access the required resources are present.

Define the Path and Method of the API to be filtered

Next, populate the authority_filtering_api_path and api_path_required_authority tables using the following API call:


curl --location -g --request POST '{{rsa_admin_uri}}/authority-filtering-api-path' \
--header 'User-Agent: agent' \
--header 'Content-Type: application/vnd.api+json' \
--header 'ApiVersion: {{rsa_admin_version}}' \
--header 'Authorization: {{rsa_admin_static_token}}' \
--data-raw '{
"data": {
"type": "authority-filtering-api-path",
"id": 1,
"attributes": {
"api": "/api/userinfo",
"method": "GET"
},
"relationships": {
"requiredAuthorities": {
"data": [
{
"id": 1,
"type": "authority"
},
{
"id": 2,
"type": "authority"
},
{
"id": 3,
"type": "authority"
},
{
"id": 4,
"type": "authority"
}
]
}
}
}
}'

Define the type of filter to apply

All filter types that can be applied to an API endpoint in FPX must be defined in the api_filter_mapping table.

Restrict/Swap/Combine

Restrict Filter

The restrict_to_authorized_claims_filter takes precedence over other types of filters defined as part of /api-filter-advice-mapping since it is responsible for removing claims from attributes.

curl --location -g --request PATCH '{{rsa_admin_uri}}/' \
--header 'User-Agent: agent' \
--header 'Content-Type: application/vnd.api+json; ext=jsonpatch' \
--header 'ApiVersion: {{rsa_admin_version}}' \
--header 'Authorization: {{rsa_admin_static_token}}' \
--data-raw '[
{
"op": "add",
"path": "/api-filter-advice-mapping",
"value": {
"type": "api-filter-advice-mapping",
"id": 1,
"attributes": {
"filterType": "restrict_to_authorized_claims_filter",
"orderPriority": 1
},
"relationships": {
"authorityFilteringApiPath": {
"data": {
"id": 1,
"type": "authority-filtering-api-path"
}
}
}
}
}
]'

If the restrict_to_authorized_claims_filter filter is not defined, the restrict filter will not be available for use. If it is defined, then all outgoing claims will need to be defined in the authority-claim-filter-config table as highlighted below:

[
{
"op": "add",
"path": "/authority-claim-filter-config",
"value": {
"type": "authority-claim-filter-config",
"id": 1,
"attributes": {
"incomingClaimName": "email",
"outgoingClaimName": "alter_email",
"priority": 1
},
"relationships": {
"authority": {
"data": {
"id": 1,
"type": "authority"
}
},
"authorityFilteringApiPath": {
"data": {
"id": 1,
"type": "authority-filtering-api-path"
}
}
}
}
},
{
"op": "add",
"path": "/authority-claim-filter-config",
"value": {
"type": "authority-claim-filter-config",
"id": 2,
"attributes": {
"incomingClaimName": "given_name",
"outgoingClaimName": "first_name",
"priority": 1
},
"relationships": {
"authority": {
"data": {
"id": 2,
"type": "authority"
}
},
"authorityFilteringApiPath": {
"data": {
"id": 1,
"type": "authority-filtering-api-path"
}
}
}
}
},
{
"op": "add",
"path": "/authority-claim-filter-config",
"value": {
"type": "authority-claim-filter-config",
"id": 3,
"attributes": {
"incomingClaimName": "family_name",
"outgoingClaimName": "last_name",
"priority": 1
},
"relationships": {
"authority": {
"data": {
"id": 2,
"type": "authority"
}
},
"authorityFilteringApiPath": {
"data": {
"id": 1,
"type": "authority-filtering-api-path"
}
}
}
}
}
]

Swap Filter

This filter is used to swap out incoming/outgoing values from an endpoint.

curl --location -g --request PATCH '{{rsa_admin_uri}}/' \
--header 'User-Agent: agent' \
--header 'Content-Type: application/vnd.api+json; ext=jsonpatch' \
--header 'ApiVersion: {{rsa_admin_version}}' \
--header 'Authorization: {{rsa_admin_static_token}}' \
--data-raw '[
{
"op": "add",
"path": "/api-filter-advice-mapping",
"value": {
"type": "api-filter-advice-mapping",
"id": 2,
"attributes": {
"filterType": "claim_key_swap_filter",
"orderPriority": 2
},
"relationships": {
"authorityFilteringApiPath": {
"data": {
"id": 1,
"type": "authority-filtering-api-path"
}
}
}
}
}
]'

If the claim_key_swap_filter filter is not defined, the swap filter will not be available for use. If it is defined, then all incoming & outgoing claims will need to be defined in the authority-claim-filter-config table as highlighted below. If the claims in the endpoint response match the 'incoming_claims', the Resource Server Adapter will convert or swap the incoming claim with the outgoing claim. The API call for the same is as below:

[
{
"op": "add",
"path": "/authority-claim-filter-config",
"value": {
"type": "authority-claim-filter-config",
"id": 1,
"attributes": {
"incomingClaimName": "email",
"outgoingClaimName": "alter_email",
"priority": 1
},
"relationships": {
"authority": {
"data": {
"id": 1,
"type": "authority"
}
},
"authorityFilteringApiPath": {
"data": {
"id": 1,
"type": "authority-filtering-api-path"
}
}
}
}
},
{
"op": "add",
"path": "/authority-claim-filter-config",
"value": {
"type": "authority-claim-filter-config",
"id": 2,
"attributes": {
"incomingClaimName": "given_name",
"outgoingClaimName": "first_name",
"priority": 1
},
"relationships": {
"authority": {
"data": {
"id": 2,
"type": "authority"
}
},
"authorityFilteringApiPath": {
"data": {
"id": 1,
"type": "authority-filtering-api-path"
}
}
}
}
},
{
"op": "add",
"path": "/authority-claim-filter-config",
"value": {
"type": "authority-claim-filter-config",
"id": 3,
"attributes": {
"incomingClaimName": "family_name",
"outgoingClaimName": "last_name",
"priority": 1
},
"relationships": {
"authority": {
"data": {
"id": 2,
"type": "authority"
}
},
"authorityFilteringApiPath": {
"data": {
"id": 1,
"type": "authority-filtering-api-path"
}
}
}
}
}
]

Combine

This filter is used to combine incoming claims together.

curl --location -g --request PATCH '{{rsa_admin_uri}}/' \
--header 'User-Agent: agent' \
--header 'Content-Type: application/vnd.api+json; ext=jsonpatch' \
--header 'ApiVersion: {{rsa_admin_version}}' \
--header 'Authorization: {{rsa_admin_static_token}}' \
--data-raw '[
{
"op": "add",
"path": "/api-filter-advice-mapping",
"value": {
"type": "api-filter-advice-mapping",
"id": 13,
"attributes": {
"filterType": "claim_combiner_filter",
"orderPriority": 3
},
"relationships": {
"authorityFilteringApiPath": {
"data": {
"id": 1,
"type": "authority-filtering-api-path"
}
}
}
}
}
]'

If the claim_combiner_filter filter is not defined, the combine filter will not be available for use. If it is defined, the administrator must define claims to be combined in the authority-claim-combiner-config table.

curl --location -g --request PATCH '{{rsa_admin_uri}}' \
--header 'User-Agent: agent' \
--header 'Content-Type: application/vnd.api+json; ext=jsonpatch' \
--header 'ApiVersion: {{rsa_admin_version}}' \
--header 'Authorization: {{rsa_admin_static_token}}' \
--data-raw '[
{
"op": "add",
"path": "/authority-claim-combiner-config",
"value": {
"type": "authority-claim-combiner-config",
"id": 1,
"attributes": {
"claimKey": "given_name",
"claimLiteral": null,
"outgoingClaimName": "full_name",
"priority": 1
},
"relationships": {
"requiredAuthority": {
"data": {
"id": 2,
"type": "authority"
}
},
"authorityFilteringApiPath": {
"data": {
"id": 1,
"type": "authority-filtering-api-path"
}
}
}
}
},
{
"op": "add",
"path": "/authority-claim-combiner-config",
"value": {
"type": "authority-claim-combiner-config",
"id": 2,
"attributes": {
"claimKey": null,
"claimLiteral": " ",
"outgoingClaimName": "full_name",
"priority": 2
},
"relationships": {
"requiredAuthority": {
"data": {
"id": 2,
"type": "authority"
}
},
"authorityFilteringApiPath": {
"data": {
"id": 1,
"type": "authority-filtering-api-path"
}
}
}
}
},
{
"op": "add",
"path": "/authority-claim-combiner-config",
"value": {
"type": "authority-claim-combiner-config",
"id": 3,
"attributes": {
"claimKey": "family_name",
"claimLiteral": null,
"outgoingClaimName": "full_name",
"priority": 3
},
"relationships": {
"requiredAuthority": {
"data": {
"id": 2,
"type": "authority"
}
},
"authorityFilteringApiPath": {
"data": {
"id": 1,
"type": "authority-filtering-api-path"
}
}
}
}
}
]'

This filter is used populate information about a related or delegated user as part of an API call that is made, e.g. a call made at the userInfo endpoint would return information pertaining to the related or linked user as well. The following API call must be made to enable the related filter:

curl --location -g --request PATCH '{{rsa_admin_uri}}/' \
--header 'User-Agent: agent' \
--header 'Content-Type: application/vnd.api+json; ext=jsonpatch' \
--header 'ApiVersion: {{rsa_admin_version}}' \
--header 'Authorization: {{rsa_admin_static_token}}' \
--data-raw '[
{
"op": "add",
"path": "/api-filter-advice-mapping",
"value": {
"type": "api-filter-advice-mapping",
"id": 14,
"attributes": {
"filterType": "user_info_related_filter",
"orderPriority": 4
},
"relationships": {
"authorityFilteringApiPath": {
"data": {
"id": 1,
"type": "authority-filtering-api-path"
}
}
}
}
}
]'

The following is a full list of available filters that can be configured and their corresponding functionality:

FiltersFunction
user_info_related_filterThis filter inserts related users into the map, which is typically used for the resource management functionality for the UserInfo endpoint. It injects the related: {} field into the JSON. This is performed by the resource management service in the 'resource-owner-token' library.
restrict_to_authorized_claims_filterThis filter uses the Spring authorities granted to the user to get a list of all claims and restricts the response to only those claims via the outgoing_claim_names in the authority_claim_filter_config table. This filter can remove all other claims, including sensitive ones like birth dates. You can set this filter to always take effect by setting the authority to null in the row.
claim_key_swap_filterThis filter uses the Spring authorities granted to the user to get a list of all claims to change the key from the incoming claim name to the outgoing claim name specified in the authority_claim_filter_config table. For example, this filter could swap the birthdate claim from its original key to a new key called birth_date. You can set this filter to always take effect by setting the authority to null in the row.
claim_combiner_filterThis filter combines multiple claims into a single claim based on the configuration specified in the authority_claim_combiner_config table. The filter uses the Spring authorities granted to the user to get a list of all claims to combine. For each outgoing claim name specified in the configuration table, the filter takes the list of claims and uses the priority to build a final claim string. For example, if you have three rows specifying the name, first name, and last name, the filter would use the priority to build a final claim string in the order of name, first name, and last name. You can set this filter to always take effect by setting the authority to null in the row.

RSA-OIDC Admin API - Supporting Features

OpenAPI Spec

The API described below has a companion openAPI specification. This YAML file is best viewed using a tool such as http://editor.swagger.io/.

JSON-API Spec

The RSA-OIDC Admin API makes use of a framework called Elide, and specifically its implementation of the JSON-API specification. The format of the API calls shown in this guide are representative of this specification. While it can be verbose, it is also provides for many useful features. For further information, see the following links: