Skip to end of metadata
Go to start of metadata

Introduction

Yona registers user and buddy information but does not know about the devices used by them. This is an issue for two upcoming new features:

  • VPN status reporting
    If the user accidentally or explicitly disengages the VPN, then that happens on a specific device. On another device of the same user, the VPN would still be on. This will cause the VPN status to alternate between on and off, depending on the last used device. To prevent that, the VPN status needs to be stored and reported on device level.
  • Push messaging
    To efficiently implement instant notifications for events like buddy requests and goal conflict messages, we need to implement push messaging, likely based on Firebase Cloud Messaging. For that, we will need some sort of device ID to push to, so each device needs to be registered.

It would also enable some new features that we do not foresee yet but could be useful:

  • Device-specific activity reporting
    Users might want to see a device-by-device activity report, so they can see when they use what device and for what type of activity

Important questions to be answered

The following questions are important for the design:

  1. Question: Will users be able to see the devices of their buddies? If the devices are known, VPN status reporting could be something like "User X disengaged the VPN on device Y" and the user would be able to see that user X has one more device. If the devices are not known to the buddies, status reporting would be like this: "User X disengaged VPN on one of their devices", "User X disengaged VPN on their device" or "User X disengaged VPN on all of their devices". For push messaging, the users don't need to know about the devices of their buddies. Device-specific reporting seems to be a feature for the user, not for buddies.
    Answer: Yes, it's desirable that buddies can see the devices of their buddies.
  2. Question: For device-specific activity reporting, we would need a VPN account per device. Do we need this in the first release?
    Answer
  3. Question: Will the user have a "Device management screen" where they can rename and remove devices?
    Answer: Yes. At sign-up, we can default the device name. The user can rename the device in the device management screen. When adding another device, we will likely ask the user for the device name.

Requirements

The below requirements are in no particular order.

  1. One user can have multiple devices.
  2. VPN status must to be maintained per device
  3. App activities must be linked to a device
  4. Network activities must be linked to a device
  5. Messages communicating a buddy's VPN status change should mention the device on which the status changed
  6. A buddy profile must contain a list of the devices of the user
  7. Users can see their own devices:
    1. Name
    2. Date and time of registration
    3. Date and time the Yona app was last opened on that device
    4. Status of the VPN connection on that device
    5. The date at the last network activity from that device was monitored
    All of the above data must be encrypted, with the exception of the last item.
  8. A buddy can see the following device information:
    1. Name
    2. Status of the VPN connection
  9. A user can change the name of a device
  10. A user can remove a device. The consequence of that is that Yona cannot be opened on that device anymore and network activity monitoring will stop for that device.
  11. When signing up for Yona, it should be possible to specify a device name. If nothing is provided, the server should default a name.
  12. When adding a new device, it should be possible to specify a device name. If nothing is provided, the server should default a name.

Design

The device information will be kept in three different classes: to be able to access the device information for an anonymized user (for instance to send a push message about a goal conflict upon a conflict detected by the analysis engine), we need a DeviceAnonymized, which will also hold the lastMonitoredActivityDate. Next, the buddies needs to maintain a subset of the device information of their buddies and the user needs to have all information. This will be handled by a base type DeviceBase, with a subtype BuddyDevice for buddy device information and UserDevice for the user's own devices. All information in these entities will be encrypted. The ID of the DeviceAnonymized will be used when informing the buddy about device changes and it will also be used to derive the device-specific VPN login ID. The ID can be a simple sequence number that starts at 0 for each user.

We will introduce two new messages:

  • DeviceChangeMessage – This message will be sent when the user adds, removes or renames a device. The name and the change (add/remove/rename) will be in the properties of the message.
  • VpnStatusChangeMessage – This message will be sent when the user engages or disengages the VPN on a device.

Class diagram

The below diagram depicts the new classes in the context of a subset the existing classes:

When a user signs up for Yona, we wil register their first device. If left the name blank, the server will generate a name based on a sequence number. The buddy request and response message now come with a set of devices, basically a collection of DeviceBase. Whether that class can be reused in the messages is to be seen. The normal device information is encrypted with the device key (i.e. the one bound to the session) while the ones linked to the messages need to be encrypted with the per-message key.

