Uygulamanız için Google dışı özel arka uç kaynaklarını (ör. kendi kendine barındırılan arka ucunuz) korumak üzere App Check kullanabilirsiniz. Bunun için aşağıdakilerin ikisini de yapmanız gerekir:
- Uygulama istemcinizi, arka uçunuza her istekle birlikte bir App Check jetonu gönderecek şekilde değiştirin. Bu işlem, iOS+, Android, web, Flutter, Unity veya C++ sayfalarında açıklanmıştır.
- Arka ucunuzu, bu sayfada açıklandığı gibi her istekte geçerli bir App Check jetonu gerektirecek şekilde değiştirin.
Jeton doğrulama
Arka uçta App Check jetonlarını doğrulamak için API uç noktalarınıza aşağıdaki işlemleri yapan bir mantık ekleyin:
Her isteğin bir App Check jetonu içerdiğini kontrol edin.
Yönetici SDK'sını kullanarak App Check jetonunu doğrulayın.
Doğrulama başarılı olursa Admin SDK, kodu çözülmüş App Check jetonunu döndürür. Başarılı doğrulama, jetonun Firebase projenize ait bir uygulamadan geldiğini gösterir.
Bu kontrollerden herhangi birinde başarısız olan istekleri reddedin. Örneğin:
Node.js
Henüz yüklemediyseniz Node.js Admin SDK'yı yükleyin.
Ardından, örnek olarak Express.js ara yazılımını kullanarak:
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
Henüz yüklemediyseniz Python Admin SDK'yı yükleyin.
Ardından, API uç noktası işleyicilerinizde app_check.verify_token()
işlevini çağırın ve başarısız olursa isteği reddedin. Aşağıdaki örnekte, @before_request
ile süslenmiş bir işlev, bu görevi tüm istekler için gerçekleştirir:
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
Henüz yüklemediyseniz Go için Admin SDK'yı yükleyin.
Ardından, API uç nokta işleyicilerinizde appcheck.Client.VerifyToken()
işlevini çağırın
ve başarısız olursa isteği reddedin. Aşağıdaki örnekte, bir sarmalayıcı işlev, bu mantığı uç nokta işleyicilerine ekler:
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.
}
Diğer
Arka uçunuz başka bir dilde yazılmışsa App Check jetonlarını doğrulamak için jwt.io adresinde bulunanlar gibi genel amaçlı bir JWT kitaplığı kullanabilirsiniz.
Jeton doğrulama mantığınız aşağıdaki adımları tamamlamalıdır:
- Firebase App Check JWKS uç noktasından Firebase App Check genel JSON Web Anahtarı (JWK) kümesini alın:
https://firebaseappcheck.googleapis.com/v1/jwks
- Meşru olduğundan emin olmak için Uygulama Kontrolü jetonunun imzasını doğrulayın.
- Jetonun başlığında RS256 algoritmasının kullanıldığından emin olun.
- Jetonun başlığının JWT türünde olduğundan emin olun.
- Jetonun, projeniz kapsamında Firebase Uygulama Kontrolü tarafından verildiğinden emin olun.
- Jetonun geçerlilik süresinin dolmadığından emin olun.
- Jetonun hedef kitlesinin projenizle eşleştiğinden emin olun.
- İsteğe bağlı: Jetonun konusunun uygulamanızın uygulama kimliğiyle eşleştiğini kontrol edin.
JWT kitaplıklarının özellikleri farklılık gösterebilir. Seçtiğiniz kitaplık tarafından işlenmeyen adımları manuel olarak tamamladığınızdan emin olun.
Aşağıdaki örnekte, jwt
gem'i bir Rack ara katman yazılımı katmanı olarak kullanarak Ruby'de gerekli adımlar gerçekleştirilir.
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
Tekrar koruması (beta)
Bir uç noktayı tekrar oynatma saldırılarına karşı korumak için, doğruladıktan sonra App Check jetonunu yalnızca bir kez kullanılacak şekilde tüketebilirsiniz.
Yeniden oynatma koruması kullanmak, verifyToken()
görüşmesine bir ağ gidiş dönüşü ekler ve bu nedenle, bunu kullanan tüm uç noktalara gecikme ekler. Bu nedenle, yeniden oynatma korumasını yalnızca özellikle hassas uç noktalarda etkinleştirmenizi öneririz.
Yeniden oynatma korumasını kullanmak için aşağıdakileri yapın:
Cloud Console'da, jetonları doğrulamak için kullanılan hizmet hesabına "Firebase App Check Jeton Doğrulayıcı" rolünü verin.
- Admin SDK'yı Firebase konsolundan indirdiğiniz Admin SDK hizmet hesabı kimlik bilgileriyle başlattıysanız gerekli rol zaten verilmiştir.
- Varsayılan Admin SDK yapılandırmasıyla 1. nesil Cloud Functions kullanıyorsanız rolü App Engine varsayılan hizmet hesabına verin. Hizmet hesabı izinlerini değiştirme başlıklı makaleyi inceleyin.
- Varsayılan Admin SDK yapılandırmasıyla 2. nesil Cloud Functions kullanıyorsanız rolü varsayılan işlem hizmeti hesabına verin.
Ardından, jetonu kullanmak için
{ consume: true }
değeriniverifyToken()
yöntemine iletin ve sonuç nesnesini inceleyin.alreadyConsumed
özelliğitrue
ise isteği reddedin veya arayanın başka kontrolleri geçmesini zorunlu kılmak gibi bir düzeltici işlem yapın.Örneğin:
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.
Bu işlem, jetonu doğrulayıp kullanılmış olarak işaretler. Aynı jetonla gelecekteki
verifyToken(appCheckToken, { consume: true })
çağrıları,alreadyConsumed
değerinitrue
olarak ayarlar. (verifyToken()
ayarlanmamışsaverifyToken()
'nın kullanılan bir jetonu reddetmediğini veya kullanılıp kullanılmadığını kontrol etmediğini unutmayın.)consume
Bu özelliği belirli bir uç nokta için etkinleştirdiğinizde, uç nokta ile kullanılmak üzere tüketilebilir sınırlı kullanım jetonları almak için uygulama istemci kodunuzu da güncellemeniz gerekir. Apple platformları, Android ve web için istemci tarafı dokümanlarına bakın.