Coder Social home page Coder Social logo

pywebpush's People

Contributors

arlopurcell avatar braedon avatar bwindels avatar capkovic avatar chris-v avatar flagboy avatar flimm avatar gladoskar avatar jbouzekri avatar jrconlin avatar kamotos avatar kilgoretrout1985 avatar mthu avatar natim avatar noyainrain avatar perosb avatar pjenvey avatar robbiet480 avatar safwanrahman avatar scyclops avatar ujjawal-garg avatar wu731642061 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pywebpush's Issues

UnauthorizedRegistration

Im trying to use pywebpush under python 2.7 (and 3.5) without any success. I am getting the error UnauthorizedRegistration with a 400 response code. Using the Push Companion, everything works just fine (with the same key and same subscription info).

Also, my internal clock is synced (some people reported having issues if your clock is not synced).

My code :

from pywebpush import WebPusher
import json

sub = json.loads('{"endpoint":"https://fcm.googleapis.com/fcm/send/<redacted>","keys":{"p256dh":"<redacted>","auth":"<redacted>"}}')
r = WebPusher(sub).send(data='hey')

Which returns :

> r.text
u'<HTML>\n<HEAD>\n<TITLE>UnauthorizedRegistration</TITLE>\n</HEAD>\n<BODY BGCOLOR="#FFFFFF" TEXT="#000000">\n<H1>UnauthorizedRegistration</H1>\n<H2>Error 400</H2>\n</BODY>\n</HTML>\n'
> r.status_code
400

I am getting the same result no matter which Python version I use.
Any help debugging this would be really really appreciated...

Default expiry of 24h may lead to errors

In my experience, the default expiry of 24hours might be causing errors on the push backends of Google and Mozilla. They reject the request, with Mozilla reporting that the expiry is too far in the future, probably due to slight clock differences.

I would suggest to reduce the default expiry time in order to avoid such problems.

'unicode' object has no attribute 'get'

Hey there, I'm trying to make a webpush call, but its giving me the error:
'unicode' object has no attribute 'get'
It looks like that error is being triggered by
url = urlparse(subscription_info.get('endpoint'))'
Any idea what might be causing this?

How to get Response on WebPushException

Is there any way to get the HTTP response code / or the response object on WebPushException.

Mozilla for example sends a 410 code when the subscription isn't valid anymore.
In this case I want to delete the subscription from my list.

raise WebPushException("Push failed: {}: {}".format( result, result.text))

You format the result to string which of course could be parsed. I wonder if there is a better solution.

Push Notification for Chrome

Hi @jrconlin

I am trying to send Push Notification to Chrome Browser using Pywebpush Library. But the call seems to be not working.

I am trying the following code:

subscription_info = {'endpoint': endpoint, 'keys': {'p256dh': p256dh_key, 'auth': auth_key}}
notify_data = {"data": "Hello"}
headers = {'Content-Type': 'application/json'}
gcm_key = "AIzaSXXXXXXXXXXXXXXXXXXXXX"
resp = WebPusher(subscription_info).send(notify_data, headers, 3600, gcm_key)

And I am getting this as the Error:
TypeError: send() takes at most 4 arguments (5 given)

Can you please suggest how can I use Pywebpush send() to send Push Notification to Chrome Browser ?

Thanks,

Pycrypto vs cryptography

I was just trying to pywebpush on appengine and one of the problems I was hitting is an issue with cryptography module:

ImportError: No module named cryptography.hazmat.bindings._constant_time

After googling it is either an issue with my setup (which generally has mixed solutions), or it could be appengine running in a weird environment / container that means the compiled library for my machine fails to work on App Engine.

Looking at the docs for AppEngine it looks like the make crypto library is pycrypto. I was just wondering if that could* be an option for this library?

I'm not a Python developer so if cryptography is the main module developers use then please close this issue, but if there is no strong opinion would you be open to taking a PR to switch?

Invalid TTL header

