Project: Configurable Content Service - ForgeRock/frdp-uma-resource-server GitHub Wiki

Why

A Content Service (CS) contains "content" that is associated to a resource. It is assumed that the "content" is JSON data. The "content" is used during the UMA use cases. A Content Service may be an existing system or may be a new service. The Resource Server needs a flexible way to configure access to different Content Services that expose a REST interface.

How

An UMA resource may be associated with content. If there is content, the Resource Server can be configured to either store the content (JSON) in a default Content Service or provide a reference (URI) to an external Content Service.

The system needs to support multiple Content Service configurations. Each content service may be configured to support the following operations:

  • CREATE
  • READ
  • REPLACE
  • DELETE

The system needs to support the two types of Content Services:

  • Content that can be managed (created / replaced / deleted) by the Resource Server When creating / registering a new UMA resource, the Resource Server may be configured to managed the content's life-cycle (via a RO application) For a CREATE operation, the full URI, of the newly created content, is stored in the resource's meta data (content.uri)
  • Content is only "referenced' by the Resource Server When creating / registering a new UMA resource, the Resource Server is given a URI, this should be verified For a CREATE operation, the URI is stored in the resource's meta data (content.uri)

What

Resources:

All resources, in the Resource Server, have meta-data. When a resource is associated to content (JSON) a content object is added to the meta-data.

The content object supports the following elements:

Element Type Description Required
id Attribute Content Service identifier true
uri Attribute Uniform Resource Identifier true

Examples

The embedded (default) content service:

{
    "meta": { },
    "content" : {
        "id": "default",
        "uri": "https://content.example.com:443/content-server/data/3580def2-c1f5-4043-b955-46e0ced14a47"
    },
    "register": "..."
}

An external (FHIR) server:

{
    "meta": { },
    "content" : {
        "id": "fhir",
        "uri": "https://fhir.healthcare.com:443/fhir-request/Claim?patient=4702"
    },
    "register": "..."
}

Content life-cycle:

When content is associated with a resource the following operations apply:

Create, option 1: URL is provided

  1. The Resource Owner application provides the following data:
    The Content Service Identifier (id)
    A URI that references the content
  2. The CREATE operation, for a provided "uri", supports two configurations for an action
    If action is get ... the URI is tested, if the response is not a 200:OK, an error is generated
    If action is reference ... no test is performed
  3. Store the URI and the id in the resource record

Sample "create" POST with URI:

{
    "meta": { },
    "content": {
        "id": "fhir",
        "uri": "https://content.example.com/data/mydata"
    }
}

Create, option 2: JSON data is provided

  1. The Resource Owner application provides the following data:
    The Content Service Identifier (id)
    The JSON data
  2. The configured Content Service CREATE operation is used to store the JSON data, if not successful an error is returned
    It is assumed that the action will be post. (mapped to HTTP POST Method)
    The uri attribute (servers[0].operations.create.uri) will be used for the create operation
    Get any headers that are defined (servers[0].operations.create.headers)
    The operation, for storing the JSON data, MUST return the URI in the HTTP Response Header named Location
  3. Store the uri (returned from the create operation) and the id in the resource record

Sample "create" POST with data, default id is used:

{
    "meta": { },
    "content": {
        "id": "default",
        "data": { }
    }
}

Read

  1. Get the content URI from the resource data (content.uri) and the Content Service Id (content.id)
  2. Get the action defined for the READ operation (servers[0].operations.read.action)
  3. If action is get
    Get any headers that are defined for the READ operation (servers[0].operations.read.headers)
    Execute HTTP GET method to obtain the content data, assumed JSON
    Return the content \
  4. Else (action is reference)
    Return the URI

Replace

  1. Get the content URI from the resource data (content.uri) and the Content Service Id (content.id)
  2. Does the Content Service implement the REPLACE operation, if not return error
  3. Get the HTTP method defined for the REPLACE operation (servers[0].operations.update.method)
  4. Get any headers that are defined for the REPLACE operation (servers[0].operations.update.headers)
  5. Use the provided JSON data to replace the existing content
  6. Execute HTTP method to update the content data

Delete

  1. Get the content URI from the resource data (content.uri) and the Content Service Id (content.id)
  2. Does the Content Service implement the DELETE operation, if not return error
  3. Get the HTTP method defined for the DELETE operation (servers[0].operations.delete.method)
  4. Get any headers that are defined for the DELETE operation (servers[0].operations.delete.headers)
  5. Execute HTTP method to delete the content data

Configuration:

A JSON file content-service.json will contain the configuration of all Content Services.

Elements Type Description Required
services Array A collection of JSON objects that represent services true
services[0].id Object Identifier for the content service true
services[0].label Attribute Short name for the service, used by an end-user interface false
services[0].description Attribute Details about the service, used by an end-user interface false
services[0].comment Attribute Any comment related to the service false
services[0].enabled Attribute Is the service available for use true
services[0].content Attribute Dot delimited string of the JSON object that contains the content false
services[0].operations Object Contains available processing operations (see below) true
services[0].operations.{id} Object Identifier for the operation true
services[0].operations.{id}.action Attribute What should be done with the URL true
services[0].operations.{id}.uri Attribute HTTP URL, primarily used for create, POST true
services[0].operations.{id}.headers Object Contains HTTP headers that will be added to the request false
services[0].operations.{id}.headers.name Attribute Header name, the value is a String false

Operations

