वेब पुश इंटरऑपरेबिलिटी जीत

मैट गांट
जो मेडले
जो मेडली

जब Chrome ने पहली बार Web Push API का इस्तेमाल किया था, तो वह Firebase क्लाउड से मैसेज (FCM) करने के लिए पुश सेवा के तौर पर काम करता था. Firebase क्लाउड से मैसेज (FCM) करने के लिए इस सेवा को पहले Google क्लाउड से मैसेज सेवा (GCM) के नाम से जाना जाता था. इसके लिए अपने मालिकाना एपीआई का इस्तेमाल करना ज़रूरी है. इससे Chrome, डेवलपर को वेब पुश एपीआई उपलब्ध करा सकता है. यह ऐसे समय में उपलब्ध था, जब वेब पुश प्रोटोकॉल का स्पेसिफ़िकेशन अब भी लिखा जा रहा था और बाद में पुष्टि (जिसका मतलब है कि मैसेज भेजने वाला वह व्यक्ति है जो वह कहता है) की पुष्टि कर रही थी जब वेब पुश प्रोटोकॉल में वह उपलब्ध नहीं था. खुशखबरी: अब इनमें से कोई भी सही नहीं है.

FCM / GCM और Chrome अब स्टैंडर्ड वेब पुश प्रोटोकॉल के साथ काम करते हैं. वहीं, भेजने वाले की पुष्टि VAPID को लागू करके की जा सकती है. इसका मतलब है कि अब आपके वेब ऐप्लिकेशन को 'gcm_sender_id' की ज़रूरत नहीं होगी.

इस लेख में, मैं पहले आपको बताऊंगी कि FCM के साथ वेब पुश प्रोटोकॉल का इस्तेमाल करने के लिए, अपने मौजूदा सर्वर कोड को कैसे बदला जाए. इसके बाद, मैं आपको बताऊँगा कि अपने क्लाइंट और सर्वर कोड, दोनों में वीएपीआईडी को कैसे लागू करना है.

FCM, वेब पुश प्रोटोकॉल के साथ काम करता है

चलिए, थोड़ी जानकारी से शुरुआत करते हैं. जब आपका वेब ऐप्लिकेशन पुश सदस्यता के लिए रजिस्टर होता है, तो उसे पुश सेवा का यूआरएल दिया जाता है. आपके वेब ऐप्लिकेशन के ज़रिए उपयोगकर्ता को डेटा भेजने के लिए, आपका सर्वर इस एंडपॉइंट का इस्तेमाल करेगा. अगर आपने किसी ऐसे उपयोगकर्ता की सदस्यता ली है जिसके पास VAPID नहीं है, तो Chrome में आपको FCM एंडपॉइंट दिया जाएगा. (हम बाद में VAPID के बारे में बात करेंगे). FCM के साथ काम करने वाले वेब पुश प्रोटोकॉल से पहले, आपको यूआरएल के आखिर से FCM रजिस्ट्रेशन आईडी निकालना पड़ता था और FCM एपीआई अनुरोध करने से पहले उसे हेडर में रखना पड़ता था. उदाहरण के लिए, https://android.googleapis.com/gcm/send/ABCD1234 के FCM एंडपॉइंट का रजिस्ट्रेशन आईडी 'ABCD1234' होगा.

अब जब FCM, वेब पुश प्रोटोकॉल के साथ काम करता है, तो आप एंडपॉइंट को बिना किसी बदलाव के छोड़ सकते हैं और यूआरएल को वेब पुश प्रोटोकॉल एंडपॉइंट के तौर पर इस्तेमाल कर सकते हैं. (इससे यह Firefox और आने वाले समय में ब्राउज़र के हर दूसरे ब्राउज़र के साथ काम करता है.)

VAPID के बारे में ज़्यादा जानकारी देने से पहले, हमें यह पक्का करना होगा कि हमारा सर्वर कोड, FCM एंडपॉइंट को सही तरीके से मैनेज करता हो. नीचे नोड में पुश सेवा को अनुरोध करने का एक उदाहरण दिया गया है. ध्यान दें कि FCM के लिए हम अनुरोध के हेडर में एपीआई पासकोड जोड़ रहे हैं. अन्य पुश सर्विस एंडपॉइंट के लिए, इसकी ज़रूरत नहीं होगी. वर्शन 52, Opera Android और Samsung ब्राउज़र से पहले के Chrome के लिए, आपको अब भी अपने वेब ऐप्लिकेशन के Manifest.json में एक 'gcm_sender_id' शामिल करना होगा. एपीआई पासकोड और भेजने वाले के आईडी का इस्तेमाल यह देखने के लिए किया जाता है कि अनुरोध करने वाला सर्वर, वाकई में उस उपयोगकर्ता को मैसेज भेज सकता है या नहीं.

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');
    }
});

याद रखें, यह FCM / GCM के एपीआई में होने वाला बदलाव है. इसलिए, आपको अपनी सदस्यताओं को अपडेट करने की ज़रूरत नहीं है. हेडर बनाने के लिए बस अपना सर्वर कोड बदलें, जैसा कि ऊपर दिखाया गया है.

पेश है सर्वर की पहचान करने के लिए VAPID

VAPID, "वॉलंटरी ऐप्लिकेशन सर्वर आइडेंटिफ़िकेशन" का नया छोटा नाम है. इस नई शर्त से यह पता चलता है कि आपके ऐप्लिकेशन के सर्वर और पुश सेवा के बीच क्या संबंध है. साथ ही, इससे पुश सेवा को यह पुष्टि करने में मदद मिलती है कि मैसेज कौनसी साइट भेज रही है. VAPID की मदद से, पुश मैसेज भेजने के लिए FCM के खास चरणों से बचा जा सकता है. अब आपको Firebase प्रोजेक्ट, gcm_sender_id या Authorization हेडर की ज़रूरत नहीं है.

यह प्रोसेस बहुत आसान है:

  1. आपका ऐप्लिकेशन सर्वर सार्वजनिक/निजी कुंजी का जोड़ा बनाता है. सार्वजनिक कुंजी आपके वेब ऐप्लिकेशन को दी जाती है.
  2. जब उपयोगकर्ता पुश पाने का विकल्प चुनता है, तो Subscribe() कॉल के विकल्प ऑब्जेक्ट में सार्वजनिक कुंजी जोड़ें.
  3. जब आपका ऐप्लिकेशन सर्वर कोई पुश मैसेज भेजता है, तो उसमें सार्वजनिक कुंजी के साथ हस्ताक्षर किया गया JSON वेब टोकन शामिल करें.

आइए, इन चरणों के बारे में ज़्यादा जानकारी देखें.

सार्वजनिक/निजी कुंजी का जोड़ा बनाएं

एन्क्रिप्ट (सुरक्षित) करने के मामले में मुझे बहुत ज़्यादा मुश्किल है. इसलिए, यहां VAPID सार्वजनिक/निजी कुंजियों के फ़ॉर्मैट की जानकारी से जुड़ा काम का सेक्शन दिया गया है:

ऐप्लिकेशन सर्वर को P-256 कर्व पर एक साइनिंग पासकोड पेयर बनाना चाहिए और उसे मैनेज करना चाहिए. इस जोड़े का इस्तेमाल इलिप्टिकल कर्व डिजिटल सिग्नेचर (ईसीडीएसए) के साथ किया जा सकता है.

ऐसा करने का तरीका, वेब-पुश नोड लाइब्रेरी में देखा जा सकता है:

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

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

सार्वजनिक पासकोड की मदद से सदस्यता लेना

VAPID सार्वजनिक कुंजी के साथ पुश के लिए किसी Chrome उपयोगकर्ता की सदस्यता लेने के लिए, आपको सार्वजनिक कुंजी को uint8Array के तौर पर पास करना होगा. इसके लिए, Subscribe() तरीके के applicationServerKey पैरामीटर का इस्तेमाल करना होगा.

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