If TTL is specified (as an integer) then the associated header value is in error (since it's not a string).

Seems str(ttl) should be used?

        if 'ttl' not in headers or ttl:
            headers['ttl'] = str(ttl)

AttributeError: 'X509' object has no attribute '_x509'

screen shot 2016-12-15 at 3 42 12 pm
I have installed pywebpush globally. My code is below config.py
from pywebpush import WebPusher

subscription_info = {"endpoint":"https://android.googleapis.com/gcm/send/e8N4w87NpOE:APA91bFmYdTBaeROOmBbzKoHD6X6QsQfJEA_Jvrzbsgc0gm-6eKlJOb20H0CQ47v6_CLIXPstre6r-7X06ea_Vm_EtTkGMKAc_e2tBN7WhaiNzhspuKcr1IHKz6ucyxe8FWrvRXyFWwr","keys":{"p256dh":"BE0i3dGxDr4aJ0ACZ-JQtcPieaXZaAS1eYqRHP4kJKGzxNe8SEd8En_JtyY7ZEB8COPVUD4wM4AAzuGS7GZBvPY=","auth":"7Gg9jurx6AUPAwD3hA0ZwQ=="}}
data = "{test:'hello'}"
headers = {'Authorization' : 'key=firebase_server_key'}
gcm = 'firebase_server_key'
wp = WebPusher(subscription_info)
wp.send(data, headers,ttl=0,gcm_key=gcm)

my python version 2.7.10

When I tried to run the above code giving error

Handle an empty payload

Webpush supports sending empty payloads.
For most use case we have with Kinto it makes sense to just try to resync on push notifications and not worry about any payload.

It would be nice for pywebpush to handle send(data=None )

Problem with private_key.pem

I have done some tests with push notification and works. But when I integrate with django, I get this error:

File "/Users/myuser/.virtualenvs/myenv/lib/python3.6/site-packages/pywebpush/__init__.py", line 359, in webpush
    vv = Vapid.from_string(private_key=vapid_private_key)
  File "/Users/myuser/.virtualenvs/myenv/lib/python3.6/site-packages/py_vapid/__init__.py", line 142, in from_string
    return cls.from_der(pkey)
  File "/Users/myuser/.virtualenvs/myenv/lib/python3.6/site-packages/py_vapid/__init__.py", line 99, in from_der
    backend=default_backend())
  File "/Users/myuser/.virtualenvs/myenv/lib/python3.6/site-packages/cryptography/hazmat/primitives/serialization.py", line 28, in load_der_private_key
    return backend.load_der_private_key(data, password)
  File "/Users/myuser/.virtualenvs/myenv/lib/python3.6/site-packages/cryptography/hazmat/backends/multibackend.py", line 323, in load_der_private_key
    return b.load_der_private_key(data, password)
  File "/Users/myuser/.virtualenvs/myenv/lib/python3.6/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 1018, in load_der_private_key
    password,
  File "/Users/myuser/.virtualenvs/myenv/lib/python3.6/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 1160, in _load_key
    self._handle_key_loading_error()
  File "/Users/myuser/.virtualenvs/myenv/lib/python3.6/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 1229, in _handle_key_loading_error
    raise ValueError("Could not deserialize key data.")
ValueError: Could not deserialize key data.

Why?

pywebpush Issue

Hi @jrconlin

I am trying to use PyWebpush Library in my python code and I am seeing these 3 kind of issues on the server side logs for chrome notifications(working absolutely fine in all cases on local server):

  1. ConnectionError(ProtocolError('Connection aborted.', error(0, 'Error')),)
  2. '[OpenSSL] EC_KEY_generate_key FAIL ... error:00000000:lib(0):func(0):reason(0)',)
    [Occurs for this line:
    encoded = WebPusher(subscription_info).encode(json.dumps(data))]
  3. extern "Python": function Cryptography_rand_bytes() called, but @ffi.def_extern() was not called in the current subinterpreter. Returning 0.

Can you please suggest how can these issues be resolved ?

Thanks,

Parse aud from endpoint in WebPusher

using the urlparse library:

aud_parsed = urlparse(_curr_user.push.subscription_info.endpoint)
aud = ("{}://{}").format(aud_parsed.scheme, aud_parsed.netloc)

