Skip to content

Front end configuration

Lahiru Jayakody edited this page Dec 4, 2016 · 2 revisions

1. Preparing client-side scripts

Open the project in IntelliJ IDEA.

Guide lines

  1. First you need to generate an elliptic curve public–private key pair (a public-key cryptosystems like old RSA). This key pair is for identification of your back-end service which will be used later to send notifications. This identification process is called VAPID. You can use front-end/keygen.html to generate a key pair. Generate and note down the VAPID keys.

  2. Put the generated public key in following files as below. N.B. File paths and names are commented at the top of each code block.

// front-end/sw.js const applicationServerPublicKey = "";


    ```javascript
// front-end/main.js
const applicationServerPublicKey = "<your-generated-public-key>";
  1. Now your client-side scripts are ready to test on non-safari browsers. You should add main.js to your web page as a script. It will register sw.js as a service worker.

  2. Open front-end/index.html in browser using any HTTP Server. You should be able to access to index.html from similar url as following.
    http://localhost:65124/browser-push/front-end/index.html
    DNS should be localhost. Otherwise, it should be https://
    Press Load Script button to inject main.js script. (instead, you can simply add main.js to the head section of the web page). After press Enable Push Messaging to subscribe for push notificatons. An input box will appear. Note down the JSON string.

    This JSON object is called user subscription. In production environment, you should send this subscription to your backen-end and it should be persisted against some user identification. Later your back-end will use that user subscription objects to send push notifications to subscribed users. For demonstration purpose, you can copy it now and hard code in server code.

Following steps are needed for Safari only. If you wish to send notifications for a non-Safari browser, move to next section

  1. Create certificates (.p12 and .cer) and a website push id for your domain from Apple developer site. Refer Registering with Apple section in Configuring Safari Push Notifications article.

  2. Add your website push id which will look like web.com.example to the code as below.

// front-end/main.js var domain = "web.com.example";


    Then you need to setup a RESTful web service which will be called every time some Safari user is trying to subscribe for your webapp. Therefore, Safari push notification protocol needs 3 components to work together as following figure.

    ![Safari-handshake](https://github.com/lahiiru/browser-push/raw/gh-pages/handshake_2x.png)

    In above diagram, pink color box *Returns push package* needs to be done by our RESTful web service. **Push package** is a zip file which contains some files and it's hashes. Although Apple developer page instructs to build push packages dynamically, in our implementation we will create it once and RESTful service will serve it as a static resource.

    > If you plan to follow Apple developer instructions strictly, that is fine and it follows good security practices. But, I suggest you to try this first. After you can change the way push packages are created by modifying `private void getZip()` method in my RESTful service implementation.

3. Navigate to `back-end/safari_push_package_creator/pushPackage.raw/`.    
Modify the files as you needed. Please refer the *Building the Push Package* section in [Configuring Safari Push Notifications](https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/NotificationProgrammingGuideForWebsites/PushNotifications/PushNotifications.html#//apple_ref/doc/uid/TP40013225-CH3-SW7) article.

    > If you are planing to add Safari push notification support to multiple domain names, specify those as **"allowedDomains"**    
in `back-end/safari_push_package_creator/pushPackage.raw/website.json`.    
Parameter **"webServiceURL"** specifies the path where the Safari RESTful service will be deployed at. **authenticationToken** will be not using to identify users in our implementation. So keep it as it is. Further, you can have your own iconset.

4. Next, a push package should be created using files in **pushPackage.raw** directory. This happens in following manner.
    1. [SHA1](https://www.w3.org/PICS/DSig/SHA1_1_0.html) hash values of the files are calculated.
    2. Those hash values are put in a file, named **manifest.json**.
    3. This manifest.json file is signed with the private key in .p12 archive and signature is written as a file named **signature**.
    4. Finally a zip archive is created with all those files.

    This process ensures the integrity of the push package (changing the content of files by a third party is avoided).
    Apple developer site has given a [php script](https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/NotificationProgrammingGuideForWebsites/CompanionFile.zip) to do that process. I have sightly changed it to cater our need easily. Do following changes first.

    ```php
// back-end/safari_push_package_creator/index.php
$certificate_path = "path/to/file/pkey.p12";         // Change this to the path where your certificate is located.
$certificate_password = "your-certificate-password"; // Change this to the certificate's import password.
  1. Run that index.php file.

php index.php


6. Then a push package for your webapp will be created at following path    
`back-end/safari_webservice_backend/binaries/push-package.zip`

7. Now make the **push-api.war** by packaging project **safari_webservice_backend**.
    ```shell
> mvn package
  1. Deploy the push-api.war file in Tomcat or other container. After the deployment, "webServiceURL" specified in website.json should matches the context path of deployed web application.
    If everything works fine,

    • http://webServiceURL/v1/ should response with BAD REQUEST
    • http://pushPackages/v1/web.com.example should download zip file push-package.bin.
  2. Now you can test Safari push notifications using front-end/index.html.

  3. A confirmation box should be displayed when Load Script button is clicked. Otherwise, check developer console outputs. If output is printed with deviceToken=null, this is a problem of your safari RESTful service or created push package. See push-api.war logs for troubleshooting.

  4. If everything works fine, input box with a token should be appeared. Note it down as Safari subscription. It is needed when sending notifications.

    In production environment, you should send this subscription to your back-end and it should be persisted against some user identification. Later your back-end will use that user subscription objects to send push notifications to subscribed users. For demonstration purpose, you can copy it now and hard code in server code.

References

If you encounter any problem with above guide lines, following resources from the original authors will be helpful.

Browser Push Github page

Clone this wiki locally