अनुमति और पुष्टि की मदद से, Secure Data Connect को सुरक्षित करना

Firebase Data Connect, क्लाइंट-साइड की मज़बूत सुरक्षा उपलब्ध कराता है. इसके लिए, ये सुविधाएं इस्तेमाल की जाती हैं:

  • मोबाइल और वेब क्लाइंट को अनुमति देना
  • अलग-अलग क्वेरी और म्यूटेशन के लेवल पर अनुमति देने के कंट्रोल
  • Firebase App Check के साथ ऐप्लिकेशन की पुष्टि.

Data Connect इस सुरक्षा को इनके साथ बढ़ाता है:

  • सर्वर साइड से अनुमति
  • IAM की मदद से, Firebase प्रोजेक्ट और Cloud SQL उपयोगकर्ता की सुरक्षा.

क्लाइंट क्वेरी और म्यूटेशन को अनुमति देना

Data Connect, Firebase Authentication के साथ पूरी तरह से इंटिग्रेट है. इसलिए, आपके पास अपने डिज़ाइन में, उन उपयोगकर्ताओं के बारे में रिच डेटा का इस्तेमाल करने का विकल्प है जो आपके डेटा को ऐक्सेस कर रहे हैं (पुष्टि). इससे यह तय किया जा सकता है कि वे उपयोगकर्ता कौनसा डेटा ऐक्सेस कर सकते हैं (अनुमति).

Data Connect, क्वेरी और बदलावों के लिए @auth डायरेक्टिव उपलब्ध कराता है. इससे, आपको ऑपरेशन को अनुमति देने के लिए, पुष्टि के लेवल को सेट करने में मदद मिलती है. इस गाइड में, उदाहरण के साथ @auth डायरेक्टिव के बारे में बताया गया है.

इसके अलावा, Data Connect, बदलावों में एम्बेड की गई क्वेरी को लागू करने की सुविधा देता है. इससे, अनुमति से जुड़ी अन्य शर्तें वापस पाई जा सकती हैं, जिन्हें आपने अपने डेटाबेस में सेव किया है. साथ ही, @check निर्देशों में उन शर्तों का इस्तेमाल करके यह तय किया जा सकता है कि बदलावों को अनुमति दी गई है या नहीं. अनुमति देने के इस मामले में, @redact डायरेक्टिव की मदद से यह कंट्रोल किया जा सकता है कि क्वेरी के नतीजे, क्लाइंट को वायर प्रोटोकॉल में दिखाए जाएं या नहीं. साथ ही, जनरेट किए गए एसडीके में एम्बेड की गई क्वेरी को हटाया जाए या नहीं. उदाहरण के साथ, इन निर्देशों के बारे में जानकारी पाएं.

@auth निर्देश को समझना

@auth डायरेक्टिव को पैरामीटराइज़ करके, ऐक्सेस के कई प्रीसेट लेवल में से किसी एक का पालन किया जा सकता है. ये लेवल, ऐक्सेस के कई सामान्य मामलों को कवर करते हैं. ये लेवल, PUBLIC से लेकर NO_ACCESS तक के होते हैं. PUBLIC लेवल पर, किसी भी तरह की पुष्टि किए बिना सभी क्लाइंट से क्वेरी और म्यूटेशन की अनुमति होती है. वहीं, NO_ACCESS लेवल पर, Firebase Admin SDK का इस्तेमाल करने वाले प्रिविलेज्ड सर्वर एनवायरमेंट के बाहर क्वेरी और म्यूटेशन की अनुमति नहीं होती. इनमें से हर लेवल, Firebase Authentication की ओर से दिए गए पुष्टि करने के फ़्लो से जुड़ा होता है.

लेवल परिभाषा
PUBLIC पुष्टि करने के बाद या बिना पुष्टि किए, कोई भी व्यक्ति यह कार्रवाई कर सकता है.
PUBLIC पुष्टि करने के बाद या बिना पुष्टि किए, कोई भी व्यक्ति यह कार्रवाई कर सकता है.
USER_ANON पहचाने गए किसी भी उपयोगकर्ता को क्वेरी या म्यूटेशन करने की अनुमति होती है. इसमें, Firebase Authentication का इस्तेमाल करके गुमनाम रूप से लॉग इन करने वाले उपयोगकर्ता भी शामिल हैं.
USER Firebase Authentication से लॉग इन करने वाले किसी भी उपयोगकर्ता के पास, क्वेरी या म्यूटेशन करने की अनुमति होती है. हालांकि, पहचान छिपाकर साइन इन करने वाले उपयोगकर्ताओं के पास यह अनुमति नहीं होती.
USER_EMAIL_VERIFIED पुष्टि किए गए ईमेल पते के साथ Firebase Authentication से लॉग इन करने वाले किसी भी उपयोगकर्ता को क्वेरी या म्यूटेशन करने की अनुमति होती है.
NO_ACCESS यह कार्रवाई, एडमिन SDK टूल के कॉन्टेक्स्ट के बाहर नहीं की जा सकती.

इन पहले से तय ऐक्सेस लेवल का इस्तेमाल शुरुआती बिंदु के तौर पर करके, @auth डायरेक्टिव में अनुमति की जटिल और बेहतर जांच की जा सकती है. इसके लिए, where फ़िल्टर और सर्वर पर जांचे गए कॉमन एक्सप्रेशन लैंग्वेज (सीईएल) एक्सप्रेशन का इस्तेमाल किया जा सकता है.

अनुमति से जुड़ी सामान्य स्थितियों को लागू करने के लिए, @auth डायरेक्टिव का इस्तेमाल करना

पहले से तय किए गए ऐक्सेस लेवल, अनुमति देने के लिए शुरुआती बिंदु हैं.

USER ऐक्सेस लेवल, शुरुआत करने के लिए सबसे ज़्यादा काम का बेसिक लेवल है.

पूरी तरह से सुरक्षित ऐक्सेस, USER लेवल के साथ-साथ उन फ़िल्टर और एक्सप्रेशन पर आधारित होगा जो उपयोगकर्ता एट्रिब्यूट, संसाधन एट्रिब्यूट, भूमिकाओं, और अन्य जांच की पुष्टि करते हैं. USER_ANON और USER_EMAIL_VERIFIED लेवल, USER केस के वैरिएशन हैं.

एक्सप्रेशन सिंटैक्स की मदद से, auth ऑब्जेक्ट का इस्तेमाल करके डेटा का आकलन किया जा सकता है. यह ऑब्जेक्ट, ऑपरेशन के साथ पास किए गए पुष्टि करने वाले डेटा को दिखाता है. इसमें, पुष्टि करने वाले टोक़न में मौजूद स्टैंडर्ड डेटा और टोक़न में मौजूद कस्टम डेटा, दोनों शामिल होते हैं. auth ऑब्जेक्ट में उपलब्ध फ़ील्ड की सूची के लिए, रेफ़रंस सेक्शन देखें.

हालांकि, कुछ मामलों में PUBLIC सही ऐक्सेस लेवल होता है. हम फिर से बताना चाहते हैं कि ऐक्सेस लेवल हमेशा शुरुआती कदम होता है. बेहतर सुरक्षा के लिए, ज़्यादा फ़िल्टर और एक्सप्रेशन की ज़रूरत होती है.

इस गाइड में अब USER और PUBLIC पर बनाने का तरीका बताया गया है.

प्रेरणा देने वाला उदाहरण

सबसे सही तरीके के इन उदाहरणों में, ब्लॉगिंग प्लैटफ़ॉर्म के लिए दिए गए स्कीमा के बारे में बताया गया है. इस प्लैटफ़ॉर्म पर कुछ कॉन्टेंट को ऐक्सेस करने के लिए, पेमेंट प्लान की ज़रूरत होती है.

ऐसे प्लैटफ़ॉर्म पर, Users औरPosts का मॉडल बनाया जा सकता है.

type User @table(key: "uid") {
  uid: String!
  name: String
  birthday: Date
  createdAt: Timestamp! @default(expr: "request.time")
}

type Post @table {
  author: User!
  text: String!
  # "one of 'draft', 'public', or 'pro'"
  visibility: String! @default(value: "draft")
  # "the time at which the post should be considered published. defaults to
  # immediately"
  publishedAt: Timestamp! @default(expr: "request.time")
  createdAt: Timestamp! @default(expr: "request.time")
  updatedAt: Timestamp! @default(expr: "request.time")
}

उपयोगकर्ता के मालिकाना हक वाले संसाधन

Firebase का सुझाव है कि आप ऐसे फ़िल्टर और एक्सप्रेशन लिखें जिनसे किसी संसाधन के उपयोगकर्ता के मालिकाना हक की जांच की जा सके. यहां दिए गए उदाहरणों में, Posts के मालिकाना हक की जांच की जा रही है.

नीचे दिए गए उदाहरणों में, एक्सप्रेशन का इस्तेमाल करके पुष्टि करने वाले टोकन का डेटा पढ़ा और उसकी तुलना की गई है. आम तौर पर, सेव किए गए authorUid की तुलना पुष्टि करने वाले टोकन में पास किए गए auth.uid (उपयोगकर्ता आईडी) से करने के लिए, where: {authorUid: {eq_expr: "auth.uid"}} जैसे एक्सप्रेशन का इस्तेमाल किया जाता है.

बनाएं

अनुमति देने का यह तरीका, पुष्टि करने वाले टोकन से auth.uid को हर नए Post में authorUid फ़ील्ड के तौर पर जोड़कर शुरू होता है, ताकि अनुमति देने के बाद होने वाले टेस्ट में तुलना की जा सके.

# Create a new post as the current user
mutation CreatePost($text: String!, $visibility: String) @auth(level: USER) {
  post_insert(data: {
    # set the author's uid to the current user uid
    authorUid_expr: "auth.uid"
    text: $text
    visibility: $visibility
  })
}
अपडेट करें

जब कोई क्लाइंट किसी Post को अपडेट करने की कोशिश करता है, तो सेव किए गए authorUid के मुकाबले, पास किए गए auth.uid की जांच की जा सकती है.

# Update one of the current user's posts
mutation UpdatePost($id: UUID!, $text: String, $visibility: String) @auth(level:USER) {
  post_update(
    # only update posts whose author is the current user
    first: { where: {
      id: {eq: $id}
      authorUid: {eq_expr: "auth.uid"}
    }}
    data: {
      text: $text
      visibility: $visibility
      # insert the current server time for updatedAt
      updatedAt_expr: "request.time"
    }
  )
}
मिटाएं