<WebPusher object>.aud => https://fcm.googleapis.com (Or mozilla or whatever endpoint is defined)

Please add ttl to webpush function.

Please add ttl option to webpush function. It's too complicated to call WebPusher.
webpush function is great, but if I need to set TTL, then I can't use it.
Thank you.

401 "Request did not validate missing authorization header" when header present

This might be a StackOverflow-type question but I'm constantly getting 401 Unauthorized, errcode 109 (Invalid authentication) and message: "Request did not validate missing authorization header". I'm using VAPID headers to a Mozilla push endpoint as suggested in #30

I use this line to send the notification:
x = pywebpush.WebPusher(subscription_info).send(data, vapid_headers, 60*60)

The authorization header appears to be present (logged x.request.headers):
{ 'Accept': '*/*', 'authorization': 'WebPush eyJ0eXAiOi...', 'crypto-key': "p256ecdsa=b'Nz2H1lIDt...7b7OAfMA-bwZP6qk_WonOnahzw7iDx4rA';keyid=p256dh;dh=BCvGo_YbulU_xUnT-U...", 'ttl': '3600', 'Accept-Encoding': 'gzip, deflate', 'content-encoding': 'aesgcm', 'encryption': 'keyid=p256dh;salt=azMk5vK0...', 'User-Agent': 'python-requests/2.11.1', 'Connection': 'keep-alive', 'Content-Length': '370' }

The lengthy details (sorry) below show what I do:
subscription_info = {'endpoint': 'https://updates.push.services.mozilla.com/wpush/v2/gAA...', 'keys': {'p256dh': 'BJv7nI...p31z4Qvt86+oeQMfZk5Nb/fhko...wmPXvo99A=', 'auth': '2Y4...+WA=='}}

data = json.loads({'abc': 'def'})

vapid_headers = _make_vapid_headers(endpoint) (endpoint is from subscription_info)

Relevant definitions below (and possibly where an error lies, as I attempted to fix an issue I got in python3 running the original code from https://blog.mozilla.org/services/2016/04/04/using-vapid-with-webpush/ )

# generated with openssl ecparam -name prime256v1 -genkey -noout -out vapid_private.pem
VAPID_PRIVATE_KEY_PATH = 'vapid_private.pem' 
priv_key = open(VAPID_PRIVATE_KEY_PATH, 'r', encoding='utf-8').read()
VAPID_PRIVATE_KEY_CONTENTS = SigningKey.from_pem(priv_key)  # from ecdsa import SigningKey

# As seen in https://blog.mozilla.org/services/2016/04/04/using-vapid-with-webpush/
def _make_jwt(header, claims, key):
    vk = key.get_verifying_key()
    jwt = jws.sign(
        claims,
        key,
        algorithm=header.get('alg', 'ES256')).strip('=')
    raw_public_key = b'\x04' + vk.to_string()  # need to work with bytes
    public_key = base64.urlsafe_b64encode(raw_public_key).strip(b'=')
    return (jwt, public_key)

def _make_vapid_headers(endpoint):
    header = {'typ': 'JWT', 'alg': 'ES256'}
    origin = endpoint.split('.com')[0] + '.com'
    claims = {
        'aud': origin,
        'exp': '{}'.format(int(time()) + 60*60*12),  # import time from time
        'sub': 'mailto:[email protected]'
    }

    my_key = settings.VAPID_PRIVATE_KEY_CONTENTS
    (jwt, public_key) = _make_jwt(header, claims, my_key)

    headers = {
        'Authorization': 'WebPush {}'.format(jwt),
        'Crypto-Key': 'p256ecdsa={}'.format(public_key)
    }
    return headers

I followed the instructions for getting the public key to send to the frontend from https://blog.mozilla.org/services/2016/08/23/sending-vapid-identified-webpush-notifications-via-mozillas-push-service/ where I removed -----BEGIN PUBLIC KEY, made the key urlsafe, etc.

PushManager.subscribe() needs applicatonServerKey option.

Please check the following links:
https://tools.ietf.org/html/draft-thomson-webpush-vapid-02#page-6
https://developer.mozilla.org/en-US/docs/Web/API/PushManager/subscribe

I believe option is necessary to send encrypted messages.

The server key is currently used for WebPusher.encode()

The comment says


The server key is an ephemeral ECDH key used only for this transaction

However, I believe this key is not only for this transaction but also for the subscribe method.

Use RFC 8188 standard encoding "aes128gcm"

RFC 8188 has been out for over a year. It's high time to set the default encoding method to "aes128gcm".

Be aware that support for the RFC draft "aesgcm" content encoding may be terminated without warning.

Not able to install pywebpush

Hello all, I am trying to install pywebpush using pip install pywebpush but I am unable to do so. I am getting following error.

kapil@sohan:~/Projects/pywebpush$ pip install pywebpush
Downloading/unpacking pywebpush
  Downloading pywebpush-1.0.5.tar.gz
  Running setup.py (path:/tmp/pip_build_kapil/pywebpush/setup.py) egg_info for package pywebpush
    
Downloading/unpacking cryptography>=1.8.1,<1.10 (from pywebpush)
  Downloading cryptography-1.9.tar.gz (409kB): 409kB downloaded
  Running setup.py (path:/tmp/pip_build_kapil/cryptography/setup.py) egg_info for package cryptography
    
    no previously-included directories found matching 'docs/_build'
    warning: no previously-included files matching '*' found under directory 'vectors'
Downloading/unpacking http-ece>=1.0.1 (from pywebpush)
  Downloading http_ece-1.0.2.tar.gz
  Running setup.py (path:/tmp/pip_build_kapil/http-ece/setup.py) egg_info for package http-ece
    error in http_ece setup command: 'install_requires' must be a string or list of strings containing valid project/version requirement specifiers
    Complete output from command python setup.py egg_info:
    error in http_ece setup command: 'install_requires' must be a string or list of strings containing valid project/version requirement specifiers

----------------------------------------
Cleaning up...
Command python setup.py egg_info failed with error code 1 in /tmp/pip_build_kapil/http-ece
Storing debug log for failure in /tmp/tmpaWU6LN

And complete log file is error.log

And if I try to install it as it said in the README file I get this error

I am unable to install it by any way.

Depend on any version of `requests`

Is there a reason that pywebpush depends on specific version of requests?

When I run pip check after upgrading requests, I get this error:

$ pip check
pywebpush 1.0.2 has requirement requests==2.13.0, but you have requests 2.14.2.

Is there a reason that install_requires in setup.py pins the dependencies to certain version numbers? (Related: install_requires vs Requirements files)

Integration Tests

If you are open to the idea, I'd be interested in adding integration tests for Chrome and Firefox for pywebpush using web-push-testing-service.

It's a node script that starts a server that accepts REST api calls, you can then request starting of a browser, getting a subscription and then request the last push received (i.e. after you sent a push message, request what was received).

UnauthorizedRegistration when sending a Chrome notification

The node cli app works fine:

web-push send-notification \
--endpoint="https://fcm.googleapis.com/fcm/send/<ENDPOINT>" \
--key="<KEY>" \
--auth="<AUTH>" \
--vapid-subject="mailto:[email protected]" \
--vapid-pubkey="<VAPID_PUBKEY>" \
--vapid-pvtkey="<VAPID_PRIVATEKEY>" \
--payload='{"version":"1"}'

but pywebpush fails using the same keys:

subscription_info = {
    'endpoint': 'https://fcm.googleapis.com/fcm/send/<ENDPOINT>',
    'keys': {
        'auth': '<AUTH>',
        'p256dh': '<KEY>',
    }
}
webpush(
    subscription_info,
    json.dumps({'version': '1'}),
    vapid_private_key='<VAPID_PRIVATEKEY>',
    vapid_claims={
        'sub': 'mailto:[email protected]'
    },
)

throws an exception:

Push failed: <Response [400]>: <HTML>
<HEAD>
<TITLE>UnauthorizedRegistration</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000">
<H1>UnauthorizedRegistration</H1>
<H2>Error 400</H2>
</BODY>
</HTML>

Chrome returning 400, Firefox working fine

Using chrome version 57. Get 400s with chrome and not on Firefox. Have tried just about everything under the sun. I know there have complaints about this before. Any solutions to the problems before?

Installing Pywebpush

Hi @jrconlin ,

I am trying to use Pywebpush Library in my Project.
When I try:

    from pywebpush import WebPusher
    resp = WebPusher(subscription_info).send(data, headers)

this code works

But if I try:
from pywebpush import WebPush

It doesn't work. Can you please suggest how can I use WebPush for just encrypting the Data (and not sending the actual notification)?

Thanks,

Issues with cryptography==1.8.2

cryptography 1.8.2 will not compile with libressl because of some bugs that was fixed on 1.9.0. Is it possible to change requirements.txt to use cryptography>=1.8.2 so the latest will be used?

Data only sends "title"

I am trying to send this block as notification:

{
"title": "Hello",
"body": "World",
"renotify": true
}

But it gets compiled into:
{"notification":{"title":"{'renotify': True, 'title': 'Hello', 'body': 'World'}"}}

Please advise

Request did not validate missing authorization header

When trying to send a push message to a firefox endpoint I get this error no matter what I try:

Traceback (most recent call last):
  File "/Users/Lieuwe/projects/hydra/venv/lib/python3.5/site-packages/channels/worker.py", line 119, in run
    consumer(message, **kwargs)
  File "/Users/Lieuwe/projects/hydra/venv/lib/python3.5/site-packages/channels/sessions.py", line 78, in inner
    return func(*args, **kwargs)
  File "/Users/Lieuwe/projects/hydra/venv/lib/python3.5/site-packages/channels/auth.py", line 42, in inner
    return func(message, *args, **kwargs)
  File "/Users/Lieuwe/projects/wendchat/consumers.py", line 61, in ws_message
    getattr(message_handlers, cmd)(message, data)
  File "/Users/Lieuwe/projects/wendchat/message_handlers.py", line 142, in on_message
    send_push_message(target, "Hallo wereld!")
  File "/Users/Lieuwe/projects/wendchat/methods.py", line 123, in send_push_message
    vapid_claims=chat_settings.CHAT_VAPID_CLAIM
  File "/Users/Lieuwe/projects/hydra/venv/lib/python3.5/site-packages/pywebpush/__init__.py", line 370, in webpush
    result, result.text))
