Xác thực các yêu cầu API Địa điểm bằng Firebase AppCheck và reCAPTCHA

1. Trước khi bắt đầu

Để đảm bảo tính hợp pháp của người dùng tương tác với ứng dụng web, bạn sẽ triển khai tính năng Kiểm tra ứng dụng Firebase, tận dụng mã thông báo JWT reCAPTCHA để xác minh phiên hoạt động của người dùng. Chế độ thiết lập này sẽ cho phép bạn xử lý an toàn các yêu cầu từ ứng dụng khách đến Places API (Mới).

b40cfddb731786fa.png

Đường liên kết trực tiếp

Sản phẩm bạn sẽ tạo ra.

Để minh hoạ điều này, bạn sẽ tạo một ứng dụng web hiển thị bản đồ khi tải. Mã này cũng sẽ tạo một mã thông báo reCAPTCHA một cách kín đáo bằng cách sử dụng SDK Firebase. Sau đó, mã thông báo này được gửi đến máy chủ Node.js của bạn, nơi Firebase xác thực mã thông báo đó trước khi thực hiện bất kỳ yêu cầu nào đối với API Địa điểm.

Nếu mã thông báo hợp lệ, Firebase App Check sẽ lưu trữ mã thông báo đó cho đến khi mã hết hạn, nhờ đó, bạn không cần tạo mã thông báo mới cho mỗi yêu cầu của ứng dụng. Nếu mã không hợp lệ, người dùng sẽ được nhắc hoàn tất quy trình xác minh reCAPTCHA một lần nữa để nhận mã mới.

2. Điều kiện tiên quyết

Bạn cần làm quen với các mục dưới đây để hoàn thành Lớp học lập trình này. daea823b6bc38b67.png

Các sản phẩm Google Cloud bắt buộc

  • Google Cloud Firebase App Check: cơ sở dữ liệu để quản lý mã thông báo
  • Google reCAPTCHA: tạo và xác minh mã thông báo. Đây là một công cụ dùng để phân biệt con người với bot trên các trang web. Công cụ này hoạt động bằng cách phân tích hành vi của người dùng, các thuộc tính của trình duyệt và thông tin mạng để tạo ra một điểm số cho biết khả năng người dùng là bot. Nếu điểm số đủ cao, người dùng được coi là người thật và bạn không cần làm gì thêm. Nếu điểm số thấp, một câu đố CAPTCHA có thể xuất hiện để xác nhận danh tính của người dùng. Phương pháp này ít gây phiền hà hơn so với các phương thức CAPTCHA truyền thống, giúp người dùng có trải nghiệm mượt mà hơn.
  • (Không bắt buộc) Google Cloud App Engine: môi trường triển khai.

Các sản phẩm bắt buộc của Nền tảng Google Maps

Trong lớp học lập trình này, bạn sẽ sử dụng các sản phẩm sau đây của Nền tảng Google Maps:

Các yêu cầu khác đối với lớp học lập trình này

Để hoàn thành Lớp học lập trình này, bạn cần có các tài khoản, dịch vụ và công cụ sau:

  • Tài khoản Google Cloud Platform đã bật tính năng thanh toán
  • Khoá API Google Maps Platform đã bật API JavaScript của Maps và Places
  • Kiến thức cơ bản về JavaScript, HTML và CSS
  • Kiến thức cơ bản về Node.js
  • Trình soạn thảo văn bản hoặc IDE mà bạn chọn

3. Bắt đầu thiết lập

Thiết lập Nền tảng Google Maps

Nếu bạn chưa có tài khoản Google Cloud Platform và dự án đã bật tính năng thanh toán, vui lòng xem hướng dẫn Bắt đầu sử dụng Google Maps Platform để tạo tài khoản thanh toán và dự án.

  1. Trong Cloud Console, hãy nhấp vào trình đơn thả xuống của dự án rồi chọn dự án mà bạn muốn sử dụng cho lớp học lập trình này.

e7ffad81d93745cd.png

  1. Bật các API và SDK của Nền tảng Google Maps cần thiết cho lớp học lập trình này trong Google Cloud Marketplace. Để làm như vậy, hãy làm theo các bước trong video này hoặc tài liệu này.
  2. Tạo khoá API trong trang Thông tin xác thực của Cloud Console. Bạn có thể làm theo các bước trong video này hoặc tài liệu này. Tất cả yêu cầu gửi đến Nền tảng Google Maps đều yêu cầu khoá API.

