Web Push Birlikte Çalışabilirliği Kazanır

Matt Gaunt
Joe Medley
Joe Medley

Chrome, Web Push API'sini ilk kez desteklediğinde Firebase Cloud Messaging (FCM (eski adıyla Google Cloud Messaging (GCM)) push hizmetini kullanıyordu. Bunun için kendi API'sini kullanmanız gerekir. Bu, Chrome'un Web Push API'si spesifikasyonunun hâlâ yazıldığı ve daha sonra, Web Push Protokolü'nün bulunmadığı bir zamanda kimlik doğrulamasını (yani iletiyi gönderen kişi olduğunu söylediği bir kişi) geliştiricilere Web Push API'sini sunmasını sağladı. İyi haber: artık bunların hiçbiri doğru değil.

FCM / GCM ve Chrome artık standart Web Push Protokolü'nü desteklemektedir. Ancak gönderen kimlik doğrulaması VAPID uygulanarak gerçekleştirilebilir. Bu, web uygulamanızın artık bir "gcm_sender_id" kimliğine ihtiyacı yoktur.

Bu makalede, ilk olarak FCM ile Web Push Protokolü'nü kullanmak için mevcut sunucu kodunuzu nasıl dönüştüreceğinizi açıklayacağım. Şimdi de istemci ve sunucu kodunuza VAPID'yi nasıl uygulayacağınızı göstereceğim.

FCM, Web Push Protokolü'nü destekler.

