Skip to content

Commit

Permalink
feat: add app check (#170)
Browse files Browse the repository at this point in the history
* feat: add app check

* feat: add app check

* feat: add app check

* feat: add app check

---------

Co-authored-by: Jaime <52668514+jsgalarraga@users.noreply.github.com>
  • Loading branch information
wolfenrain and jsgalarraga authored Apr 2, 2024
1 parent 8c3e884 commit 23430e0
Show file tree
Hide file tree
Showing 15 changed files with 138 additions and 19 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/deploy_app_dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
with:
channel: "stable"
- run: flutter packages get
- run: flutter build web --web-renderer canvaskit -t lib/main_development.dart
- run: flutter build web --web-renderer canvaskit -t lib/main_development.dart --dart-define RECAPTCHA_KEY=${{ secrets.RECAPTCHA_KEY }}


- uses: FirebaseExtended/action-hosting-deploy@v0
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/deploy_app_prod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
with:
channel: "stable"
- run: flutter packages get
- run: flutter build web --web-renderer canvaskit -t lib/main_production.dart
- run: flutter build web --web-renderer canvaskit -t lib/main_production.dart --dart-define RECAPTCHA_KEY=${{ secrets.RECAPTCHA_KEY_PROD }}


- uses: FirebaseExtended/action-hosting-deploy@v0
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/deploy_app_staging.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
with:
channel: "stable"
- run: flutter packages get
- run: flutter build web --web-renderer canvaskit -t lib/main_staging.dart
- run: flutter build web --web-renderer canvaskit -t lib/main_staging.dart --dart-define RECAPTCHA_KEY=${{ secrets.RECAPTCHA_KEY }}


- uses: FirebaseExtended/action-hosting-deploy@v0
Expand Down
21 changes: 21 additions & 0 deletions api/headers/allow_headers.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import 'package:dart_frog/dart_frog.dart';
import 'package:jwt_middleware/jwt_middleware.dart';
import 'package:shelf_cors_headers/shelf_cors_headers.dart';

Middleware allowHeaders() {
return (handler) {
return (context) async {
final response = await handler(context);
final headers = Map<String, String>.from(response.headers);
final accessControlAllowHeaders = headers[ACCESS_CONTROL_ALLOW_HEADERS];
if (accessControlAllowHeaders != null) {
headers[ACCESS_CONTROL_ALLOW_HEADERS] =
'$accessControlAllowHeaders, $X_FIREBASE_APPCHECK';

return response.copyWith(headers: headers);
}

return response;
};
};
}
2 changes: 2 additions & 0 deletions api/headers/headers.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export 'allow_headers.dart';
export 'cors_headers.dart';
3 changes: 2 additions & 1 deletion api/routes/_middleware.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import 'package:google_cloud/google_cloud.dart';
import 'package:leaderboard_repository/leaderboard_repository.dart';
import 'package:logging/logging.dart';

import '../headers/cors_headers.dart';
import '../headers/headers.dart';
import '../main.dart';

Handler middleware(Handler handler) {
Expand All @@ -18,5 +18,6 @@ Handler middleware(Handler handler) {
.use(provider<LeaderboardRepository>((_) => leaderboardRepository))
.use(provider<FirebaseCloudStorage>((_) => firebaseCloudStorage))
.use(corsHeaders())
.use(allowHeaders())
.use(fromShelfMiddleware(cloudLoggingMiddleware(projectId)));
}
3 changes: 3 additions & 0 deletions lib/bootstrap.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'dart:developer';

import 'package:bloc/bloc.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_app_check/firebase_app_check.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/widgets.dart';

Expand All @@ -25,6 +26,7 @@ class AppBlocObserver extends BlocObserver {
typedef BootstrapBuilder = FutureOr<Widget> Function(
FirebaseFirestore firestore,
FirebaseAuth firebaseAuth,
FirebaseAppCheck appCheck,
);

Future<void> bootstrap(BootstrapBuilder builder) async {
Expand All @@ -40,6 +42,7 @@ Future<void> bootstrap(BootstrapBuilder builder) async {
await builder(
FirebaseFirestore.instance,
FirebaseAuth.instance,
FirebaseAppCheck.instance,
),
);
}
23 changes: 20 additions & 3 deletions lib/main_debug.dart
Original file line number Diff line number Diff line change
@@ -1,17 +1,27 @@
// ignore_for_file: avoid_web_libraries_in_flutter

import 'dart:async';
import 'dart:js' as js;

import 'package:api_client/api_client.dart';
import 'package:authentication_repository/authentication_repository.dart';
import 'package:board_info_repository/board_info_repository.dart';
import 'package:crossword_repository/crossword_repository.dart';
import 'package:firebase_app_check/firebase_app_check.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:io_crossword/app/app.dart';
import 'package:io_crossword/bootstrap.dart';
import 'package:io_crossword/crossword/game/game.dart';
import 'package:io_crossword/firebase_options_development.dart';

void main() async {
if (kDebugMode) {
js.context['FIREBASE_APPCHECK_DEBUG_TOKEN'] =
const String.fromEnvironment('APPCHECK_DEBUG_TOKEN');
}

WidgetsFlutterBinding.ensureInitialized();

await Firebase.initializeApp(
Expand All @@ -20,7 +30,14 @@ void main() async {

unawaited(
bootstrap(
(firestore, firebaseAuth) async {
(firestore, firebaseAuth, appCheck) async {
await appCheck.activate(
webProvider: ReCaptchaV3Provider(
const String.fromEnvironment('RECAPTCHA_KEY'),
),
);
await appCheck.setTokenAutoRefreshEnabled(true);

final authenticationRepository = AuthenticationRepository(
firebaseAuth: firebaseAuth,
);
Expand All @@ -34,8 +51,8 @@ void main() async {
baseUrl: 'https://io-crossword-dev-api-sea6y22h5q-uc.a.run.app',
idTokenStream: authenticationRepository.idToken,
refreshIdToken: authenticationRepository.refreshIdToken,
// TODO(any): implement app check
appCheckTokenStream: const Stream.empty(),
appCheckTokenStream: appCheck.onTokenChange,
appCheckToken: await appCheck.getToken(),
);

return App(
Expand Down
23 changes: 20 additions & 3 deletions lib/main_development.dart
Original file line number Diff line number Diff line change
@@ -1,16 +1,26 @@
// ignore_for_file: avoid_web_libraries_in_flutter

import 'dart:async';
import 'dart:js' as js;

import 'package:api_client/api_client.dart';
import 'package:authentication_repository/authentication_repository.dart';
import 'package:board_info_repository/board_info_repository.dart';
import 'package:crossword_repository/crossword_repository.dart';
import 'package:firebase_app_check/firebase_app_check.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:io_crossword/app/app.dart';
import 'package:io_crossword/bootstrap.dart';
import 'package:io_crossword/firebase_options_development.dart';

void main() async {
if (kDebugMode) {
js.context['FIREBASE_APPCHECK_DEBUG_TOKEN'] =
const String.fromEnvironment('APPCHECK_DEBUG_TOKEN');
}

WidgetsFlutterBinding.ensureInitialized();

await Firebase.initializeApp(
Expand All @@ -19,7 +29,14 @@ void main() async {

unawaited(
bootstrap(
(firestore, firebaseAuth) async {
(firestore, firebaseAuth, appCheck) async {
await appCheck.activate(
webProvider: ReCaptchaV3Provider(
const String.fromEnvironment('RECAPTCHA_KEY'),
),
);
await appCheck.setTokenAutoRefreshEnabled(true);

final authenticationRepository = AuthenticationRepository(
firebaseAuth: firebaseAuth,
);
Expand All @@ -31,8 +48,8 @@ void main() async {
baseUrl: 'https://io-crossword-dev-api-sea6y22h5q-uc.a.run.app',
idTokenStream: authenticationRepository.idToken,
refreshIdToken: authenticationRepository.refreshIdToken,
// TODO(any): implement app check
appCheckTokenStream: const Stream.empty(),
appCheckTokenStream: appCheck.onTokenChange,
appCheckToken: await appCheck.getToken(),
);

return App(
Expand Down
20 changes: 17 additions & 3 deletions lib/main_local.dart
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
// ignore_for_file: avoid_web_libraries_in_flutter

import 'dart:async';
import 'dart:js' as js;

import 'package:api_client/api_client.dart';
import 'package:authentication_repository/authentication_repository.dart';
import 'package:board_info_repository/board_info_repository.dart';
import 'package:crossword_repository/crossword_repository.dart';
import 'package:firebase_app_check/firebase_app_check.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/widgets.dart';
import 'package:io_crossword/app/app.dart';
import 'package:io_crossword/bootstrap.dart';
import 'package:io_crossword/firebase_options_development.dart';

void main() async {
js.context['FIREBASE_APPCHECK_DEBUG_TOKEN'] =
const String.fromEnvironment('APPCHECK_DEBUG_TOKEN');

WidgetsFlutterBinding.ensureInitialized();

await Firebase.initializeApp(
Expand All @@ -19,7 +26,14 @@ void main() async {

unawaited(
bootstrap(
(firestore, firebaseAuth) async {
(firestore, firebaseAuth, appCheck) async {
await appCheck.activate(
webProvider: ReCaptchaV3Provider(
const String.fromEnvironment('RECAPTCHA_KEY'),
),
);
await appCheck.setTokenAutoRefreshEnabled(true);

final authenticationRepository = AuthenticationRepository(
firebaseAuth: firebaseAuth,
);
Expand All @@ -31,8 +45,8 @@ void main() async {
baseUrl: 'http://localhost:8080',
idTokenStream: authenticationRepository.idToken,
refreshIdToken: authenticationRepository.refreshIdToken,
// TODO(any): implement app check
appCheckTokenStream: const Stream.empty(),
appCheckTokenStream: appCheck.onTokenChange,
appCheckToken: await appCheck.getToken(),
);

return App(
Expand Down
14 changes: 11 additions & 3 deletions lib/main_production.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:api_client/api_client.dart';
import 'package:authentication_repository/authentication_repository.dart';
import 'package:board_info_repository/board_info_repository.dart';
import 'package:crossword_repository/crossword_repository.dart';
import 'package:firebase_app_check/firebase_app_check.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/widgets.dart';
import 'package:io_crossword/app/app.dart';
Expand All @@ -19,7 +20,14 @@ void main() async {

unawaited(
bootstrap(
(firestore, firebaseAuth) async {
(firestore, firebaseAuth, appCheck) async {
await appCheck.activate(
webProvider: ReCaptchaV3Provider(
const String.fromEnvironment('RECAPTCHA_KEY'),
),
);
await appCheck.setTokenAutoRefreshEnabled(true);

final authenticationRepository = AuthenticationRepository(
firebaseAuth: firebaseAuth,
);
Expand All @@ -31,8 +39,8 @@ void main() async {
baseUrl: 'https://io-crossword-api-u3emptgwka-uc.a.run.app',
idTokenStream: authenticationRepository.idToken,
refreshIdToken: authenticationRepository.refreshIdToken,
// TODO(any): implement app check
appCheckTokenStream: const Stream.empty(),
appCheckTokenStream: appCheck.onTokenChange,
appCheckToken: await appCheck.getToken(),
);

return App(
Expand Down
15 changes: 12 additions & 3 deletions lib/main_staging.dart
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
// ignore_for_file: avoid_web_libraries_in_flutter

import 'dart:async';
import 'dart:js' as js;

import 'package:api_client/api_client.dart';
import 'package:authentication_repository/authentication_repository.dart';
import 'package:board_info_repository/board_info_repository.dart';
import 'package:crossword_repository/crossword_repository.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:io_crossword/app/app.dart';
import 'package:io_crossword/bootstrap.dart';
import 'package:io_crossword/firebase_options_development.dart';

void main() async {
if (kDebugMode) {
js.context['FIREBASE_APPCHECK_DEBUG_TOKEN'] =
const String.fromEnvironment('APPCHECK_DEBUG_TOKEN');
}

WidgetsFlutterBinding.ensureInitialized();

await Firebase.initializeApp(
Expand All @@ -19,7 +28,7 @@ void main() async {

unawaited(
bootstrap(
(firestore, firebaseAuth) async {
(firestore, firebaseAuth, appCheck) async {
final authenticationRepository = AuthenticationRepository(
firebaseAuth: firebaseAuth,
);
Expand All @@ -31,8 +40,8 @@ void main() async {
baseUrl: 'https://io-crossword-staging-api-sea6y22h5q-uc.a.run.app',
idTokenStream: authenticationRepository.idToken,
refreshIdToken: authenticationRepository.refreshIdToken,
// TODO(any): implement app check
appCheckTokenStream: const Stream.empty(),
appCheckTokenStream: appCheck.onTokenChange,
appCheckToken: await appCheck.getToken(),
);

return App(
Expand Down
2 changes: 2 additions & 0 deletions macos/Flutter/GeneratedPluginRegistrant.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import Foundation

import audioplayers_darwin
import cloud_firestore
import firebase_app_check
import firebase_auth
import firebase_core
import path_provider_foundation
Expand All @@ -15,6 +16,7 @@ import url_launcher_macos
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
AudioplayersDarwinPlugin.register(with: registry.registrar(forPlugin: "AudioplayersDarwinPlugin"))
FLTFirebaseFirestorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseFirestorePlugin"))
FLTFirebaseAppCheckPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAppCheckPlugin"))
FLTFirebaseAuthPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAuthPlugin"))
FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
Expand Down
24 changes: 24 additions & 0 deletions pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,30 @@ packages:
url: "https://pub.dev"
source: hosted
version: "7.0.0"
firebase_app_check:
dependency: "direct main"
description:
name: firebase_app_check
sha256: db93b6dfc432d17c0c9a4b7917b6b2af103d74e6e830326fa8502b945cc7f139
url: "https://pub.dev"
source: hosted
version: "0.2.1+19"
firebase_app_check_platform_interface:
dependency: transitive
description:
name: firebase_app_check_platform_interface
sha256: c7c8647385a9fbeade985f9542c6967f36a77984e7c7355bdb2c14b779518eed
url: "https://pub.dev"
source: hosted
version: "0.1.0+21"
firebase_app_check_web:
dependency: transitive
description:
name: firebase_app_check_web
sha256: "23d906eab0a54bbbf6bad58c3ee5b9461dfde0bd62896a8a60f50fb1cdcecc6a"
url: "https://pub.dev"
source: hosted
version: "0.1.1+1"
firebase_auth:
dependency: "direct main"
description:
Expand Down
1 change: 1 addition & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ dependencies:
crossword_repository:
path: packages/crossword_repository
equatable: ^2.0.5
firebase_app_check: ^0.2.1+18
firebase_auth: ^4.18.0
firebase_core: ^2.27.1
flame: ^1.16.0
Expand Down

0 comments on commit 23430e0

Please sign in to comment.