मिटाने की कार्रवाइयों को अनुमति देने के लिए भी इसी तकनीक का इस्तेमाल किया जाता है.

# Delete one of the current user's posts
mutation DeletePost($id: UUID!) @auth(level: USER) {
  post_delete(
    # only delete posts whose author is the current user
    first: { where: {
      id: {eq: $id}
      authorUid: {eq_expr: "auth.uid"}
    }}
  )
}
# Common display information for a post
fragment DisplayPost on Post {
  id, text, createdAt, updatedAt
  author { uid, name }
}
सूची
# List all posts belonging to the current user
query ListMyPosts @auth(level: USER) {
  posts(where: {
    userUid: {eq_expr: "auth.uid"}
  }) {
    # See the fragment above
    ...DisplayPost
    # also show visibility since it is user-controlled
    visibility
  }
}
पाएं
# Get a post only if it belongs to the current user
query GetMyPost($id: UUID!) @auth(level: USER) {
  post(key: {id: $id},
    first: {where: {
      id: {eq: $id}
      authorUid: {eq_expr: "auth.uid"}}
      }}, {
      # See the fragment above
      ...DisplayPost
      # also show visibility since it is user-controlled
      visibility
  }
}

डेटा फ़िल्टर करना

Data Connect के अनुमति देने वाले सिस्टम की मदद से, बेहतर फ़िल्टर लिखे जा सकते हैं. इन फ़िल्टर में, PUBLIC जैसे पहले से तय किए गए ऐक्सेस लेवल के साथ-साथ, पुष्टि करने वाले टोकन का डेटा भी इस्तेमाल किया जा सकता है.

अनुमति देने वाले सिस्टम की मदद से, सिर्फ़ एक्सप्रेशन का इस्तेमाल किया जा सकता है. इसके लिए, आपको बुनियादी ऐक्सेस लेवल की ज़रूरत नहीं होती. इसका उदाहरण नीचे दिए गए कुछ उदाहरणों में दिया गया है.

रिसॉर्स एट्रिब्यूट के हिसाब से फ़िल्टर करना

यहां अनुमति, पुष्टि करने वाले टोकन के आधार पर नहीं दी जाती, क्योंकि सुरक्षा का बुनियादी लेवल PUBLIC पर सेट है. हालांकि, हम अपने डेटाबेस में रिकॉर्ड को साफ़ तौर पर, सार्वजनिक ऐक्सेस के लिए सेट कर सकते हैं. मान लें कि हमारे डेटाबेस में Post रिकॉर्ड हैं और visibility को "सार्वजनिक" पर सेट किया गया है.

# List all posts marked as 'public' visibility
query ListPublicPosts @auth(level: PUBLIC) {
  posts(where: {
    # Test that visibility is "public"
    visibility: {eq: "public"}
    # Only display articles that are already published
    publishedAt: {lt_expr: "request.time"}
  }) {
    # see the fragment above
    ...DisplayPost
  }
}
उपयोगकर्ता के दावों के हिसाब से फ़िल्टर करना

यहां मान लें कि आपने उपयोगकर्ता के ऐसे कस्टम दावे सेट अप किए हैं जो पुष्टि करने वाले टोकन में पास किए जाते हैं. इन दावों की मदद से, आपके ऐप्लिकेशन के "प्रॉ" प्लान में उपयोगकर्ताओं की पहचान की जाती है. ये दावे, पुष्टि करने वाले टोकन में auth.token.plan फ़ील्ड के साथ फ़्लैग किए जाते हैं. आपके एक्सप्रेशन इस फ़ील्ड के हिसाब से जांचे जा सकते हैं.

# List all public or pro posts, only permitted if user has "pro" plan claim
query ProListPosts @auth(expr: "auth.token.plan == 'pro'") {
  posts(where: {
    # display both public posts and "pro" posts
    visibility: {in: ['public', 'pro']},
    # only display articles that are already published
    publishedAt: {lt_expr: "request.time"},
  }) {
    # see the fragment above
    ...DisplayPost
    # show visibility so pro users can see which posts are pro\
    visibility
  }
}
क्रम और सीमा के हिसाब से फ़िल्टर करना

इसके अलावा, हो सकता है कि आपने Post रिकॉर्ड में visibility सेट किया हो, ताकि यह पता चल सके कि वे "प्रॉफ़ेशनल" उपयोगकर्ताओं के लिए उपलब्ध कॉन्टेंट हैं. हालांकि, डेटा की झलक या टीज़र लिस्टिंग के लिए, रिकॉर्ड की संख्या को और सीमित करें.

# Show 2 oldest Pro post as a preview
query ProTeaser @auth(level: USER) {
  posts(
    where: {
      # show only pro posts
      visibility: {eq: "pro"}
      # that have already been published more than 30 days ago
      publishedAt: {lt_time: {now: true, sub: {days: 30}}}
    },
    # order by publish time
    orderBy: [{publishedAt: DESC}],
    # only return two posts
    limit: 2
  ) {
    # See the fragment above
    ...DisplayPost
  }
}
भूमिका के हिसाब से फ़िल्टर करना

अगर आपके कस्टम दावे में admin भूमिका तय की गई है, तो आपके पास इसके हिसाब से कार्रवाइयों की जांच करने और उन्हें अनुमति देने का विकल्प होता है.

