एन्क्रिप्टेड चैनल
जिस चैनल का नाम private-encrypted- से शुरू होता है, वह एंड-टू-एंड एन्क्रिप्टेड होता है। आपका सर्वर हर पेलोड को प्रकाशित करने से पहले सील करता है, और स्वीकृत ब्राउज़र क्लाइंट आपके ऑथराइज़ेशन एंडपॉइंट से मिली कुंजी से उसे डिक्रिप्ट करते हैं। Realtime एज और नेटवर्क मध्यस्थ केवल सिफरटेक्स्ट देखते हैं।
32-बाइट की एक मास्टर कुंजी बनाएँ और उसे सुरक्षित रखें। मास्टर कुंजी किसी भी Realtime API अनुरोध में कभी नहीं जाती, और चैनल-नाम का प्रीफ़िक्स ही इस सुविधा को चालू करता है। Bird खोई हुई कुंजी को वापस नहीं ला सकता, और कुंजी बदलने के बाद भी उस कुंजी से सील किए गए पेलोड पढ़े नहीं जा सकते।
एन्क्रिप्टेड चैनल वही एंडपॉइंट और सिग्नेचर इस्तेमाल करते हैं जो प्राइवेट चैनल करते हैं। ऑथराइज़ेशन प्रतिक्रिया में चैनल की व्युत्पन्न डिक्रिप्शन कुंजी भी shared_secret के रूप में शामिल होती है। अगर आप किसी सब्सक्रिप्शन को अस्वीकार करते हैं, तो उस क्लाइंट को कुंजी नहीं मिलती।
मास्टर कुंजी बनाएँ
32 रैंडम बाइट बनाएँ, उन्हें base64 में एन्कोड करें, और इस मान को ऐप सीक्रेट की तरह सुरक्षित रखें:
openssl rand -base64 32इसे realtime कॉन्फ़िगरेशन के हिस्से के रूप में, ऐप कुंजी और सीक्रेट के साथ, अपने सर्वर SDK को दें।
एन्क्रिप्टेड इवेंट प्रकाशित करें
सर्वर SDK चैनल प्रीफ़िक्स पहचानता है, मास्टर कुंजी से उस चैनल की कुंजी व्युत्पन्न करता है, और JSON पेलोड को स्थानीय रूप से सील करता है। प्रकाशन अनुरोध में सील किया हुआ एनवेलप होता है।
import { BirdClient } from "@messagebird/sdk";
const bird = new BirdClient({
apiKey: process.env.BIRD_API_KEY,
realtime: {
key: process.env.BIRD_REALTIME_KEY,
secret: process.env.BIRD_REALTIME_SECRET,
encryptionMasterKey: process.env.BIRD_REALTIME_MASTER_KEY,
},
});
await bird.realtime.publish("rap_01krdgeqcxet5s7t44vh8rt9mg", {
event: "order.updated",
channels: ["private-encrypted-orders"],
data: { order_id: "ord_123", status: "shipped" },
});from bird import Bird
client = Bird(
realtime_key=os.environ["BIRD_REALTIME_KEY"],
realtime_secret=os.environ["BIRD_REALTIME_SECRET"],
realtime_encryption_master_key=os.environ["BIRD_REALTIME_MASTER_KEY"],
)
client.realtime.publish(
"rap_01krdgeqcxet5s7t44vh8rt9mg",
event="order.updated",
channels=["private-encrypted-orders"],
data={"order_id": "ord_123", "status": "shipped"},
)client, err := bird.NewClient(
option.WithAPIKey(os.Getenv("BIRD_API_KEY")),
option.WithRealtimeCredentials(os.Getenv("BIRD_REALTIME_KEY"), os.Getenv("BIRD_REALTIME_SECRET")),
option.WithRealtimeEncryptionMasterKey(os.Getenv("BIRD_REALTIME_MASTER_KEY")),
)
if err != nil {
log.Fatal(err)
}
_, err = client.Realtime.Publish(context.Background(), "rap_01krdgeqcxet5s7t44vh8rt9mg", bird.RealtimePublishParams{
Event: "order.updated",
Channels: []string{"private-encrypted-orders"},
Data: map[string]any{"order_id": "ord_123", "status": "shipped"},
})$bird = new Bird(getenv('BIRD_API_KEY'), realtime: new RealtimeOptions(
key: getenv('BIRD_REALTIME_KEY'),
secret: getenv('BIRD_REALTIME_SECRET'),
encryptionMasterKey: getenv('BIRD_REALTIME_MASTER_KEY'),
));
$bird->realtime->publish('rap_01krdgeqcxet5s7t44vh8rt9mg', (new RealtimePublish())
->setEvent('order.updated')
->setChannels(['private-encrypted-orders'])
->setData(['order_id' => 'ord_123', 'status' => 'shipped']));किसी एक प्रकाशन में एन्क्रिप्टेड चैनल अकेला चैनल होना चाहिए। हर एन्क्रिप्टेड चैनल अलग कुंजी व्युत्पन्न करता है, इसलिए दूसरे चैनल उसी सील किए गए पेलोड को डिक्रिप्ट नहीं कर पाएँगे। SDK इस फ़ैन-आउट को स्थानीय रूप से अस्वीकार करते हैं, और ऐसा अनुरोध मिलने पर API E23000 लौटाता है। कई एन्क्रिप्टेड चैनलों पर प्रकाशित करने के लिए ऐसा बैच इस्तेमाल करें जिसमें हर इवेंट में एक ही चैनल हो।
अपने ऑथ एंडपॉइंट से साझा सीक्रेट लौटाएँ
आपका ऑथ एंडपॉइंट एन्क्रिप्टेड सब्सक्रिप्शन को उसी तरह स्वीकृत करता है जैसे निजी सब्सक्रिप्शन को। SDK के authorizeChannel हेल्पर का उपयोग करें। जब भी चैनल के नाम में एन्क्रिप्टेड प्रीफ़िक्स होता है, प्रतिक्रिया में shared_secret अपने आप जुड़ जाता है:
app.post("/bird/auth", async (req, res) => {
const { connection_id, channel_name } = req.body;
const user = getUserFromSession(req);
if (!user || !mayJoin(user, channel_name)) return res.sendStatus(403);
res.json(
await bird.realtime.authorizeChannel({
connectionId: connection_id,
channelName: channel_name,
}),
);
});@app.post("/bird/auth")
def bird_auth():
body = request.get_json()
user = get_user_from_session()
if user is None or not may_join(user, body["channel_name"]):
abort(403)
return client.realtime.authorize_channel(
connection_id=body["connection_id"],
channel_name=body["channel_name"],
)func birdAuth(w http.ResponseWriter, r *http.Request) {
var body struct {
ConnectionID string `json:"connection_id"`
ChannelName string `json:"channel_name"`
}
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
http.Error(w, "bad request", http.StatusBadRequest)
return
}
user, ok := userFromSession(r)
if !ok || !mayJoin(user, body.ChannelName) {
http.Error(w, "forbidden", http.StatusForbidden)
return
}
auth, err := client.Realtime.AuthorizeChannel(bird.RealtimeChannelAuthorizationParams{
ConnectionID: body.ConnectionID,
ChannelName: body.ChannelName,
})
if err != nil {
http.Error(w, "authorization failed", http.StatusInternalServerError)
return
}
json.NewEncoder(w).Encode(auth)
}function birdAuth(string $connectionId, string $channelName, User $user): array
{
if (!mayJoin($user, $channelName)) {
http_response_code(403);
exit;
}
return $bird->realtime->authorizeChannel($connectionId, $channelName);
}SDK हर चैनल के लिए अलग shared_secret बनाता है। इसलिए private-encrypted-orders का ऑथराइज़ेशन private-encrypted-invoices को डिक्रिप्ट नहीं करता। सीक्रेट आपकी ऑथराइज़ेशन प्रतिक्रिया में जाता है और एज को भेजे गए सब्सक्रिप्शन फ़्रेम में शामिल नहीं होता।
ब्राउज़र में सब्सक्राइब और डिक्रिप्ट करें
साइफ़र अलग @messagebird/realtime/encrypted एंट्री पॉइंट का उपयोग करता है। इसे इम्पोर्ट करें और क्लाइंट के encryption विकल्प के रूप में पास करें:
import { BirdRealtime } from "@messagebird/realtime";
import { encryption } from "@messagebird/realtime/encrypted";
const bird = new BirdRealtime({
appKey: "your-app-key",
region: "us1",
authEndpoint: "/bird/auth",
encryption,
});
const orders = bird.subscribe("private-encrypted-orders");
orders.bind("order.updated", (data) => {
console.log(data); // decrypted: { order_id: "ord_123", status: "shipped" }
});बाइंडिंग्स को प्लेनटेक्स्ट मिलता है। encryption विकल्प के बिना सब्सक्राइब करने पर तुरंत त्रुटि आती है, और shared_secret के बिना ऑथराइज़ेशन प्रतिक्रिया मिलने पर सब्सक्रिप्शन विफल हो जाता है।
केवल ब्राउज़र क्लाइंट एन्क्रिप्टेड चैनल प्राप्त करता है। Swift और Kotlin क्लाइंट private-encrypted- सब्सक्रिप्शन अस्वीकार करते हैं, क्योंकि उनमें डिक्रिप्शन लागू नहीं है।
मास्टर कुंजी बदलें
नई कुंजी को हर पब्लिशर और ऑथराइज़ेशन एंडपॉइंट पर एक साथ डिप्लॉय करें। कुंजी बदलने के दौरान:
- नए पब्लिश नई कुंजी से सील होते हैं।
- सब्सक्राइब किया हुआ ब्राउज़र क्लाइंट जब किसी इवेंट को डिक्रिप्ट नहीं कर पाता, तो वह एक बार फिर से ऑथराइज़ करता है और नया
shared_secretप्राप्त करता है। - अलग-अलग मास्टर कुंजियों का उपयोग करने वाले इंस्टेंस थोड़े समय के लिए ऐसे इवेंट पब्लिश कर सकते हैं जिन्हें कुछ क्लाइंट डिक्रिप्ट नहीं कर पाते, इसलिए सभी इंस्टेंस पर रोलआउट का तालमेल रखें।
लीक हुई या खोई हुई कुंजी को रोटेट करें। रोटेशन भविष्य के पेलोड को सुरक्षित करता है, लेकिन पहले के इवेंट को दोबारा सील नहीं कर सकता और पुरानी कुंजी की प्रतियों को रद्द नहीं कर सकता।
एन्क्रिप्टेड चैनल क्या नहीं करते
- आधिकारिक क्लाइंट, क्लाइंट इवेंट का समर्थन नहीं करते। एन्क्रिप्टेड चैनलों पर ब्राउज़र
trigger()त्रुटि देता है, क्योंकि क्लाइंट एक क्लाइंट से दूसरे क्लाइंट को भेजे जाने वाले पेलोड को सील नहीं करता। किसी कस्टम क्लाइंट से प्लेनटेक्स्ट क्लाइंट इवेंट न भेजें। - प्रेज़ेंस और एन्क्रिप्शन को एक साथ इस्तेमाल नहीं किया जा सकता।
presence-encrypted-प्रीफ़िक्स समर्थित नहीं है। कैश और एन्क्रिप्शन साथ काम करते हैं:private-encrypted-cache-चैनल कैश किए गए इवेंट को सील करके संग्रहीत करते हैं, हालांकि कुंजी रोटेशन के बाद कैश की गई प्रति तब तक पुरानी कुंजी से सील रहती है जब तक अगला पब्लिश उसे बदल नहीं देता। - चैनल नाम और इवेंट नाम एन्क्रिप्ट नहीं होते। केवल पेलोड एन्क्रिप्ट होता है। ऐसे चैनल नाम चुनें जिनसे यह पता न चले कि आप क्या सुरक्षित कर रहे हैं।
- Realtime एज पेलोड की जांच नहीं कर सकता। चैनल और इवेंट नाम दिखाई देते रहते हैं, जबकि पेलोड एन्क्रिप्टेड रहता है।
अगले कदम
- चैनलों को अधिकृत करना वह सिग्नेचर तंत्र है जिस पर यह गाइड आधारित है।
- इवेंट पब्लिश करना में पब्लिश और बैच API के बारे में बताया गया है।
- कैश चैनल उस अंतिम-इवेंट रीप्ले के बारे में बताता है जिसके साथ
private-encrypted-cache-मिलकर काम करता है।
संबंधित संसाधन
इस विषय के लिए दस्तावेज़, गाइड और उदाहरणों के साथ आगे बढ़ें।