From 3e50566105bcf09061b1c87a6f32282082078620 Mon Sep 17 00:00:00 2001 From: Matthias Schoettle Date: Mon, 1 Dec 2025 16:06:13 -0500 Subject: [PATCH 1/9] docs: add details for Firebase projects when deploying --- docs/install/index.md | 73 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/docs/install/index.md b/docs/install/index.md index 9d76fe2..5c1e765 100644 --- a/docs/install/index.md +++ b/docs/install/index.md @@ -39,6 +39,42 @@ The database server can also be run on a separate server: Relationships between components on the same host are left out for brevity (except those making use of third-party components). +### Requirements + +You need at least one machine on which to deploy the Opal PIE. +This machine needs to have the [Docker Engine](https://docs.docker.com/engine/) and [Docker Compose](https://docs.docker.com/compose/) installed. +A compatible container engine that also has support for compose can also be used. + +In addition, you need a Firebase project. + +#### Creating a new Firebase project + +If you don't have a Firebase project yet, [create a Firebase project](../development/local-dev-setup.md#create-a-new-firebase-project), [create a Realtime Database](../development/local-dev-setup.md#create-a-new-realtime-database), and [enable password-based authentication](../development/local-dev-setup.md#enable-email-and-password-authentication). + +#### Create a Firebase service account + +By default, Firebase creates a service account and API keys with excessive permissions. +This is fine for development. +However, it is not recommended for a production environment. + +To create a dedicated service account, go to the [Service Accounts in Google Cloud](https://console.cloud.google.com/projectselector2/iam-admin/serviceaccounts) and: + +1. Select your Firebase project +1. Select "Create service account" +1. Type in a display name and generate a service account ID +1. Click "Create and continue" +1. In the "Permissions" section, select the following roles: + - *Firebase Authentication Admin* + - *Firebase Cloud Messaging Admin* + - *Firebase Realtime Database Admin* + - *Firebase Rules Admin* +1. Click "Continue" +1. Click "Done" +1. Click on the newly created service account +1. Select "Keys", select "Add key", and then "Create new key" +1. Choose key type "JSON" and click "Create" +1. Store this file in a secure place for later + ### Automated deployment We offer a semi-automated deployment via a [`copier`](https://copier.readthedocs.io/en/stable/) template. @@ -52,3 +88,40 @@ Please follow the instructions in the [`deploy-pie`](https://github.com/opalmeda ```plantuml source="docs/install/diagrams/deployment_diagram_user.puml" ``` + +### Requirements + +#### Create or restrict Firebase API keys + +If you already [retrieved Firebase client configurations](../development/local-dev-setup.md#retrieve-the-firebase-project-configurations), then you do not need to create new API keys but can instead restrict the already generated ones. +In that case, skip the create steps below and edit the exiting keys instead. + +Go to the [API Credentials in Google Cloud](https://console.cloud.google.com/apis/) and select the corresponding Firebase project. + +##### Browser key + +1. Click "Create credentials" and select "API Key" +1. Give it a name, such as "Browser key" +1. Under "Application restrictions", choose "Websites" +1. Add the following websites at a minimum + - `app://localhost` + - `http://localhost` + - `https://.firebaseapp.com` +1. Under "API Restrictions", choose "Restrict key" +1. Choose the following APIs + - *FCM Registration API* + - *Firebase Realtime Database Management API* + - *Identity Toolkit API* +1. Click "Create" + +##### Android key + +1. Click "Create credentials" and select "API Key" +1. Give it a name, such as "Android key" +1. Under "API Restrictions", choose "Restrict key" +1. Choose the following APIs + - *FCM Registration API* + - *Firebase Realtime Database Management API* + - *Identity Toolkit API* + - *Firebase Installations API* +1. Click "Create" From 97663ec3ae9fd0b1651cf816838ac45911a7ec80 Mon Sep 17 00:00:00 2001 From: Matthias Schoettle Date: Tue, 2 Dec 2025 12:13:37 -0500 Subject: [PATCH 2/9] more details --- .pre-commit-config.yaml | 14 ++++++++----- docs/install/index.md | 46 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index dbd9abf..c928396 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -84,11 +84,15 @@ repos: - id: check-renovate args: ["--verbose"] additional_dependencies: ['json5'] - # requires: https://github.com/python-jsonschema/check-jsonschema/issues/341 - # - id: check-jsonschema - # name: "Validate devcontainer" - # files: ^\.devcontainer/.*\.json$ - # args: ["--schemafile", "https://raw.githubusercontent.com/devcontainers/spec/main/schemas/devContainer.schema.json"] + - id: check-jsonschema + name: "Validate devcontainer" + files: ^\.devcontainer/.*\.json$ + args: [ + "--schemafile", + "https://raw.githubusercontent.com/devcontainers/spec/main/schemas/devContainer.schema.json", + "--force-filetype", + "json5", + ] # waiting for custom YAML tags support: https://github.com/python-jsonschema/check-jsonschema/issues/489 # - id: check-jsonschema # name: "Validate MkDocs file" diff --git a/docs/install/index.md b/docs/install/index.md index 5c1e765..e4cad27 100644 --- a/docs/install/index.md +++ b/docs/install/index.md @@ -47,7 +47,7 @@ A compatible container engine that also has support for compose can also be used In addition, you need a Firebase project. -#### Creating a new Firebase project +#### Create a new Firebase project If you don't have a Firebase project yet, [create a Firebase project](../development/local-dev-setup.md#create-a-new-firebase-project), [create a Realtime Database](../development/local-dev-setup.md#create-a-new-realtime-database), and [enable password-based authentication](../development/local-dev-setup.md#enable-email-and-password-authentication). @@ -75,6 +75,50 @@ To create a dedicated service account, go to the [Service Accounts in Google Clo 1. Choose key type "JSON" and click "Create" 1. Store this file in a secure place for later +#### Retrieve the Apple Push Notification certificates + +!!! note + + These instructions are specific to *macOS* as they require the *Keychain Access* utility. + +While push notifications on Android are delivered via *Firebase Cloud Messaging*, on iOS the *Apple Push Notification Service* is used. + +The following instructions assume that your iOS app has already been created in [App Store Connect](https://appstoreconnect.apple.com/apps) and therefore has an *App ID*. + +!!! success "Preparation: Generate a *Certificate Signing Request*" + + As a preparation, follow the instructions to [create a certificate signing request](https://developer.apple.com/help/account/certificates/create-a-certificate-signing-request). + +Log in to your [Apple Developer Account](https://developer.apple.com/account) and do the following: + +1. Under "Program resources" > "Certificates, IDs & Profiles", click "Certificates" +1. Click the plus icon next to "Certificates" +1. Under "Services", select "Apple Push Notification service SSL (Sandbox & Production)" and click "Continue" +1. Select the App ID of your app and click "Continue" +1. Upload your certificate signing request and click "Continue" +1. Download your certificate + +You now have a `.cer` file which needs to be imported to the keychain so it can be exported as a PKCS #12 archive: + +1. Double-click the `.cer` file to add it to your keychain +1. In *Keychain Access*, select the "login" keychain and look for the "Apple Push Services: ``" certificate +1. Expand this certificate to reveal the private key entry +1. Select both certificate and private key +1. Right-click and select "Export 2 items..." +1. Save the `.p12` file somewhere + - Leave the password empty + - Confirm the export with your password and selecting "Allow" + +The `Certificates.p12` file contains both the certificate and private key. +To separate them, run the following we use `openssl` with the `pkcs12` command: + +```console +# export certificate +openssl pkcs12 -in Certificates.p12 -clcerts -nokeys -out apn.crt +# export private key +openssl pkcs12 -in Certificates.p12 -nodes -nocerts -out apn.key +``` + ### Automated deployment We offer a semi-automated deployment via a [`copier`](https://copier.readthedocs.io/en/stable/) template. From d18c68b797904f7b58dfed42bfc3bc8faabf4d48 Mon Sep 17 00:00:00 2001 From: Matthias Schoettle Date: Tue, 2 Dec 2025 12:22:44 -0500 Subject: [PATCH 3/9] add missing dependency --- .pre-commit-config.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c928396..a240fd8 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -87,6 +87,7 @@ repos: - id: check-jsonschema name: "Validate devcontainer" files: ^\.devcontainer/.*\.json$ + additional_dependencies: ['json5'] args: [ "--schemafile", "https://raw.githubusercontent.com/devcontainers/spec/main/schemas/devContainer.schema.json", From 6b6fb6bd1a2f01a0714eff9be5f0eef95fe7f8ac Mon Sep 17 00:00:00 2001 From: Matthias Schoettle Date: Tue, 2 Dec 2025 12:32:57 -0500 Subject: [PATCH 4/9] disable it again --- .pre-commit-config.yaml | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a240fd8..d5f192c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -84,16 +84,17 @@ repos: - id: check-renovate args: ["--verbose"] additional_dependencies: ['json5'] - - id: check-jsonschema - name: "Validate devcontainer" - files: ^\.devcontainer/.*\.json$ - additional_dependencies: ['json5'] - args: [ - "--schemafile", - "https://raw.githubusercontent.com/devcontainers/spec/main/schemas/devContainer.schema.json", - "--force-filetype", - "json5", - ] + # - id: check-jsonschema + # name: "Validate devcontainer" + # files: ^\.devcontainer/.*\.json$ + # additional_dependencies: ['json5'] + # args: [ + # "--schemafile", + # "https://raw.githubusercontent.com/devcontainers/spec/main/schemas/devContainer.schema.json", + # "--force-filetype", + # "json5", + # "--verbose", + # ] # waiting for custom YAML tags support: https://github.com/python-jsonschema/check-jsonschema/issues/489 # - id: check-jsonschema # name: "Validate MkDocs file" From 5bba0f9b9e44705feda1dfc4c3f9042d0547f9d5 Mon Sep 17 00:00:00 2001 From: Matthias Schoettle Date: Tue, 2 Dec 2025 12:52:26 -0500 Subject: [PATCH 5/9] add legacy argument --- docs/install/index.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/docs/install/index.md b/docs/install/index.md index e4cad27..0cc1593 100644 --- a/docs/install/index.md +++ b/docs/install/index.md @@ -114,11 +114,17 @@ To separate them, run the following we use `openssl` with the `pkcs12` command: ```console # export certificate -openssl pkcs12 -in Certificates.p12 -clcerts -nokeys -out apn.crt +openssl pkcs12 -in Certificates.p12 -clcerts -nokeys -legacy -out apn.crt # export private key -openssl pkcs12 -in Certificates.p12 -nodes -nocerts -out apn.key +openssl pkcs12 -in Certificates.p12 -nodes -nocerts -legacy -out apn.key ``` +!!! note "Note on OpenSSL version" + + The above commands assume that you are using OpenSSL v3 which requires the `-legacy` flag. + This is because older algorithms like the one used by keychain when exporting the certificates are disabled by default. + If you are using OpenSSL v1.1, remove the `-legacy` flag from the commands. + ### Automated deployment We offer a semi-automated deployment via a [`copier`](https://copier.readthedocs.io/en/stable/) template. From 4d04e53bc47f84cb64c72b7bf7e3dff86bb00922 Mon Sep 17 00:00:00 2001 From: Matthias Schoettle Date: Wed, 3 Dec 2025 14:20:31 -0500 Subject: [PATCH 6/9] improve docs --- docs/development/local-dev-setup.md | 30 +++++++++++++-- docs/install/index.md | 58 +++++++++++++++++++++-------- 2 files changed, 70 insertions(+), 18 deletions(-) diff --git a/docs/development/local-dev-setup.md b/docs/development/local-dev-setup.md index 8ebfa90..dd4ed23 100644 --- a/docs/development/local-dev-setup.md +++ b/docs/development/local-dev-setup.md @@ -54,9 +54,9 @@ You need your own Firebase project so that your local app can communicate with t #### Create a new Firebase project 1. Open the [Firebase Console](https://console.firebase.google.com) -1. Click on "+ Add project" +1. Click on "Create a new Firebase project" 1. Give it a relevant project name, such as "Opal Local" -1. Uncheck "Enable Google Analytics for this project" +1. Uncheck "Enable Google Analytics for this project" and other options that are proposed to you 1. Click "Create project" The "Authentication" and "Realtime Database" features are needed for communication between the apps and backend components. @@ -89,15 +89,39 @@ See also the Firebase documentation on [Firebase Authentication](https://firebas #### Retrieve the Firebase project configurations -Retrieve the client configuration: +Retrieve the client configuration for browser and Android apps: + +##### Browser client configuration 1. Click on the settings icon (gear) next to "Project Overview" + 1. Click on "Project Settings" + 1. In the "General" tab, under "Your Apps", click the "\" icon + 1. Choose an app nickname, such as "Opal Local" + + You can also enable "Firebase Hosting" at this time if you are planning to use this project for production or intend to test the password reset feature in the app. + 1. Click "Register app" + 1. Copy the code and save it somewhere for later +##### Mobile app client configuration + +1. Go back to the "Project Settings" page +1. In the "General" tab, under "Your Apps", click the Android icon +1. Choose an Android package name +1. Click "Register app" +1. Download the `google-services.json` file and save it somewhere for later + +!!! question "Do I need to add an iOS app?" + + No. + The iOS app is reusing the `google-services.json` file during the build. + +##### Service account + Retrieve the private key for the admin SDK: 1. Go back to the "Project Settings" page and click on the "Service accounts" tab diff --git a/docs/install/index.md b/docs/install/index.md index 0cc1593..fdbd09d 100644 --- a/docs/install/index.md +++ b/docs/install/index.md @@ -47,16 +47,25 @@ A compatible container engine that also has support for compose can also be used In addition, you need a Firebase project. -#### Create a new Firebase project +#### Create and set up a new Firebase project -If you don't have a Firebase project yet, [create a Firebase project](../development/local-dev-setup.md#create-a-new-firebase-project), [create a Realtime Database](../development/local-dev-setup.md#create-a-new-realtime-database), and [enable password-based authentication](../development/local-dev-setup.md#enable-email-and-password-authentication). +If you don't have a dedicated Firebase project yet, follow the steps to [create a Firebase project](../development/local-dev-setup.md#create-a-new-firebase-project). +If you already have a dedicated Firebase project, ensure that you have done the following steps: -#### Create a Firebase service account +- [create a Realtime Database](../development/local-dev-setup.md#create-a-new-realtime-database) +- [enable email and password authentication](../development/local-dev-setup.md#enable-email-and-password-authentication) +- [retrieve Firebase configurations](../development/local-dev-setup.md#retrieve-the-firebase-project-configurations) + +#### Restrict service account permissions By default, Firebase creates a service account and API keys with excessive permissions. This is fine for development. However, it is not recommended for a production environment. +##### Create a Firebase service account + +We recommend you delete the service account that was created by default. + To create a dedicated service account, go to the [Service Accounts in Google Cloud](https://console.cloud.google.com/projectselector2/iam-admin/serviceaccounts) and: 1. Select your Firebase project @@ -110,7 +119,7 @@ You now have a `.cer` file which needs to be imported to the keychain so it can - Confirm the export with your password and selecting "Allow" The `Certificates.p12` file contains both the certificate and private key. -To separate them, run the following we use `openssl` with the `pkcs12` command: +To separate them, run the following using the OpenSSL `pkcs12` command: ```console # export certificate @@ -141,37 +150,56 @@ Please follow the instructions in the [`deploy-pie`](https://github.com/opalmeda ### Requirements -#### Create or restrict Firebase API keys +#### Restrict Firebase API keys + +We assume that you already [set up your Firebase project](#create-and-set-up-a-new-firebase-project) and [retrieved Firebase client configurations](../development/local-dev-setup.md#retrieve-the-firebase-project-configurations). +This means that API keys were already created for you. +By default, Firebase creates a service account and API keys with excessive permissions. + +!!! question "Can new API keys be created instead?" -If you already [retrieved Firebase client configurations](../development/local-dev-setup.md#retrieve-the-firebase-project-configurations), then you do not need to create new API keys but can instead restrict the already generated ones. -In that case, skip the create steps below and edit the exiting keys instead. + This is generally possible. + However, as part of the set up you will need to get a `google-services.json` file. + When this file is retrieved, Firebase automatically creates corresponding API keys. -Go to the [API Credentials in Google Cloud](https://console.cloud.google.com/apis/) and select the corresponding Firebase project. +Go to the [API Credentials in Google Cloud](https://console.cloud.google.com/apis/credentials) and select the corresponding Firebase project. ##### Browser key -1. Click "Create credentials" and select "API Key" -1. Give it a name, such as "Browser key" +1. The browser key should have a name like "Browser key (auto created by Firebase)" + +1. Click on its name to edit it + 1. Under "Application restrictions", choose "Websites" -1. Add the following websites at a minimum + +1. Add the following websites at a minimum to allow mobile app users to access this project + - `app://localhost` - `http://localhost` - `https://.firebaseapp.com` + + You should also add the base URL of your registration and web app to this list. + 1. Under "API Restrictions", choose "Restrict key" + 1. Choose the following APIs + - *FCM Registration API* - *Firebase Realtime Database Management API* - *Identity Toolkit API* -1. Click "Create" + +1. Click "Save" ##### Android key -1. Click "Create credentials" and select "API Key" -1. Give it a name, such as "Android key" +1. The Android API key should have a name like "Android key (auto created by Firebase)" +1. Click on its name to edit it 1. Under "API Restrictions", choose "Restrict key" 1. Choose the following APIs - *FCM Registration API* - *Firebase Realtime Database Management API* - *Identity Toolkit API* - *Firebase Installations API* -1. Click "Create" +1. Click "Save" + +It is also possible to restrict the key further to a specific Android app. From 7d6c60cc52c5525f01e3541a7d98c86490409999 Mon Sep 17 00:00:00 2001 From: Matthias Schoettle Date: Wed, 3 Dec 2025 14:29:22 -0500 Subject: [PATCH 7/9] update instructions for service account --- docs/install/index.md | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/docs/install/index.md b/docs/install/index.md index fdbd09d..b527f30 100644 --- a/docs/install/index.md +++ b/docs/install/index.md @@ -62,27 +62,19 @@ By default, Firebase creates a service account and API keys with excessive permi This is fine for development. However, it is not recommended for a production environment. -##### Create a Firebase service account - We recommend you delete the service account that was created by default. -To create a dedicated service account, go to the [Service Accounts in Google Cloud](https://console.cloud.google.com/projectselector2/iam-admin/serviceaccounts) and: +Go to the [Service Accounts in Google Cloud](https://console.cloud.google.com/projectselector2/iam-admin/serviceaccounts) and select your Firebase project, then: 1. Select your Firebase project -1. Select "Create service account" -1. Type in a display name and generate a service account ID -1. Click "Create and continue" -1. In the "Permissions" section, select the following roles: +1. Click on the name of the service account that was created for you +1. Go to "Permissions" and click on "Manage access" +1. Update the assigned roles to match the following roles: - *Firebase Authentication Admin* - *Firebase Cloud Messaging Admin* - *Firebase Realtime Database Admin* - *Firebase Rules Admin* -1. Click "Continue" -1. Click "Done" -1. Click on the newly created service account -1. Select "Keys", select "Add key", and then "Create new key" -1. Choose key type "JSON" and click "Create" -1. Store this file in a secure place for later +1. Click "Save" #### Retrieve the Apple Push Notification certificates From ee18d5e190c4e1f1427672de4a2da56570949fc3 Mon Sep 17 00:00:00 2001 From: Matthias Schoettle Date: Mon, 15 Dec 2025 16:48:30 -0500 Subject: [PATCH 8/9] improvements --- docs/development/local-dev-setup.md | 11 +++++++++-- docs/install/index.md | 13 ++++++++----- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/docs/development/local-dev-setup.md b/docs/development/local-dev-setup.md index dd4ed23..90a5d41 100644 --- a/docs/development/local-dev-setup.md +++ b/docs/development/local-dev-setup.md @@ -115,11 +115,18 @@ Retrieve the client configuration for browser and Android apps: 1. Click "Register app" 1. Download the `google-services.json` file and save it somewhere for later -!!! question "Do I need to add an iOS app?" +!!! question "Do I also need to add an iOS app?" - No. + You do not need to add it if you are only building the iOS app. The iOS app is reusing the `google-services.json` file during the build. + However, if you intend to use [Firebase App Distribution](https://firebase.google.com/docs/app-distribution) to distribute your mobile app to testers, you will need to register an iOS app as well. + + 1. Go back to the "Project Settings" page + 1. In the "General" tab, under "Your Apps", click the iOS icon + 1. Provide the Apple bundle ID of your app + 1. Click "Register app" + ##### Service account Retrieve the private key for the admin SDK: diff --git a/docs/install/index.md b/docs/install/index.md index b527f30..c533eb9 100644 --- a/docs/install/index.md +++ b/docs/install/index.md @@ -58,11 +58,9 @@ If you already have a dedicated Firebase project, ensure that you have done the #### Restrict service account permissions -By default, Firebase creates a service account and API keys with excessive permissions. -This is fine for development. -However, it is not recommended for a production environment. - -We recommend you delete the service account that was created by default. +By default, Firebase creates a service account and API keys. +The service account likely has more permissions than are needed. +We recommend to restrict the permissions as much as possible. Go to the [Service Accounts in Google Cloud](https://console.cloud.google.com/projectselector2/iam-admin/serviceaccounts) and select your Firebase project, then: @@ -195,3 +193,8 @@ Go to the [API Credentials in Google Cloud](https://console.cloud.google.com/api 1. Click "Save" It is also possible to restrict the key further to a specific Android app. + +##### iOS key + +The iOS key gets generated when [registering an iOS app](../development/local-dev-setup.md#mobile-app-client-configuration). +This key, named "iOS key (auto created by Firebase)", is not needed and can be deleted. From 08307318ee74905159c7ba58371041c9473ea54e Mon Sep 17 00:00:00 2001 From: Matthias Schoettle Date: Tue, 16 Dec 2025 15:43:33 -0500 Subject: [PATCH 9/9] remove redundant first step --- docs/install/index.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/install/index.md b/docs/install/index.md index c533eb9..83e7a6f 100644 --- a/docs/install/index.md +++ b/docs/install/index.md @@ -64,7 +64,6 @@ We recommend to restrict the permissions as much as possible. Go to the [Service Accounts in Google Cloud](https://console.cloud.google.com/projectselector2/iam-admin/serviceaccounts) and select your Firebase project, then: -1. Select your Firebase project 1. Click on the name of the service account that was created for you 1. Go to "Permissions" and click on "Manage access" 1. Update the assigned roles to match the following roles: