This document provides essential information regarding the process of key rotation for an Isolated Web App (IWA), including when it is necessary and the steps developers must follow if a key is lost or compromised.
Key rotation for IWAs
Key rotation is a mechanism that allows the private keys used to sign your IWA to be replaced in the event of a leak or loss. This process keeps the app functional and maintains a stable bundle ID and origin, ensuring the continuity of your app's distribution and updates.
The key rotation process doesn't require any administrator or user changes, and if performed correctly, won't be perceptible to them. The trusted contact channels established during the initial allowlisting process are essential for enabling key rotation.
The need for key rotation
Key rotation is strictly necessary in two primary scenarios:
- Key leak or compromise: If your private signing key is compromised or potentially leaked, you must immediately start the key rotation process to secure your application. A leaked key can be used to impersonate you, cause harm to your app users, and endanger your company's reputation.
- Key loss: If you lose access to your private signing key and cannot sign new updates, key rotation is required to re-establish your ability to distribute your application.
Developer requirements
Before initiating a key rotation, you must meet the following criteria:
- Allowlisted app: Only allowlisted apps can be subject to a key rotation.
- Trusted email: You must use the trusted email address provided during the allowlisting process to request a key rotation.
Resigning hosted apps and releasing new versions
After rotating a key, all installed app instances that are not signed with a valid key are blocked. To prevent disruptions for your users, you must deliver an app signed with the new key (or both keys). The technical details of resigning bundles can be found in the section How to sign a bundle with multiple keys. Depending on your specific situation, there are different scenarios:
Scenario A: The key is not lost (for example, proactive rotation or leak)
You must sign the app with both keys (the old and the new one) and deliver them to users by either:
- Releasing a new app version (adding the new version to your update manifests), or
- Updating your hosted
.swbnfiles (linked in your update manifests) to be signed with both keys. The CLI tool lets you add another signature to the existingswbnbundle.
This must be done before the key rotation is processed by Google to ensure your users won't notice the change.
Scenario B: The key is lost
Because the app cannot be signed with the lost key this case is more complex. Request the key rotation and ask your Google contact for further steps. You might be asked to add the new signatures to your hosted bundles following these instructions.
Key rotation process
The process for key rotation involves the following steps:
| Step | Action | Details | Responsible |
|---|---|---|---|
| 1 | Request key rotation | Developer/partner reaches out to their Google contact (Partner Engineering or other point of contact) through trusted email provided in allowlisting process and asks for the key rotation instructions explaining the reason. In the key compromised case we recommend attaching the update manifest with bundles signed with old and new keys to speed up the process. | Developer / Partner |
| 2 | Response to requestor | Google contact provides further instructions and questions to the requestor. This step may involve a few back-and-forths. | Google Contact |
| 3 | Provide data | Developer/partner follows instructions, which among others may involve:
|
Developer / Partner |
| 4 | Request processing and providing feedback |
Google reviews the key rotation request and responds within one business week, either approving or denying it, or contacting the developer with further questions. Upon approval, Google rotates the key and provides feedback. | Google Contact |
Update channel and version pinning
Administrators sometimes use custom update channels or version pinning, which lets them
manage app versions on their client devices. After a key rotation, all
apps installed with invalid keys become invalid and are blocked. To prevent
this, earlier versions of apps hosted under links provided in the
update_manifest.json must also be updated and signed with two signatures prior
to the key rotation. If your old key is lost and the app cannot be signed with
two keys, notify your Google contact immediately. We will work with you
to mitigate the situation so the app can be updated without disturbing your
users' workflows.
How to sign a bundle with multiple keys
This section describes how you can sign your web bundles with one or two keys
through CLI tools, or Webpack/Rollup/Vite plugins configuration. CLI tools also
enable adding one more signature to existing swbn bundles, which might be
useful in key-lost cases or updating the previous hosted bundles.
CLI Tools
First, ensure you have the wbn-sign package installed with npm:
$ npm i wbn-sign
Add -g to install the package globally instead of doing it only in the current
folder.
Signing with one key
$ wbn-sign -i unsigned.wbn -o signed.swbn -k private.pem
Signing with two keys
$ wbn-sign sign webbundle.wbn old_key.pem new_key.pem -o signed.swbn --web-bundle-id <your-id-from-old-private>
The --web-bundle-id <id> argument can be skipped, if old_key is the first key
the initial version of the app was signed with, then the bundle ID will be
derived from the key. You can verify the bundle ID with
wbn-sign info signed.swbn command.
Adding a signature to the existing bundle
$ wbn-sign add-signature signed.swbn key3.pem --in-place
Use -o if you don't want to override the bundle but create a new
double-signed.
More information about CLI Tool
For more information on using CLI tool check the npm wbn-sign
page. Alternatively, use: wnb-sign
help.
Webpack plugin
Signing with one key
To configure the Webpack plugin to sign your IWA using a single private key:
- Set up the
WebBundlePluginto automatically derive the required Base URL directly from this key. - Use a single
NodeCryptoSigningStrategyto produce your signed.swbnfile.
// key is parsePemKey(private.pem)
plugins.push(
new WebBundlePlugin({
baseURL: new WebBundleId(key).serializeWithIsolatedWebAppOrigin(),
static: { dir: 'public' },
output: 'signed.swbn',
integrityBlockSign: {
strategy: new NodeCryptoSigningStrategy(key)
}
})
)
Signing with two keys
When you need to double-sign your application during a key rotation:
- Define the
webBundleIdand Base URL based on your original (old_key) to ensure the app's identity remains stable for your users. - Use an array of signing strategies to apply both your old and new private keys.
// old_key is parsePemKey(old_private.pem)
// new_key is parsePemKey(new_private.pem)
plugins.push(
new WebBundlePlugin({
baseURL: new WebBundleId(old_key).serializeWithIsolatedWebAppOrigin(),
static: { dir: 'public') },
output: 'signed.swbn',
integrityBlockSign: {
strategies: [
new NodeCryptoSigningStrategy(old_key),
new NodeCryptoSigningStrategy(new_key)
],
webBundleId: new WebBundleId(old_key).serialize()
}
})
)
Rollup or Vite plugin
Signing with one key
To use the Rollup or Vite plugin to sign your application with a single private key, similar to the Webpack setup, the plugin uses a single signing strategy and handles deriving the Base URL from the provided key to generate your signed output.
// key is parsePemKey(private.pem)
plugins.push({
...wbn({
baseURL: new WebBundleId(key).serializeWithIsolatedWebAppOrigin(),
static: { dir: 'public' },
output: 'signed.swbn',
integrityBlockSign: {
strategy: new NodeCryptoSigningStrategy(key)
}
}),
enforce: 'post'
})
Signing with two keys
To double-sign your application using Rollup or Vite, you must configure the
plugin to accept multiple keys. This snippet applies both the old and new
private keys using the strategies array. It ensures a seamless transition by
explicitly maintaining the Base URL and webBundleId derived from your
original, existing key.
// old_key is parsePemKey(old_private.pem)
// new_key is parsePemKey(new_private.pem)
plugins.push({
...wbn({
baseURL: new WebBundleId(old_key).serializeWithIsolatedWebAppOrigin(),
static: { dir: 'public' },
output: 'signed.swbn',
integrityBlockSign: {
strategies: [
new NodeCryptoSigningStrategy(old_key),
new NodeCryptoSigningStrategy(new_key)
],
webBundleId: new WebBundleId(old_key).serialize()
}
}),
enforce: 'post'
})
Conclusion
Successfully managing key rotation for your IWA is crucial for maintaining the security and continuity of your application's distribution. Independently on your specific situation (for example, whether the key is lost or not), following the outlined steps ensures that your users experience minimal disruption. By utilizing the provided CLI tools or plugin configurations for Webpack, Rollup, or Vite, you can efficiently manage your app's signatures and navigate the key rotation process smoothly. In emergency scenarios, remember to communicate promptly with your Google contact through your designated trusted email.