# List all posts unconditionally iff the current user has an admin claim
query AdminListPosts @auth(expr: "auth.token.admin == true") {
  posts { ...DisplayPost }
}

@check और @redact डायरेक्टिव को समझना

@check डायरेक्टिव यह पुष्टि करता है कि क्वेरी के नतीजों में, तय किए गए फ़ील्ड मौजूद हैं. फ़ील्ड वैल्यू की जांच करने के लिए, कॉमन एक्सप्रेशन लैंग्वेज (सीईएल) एक्सप्रेशन का इस्तेमाल किया जाता है. डायरेक्टिव का डिफ़ॉल्ट तरीका, null वैल्यू वाले नोड की जांच करना और उन्हें अस्वीकार करना है.

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

Data Connect में, @check और @redact निर्देशों का इस्तेमाल अक्सर अनुमति की जांच के संदर्भ में किया जाता है. ज़्यादा जानकारी के लिए, अनुमति के डेटा लुकअप की चर्चा देखें.

अनुमति का डेटा देखने के लिए, @check और @redact निर्देश जोड़ें

अनुमति के इस्तेमाल के सामान्य उदाहरण में, आपके डेटाबेस में अनुमति की कस्टम भूमिकाएं सेव करना शामिल है. उदाहरण के लिए, खास अनुमतियों वाली टेबल में. साथ ही, डेटा बनाने, अपडेट करने या मिटाने के लिए, म्यूटेशन की अनुमति देने के लिए उन भूमिकाओं का इस्तेमाल करना.

अनुमति वाले डेटा लुकअप का इस्तेमाल करके, userID के आधार पर भूमिकाओं के लिए क्वेरी की जा सकती है. साथ ही, बदलाव की अनुमति है या नहीं, यह तय करने के लिए सीईएल एक्सप्रेशन का इस्तेमाल किया जा सकता है. उदाहरण के लिए, हो सकता है कि आपको ऐसा UpdateMovieTitle म्यूटेशन लिखना हो जिससे अनुमति पा चुके क्लाइंट, फ़िल्म के टाइटल अपडेट कर सकें.

इस चर्चा के बाकी हिस्से के लिए, मान लें कि फ़िल्म की समीक्षा करने वाले ऐप्लिकेशन का डेटाबेस, अनुमति देने वाली भूमिका को MoviePermission टेबल में सेव करता है.

# MoviePermission
# Suppose a user has an authorization role with respect to records in the Movie table
type MoviePermission @table(key: ["doc", "userId"]) {
  movie: Movie! # implies another field: movieId: UUID!
  userId: String! # Can also be a reference to a User table, doesn't matter
  role: String!
}

नीचे दिए गए उदाहरण में, UpdateMovieTitle म्यूटेशन में MoviePermission से डेटा पाने के लिए query फ़ील्ड शामिल है. साथ ही, यह पक्का करने के लिए ये निर्देश भी शामिल हैं कि ऑपरेशन सुरक्षित और मज़बूत हो:

  • @transaction डायरेक्टिव, जिससे यह पक्का किया जा सके कि अनुमति से जुड़ी सभी क्वेरी और जांच पूरी हो गई हों या एक साथ पूरी न हुई हों.
  • रिस्पॉन्स से क्वेरी के नतीजे हटाने के लिए @redact डायरेक्टिव. इसका मतलब है कि अनुमति की जांच Data Connect सर्वर पर की जाती है, लेकिन संवेदनशील डेटा को क्लाइंट को नहीं दिखाया जाता.
  • क्वेरी के नतीजों पर अनुमति के लॉजिक का आकलन करने के लिए, @check निर्देशों का एक जोड़ा. जैसे, यह जांच करना कि किसी दिए गए userID के पास बदलाव करने के लिए सही भूमिका है या नहीं.

mutation UpdateMovieTitle($movieId: UUID!, $newTitle: String!) @auth(level: USER) @transaction {
  # Step 1: Query and check
  query @redact {
    moviePermission( # Look up a join table called MoviePermission with a compound key.
      key: {movieId: $movieId, userId_expr: "auth.uid"}
    # Step 1a: Use @check to test if the user has any role associated with the movie
    # Here the `this` binding refers the lookup result, i.e. a MoviePermission object or null
    # The `this != null` expression could be omitted since rejecting on null is default behavior
    ) @check(expr: "this != null", message: "You do not have access to this movie") {
      # Step 1b: Check if the user has the editor role for the movie
      # Next we execute another @check; now `this` refers to the contents of the `role` field
      role @check(expr: "this == 'editor'", message: "You must be an editor of this movie to update title")
    }
  }
  # Step 2: Act
  movie_update(id: $movieId, data: {
    title: $newTitle
  })
}

अनुमति देने के दौरान, इन गलत तरीकों से बचना

पिछले सेक्शन में, @auth निर्देश का इस्तेमाल करते समय अपनाए जाने वाले पैटर्न के बारे में बताया गया है.

आपको उन ज़रूरी एंटीपैटर्न के बारे में भी पता होना चाहिए जिनसे बचना है.

क्वेरी और म्यूटेशन आर्ग्युमेंट में, उपयोगकर्ता एट्रिब्यूट आईडी और पुष्टि करने वाले टोकन पैरामीटर पास करने से बचें

