Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Protect your backends with Firebase App Check

Protect your backends with Firebase App Check

A powerful layer of security for your backend infrastructure that helps protect access to your services by attesting that incoming traffic is coming from your app, and blocking traffic that doesn't have valid credentials. It helps protect your backend from abuse, such as billing fraud, phishing, app impersonation, and data poisoning.

Firebase Thailand

October 01, 2022
Tweet

More Decks by Firebase Thailand

Other Decks in Technology

Transcript

  1. Release and Monitor Crashlytics Performance Monitoring Test Lab Engage In-App

    Messaging Predictions Cloud Messaging Remote Config A/B Testing Dynamic Links Build Auth Cloud Functions Cloud Firestore Cloud Storage Hosting Realtime Database
  2. Attestation Providers SafetyNet Device Check reCAPTCHA V3 Custom Attestation New

    App Attest reCAPTCHA Enterprise New Play Integrity New reCAPTCHA V3 SafetyNet Device Check
  3. To support prior versions to iOS 11, use custom attestation.

    Device Check Supported on iOS 11+ Only supported on iOS 14+ App Attest And
  4. App Check Backend Issues App Check token with TTL in

    Attestation flow App Check token grants access to Firestore while TTL is valid
  5. App Check Backend App Check token exceeds TTL Re-perform Attestation

    flow to keep valid App Check token Issues App Check token with TTL in Attestation flow
  6. App Check Backend Refreshed App Check token with valid TTL

    Re-perform Attestation flow to keep valid App Check token Issues App Check token with TTL in Attestation flow
  7. 30 Min 7 Days Short TTL Long TTL Recommend 1

    hr for most apps Custom TTL
  8. App Check Service Access User Data + Security Rules Firebase

    Auth Better together Firebase Security
  9. const express = require('express'); const app = express(); const firebaseAdmin

    = require('firebase-admin'); const firebaseApp = firebaseAdmin.initializeApp(); const appCheckVerification = async (req, res, next) => { // implementation details next slide. } app.get('/yourApiEndpoint', [appCheckVerification], (req, res) => { // Handle request. }); App Check in the Backend Service
  10. 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 firebaseAdmin.appCheck().verifyToken(appCheckToken); // If verifyToken() succeeds, continue with the next middleware function return next(); } catch (err) { res.status(401); return next('Unauthorized'); } } App Check in the Backend Service
  11. 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 firebaseAdmin.appCheck().verifyToken(appCheckToken); // If verifyToken() succeeds, continue with the next middleware function return next(); } catch (err) { res.status(401); return next('Unauthorized'); } } App Check in the Backend Service
  12. 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 firebaseAdmin.appCheck().verifyToken(appCheckToken); // If verifyToken() succeeds, continue with the next middleware function return next(); } catch (err) { res.status(401); return next('Unauthorized'); } } App Check in the Backend Service
  13. 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 firebaseAdmin.appCheck().verifyToken(appCheckToken); // If verifyToken() succeeds, continue with the next middleware function return next(); } catch (err) { res.status(401); return next('Unauthorized'); } } App Check in the Backend Service
  14. class ApiWithAppCheckExample { interface YourExampleBackendService { @GET("yourExampleEndpoint") fun exampleData( @Header("X-Firebase-AppCheck")

    appCheckToken: String ): Call<List<String>> } var yourExampleBackendService: YourExampleBackendService = Retrofit.Builder() .baseUrl("https://yourbackend.example.com/") .build() .create(YourExampleBackendService::class.java) fun callApiExample() { FirebaseAppCheck.getInstance().getAppCheckToken(false) .addOnSuccessListener { tokenResponse -> val appCheckToken = tokenResponse.token val apiCall = yourExampleBackendService.exampleData(appCheckToken) // ... } } } Custom Backend for Android
  15. class ApiWithAppCheckExample { interface YourExampleBackendService { @GET("yourExampleEndpoint") fun exampleData( @Header("X-Firebase-AppCheck")

    appCheckToken: String ): Call<List<String>> } var yourExampleBackendService: YourExampleBackendService = Retrofit.Builder() .baseUrl("https://yourbackend.example.com/") .build() .create(YourExampleBackendService::class.java) fun callApiExample() { FirebaseAppCheck.getInstance().getAppCheckToken(false) .addOnSuccessListener { tokenResponse -> val appCheckToken = tokenResponse.token val apiCall = yourExampleBackendService.exampleData(appCheckToken) // ... } } } Custom Backend for Android
  16. class ApiWithAppCheckExample { interface YourExampleBackendService { @GET("yourExampleEndpoint") fun exampleData( @Header("X-Firebase-AppCheck")

    appCheckToken: String ): Call<List<String>> } var yourExampleBackendService: YourExampleBackendService = Retrofit.Builder() .baseUrl("https://yourbackend.example.com/") .build() .create(YourExampleBackendService::class.java) fun callApiExample() { FirebaseAppCheck.getInstance().getAppCheckToken(false) .addOnSuccessListener { tokenResponse -> val appCheckToken = tokenResponse.token val apiCall = yourExampleBackendService.exampleData(appCheckToken) // ... } } } Custom Backend for Android
  17. class ApiWithAppCheckExample { interface YourExampleBackendService { @GET("yourExampleEndpoint") fun exampleData( @Header("X-Firebase-AppCheck")

    appCheckToken: String ): Call<List<String>> } var yourExampleBackendService: YourExampleBackendService = Retrofit.Builder() .baseUrl("https://yourbackend.example.com/") .build() .create(YourExampleBackendService::class.java) fun callApiExample() { FirebaseAppCheck.getInstance().getAppCheckToken(false) .addOnSuccessListener { tokenResponse -> val appCheckToken = tokenResponse.token val apiCall = yourExampleBackendService.exampleData(appCheckToken) // ... } } } Custom Backend for Android
  18. AppCheck.appCheck().token(forcingRefresh: false) { token, error in guard error == nil

    else { return } guard let token = token else { return } let tokenString = token.token let url = URL(string: "https://yourbackend.example.com/yourApiEndpoint")! var request = URLRequest(url: url) request.httpMethod = "GET" request.setValue(tokenString, forHTTPHeaderField: "X-Firebase-AppCheck") let task = URLSession.shared.dataTask(with: request) { data, response, error in // Handle response from your backend. } task.resume() } Custom Backend for iOS
  19. AppCheck.appCheck().token(forcingRefresh: false) { token, error in guard error == nil

    else { return } guard let token = token else { return } let tokenString = token.token let url = URL(string: "https://yourbackend.example.com/yourApiEndpoint")! var request = URLRequest(url: url) request.httpMethod = "GET" request.setValue(tokenString, forHTTPHeaderField: "X-Firebase-AppCheck") let task = URLSession.shared.dataTask(with: request) { data, response, error in // Handle response from your backend. } task.resume() } Custom Backend for iOS
  20. AppCheck.appCheck().token(forcingRefresh: false) { token, error in guard error == nil

    else { return } guard let token = token else { return } let tokenString = token.token let url = URL(string: "https://yourbackend.example.com/yourApiEndpoint")! var request = URLRequest(url: url) request.httpMethod = "GET" request.setValue(tokenString, forHTTPHeaderField: "X-Firebase-AppCheck") let task = URLSession.shared.dataTask(with: request) { data, response, error in // Handle response from your backend. } task.resume() } Custom Backend for iOS
  21. const callApiWithAppCheckExample = async () => { let appCheckTokenResponse; try

    { appCheckTokenResponse = await firebase.appCheck().getToken(false); } catch (err) { return; } const apiResponse = await fetch('https://yourbackend.example.com/yourApiEndpoint', { headers: { 'X-Firebase-AppCheck': appCheckTokenResponse.token, } }); // Handle response from your backend. }; Custom Backend for Web
  22. const callApiWithAppCheckExample = async () => { let appCheckTokenResponse; try

    { appCheckTokenResponse = await firebase.appCheck().getToken(false); } catch (err) { return; } const apiResponse = await fetch('https://yourbackend.example.com/yourApiEndpoint', { headers: { 'X-Firebase-AppCheck': appCheckTokenResponse.token, } }); // Handle response from your backend. }; Custom Backend for Web
  23. void callApiExample() async { final appCheckToken = await FirebaseAppCheck.instance.getToken(); if

    (appCheckToken != null) { final response = await http.get( Uri.parse("https://yourbackend.example.com/yourExampleEndpoint"), headers: {"X-Firebase-AppCheck": appCheckToken}, ); } else { // Error: couldn't get an App Check token. } } Custom Backend for Flutter
  24. void callApiExample() async { final appCheckToken = await FirebaseAppCheck.instance.getToken(); if

    (appCheckToken != null) { final response = await http.get( Uri.parse("https://yourbackend.example.com/yourExampleEndpoint"), headers: {"X-Firebase-AppCheck": appCheckToken}, ); } else { // Error: couldn't get an App Check token. } } Custom Backend for Flutter
  25. void callApiExample() async { final appCheckToken = await FirebaseAppCheck.instance.getToken(); if

    (appCheckToken != null) { final response = await http.get( Uri.parse("https://yourbackend.example.com/yourExampleEndpoint"), headers: {"X-Firebase-AppCheck": appCheckToken}, ); } else { // Error: couldn't get an App Check token. } } Custom Backend for Flutter