Skip to content

catalyzeio/omh-dsu-ri

 
 

Repository files navigation

Open mHealth DSU RI

This repository contains a Java reference implementation of an Open mHealth DSU. This DSU supports the 1.0.M1 data point API.

This code is in its early stages and requires further work and testing. Please do not use it in production without proper testing.

tl;dr

  • this repository contains a secure endpoint that offers an API for storing and retrieving data points
  • data points conform to the Open mHealth data point schema
  • the code consists of an OAuth 2.0 authorization server and resource server
  • the authorization server manages access tokens
  • the resource server implements the data point API documented here
  • the servers are written in Java using the Spring Framework, Spring Security OAuth 2.0 and Spring Boot
  • the authorization server needs PostgreSQL to store client credentials and access tokens, and MongoDB to store user accounts
  • the resource server needs PostgreSQL to read access tokens and MongoDB to store data points
  • you can pull Docker containers for both servers from our Docker Hub page
  • you can use a Postman collection to easily issue API requests

Overview

A data point is a JSON document that represents a piece of data and conforms to the data-point schema. The header of a data point conforms to the header schema, and the body can conform to any schema you like. The header is designed to contain operational metadata, such as identifiers and provenance, whereas the body contains the data being acquired or computed.

The data point API is a simple RESTful API that supports the creation, retrieval, and deletion of data points. The API authorizes access using OAuth 2.0.

This implementation uses two components that reflect the OAuth 2.0 specification. A resource server manages data point resources and implements the data point API. The resource server authorizes requests using OAuth 2.0 access tokens. An authorization server manages the granting of access tokens.

Installation

There are two ways to build and run the authorization and resource servers.

  1. You can run a Docker container for each server that executes a pre-built binary.
  • This is the fastest way to get up and running and isolates the install from your system.
  1. You can build all the code from source and run it on your host system.
  • This is a quick way to get up and running if you don't need isolation and your system already has MongoDB, PostgreSQL and is prepped to build Java code.

Option 1. Running a pre-built binary in Docker

If you don't have Docker 1.2+ installed, download Docker and follow the installation instructions for your platform.

The rest of the dependencies are handled via Docker. In a terminal,

  1. If you don't already have a MongoDB image, download one by running
    • docker pull mongo:latest
    • This will download up to 400 MB of images.
  2. If a MongoDB container isn't running or if you want a new container, start one by running
    • docker run --name omh-mongo -d mongo:latest
  3. If you don't already have a PostgreSQL image, download one by running
    • docker pull postgres:latest
    • This will download up to 200 MB of images.
  4. If a PostgreSQL container isn't running or if you want a new container, start one by running
    • docker run --name omh-postgres -d postgres:latest
  5. To source the Spring Security OAuth schema in the PostgreSQL container
    • If you're on Docker 1.3
      1. Run docker exec -it omh-postgres bash to start a shell on the omh-postgres container
      2. Run psql -U postgres in the resulting shell to start psql
      3. Copy and paste the contents of the setup script to create the schema.
      4. \q to exit psql
      5. exit to exit the shell
    • If you're on an older version of Docker
      1. Start psql in its own container using docker run -it --link omh-postgres:postgres --rm postgres sh -c 'exec psql -h "$POSTGRES_PORT_5432_TCP_ADDR" -p "$POSTGRES_PORT_5432_TCP_PORT" -U postgres'
      2. Copy and paste the contents of the setup script to create the schema.
      3. \q to exit psql
  6. Download the authorization server image by running
    • docker pull openmhealth/omh-dsu-authorization-server:latest
    • This will download up to 300 MB of Docker images, 25 MB of which is the application.
  7. Download the resource server image by running
    • docker pull openmhealth/omh-dsu-resource-server:latest
    • This will download up to 300 MB of Docker images, 25 MB of which is the application.
  8. Start the authorization server by running
    • docker run --name omh-dsu-authorization-server --link omh-postgres:omh-postgres --link omh-mongo:omh-mongo -d -p 8082:8082 'openmhealth/omh-dsu-authorization-server:latest'
  9. Start the resource server by running
    • docker run --name omh-dsu-resource-server --link omh-postgres:omh-postgres --link omh-mongo:omh-mongo -d -p 8083:8083 'openmhealth/omh-dsu-resource-server:latest'

The servers should now be running on your Docker host. Run docker ps to verify.

Option 2. Building from source and running on your host system

We will add documentation on running the servers on your host system shortly.

Configuring the authorization server

The authorization and resource servers are configured in YAML using Spring Boot conventions. You can see the authorization server's configuration here and the resource server's configuration here.

If you want to override the default configuration and you're running the servers on your host system, you can either

  • Add an environment variable with -eto the Docker run command corresponding to the property you want to set.
    • e.g. docker run --name omh-dsu-authorization-server -e logging.level.org.springframework=DEBUG ...
    • e.g. docker run --name omh-dsu-resource-server -e spring.data.mongodb.database=bar ...
  • Create an application.yml file in the /opt/omh-dsu-ri/*-server directory with the overriding YAML properties.
    • This is particularly useful because you can change the configuration without running new containers.
    • You may need to install an editor, e.g. using apt-get install vim.

It is possible to use multiple resource servers with the same authorization server.

Adding clients

The authorization server manages the granting of access tokens to clients according to the OAuth 2.0 specification. Since it is good practice to not roll your own security infrastructure, we leverage Spring Security OAuth 2.0 in this implementation. You can find the Spring Security OAuth 2.0 developer guide here.

It is beyond the scope of this document to explain the workings of OAuth 2.0, Spring Security and Spring Security OAuth. The configuration information in this document is meant to help you get started, but is in no way a replacement for reading the documentation of the respective standards and projects.

The authorization server uses Spring Security OAuth 2.0's JdbcClientDetailsService to store OAuth 2.0 client credentials. This necessitates access to a PostgreSQL database, although we intend to release a MongoDB service down the road to make this dependency optional.

The client details in the oauth_client_details table controls the identity and authentication of clients, the grant types they can use to show they have been granted authorization, and the resources they can access and actions they can take once they have an access token. Specifically, the client details table contains

  • the identity of the client (column client_id)
  • the resource identifiers (column resource_ids) the client can access , dataPoints in our case
  • the client secret, if any (column client_secret)
  • the scope (column scope) to which the client is limited, in our case some comma-separated combination of
    • read_data_points if the client is allowed to read data points
    • write_data_points if the client is allowed to write data points
    • delete_data_points if the client is allowed to delete data points
  • the authorization grant types (column authorized_grant_types) the client is limited to, some comma-separated combination of
  • the Spring Security authorities (column authorities) the token bearer has, in our case ROLE_CLIENT

To create a client,

  1. Connect to the omh PostgreSQL database using the same mechanism you used during the installation.
  2. Add a row to the oauth_client_details table. You can find a script with a sample INSERT statement here.

The remainder of this documentation is actively being worked on.

Adding end-users

The data points accessible over the data point API belong to a user. In OAuth 2.0, this user is called the resource owner or end-user. A client requests authorization from the authorization server to access the data points of one or more users.

The authorization server includes a simple RESTful endpoint to create users. To create a user, either execute the following command

curl -H "Content-Type:application/json" --data '{"username": "testUser", "password": "testUserPassword"}' http://${DOCKER_IP}:8082/users

or use the create an end-user/success or conflict request in the Postman collection discussed below.

The user creation endpoint is primitive by design; it is only meant as a way to bootstrap a couple users when first starting out. In general, the creation of users is typically the concern of a user management component, not the authorization server. And it's quite common for integrators to already have a user management system complete with its own user account database before introducing the authorization server.

To integrate a user management system with the authorization server, you would

  1. Disable the org.openmhealth.dsu.controller.EndUserController, usually by commenting out the @Controller annotation.
  2. Provide your own implementation of either the org.openmhealth.dsu.service.EndUserService or the org.openmhealth.dsu.repository.EndUserRepository, populating org.openmhealth.dsu.domain.EndUser instances with data read from your own data stores or APIs.

Issuing requests with Postman

Your code interacts with the authorization and resource servers by sending them HTTP requests. To make learning about those requests easier, we've created a Postman collection that contains a predefined set of requests for different actions and outcomes. Postman is a Chrome packaged application whose UI lets you craft and send HTTP requests.

These instructions are written for Postman 1.0.1. If you're using a newer version and they don't work, let us know and we'll fix them.

To set up the collection,

  1. Download Postman.
  2. Start it.
  3. Click the Import button, choose the Download from link tab and paste https://www.getpostman.com/collections/18e6065476d59772c748
  4. The collection should now be available. The folder names describe the requests, and the request names describe the expected outcome.
  5. Create an environment. Environments provide values for the {{...}} placeholders in the collection. Add the following environment keys and values, possibly changing the values if you've customised the installation.
    • authorizationServer.host - IP address of your Docker host (on Mac OS X and Windows, boot2docker ip will print this IP to the console)
    • authorizationServer.port - 8082
    • resourceServer.host - IP address of your Docker host
    • resourceServer.port - 8083
    • accessToken - issue the get access token using RO password grant/success request and copy the access_token value from the response here, without quotes
    • apiVersion - 1.0.M1

To send a request, pick the request and click its Send button. The different requests should be self-explanatory, and correspond to the verbs and resources in the data point API.

The folders also have descriptions, which you can currently only see by clicking the corresponding Edit folder button (but Postman are working on that). You can see the request descriptions by selecting the request.

Using the authorization server

We may add documentation here if we find that the Postman collection isn't sufficient.

Using the resource server

The data point API is documented in a RAML file to avoid ambiguity.

A data point looks something like this

{
    "header": {
        "id": "123e4567-e89b-12d3-a456-426655440000",
        "creation_date_time": "2013-02-05T07:25:00Z",
        "schema_id": {
            "namespace": "omh",
            "name": "physical-activity",
            "version": "1.0"
        },
        "acquisition_provenance": {
            "source_name": "RunKeeper",
            "modality": "sensed"
        }
    },
    "body": {
        "activity_name": "walking",
        "distance": {
            "value": 1.5,
            "unit": "mi"
        },
        "reported_activity_intensity": "moderate",
        "effective_time_frame": {
            "time_interval": {
                "date": "2013-02-05",
                "part_of_day": "morning"
            }
        }
    }
}

We may add documentation here if we find that the Postman collection isn't sufficient.

Roadmap

The following features are scheduled for future milestones

  • improve test coverage
  • support refresh tokens
  • support the client credentials grant type
  • make it easier to customise the authorization code and implicit grant forms
  • support SSL out of the box
  • filter data points based on their bodies

If you have other feature requests, create an issue for each and we'll figure out how to prioritise them. Or better yet, send us a pull request. And if you want to work on any of the above features, just let us know by submitting an issue.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Java 100.0%