401 "Request did not validate missing authorization header" when header present
See original GitHub issueThis 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:admin@mysite.com'
}
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.
Issue Analytics
- State:
- Created 7 years ago
- Comments:12 (7 by maintainers)
OBE by #53 (Thanks!)
Yeah, it seems like some other people had this problem, reading this is where I thought something could be up with the signature: http://stackoverflow.com/questions/39336523/webpushvapid-request-fails-with-400-unauthorizedregistration
Edit: I tried my code with the example keys in test_vapid.py copied over and it didn’t work with same errors, which is highly confusing and makes me think there’s something wrong on my end. Not sure what could be going wrong - All tests passed on py_vapid on my setup too