web-push-libs / webpush-java Goto Github PK
View Code? Open in Web Editor NEWWeb Push library for Java
License: MIT License
Web Push library for Java
License: MIT License
I am pushing single message to single subscriber ,but recieving the notification 2 times .I have tried in both chrome and mozilla . Could somebody help ?
I noticed in this commit: 64baebc#diff-635c01aada177ec436f99d8e16a73972 that for Chrome notifications, the POST body being sent is no longer the same as it was before, which was:
{ "registration_ids": [...], "raw_data": ..... }
Is this intended behavior? I've read that the entire body might need to be encrypted, which is what it seems like the code is now doing, but it seems a little strange that GcmNotification registrationIds are no longer being used anywhere in making the request (and I'm getting error=MissingRegistration when sending the notifications).
Following the article about sending web push notifications I managed to make it work in both Chrome and Firefox browsers. Using the webpush-java I managed to make it send notifications to Firefox, but not to Chrome. When sending to Chrome, I am getting return code 400 UnauthorizedRegistration.
The web server I use is web server for Chrome, as suggested in the article. I use the corresponding applicationServerPublicKey, as generated in the companion site, and use corresponding public/private keys (different for Firefox and Chrome).
Searching the internet didn't yield any actionable steps. Any suggestions as to what to try/how to get to the bottom of this? Please let me know if any more/additional information is needed.
Thanks!
When I ran the encryption code with open jdk 1.8 it is all working fine. But when I am running with sun jdk jdk1.8.0_20, it is trowing following exception
Exception in thread "main" java.security.InvalidKeyException: Not an EC key: ECDH
at sun.security.ec.ECKeyFactory.checkKey(ECKeyFactory.java:121)
at sun.security.ec.ECKeyFactory.toECKey(ECKeyFactory.java:90)
at sun.security.ec.ECDHKeyAgreement.engineInit(ECDHKeyAgreement.java:67)
at javax.crypto.KeyAgreement.implInit(KeyAgreement.java:341)
at javax.crypto.KeyAgreement.chooseProvider(KeyAgreement.java:373)
at javax.crypto.KeyAgreement.init(KeyAgreement.java:465)
at javax.crypto.KeyAgreement.init(KeyAgreement.java:436)
at nl.martijndwars.webpush.HttpEce.deriveDH(HttpEce.java:117)
at nl.martijndwars.webpush.HttpEce.deriveKey(HttpEce.java:54)
at nl.martijndwars.webpush.HttpEce.encrypt(HttpEce.java:166)
at nl.martijndwars.webpush.PushService.encrypt(PushService.java:62)
Hi
I'm having trouble getting this to work.
I have generated keys with the help of:
C:\Proj\git\webpush-java>java -jar build/libs/web-push-3.0.0-all.jar generate-key
PublicKey:
BMU04E2PG6WEPFNpNjdm2axI-tPkBwIgEP60WVRy9-fgCKvPC7U1DA02XaPG9-Iwj_l6EnHo9zbW-aNhNO8BLDk=
PrivateKey:
G5yq2I6-xwK2pRizUFznueDbYm-DNgkHfWB4DqqS9Pc=
And in my java code I try to do:
String publicKey = "BMU04E2PG6WEPFNpNjdm2axI-tPkBwIgEP60WVRy9-fgCKvPC7U1DA02XaPG9-Iwj_l6EnHo9zbW-aNhNO8BLDk=";
String privateKey = "G5yq2I6-xwK2pRizUFznueDbYm-DNgkHfWB4DqqS9Pc=";
PushService pushService = new PushService(publicKey, privateKey, "mailto:[email protected]");
But I get "key spec not recognised".
What am I doing wrong, is it the subject that is wrong? what should the subject be ?
Hi Martin,
Thank you for this library. I've successfully run this project and I can see that the notifications are being delivered to Firefox and Chrome. I've just noticed that the payload has an issue with Chrome, the data in PushEvent is always null while in Firefox everything is ok. Is there any modification that I need to do in for the payload to be delivered in Chrome clients too?
Cheers,
Rae
Hi there,
in HttpEce.deriveKey(...)
method you have following flow:
byte[] secret = null;
byte[] context = null;//follow this one
if (key != null) {
secret = key;
} else if (dh != null) {
byte[][] bytes = deriveDH(keyId, dh);
secret = bytes[0];
context = bytes[1]; //the only place you initialize context
} else if (keyId != null) {
secret = keys.get(keyId).getPublic().getEncoded();
}
// no more changes to the context var
keyinfo = buildInfo("aesgcm", context);
and in buildinfo method you have immediately:
protected static byte[] buildInfo(String type, byte[] context) {
ByteBuffer buffer = ByteBuffer.allocate(19 + type.length() + context.length);
so it seems that the only way to Not get NullPointer is to have key == null && dh != null,
so first & third conditions will never work anyway, and in code key is indeed passed as null when used.
Maybe I'm missing a bigger picture here?
If this library could be updated to support VAPID, and the documentation updated to include an example, that would be great:)
Don't know if it is the library or the push api or something else. But at least when having the character å in the payload, the data property on the event becomes null. Would assume the same goes for all three umlauts åäö. If I Base64 it before sendoff it works.
We should use Selenium to run end-to-end browser tests. My work in progress is in the selenium branch.
Currently, the selenium tests only check that the endpoint accepts the push notification (201 status code). We can also check that the notification arrives in the browser and the message is as expected. For broadcasting from a service worker to a client, see here.
Hi,
I have just spent a day trying to send notifications through WebPush, ad managed to get this done by specifically adding private and public keys to the PushService. Without this, I get authentication errors. This is not specifically mentioned in the ReadMe.md, so it may be worth adding this to the tutorial.
Thanks
Kees
removed example for legal reasons
When I try to send a notification (using VAPID) with a payload that contains some UTF-8 characters like 'ç', the notification is sent and received by the end user, but with no data.
All the rest is working perfectly.
Thanks!
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.
webpush-java has a dependency to guava, which obviously doesn't serve a valid purpose:
// Not sure what for..
compile group: 'com.google.guava', name: 'guava', version: '19.0'
since guava is a quite heavy lib (around 3mb), it would be nice to remove this dependency.
I've been trying to get the push notification running with your example usage code, with no luck.
The browser keeps throwing this error.
The ServiceWorker for scope ‘http://localhost:8081/’ encountered an error decrypting a push message: ‘OperationError: The operation failed for an operation-specific reason’. For help with encryption, please see https://developer.mozilla.org/en-US/docs/Web/API/Push_API/Using_the_Push_API#Encryption
Any idea whats going on?
I used a node library to run a small server to make sure there's no issues in the client side. The issue seem to be in the client side.
When the push message is sent from the server side, I get a 201 http response.
HttpResponseProxy{HTTP/1.1 201 Created [Access-Control-Allow-Headers: content-encoding,encryption,crypto-key,ttl,encryption-key,content-type,authorization, Access-Control-Allow-Methods: POST, Access-Control-Allow-Origin: *, Access-Control-Expose-Headers: location,www-authenticate, Content-Type: text/html; charset=UTF-8, Date: Tue, 03 Jan 2017 01:45:54 GMT, Location: https://updates.push.services.mozilla.com/m/gAAAAABYawJSH-_1uf7tv292lj_TBcDoZ_uJlCI24KqOXcDaNyX7isiiSP0-iYb5z9G2j-EgEwPuntOQsLNq6R2lWrUjNoIefCvJNRUQIvrZQep5gCDD-2ZtBx6hWUpk3it-LI5i252aZMqRiNfcmf1w1Sv3GgOMhfEywI1IS6R7Y3rSfDg1HPJGa7plv_jfaofFsmesmyOk, Server: nginx, TTL: 2419200, Content-Length: 0, Connection: keep-alive] [Content-Type: text/html; charset=UTF-8,Content-Length: 0,Chunked: false]}
for vapid do we need any license for commercial use
First off, thanks for this library.
RFC 8188 has been out for over a year, and some clients may soon no longer support the older "aesgcm" encoding format. Can you please make the default "aes128gcm"? Thanks!
For sending notifications to multiple subscribers, I assume that we would have to create a single instance of PushService and many instances of Notification in a loop, is that correct?
If so, is it practical to send notifications to a very large number of subscribers using the above method? Are there any performance implications? Would this be highly memory or CPU intensive?
Would it make more sense to split the notifications into batches and run them separately? If so, what would be a good rule of thumb for each batch size?
Thanks!
Hello,
Could you please push latest version (3.1.1) to Maven?
https://mvnrepository.com/artifact/nl.martijndwars/web-push the last one is 3.1.0.
Thanks!
I try send notification from jar in IDEA.
Keys generated with same jar.
My arguments command:
send-notification
--subscription="{'endpoint': 'https://fcm.googleapis.com/fcm/send/f2tFGlQREiw:APA91bGKY0TakQ92UOPNlRe3_DiJ2CT0bC-m98CINcBRuKqvjBhkaO9im01T9ZLlOJeVRCXV57zSk1qgLTB5Wz6oAjrJ3Y19G4vQrWgKqsvwKeRAiCJHlmac_aJrF_tWlMgwyqfRwOHA', 'expirationTime': null, 'keys': {'p256dh': 'BKBQF2VLYXmpQ3sEcgj8wjUJjfhgz5GW7PyTvN2FB1MlAMSLN2bgwOqe9GkSbmoiRedlpgfp6CihUzGhp5DtCkM','auth': 'BJO4i2ltwyyV8ekNpaW4hQ'}}"
--publicKey="BIqmcv0cVhdGJMjBa16jAhMh-eRfiG5-g14WkSj_62pL7zSKJP1KDoPOGW2wN-BIo6VNQsxZKr1VrYXO66If2hc="
--privateKey="RauHMIAXL8UKqrtn1EvWUWeO2No62P-XTo56yM59lDI="
--payload="Hello, lovely world"
subscription
I get from your UI from js-subscription-json element.
What wrong?
Could you please push the tag? thanks.
Using Java on Ubuntu 16.04:
openjdk version "1.8.0_162"
OpenJDK Runtime Environment (build 1.8.0_162-8u162-b12-0ubuntu0.16.04.2-b12)
OpenJDK Server VM (build 25.162-b12, mixed mode)
Though the build was success but I am getting following error while executing the jar:
$java -jar webpush-1.jar generate-key
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.NoClassDefFoundError: com/beust/jcommander/ParameterException
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
at java.lang.Class.privateGetMethodRecursive(Class.java:3048)
at java.lang.Class.getMethod0(Class.java:3018)
at java.lang.Class.getMethod(Class.java:1784)
at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:544)
at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:526)
Caused by: java.lang.ClassNotFoundException: com.beust.jcommander.ParameterException
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:338)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 7 more
Please let me know if I am missing anything.
Thanks.
Hello.
I am trying to use webpush-java with a web page and I created a Java test application (Jar file) to try it. But I have a problem:
When I run the test in the Windows prompt I get success and a push notification in my workstation, but when I run the test in the CMS (Opencms - Tomcat) I get the error:
09 ago 2018 11:44:17,794 ERROR [s.scheduler.CmsScheduleManager: 576] Error executing scheduled job "teste para notificacao".
**java.security.spec.InvalidKeySpecException: key spec not recognized**
at org.bouncycastle.jcajce.provider.asymmetric.util.BaseKeyFactorySpi.engineGeneratePublic(Unknown Source)
at org.bouncycastle.jcajce.provider.asymmetric.ec.KeyFactorySpi.engineGeneratePublic(Unknown Source)
at java.security.KeyFactory.generatePublic(Unknown Source)
at nl.martijndwars.webpush.Utils.loadPublicKey(Utils.java:70)
at nl.martijndwars.webpush.Notification.<init>(Notification.java:51)
at PushServiceTest.testPushChromeVapid(PushServiceTest.java:69)
at disparaTeste.launch(disparaTeste.java:22)
at org.opencms.scheduler.CmsScheduleManager.executeJob(CmsScheduleManager.java:568)
at org.opencms.scheduler.CmsScheduleManager$1.run(CmsScheduleManager.java:170)
I think the problem is in the command:
pushService.setPublicKey(Utils.loadPublicKey("BOH8nTQA5iZhl23+NCzGG9prvOZ5BE0MJXBW+GUkQIvRVTVB32JxmX0V1j6z0r7rnT7+bgi6f2g5fMPpAh5brqM="));
Have you some suggestion to solve the problem?
Thanks a lot.
https://tools.ietf.org/html/rfc8030#section-5.3
5.3. Push Message Urgency
For a device that is battery-powered, it is often critical that it
remains dormant for extended periods. Radio communication in
particular consumes significant power and limits the length of time
that the device can operate.
To avoid consuming resources to receive trivial messages, it is
helpful if an application server can communicate the urgency of a
message and if the user agent can request that the push server only
forwards messages of a specific urgency.
An application server MAY include an Urgency header field in its
request for push message delivery. This header field indicates the
message urgency. The push service MUST NOT forward the Urgency
header field to the user agent. A push message without the Urgency
header field defaults to a value of "normal".
A user agent MAY include the Urgency header field when monitoring for
push messages to indicate the lowest urgency of push messages that it
is willing to receive. A push service MUST NOT deliver push messages
with lower urgency than the value indicated by the user agent in its
monitoring request. Push messages of any urgency are delivered to a
user agent that does not include an Urgency header field when
monitoring for messages.
The grammar for the Urgency header field is as follows:
Urgency = urgency-option
urgency-option = ("very-low" / "low" / "normal" / "high")
In order of increasing urgency:
+----------+-----------------------------+--------------------------+
| Urgency | Device State | Example Application |
| | | Scenario |
+----------+-----------------------------+--------------------------+
| very-low | On power and Wi-Fi | Advertisements |
| low | On either power or Wi-Fi | Topic updates |
| normal | On neither power nor Wi-Fi | Chat or Calendar Message |
| high | Low battery | Incoming phone call or |
| | | time-sensitive alert |
+----------+-----------------------------+--------------------------+
Table 1: Illustrative Urgency Values
Multiple values for the Urgency header field MUST NOT be included in
requests; otherwise, the push service MUST return a 400 (Bad Request)
status code.
I saw that in this commit you removed Async request.
4737ed8
Could you please explain a little bit why it is removed? Thanks!
i am trying to use your new method of sending push using httppost, but the httpresponse is giving status code as 201 and body as null.
However when i use old way (using request and async) it gives proper response. Can you please help me with this?
Thanks
https://tools.ietf.org/html/draft-ietf-webpush-vapid-01
They changed the format of the Authorization header. Looks like it should now be "WebPush aklsjdalksjdlkajsf" instead of Bearer.
Also according to this: https://developers.google.com/web/updates/2016/07/web-push-interop-wins crypto-key claims should be comma separated instead of semi-colon.
The following method is not found and fails at runtime.
org.bouncycastle.util.BigIntegers.fromUnsignedByteArray
Hi,
I tested sending a notification to MS Edge - already working in Chrome and Firefox - without success: the push server (https://db5.notify.windows.com/w/?token=...
) returns 400 Bad Request with no body.
After a quick check and according to https://github.com/web-push-libs/web-push-php/releases/tag/v4.0.0 it appears to be because it requires the aes128gcm
content encoding, aesgcm
won't work (I have not confirmed this).
Are there any plans to add support for aes128gcm? Thanks!
Hi,
When I try to encrypt in node js it is taking around 1ms to complete where are here it is taking about
700+ ms on java version in the same machine.
We are using this library on an app that runs in a Docker instance. We noticed that the random number generation used for the salt can be very slow and block the execution for up to 5 minutes, just to generate the 16 bytes.
The problem is with this line in PushService:
byte[] salt = SecureRandom.getSeed( 16 );
Is there any specific reason to use getSeed()
?
Why not use nextBytes() instead? This random number generation is not blocking:
byte[] salt = new byte[16];
new SecureRandom().nextBytes( salt );
I can create a pull request for this if it helps.
I use this code:
import java.nio.charset.StandardCharsets;
import java.security.Security;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import com.google.gson.JsonObject;
import nl.martijndwars.webpush.Notification;
import nl.martijndwars.webpush.PushService;
public class Teste {
public static void main(String[] args) {
try {
Security.addProvider(new BouncyCastleProvider());
// Send notification!
sendPushMessage(getPayload());
} catch (Exception e) {
e.printStackTrace();
}
}
private static final int TTL = 255;
public static void sendPushMessage(byte[] payload) {
// Figure out if we should use GCM for this notification somehow
try{
Notification notification;
PushService pushService;
// Create a notification with the endpoint, userPublicKey from the subscription and a custom payload
notification = new Notification(
"https://fcm.googleapis.com/fcm/send/d8KX2q4goDM:APA91bH5Boq0076mY4-YdxIOrsD_pzfx6DorrD6FRaksk5sf64A3Z9cySX2JhxwOlql1wq-Bdo0SZvSmBbARZaxTgn4_O9MHbbG_JFY-ZJp0i6WauLwllglA54lBp6NkWB0q6axNHIa3",
"BPNcSFiObeUbcCg4m5c1AybHv7NSdBE_X5YJ6ZFQfpXWnXQbDnEILz3qPe4Zb-9M9B6Lc_W20uSzVmH1ZyNuWwk=",
"nJiZotPSQE4P4z75Igq57Q==",
"Hello, world!"
);
// Instantiate the push service, no need to use an API key for Push API
pushService = new PushService();
// Send the notification
HttpResponse httpResponse = pushService.send(notification);
System.out.println(httpResponse.getStatusLine().getStatusCode());
System.out.println(IOUtils.toString(httpResponse.getEntity().getContent(), StandardCharsets.UTF_8));
} catch (Exception e) {
e.printStackTrace();
}
}
private static byte[] getPayload() {
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("title", "Hello");
jsonObject.addProperty("message", "World");
return jsonObject.toString().getBytes();
}
}
And receive this answer:
400
<HTML>
<HEAD>
<TITLE>UnauthorizedRegistration</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000">
<H1>UnauthorizedRegistration</H1>
<H2>Error 400</H2>
</BODY>
</HTML>
Hello,
When instanciating a PushService object, the line KeyFactory.getInstance("ECDH", "BC") in Utils.class throws a NoSuchProviderException for "BC".
Is it normal ?
Thanks.
I'm getting a org.jose4j.lang.InvalidKeyException, when i'm trying to push a notification:
Exception:
2018-02-20 18:20:46,787|000-exec-2|ERROR|boration.review.ReviewOverview|The given key (algorithm=ECDH) is not valid (not a private key or is the wrong type of key) for SHA256withECDSA / ES256 java.lang.ClassCastException: org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey cannot be cast to java.security.interfaces.ECPrivateKey
org.jose4j.lang.InvalidKeyException: The given key (algorithm=ECDH) is not valid (not a private key or is the wrong type of key) for SHA256withECDSA / ES256 java.lang.ClassCastException: org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey cannot be cast to java.security.interfaces.ECPrivateKey
at org.jose4j.jws.BaseSignatureAlgorithm.validateSigningKey(BaseSignatureAlgorithm.java:160)
at org.jose4j.jws.JsonWebSignature.sign(JsonWebSignature.java:98)
at org.jose4j.jws.JsonWebSignature.getCompactSerialization(JsonWebSignature.java:73)
at nl.martijndwars.webpush.PushService.preparePost(PushService.java:198)
at nl.martijndwars.webpush.PushService.sendAsync(PushService.java:131)
at nl.martijndwars.webpush.PushService.send(PushService.java:118)
at de.aeneis.web.collaboration.review.ReviewOverview$2.onEvent(ReviewOverview.java:154)
at org.zkoss.zk.ui.AbstractComponent.onEvent(AbstractComponent.java:3163)
at org.zkoss.zk.ui.AbstractComponent.service(AbstractComponent.java:3133)
at org.zkoss.zk.ui.AbstractComponent.service(AbstractComponent.java:3075)
at org.zkoss.zk.ui.impl.EventProcessor.process(EventProcessor.java:138)
at org.zkoss.zk.ui.impl.UiEngineImpl.processEvent(UiEngineImpl.java:1853)
at org.zkoss.zk.ui.impl.UiEngineImpl.process(UiEngineImpl.java:1625)
at org.zkoss.zk.ui.impl.UiEngineImpl.execUpdate(UiEngineImpl.java:1328)
at org.zkoss.zk.au.http.DHtmlUpdateServlet.process(DHtmlUpdateServlet.java:606)
at de.aeneis.bpmportal.zk.UpdateServlet.process(UpdateServlet.java:53)
at org.zkoss.zk.au.http.DHtmlUpdateServlet.doGet(DHtmlUpdateServlet.java:482)
at de.aeneis.bpmportal.zk.UpdateServlet.doGet(UpdateServlet.java:43)
at org.zkoss.zk.au.http.DHtmlUpdateServlet.doPost(DHtmlUpdateServlet.java:490)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at io.swagger.api.ApiOriginFilter.doFilter(ApiOriginFilter.java:16)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
My Code:
Security.addProvider(new BouncyCastleProvider());
PushService pushService = new PushService()
.setPublicKey(PUBLIC_KEY)
.setPrivateKey(PRIVATE_KEY)
.setSubject("mailto:[email protected]");
nl.martijndwars.webpush.Subscription subscription = new nl.martijndwars.webpush.Subscription();
Subscription.Keys keys = subscription.new Keys(
"BFxzKvlzk9tarZ5f2M7DUwBJEWxeJ4IQ_yety8cE8TgfWwSLPKeUROxxlnPUNN5SCoAJd3KE3nBBcQ9JCrMPsm0=",
"JoLTqdBPvO-FdQT01A6w-Q=="
);
nl.martijndwars.webpush.Subscription subscription2 = new nl.martijndwars.webpush.Subscription(
"https://fcm.googleapis.com/fcm/send/d7NgqbmcoKo:APA91bG3J9OCjcjdGYGVWhtGVjB2nFUcKQTuePjUYMxQ2TH8HEUXLH7EwXcFQvIZ4pAvPT3_y7aIu6kYTJdcoo_qy4ukG3C3fLOK2-YZwYS5eRtpvo3gbuPM5ZxD6YLxmr0WLP0rOXlk",
keys
);
Notification notification = new Notification(subscription2, "Hello");
pushService.send(notification);
The work on the client side is done and it seems to be ok.
The keys are created with GenerateKeyCommand.java
I use localhost in my browser for tests.
What i am doing wrong?
Thx
Hi Martin,
so my use case i want to decrypt the webpush payload for automation. I have all keys server public private , and client p256dh and auth . how i will do that
Hey @martijndwars,
I've made a small http wrapper over your library for own needs, but thought it may be useful for other folks.
Cheers,
Bogdan
if i configure the JVM parameter with
-Dhttp.proxyHost=proxy.test.it -Dhttp.proxyPort=3128 -Dhttp.proxyUser=username -Dhttp.proxyPassword=passw
-Dhttps.proxyHost=proxy.test.it -Dhttps.proxyPort=3128 -Dhttps.proxyUser=username -Dhttps.proxyPassword=passw
but the autentication doesn't work.
the solution to work is:
HttpHost proxy = new HttpHost("proxy.test.it", 3128);
DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxy);
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(new AuthScope("proxy.test.it", 3128),
new UsernamePasswordCredentials("username", "passw"));
CloseableHttpAsyncClient closeableHttpAsyncClient = HttpAsyncClients.custom()
.setProxy(proxy)
.setRoutePlanner(routePlanner)
.setDefaultCredentialsProvider(credsProvider)
.build();
closeableHttpAsyncClient.start();
HttpResponse httpResponse = (HttpResponse) closeableHttpAsyncClient.execute(httpPost, new ClosableCallback(closeableHttpAsyncClient)).get();
Just a few things that aren't clear at once by reading the documentation is what the PublicKey and userAuth are.
I believe userAuth is the key generated by the push messaging service from the browser side. Is the PublicKey somehow our public key?
Also please confirm that the PushService's default constructor is to be used with non-chrome browsers (Firefox at the moment.). Seem to be the case but I'd prefer to confirm and update the docs.
I have a web app that is able to register subscriptions and send web pushes to chrome and firefox using node, but when I try to use those subscriptions with this library in java, I am getting Unauthorized Registration
.
My test is below, which is modeled on this test in the web-push repo.
If you have any ideas about how I could be screwing this up, I'd be much obliged.
@Test
public void testPushChromeVapid() throws Exception {
String endpoint = "https://fcm.googleapis.com/fcm/send/eKUKTbHcFbQ:APA91bFzJMkNQO1xHc2-JVcRRa4I76yKR9o4IvgJBx1eIyF1EordVbWbpyD5pxMZJfbjnmPo_EGU8yCATZbeypc2_hMZE3GutdJGqqFdjht7PhhaIGg2IwRdRtH8r0lSRK0wAN8bD00O";
// Base64 string user public key/auth
String userPublicKey = "BF1xKcbEKKydzY72hHTZOdlrGCK1OE2DLgcTA_qzOejXCAuPmP87MKgEVwaGsYjpbSIUyG2E4GxZYF74lWXG04w=";
String userAuth = "tRoRvuq0UZqzbT0lv3r3Cw==";
// Base64 string server public/private key
String vapidPublicKey = "BDML-FghkuCdr0U1AlPHycUDlmAio4xL2OeX2oC_-X1ArOWdqzFea2_h3pyqxvl2x633Y-RR7hWbpbCmP73qn58";
String vapidPrivateKey = "<redacted>";
// Construct notification
Notification notification = new Notification(endpoint, userPublicKey, userAuth, getPayload());
// Construct push service
PushService pushService = new PushService();
pushService.setSubject("mailto:[email protected]");
pushService.setPublicKey(Utils.loadPublicKey(vapidPublicKey));
pushService.setPrivateKey(Utils.loadPrivateKey(vapidPrivateKey));
// Send notification!
HttpResponse httpResponse = pushService.send(notification);
System.out.println(httpResponse.getStatusLine().getStatusCode());
System.out.println(IOUtils.toString(httpResponse.getEntity().getContent(), StandardCharsets.UTF_8));
}
A very similar attempt with a valid firefox subscription results in a 401 with a mozilla error code about a problem with the authorization header.
{
"code": 401,
"errno": 109,
"error": "Unauthorized",
"message": "Request did not validate Invalid Authorization Header",
"more_info": "http://autopush.readthedocs.io/en/latest/http.html#error-codes"
}
use https://web-push-codelab.glitch.me/ for getting keys and your sendPushMessage
method from UsageExample
I get 400 UnauthorizedRegistration
error.
Java code:
if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
Security.addProvider(new BouncyCastleProvider());
}
SubscriptionMy subscriptionMy = new SubscriptionMy(p256dh, auth, endpoint);
sendPushMessage(subscriptionMy, getPayload().getBytes(Charset.forName("UTF-8")));
public void sendPushMessage(SubscriptionMy sub, byte[] payload) throws GeneralSecurityException, InterruptedException, JoseException, ExecutionException, IOException {
// useGcm = true OR false -> same error
boolean useGcm = true;
Notification notification;
PushService pushService;
if (useGcm) {
// Create a notification with the endpoint, userPublicKey from the subscription and a custom payload
notification = new Notification(
sub.getEndpoint(),
sub.getKey(),
sub.getAuth(),
payload
);
// Instantiate the push service, no need to use an API key for Push API
pushService = new PushService();
} else {
// Or create a GcmNotification, in case of Google Cloud Messaging
notification = new Notification(
sub.getEndpoint(),
sub.getKey(),
sub.getAuth(),
payload
);
// Instantiate the push service with a GCM API key
pushService = new PushService(GCM_API_KEY);
}
// Send the notification
HttpResponse response = pushService.send(notification);
System.out.println(response);
}
public class SubscriptionMy {
private String key;
private String auth;
private String endpoint;
public SubscriptionMy(String key, String auth, String endpoint) {
this.key = key;
this.auth = auth;
this.endpoint = endpoint;
}
public String getEndpoint() {
return endpoint;
}
public void setAuth(String auth) {
this.auth = auth;
}
public String getAuth() {
return auth;
}
/**
* Returns the base64 encoded auth string as a byte[]
*/
public byte[] getAuthAsBytes() {
return Base64.getDecoder().decode(getAuth());
}
public void setKey(String key) {
this.key = key;
}
public String getKey() {
return key;
}
/**
* Returns the base64 encoded public key string as a byte[]
*/
public byte[] getKeyAsBytes() {
return Base64.getDecoder().decode(getKey());
}
/**
* Returns the base64 encoded public key as a PublicKey object
*/
public PublicKey getUserPublicKey() throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchProviderException {
KeyFactory kf = KeyFactory.getInstance("ECDH", BouncyCastleProvider.PROVIDER_NAME);
ECNamedCurveParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec("secp256r1");
ECPoint point = ecSpec.getCurve().decodePoint(getKeyAsBytes());
ECPublicKeySpec pubSpec = new ECPublicKeySpec(point, ecSpec);
return kf.generatePublic(pubSpec);
}
}
Im not use
getKeyAsBytesmethod because i get Exception
java.lang.IllegalArgumentException: Illegal base64 character 5f`
And Im not use
getUserPublicKeymethod because i get Exception
java.lang.IllegalArgumentException: Invalid point encoding 0x42`
Please. help me.
a) Not able to use API objects as params for web controller (which in most cases uses jackson and not gson)
b) Having to write custom dto objects introduces name clashes (Subscription, Notification etc.)
c) Having generated VAPID public key and private key I also have to provide subject, which should be optional as per https://tools.ietf.org/html/rfc7519#page-9.
P.S.:
SubscriptionKeys sk = originalSub.getKeys();
nl.martijndwars.webpush.Subscription.Keys keys = new nl.martijndwars.webpush.Subscription().new Keys(sk.getP256dh(), sk.getAuth());
nl.martijndwars.webpush.Subscription sub = new nl.martijndwars.webpush.Subscription();
sub.endpoint = originalSub.getEndpoint();
sub.keys = keys;
This is not flexible and is hard to read
I have used the same API and procedure to sent notification , I am able to send notification successfully with response code 200, but still push event is not happening on receiving notification.
{ auth:"hcQQq+1FeDuSu7V0zd5DXA==" endpoint:"https://fcm.googleapis.com/fcm/send/ cXgp0l3svNo:APA91bG8dDfZhrc0iaSyzvuV1BvnxXz9T- SmLCKOymKrEdwvrh0_SjzjnU3ORRKvW5QD- Zp196T5nAGPayR7EKu_Bkb0pQrSex7Q3DZSu54Lo83AEiUE6p-2Xn-nrquCymKVFt6Z4nY8" key:"BJv2qC3WSCsRszMi57vOBpFjnIpdJ/ uXQQFj4d0XZD9lRuZKuBgJNVFra0SFEvRlQQ88eG8RWWs7sSvO9Pbdkwk=" }
above given is my endpoint in which i am sending notification.
Since updating from 3.0.1 to 4.0.0 we are getting errors when sending GCM notifications. We were able to send them without supplying valid keys before but it's now failing on this assertion.
webpush-java/src/main/java/nl/martijndwars/webpush/PushService.java
Lines 173 to 174 in 87f2481
Maybe will be good to move
public class Keys {
public String p256dh;
public String auth;
public Keys() {
}
public Keys(String p256dh, String auth) {
this.p256dh = p256dh;
this.auth = auth;
}
}
to Keys.java class
hello..
I practice web-push in java.
How make public key in java?
Public key means applicationServerpublicKey.
Execution failed for task ':compileJava'.
Could not find tools.jar. Please check that C:\Program Files\Java\jre1.8.0_151 contains a valid JDK installation
I use java 8
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.