Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generating VAPID Keys #30

Closed
MathikumarC opened this issue May 22, 2017 · 4 comments
Closed

Generating VAPID Keys #30

MathikumarC opened this issue May 22, 2017 · 4 comments
Assignees

Comments

@MathikumarC
Copy link

MathikumarC commented May 22, 2017

Hi,

Your libs are excellent to learn for web push in java.

My requirement is sending push messages without GCM ,FCM ,etc... Without application server key when i try to subscribe in client side i am getting below error message.

app.js:57 Unable to register service worker. DOMException: Registration failed - missing applicationServerKey, and manifest empty or missing

So I have generated VAPID keys using below code and output as follows.

 ECNamedCurveParameterSpec parameterSpec = 
 ECNamedCurveTable.getParameterSpec("prime256v1");
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("ECDH", "BC");
        keyPairGenerator.initialize(parameterSpec);
        KeyPair serverKey = keyPairGenerator.generateKeyPair();
        
        PrivateKey priv = serverKey.getPrivate();
        PublicKey pub = serverKey.getPublic();

Below is my public and private keys:

EC Private Key
S: 84d0fbbda6e65e29b4ef314fb502879da07581280b3059cb8e8ef41b28099d5b

EC Public Key
X: 171874128880f91dea2daf4514e5bcf7020c86da1abf063d389149392c0812ff
Y: 175edbd04506da58581b72c28cd4833d4f104c7cc2b5300416ee547c5d7bd9d4

How do i pass my public key to PushManager.subscribe method.

Can you please help me out on this.

Thanks in advance.

@martijndwars
Copy link
Member

martijndwars commented May 23, 2017

Did you read this document? It explains how to generate a keypair using openssl, how to encode the public key for use in your frontend (i.e. for PushManager.subscribe), and how to load it into your Java application that uses this library.

@MathikumarC
Copy link
Author

@martijndwars R Thanks for the prompt reply. It is working perfectly when i generate VAPID keys using openssl :-) . But in my use case i need generate VAPID keys in java then subscribe with public key which i generated in java and push messages from my application server using java.

@martijndwars martijndwars self-assigned this May 27, 2017
@martijndwars
Copy link
Member

martijndwars commented May 29, 2017

Ah, right. In that case, you can use Utils.savePublicKey to convert your Java-generated PublicKey to a byte[]. This byte[] is then passed to the PushManager.subscribe method.

It may be more convenient to base64 encode the byte[] in Java and base64 decode the string in JavaScript. For example, after generating the keypair in Java:

KeyPair keyPair = generateKeyPair();
byte[] publicKey = Utils.savePublicKey((ECPublicKey) keyPair.getPublic());
String publicKeyBase64 = BaseEncoding.base64Url().encode(publicKey);
System.out.println("PublicKey = " + publicKeyBase64);
// PublicKey = BPf36QAqZNNvvnl9kkpTDerXUOt6Nm6P4x9GEvmFVFKgVyCVWy24KUTs6wLQtbV2Ug81utbNnx86_vZzXDyrl88=

Then in JavaScript:

function subscribe() {
    const publicKey = base64UrlToUint8Array('BPf36QAqZNNvvnl9kkpTDerXUOt6Nm6P4x9GEvmFVFKgVyCVWy24KUTs6wLQtbV2Ug81utbNnx86_vZzXDyrl88=');
    
    navigator.serviceWorker.ready.then(function (serviceWorkerRegistration) {
        serviceWorkerRegistration.pushManager.subscribe({
            userVisibleOnly: true,
            applicationServerKey: publicKey
        })
        .then(function (subscription) {
            return sendSubscriptionToServer(subscription);
        })
        .catch(function (e) {
            if (Notification.permission === 'denied') {
                console.warn('Permission for Notifications was denied');
            } else {
                console.error('Unable to subscribe to push.', e);
            }
        });
    });
}

function base64UrlToUint8Array(base64UrlData) {
    const padding = '='.repeat((4 - base64UrlData.length % 4) % 4);
    const base64 = (base64UrlData + padding)
        .replace(/\-/g, '+')
        .replace(/_/g, '/');

    const rawData = atob(base64);
    const buffer = new Uint8Array(rawData.length);
    
    for (let i = 0; i < rawData.length; ++i) {
        buffer[i] = rawData.charCodeAt(i);
    }
    
    return buffer;
}

@MathikumarC
Copy link
Author

Great!!!!. It is working exactly what i have expected.

Thanks a lot.

Regards
Mathikumar

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants