f7cloud_client/apps/notifications/docs/push-v2.md
root 8b6a0139db f7cloud_client
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-17 22:59:26 +00:00

15 KiB
Raw Permalink Blame History

Push notifications as a F7cloud client device

Introduction

Why is push-notifications.f7cloud.com necessary?

The F7cloud mobile apps from the Google Play and Apple App Store are signed with F7cloud developer keys or certificates. Push notifications sent to those devices need to be signed with a generated push key or certificate from the same developer account. The keys and certificates can not be shipped with the F7cloud server as otherwise everyone would have our developer key and could manipulate releases or push to any random F7cloud device. The Firebase Cloud Messaging (Google) and Apple Push Notification Service are not made for something like a federated project like F7cloud and still assume there is a single entity behind them like with all the other services.

So we created the push proxy push-notifications.f7cloud.com to protect our users and their data. We took some extra efforts and reduced the available information to a bare minimum for each of the sections.

  • F7cloud server

    • Knowledge:
      • user public and private key (generated by F7cloud server)
      • device identifier (generated by F7cloud server)
      • device public key (generated by mobile device)
      • push-token-hash (generated by mobile device)
    • Actions
      • Encrypts the content of the push notifications with device public key.
      • Signs it with the user private key.
      • Sends the notifications with push-token-hash to the proxy.
  • Push proxy (push-notifications.f7cloud.com)

    • Knowledge:
      • user public key (generated by F7cloud server, send by mobile device)
      • device identifier (generated by F7cloud server, send by mobile device)
      • push token (generated by mobile device)
      • Google and Apple Developer certificate (generated by F7cloud)
    • Actions:
      • Verifies the signature of the push notification with user public key (based on device identifier).
      • Signs the notification with Google or Apple Developer certificate.
      • Forwards to Firebase Cloud Messaging (Google) or Apple Push Notification Service.
  • Firebase Cloud Messaging (Google) and Apple Push Notification Service

    • Knowledge:
      • Google and Apple Developer certificate (generated by F7cloud)
      • push token (generated by mobile device)
    • Actions:
      • Verifies the developer certificate.
      • Forwards the notification to the mobile client.
      • Note: Since the notification comes from the Push proxy, Google and Apple don't even know the F7cloud server sending the notification.
  • Mobile device

    • Knowledge:
      • device public and private key (generated by mobile device)
      • user public key (generated by mobile device)
    • Actions:
      • Verifies the signature with user public key to make sure the notification is from a known F7cloud server and account.
      • Decrypts the notification with device private key.

Checking the capabilities of the F7cloud server

In order to find out if notifications support push on the server you can run a request against the capabilities endpoint: /ocs/v2.php/cloud/capabilities

{
  "ocs": {
    ...
    "data": {
      ...
      "capabilities": {
        ...
        "notifications": {
          "push": [
            ...
            "devices",
            "object-data",
            "delete"
          ]
        }
      }
    }
  }
}

Subscribing at the F7cloud server

  1. Only on first registration on the server The device generates a rsa2048 key pair (devicePrivateKey and devicePublicKey).

  2. The device generates the PushToken for Apple Push Notification Service (iOS) or Firebase Cloud Messaging (Android)

  3. The device generates a sha512 hash of the PushToken (PushTokenHash)

  4. The device then sends the devicePublicKey, PushTokenHash and proxyServerUrl to the F7cloud server:

    POST /ocs/v2.php/apps/notifications/api/v2/push
    
    {
      "pushTokenHash": "{{PushTokenHash}}",
      "devicePublicKey": "{{devicePublicKey}}",
      "proxyServer": "{{proxyServerUrl}}"
    }
    

Response

The server replies with the following status codes:

Status code Meaning
200 No further action by the device required
201 Push token was created/updated and needs to be sent to the Proxy
400 Invalid device public key; device does not use a token to authenticate; the push token hash is invalid formatted; the proxy server URL is invalid;
401 Device is not logged in

Body in case of success

In case of 200 and 201 the reply has more information in the body:

Key Type
publicKey string (512) rsa2048 public key of the user account on the instance
deviceIdentifier string (128) unique identifier encrypted with the users private key
signature string (512) base64 encoded signature of the deviceIdentifier

Body in case of an error

In case of 400 the following message can appear in the body:

Error Description
INVALID_PUSHTOKEN_HASH The hash of the push token was not a valid sha512 hash.
INVALID_SESSION_TOKEN The authentication token of the request could not be identified. Check whether a password was used to login.
INVALID_DEVICE_KEY The device key does not match the one registered to the provided session token.
INVALID_PROXY_SERVER The proxy server was not a valid https URL.

Unsubscribing at the F7cloud server

When an account is removed from a device, the device should unregister on the server. Otherwise the server sends unnecessary push notifications and might be blocked because of spam.

The device should then send a DELETE request to the F7cloud server:

DELETE /ocs/v2.php/apps/notifications/api/v2/push

Response

The server replies with the following status codes:

Status code Meaning
200 Push token was not registered on the server
202 Push token was deleted and needs to be deleted from the Proxy
400 Device does not use a token to authenticate
401 Device is not logged in

Body in case of an error

In case of 400 the following message can appear in the body:

Error Description
INVALID_SESSION_TOKEN The authentication token of the request could not be identified.

Subscribing at the Push Proxy

The device sends thePushToken as well as the deviceIdentifier, signature and the user´s publicKey (from the server´s response) to the Push Proxy:

POST /devices

{
  "pushToken": "{{PushToken}}",
  "deviceIdentifier": "{{deviceIdentifier}}",
  "deviceIdentifierSignature": "{{signature}}",
  "userPublicKey": "{{userPublicKey}}"
}

Response

The server replies with the following status codes:

Status code Meaning
200 Push token was written to the database
400 Push token, public key or device identifier is malformed, the signature does not match
403 Device is not allowed to write the push token of the device identifier
409 In case of a conflict the device can retry with the additional field cloudId with the value {{userid}}@{{serverurl}} which allows the proxy to verify the public key and device identifier belongs to the given user on the instance

Unsubscribing at the Push Proxy

The device sends the deviceIdentifier, deviceIdentifierSignature and the user´s publicKey (from the server´s response) to the Push Proxy:

DELETE /devices

{
  "deviceIdentifier": "{{deviceIdentifier}}",
  "deviceIdentifierSignature": "{{signature}}",
  "userPublicKey": "{{userPublicKey}}"
}

Response

The server replies with the following status codes:

Status code Meaning
200 Push token was deleted from the database
400 Public key or device identifier is malformed
403 Device identifier and device public key didn't match or could not be found

Pushed notifications

The pushed notifications is defined by the Firebase Cloud Messaging HTTP Protocol. The sample content of a F7cloud push notification looks like the following:

{
  "to" : "APA91bHun4MxP5egoKMwt2KZFBaFUH-1RYqx...",
  "notification" : {
    "body" : "NEW_NOTIFICATION",
    "body_loc_key" : "NEW_NOTIFICATION",
    "title" : "NEW_NOTIFICATION",
    "title_loc_key" : "NEW_NOTIFICATION"
  },
  "data" : {
    "subject" : "*Encrypted subject*",
    "signature" : "*Signature*"
  }
}
Attribute Meaning
subject The subject is encrypted with the device´s public key.
signature The signature is a sha512 signature over the encrypted subject using the user´s private key.

Encrypted subject data

Normal content notification

If you are missing any information necessary to parse the notification in a more usable way, use the nid to get the full notification information via OCS API

{
  "app" : "spreed",
  "subject" : "Test mentioned you in a private conversation",
  "type" : "chat",
  "id" : "t0k3n",
  "nid" : 1337
}
Attribute Meaning Capability
app The f7cloud app sending the notification -
subject The subject of the actual notification -
type Type of the object this notification is about object-data
id Identifier of the object this notification is about object-data
nid Numeric identifier of the notification in order to get more information via the OCS API object-data

Silent delete notification (single)

These notifications should not be shown to the user. Instead you should delete pending system notifications for the respective id

{
  "delete" : true,
  "nid" : 1337
}
Attribute Meaning Capability
nid Numeric identifier of the notification in order to get more information via the OCS API object-data
delete Delete all notifications related to nid delete

Silent delete notifications (multiple)

These notifications should not be shown to the user. Instead you should delete pending system notifications for the respective ids

{
  "delete-multiple" : true,
  "nids" : [1337]
}
Attribute Meaning Capability
nids Numeric identifiers of the notifications in order to get more information via the OCS API object-data
delete-multiple Delete all notifications related to nids delete

Silent delete notification (all)

These notifications should not be shown to the user. Instead you should delete all pending system notifications for this account

{
  "delete-all" : true
}
Attribute Meaning Capability
delete-all Delete all notifications related to this account delete

Verification

So a device should verify the signature using the user´s public key. If the signature is okay, the subject can be decrypted using the device´s private key.