pywebpush.WebPushException: Push failed: <Response [401]>: {"code": 401, "errno": 109, "error": "Unauthorized", "more_info": "http://autopush.readthedocs.io/en/latest/http.html#error-codes", "message": "Request did not validate missing authorization header"}

I'm generating the vapid keys as follows:

vapid = Vapid()
vapid.generate_keys()
vapid.save_key('vapid.private.pem')
vapid.save_public_key(vapid.public.pem)

The client then returns a subscription like

{"endpoint":"https://updates.push.services.mozilla.com/wpush/v2/gAAAAABaJRho_CagHOmnZA_qWzmKYyHuKCLL5cWTgNPZ8kx9AN6eKoyTr-sQYxcfmLnx_ddeE3GhlCgvELYu4a8sFOAihmCf0PzF_uaVMcAmOr7z1O8RKk006sEnK0qOULpumVOkMWQB1y237gQodOl686nwVvfefYHnVh_rY73f_jh8pLod-iY","keys":{"auth":"ImHBySkqpnaySV_PUbGKzQ","p256dh":"BOghS7L240dUayNDc0NP8jI-iEqLBWFOqElCRJyWyLEDEezNYwtyobd5JUFPv536o_YiB_zUwT8RRJLYYZXRaAM"}}

And I send a push notification like this

webpush(
                json.loads(sub.info),
                message,
                vapid_private_key='vapid.private.pem',
                vapid_claims=CHAT_VAPID_CLAIM = {"sub": "mailto:<redacted>", 'aud': 'https://localhost:8000'}
            )

When dumping the sent request using the curl option I do see an authorization header, so I'm not sure why the error is complaining about that header missing.

