This is an overview of the GPII Preferences Service: the pieces that make it up and how they are connected.
The Parts
- Preferences Server, the central piece that allows access to users' preferences
- Preference Framework, handles preference ontologies
- OAuth2, authorization service to allow client applications access to users' preferences
- Database, the storage of the preferences data
Questions to answer
- Why does FLOE needs a preferences server? What purposes?
- Have a common way for multiple projects to store and retrieve preferences
- Share the same preferences among different projects. A kind of "portable preferences".
- What is the actual structure of the preferences themselves?
- What database to use?
- GPII used CouchDB but was moving away
- OAuth2 machinery is integrated with the Flow Manager
- OAuth2 also has dependencies on the database
- of course it does, since the credential and other authorization information is in the database
- but, the database is CouchDB in GPII, so there is a dependency on couchdb access by the authorization service
- encapsulated in gpii-db-opertions.
- Serverless http – suggested by Antranig in #fluid-work
Preferences Server API
This outlines the preferences server endpoints that define what the server provides in terms of accessing user preferences. The API is RESTful, and is implemented internally using the fluid project's kettle. Clients can make these http requests using tools such as curl
, a web-based form, or some other http request library.
Note that authorization, or OAuth2 is not part of this API. Getting ahead of this presentation: OAuth2 is a separate service and, in GPII, is built into the cloud based flow manager (CBFM). That is, one can set up a preferences services and make the requests documented below without any authorization. However, in the case of a deployed production version of the GPII, the preferences server is not available to the outside world, and is accessed via CBFM endpoints that in turn makes these Preferences Server requests. The CBFM defers to the OAuth2 service to verify that the Preferences Server requests are allowed.
Another aspect of the way these requests work is the implied structure of the preferences. Combined with the ontology handler in the Preferences Framework, the structure is:
- a container of containers individuated by and ontology, e.g. "ISO-24751", "flat", etc.
- there seems to be only two ontologies ever mentioned?
- each ontology has a "preferences" container, that in turn has a "contexts" container. The context specifies sets of named preferences. For example, in GPII there is always a set named "gpii-default".
- each named prefsSet (or context) has a container named "preferences" that lists the actual preferences.
- the structure of the information within this inner "preferences" container is determined by the ontology. For example, some ontologies are hierarchical while others are flat.
Even though the preferences are individuated by ontology, the Preferences Server requests always involve one ontology. For example, if a user's preferences are requested, the preferences for only one ontology is returned. If there is a request to modify preferences, only one ontology is supplied, although with a "merge", it looks like mulitple ontologies are updated in the backend?
Preferences Server Endpoints
OAuth2
An OAuth2 authorization service is used to grant access to the preferences server. In GPII, as noted above, the authorization requests are routed through the CBFM. More specifically, the authorization service is a sub-component of the the CBFM. Documentation of how OAuth2 is used in GPII is available on the gpii wiki: https://wiki.gpii.net/w/GPII_OAuth_2_Guide, and is summarized below.
OAuth2 Workflow
The workflow is two steps:
- The OAuth client authenticates with the authorization server, and receives an access token if the client is verified.
- The client then uses this access token when making subsequent requests
A more detailed description of this workflow, as used in GPII:
- POST a request to the CBFM: https://flowmanager:9082/access_token
- The body of the POST request contains:
- grant_type: "password", - the type of access authentication to use.
- client_id: "pilot_computer", - OAuth2 client identifier, or who is asking for permission to access the preferences
- client_secret: "pilot-computer-secret" - a secret known only to the client and the OAuth2 authentication service
- username: "carla" - GPII Key associated with the user whose preferences are sought, typically a UUID
- password: "dummy" - can be any string.
- The return value, if successful is:
- "access_token": "1ab47092a3fc6cc9f30729aa4581796c" - random 16 bytes
- "expiresIn": 3600 - number of seconds that the access token is valid (one hour, in this case).
- "token_type": "Bearer", used in the "Authorization" header of subsequent requests regarding the user specified in the POST request above.
The access token received at step two, which is used in subsequent requests, is reflected in the database as an "App Installation Client" data structure. Among other fields such as id, revision, expiry time, revoked, and so on, this database "access token" record has a user field ("carla" in the above example) and the access_token value returned at step two above. It is used by the authorization machinery to permit access to the user's preferences. An outline of the App Installation Client, or access-token-in-the-database is:
- type: "gpiiAppInstallationAuthorization"
- gpiiKey: the user or key that was used in the authorization request posted at step 1 above, called "username" there.
- accessToken: the same random 16 bytes returned at step 2 above, called "access_token" there.
- clientId: The client id that this authorization is assigned to. (what is this?)
- clientCredentialId: The client credential id that is used to request this authorization. (what is this?)
- schemaVersion, revoked, time stamps, etc.
One "can" use CBFM endpoints to acquire preferences, but it's not as simple as with the Preferences Server. The Preferences Server deals just with a user's preferences, The CBFM requests of a user's preferences must include information about solutions (e.g., ATs) and the result is a set of life cycle instructions. Using the CBFM invokes a lot of GPII machinery including the MatchMaker and the SolutionsRegistry.
Database
The section is about what is stored in the data base, or the structure of the data. The actual database used in GPII is CouchDB but that's likely an implementation detail. Regardless of what database is, the structures or information stored in it are conceptually the same.
At a very high level, the information that is stored in the database are Keys, Preferences Safes, Client Credentials, App Installation Clients, and App Installation Authorizations. The full documentation regarding these is on the GPII wiki: https://wiki.gpii.net/w/Keys,_KeyTokens,_and_Preferences
Note that the "Keys, Key Tokens and Preferences" document lists a future version of these structures. Which version do we want to use. The following is a description of the past (not future).
With respect to preferences, the two most important of these are Preferences Safes and their Keys. The rest of the structures have to do with secure access.
Preferences Safes
A safe in which to put preferences.
- aka prefsSafes
- where the preferences are saved
- A container whose top level has a number of atomic fields, and a "preferences" container
- atoms: id, type (always "prefsSafe", schemaVersion, prefsSafeType ("snapset" vs. "user"), username, password, email, creation and modification dates
- preferences is a container of ontologies
- each ontology is named, e.g., "flat", "ISO24751"
- the value is a container of sets of preferences:
- the set has a name, e.g., "Carla".
- the prefsSets themselves are within a container named "contexts"
- each prefsSet is named, e.g. "gpii-default"
- a prefSet is a container with a name, and a "preferences" container.
- it is this innermost "preferences" container that holds the preferences
- Thus, the path to the actual preferences:
- Example of structure of actual preferences:
"http://registry.gpii.net/applications/org.gnome.desktop.a11y.magnifier": { // application, here the GNOME shell magnifier
"show-cross-hairs": true,
"mag-factor": 2,
"mouse-tracking": "push",
"screen-position": "right-half",
"scroll-at-edges": true
}
- These are literally the same as the actual GNOME magnifier's "gsettings".
- Are all preferences this one-to-one?
- Are any preferences given in a generic, non-application specific way?
- Role of common terms?
Keys
The Key records within the database are a way to connect a user to a prefsSafe, and a set of preferences within that safe.
- id: user identifier, e.g., "carla"
- usually a UUID,
- also used in the internal access token records (App Installation Clients) to control access
- type: always "gpii-key". (Always???
) - prefsSafeId: identifier of the associated preferences safe
- matches a prefsSafe record's "id" field
- prefsSetId: identifier of a prefsSet (context) within a prefsSafe
- revoked: boolean declaring if this key has been revoked and can no longer be used to access preferences safes
Documentation Links
- PreferencesServer:
- Preferences Safes and Keys:
- OAuth2
- Preferences Framework: