Cht-core: Add support for outbound push to RapidPro

Created on 18 Jan 2020  路  13Comments  路  Source: medic/cht-core

Describe the solution you'd like
The ability to integrate workflows initiated in a CHT app with RapidPro. It seems as though the best way to send data from the CHT app is by using the outbound push feature to RapidPro's API. Currently outbound push only support basic auth and a custom auth protocol for a bespoke EMR. To make outbound push work with RapidPro we'd need to support it's token authentication.

Describe alternatives you've considered
It is possible to push data to RapidPro using outbound push by redirecting via webhooks that have authentication compatible with outbound push (eg basic auth with Zapier). This is an unnecessary and potentially costly redirect.

Additional context
The authentication needed is described in the Authentication section of the RapidPro API:

You must authenticate all calls by including an Authorization header with your API token. If you are logged in, your token will be visible at the top of this page. The Authorization header should look like:

Authorization: Token YOUR_API_TOKEN

Workflows in RapidPro can send data back to a CHT via the API, and connect with CouchDB directly for exploratory purposes. Through this exploration we'll be able to better understand the API requirements needed, which can be opened in another issue.

API COVID-19 2 - Medium Feature

All 13 comments

I'm not that well travelled when it comes to authorization schemes, so I'm not sure if this is a standard scheme (and should be named as such).

The header and general format is standard. However, "Token" doesn't appear as a known type. It looks like maybe they should be using "Bearer", but that's not our call.

So we _can_ make it somewhat generic by adding an auth_header type, where in the auth section you just provide the type and credentials (as noted in the standard doc).

This should serve us for pre-determined auth that follows this standard header.

I am not certain why Token is used instead of Bearer here, but they are formatted similarly. I am happy to make it a bit more generic to be more widely reusable.

The hardest part seems to be related to naming, of course:

  • The config has an auth object which is authentication, and the header used here is Authorization, which makes using auth as a prefix ambiguous.
  • Within the auth object we have a type to specify the authentication type, and the Authorization header itself also has a type - meaning that there are two "auth" types, which could lead to confusion.

Here are some possible ways to avoid confusion:

Flat auth object

    "auth": {
        "type": "authorization_header",    // or just "header"
        "header_type": "Token",
        "credentials_key": "textit.in"
    },

Nested header object

    "auth": {
        "type": "authorization_header",    // or just "header"
        "header":{
            "type": "Token",
            "credentials_key": "textit.in"
        } 
    },

Header type and credentials together in CouchDB config

    "auth": {
        "type": "authorization_header",    // or just "header"
        "header_key": "textit.in"  // include type with credentials eg "textit.in": "Token 1234567890abcdef"
        } 
    },

Which scheme makes most sense?
And should the type be header, or authorization_header?

I think I'd structure it something like...

"auth": {
  "type": "header",
  "name": "Authorization",
  "value_key": "textit.in"
}

Ok, just confirming that means that the value in CouchDB includes the authorization header type and credentials eg Bearer 1234567890abcdef? That seems like a good approach since it could eventually be written to programmatically for some auth schemes.

Here is a snippet of an app settings file with a working config using config/default. It starts a RapidPro flow to have a patient verify their phone number when their profile is created or edited. Although this is not a robust example as is, since it fires during edits even if the phone number hasn't changed and there isn't enough guarding for the fields used, it can be used as an example for testing.

    "outbound": {
        "textit-patient": {
            "relevant_to": "doc.type === 'person' && doc.phone && doc.parent.parent.parent",
            "destination": {
                "base_url": "https://textit.in",
                "auth": {
                    "type": "header",
                    "name": "Authorization",
                    "value_key": "textit.in"
                },
                "path": "/api/v2/flow_starts.json"
            },
            "mapping": {
                "flow": {
                    "expr": "'94d7e4e1-775b-4162-b2bd-cd299e7ba075'"
                },
                "urns": {
                    "expr": "[ 'tel:' + doc.phone ]",
                    "optional": false
                },
                "extra.patient._id": "doc._id",
                "extra.patient._rev": "doc._rev",
                "extra.patient.name": "doc.name",
                "extra.patient.short_name": "doc.short_name",
                "extra.patient.date_of_birth": "doc.date_of_birth",
                "extra.patient.medic_id": "doc.patient_id",
                "extra.patient.phone": "doc.phone",
                "extra.chw._id": "doc.parent.parent.contact._id",
                "extra.chw.name": "doc.parent.parent.contact.name"
            }
        }
    }

Ready for AT in: 6207-rapidpro-outbound-push

@abbyad to write AT notes

To acceptance test this issue you should be able to trigger a flow in a RapidPro instance. The simplest way to test is by setting up an account and flow using https://textit.in.

@medic/quality-assurance, if you need help in using RapidPro or TextIt please reach out as I wouldn't want the RapidPro side to be the blocker in ATing this issue.

AT update: I didn't notice but @abbyad actually merged the PR at the time, so AT for this now should be done against master.

Thanks for mentioning that, and sorry about that premature merge!

@abbyad Can you please elaborate on how this integrates with RapidPro? Do we have an account with RapidPro to use for testing ?

I sent you an invite for a test account, and you can try to start this RapidPro flow. It will send you an email with some debug data.

LGTM.
Tested by adding the snippet provided above to app_settings.json , with one single modification of the flow number - expr. And adding textit token to medic-credentials in couchDb....
image

The branch has already been merged to master, so I will go ahead and close the ticket!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

abbyad picture abbyad  路  3Comments

alxndrsn picture alxndrsn  路  4Comments

n-orlowski picture n-orlowski  路  5Comments

ngaruko picture ngaruko  路  3Comments

estellecomment picture estellecomment  路  5Comments