Firebase Authentication, पुष्टि करने के फ़्लो को दिखाने और पुष्टि करने से जुड़े डेटा को सुरक्षित तरीके से कैप्चर करने के लिए एक बेहतरीन टूल है. जैसे, रजिस्टर किए गए उपयोगकर्ता आईडी और पुष्टि करने वाले टोकन में सेव किए गए कई फ़ील्ड.

क्वेरी और म्यूटेशन आर्ग्युमेंट में उपयोगकर्ता आईडी और पुष्टि करने वाले टोकन का डेटा पास करने का सुझाव नहीं दिया जाता.

# Antipattern!
# This incorrectly allows any user to view any other user's posts
query AllMyPosts($userId: String!) @auth(level: USER) {
  posts(where: {authorUid: {eq: $userId}}) {
    id, text, createdAt
  }
}

बिना किसी फ़िल्टर के USER ऐक्सेस लेवल का इस्तेमाल करने से बचें

जैसा कि गाइड में कई बार बताया गया है, USER, USER_ANON, USER_EMAIL_VERIFIED जैसे मुख्य ऐक्सेस लेवल, अनुमति की जांच के लिए आधारभूत और शुरुआती पॉइंट होते हैं. इन्हें फ़िल्टर और एक्सप्रेशन की मदद से बेहतर बनाया जा सकता है. कौन उपयोगकर्ता अनुरोध कर रहा है, यह जांच करने वाले फ़िल्टर या एक्सप्रेशन के बिना इन लेवल का इस्तेमाल करना, PUBLIC लेवल का इस्तेमाल करने के बराबर है.

# Antipattern!
# This incorrectly allows any user to view all documents
query ListDocuments @auth(level: USER) {
  documents {
    id
    title
    text
  }
}

प्रोटोटाइप बनाने के लिए, PUBLIC या USER ऐक्सेस लेवल का इस्तेमाल करने से बचें

डेवलपमेंट की प्रोसेस को तेज़ करने के लिए, सभी ऑपरेशन को PUBLIC ऐक्सेस लेवल या USER ऐक्सेस लेवल पर सेट किया जा सकता है. ऐसा करने से, सभी ऑपरेशन को अनुमति मिल जाती है और आपको अपने कोड की तुरंत जांच करने में मदद मिलती है.

इस तरह से प्रोटोटाइप बनाने के बाद, NO_ACCESS से PUBLIC और USER लेवल पर, प्रोडक्शन के लिए तैयार अनुमति पर स्विच करें. हालांकि, इस गाइड में दिखाए गए अतिरिक्त लॉजिक को जोड़े बिना, उन्हें PUBLIC या USER के तौर पर डिप्लॉय न करें.

# Antipattern!
# This incorrectly allows anyone to delete any post
mutation DeletePost($id: UUID!) @auth(level: PUBLIC) {
  post: post_delete(
    id: $id,
  )
}

ऐप्लिकेशन की पुष्टि करने के लिए Firebase App Check का इस्तेमाल करना

पुष्टि और अनुमति, Data Connect की सुरक्षा के लिए ज़रूरी हैं. पुष्टि करने और अनुमति देने की सुविधा के साथ-साथ ऐप्लिकेशन की पुष्टि करने की सुविधा, सुरक्षा का एक बहुत ही बेहतरीन समाधान है.

Firebase App Check की मदद से पुष्टि करने पर, आपके ऐप्लिकेशन को चलाने वाले डिवाइस, ऐप्लिकेशन या डिवाइस की पुष्टि करने वाली किसी सेवा का इस्तेमाल करेंगे. यह सेवा पुष्टि करती है कि Data Connect के ऑपरेशन, आपके असली ऐप्लिकेशन से शुरू होते हैं और अनुरोध, असली और बिना छेड़छाड़ किए गए डिवाइस से शुरू होते हैं. यह पुष्टि, Data Connect से किए गए आपके ऐप्लिकेशन के हर अनुरोध के साथ अटैच की जाती है.

Data Connect के लिए App Check को चालू करने और अपने ऐप्लिकेशन में इसके क्लाइंट SDK टूल को शामिल करने का तरीका जानने के लिए, App Check की खास जानकारी देखें.

@auth(level) डायरेक्टिव के लिए पुष्टि के लेवल

इस टेबल में, ऐक्सेस के सभी स्टैंडर्ड लेवल और उनके सीईएल लेवल की जानकारी दी गई है. पुष्टि करने के लेवल, बड़े से छोटे क्रम में दिए गए हैं -- हर लेवल में उन सभी उपयोगकर्ताओं को शामिल किया जाता है जो इन लेवल से मैच करते हैं.

लेवल परिभाषा
PUBLIC पुष्टि करने के बाद या बिना पुष्टि किए, कोई भी व्यक्ति यह कार्रवाई कर सकता है.

ध्यान देने वाली बातें: डेटा को कोई भी उपयोगकर्ता पढ़ सकता है या उसमें बदलाव कर सकता है. Firebase, सार्वजनिक तौर पर ब्राउज़ किए जा सकने वाले डेटा के लिए, अनुमति के इस लेवल का सुझाव देता है. जैसे, प्रॉडक्ट या मीडिया लिस्टिंग. सबसे सही तरीके के उदाहरण और विकल्प देखें.

@auth(expr: "true") के बराबर है