Till now, the VPN login ID was equal to the user anonymized ID. With the introduction of device-specific VPN connections, the VPN login ID will be based on the device ID and the user anonymized ID. This allows finding the device and the user anonymized based on the information available in SmoothWall.

Changes to the REST API

Some APIs now need to become device-specific:

  • POST of app activity
  • POST of app open event

To guide the app to the right API, we will add a query parameter to the user URL: requestingDeviceId. When the user signs up, the user POST request message contains the device name (optional, defaulted when missing). The self-URL of the returned user will include the device ID in the query string, so successive requests on that device carry the device context. The user profile will contain device-specific URLs to POST the app activity and the app open event. This change is transparent to the apps.

The apps need to be updated to support registering a new device. This will be done based on a newDeviceRequest. The flow is detailed on the page Flow - Add another device.

POST new user

The request message now includes an optional device name and operating system. The returned self-link contains a query string with the device ID of the newly registered device.

PUT on existing user

The PUT request when updating a user created on budy request now includes an optional device name and operating system.

GET on existing user

It's possible to GET an existing user in three different ways:

 

RepresentationDescriptionOld query stringNew query string
Own userAll data available for the own user entity, with embedded devices including private device informationincludePrivateData=truerequestingUserId=<own ID>
Buddy userAll data available for a buddy, with embedded devices including only information available to buddiesn/a, embedded in buddy entityrequestingUserId=<ID of a buddy>
MinimalBasic user data (first name, last name, mobile number, nickname)includePrivateData=falsen/a, embedded in a message

New device management path

We introduce the following new path/method combinations:

PathMethodDescription
/users/{userID}/devices/POSTRegisters a new device for the specified user (this must be the current user; the requestingUserId query parameter is not supported). For this to work, a new device request needs to exist and the corresponding password is to be provided in the Yona-NewDeviceRequestPassword header. The response payload is identical to a GET on a user, so it includes the user URL, the Yona password and the newly registered device.
/users/{userID}/devices/GETRetrieves all devices of the specified user. This path supports the requestingUserId to allow fetching the devices of your buddies.
/users/{userID}/devices/{deviceID}GETRetrieves the specified device for the specified user. This path supports the requestingUserId to allow fetching the devices of your buddies.
/users/{userID}/devices/{deviceID}PUTUpdates an existing device for the specified user (this must be the current user; the requestingUserId query parameter is not supported).
/users/{userID}/devices/{deviceID}DELETEDeletes an existing device for the specified user (this must be the current user; the requestingUserId query parameter is not supported). Note the Yona server will not accept subsequent requests for this device. The last device cannot be deleted (the user should unsubscribe instead).

Note that the device name needs to be unique in the scope of a user.

POST of app activity

The old API (/users/{userID}/appActivity/) will be abandoned and a new one will be introduced on the path /users/{userID}/devices/{deviceID}/appActivity. The payload will be identical to the current payload. Given that the app takes the link frome the GET user response, this change is transparent for the app.

POST of app open event

The old API (/users/{userID}/openApp) will be abandoned and a new one will be introduced on the path /users/{userID}/devices/{deviceID}/openApp. The payload will be extended with two optional properties:

  • operatingSystem – This will be used to set the operating system for legacy users, where it was initialized as UNKNOWN. Possible values: ANDROID and IOS. If the given value differs from the known value, we are facing a legacy situation where a user had two devices, one iOS and one Android. In that case, the device OS should not be updated.
  • appVersion – This is used for statistical purposes and to reject app versions that are too old to work with the current server.

The server will respond with an error when posting the app open event on an unregistered device.

GET of raw activity data

This now includes the device name for each activity

Handling existing users and old apps

We will implement an upgrade step that automatically creates a device with a default name for all existing users. This upgrade logic runs when the user fetches their user profile (which hapens when they open the app). When an old app POSTs a new user while omitting the device information, the server will automatically create a device with a default name. The implication of this behavior is that the server is aware of only a single device, even if the user uses more than one of them. Once the app supports the device notion, the user can register their second device by uninstalling Yona on one device and installing it again.

