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

401 Unauthorized: authorization header must be specified #293

Closed
9 tasks done
stephanvierkant opened this issue Sep 7, 2020 · 14 comments
Closed
9 tasks done

401 Unauthorized: authorization header must be specified #293

stephanvierkant opened this issue Sep 7, 2020 · 14 comments

Comments

@stephanvierkant
Copy link
Contributor

stephanvierkant commented Sep 7, 2020

  • I have read the README entirely
  • I have verified in the issues that my problem hasn't already been resolved

Setup

  • Operating System: Linux
  • PHP Version: 7.4
  • web-push-php Version: <6.0.0>

Please check that you have installed and enabled these PHP extensions :

  • gmp
  • mbstring
  • curl
  • openssl

Please select any browsers that you are experiencing problems with:

  • CLI

Features Used

  • VAPID Support
  • Sending with Payload

Problem

As of v6.0.0, I get a 401 Unauthorized when sending a push notification:

Client error: POST https://fcm.googleapis.com/fcm/send/.... resulted in a 401 Unauthorized response: authorization header must be specified.

I'm using minishlink/web-push-bundle and everything worked perfectly, but upgrading to v6 gives this problem. For Windows clients I get a curl timeout, for FCM I get this 401.

Any idea what causes this problem?

@Minishlink
Copy link
Member

Hi, can you try on v6.0.1 please?

@nico-martin
Copy link

nico-martin commented Sep 13, 2020

I have the same problem with v6.0.1

application.js

navigator.serviceWorker.getRegistration().then((registration) => {
  registration.pushManager
    .subscribe({
      userVisibleOnly: true,
        applicationServerKey: urlBase64ToUint8Array(
          WebPushVars.vapidPublcKey
        ),
      })
      .then((subscription) =>
        uploadSubscription(subscription)
      );
  });

push.php

$web_push = new WebPush();

$send_to_subscriptions = [ // onyl an example to show the structure
    [ 
        "endpoint" => "https://example.com/other/endpoint/of/another/vendor/abcdef...",
        "keys" => [
            'p256dh' => '(stringOf88Chars)',
            'auth' => '(stringOf24Chars)'
        ],
    ]
]

foreach ( $send_to_subscriptions as $subscription ) {
	$subscription                    = (array) $subscription;
	$subscription['contentEncoding'] = 'aesgcm';
	$web_push->queueNotification(
		Subscription::create( $subscription ),
		json_encode( $data )
	);
}

$success = [];
$failed  = [];
foreach ( $web_push->flush() as $report ) {
	$endpoint = $report->getRequest()->getUri()->__toString();
	if ( $report->isSuccess() ) {
		$success[] = [
			'id' => self::id_from_endpoint( $endpoint ),
		];
	} else {
		$failed[] = [
			'id'     => self::id_from_endpoint( $endpoint ),
			'reason' => $report->getReason(),
		];
	}
}

@nico-martin
Copy link

In my understanding, if I create the push subscription with the publicKey, the subscription itself should be enough to authenticate against the push Service, right?
Or do I need to instanciate WebPush with my VAPID details?
Here is an exmple where I use WebPush with NodeJS. And there I need to set my VAPID Detail manually, explicitly, which makes sense. But I haven't found out how to set those in web-push-php:
https://github.com/hackantons/eurorelief-app-backend/blob/master/app/push/index.ts#L9-L13

@nico-martin
Copy link

nico-martin commented Sep 13, 2020

Even if I add VAPID settings to the Constructor

$web_push = new WebPush( [
    'VAPID' => self::get_vapid(),
] );

or to queueNotification

$web_push->queueNotification(
    Subscription::create( $subscription ),
    json_encode( $data ),
    [],
    [
        'VAPID' => self::get_vapid(),
    ]
);

it does not help. Still 401 for Chrome and Firefox Subscriptions.

@stephanvierkant
Copy link
Contributor Author

Hi, can you try on v6.0.1 please?

Nope, still doesn't work :(

@nico-martin
Copy link

I just found out that this only happens on my local environment (MAMP). If I upload the exact same code to my remote host it works. @stephanvierkant, could this be the same on your system?

@stephanvierkant
Copy link
Contributor Author

Nope, it doesn't work either. But my CI, local system and production system are quite similar in my case. Maybe you could try to find what makes a difference between your local system and remote host?

