您可以保護應用程式的非 Firebase 資源,例如自行管理的後端。 與 App Check 整合如要這麼做,您需要執行這兩項操作:
權杖驗證
如要在後端驗證 App Check 權杖,請將邏輯新增至 API 端點 負責執行以下作業:
檢查每個要求是否包含 App Check 權杖。
使用 Admin SDK 驗證 App Check 權杖。
如果驗證成功,Admin SDK 會傳回已解碼的 App Check 產生下一個符記驗證成功表示應用程式產生的權杖 隸屬於 Firebase 專案中
拒絕任何未通過任一檢查的要求。例如:
Node.js
如果您尚未安裝 Node.js Admin 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 Admin 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
如果您尚未安裝 Admin SDK for 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 程式庫,例如 jwt.io,用於驗證 App Check 權杖。
您的權杖驗證邏輯必須完成下列步驟:
- 從應用程式取得 Firebase App Check 公開 JSON Web Key (JWK) 集
檢查 JWKS 端點:
https://firebaseappcheck.googleapis.com/v1/jwks
- 驗證 App Check 權杖的簽章,確保其合法性。
- 確認權杖的標頭使用演算法 RS256。
- 確認權杖的標頭含有 JWT 類型。
- 確認權杖是由 Firebase App Check 核發 專案。
- 確認權杖並未過期。
- 確認權杖的目標對象與專案相符。
- 選用:檢查權杖的主旨是否與應用程式的應用程式 ID 相符。
JWT 程式庫的功能可能有所不同。請務必手動完成 所選程式庫未處理的任何步驟。
以下範例使用 jwt
在 Ruby 中執行必要步驟
gem 做為 Rack 中介軟體層
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
重播防護措施 (Beta 版)
如要防止端點受到重送攻擊,可以使用 App Check 權杖 並確定其只能使用一次。
使用重送防護功能會新增網路往返至 verifyToken()
呼叫,因此會增加使用該端點的端點。因此
建議您只在非常敏感時,才啟用重播保護機制
端點。
如要使用重播防護功能,請執行下列操作:
在 Cloud 控制台 授予「Firebase App Check 權杖驗證者」授予服務帳戶的角色 以便驗證權杖
- 如果您使用 Admin SDK 服務帳戶初始化 Admin SDK 憑證,就必須具備必要的角色 。
- 如果您是搭配預設管理員使用第 1 代 Cloud Functions SDK 設定,將角色授予 App Engine 預設服務 帳戶。請參閱變更服務帳戶權限。
- 如果您是搭配預設管理員使用第 2 代 Cloud Functions SDK 設定,將角色授予預設運算服務 帳戶。
接著,如要取用符記,請將
{ consume: true }
傳遞至verifyToken()
方法,並檢查結果物件;如果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,以及 網頁。