For preexisting users, we will continue to use a VPN login ID based on only the user anonymized ID. Users created after the device notion is implemented will get a VPN login ID based on a combination of the user anonymized ID and the device index (an integer number). The server needs to handle both VPN login IDs properly for an extended period of time, if not indefinitely. The simple solution could be to automatically select "0" as the device ID in case there is no device ID present in the VPN login ID.

Tasks

  • Create the entity model, create the first device when adding a user (even when not included in the POST request) and add it to the GET response YD-495 - Getting issue details... STATUS
  • Add devices to the buddy GET response YD-496 - Getting issue details... STATUS
  • Add the device registration option YD-520 - Getting issue details... STATUS
  • Add device management end point YD-497 - Getting issue details... STATUS
  • Implement the device change messages YD-498 - Getting issue details... STATUS
  • Implement the migration step YD-499 - Getting issue details... STATUS
  • Change the VPN provisioning YD-500 - Getting issue details... STATUS

What to do in the apps

  1. When registering a new user, include deviceNamedeviceOperatingSystem and deviceAppVersion. Note the constraints described in the Swagger spec.
  2. When registering a new device, follow the revised Flow - Add another device. Once this is done, we can implement  YD-521 - Getting issue details... STATUS .
  3. The device-specific links are now added to the device resource, see  YD-546 - Getting issue details... STATUS . The apps should consume these links instead of the equivalent ones that are part of the user resource. Once this is done, we can implement  YD-544 - Getting issue details... STATUS .
  4. The VPN profile is now added to the device resource, see  YD-500 - Getting issue details... STATUS . The apps should now consume the VPN profile from the device. Once this is done, we can implement  YD-541 - Getting issue details... STATUS .
  5. In the settings menu, add an option to unregister the current device (next to the Unsubscribe option). 
  6. Prevent from deleting the last device. Instead, the user should unsubscribe
  7. Add a possibility to see all devices of the user, with the option to
    1. Rename a device. This can be done through a PUT on the device's edit URL. Note the constraints described in the Swagger spec.
    2. Delete a device. Give a warning when deleting the current device, as that makes it immediately unusable. To delete a device, do a DELETE on the device's edit URL. If it's the current device, also remove the Yona data on the device and go back to the sign up/login screen.
  8. Add a possibility to see all devices of a buddy
  9. When posting the appOpen event to the server, the server might respond with an error. In that case, the app should fail to open.
  10. The VPN profile now needs to be taken from the device rather than the user. The VPN information on the user will soon be removed, see  YD-541 - Getting issue details... STATUS
  11. Add support for the BuddyDeviceChangeMessage. Content-wise, this message is identical to the BuddyInfoChangeMessage.

 

  • No labels

5 Comments

  1. When registering a new device, follow the revised Flow - Add another device. Once this is done, we can implement
    This flow is already implemented in both iOS and Android. Please correct me if I am missing something here.
    However, we need to use the flow for legacy situations as described in Detect legacy situation of multiple devices
    1. I don't think this is done. Note that we speak about the revised flow. I searched the Android code for the link yona:registerDevice as metioned on the page Flow - Add another device, but couldn't find that link in the code, so I think the revised flow isn't implemented yet.

      1. Yes, you are correct It is partially done. Registering the device after validating the mobile number is pending. thanks.

    1. The device-specific links are now added to the device resource, see  YD-546 - Add device-specific links to device resource Done . The apps should consume these links instead of the equivalent ones that are part of the user resource. Once this is done, we can implement  YD-544 - Remove device links from user resource In Progress .
    2. The VPN profile is now added to the device resource, see  YD-500 - Provision VPN account per device Done . The apps should now consume the VPN profile from the device. Once this is done, we can implement
    3. The VPN profile now needs to be taken from the device rather than the user. The VPN information on the user will soon be removed, see  YD-541 - Remove VPN profile from User resource In Progress

    These two points are already as part of 1.2 in both android and ios

    1. Indeed, these are done as part of 1.2