@nico-martin
Copy link

@stephanvierkant, those are completely different systems.. remote it's a shared hosting where I don't have a lot of possibilities. But in that case I'm sure it depends on some system settings..

@nonovd
Copy link

nonovd commented Sep 21, 2020

@nico-martin Could the difference between your environments be about GMP and/or BCMath PHP extensions ?

@digilist
Copy link

digilist commented Sep 23, 2020

I am getting the same error. (I am not sure if my observation is related to this issue in general or has just the same error)

I did some debugging and noticed that the VAPID header is not calculated when there is no content encoding. Adding a content encoding helped:

if (array_key_exists('VAPID', $auth) && $contentEncoding) {

I am not sure if the content encoding is always required, even if no payload is sent, but the example in the README doesn't do it.

This is the code I was using for my tests:

$notifications = [
    [
        'subscription' => Subscription::create([
            'endpoint' => 'https://fcm.googleapis.com/fcm/send/dL....',
//            'contentEncoding' => 'aesgcm',
        ]),
        'payload' => null,
    ],
];

$auth = [
    'VAPID' => [
        'subject' => 'mailto:foo@bar.de',
        'publicKey' => 'BFF3IX....',
        'privateKey' => 'Mrl3....',
    ],
];
$webPush = new WebPush($auth);

(For me it looks like google requires the VAPID to accept the notification, otherwise the mentioned error is returned)

UPDATE: For Firefox it works without the contentEncoding and without a VAPID header, but Google seems to require it.

UPDATE2: Now that I used the whole payload that I get when I encode the subscription to JSON (including the keys) array it works again (at first I used only the URL like in the example). With the keys property the contentEncoding is then set automatically.

@nico-martin
Copy link

Strange. With encoding it works for me in Chrome, but not in Firefox:

{
    "endpoint":"https://fcm.googleapis.com/fcm/send/{...}",
    "expirationTime":null,
    "keys":{
        "p256dh":"{...}",
        "auth":"{...}"
    },
    "contentEncoding":"aes128gcm"
}

@veldenb
Copy link

veldenb commented Oct 23, 2020

I think it might be a bug in the bundle: Minishlink/web-push-bundle#19 (comment)
In my case the VAPID-keys where not added to the library.

@stephanvierkant
Copy link
Contributor Author

Thanks @veldenb for pointing out. I've created a PR in the bundle repository.

@pericodes
Copy link

I am getting the same error. (I am not sure if my observation is related to this issue in general or has just the same error)

I did some debugging and noticed that the VAPID header is not calculated when there is no content encoding. Adding a content encoding helped:

if (array_key_exists('VAPID', $auth) && $contentEncoding) {

I am not sure if the content encoding is always required, even if no payload is sent, but the example in the README doesn't do it.

This is the code I was using for my tests:

$notifications = [
    [
        'subscription' => Subscription::create([
            'endpoint' => 'https://fcm.googleapis.com/fcm/send/dL....',
//            'contentEncoding' => 'aesgcm',
        ]),
        'payload' => null,
    ],
];

$auth = [
    'VAPID' => [
        'subject' => 'mailto:foo@bar.de',
        'publicKey' => 'BFF3IX....',
        'privateKey' => 'Mrl3....',
    ],
];
$webPush = new WebPush($auth);

(For me it looks like google requires the VAPID to accept the notification, otherwise the mentioned error is returned)

UPDATE: For Firefox it works without the contentEncoding and without a VAPID header, but Google seems to require it.

UPDATE2: Now that I used the whole payload that I get when I encode the subscription to JSON (including the keys) array it works again (at first I used only the URL like in the example). With the keys property the contentEncoding is then set automatically.

That worked for me in Chrome. I just needed to add the VAPID to the constructor as you mentioned and the encoding to the subscription .

Here is my code:

$auth = [
    'VAPID' => [
        'subject' => 'mailto:foo@bar.de',
        'publicKey' => '<My public key>',
        'privateKey' => '<My private key>',
    ],
];
$webPush = new WebPush($auth);
$subscription = json_decode('<My subscription json>', true);
$report = $webPush->sendOneNotification(
    Subscription::create($subscription),
    '{"msg":"Hello World!"}' // optional (defaults null)
);

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

7 participants