Чтобы использовать Push API с VAPID, мне нужен applicationServerKey
:
serviceWorkerRegistration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: applicationServerKey // we've got it with getApplicationServerKey() defined below
});
Я генерирую его на стороне сервера с помощью Ruby:
ecdsa_private_key = OpenSSL::PKey::EC.new 'prime256v1'
ecdsa_private_key.generate_key
sender.vapid_private_key = ecdsa_private_key.to_pem
ecdsa_public_key = OpenSSL::PKey::EC.new ecdsa_private_key
ecdsa_public_key.private_key = nil
sender.vapid_public_key = ecdsa_public_key.to_pem
Затем я должен скачать его:
getApplicationServerKey: function () {
return new Promise(function (resolve, reject) {
var request = new Request('https://example.com/application_server_key');
fetch(request).then(function (response) {
response.text().then(function (base64) {
resolve(_.base64ToArrayBuffer(base64));
});
});
});
},
base64ToArrayBuffer: function (base64) {
var binary_string = window.atob(base64);
var len = binary_string.length;
var bytes = new Uint8Array(len);
for (var i = 0; i < len; i++) {
bytes[i] = binary_string.charCodeAt(i);
}
return bytes.buffer;
}
Ключ возвращается контроллером в виде строки base64:
ecdsa_public_key = OpenSSL::PKey.read @sender.vapid_public_key
base64 = Base64.encode64(ecdsa_public_key.public_key.to_bn.to_s(2))
render text: base64
Проблема в том, что Firefox возвращает эту ошибку, когда я вызываю pushManager.subscribe
:
DOMException [InvalidAccessError: "Invalid raw ECDSA P-256 public key."
code: 15
nsresult: 0x8053000f]
Любая помощь приветствуется.
ОБНОВЛЕНИЕ: это сводит меня с ума... Я также пробовал кодировать/декодировать в шестнадцатеричном формате вместо base64, но получаю ту же ошибку.
Из Руби:
$ ecdsa_public_key.to_text
=> "Private-Key: (256 bit)\npub: \n
04:28:a9:89:be:8a:a8:f2:f1:bf:ed:04:d2:28:e9:\n
70:e9:b7:f3:8c:3c:f7:20:dc:95:30:1a:72:77:66:\n
09:0d:29:f6:6c:6c:c8:45:6e:da:ac:05:d6:ff:43:\n
9a:66:d0:c3:4c:bc:4a:0f:a3:ad:e8:23:33:22:40:\n
20:9e:de:14:56\n
ASN1 OID: prime256v1\n
NIST CURVE: P-256\n"
$ ecdsa_public_key.public_key.to_bn.to_s 16
=> "0428A989BE8AA8F2F1BFED04D228E970E9B7F38C3CF720DC95301A727766090D29F66C6CC8456EDAAC05D6FF439A66D0C34CBC4A0FA3ADE823332240209EDE1456"
Как вы можете видеть, это ключ P-256 (я не знаю, почему он говорит «Закрытый ключ» вместо «Открытый ключ», но, как вы можете видеть из кода, который его генерирует, это открытый ключ).
Затем я загружаю шестнадцатеричную строку с помощью Javascript fetch
, и вот что я получаю:
0428A989BE8AA8F2F1BFED04D228E970E9B7F38C3CF720DC95301A727766090D29F66C6CC8456EDAAC05D6FF439A66D0C34CBC4A0FA3ADE823332240209EDE1456
Array [ "04", "28", "A9", "89", "BE", "8A", "A8", "F2", "F1", "BF", 55 more… ]
Uint8Array [ 4, 40, 169, 137, 190, 138, 168, 242, 241, 191, 55 more… ]
ArrayBuffer { byteLength: 65 } // I get it by calling .buffer on the Uint8Array
DOMException [InvalidAccessError: "Invalid raw ECDSA P-256 public key."
code: 15
nsresult: 0x8053000f]
Как видно из промежуточных шагов, которые я печатаю в консоли, ключ обрабатывается корректно. Однако я все еще получаю эту ошибку...
ОБНОВЛЕНИЕ 2: тот же код успешно работает в Chrome: мне удалось отправить уведомление с помощью VAPID. Вероятно, это ошибка Firefox.