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
- The Resource Owner application provides the following data:
The Content Service Identifier (id
)
A URI that references the content - The
CREATE
operation, for a provided "uri", supports two configurations for an action
If action isget
... the URI is tested, if the response is not a200:OK
, an error is generated
If action isreference
... no test is performed - 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
- The Resource Owner application provides the following data:
The Content Service Identifier (id
)
The JSON data - 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 bepost
. (mapped to HTTP POST Method)
Theuri
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 namedLocation
- Store the
uri
(returned from the create operation) and theid
in the resource record
Sample "create" POST with data, default id
is used:
{
"meta": { },
"content": {
"id": "default",
"data": { }
}
}
Read
- Get the content URI from the resource data (
content.uri
) and the Content Service Id (content.id
) - Get the action defined for the
READ
operation (servers[0].operations.read.action
) - If action is
get
Get any headers that are defined for theREAD
operation (servers[0].operations.read.headers
)
Execute HTTP GET method to obtain the content data, assumed JSON
Return the content \ - Else (action is
reference
)
Return the URI
Replace
- Get the content URI from the resource data (
content.uri
) and the Content Service Id (content.id
) - Does the Content Service implement the
REPLACE
operation, if not return error - Get the HTTP method defined for the
REPLACE
operation (servers[0].operations.update.method
) - Get any headers that are defined for the
REPLACE
operation (servers[0].operations.update.headers
) - Use the provided JSON data to replace the existing content
- Execute HTTP method to update the content data
Delete
- Get the content URI from the resource data (
content.uri
) and the Content Service Id (content.id
) - Does the Content Service implement the
DELETE
operation, if not return error - Get the HTTP method defined for the
DELETE
operation (servers[0].operations.delete.method
) - Get any headers that are defined for the
DELETE
operation (servers[0].operations.delete.headers
) - 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 savedREAD
Obtains the resource's related content by using the "method" and the URL
If you want thecontent
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 URLDELETE
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"
}
}
}
]
}