अगर ऑरिजिन fcm.googleapis.com है, तो पता चल जाएगा कि उसने सदस्यता ऑब्जेक्ट में एंडपॉइंट की जांच करके काम किया है या नहीं.

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

पुश मैसेज भेजा जा रहा है

VAPID का इस्तेमाल करके मैसेज भेजने के लिए, आपको दो अतिरिक्त एचटीटीपी हेडर के साथ एक सामान्य वेब पुश प्रोटोकॉल अनुरोध करना होगा: ऑथराइज़ेशन हेडर और क्रिप्टो-कुंजी हेडर.

अनुमति देने वाला हेडर

Authorization हेडर के आगे 'WebPush ' लिखा हुआ JSON Web Token (JWT) होता है.

JWT, JSON ऑब्जेक्ट को दूसरे पक्ष के साथ इस तरह से शेयर करने का तरीका है कि भेजने वाला पक्ष उस पर हस्ताक्षर कर सके और पाने वाला पक्ष, मैसेज भेजने वाले के हस्ताक्षर की पुष्टि कर सके. JWT की संरचना तीन एन्क्रिप्ट (सुरक्षित) की गई स्ट्रिंग होती है और इनके बीच एक बिंदु होता है.

<JWTHeader>.<Payload>.<Signature>

JWT हेडर

JWT के हेडर में हस्ताक्षर करने के लिए इस्तेमाल किया जाने वाला एल्गोरिदम का नाम और टोकन का टाइप शामिल होता है. वीएपीआईडी के लिए यह ज़रूरी है:

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

इसके बाद, इसे base64 यूआरएल कोड में बदला जाता है और यह JWT का पहला हिस्सा बनता है.

पेलोड

पेलोड एक और JSON ऑब्जेक्ट है, जिसमें ये चीज़ें शामिल हैं:

  • ऑडियंस ("ऑडिट")
    • यह पुश सेवा का ऑरिजिन है (आपकी साइट का ऑरिजिन नहीं). JavaScript में, ऑडियंस पाने के लिए ये काम किए जा सकते हैं: const audience = new URL(subscription.endpoint).origin
  • खत्म होने का समय ("exp")
    • यह सेकंड की वह संख्या है. जब तक यह माना नहीं जाएगा कि अनुरोध की समयसीमा खत्म हो गई है. यह ज़रूरी है कि अनुरोध किए जाने के 24 घंटे के अंदर, यूटीसी में ऐसा हो.
  • विषय ("सब")
    • विषय एक URL या mailto: URL होना चाहिए. अगर पुश सेवा को मैसेज भेजने वाले से संपर्क करने की ज़रूरत हो, तो यह एक संपर्क जानकारी देता है.

पेलोड का एक उदाहरण ऐसा दिख सकता है:

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

यह JSON ऑब्जेक्ट, base64 यूआरएल कोड में बदला गया है और यह JWT का दूसरा हिस्सा है.

हस्ताक्षर

हस्ताक्षर, कोड में बदले गए हेडर और पेलोड को एक बिंदु की मदद से जोड़कर बनाया जाता है. इसके बाद, पहले बनाई गई VAPID निजी कुंजी की मदद से, नतीजे को एन्क्रिप्ट (सुरक्षित) किया जाता है. नतीजे को हेडर में बिंदु से जोड़ा जाना चाहिए.

मैं इसके लिए कोड सैंपल नहीं दिखाऊंगी, क्योंकि ऐसी कई लाइब्रेरी हैं जो हेडर और पेलोड करेगी और आपके लिए यह सिग्नेचर जनरेट करेंगी.

साइन किए गए JWT का इस्तेमाल इसके पहले 'WebPush ' के साथ अनुमति वाले हेडर के तौर पर किया जाता है. यह कुछ ऐसा दिखेगा:

WebPush eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJhdWQiOiJodHRwczovL2ZjbS5nb29nbGVhcGlzLmNvbSIsImV4cCI6MTQ2NjY2ODU5NCwic3ViIjoibWFpbHRvOnNpbXBsZS1wdXNoLWRlbW9AZ2F1bnRmYWNlLmNvLnVrIn0.Ec0VR8dtf5qb8Fb5Wk91br-evfho9sZT6jBRuQwxVMFyK5S8bhOjk8kuxvilLqTBmDXJM5l3uVrVOQirSsjq0A

इस बारे में कुछ चीज़ों पर ध्यान दें. पहले, प्राधिकरण हेडर में शाब्दिक रूप से 'WebPush' शब्द होता है और उसके बाद एक स्पेस और फिर JWT होना चाहिए. साथ ही, JWT हेडर, पेलोड, और सिग्नेचर को अलग करने वाले डॉट पर ध्यान दें.

क्रिप्टो-कुंजी हेडर

ऑथराइज़ेशन हेडर के साथ-साथ, आपको Crypto-Key हेडर में अपनी VAPID सार्वजनिक कुंजी को, base64 यूआरएल कोड में बदली गई स्ट्रिंग के तौर पर जोड़ना होगा. इसके साथ p256ecdsa= पहले जोड़ना होगा.

p256ecdsa=BDd3_hVL9fZi9Ybo2UUzA284WG5FZR30_95YeZJsiApwXKpNcF1rRPF3foIiBHXRdJI2Qhumhf6_LFTeZaNndIo

जब एन्क्रिप्ट (सुरक्षित) किए गए डेटा के साथ सूचना भेजी जा रही हो, तब भी Crypto-Key हेडर का इस्तेमाल किया जा रहा होगा. इसलिए, ऐप्लिकेशन सर्वर कुंजी जोड़ने के लिए, आपको ऊपर दिया गया कॉन्टेंट जोड़ने से पहले सेमीकोलन जोड़ना होगा. ऐसा करने से:

dh=BGEw2wsHgLwzerjvnMTkbKrFRxdmwJ5S_k7zi7A1coR_sVjHmGrlvzYpAT1n4NPbioFlQkIrTNL8EH4V3ZZ4vJE;
p256ecdsa=BDd3_hVL9fZi9Ybo2UUzA284WG5FZR30_95YeZJsiApwXKpNcF1rRPF3foIiBHXRdJI2Qhumhf6_LFTeZaN

इन बदलावों की हकीकत

VAPID के साथ अब आपको Chrome में पुश का उपयोग करने के लिए GCM वाले खाते में साइन अप करने की ज़रूरत नहीं है और आप उपयोगकर्ता को सदस्यता लेने और Chrome और Firefox, दोनों में किसी उपयोगकर्ता को संदेश भेजने के लिए इसी कोड पथ का उपयोग कर सकते हैं. दोनों स्टैंडर्ड का पालन कर रहे हैं.

आपको यह ध्यान रखना होगा कि Chrome 51 और उससे पहले के वर्शन वाले Android और Samsung ब्राउज़र में, आपको अब भी अपने वेब ऐप्लिकेशन मेनिफ़ेस्ट में gcm_sender_id तय करना होगा. साथ ही, आपको FCM एंडपॉइंट में ऑथराइज़ेशन हेडर जोड़ना होगा.

VAPID, मालिकाना हक की इन ज़रूरी शर्तों के हिसाब से ऑफ़ रैंप देता है. अगर VAPID को लागू किया जाता है, तो यह वेब पुश के साथ काम करने वाले सभी ब्राउज़र में काम करेगा. जैसे-जैसे ज़्यादा ब्राउज़र VAPID के साथ काम करते हैं, आपके पास यह तय करने का विकल्प होता है कि gcm_sender_id को अपने मेनिफ़ेस्ट से कब हटाना है.