আপনি আপনার অ্যাপের জন্য গুগল-বহির্ভূত কাস্টম ব্যাকএন্ড রিসোর্স, যেমন আপনার নিজস্ব সেলফ-হোস্টেড ব্যাকএন্ড, সুরক্ষিত করতে App Check ব্যবহার করতে পারেন। এটি করার জন্য, আপনাকে নিম্নলিখিত দুটি কাজই করতে হবে:
- iOS+ , Android , web , Flutter , Unity , বা C++ এর পেজগুলিতে বর্ণিত পদ্ধতি অনুযায়ী, আপনার অ্যাপ ক্লায়েন্টকে এমনভাবে পরিবর্তন করুন যাতে এটি আপনার ব্যাকএন্ডে প্রতিটি অনুরোধের সাথে একটি App Check টোকেন পাঠায়।
- এই পৃষ্ঠায় বর্ণিত পদ্ধতি অনুযায়ী, প্রতিটি অনুরোধের জন্য একটি বৈধ App Check টোকেন আবশ্যক করতে আপনার ব্যাকএন্ড পরিবর্তন করুন।
টোকেন যাচাইকরণ
আপনার ব্যাকএন্ডে App Check টোকেন যাচাই করার জন্য, আপনার এপিআই এন্ডপয়েন্টগুলিতে এমন লজিক যোগ করুন যা নিম্নলিখিত কাজগুলো করে:
নিশ্চিত করুন যে প্রতিটি অনুরোধে একটি App Check টোকেন অন্তর্ভুক্ত আছে।
অ্যাডমিন এসডিকে ব্যবহার করে App Check টোকেনটি যাচাই করুন।
যাচাইকরণ সফল হলে, অ্যাডমিন এসডিকে ডিকোড করা App Check টোকেনটি ফেরত দেয়। সফল যাচাইকরণ নির্দেশ করে যে টোকেনটি আপনার ফায়ারবেস প্রজেক্টের অন্তর্গত কোনো অ্যাপ থেকে এসেছে।
যে কোনো অনুরোধ যা উভয় যাচাইয়ে ব্যর্থ হয়, তা প্রত্যাখ্যান করুন। উদাহরণস্বরূপ:
নোড.জেএস
আপনি যদি এখনও 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.
});
পাইথন
আপনি যদি এখনও পাইথন অ্যাডমিন এসডিকে ইনস্টল না করে থাকেন, তবে তা করে নিন।
তারপর, আপনার 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-এর জন্য অ্যাডমিন এসডিকে ইনস্টল না করে থাকেন, তবে তা করে নিন।
এরপর, আপনার 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.io- এর মতো কোনো সাধারণ JWT লাইব্রেরি ব্যবহার করতে পারেন।
আপনার টোকেন যাচাইকরণ লজিককে অবশ্যই নিম্নলিখিত ধাপগুলো সম্পন্ন করতে হবে:
- অ্যাপ চেক JWKS এন্ডপয়েন্ট থেকে Firebase App Check পাবলিক JSON ওয়েব কী (JWK) সেটটি সংগ্রহ করুন:
https://firebaseappcheck.googleapis.com/v1/jwks - অ্যাপ চেক টোকেনটির স্বাক্ষর যাচাই করে নিশ্চিত করুন যে এটি বৈধ।
- নিশ্চিত করুন যে টোকেনের হেডারে RS256 অ্যালগরিদম ব্যবহার করা হয়েছে।
- নিশ্চিত করুন যে টোকেনটির হেডারের টাইপ JWT।
- নিশ্চিত করুন যে টোকেনটি আপনার প্রোজেক্টের অধীনে Firebase App Check দ্বারা ইস্যু করা হয়েছে।
- নিশ্চিত করুন যে টোকেনটির মেয়াদ শেষ হয়ে যায়নি।
- নিশ্চিত করুন যে টোকেনটির ব্যবহারকারী গোষ্ঠী আপনার প্রকল্পের সাথে মেলে।
- ঐচ্ছিক : যাচাই করুন যে টোকেনটির বিষয়বস্তু আপনার অ্যাপের অ্যাপ আইডির সাথে মেলে কিনা।
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() কলে একটি নেটওয়ার্ক রাউন্ড ট্রিপ যুক্ত হয়, এবং এর ফলে এটি ব্যবহারকারী যেকোনো এন্ডপয়েন্টে ল্যাটেন্সি বেড়ে যায়। এই কারণে, আমরা সুপারিশ করি যে আপনি শুধুমাত্র বিশেষভাবে সংবেদনশীল এন্ডপয়েন্টগুলিতেই রিপ্লে প্রোটেকশন চালু করুন।
রিপ্লে সুরক্ষা ব্যবহার করতে, নিম্নলিখিতগুলি করুন:
ক্লাউড কনসোলে , টোকেন যাচাই করতে ব্যবহৃত সার্ভিস অ্যাকাউন্টটিকে 'Firebase App Check Token Verifier' রোলটি প্রদান করুন।
- আপনি যদি Firebase কনসোল থেকে ডাউনলোড করা অ্যাডমিন এসডিকে সার্ভিস অ্যাকাউন্টের ক্রেডেনশিয়াল ব্যবহার করে অ্যাডমিন এসডিকে চালু করে থাকেন, তাহলে প্রয়োজনীয় রোলটি ইতিমধ্যেই মঞ্জুর করা আছে।
- আপনি যদি ডিফল্ট অ্যাডমিন SDK কনফিগারেশনের সাথে প্রথম প্রজন্মের ক্লাউড ফাংশন ব্যবহার করেন, তাহলে অ্যাপ ইঞ্জিনের ডিফল্ট সার্ভিস অ্যাকাউন্টকে রোলটি প্রদান করুন। সার্ভিস অ্যাকাউন্টের অনুমতি পরিবর্তন দেখুন।
- আপনি যদি ডিফল্ট অ্যাডমিন এসডিকে কনফিগারেশনের সাথে দ্বিতীয় প্রজন্মের ক্লাউড ফাংশন ব্যবহার করেন, তাহলে ডিফল্ট কম্পিউট সার্ভিস অ্যাকাউন্টকে রোলটি প্রদান করুন।
এরপর, একটি টোকেন ব্যবহার করতে,
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.এটি টোকেনটি যাচাই করে এবং তারপর সেটিকে ব্যবহৃত (consumed) হিসেবে চিহ্নিত করে। একই টোকেনের উপর
verifyToken(appCheckToken, { consume: true })এর পরবর্তী প্রয়োগalreadyConsumedtrueসেট করবে। (উল্লেখ্য যে, যদিconsumeসেট করা না থাকে, তাহলেverifyToken()একটি ব্যবহৃত টোকেন প্রত্যাখ্যান করে না বা সেটি ব্যবহৃত হয়েছে কিনা তাও যাচাই করে না।)
যখন আপনি কোনো নির্দিষ্ট এন্ডপয়েন্টের জন্য এই ফিচারটি চালু করবেন, তখন সেই এন্ডপয়েন্টে ব্যবহারের জন্য ব্যবহারযোগ্য সীমিত-সময়ের টোকেন সংগ্রহ করতে আপনাকে অবশ্যই আপনার অ্যাপ ক্লায়েন্ট কোডও আপডেট করতে হবে। Apple প্ল্যাটফর্ম , Android এবং ওয়েবের জন্য ক্লায়েন্ট-সাইড ডকুমেন্টেশন দেখুন।