This document describes the functional requirements of a companion application for eduvpn for Android. This means it will describe what the application must be capable of and not necessarily how, although there will be some implementation suggestions mentioned throughout and some acceptance criteria as well.
Configuring eduvpn on your Android device is quite involved, i.e. it requires a relatively big number of steps and is limited in after-configuration updates and changes.
Assuming you want to use eduvpn on Android you need to go through these steps:
https://eduvpn.surfcloud.nl/
;We'd like to make this simpler and more secure for the user, i.e. reduce the number of steps and no require to download a configuration file containing private keys in a "public" storage on the Android device.
So, we'd like to optimize the flow as follows:
Between step 4 and 5 the configuration is automatically downloaded and installed.
With this optimized flow we can accomplish further benefits without requiring user involvement:
Everyone can deploy their own instance of eduvpn. The application MUST be able to connect to a predefined list of instances, but also to instances not yet added to this list.
The list of instances available to connect to MUST be updatable by modifying
a JSON file on a to be determined location, e.g.
https://www.eduvpn.nl/instances.json
. This file will contain the name of
the instance, a link to a logo and the base URL.
PRELIMINARY FORMAT
{
"instances": [
{
"display_name": "Fran\u00e7ois (vpN.tuxed.net)",
"base_uri": "https://vpn.tuxed.net/",
"logo_uri": "https://eduvpn.surfcloud.nl/img/placeholder.png"
},
{
"display_name": "SURFnet (labrat.eduvpn.nl)",
"base_uri": "https://labrat.eduvpn.nl/",
"logo_uri": "https://eduvpn.surfcloud.nl/img/placeholder.png"
},
{
"display_name": "Fran\u00e7ois (vpX.tuxed.net)",
"base_uri": "https://vpx.tuxed.net/",
"logo_uri": "https://eduvpn.surfcloud.nl/img/placeholder.png"
}
],
"version": 1
}
On application startup (and periodically when running constantly, e.g. once a day) this document is retrieved and the content used to overwrite the built-in or previously update list of instances. If the retrieval fails, the last known good update (or initially built-in list) is used.
DISCUSS: maybe we can encode the logos as base64 in the JSON file instead
of providing URLs. That would be more efficient, but also increase the file
size. What is the best approach here? HTTP caching? Caching in the app? Only
update the logo when the JSON file is updated? How to determine if an update
is needed? ETag? Last-Modified HTTP headers? Do we need multi-language support?
Do we need to maybe host the logo at the instance itself and publish it in the
info.json
?
NOTE the version
field indicates the list format, it does not talk
about the content!
The eduvpn services exposes an API that can be used by the application to obtain a configuration. This API is protected using OAuth 2.0 (RFC 6749). This makes it possible to integrate the application with an instance without requiring a specific authentication mechanism. This way it becomes possible to support e.g. SAML or OpenID Connect without modifying the application.
OAuth 2.0 will here be in essence used as a way to provision an application/device specific password called a Bearer token (RFC 6750).
See API.
Each instance can configure their own authentication, it could be a simple username/password authentication or be integrated in a SAML federation. This is of no consequence to the app. The app will only use OAuth 2.0 and Bearer tokens to interact with the instance.
The app will open an (embedded) browser and point it to the
authorization_endpoint
, at that point the instance will take care of the
user authentication and provide an authorization_code
that will be provided
back to the app using the redirect_uri
that will need to be caught by the
app using an intent registration.
The obtained authorization_code
can be exchanged for an access_token
at the
token_endpoint
. The obtained access_token
will be a Bearer token that can
be used at the api_endpoint
to interact with the API.
NOTE: this describes the OAuth 2.0 "authorization code" flow, it may very well be that the "implicit grant" flow will also be supported which is somewhat simpler.
The target platform should be Android >= 4.
Principle: anyone with a computer with just Android Studio on it MUST be able to build the application and its dependencies from source in the easiest way possible and generate an installable application (APK).
The "OpenVPN for Android" application from Arne Schwabe SHOULD be used. This is free software and can be integrated directly in the eduvpn app. This is documented in the source repository of OpenVPN for Android. It may be possible to use the OpenVPN for Android API when OpenVPN for Android is already installed, or its installation could be requested/triggered.
The application MUST be built from source using only free software components and tools.
It must be made available to at least these two App stores:
The requirement for being available through F-Droid means that no Google proprietary libraries may be used, e.g. "Google Cloud Messaging" and that the application can be built from source straight from a public repository. See also the F-Droid Inclusion Policy.
The signing key+certificate and the Google Account used to submit the application MUST be made available as well as to allow for submission of updates independent of the developers of the Android application, e.g. to push updates to the list of organizations embedded in the application.
In case additional dependencies are required, they should be clearly mentioned in the main README, MUST be free software as well, MUST have compatible licensing.
No proprietary tools may be used for building, deploying, signing or publishing the application. Best practices as documented by Google MUST be followed unless there are very good reasons for not doing that.
A proof of concept application is available here. It more or less works, but still has lots of issues, and is far from complete, see also the TODO section there.