Any help would be greatly appreciated.

webpush modifies the vapid_claims parameter

I have an object in my Django config for vapid claims and I'm using it in the webpush method.

I couldn't realize why after sending push messages on Firefox I was constantly getting "unauthorized registration" errors on Chrome, until I saw that the object passed as vapid_claims parameter gets modified from something like this:

{
    'sub': 'mailto:<my_email>'
}

to this :

{
    'aud': 'https://updates.push.services.mozilla.com',
    'exp': '1508309139',
    'sub': 'mailto:<my_email>'
}

I tried passing every time a new object and everything works fine, but now I'm wondering, is this expected behavior, and am I supposed to store that modified object?

When using the WebPusher object, use a dedicated function to change its subscription_info

Use case
I'm using this lib and especially the WebPusher object to send Vapid Web Push.
Why don't I use the webpush function ? Because my app can use the same WebPusher instance throughout its entire lifetime. That is why, for optimisation reason, I prefer using the same requests.Session() object each time I need WebPush.
The issue is that the subscription_info changes almost every time but I don't want to instanciate a new WebPusher;

Current workaround
in my wrapper, I have this method :

    def _update_subscription_info(self, subscription_info):
        # Here we naively copy the operations linked to subscription_info
        # from WebPusher.__init__()
        # aka validate subscription_info and store keys
        # Mandatory because subscription_info keeps changing
        if 'endpoint' not in subscription_info:
            raise WebPushException(
                "subscription_info missing endpoint URL"
            )
        self.webpusher.subscription_info = deepcopy(subscription_info)
        self.webpusher.auth_key = self.webpusher.receiver_key = None
        if 'keys' in subscription_info:
            keys = self.webpusher.subscription_info['keys']
            for k in ['p256dh', 'auth']:
                if keys.get(k) is None:
                    raise WebPushException(
                        "Missing keys value: {}".format(k))
                if isinstance(keys[k], six.string_types):
                    keys[k] = bytes(keys[k].encode('utf8'))
            receiver_raw = base64.urlsafe_b64decode(
                self.webpusher._repad(keys['p256dh']))
            if len(receiver_raw) != 65 and receiver_raw[0] != "\x04":
                raise WebPushException("Invalid p256dh key specified")
            self.webpusher.receiver_key = receiver_raw
            self.webpusher.auth_key = base64.urlsafe_b64decode(
                self.webpusher._repad(keys['auth']))

which is quite a dirty hack as it's just a copy/paste.

Question
Would you implement such a method in a more graceful way directly in the WebPusher, in order to simply be able to do a my_web_pusher.update_subscription_info(subscription_info) ?

If needed, I could spend a bit of time to suggest a PR.

Fix keyid handler for aes128gcm

Currently the keyid for aes128gcm is being passed as base64 encoded instead of raw values. We shouldn't pass a keyid at all, really.

Getting an SSLError

When I try to get push messaging to clients working I get the following error produced by OpenSSL probably.