@auth फ़िल्टर और एक्सप्रेशन का इस्तेमाल, इस ऐक्सेस लेवल के साथ नहीं किया जा सकता. ऐसे किसी भी एक्सप्रेशन को 400 गलत अनुरोध वाली गड़बड़ी के साथ अस्वीकार कर दिया जाएगा.
USER_ANON पहचाने गए किसी भी उपयोगकर्ता को क्वेरी या म्यूटेशन करने की अनुमति होती है. इसमें, Firebase Authentication का इस्तेमाल करके गुमनाम रूप से लॉग इन करने वाले उपयोगकर्ता भी शामिल हैं.

ध्यान दें: USER_ANON, USER का सुपरसेट है.

ध्यान देने वाली बातें: ध्यान दें कि अनुमति के इस लेवल के लिए, आपको अपनी क्वेरी और म्यूटेशन को ध्यान से डिज़ाइन करना होगा. इस लेवल पर, उपयोगकर्ता को Authentication की मदद से बिना पहचान ज़ाहिर किए (सिर्फ़ उपयोगकर्ता के डिवाइस से जुड़ा ऑटोमैटिक साइन-इन) लॉग इन करने की अनुमति मिलती है. साथ ही, यह अपने-आप कोई और जांच नहीं करता. उदाहरण के लिए, यह जांच नहीं करता कि डेटा उपयोगकर्ता का है या नहीं. सबसे सही तरीके के उदाहरण और विकल्प देखें.

पहचान छिपाकर लॉगिन करने वाले Authentication फ़्लो, uid जारी करते हैं. इसलिए, USER_ANON लेवल,
@auth(expr: "auth.uid != nil") के बराबर है
USER Firebase Authentication से लॉग इन करने वाले किसी भी उपयोगकर्ता के पास, क्वेरी या म्यूटेशन करने की अनुमति होती है. हालांकि, पहचान छिपाकर साइन इन करने वाले उपयोगकर्ताओं के पास यह अनुमति नहीं होती.

ध्यान देने वाली बातें: ध्यान दें कि अनुमति के इस लेवल के लिए, आपको अपनी क्वेरी और म्यूटेशन को ध्यान से डिज़ाइन करना होगा. यह लेवल सिर्फ़ यह जांच करता है कि उपयोगकर्ता ने Authentication से लॉग इन किया है या नहीं. यह अपने-आप कोई दूसरी जांच नहीं करता. उदाहरण के लिए, यह जांच नहीं करता कि डेटा उपयोगकर्ता का है या नहीं. सबसे सही तरीके के उदाहरण और विकल्प देखें.

@auth(expr: "auth.uid != nil && auth.token.firebase.sign_in_provider != 'anonymous'")" के बराबर
USER_EMAIL_VERIFIED पुष्टि किए गए ईमेल पते के साथ Firebase Authentication से लॉग इन करने वाले किसी भी उपयोगकर्ता को क्वेरी या म्यूटेशन करने की अनुमति होती है.

ध्यान देने वाली बातें: ईमेल पते की पुष्टि, Authentication का इस्तेमाल करके की जाती है. यह पुष्टि करने का एक बेहतर तरीका है. इसलिए, यह लेवल USER या USER_ANON की तुलना में ज़्यादा सुरक्षित होता है.Authentication यह लेवल सिर्फ़ यह जांच करता है कि उपयोगकर्ता ने पुष्टि किए गए ईमेल पते से Authentication में लॉग इन किया है या नहीं. यह अपने-आप कोई दूसरी जांच नहीं करता. उदाहरण के लिए, यह जांच नहीं करता कि डेटा उपयोगकर्ता का है या नहीं. सबसे सही तरीके के उदाहरण और विकल्प देखें.

@auth(expr: "auth.uid != nil && auth.token.email_verified")" के बराबर
NO_ACCESS यह कार्रवाई, एडमिन SDK टूल के कॉन्टेक्स्ट के बाहर नहीं की जा सकती.

@auth(expr: "false") के बराबर

@auth(expr) और @check(expr) के लिए सीईएल रेफ़रंस

इस गाइड में दिए गए उदाहरणों में दिखाया गया है कि @auth(expr:) और @check निर्देशों का इस्तेमाल करके, Data Connect के लिए अनुमति को कंट्रोल करने के लिए, कॉमन एक्सप्रेशन लैंग्वेज (सीईएल) में बताए गए एक्सप्रेशन का इस्तेमाल किया जा सकता है और किया जाना चाहिए.

इस सेक्शन में, इन निर्देशों के लिए एक्सप्रेशन बनाने से जुड़ा सीईएल सिंटैक्स शामिल है.

सीईएल के लिए पूरी रेफ़रंस जानकारी, सीईएल स्पेसिफ़िकेशन में दी गई है.

क्वेरी और म्यूटेशन में पास किए गए वैरिएबल की जांच करना

@auth(expr) सिंटैक्स की मदद से, क्वेरी और बदलावों से वैरिएबल ऐक्सेस किए जा सकते हैं और उनकी जांच की जा सकती है.

उदाहरण के लिए, vars.status का इस्तेमाल करके, $status जैसे ऑपरेशन वैरिएबल को शामिल किया जा सकता है.

mutation Update($id: UUID!, $status: Any) @auth(expr: "has(vars.status)")