Thông tin xác thực mặc định của ứng dụng

Bạn sẽ sử dụng SDK quản trị Firebase để tương tác với dự án Firebase cũng như gửi yêu cầu đến API Địa điểm và cần cung cấp thông tin xác thực hợp lệ để API này hoạt động.

Chúng tôi sẽ sử dụng tính năng Xác thực ADC (Thông tin xác thực mặc định tự động) để xác thực máy chủ của bạn nhằm đưa ra yêu cầu. Ngoài ra (không nên), bạn có thể tạo một tài khoản dịch vụ và lưu trữ thông tin xác thực trong mã của mình.

Định nghĩa: Thông tin xác thực mặc định của ứng dụng (ADC) là một cơ chế mà Google Cloud cung cấp để tự động xác thực các ứng dụng của bạn mà không cần quản lý thông tin xác thực một cách rõ ràng. Phương thức này tìm thông tin xác thực ở nhiều vị trí (chẳng hạn như biến môi trường, tệp tài khoản dịch vụ hoặc máy chủ siêu dữ liệu Google Cloud) và sử dụng thông tin xác thực đầu tiên tìm thấy.

  • Trong Terminal, hãy sử dụng lệnh dưới đây để cho phép các ứng dụng của bạn thay mặt cho người dùng hiện đã đăng nhập truy cập an toàn vào các tài nguyên của Google Cloud:
gcloud auth application-default login
  • Bạn sẽ tạo một tệp .env ở thư mục gốc để chỉ định biến Dự án Google Cloud:
GOOGLE_CLOUD_PROJECT="your-project-id"

Tạo một tài khoản dịch vụ

  • Thẻ Google Maps Platform > "+Create Credentials" (Tạo thông tin xác thực) > Tài khoản dịch vụ
  • Thêm vai trò Quản trị viên Firebase AppCheck, sau đó nhập tên tài khoản dịch vụ mà bạn vừa nhập, tức là: firebase-appcheck-codelab@yourproject.iam.gserviceaccount.com

Thông tin xác thực

  • Nhấp vào tài khoản dịch vụ đã tạo
  • Chuyển đến thẻ KHÓA để Tạo khoá > JSON > lưu thông tin xác thực json đã tải xuống. Di chuyển tệp xxx.json được tải xuống tự động vào thư mục gốc
  • (Chương tiếp theo) Đặt tên chính xác cho tệp này trong tệp nodejs server.js (firebase-credentials.json)

4. Tích hợp Firebase AppCheck

Bạn sẽ nhận được thông tin chi tiết về cấu hình Firebase và khoá bí mật reCAPTCHA.

Bạn sẽ dán các tệp này vào ứng dụng minh hoạ và khởi động máy chủ.

Tạo ứng dụng trong Firebase

CHỌN dự án Google Cloud đã tạo (bạn có thể phải chỉ định: "Chọn tài nguyên mẹ")"

a6d171c6d7e98087.png a16010ba102cc90b.png

  • Thêm một Ứng dụng từ Trình đơn (biểu tượng bánh răng) ở trên cùng bên trái

18e5a7993ad9ea53.png 4632158304652118.png

Mã khởi chạy Firebase

  • Lưu mã khởi chạy Firebase để dán vào script.js (chương tiếp theo) cho phía máy khách

f10dcf6f5027e9f0.png

  • Đăng ký ứng dụng của bạn để cho phép Firebase sử dụng mã thông báo reCAPTCHA v3

https://console.firebase.google.com/u/0/project/YOUR_PROJECT/appcheck/apps

da7efe203ce4142c.png

  • Chọn reCAPTCHA → tạo khoá trong trang web reCAPTCHA (đã định cấu hình đúng miền: localhost cho nhà phát triển ứng dụng)

b47eab131617467.png e6bddef9d5cf5460.png

  • Dán khoá reCAPTCHA vào Firebase AppCheck

a63bbd533a1b5437.png

  • Trạng thái ứng dụng sẽ chuyển sang màu xanh lục

4f7962b527b78ee5.png

5. Ứng dụng minh hoạ

  • Ứng dụng web của máy khách: Tệp HTML, JavaScript, CSS
  • Máy chủ: Tệp Node.js
  • Môi trường (.env): Khoá API
  • Cấu hình (app.yaml): Chế độ cài đặt triển khai Google App Engine