Traceback (most recent call last):
  File "manage.py", line 22, in <module>
    execute_from_command_line(sys.argv)
  File "/usr/local/lib/python2.7/dist-packages/django/core/management/__init__.py", line 367, in execute_from_command_line
    utility.execute()
  File "/usr/local/lib/python2.7/dist-packages/django/core/management/__init__.py", line 359, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/usr/local/lib/python2.7/dist-packages/django/core/management/base.py", line 294, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/usr/local/lib/python2.7/dist-packages/django/core/management/base.py", line 345, in execute
    output = self.handle(*args, **options)
  File "/home/sem/scorpios-web/ScorpiosWeb/sc/management/commands/updateborrels.py", line 36, in handle
    webpush(subscription_info, data=str(message), vapid_private_key=vapid_path, vapid_claims=claims)
  File "/usr/local/lib/python2.7/dist-packages/pywebpush/__init__.py", line 356, in webpush
    curl=curl,
  File "/usr/local/lib/python2.7/dist-packages/pywebpush/__init__.py", line 288, in send
    headers=headers)
  File "/usr/local/lib/python2.7/dist-packages/requests/api.py", line 112, in post
    return request('post', url, data=data, json=json, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/requests/api.py", line 58, in request
    return session.request(method=method, url=url, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/requests/sessions.py", line 513, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/local/lib/python2.7/dist-packages/requests/sessions.py", line 623, in send
    r = adapter.send(request, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/requests/adapters.py", line 514, in send
    raise SSLError(e, request=request)
requests.exceptions.SSLError: ("bad handshake: Error([('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE', 'certificate verify failed')],)",)
import os
from datetime import date
from pywebpush import webpush, WebPushException, WebPusher
from django.core.management import BaseCommand

from sc.models import PushSubscription
from sc.models.Drinks import DrinksDag, DrinksEvening


class Command(BaseCommand):
    help = 'Cronjob to automatically update this drinks evening'

    def handle(self, *args, **options):
        now = date.today()
        drinks_day = DrinksDay.get_is_drinks_date(now)
        if drinks_day:
            DrinksEvening(date=now).save()
            if not drinks_day.is_recurring():
                drinks_day.delete()

            devices = PushSubscription.objects.all()

            for device in devices:
                subscription_info = {'endpoint': device.endpoint, 'keys': {'auth': device.auth, 'p256dh': device.p256dh}}
                message_title = "Drinks evening update"
                message_body = "Good evening participant"

                message = {'title': message_title, 'body': message_body}
                try:
                    vapid_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../../../private_key.pem')
                    claims = {'sub': '[email protected]', 'aud': 'https://fcm.googleapis.com'}

                    webpush(subscription_info, data=str(message), vapid_private_key=vapid_path, vapid_claims=claims)
                except WebPushException as e:
                    print("Unable to webpush: {}", repr(e))

My endpoint is in the form of https://fcm.googleapis.com/fcm/send/ { private endpoint }.

Do you have an idea what is going wrong, I have generated the private_key.pem with this vapid library (python) and I also generated the application server public key and pasted that in the javascript client side. Thanks

Requests requirement.

Requests is a popular requirement. By pinning the version you require all other packages that want to depend on you to use the same version. Could the requirement be made more flexible?

And now as a counter argument to this request, pywebpush currently does not work with Requests 2.11.0 due to the following change:

Some previous releases accidentally accepted non-strings as acceptable header values. This release does not.

This breaks as ttl header defaults to the integer 0.

VAPID r3 support

VAPID r3 introduces a content type of "application/webpush-options+json".

May add an option to use this, but depends on how strict push services are about content types.

403 MismatchSenderId

Any idea how to solve or debug this error? I'm using the latest version from master.

https://stackoverflow.com/questions/53875035/how-to-fix-403-mismatchsenderid-when-sending-web-push-notifications

I get the following traceback:

pytest test_push.py
====================================================== test session starts =======================================================
platform darwin -- Python 3.6.2, pytest-3.9.1, py-1.7.0, pluggy-0.8.0
rootdir: /Users/kayibal/Downloads, inifile:
plugins: django-3.4.3
collected 1 item

test_push.py F                                                                                                             [100%]

============================================================ FAILURES ============================================================
___________________________________________________________ test_push ____________________________________________________________

subs = {'endpoint': 'https://fcm.googleapis.com/fcm/send/cvNVGGLtZVo:APA91bFqfRXSHhqdzv6MXFKu7SFUvqyPSRlSNxER2B9cIj5OQZAC1THz...w1dNBzuNYFG7FMA', 'p256dh': 'BDz4O5Lb96W133iNj7uEmN0nnZuCDQKg8DTqa4P50stLUJ0vXBhwLker4EyMtf_U2Hr-UFf084QCxwZSR_3F70A'}}
vapid_data = {'privateKey': 'Ew2kli-56Ps6FEspgshs9MnFhhuX2mlMdXqhZqisN5w', 'publicKey': 'BEtyWjkXAXTOTN-5X018konhbR5KpAaQbM4jcWptLDzO2Ia-tm93NCY72TMh5kYAjYDThYY40FGh2BFHJeSX-04', 'subject': 'mailto:[email protected]'}

    def test_push(subs, vapid_data):
        webpush(subs,
                'Your Push Payload Text',
                vapid_private_key=vapid_data['privateKey'],
                vapid_claims={"sub": "mailto:[email protected]"},
>               ttl=2419200,
                )

test_push.py:27:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

subscription_info = {'endpoint': 'https://fcm.googleapis.com/fcm/send/cvNVGGLtZVo:APA91bFqfRXSHhqdzv6MXFKu7SFUvqyPSRlSNxER2B9cIj5OQZAC1THz...w1dNBzuNYFG7FMA', 'p256dh': 'BDz4O5Lb96W133iNj7uEmN0nnZuCDQKg8DTqa4P50stLUJ0vXBhwLker4EyMtf_U2Hr-UFf084QCxwZSR_3F70A'}}
data = 'Your Push Payload Text', vapid_private_key = 'Ew2kli-56Ps6FEspgshs9MnFhhuX2mlMdXqhZqisN5w'
vapid_claims = {'aud': 'https://fcm.googleapis.com', 'exp': 1548326836, 'sub': 'mailto:[email protected]'}
content_encoding = 'aes128gcm', curl = False, timeout = None, ttl = 2419200

    def webpush(subscription_info,
                data=None,
                vapid_private_key=None,
                vapid_claims=None,
                content_encoding="aes128gcm",
                curl=False,
                timeout=None,
                ttl=0):
        """
            One call solution to endcode and send `data` to the endpoint
            contained in `subscription_info` using optional VAPID auth headers.

            in example:

            .. code-block:: python

            from pywebpush import python

            webpush(
                subscription_info={
                    "endpoint": "https://push.example.com/v1/abcd",
                    "keys": {"p256dh": "0123abcd...",
                             "auth": "001122..."}
                     },
                data="Mary had a little lamb, with a nice mint jelly",
                vapid_private_key="path/to/key.pem",
                vapid_claims={"sub": "[email protected]"}
                )

            No additional method call is required. Any non-success will throw a
            `WebPushException`.

        :param subscription_info: Provided by the client call
        :type subscription_info: dict
        :param data: Serialized data to send
        :type data: str
        :param vapid_private_key: Vapid instance or path to vapid private key PEM \
                                  or encoded str
        :type vapid_private_key: Union[Vapid, str]
        :param vapid_claims: Dictionary of claims ('sub' required)
        :type vapid_claims: dict
        :param content_encoding: Optional content type string
        :type content_encoding: str
        :param curl: Return as "curl" string instead of sending
        :type curl: bool
        :param timeout: POST requests timeout
        :type timeout: float or tuple
        :param ttl: Time To Live
        :type ttl: int
        :return requests.Response or string

        """
        vapid_headers = None
        if vapid_claims:
            if not vapid_claims.get('aud'):
                url = urlparse(subscription_info.get('endpoint'))
                aud = "{}://{}".format(url.scheme, url.netloc)
                vapid_claims['aud'] = aud
            if not vapid_claims.get('exp'):
                # encryption lives for 12 hours
                vapid_claims['exp'] = int(time.time()) + (12 * 60 * 60)
            if not vapid_private_key:
                raise WebPushException("VAPID dict missing 'private_key'")
            if isinstance(vapid_private_key, Vapid):
                vv = vapid_private_key
            elif os.path.isfile(vapid_private_key):
                # Presume that key from file is handled correctly by
                # py_vapid.
                vv = Vapid.from_file(
                    private_key_file=vapid_private_key)  # pragma no cover
            else:
                vv = Vapid.from_string(private_key=vapid_private_key)
            vapid_headers = vv.sign(vapid_claims)
        response = WebPusher(subscription_info).send(
            data,
            vapid_headers,
            ttl=ttl,
            content_encoding=content_encoding,
            curl=curl,
            timeout=timeout,
        )
        if not curl and response.status_code > 202:
            raise WebPushException("Push failed: {} {}".format(
                response.status_code, response.reason),
>               response=response)
E           pywebpush.WebPushException: WebPushException: Push failed: 403 MismatchSenderId

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.