These define what capabilities the Resource Server will allow for a given Content Service

  • CREATE
    Creates / stores new content related to a given resource.
    If the method is "post", the returned URL is saved
    If the method is "get", the URL is derived and then tested, if success (200: OK) then the URL is saved
  • READ
    Obtains the resource's related content by using the "method" and the URL
    If you want the content to return the reference information instead of the actual related JSON data ... add the query parameter ?content=reference
  • REPLACE
    Replaces the resource's related content by using the "method" and the URL
  • DELETE
    Removes the resource's related content by using the "method" and the URL

Actions

Name Description Notes
post HTTP POST Method Requires setting the uri attribute. Will use defined headers
get HTTP GET Method Will use defined headers
put HTTP PUT Method Will use defined headers
delete HTTP DELETE Method Will use defined headers
reference manage URI value only The URI will not be used to access any external service

Supported Operations and Actions

The following table covers the allowed combination of Operations and Actions

Operations Actions Allowed Description
CREATE post JSON content (data) is provided. Requires configured uri. Saves data @ uri. It is assumed a location uri will be returned for the new data. The location uri is stored in the Resource entry.
get Only a URI is provided to existing content. The URI tested with a HTTP GET method. If the content can not be accesses, an error is generated.
put Not supported ... A create must return a Location header with the new URI
delete Not supported
reference Only a URI is provided to existing content. The URI is stored in the Resource entry, not check is performed.
READ post Not supported
get Use the Resource content.uri and obtain the JSON content. return the content.
put Not supported
delete Not supported
reference Return the content.uri only. DO NOT try to obtain related data.
REPLACE post Not supported
get Not supported
put JSON content (data) and the content.uri are provided. A HTTP PUT replaces the data in the content service.
delete Not supported
reference The content.uri value is replaces.
DELETE post Not supported
get Not supported
put Not supported
delete The content.uri are provided. A 'HTTP DELETE` removed the data in the content service.
reference The content.uri value is deleted.

Example

content-service.json

There are three configured Content Services, only the default one is enabled by default:

Id Description Operations
default Default reference Content Service which uses MongoDB to store resource content CREATE: Uses HTTP POST to the URI defined in the uri attribute Will include the declared headers
READ: Uses HTTP GET with the stored resource content.uri attribute. Will include the declared headers
REPLACE: Uses HTTP PUT with the stored resource content.uri attribute. Will include the declared headers
DELETE: Uses HTTP DELETE with the stored resource content.uri attribute
fhir No JSON content is ever provided ... a URI is provided when the resource is created CREATE: Uses HTTP GET with the content.uri attribute, test the existence of a valid URI. Will include the declared headers. Generates an error if GET fails (not 200:OK)
READ: Uses HTTP GET with the stored resource content.uri attribute, obtains the content from the external service. Will include the declared headers
REPLACE: Will replace the value of the content.uri attribute
DELETE: Will delete the value of the content.uri attribute
ref only No JSON content is ever provided ... a URI is provided when the resource is created CREATE: Will set the value of the content.uri attribute.
READ: Will read the value of the content.uri attribute, and return the URI
REPLACE: Will replace the value of the content.uri attribute
DELETE: Will delete the value of the content.uri attribute
{
    "comment": "Content Services",
    "services": [
        {
            "id": "default",
            "label": "MongoDB Content Service",
            "description": "The reference implementation sample Content Service, using MongoDB",
            "comment": "The default Content Service, REST interface to MongoDB",
            "enabled": true,
            "content": "data",
            "operations": {
                "create": {
                    "comment": "Use 'uri' attribute and input 'data' to CREATE external content",
                    "action": "post",
                    "uri": "https://uma.example.com:443/content-server/rest/content-server/content"
                },
                "read": {
                    "comment": "Use input 'uri' to READ external content",
                    "action": "get"
                },
                "replace": {
                    "comment": "Use input 'data' to REPLACE at input 'uri'",
                    "action": "put"
                },
                "delete": {
                    "comment": "Use input 'uri' to DELETE external content",
                    "action": "delete"
                }
            }
        },
        {
            "id": "fhir",
            "label": "FHIR",
            "description": "This is the sample FHIR service",
            "comment": "Example FHIR URL https://fhir.example.com:443/fhir-request/Claim?patient=1234",
            "enabled": true,
            "operations": {
                "create": {
                    "comment": "Test the provided URL, returns error if not 200:OK",
                    "action": "get"
                },
                "read": {
                    "comment": "Use input 'uri' to READ external content",
                    "action": "get"
                },
                "replace": {
                    "comment": "Use input 'uri' to REPLACE the existing 'uri'",
                    "action": "reference"
                },
                "delete": {
                    "comment": "Use input 'uri' to DELETE the existing 'uri'",
                    "action": "reference"
                }
            }
        },
        {
            "id": "refonly",
            "comment": "The URL is only for reference, it is NOT use to manage/access external content",
            "enabled": true,
            "operations": {
                "create": {
                    "comment": "Use input 'uri' to CREATE a new 'uri'",
                    "action": "reference"
                },
                "read": {
                    "comment": "Use input 'uri' to READ the existing 'uri'",
                    "action": "reference"
                },
                "replace": {
                    "comment": "Use input 'uri' to REPLACE the existing 'uri'",
                    "action": "reference"
                },
                "delete": {
                    "comment": "Use input 'uri' to DELETE the existing 'uri'",
                    "action": "reference"
                }
            }
        }
    ]
}