किसी कस्टम बैकएंड से, ऐप्लिकेशन की जांच वाले टोकन की पुष्टि करें

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

  • अपने ऐप्लिकेशन क्लाइंट में बदलाव करें, ताकि वह हर अनुरोध के साथ App Check टोकन भेज सके को आपके बैकएंड के लिए कस्टमाइज़ किया जा सकता है, जैसा कि iOS+ Android, और वेब.
  • अपने बैकएंड में बदलाव करें, ताकि हर अनुरोध के साथ एक मान्य ऐप्लिकेशन चेक टोकन ज़रूरी हो. जैसा कि इस पेज पर बताया गया है.

टोकन की पुष्टि

अपने बैकएंड पर, ऐप्लिकेशन की जांच वाले टोकन की पुष्टि करने के लिए, अपने एपीआई एंडपॉइंट में लॉजिक जोड़ें जो:

  • यह देखें कि हर अनुरोध में, ऐप्लिकेशन की जांच के लिए टोकन शामिल है या नहीं.

  • एडमिन SDK का इस्तेमाल करके, ऐप्लिकेशन की जांच वाले टोकन की पुष्टि करें.

    अगर पुष्टि हो जाती है, तो एडमिन SDK टूल, डिकोड किए गए ऐप्लिकेशन की जांच करता है टोकन. पुष्टि होने से पता चलता है कि किसी ऐप्लिकेशन से बनाया गया टोकन आपका Firebase प्रोजेक्ट क्या है.

जांच में फ़ेल होने वाले किसी भी अनुरोध को अस्वीकार कर दें. उदाहरण के लिए:

Node.js

अगर आपने पहले से Node.js एडमिन SDK इंस्टॉल नहीं किया है, तो शामिल हैं.

इसके बाद, उदाहरण के तौर पर Express.js मिडलवेयर का इस्तेमाल करके:

import express from "express";
import { initializeApp } from "firebase-admin/app";
import { getAppCheck } from "firebase-admin/app-check";

const expressApp = express();
const firebaseApp = initializeApp();

const appCheckVerification = async (req, res, next) => {
    const appCheckToken = req.header("X-Firebase-AppCheck");

    if (!appCheckToken) {
        res.status(401);
        return next("Unauthorized");
    }

    try {
        const appCheckClaims = await getAppCheck().verifyToken(appCheckToken);

        // If verifyToken() succeeds, continue with the next middleware
        // function in the stack.
        return next();
    } catch (err) {
        res.status(401);
        return next("Unauthorized");
    }
}

expressApp.get("/yourApiEndpoint", [appCheckVerification], (req, res) => {
    // Handle request.
});

Python

अगर आपने पहले से Python एडमिन SDK इंस्टॉल नहीं किया है, तो शामिल हैं.

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

import firebase_admin
from firebase_admin import app_check
import flask
import jwt

firebase_app = firebase_admin.initialize_app()
flask_app = flask.Flask(__name__)

@flask_app.before_request
def verify_app_check() -> None:
    app_check_token = flask.request.headers.get("X-Firebase-AppCheck", default="")
    try:
        app_check_claims = app_check.verify_token(app_check_token)
        # If verify_token() succeeds, okay to continue to route handler.
    except (ValueError, jwt.exceptions.DecodeError):
        flask.abort(401)

@flask_app.route("/yourApiEndpoint")
def your_api_endpoint(request: flask.Request):
    # Handle request.
    ...

शुरू करें

अगर आपने पहले से Go के लिए एडमिन SDK इंस्टॉल नहीं किया है, तो शामिल हैं.

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

package main

import (
    "context"
    "log"
    "net/http"

    firebaseAdmin "firebase.google.com/go/v4"
    "firebase.google.com/go/v4/appcheck"
)

var (
    appCheck *appcheck.Client
)

func main() {
    app, err := firebaseAdmin.NewApp(context.Background(), nil)
    if err != nil {
        log.Fatalf("error initializing app: %v\n", err)
    }

    appCheck, err = app.AppCheck(context.Background())
    if err != nil {
        log.Fatalf("error initializing app: %v\n", err)
    }

    http.HandleFunc("/yourApiEndpoint", requireAppCheck(yourApiEndpointHandler))
    log.Fatal(http.ListenAndServe(":8080", nil))
}

