चैनल को अधिकृत करना
app key रखने वाला कोई भी क्लाइंट public चैनल को सब्सक्राइब कर सकता है। दो चैनल-नाम प्रीफ़िक्स के लिए आपके बैकएंड को सब्सक्रिप्शन अधिकृत करना होता है। आप चैनल अलग से कॉन्फ़िगर नहीं करते।
private-… नाम वाले चैनल के लिए आपके बैकएंड को हर सब्सक्रिप्शन स्वीकृत करना होता है। presence-… नाम वाला चैनल भी यही करता है और सब्सक्राइबर से एक पहचान भी जोड़ता है, ताकि चैनल पर मौजूद हर कोई देख सके कि और कौन है। कोई भी अन्य नाम public है।
केवल आपके बैकएंड के पास app secret होता है। क्लाइंट आपके सर्वर से एक विशिष्ट सब्सक्रिप्शन साइन करने के लिए कहता है, और Realtime edge उस सिग्नेचर को स्वीकार करने से पहले सत्यापित करता है। आपका सर्वर तय करता है कि कॉलर सब्सक्राइब कर सकता है या नहीं, बिना secret को क्लाइंट के सामने उजागर किए।
क्लाइंट को अपने endpoint पर पॉइंट करें
क्लाइंट को अपने बैकएंड पर एक authEndpoint दें:
import { BirdRealtime } from "@messagebird/realtime";
const bird = new BirdRealtime({
appKey: "your-app-key",
region: "us1",
authEndpoint: "/bird/auth",
});
const room = bird.subscribe("presence-room-1");import BirdRealtime
let bird = BirdRealtime(options: .init(
appKey: "your-app-key",
region: "us1",
authEndpoint: URL(string: "https://your-backend.example.com/bird/auth")
))
let room = bird.subscribe("presence-room-1")import com.bird.realtime.BirdRealtime
import com.bird.realtime.BirdRealtimeOptions
val bird = BirdRealtime(
BirdRealtimeOptions(
appKey = "your-app-key",
region = "us1",
authEndpoint = "https://your-backend.example.com/bird/auth",
)
)
val room = bird.subscribe("presence-room-1")क्लाइंट हर private या presence सब्सक्रिप्शन के लिए इस endpoint को कॉल करता है, जिसमें reconnect के बाद पुनर्स्थापित सब्सक्रिप्शन भी शामिल हैं। अधिकरण एक कनेक्शन पर लागू होता है क्योंकि सिग्नेचर में उसका connection ID शामिल होता है।
ब्राउज़र क्लाइंट को डिफ़ॉल्ट रूप से same-origin endpoint चाहिए। cross-origin authEndpoint उपयोग करने के लिए allowCrossOriginAuth: true सेट करें। ब्राउज़र क्लाइंट कॉन्फ़िगर किए गए authHeaders केवल same-origin endpoint को भेजता है।
आपका endpoint क्या प्राप्त करता है और क्या लौटाता है
क्लाइंट JSON POST करता है:
कोड उदाहरण
{ "connection_id": "26896.319537", "channel_name": "presence-room-1" }सिग्नेचर के साथ रिस्पॉन्स दें:
कोड उदाहरण
{ "auth": "your-app-key:8f9a…" }presence चैनल के लिए, सदस्य की पहचान भी एक JSON स्ट्रिंग के रूप में लौटाएँ, वही स्ट्रिंग जिसे आपने साइन किया:
कोड उदाहरण
{
"auth": "your-app-key:8f9a…",
"member_data": "{\"member_id\":\"u_42\",\"member_info\":{\"name\":\"Ada\"}}"
}member_id वह पहचान है जो अन्य सदस्य देखते हैं और जिसे disconnect ऑपरेशन लक्षित करता है। member_info वैकल्पिक JSON डेटा है जो हर चैनल सदस्य को दिया जाता है। इसकी सीमा 1 KB है, इसलिए केवल छोटा, गैर-संवेदनशील प्रोफ़ाइल डेटा शामिल करें।
इस endpoint में कॉलर को उसकी session cookie या bearer token से अधिकृत करें। जब कॉलर को चैनल में शामिल नहीं होना चाहिए तो 403 Forbidden लौटाएँ। presence चैनल के लिए, उसी रिस्पॉन्स में पहचान असाइन करें।
वह स्ट्रिंग जिसे आप साइन करते हैं
कोलन से जोड़ें, फिर app secret के साथ HMAC-SHA256 करें और hex-encode करें। परिणाम के आगे app key और एक कोलन लगाएँ।
| चैनल प्रकार | साइन करने की स्ट्रिंग |
|---|---|
| private-… | <connection_id>:<channel_name> |
| private-encrypted-… | <connection_id>:<channel_name> |
| presence-… | <connection_id>:<channel_name>:<member_data> |
presence चैनल के लिए, ठीक वही member_data स्ट्रिंग साइन करें जो आप लौटाते हैं। उसी ऑब्जेक्ट को दोबारा serialize करने से key क्रम या स्पेसिंग बदल सकती है और सिग्नेचर अमान्य हो सकता है।
एक encrypted चैनल private की तरह साइन होता है, और उसका auth रिस्पॉन्स अतिरिक्त रूप से चैनल की decryption key shared_secret के रूप में लौटाता है। SDK हेल्पर इसे स्वचालित रूप से जोड़ता है; Encrypted channels में derivation और चैनल व्यवहार शामिल है।
हर सर्वर SDK एक authorizeChannel हेल्पर प्रदान करता है। यह कॉन्फ़िगर किए गए app credentials से साइन करता है और बिना नेटवर्क रिक्वेस्ट किए रिस्पॉन्स बॉडी लौटाता है। encrypted चैनल के लिए, हेल्पर shared_secret भी जोड़ता है।
app.post("/bird/auth", async (req, res) => {
const { connection_id, channel_name } = req.body;
// Your own authorization decision goes here.
const user = getUserFromSession(req);
if (!user || !mayJoin(user, channel_name)) return res.sendStatus(403);
const memberData = channel_name.startsWith("presence-")
? JSON.stringify({ member_id: user.id, member_info: { name: user.name } })
: undefined;
res.json(
await bird.realtime.authorizeChannel({
connectionId: connection_id,
channelName: channel_name,
memberData,
}),
);
});import json
@app.post("/bird/auth")
def bird_auth():
body = request.get_json()
channel_name = body["channel_name"]
# Your own authorization decision goes here.
user = get_user_from_session()
if user is None or not may_join(user, channel_name):
abort(403)
member_data = None
if channel_name.startswith("presence-"):
member_data = json.dumps({"member_id": user.id, "member_info": {"name": user.name}})
return client.realtime.authorize_channel(
connection_id=body["connection_id"],
channel_name=channel_name,
member_data=member_data,
)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
}
// Your own authorization decision goes here.
user, ok := userFromSession(r)
if !ok || !mayJoin(user, body.ChannelName) {
http.Error(w, "forbidden", http.StatusForbidden)
return
}
params := bird.RealtimeChannelAuthorizationParams{
ConnectionID: body.ConnectionID,
ChannelName: body.ChannelName,
}
if strings.HasPrefix(body.ChannelName, "presence-") {
memberData, _ := json.Marshal(map[string]any{
"member_id": user.ID,
"member_info": map[string]string{"name": user.Name},
})
params.MemberData = string(memberData)
}
auth, err := client.Realtime.AuthorizeChannel(params)
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
{
// Your own authorization decision goes here.
if (!mayJoin($user, $channelName)) {
http_response_code(403);
exit;
}
$memberData = null;
if (str_starts_with($channelName, 'presence-')) {
$memberData = json_encode(['member_id' => $user->id, 'member_info' => ['name' => $user->name]]);
}
return $bird->realtime->authorizeChannel($connectionId, $channelName, $memberData);
}बिना SDK वाली भाषा में भी साइनिंग अनुबंध वही है: स्ट्रिंग को app secret के साथ HMAC-SHA256 करें, hex-encode करें, और आगे app key और एक कोलन लगाएँ।
सदस्य और कनेक्शन
एक सदस्य एक पहचान है, जबकि एक कनेक्शन एक खुला WebSocket है। अगर कोई आपके ऐप को तीन टैब में खोलता है, तो एक सदस्य के पास तीन कनेक्शन होते हैं। member_added तब फ़ायर होता है जब पहला कनेक्शन सब्सक्राइब करता है, और member_removed तब फ़ायर होता है जब अंतिम कनेक्शन छोड़ता है। अन्य कनेक्शन चैनल की कनेक्शन संख्या बदलते हैं लेकिन सदस्य इवेंट उत्पन्न नहीं करते।
सामान्य विफलताएँ
अस्वीकृत सब्सक्रिप्शन क्लाइंट error के रूप में आता है। इन सामान्य कारणों की जाँच करें:
- अमान्य सिग्नेचर। आपने जो स्ट्रिंग साइन की वह मेल नहीं खाती। लगभग हमेशा एक दोबारा serialize किया गया member_data, या चैनल नाम पर बिना private- या presence- प्रीफ़िक्स के कंप्यूट किया गया सिग्नेचर।
- अमान्य key। auth में key किसी दूसरे ऐप की है, या रद्द कर दी गई है। key बदलने का मतलब है क्लाइंट की appKey और आपके endpoint में साइनिंग के लिए उपयोग होने वाला secret दोनों अपडेट करना।
- सदस्य डेटा अनुपलब्ध। एक presence सब्सक्रिप्शन member_data के बिना आया। presence चैनल में गुमनाम रूप से शामिल नहीं हुआ जा सकता।
- आपके अपने endpoint से 403। आपके अधिकरण निर्णय ने अस्वीकार किया, जो उस उपयोगकर्ता के लिए अपेक्षित परिणाम है जो शामिल नहीं हो सकता।
अगले कदम
- अपना पहला realtime इवेंट भेजें वह एंड-टू-एंड वॉकथ्रू है जिस पर यह गाइड आधारित है।
- Encrypted channels इस सिग्नेचर पर आधारित हैं और स्वीकृत सब्सक्राइबर को एक decryption key भी देते हैं।
- Presence channels सदस्य सूची, सदस्य इवेंट, और आपके सर्वर से presence पढ़ने को कवर करता है।
- सदस्य कनेक्शन समाप्त करना वह दूसरा सिग्नेचर है जो आपका बैकएंड कंप्यूट करता है, और जो आपको किसी सदस्य के कनेक्शन बंद करने देता है।
- Webhooks & events आपके अपने endpoint पर realtime.* इवेंट को कवर करता है, जिसमें सदस्यों का शामिल होना और छोड़ना शामिल है।
संबंधित संसाधन
इस विषय के लिए डॉक्यूमेंटेशन, गाइड और उदाहरणों के साथ आगे बढ़ें। संसाधन अंग्रेज़ी में हैं।