एन्क्रिप्टेड चैनल
जिस चैनल का नाम private-encrypted- से शुरू होता है वह एंड-टू-एंड एन्क्रिप्टेड होता है। आपका सर्वर हर पेलोड को पब्लिश करने से पहले सील करता है, और अनुमोदित ब्राउज़र क्लाइंट उसे आपके authorization endpoint से मिली key से डिक्रिप्ट करते हैं। Realtime edge और नेटवर्क बिचौलियों को केवल ciphertext दिखता है।
एक 32-byte मास्टर key जनरेट करें और स्टोर करें। मास्टर key कभी भी Realtime API रिक्वेस्ट में नहीं आती, और चैनल-नाम का prefix यह फ़ीचर सक्रिय करता है। Bird खोई हुई key को पुनर्प्राप्त नहीं कर सकता, और उस key से सील किए गए पेलोड आपके द्वारा key बदलने के बाद भी अपठनीय रहते हैं।
एन्क्रिप्टेड चैनल वही endpoint और signature उपयोग करते हैं जो प्राइवेट चैनल उपयोग करते हैं। authorization रिस्पॉन्स में चैनल की व्युत्पन्न डिक्रिप्शन key भी shared_secret के रूप में शामिल होती है। सब्सक्रिप्शन अस्वीकार करने से उस क्लाइंट को key मिलने से रोका जाता है।
मास्टर key जनरेट करें
32 रैंडम bytes जनरेट करें, उन्हें base64 में एन्कोड करें, और वैल्यू को app secret की तरह स्टोर करें:
कोड उदाहरण
openssl rand -base64 32इसे अपने सर्वर SDK को realtime कॉन्फ़िगरेशन के हिस्से के रूप में दें, app key और secret के साथ।
एक एन्क्रिप्टेड इवेंट पब्लिश करें
सर्वर SDK चैनल prefix को पहचानता है, मास्टर key से उसकी key व्युत्पन्न करता है, और JSON पेलोड को लोकली सील करता है। पब्लिश रिक्वेस्ट में सील किया हुआ envelope होता है।
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']));एक एन्क्रिप्टेड चैनल एकल publish में एकमात्र चैनल होना चाहिए। हर एन्क्रिप्टेड चैनल अलग key व्युत्पन्न करता है, इसलिए अन्य चैनल उसी सील्ड पेलोड को डिक्रिप्ट नहीं कर सकते। SDK इस fan-out को लोकली अस्वीकार करते हैं, और API ऐसा मिलने पर E23000 लौटाता है। कई एन्क्रिप्टेड चैनलों पर पब्लिश करने के लिए, प्रति इवेंट एक चैनल वाले batch का उपयोग करें।
अपने auth endpoint से shared secret लौटाएँ
आपका auth endpoint एन्क्रिप्टेड सब्सक्रिप्शन को उसी तरह अनुमोदित करता है जैसे प्राइवेट सब्सक्रिप्शन को। SDK के authorizeChannel हेल्पर का उपयोग करें और जब भी चैनल नाम में encrypted prefix हो, रिस्पॉन्स में 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 के लिए authorization इसलिए private-encrypted-invoices को डिक्रिप्ट नहीं करता। secret आपके authorization रिस्पॉन्स में यात्रा करता है और edge को भेजे गए subscription फ़्रेम में शामिल नहीं होता।
ब्राउज़र में सब्सक्राइब और डिक्रिप्ट करें
cipher अलग @messagebird/realtime/encrypted एंट्री पॉइंट का उपयोग करता है। इसे import करें और क्लाइंट के encryption option के रूप में पास करें:
कोड उदाहरण
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" }
});Bindings प्लेनटेक्स्ट प्राप्त करती हैं। encryption option के बिना सब्सक्राइब करने पर तुरंत error throw होता है, और shared_secret के बिना authorization रिस्पॉन्स सब्सक्रिप्शन विफल कर देता है।
वर्तमान में केवल ब्राउज़र क्लाइंट एन्क्रिप्टेड चैनल प्राप्त करता है। Swift और Kotlin क्लाइंट private-encrypted- सब्सक्रिप्शन अस्वीकार करते हैं क्योंकि वे डिक्रिप्शन लागू नहीं करते।
मास्टर key रोटेट करें
नई key को हर publisher और authorization endpoint पर एक साथ deploy करें। रोटेशन के दौरान:
- नए publish नई key से सील होते हैं।
- एक सब्सक्राइब्ड ब्राउज़र क्लाइंट जो किसी इवेंट को डिक्रिप्ट नहीं कर पाता, एक बार फिर से authorize होता है और नया shared_secret प्राप्त करता है।
- अलग-अलग मास्टर key वाले instances थोड़े समय के लिए ऐसे इवेंट पब्लिश कर सकते हैं जिन्हें कुछ क्लाइंट डिक्रिप्ट नहीं कर पाते, इसलिए rollout को instances में समन्वित करें।
लीक या खोई हुई key को रोटेट करें। रोटेशन भविष्य के पेलोड की रक्षा करता है लेकिन पहले के इवेंट को दोबारा सील नहीं कर सकता या पुरानी key की प्रतियाँ रद्द नहीं कर सकता।
एन्क्रिप्टेड चैनल क्या नहीं करते
- आधिकारिक क्लाइंट client events सपोर्ट नहीं करते। ब्राउज़र trigger() एन्क्रिप्टेड चैनलों पर throw करता है क्योंकि क्लाइंट client-to-client पेलोड सील नहीं करता। कस्टम क्लाइंट से प्लेनटेक्स्ट client events न भेजें।
- Presence और encryption को जोड़ा नहीं जा सकता। presence-encrypted- prefix असमर्थित है। Cache और encryption साथ काम करते हैं: private-encrypted-cache- चैनल कैश किए गए इवेंट को सील करके स्टोर करते हैं, हालाँकि key रोटेशन के बाद कैश की गई प्रति पुरानी key से सील रहती है जब तक अगला publish उसे बदल नहीं देता।
- चैनल नाम और इवेंट नाम एन्क्रिप्टेड नहीं होते। केवल पेलोड एन्क्रिप्टेड होता है। ऐसे चैनल नाम चुनें जो यह उजागर न करें कि आप क्या सुरक्षित कर रहे हैं।
- Realtime edge पेलोड का निरीक्षण नहीं कर सकता। चैनल और इवेंट नाम दिखते रहते हैं, जबकि पेलोड एन्क्रिप्टेड रहता है।
अगले कदम
- चैनल authorize करना वह signature तंत्र है जिस पर यह गाइड आधारित है।
- इवेंट पब्लिश करना publish और batch API को विस्तार से कवर करता है।
- Cache चैनल last-event replay की व्याख्या करता है जिसे private-encrypted-cache- इसके साथ जोड़ता है।
संबंधित संसाधन
इस विषय के लिए डॉक्यूमेंटेशन, गाइड और उदाहरणों के साथ आगे बढ़ें। संसाधन अंग्रेज़ी में हैं।
क्षमता जानेंRealtimeलर्निंग पाथ फ़ॉलो करेंBuild your first integrationइम्प्लीमेंटेशन गाइडSend your first realtime event
अभ्यास करें और इम्प्लीमेंटेशन ब्रीफ़ पाएँ