func requireAppCheck(handler func(http.ResponseWriter, *http.Request)) func(http.ResponseWriter, *http.Request) {
    wrappedHandler := func(w http.ResponseWriter, r *http.Request) {
        appCheckToken, ok := r.Header[http.CanonicalHeaderKey("X-Firebase-AppCheck")]
        if !ok {
            w.WriteHeader(http.StatusUnauthorized)
            w.Write([]byte("Unauthorized."))
            return
        }

        _, err := appCheck.VerifyToken(appCheckToken[0])
        if err != nil {
            w.WriteHeader(http.StatusUnauthorized)
            w.Write([]byte("Unauthorized."))
            return
        }

        // If VerifyToken() succeeds, continue with the provided handler.
        handler(w, r)
    }
    return wrappedHandler
}

func yourApiEndpointHandler(w http.ResponseWriter, r *http.Request) {
    // Handle request.
}

अन्य

अगर आपका बैकएंड किसी दूसरी भाषा में लिखा गया है, तो अलग-अलग कामों के लिए इस्तेमाल की जाने वाली JWT लाइब्रेरी, जो कि jwt.io. इसका इस्तेमाल करके, App Check टोकन की पुष्टि की जा सकती है.

टोकन की पुष्टि करने वाले लॉजिक को ये चरण पूरे करने होंगे:

  1. ऐप्लिकेशन से 'Firebase ऐप्लिकेशन जांच' की सार्वजनिक JSON वेब कुंजी (JWK) सेट पाएं JWKS एंडपॉइंट की जांच करें: https://firebaseappcheck.googleapis.com/v1/jwks अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है
  2. App Check टोकन के हस्ताक्षर की पुष्टि करके यह पक्का किया जा सकता है कि हस्ताक्षर सही है.
  3. पक्का करें कि टोकन का हेडर, एल्गोरिदम RS256 का इस्तेमाल करता हो.
  4. पक्का करें कि टोकन के हेडर का टाइप JWT है.
  5. पक्का करें कि टोकन को Firebase ऐप्लिकेशन जांच के ज़रिए जारी किया गया हो. प्रोजेक्ट.
  6. पक्का करें कि टोकन की समयसीमा खत्म न हुई हो.
  7. पक्का करें कि टोकन की ऑडियंस, आपके प्रोजेक्ट से मेल खाती हो.
  8. ज़रूरी नहीं: देखें कि टोकन का विषय, आपके ऐप्लिकेशन के ऐप्लिकेशन आईडी से मेल खाता है या नहीं.

JWT लाइब्रेरी की क्षमताएं अलग-अलग हो सकती हैं; मैन्युअल तरीके से पूरा करना न भूलें कोई भी चरण जिसे आपकी चुनी गई लाइब्रेरी में शामिल नहीं किया जाता.

यहां दिए गए उदाहरण में, Ruby में jwt का इस्तेमाल करके ज़रूरी चरणों को पूरा करने के बारे में बताया गया है जेम को रैक मिडलवेयर लेयर के तौर पर इस्तेमाल करना.

require 'json'
require 'jwt'
require 'net/http'
require 'uri'

class AppCheckVerification
def initialize(app, options = {})
    @app = app
    @project_number = options[:project_number]
end

def call(env)
    app_id = verify(env['HTTP_X_FIREBASE_APPCHECK'])
    return [401, { 'Content-Type' => 'text/plain' }, ['Unauthenticated']] unless app_id
    env['firebase.app'] = app_id
    @app.call(env)
end

