Uygulama Kontrolü ile uygulamanızın kendi kendine barındırılan arka uçlar gibi Firebase dışı kaynaklarını koruyabilirsiniz. Bunu yapmak için, aşağıdakilerin ikisini de yapmanız gerekir:
- iOS+ , Android ve web sayfalarında açıklandığı gibi arka ucunuza her istekle birlikte bir Uygulama Kontrolü belirteci göndermek için uygulama istemcinizi değiştirin.
- Bu sayfada açıklandığı gibi, her istekte geçerli bir Uygulama Kontrolü belirteci gerektirecek şekilde arka ucunuzu değiştirin.
Belirteç doğrulaması
Arka ucunuzdaki Uygulama Kontrolü belirteçlerini doğrulamak için API uç noktalarınıza aşağıdakileri yapan bir mantık ekleyin:
Her isteğin bir Uygulama Kontrolü belirteci içerdiğini kontrol edin.
Admin SDK'yı kullanarak App Check belirtecini doğrulayın.
Doğrulama başarılı olursa Admin SDK, kodu çözülmüş Uygulama Kontrolü belirtecini döndürür. Başarılı doğrulama, jetonun Firebase projenize ait bir uygulamadan geldiğini gösterir.
Her iki kontrolde de başarısız olan istekleri reddedin. Örneğin:
Node.js
Node.js Admin SDK'yı henüz yüklemediyseniz 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.
});
Piton
Python Admin SDK'yı henüz yüklemediyseniz, kurun.
Ardından, API uç nokta işleyicilerinizde app_check.verify_token()
öğesini çağırın ve başarısız olursa isteği reddedin. Aşağıdaki örnekte, @before_request
ile dekore edilmiş 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.
...
Gitmek
Go için Admin SDK'yı henüz yüklemediyseniz, yükleyin.
Ardından, API uç nokta işleyicilerinizde appcheck.Client.VerifyToken()
öğesini çağırın ve başarısız olursa isteği reddedin. Aşağıdaki örnekte, bir sarmalayıcı işlevi 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 ucunuz başka bir dilde yazılmışsa, Uygulama Kontrolü belirteçlerini doğrulamak için jwt.io'da 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 genel JSON Web Anahtarı (JWK) Setini App Check JWKS uç noktasından edinin:
https://firebaseappcheck.googleapis.com/v1/jwks
- Meşru olduğundan emin olmak için Uygulama Kontrolü belirtecinin imzasını doğrulayın.
- Jeton başlığının RS256 algoritmasını kullandığından emin olun.
- Jeton başlığının JWT tipinde olduğundan emin olun.
- Jetonun, projeniz kapsamında Firebase Uygulama Kontrolü tarafından verildiğinden emin olun.
- Jetonun süresinin dolmadığından emin olun.
- Simgenin hedef kitlesinin projenizle eşleştiğinden emin olun.
- İsteğe bağlı : Simgenin konusunun, uygulamanızın Uygulama Kimliği ile eşleştiğini kontrol edin.
JWT kitaplıklarının yetenekleri farklılık gösterebilir; seçtiğiniz kitaplık tarafından işlenmeyen adımları el ile tamamladığınızdan emin olun.
Aşağıdaki örnek, jwt
gem'i Rack ara yazılımı katmanı olarak kullanarak Ruby'de gerekli adımları gerçekleştirir.
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ı yeniden oynatma saldırılarından korumak için, Uygulama Kontrolü belirtecini doğruladıktan sonra yalnızca bir kez kullanılabilmesi için kullanabilirsiniz.
Yeniden oynatma korumasını kullanmak, verifyToken()
çağrısına bir ağ gidiş gelişi ekler ve bu nedenle, onu kullanan tüm uç noktalara gecikme ekler. Bu nedenle, tekrar korumasını yalnızca özellikle hassas uç noktalarda etkinleştirmenizi öneririz.
Tekrar korumasını kullanmak için aşağıdakileri yapın:
Bulut konsolunda , belirteçleri doğrulamak için kullanılan hizmet hesabına "Firebase App Check Token Verifier" rolü 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 Yönetici SDK yapılandırmasıyla 1. nesil Bulut İşlevlerini kullanıyorsanız rolü App Engine varsayılan hizmet hesabına atayın. Hizmet hesabı izinlerini değiştirme konusuna bakın.
- Varsayılan Yönetici SDK yapılandırmasıyla 2. nesil Bulut İşlevlerini kullanıyorsanız, rolü Varsayılan bilgi işlem hizmeti hesabına atayın.
Ardından, bir jetonu tüketmek için,
verifyToken()
yöntemine{ consume: true }
iletin ve sonuç nesnesini inceleyin;alreadyConsumed
özelliğitrue
ise, isteği reddedin veya arayanın diğer kontrolleri geçmesini istemek gibi bir tür 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, belirteci doğrular ve ardından tüketildi olarak işaretler. Aynı belirteç üzerinde
verifyToken(appCheckToken, { consume: true })
öğesinin gelecekteki çağrıları,alreadyConsumed
öğesinitrue
olarak ayarlayacaktır. (verifyToken()
öğesinin tüketilen bir belirteci reddetmediğini ve hattaconsume
ayarlanmamışsa tüketilip tüketilmediğini kontrol etmediğini unutmayın.)
Bu özelliği belirli bir uç nokta için etkinleştirdiğinizde, uç noktayla kullanım için tüketilebilir sınırlı kullanım belirteçleri almak üzere uygulama istemci kodunuzu da güncellemeniz gerekir. Apple platformları , Android ve web için istemci tarafı belgelerine bakın.