Biraz bağlam üzerinden başlayalım. Web uygulamanız bir push aboneliğine kaydolduğunda, push hizmetinin URL'si verilir. Sunucunuz, web uygulamanız aracılığıyla kullanıcınıza veri göndermek için bu uç noktayı kullanır. Chrome'da, VAPID'si olmayan bir kullanıcıya abone olursanız Chrome'da bir FCM uç noktası verilir. (VAPID'yi daha sonra ele alacağız). FCM, Web Push Protokolü'nü desteklemeden önce, URL'nin sonundan FCM kayıt kimliğini çıkarmanız ve bir FCM API isteği göndermeden önce başlığa yerleştirmeniz gerekiyordu. Örneğin, https://android.googleapis.com/gcm/send/ABCD1234 türündeki bir FCM uç noktasının kayıt kimliği "ABCD1234" olur.

FCM artık Web Push Protokolü'nü desteklediğine göre uç noktayı olduğu gibi bırakabilir ve URL'yi Web Aktarma Protokolü uç noktası olarak kullanabilirsiniz. (Bu da onu Firefox ile uyumlu hale getirecektir. Umarız gelecekteki tüm diğer tarayıcılardır.)

VAPID'ye geçmeden önce, sunucu kodumuzun FCM uç noktasını doğru şekilde işlediğinden emin olmamız gerekiyor. Aşağıda, Node'da bir push hizmetine istek göndermeyle ilgili bir örnek verilmiştir. FCM için API anahtarını istek başlıklarına eklediğimize dikkat edin. Diğer push hizmeti uç noktaları için bu gerekli değildir. 52 sürümünden önceki Chrome, Opera Android ve Samsung Tarayıcı uygulamaları için web uygulamanızın manifest.json dosyasına bir "gcm_sender_id" eklemeniz de zorunludur. API anahtarı ve gönderen kimliği, istekte bulunan sunucunun gerçekten alıcı kullanıcıya mesaj göndermesine izin verilip verilmediğini kontrol etmek için kullanılır.

const headers = new Headers();
// 12-hour notification time to live.
headers.append('TTL', 12 * 60 * 60);
// Assuming no data is going to be sent
headers.append('Content-Length', 0);

// Assuming you're not using VAPID (read on), this
// proprietary header is needed
if(subscription.endpoint
    .indexOf('https://android.googleapis.com/gcm/send/') === 0) {
    headers.append('Authorization', 'GCM_API_KEY');
}

fetch(subscription.endpoint, {
    method: 'POST',
    headers: headers
})
.then(response => {
    if (response.status !== 201) {
    throw new Error('Unable to send push message');
    }
});

Bunun FCM / GCM'nin API'sinde yapılan bir değişiklik olduğunu unutmayın. Bu nedenle, aboneliklerinizi güncellemeniz gerekmez. Üstbilgileri yukarıda gösterildiği gibi tanımlamak için sunucu kodunuzu değiştirmeniz yeterlidir.

Sunucu tanımlama için VAPID ile tanışın

VAPID, "Gönüllü Uygulama Sunucusu Tanımlama"nın yeni ve havalı kısa adıdır. Bu yeni spesifikasyon temel olarak uygulama sunucunuz ile push hizmeti arasında bir el sıkışmayı tanımlar ve push hizmetinin hangi sitenin mesaj gönderdiğini doğrulamasını sağlar. VAPID ile, push mesajı göndermek için FCM'ye özel adımlardan kaçınabilirsiniz. Artık Firebase projesine, gcm_sender_id veya Authorization başlığına ihtiyacınız yok.

Süreç oldukça basittir:

  1. Uygulama sunucunuz bir ortak/özel anahtar çifti oluşturur. Ortak anahtar, web uygulamanıza verilir.
  2. Kullanıcı aktarmaları almayı seçtiğinde ortak anahtarı, subscribe() çağrısının seçenekler nesnesine ekleyin.
  3. Uygulama sunucunuz bir push mesajı gönderdiğinde ortak anahtarla birlikte imzalı bir JSON Web Jetonu ekleyin.

Bu adımları ayrıntılı olarak inceleyelim.

Ortak/özel anahtar çifti oluşturma

Şifreleme konusunda çok kötüyüm. VAPID ortak/özel anahtarlarının biçimiyle ilgili spesifikasyondaki ilgili bölümü aşağıda bulabilirsiniz:

Uygulama sunucuları, P-256 eğrisi üzerinde eliptik eğri dijital imza (ECDSA) ile kullanılabilen bir imzalama anahtar çifti oluşturmalı ve korumalıdır.

Bunu nasıl yapacağınızı web push düğümü kitaplığında görebilirsiniz:

function generateVAPIDKeys() {
    var curve = crypto.createECDH('prime256v1');
    curve.generateKeys();

    return {
    publicKey: curve.getPublicKey(),
    privateKey: curve.getPrivateKey(),
    };
}

Ortak anahtarla abone olma

Bir Chrome kullanıcısını VAPID ortak anahtarıyla push bildirimine abone olmak için abone olma() yönteminin applicationServerKey parametresini kullanarak ortak anahtarı Uint8Array olarak iletmeniz gerekir.

const publicKey = new Uint8Array([0x4, 0x37, 0x77, 0xfe, …. ]);
serviceWorkerRegistration.pushManager.subscribe(
    {
    userVisibleOnly: true,
    applicationServerKey: publicKey
    }
);

Sonuçta ortaya çıkan abonelik nesnesindeki uç noktayı inceleyerek çalışıp çalışmadığını, kaynak fcm.googleapis.com ise çalışıp çalışmadığını anlayabilirsiniz.

https://fcm.googleapis.com/fcm/send/ABCD1234

Push mesajı gönderme

VAPID'yi kullanarak mesaj göndermek için bir Yetkilendirme üst bilgisi ve bir Şifreleme Anahtarı üstbilgisi olmak üzere iki ek HTTP üst bilgisi içeren normal bir Web Push Protokolü isteği göndermeniz gerekir.

Yetkilendirme üst bilgisi

Authorization üstbilgisi, önünde "WebPush" ifadesi bulunan imzalı bir JSON Web Jetonu'dur (JWT).

JWT, bir JSON nesnesini ikinci bir tarafla, gönderen tarafın imzalayabileceği ve alıcı tarafın imzanın beklenen gönderenden geldiğini doğrulayabileceği şekilde paylaşmanın bir yoludur. JWT'nin yapısı, aralarında tek bir nokta bulunan ve şifrelenmiş üç dizeden oluşur.

<JWTHeader>.<Payload>.<Signature>

JWT başlığı

JWT Başlığı, imzalama için kullanılan algoritma adını ve jetonun türünü içerir. VAPID için bu olmalıdır:

{
    "typ": "JWT",
    "alg": "ES256"
}

Bu daha sonra base64 URL'si kodlanır ve JWT'nin ilk bölümünü oluşturur.

Yük

Yük, aşağıdakileri içeren başka bir JSON nesnesidir:

  • Kitle ("aud")
    • Push hizmetinin kaynağı (sitenizin kaynağı DEĞİL). JavaScript'te kitleyi almak için şu işlemleri yapabilirsiniz: const audience = new URL(subscription.endpoint).origin
  • Geçerlilik Bitiş Tarihi ("exp")
    • Bu, isteğin süresi dolmuş olarak kabul edilmesi için geçen saniye sayısıdır. Bunun, istekte bulunulduktan sonraki 24 saat içinde (UTC) olması ZORUNLUDUR.
  • Konu ("alt")
    • Konu bir URL veya mailto: URL'si olmalıdır. Bu, push hizmetinin mesajı gönderenle iletişime geçmesi gerektiğinde bir iletişim noktası sağlar.

Örnek yük aşağıdaki gibi görünebilir:

{
    "aud": "http://push-service.example.com",
    "exp": Math.floor((Date.now() / 1000) + (12 * 60 * 60)),
    "sub": "mailto: my-email@some-url.com"
}

Bu JSON nesnesi, base64 URL'si ile kodlanmıştır ve JWT'nin ikinci bölümünü oluşturur.

İmza

İmza, kodlanmış başlık ve yükün bir noktayla birleştirilmesinin ve sonucun, daha önce oluşturduğunuz VAPID özel anahtarı kullanılarak şifrelenmesinden elde edilir. Sonucun kendisi başlığa bir noktayla eklenmelidir.

Üstbilgiyi ve yük JSON nesnelerini alıp sizin için bu imzayı oluşturan çeşitli kitaplıklar bulunduğundan bununla ilgili bir kod örneği göstermeyeceğim.

İmzalanmış JWT, Yetkilendirme üst bilgisi olarak kullanılır ve başına "WebPush" eklenir ve bu kod aşağıdaki gibi görünür:

WebPush eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJhdWQiOiJodHRwczovL2ZjbS5nb29nbGVhcGlzLmNvbSIsImV4cCI6MTQ2NjY2ODU5NCwic3ViIjoibWFpbHRvOnNpbXBsZS1wdXNoLWRlbW9AZ2F1bnRmYWNlLmNvLnVrIn0.Ec0VR8dtf5qb8Fb5Wk91br-evfho9sZT6jBRuQwxVMFyK5S8bhOjk8kuxvilLqTBmDXJM5l3uVrVOQirSsjq0A

Bu konuda birkaç şeye dikkat edin. İlk olarak, Yetkilendirme başlığı "WebPush" kelimesini içerir ve ardından bir boşluk ve ardından JWT gelmelidir. JWT başlığını, yükü ve imzayı ayıran noktalara da dikkat edin.

Şifreleme Anahtarı başlığı

Yetkilendirme üst bilgisinin yanı sıra VAPID ortak anahtarınızı da Crypto-Key başlığına p256ecdsa= içeren base64 URL kodlamalı bir dize olarak eklemeniz gerekir.

p256ecdsa=BDd3_hVL9fZi9Ybo2UUzA284WG5FZR30_95YeZJsiApwXKpNcF1rRPF3foIiBHXRdJI2Qhumhf6_LFTeZaNndIo

Şifrelenmiş veri içeren bir bildirim gönderirken zaten Crypto-Key üstbilgisini kullanıyor olursunuz. Bu nedenle, uygulama sunucusu anahtarını eklemek için yukarıdaki içeriği eklemeden önce bir noktalı virgül eklemeniz yeterlidir. Bu işlem sonucunda şunlar olur:

dh=BGEw2wsHgLwzerjvnMTkbKrFRxdmwJ5S_k7zi7A1coR_sVjHmGrlvzYpAT1n4NPbioFlQkIrTNL8EH4V3ZZ4vJE;
p256ecdsa=BDd3_hVL9fZi9Ybo2UUzA284WG5FZR30_95YeZJsiApwXKpNcF1rRPF3foIiBHXRdJI2Qhumhf6_LFTeZaN

Bu değişikliklerin gerçekliği

VAPID ile artık Chrome'da push bildirimlerini kullanmak için GCM'ye hesap açmanıza gerek yoktur. Hem Chrome'da hem de Firefox'ta bir kullanıcıya abone olmak ve bir kullanıcıya ileti göndermek için aynı kod yolunu kullanabilirsiniz. Her ikisi de standartları karşılıyor.

Unutmamanız gereken şey, Chrome 51 ve önceki sürümlerde, Android ve Samsung için Opera tarayıcısında gcm_sender_id öğesini yine de web uygulaması manifest'inizde tanımlamanız ve döndürülecek FCM uç noktasına Yetkilendirme başlığını eklemeniz gerektiğidir.

VAPID, bu özel gereksinimlere karşı bir çıkış rampası sağlar. VAPID'yi uygularsanız bu, web push'u destekleyen tüm tarayıcılarda çalışır. VAPID'yi daha fazla tarayıcı desteklediğinden, gcm_sender_id öğesini manifest dosyanızdan ne zaman çıkaracağınıza karar verebilirsiniz.