Thiết lập Node.js:

  • Navigate (Di chuyển): Mở cửa sổ dòng lệnh rồi chuyển đến thư mục gốc của dự án đã sao chép.
  • Cài đặt Node.js (nếu cần): phiên bản 18 trở lên.
node -v  # Check installed version
  • Khởi chạy dự án: Chạy lệnh sau để khởi chạy một dự án Node.js mới, giữ nguyên tất cả các chế độ cài đặt mặc định:
npm init 
  • Cài đặt phần phụ thuộc: Sử dụng lệnh sau để cài đặt các phần phụ thuộc dự án bắt buộc:
npm install @googlemaps/places firebase-admin express axios dotenv

Cấu hình: Biến môi trường cho dự án trên Google Cloud

  • Tạo tệp môi trường: Tại thư mục gốc của dự án, hãy tạo một tệp có tên là .env. Tệp này sẽ lưu trữ dữ liệu cấu hình nhạy cảm và không được xác nhận vào hệ thống quản lý phiên bản.
  • Điền sẵn biến môi trường: Mở tệp .env và thêm các biến sau, thay thế phần giữ chỗ bằng các giá trị thực tế trong Dự án Google Cloud của bạn:
# Google Cloud Project ID
GOOGLE_CLOUD_PROJECT="your-cloud-project-id"

# reCAPTCHA Keys (obtained in previous steps) 
RECAPTCHA_SITE_KEY="your-recaptcha-site-key"
RECAPTCHA_SECRET_KEY="your-recaptcha-secret-key"

# Maps Platform API Keys (obtained in previous steps)
PLACES_API_KEY="your-places-api-key"
MAPS_API_KEY="your-maps-api-key"

6. Tổng quan về mã

index.html

  • Tải thư viện firebase để tạo mã thông báo trong ứng dụng
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Places API with AppCheck</title>
  <style></style>  </head>
<body>
  <div id="map"></div>

    <!-- Firebase services -->
  <script src="https://www.gstatic.com/firebasejs/9.15.0/firebase-app-compat.js"></script>
  <script src="https://www.gstatic.com/firebasejs/9.15.0/firebase-app-check-compat.js"></script>
  
  <script type="module" src="./script.js"></script> 
  <link rel="stylesheet" href="./style.css">
</body>
</html>

script.js

  • Tìm nạp khoá API: Truy xuất khoá API cho Google Maps và Firebase App Check từ máy chủ phụ trợ.
  • Khởi chạy Firebase: Thiết lập Firebase để xác thực và bảo mật. (Thay thế cấu hình → xem Chương 4).

Thời hạn hiệu lực của mã thông báo Firebase App Check (từ 30 phút đến 7 ngày) được định cấu hình trong bảng điều khiển Firebase và không thể thay đổi bằng cách cố gắng buộc làm mới mã thông báo.

  • Kích hoạt tính năng Kiểm tra ứng dụng: Cho phép tính năng Kiểm tra ứng dụng Firebase xác minh tính xác thực của các yêu cầu đến.
  • Tải API Google Maps: Tải linh động thư viện JavaScript của Google Maps để hiển thị bản đồ.
  • Khởi chạy bản đồ: Tạo một bản đồ Google Maps ở vị trí trung tâm là vị trí mặc định.
  • Xử lý lượt nhấp trên bản đồ: Theo dõi các lượt nhấp trên bản đồ và cập nhật điểm trung tâm cho phù hợp.
  • Truy vấn API Địa điểm: Gửi yêu cầu đến một API phụ trợ (/api/data) để tìm nạp thông tin về các địa điểm (nhà hàng, công viên, quán bar) gần vị trí được nhấp, sử dụng tính năng Xác minh ứng dụng Firebase để uỷ quyền.
  • Hiển thị điểm đánh dấu: Vẽ dữ liệu đã tìm nạp trên bản đồ dưới dạng điểm đánh dấu, hiển thị tên và biểu tượng của các điểm đánh dấu đó.
let mapsApiKey, recaptchaKey; // API keys
let currentAppCheckToken = null; // AppCheck token

async function init() {
  try {
    await fetchConfig(); // Load API keys from .env variable

    /////////// REPLACE with your Firebase configuration details
    const firebaseConfig = {
      apiKey: "AIza.......",
      authDomain: "places.......",
      projectId: "places.......",
      storageBucket: "places.......",
      messagingSenderId: "17.......",
      appId: "1:175.......",
      measurementId: "G-CPQ.......",
    };
    /////////// REPLACE 

    // Initialize Firebase and App Check
    await firebase.initializeApp(firebaseConfig);
    await firebase.appCheck().activate(recaptchaKey);

    // Get the initial App Check token
    currentAppCheckToken = await firebase.appCheck().getToken();

    // Load the Maps JavaScript API dynamically
    const scriptMaps = document.createElement("script");
    scriptMaps.src = `https://maps.googleapis.com/maps/api/js?key=${mapsApiKey}&libraries=marker,places&v=beta`;
    scriptMaps.async = true;
    scriptMaps.defer = true;
    scriptMaps.onload = initMap; // Create the map after the script loads
    document.head.appendChild(scriptMaps);
  } catch (error) {
    console.error("Firebase initialization error:", error);
    // Handle the error appropriately (e.g., display an error message)
  }
}
window.onload = init()

// Fetch configuration data from the backend API
async function fetchConfig() {
  const url = "/api/config";

  try {
    const response = await fetch(url);
    const config = await response.json();
    mapsApiKey = config.mapsApiKey;
    recaptchaKey = config.recaptchaKey;
  } catch (error) {
    console.error("Error fetching configuration:", error);
    // Handle the error (e.g., show a user-friendly message)
  }
}

// Initialize the map when the Maps API script loads
let map; // Dynamic Map
let center = { lat: 48.85557501, lng: 2.34565006 };
function initMap() {
  map = new google.maps.Map(document.getElementById("map"), {
    center: center,
    zoom: 13,
    mapId: "b93f5cef6674c1ff",
    zoomControlOptions: {
      position: google.maps.ControlPosition.RIGHT_TOP,
    },
    streetViewControl: false,
    mapTypeControl: false,
    clickableIcons: false,
    fullscreenControlOptions: {
      position: google.maps.ControlPosition.LEFT_TOP,
    },
  });

  // Initialize the info window for markers
  infoWindow = new google.maps.InfoWindow({});

  // Add a click listener to the map
  map.addListener("click", async (event) => {
    try {
      // Get a fresh App Check token on each click
      const appCheckToken = await firebase.appCheck().getToken();
      currentAppCheckToken = appCheckToken;

      // Update the center for the Places API query
      center.lat = event.latLng.lat();
      center.lng = event.latLng.lng();

      // Query for places with the new token and center
      queryPlaces();
    } catch (error) {
      console.error("Error getting App Check token:", error);
    }
  });
}

function queryPlaces() {
  const url = '/api/data'; // "http://localhost:3000/api/data"

  const body = {
    request: {
      includedTypes: ['restaurant', 'park', 'bar'],
      excludedTypes: [],
      maxResultCount: 20,
      locationRestriction: {
        circle: {
          center: {
            latitude: center.lat,
            longitude: center.lng,
          },
          radius: 4000,
        },
      },
    },
  };

  // Provides token to the backend using header: X-Firebase-AppCheck

  fetch(url, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-Firebase-AppCheck': currentAppCheckToken.token,
    },
    body: JSON.stringify(body),
  })
    .then((response) => response.json())
    .then((data) => {
      // display if response successful
      displayMarkers(data.places);
    })
    .catch((error) => {
      alert('No places');
      // eslint-disable-next-line no-console
      console.error('Error:', error);
    });
}


//// display places markers on map
...

server.js

  • Tải các biến môi trường (khoá API, mã dự án Google) từ tệp .env.
  • Khởi động máy chủ, lắng nghe các yêu cầu trên http://localhost:3000.
  • Khởi chạy SDK quản trị Firebase bằng Thông tin xác thực mặc định của ứng dụng (ADC).
  • Nhận mã thông báo reCAPTCHA từ script.js.
  • Xác minh tính hợp lệ của mã thông báo đã nhận được.
  • Nếu mã thông báo hợp lệ, hãy gửi yêu cầu POST đến API Google Địa điểm kèm theo các thông số tìm kiếm.
  • Xử lý và trả về phản hồi từ API Địa điểm cho ứng dụng khách.
const express = require('express');
const axios = require('axios');

const admin = require('firebase-admin');

// .env variables
require('dotenv').config();

// Store sensitive API keys in environment variables
const recaptchaSite = process.env.RECAPTCHA_SITE_KEY;
const recaptchaSecret = process.env.RECAPTCHA_SECRET_KEY;
const placesApiKey = process.env.PLACES_API_KEY;
const mapsApiKey = process.env.MAPS_API_KEY;

// Verify environment variables loaded (only during development)
console.log('recaptchaSite:', recaptchaSite, '\n');
console.log('recaptchaSecret:', recaptchaSecret, '\n');

const app = express();
app.use(express.json());

// Firebase Admin SDK setup with Application Default Credentials (ADC)
const { GoogleAuth } = require('google-auth-library');
admin.initializeApp({
  // credential: admin.credential.applicationDefault(), // optional: explicit ADC
});

// Main API Endpoint 
app.post('/api/data', async (req, res) => {
  const appCheckToken = req.headers['x-firebase-appcheck'];

  console.log("\n", "Token", "\n", "\n", appCheckToken, "\n")

  try {
    // Verify Firebase App Check token for security
    const appCheckResult = await admin.appCheck().verifyToken(appCheckToken);

    if (appCheckResult.appId) {
      console.log('App Check verification successful!');
      placesQuery(req, res);
    } else {
      console.error('App Check verification failed.');
      res.status(403).json({ error: 'App Check verification failed.' });
    }
  } catch (error) {
    console.error('Error verifying App Check token:', error);
    res.status(500).json({ error: 'Error verifying App Check token.' });
  }
});

// Function to query Google Places API
async function placesQuery(req, res) {
  console.log('#################################');
  console.log('\n', 'placesApiKey:', placesApiKey, '\n');

  const queryObject = req.body.request;
  console.log('\n','Request','\n','\n', queryObject, '\n')

  const headers = {
    'Content-Type': 'application/json',
    'X-Goog-FieldMask': '*',
    'X-Goog-Api-Key': placesApiKey,
    'Referer': 'http://localhost:3000',  // Update for production(ie.: req.hostname)
  };

  const myUrl = 'https://places.googleapis.com/v1/places:searchNearby';

  try {
    // Authenticate with ADC
    const auth = new GoogleAuth();
    const { credential } = await auth.getApplicationDefault();

    const response = await axios.post(myUrl, queryObject, { headers, auth: credential });
    
    console.log('############### SUCCESS','\n','\n','Response','\n','\n', );
    const myBody = response.data;
    myBody.places.forEach(place => {
      console.log(place.displayName); 
    });
    res.json(myBody); // Use res.json for JSON data
  } catch (error) {
    console.log('############### ERROR');
    // console.error(error); // Log the detailed error for debugging
    res.status(error.response.status).json(error.response.data); // Use res.json for errors too
  }
}

// Configuration endpoint (send safe config data to the client)
app.get('/api/config', (req, res) => {
  res.json({
    mapsApiKey: process.env.MAPS_API_KEY, 
    recaptchaKey: process.env.RECAPTCHA_SITE_KEY, 
  });
});

// Serve static files
app.use(express.static('static'));

// Start the server
const port = process.env.PORT || 3000;
app.listen(port, () => {
  console.log(`Server listening on port ${port}`, '\n');
});

7. Chạy ứng dụng

Trong môi trường đã chọn, hãy chạy máy chủ từ dòng lệnh và chuyển đến http://localhost:3000

npm start 

Mã thông báo được tạo dưới dạng biến toàn cục, ẩn khỏi cửa sổ trình duyệt của người dùng và được truyền đến máy chủ để xử lý. Bạn có thể xem thông tin chi tiết về mã thông báo trong nhật ký máy chủ.

Bạn có thể xem thông tin chi tiết về các hàm của máy chủ và phản hồi đối với yêu cầu Tìm kiếm địa điểm lân cận của API Địa điểm trong nhật ký máy chủ.

Khắc phục sự cố:

Đảm bảo Mã dự án của Google nhất quán trong quá trình thiết lập:

  • trong tệp .env (biến GOOGLE_CLOUD_PROJECT)
  • trong cấu hình gcloud của dòng lệnh:
gcloud config set project your-project-id
  • trong phần thiết lập reCaptcha

e6bddef9d5cf5460.png

  • trong quá trình thiết lập Firebase

7e17bfbcb8007763.png

Khác

  • Tạo mã thông báo gỡ lỗi có thể được dùng thay cho khoá trang web reCAPTCHA trong script.js cho mục đích kiểm thử và khắc phục sự cố.

9c0beb760d13faef.png

try {
 // Initialize Firebase first
 await firebase.initializeApp(firebaseConfig);
  // Set the debug token
  if (window.location.hostname === 'localhost') { // Only in development
    await firebase.appCheck().activate(
      'YOUR_DEBUG_FIREBASE_TOKEN', // Replace with the token from the console
      true // Set to true to indicate it's a debug token
      );
  } else {
      // Activate App Check
      await firebase.appCheck().activate(recaptchaKey);
}
  • Việc thử xác thực quá nhiều lần nhưng không thành công, ví dụ: sử dụng khoá trang web recaptcha giả mạo, có thể kích hoạt tình trạng điều tiết tạm thời.
FirebaseError: AppCheck: Requests throttled due to 403 error. Attempts allowed again after 01d:00m:00s (appCheck/throttled).

Thông tin đăng nhập ADC

  • Đảm bảo bạn đang sử dụng đúng tài khoản gcloud
gcloud auth login 
  • Đảm bảo đã cài đặt các thư viện cần thiết
npm install @googlemaps/places firebase-admin
  • Đảm bảo thư viện Firebase được tải trong server.js
const {GoogleAuth} = require('google-auth-library');
gcloud auth application-default login
  • Giả mạo: Đã lưu thông tin xác thực ADC
gcloud auth application-default login --impersonate-service-account your_project@appspot.gserviceaccount.com
  • Cuối cùng, hãy kiểm thử ADC cục bộ, lưu tập lệnh sau dưới dạng test.js và chạy trong Terminal: node test.js
const {GoogleAuth} = require('google-auth-library');

async function requestTestADC() {
 try {
   // Authenticate using Application Default Credentials (ADC)
   const auth = new GoogleAuth();
   const {credential} = await auth.getApplicationDefault();

   // Check if the credential is successfully obtained
   if (credential) {
     console.log('Application Default Credentials (ADC) loaded successfully!');
     console.log('Credential:', credential); // Log the credential object
   } else {
     console.error('Error: Could not load Application Default Credentials (ADC).');
   }

   // ... rest of your code ...

 } catch (error) {
   console.error('Error:', error);
 }
}

requestTestADC();

8. Vậy là xong! Bạn đã làm rất tốt!

Các bước tiếp theo

Triển khai lên App Engine:

  • Chuẩn bị dự án để triển khai trên Google App Engine, thực hiện mọi thay đổi cấu hình cần thiết.
  • Sử dụng công cụ dòng lệnh gcloud hoặc bảng điều khiển App Engine để triển khai ứng dụng.

Tăng cường tính năng Xác thực Firebase:

  • Mã thông báo mặc định so với mã thông báo tuỳ chỉnh: Triển khai mã thông báo tuỳ chỉnh Firebase để sử dụng các dịch vụ Firebase một cách chuyên sâu hơn.
  • Vòng đời mã thông báo: Đặt vòng đời mã thông báo thích hợp, ngắn hơn cho các thao tác nhạy cảm (mã thông báo Firebase tuỳ chỉnh tối đa một giờ), dài hơn cho các phiên chung (mã thông báo reCAPTCHA: 30 phút đến 7 giờ).
  • Khám phá các giải pháp thay thế cho reCAPTCHA: Hãy điều tra xem DeviceCheck (iOS), SafetyNet (Android) hay Chứng thực ứng dụng có phù hợp với nhu cầu bảo mật của bạn hay không.

Tích hợp các sản phẩm Firebase:

  • Cơ sở dữ liệu theo thời gian thực hoặc Firestore: Nếu ứng dụng của bạn cần đồng bộ hoá dữ liệu theo thời gian thực hoặc có chức năng ngoại tuyến, hãy tích hợp với Cơ sở dữ liệu theo thời gian thực hoặc Firestore.
  • Bộ nhớ trên đám mây: Sử dụng Bộ nhớ trên đám mây để lưu trữ và phân phát nội dung do người dùng tạo, chẳng hạn như hình ảnh hoặc video.
  • Xác thực: Tận dụng tính năng Xác thực Firebase để tạo tài khoản người dùng, quản lý phiên đăng nhập và xử lý việc đặt lại mật khẩu.

Mở rộng sang thiết bị di động:

  • Android và iOS: Nếu bạn dự định tạo ứng dụng di động, hãy tạo phiên bản cho cả nền tảng Android và iOS.
  • SDK Firebase: Sử dụng SDK Firebase cho Android và iOS để tích hợp liền mạch các tính năng của Firebase vào ứng dụng di động.