একটি কাস্টম ব্যাকএন্ড থেকে অ্যাপ চেক টোকেন যাচাই করুন

আপনি অ্যাপ চেকের মাধ্যমে আপনার অ্যাপের নন-ফায়ারবেস সংস্থানগুলি যেমন স্ব-হোস্টেড ব্যাকএন্ডগুলি রক্ষা করতে পারেন৷ এটি করার জন্য, আপনাকে নিম্নলিখিত উভয়টি করতে হবে:

  • আপনার ব্যাকএন্ডে প্রতিটি অনুরোধের সাথে একটি অ্যাপ চেক টোকেন পাঠাতে আপনার অ্যাপ ক্লায়েন্টকে পরিবর্তন করুন, যেমনটি iOS+ , Android এবং ওয়েবের পৃষ্ঠাগুলিতে বর্ণিত হয়েছে।
  • এই পৃষ্ঠায় বর্ণিত প্রতিটি অনুরোধের সাথে একটি বৈধ অ্যাপ চেক টোকেনের প্রয়োজনে আপনার ব্যাকএন্ড পরিবর্তন করুন।

টোকেন যাচাইকরণ

আপনার ব্যাকএন্ডে অ্যাপ চেক টোকেন যাচাই করতে, আপনার API এন্ডপয়েন্টগুলিতে যুক্তি যোগ করুন যা নিম্নলিখিতগুলি করে:

  • প্রতিটি অনুরোধে একটি অ্যাপ চেক টোকেন অন্তর্ভুক্ত রয়েছে তা পরীক্ষা করুন।

  • অ্যাডমিন SDK ব্যবহার করে অ্যাপ চেক টোকেন যাচাই করুন।

    যাচাইকরণ সফল হলে, অ্যাডমিন SDK ডিকোড করা অ্যাপ চেক টোকেন ফেরত দেয়। সফল যাচাইকরণ নির্দেশ করে যে টোকেনটি আপনার ফায়ারবেস প্রকল্পের অন্তর্গত একটি অ্যাপ থেকে উদ্ভূত হয়েছে।

চেক ব্যর্থ হয় যে কোনো অনুরোধ প্রত্যাখ্যান. উদাহরণ স্বরূপ:

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.
});

পাইথন

আপনি যদি ইতিমধ্যে পাইথন অ্যাডমিন SDK ইনস্টল না করে থাকেন তবে তা করুন৷

তারপর, আপনার API এন্ডপয়েন্ট হ্যান্ডলারে, 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 ইনস্টল না করে থাকেন তবে তা করুন৷

তারপর, আপনার API এন্ডপয়েন্ট হ্যান্ডলারে, 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- তে পাওয়া একটি।

আপনার টোকেন যাচাইকরণ যুক্তিকে অবশ্যই নিম্নলিখিত পদক্ষেপগুলি সম্পূর্ণ করতে হবে:

  1. ফায়ারবেস অ্যাপ পান অ্যাপ থেকে জেএসএন ওয়েব কী (JWK) সেট চেক পাবলিক চেক JWKS এন্ডপয়েন্ট: https://firebaseappcheck.googleapis.com/v1/jwks
  2. এটি বৈধ কিনা তা নিশ্চিত করতে অ্যাপ চেক টোকেনের স্বাক্ষর যাচাই করুন।
  3. নিশ্চিত করুন যে টোকেনের হেডারটি অ্যালগরিদম RS256 ব্যবহার করছে।
  4. নিশ্চিত করুন যে টোকেনের হেডারে JWT টাইপ আছে।
  5. আপনার প্রকল্পের অধীনে Firebase অ্যাপ চেক দ্বারা টোকেন জারি করা হয়েছে তা নিশ্চিত করুন।
  6. নিশ্চিত করুন যে টোকেনের মেয়াদ শেষ হয়নি।
  7. নিশ্চিত করুন যে টোকেনের দর্শক আপনার প্রকল্পের সাথে মেলে।
  8. ঐচ্ছিক : টোকেনের বিষয় আপনার অ্যাপের অ্যাপ আইডির সাথে মেলে কিনা তা পরীক্ষা করুন।

JWT লাইব্রেরির ক্ষমতা ভিন্ন হতে পারে; আপনার চয়ন করা লাইব্রেরি দ্বারা পরিচালিত নয় এমন কোনও পদক্ষেপ ম্যানুয়ালি সম্পূর্ণ করতে ভুলবেন না।

নিচের উদাহরণটি র্যাক মিডলওয়্যার স্তর হিসাবে 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. ক্লাউড কনসোলে , টোকেন যাচাই করতে ব্যবহৃত পরিষেবা অ্যাকাউন্টে "Firebase অ্যাপ চেক টোকেন যাচাইকারী" ভূমিকা মঞ্জুর করুন৷

    • আপনি Firebase কনসোল থেকে ডাউনলোড করা অ্যাডমিন SDK পরিষেবা অ্যাকাউন্টের শংসাপত্রগুলির সাথে অ্যাডমিন SDK শুরু করলে, প্রয়োজনীয় ভূমিকা ইতিমধ্যেই মঞ্জুর করা হয়েছে৷
    • আপনি যদি ডিফল্ট অ্যাডমিন SDK কনফিগারেশন সহ 1ম প্রজন্মের ক্লাউড ফাংশন ব্যবহার করেন, অ্যাপ ইঞ্জিন ডিফল্ট পরিষেবা অ্যাকাউন্টে ভূমিকাটি মঞ্জুর করুন৷ পরিষেবা অ্যাকাউন্টের অনুমতি পরিবর্তন করা দেখুন।
    • আপনি যদি ডিফল্ট অ্যাডমিন 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 এবং ওয়েবের জন্য ক্লায়েন্ট-সাইড ডক্স দেখুন।