Commit
·
2262841
1
Parent(s):
c8627a0
feat: support FIREBASE_CREDENTIALS_JSON env var + improve error handling
Browse files- firebase_app_check.py +45 -21
firebase_app_check.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
| 1 |
import os
|
|
|
|
| 2 |
from typing import Optional
|
| 3 |
|
| 4 |
try:
|
|
@@ -7,9 +8,9 @@ try:
|
|
| 7 |
# App Check verification is available in newer firebase_admin versions
|
| 8 |
try:
|
| 9 |
from firebase_admin import app_check
|
| 10 |
-
except
|
| 11 |
app_check = None
|
| 12 |
-
except
|
| 13 |
firebase_admin = None
|
| 14 |
credentials = None
|
| 15 |
app_check = None
|
|
@@ -19,9 +20,11 @@ _initialized = False
|
|
| 19 |
def initialize_firebase() -> bool:
|
| 20 |
"""Initialize Firebase Admin SDK from env.
|
| 21 |
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
|
|
|
|
|
|
| 25 |
"""
|
| 26 |
global _initialized
|
| 27 |
if _initialized:
|
|
@@ -35,22 +38,37 @@ def initialize_firebase() -> bool:
|
|
| 35 |
_initialized = True
|
| 36 |
return True
|
| 37 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 38 |
cred_path = os.getenv("FIREBASE_CREDENTIALS")
|
| 39 |
-
if
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
|
| 52 |
def verify_app_check_token(token: Optional[str]) -> bool:
|
| 53 |
-
"""Verify Firebase App Check token
|
| 54 |
|
| 55 |
Returns True if verification succeeds. If App Check is not available or
|
| 56 |
not initialized, returns False to indicate verification not possible.
|
|
@@ -58,16 +76,22 @@ def verify_app_check_token(token: Optional[str]) -> bool:
|
|
| 58 |
if not token:
|
| 59 |
return False
|
| 60 |
|
|
|
|
| 61 |
if app_check is None:
|
|
|
|
| 62 |
return False
|
| 63 |
|
| 64 |
if not initialize_firebase():
|
|
|
|
| 65 |
return False
|
| 66 |
|
| 67 |
try:
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
|
|
|
|
|
|
|
|
|
| 71 |
return False
|
| 72 |
|
| 73 |
|
|
|
|
| 1 |
import os
|
| 2 |
+
import json
|
| 3 |
from typing import Optional
|
| 4 |
|
| 5 |
try:
|
|
|
|
| 8 |
# App Check verification is available in newer firebase_admin versions
|
| 9 |
try:
|
| 10 |
from firebase_admin import app_check
|
| 11 |
+
except ImportError:
|
| 12 |
app_check = None
|
| 13 |
+
except ImportError:
|
| 14 |
firebase_admin = None
|
| 15 |
credentials = None
|
| 16 |
app_check = None
|
|
|
|
| 20 |
def initialize_firebase() -> bool:
|
| 21 |
"""Initialize Firebase Admin SDK from env.
|
| 22 |
|
| 23 |
+
Supports two ways to provide credentials:
|
| 24 |
+
1. FIREBASE_CREDENTIALS_JSON: Full JSON content as string
|
| 25 |
+
2. FIREBASE_CREDENTIALS: Path to service account JSON file
|
| 26 |
+
|
| 27 |
+
Optional: FIREBASE_PROJECT_ID to override project ID
|
| 28 |
"""
|
| 29 |
global _initialized
|
| 30 |
if _initialized:
|
|
|
|
| 38 |
_initialized = True
|
| 39 |
return True
|
| 40 |
|
| 41 |
+
# Try JSON content first (for Hugging Face secrets)
|
| 42 |
+
cred_json = os.getenv("FIREBASE_CREDENTIALS_JSON")
|
| 43 |
+
if cred_json:
|
| 44 |
+
try:
|
| 45 |
+
cred_dict = json.loads(cred_json)
|
| 46 |
+
cred = credentials.Certificate(cred_dict)
|
| 47 |
+
firebase_admin.initialize_app(cred, {
|
| 48 |
+
"projectId": os.getenv("FIREBASE_PROJECT_ID") or cred_dict.get("project_id")
|
| 49 |
+
})
|
| 50 |
+
_initialized = True
|
| 51 |
+
return True
|
| 52 |
+
except Exception as e:
|
| 53 |
+
print(f"Warning: Failed to initialize Firebase from JSON: {e}")
|
| 54 |
+
|
| 55 |
+
# Fallback to file path
|
| 56 |
cred_path = os.getenv("FIREBASE_CREDENTIALS")
|
| 57 |
+
if cred_path and os.path.exists(cred_path):
|
| 58 |
+
try:
|
| 59 |
+
cred = credentials.Certificate(cred_path)
|
| 60 |
+
firebase_admin.initialize_app(cred, {
|
| 61 |
+
"projectId": os.getenv("FIREBASE_PROJECT_ID")
|
| 62 |
+
})
|
| 63 |
+
_initialized = True
|
| 64 |
+
return True
|
| 65 |
+
except Exception as e:
|
| 66 |
+
print(f"Warning: Failed to initialize Firebase from file: {e}")
|
| 67 |
+
|
| 68 |
+
return False
|
| 69 |
|
| 70 |
def verify_app_check_token(token: Optional[str]) -> bool:
|
| 71 |
+
"""Verify Firebase App Check token.
|
| 72 |
|
| 73 |
Returns True if verification succeeds. If App Check is not available or
|
| 74 |
not initialized, returns False to indicate verification not possible.
|
|
|
|
| 76 |
if not token:
|
| 77 |
return False
|
| 78 |
|
| 79 |
+
# If App Check module is not available, skip verification
|
| 80 |
if app_check is None:
|
| 81 |
+
print("Warning: Firebase App Check module not available")
|
| 82 |
return False
|
| 83 |
|
| 84 |
if not initialize_firebase():
|
| 85 |
+
print("Warning: Firebase not initialized, skipping App Check verification")
|
| 86 |
return False
|
| 87 |
|
| 88 |
try:
|
| 89 |
+
# Verify the App Check token
|
| 90 |
+
# Note: verify_token() returns decoded token claims if valid, raises exception if invalid
|
| 91 |
+
decoded_token = app_check.verify_token(token)
|
| 92 |
+
return decoded_token is not None
|
| 93 |
+
except Exception as e:
|
| 94 |
+
print(f"Warning: App Check token verification failed: {e}")
|
| 95 |
return False
|
| 96 |
|
| 97 |
|