एक्सप्रेशन के लिए उपलब्ध डेटा

@auth(expr:) और @check(expr:), दोनों सीईएल एक्सप्रेशन इनका आकलन कर सकते हैं:

  • request.operationName
  • vars (request.variables का उपनाम)
  • auth (request.auth का उपनाम)

इसके अलावा, @check(expr:) एक्सप्रेशन का इस्तेमाल करके इनका आकलन किया जा सकता है:

  • this (मौजूदा फ़ील्ड की वैल्यू)

request.operationName ऑब्जेक्ट

request.operarationName ऑब्जेक्ट, ऑपरेशन का टाइप सेव करता है. यह क्वेरी या म्यूटेशन, दोनों में से कोई एक हो सकता है.

vars ऑब्जेक्ट

vars ऑब्जेक्ट की मदद से, आपके एक्सप्रेशन आपकी क्वेरी या म्यूटेशन में पास किए गए सभी वैरिएबल ऐक्सेस कर सकते हैं.

किसी एक्सप्रेशन में, vars.<variablename> का इस्तेमाल पूरी तरह से तय किए गए request.variables.<variablename> के लिए, किसी दूसरे नाम के तौर पर किया जा सकता है:

# The following are equivalent
mutation StringType($v: String!) @auth(expr: "vars.v == 'hello'")
mutation StringType($v: String!) @auth(expr: "request.variables.v == 'hello'")

auth ऑब्जेक्ट

Authentication, आपके डेटा को ऐक्सेस करने का अनुरोध करने वाले उपयोगकर्ताओं की पहचान करता है. साथ ही, उस जानकारी को ऑब्जेक्ट के तौर पर उपलब्ध कराता है, जिसे अपने एक्सप्रेशन में इस्तेमाल किया जा सकता है.

अपने फ़िल्टर और एक्सप्रेशन में, auth का इस्तेमाल request.auth के लिए किसी दूसरे नाम के तौर पर किया जा सकता है.

auth ऑब्जेक्ट में यह जानकारी शामिल होती है:

  • uid: अनुरोध करने वाले उपयोगकर्ता को असाइन किया गया यूनीक यूज़र आईडी.
  • token: Authentication से इकट्ठा की गई वैल्यू का मैप.

auth.token के कॉन्टेंट के बारे में ज़्यादा जानकारी के लिए, पुष्टि करने वाले टोकन में मौजूद डेटा देखें

this बाइंडिंग

बाइंडिंग this उस फ़ील्ड का आकलन करता है जिससे @check डायरेक्टिव जुड़ा है. सामान्य तौर पर, एक वैल्यू वाली क्वेरी के नतीजों का आकलन किया जा सकता है.

mutation UpdateMovieTitle($movieId: UUID!, $newTitle: String!) @auth(level: USER) @transaction {
  # Step 1: Query and check
  query @redact {
    moviePermission( # Look up a join table called MoviePermission with a compound key.
      key: {movieId: $movieId, userId_expr: "auth.uid"}
    ) {
      # Check if the user has the editor role for the movie. `this` is the string value of `role`.
      # If the parent moviePermission is null, the @check will also fail automatically.
      role @check(expr: "this == 'editor'", message: "You must be an editor of this movie to update title")
    }
  }
  # Step 2: Act
  movie_update(id: $movieId, data: {
    title: $newTitle
  })
}

अगर कोई पैरंट फ़ील्ड सूची है, तो रिटर्न किया गया फ़ील्ड कई बार दिख सकता है. ऐसे में, हर वैल्यू के साथ बाउंड किए गए this की मदद से, हर बार दिखने वाले फ़ील्ड की जांच की जाती है.

किसी भी पाथ के लिए, अगर कोई पैरंट null या [] है, तो फ़ील्ड तक नहीं पहुंचा जा सकेगा और उस पाथ के लिए सीईएल का आकलन नहीं किया जाएगा. दूसरे शब्दों में, आकलन सिर्फ़ तब होता है, जब this null या नॉन-null हो, लेकिन कभी भी undefined नहीं.

जब फ़ील्ड खुद ही कोई सूची या ऑब्जेक्ट होता है, तो this उसी स्ट्रक्चर का पालन करता है (इसमें ऑब्जेक्ट के मामले में चुने गए सभी डिसेंटेंट शामिल होते हैं), जैसा कि नीचे दिए गए उदाहरण में दिखाया गया है.

mutation UpdateMovieTitle2($movieId: UUID!, $newTitle: String!) @auth(level: USER) @transaction {
  # Step 1: Query and check
  query {
    moviePermissions( # Now we query for a list of all matching MoviePermissions.
      where: {movieId: {eq: $movieId}, userId: {eq_expr: "auth.uid"}}
    # This time we execute the @check on the list, so `this` is the list of objects.
    # We can use the `.exists` macro to check if there is at least one matching entry.
    ) @check(expr: "this.exists(p, p.role == 'editor')", message: "You must be an editor of this movie to update title") {
      role
    }
  }
  # Step 2: Act
  movie_update(id: $movieId, data: {
    title: $newTitle
  })
}

कॉम्प्लेक्स एक्सप्रेशन का सिंटैक्स

&& और || ऑपरेटर को मिलाकर, ज़्यादा जटिल एक्सप्रेशन लिखे जा सकते हैं.