def verify(token)
    return unless token

    # 1. Obtain the Firebase App Check Public Keys
    # Note: It is not recommended to hard code these keys as they rotate,
    # but you should cache them for up to 6 hours.
    uri = URI('https://firebaseappcheck.googleapis.com/v1/jwks')
    jwks = JSON(Net::HTTP.get(uri))

    # 2. Verify the signature on the App Check token
    payload, header = JWT.decode(token, nil, true, jwks: jwks, algorithms: 'RS256')

    # 3. Ensure the token's header uses the algorithm RS256
    return unless header['alg'] == 'RS256'

    # 4. Ensure the token's header has type JWT
    return unless header['typ'] == 'JWT'

    # 5. Ensure the token is issued by App Check
    return unless payload['iss'] == "https://firebaseappcheck.googleapis.com/#{@project_number}"

    # 6. Ensure the token is not expired
    return unless payload['exp'] > Time.new.to_i

    # 7. Ensure the token's audience matches your project
    return unless payload['aud'].include? "projects/#{@project_number}"

    # 8. The token's subject will be the app ID, you may optionally filter against
    # an allow list
    payload['sub']
rescue
end
end

class Application
def call(env)
    [200, { 'Content-Type' => 'text/plain' }, ["Hello app #{env['firebase.app']}"]]
end
end

use AppCheckVerification, project_number: 1234567890
run Application.new

रीप्ले प्रोटेक्शन (बीटा वर्शन)

एंडपॉइंट को फिर से चलाने वाले हमलों से सुरक्षित रखने के लिए, ऐप्लिकेशन की जांच वाले टोकन का इस्तेमाल किया जा सकता है ताकि इसका इस्तेमाल सिर्फ़ एक बार किया जा सके.

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

रीप्ले सुरक्षा का इस्तेमाल करने के लिए, ये काम करें:

  1. इस Cloud Console, "Firebase ऐप्लिकेशन चेक टोकन की पुष्टि करने वाले" को मंज़ूरी दें सेवा खाते की भूमिका इसका इस्तेमाल टोकन की पुष्टि करने के लिए किया जाता है.

    • अगर आपने 'एडमिन SDK' सेवा खाते से 'एडमिन SDK' को शुरू किया है, तो Firebase कंसोल से डाउनलोड किए गए क्रेडेंशियल के लिए, ज़रूरी भूमिका है पहले ही स्वीकार कर लिया है.
    • अगर पहली जनरेशन के Cloud Functions का इस्तेमाल, डिफ़ॉल्ट एडमिन के साथ किया जा रहा है, तो SDK कॉन्फ़िगरेशन, App Engine डिफ़ॉल्ट सेवा को भूमिका दें जोड़ें. सेवा खाते की अनुमतियां बदलना लेख पढ़ें.
    • अगर दूसरी पीढ़ी के Cloud Functions का इस्तेमाल, डिफ़ॉल्ट एडमिन के साथ किया जा रहा है, तो SDK टूल कॉन्फ़िगरेशन, कंप्यूट सेवा की डिफ़ॉल्ट सेवा को भूमिका दें जोड़ें.
  2. इसके बाद, टोकन का इस्तेमाल करने के लिए, verifyToken() को { consume: true } पास करें विधि का इस्तेमाल करें और नतीजे के लिए ऑब्जेक्ट की जांच करें; अगर alreadyConsumed प्रॉपर्टी true, अनुरोध को अस्वीकार कर दें या सुधार करने से जुड़ी कोई कार्रवाई करें, जैसे कॉलर से अन्य चेक पास करने के लिए कहना.

    उदाहरण के लिए:

    const appCheckClaims = await getAppCheck().verifyToken(appCheckToken, { consume: true });
    
    if (appCheckClaims.alreadyConsumed) {
        res.status(401);
        return next('Unauthorized');
    }
    
    // If verifyToken() succeeds and alreadyConsumed is not set, okay to continue.
    

    यह टोकन की पुष्टि करता है और फिर उसे 'इस्तेमाल किया गया' के तौर पर फ़्लैग करता है. आने वाले समय के लिए बातचीत verifyToken(appCheckToken, { consume: true }) का इस्तेमाल करने पर alreadyConsumed को true पर सेट करें. ध्यान दें कि verifyToken() इस्तेमाल किए जा चुके टोकन को अस्वीकार नहीं करता. इसके अलावा, यह भी जांच करता है कि अगर consume को सेट नहीं किया जाता है, तो इसका इस्तेमाल किया जा सकता है.)

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