mutation UpsertUser($username: String!) @auth(expr: "(auth != null) && (vars.username == 'joe')")

नीचे दिए गए सेक्शन में, सभी उपलब्ध ऑपरेटर के बारे में बताया गया है.

ऑपरेटर और ऑपरेटर की प्राथमिकता

ऑपरेटर और उनके क्रम के रेफ़रंस के लिए, नीचे दी गई टेबल का इस्तेमाल करें.

a और b एक्सप्रेशन, f फ़ील्ड, और i इंडेक्स.

ऑपरेटर ब्यौरा असोसिएटिविटी
a[i] a() a.f इंडेक्स, कॉल, फ़ील्ड ऐक्सेस बाएं से दाएं
!a -a एक आर्ग्युमेंट वाला नेगेटिव दाएं से बाएं
a/b a%b a*b गुणा करने वाले ऑपरेटर बाएं से दाएं
a+b a-b ऐडिटिव ऑपरेटर बाएं से दाएं
a>b a>=b a<b a<=b रिलेशनल ऑपरेटर बाएं से दाएं
a in b सूची या मैप में मौजूद होना बाएं से दाएं
type(a) == t टाइप की तुलना, जहां t के तौर पर bool, int, float, number, string, list, map, timestamp या duration का इस्तेमाल किया जा सकता है बाएं से दाएं
a==b a!=b कंपैरिज़न ऑपरेटर बाएं से दाएं
a && b कंडीशनल ऐंड बाएं से दाएं
a || b कंडीशनल OR बाएं से दाएं
a ? true_value : false_value तीसरे डिग्री का एक्सप्रेशन बाएं से दाएं

पुष्टि करने वाले टोकन में डेटा

auth.token ऑब्जेक्ट में ये वैल्यू हो सकती हैं:

फ़ील्ड ब्यौरा
email खाते से जुड़ा ईमेल पता, अगर मौजूद हो.
email_verified true, अगर उपयोगकर्ता ने पुष्टि की है कि उसके पास email पते का ऐक्सेस है. ईमेल की सेवा देने वाली कुछ कंपनियां, अपने ईमेल पतों की पुष्टि अपने-आप करती हैं.
phone_number खाते से जुड़ा फ़ोन नंबर, अगर मौजूद हो.
name अगर सेट किया गया है, तो उपयोगकर्ता का डिसप्ले नेम.
sub उपयोगकर्ता का Firebase यूआईडी. यह किसी प्रोजेक्ट में यूनीक होता है.
firebase.identities इस उपयोगकर्ता के खाते से जुड़ी सभी पहचानों की डिक्शनरी. डिक्शनरी की कुंजियां इनमें से कोई भी हो सकती हैं: email, phone, google.com, facebook.com, github.com, twitter.com. डिक्शनरी की वैल्यू, खाते से जुड़े हर आइडेंटिटी प्रोवाइडर के लिए यूनीक आइडेंटिफ़ायर के कलेक्शन होती हैं. उदाहरण के लिए, auth.token.firebase.identities["google.com"][0] में खाते से जुड़ा पहला Google उपयोगकर्ता आईडी होता है.
firebase.sign_in_provider इस टोकन को पाने के लिए, साइन इन करने की सुविधा देने वाली कंपनी. यह इनमें से कोई एक स्ट्रिंग हो सकती है: custom, password, phone, anonymous, google.com, facebook.com, github.com, twitter.com.
firebase.tenant खाते से जुड़ा tenantId, अगर मौजूद हो. उदाहरण के लिए, tenant2-m6tyz

JWT आईडी टोकन में अतिरिक्त फ़ील्ड

यहां दिए गए auth.token फ़ील्ड भी ऐक्सेस किए जा सकते हैं:

कस्टम टोकन पर दावे
alg एल्‍गोरि‍दम "RS256"
iss जारी करने वाला आपके प्रोजेक्ट के सेवा खाते का ईमेल पता
sub विषय आपके प्रोजेक्ट के सेवा खाते का ईमेल पता
aud ऑडियंस "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit"
iat जारी करने का समय यूनिक्स के टाइमस्टैंप के बाद से, सेकंड में मौजूदा समय
exp समाप्ति समय यूनिक्स के टाइमस्टैंप के बाद सेकंड में, टोकन की समयसीमा खत्म होने का समय. यह iat के मुकाबले ज़्यादा से ज़्यादा 3600 सेकंड बाद हो सकता है.
ध्यान दें: इससे सिर्फ़ कस्टम टोकन के खत्म होने का समय कंट्रोल होता है. हालांकि, signInWithCustomToken() का इस्तेमाल करके किसी उपयोगकर्ता को साइन इन करने के बाद, वह डिवाइस में तब तक साइन इन रहेगा, जब तक उसका सेशन अमान्य नहीं हो जाता या वह साइन आउट नहीं कर देता.
<claims> (ज़रूरी नहीं) टोकन में शामिल करने के लिए, ज़रूरी नहीं कि कस्टम दावे किए जाएं. इन्हें एक्सप्रेशन में auth.token (या request.auth.token) के ज़रिए ऐक्सेस किया जा सकता है. उदाहरण के लिए, अगर आपने कोई कस्टम दावा adminClaim किया है, तो उसे auth.token.adminClaim से ऐक्सेस किया जा सकता है.

आगे क्या करना है?