diff --git a/docs/architecture/index.mdx b/docs/architecture/index.mdx new file mode 100644 index 000000000..ba5de46cb --- /dev/null +++ b/docs/architecture/index.mdx @@ -0,0 +1,79 @@ +--- +sidebar_position: 5 +--- + +# .NET MAUI (legacy) + +:::warning Legacy + +This represents the **legacy** mobile app architecture done in .NET MAUI. + +::: + +The mobile .NET MAUI clients are Android and iOS applications with extensions and watchOS. They are +all located at https://github.com/bitwarden/mobile. + +Principal structure is a follows: + +- `App`: Main .NET MAUI project that shares code between both platforms (Android & iOS). One can see + specific platform code under the `Platforms` folder. +- `Core`: Shared code having both logical and UI parts of the app. Several classes are a port from + the Web Clients to C#. Here one can find most of the UI and logic since it's shared between App + and the iOS extensions. +- `iOS.Core`: Shared code used by the main iOS app and its extensions +- `iOS.Autofill`: iOS extension that handles Autofill +- `iOS.Extensions`: iOS extension that handles Autofill from the bottom sheet extension +- `iOS.ShareExtension`: iOS extension that handles sharing files through Send +- `watchOS`: All the code specific to the watchOS platform + - `bitwarden`: Stub iOS app so that the watchOS app has a companion app on Xcode + - `bitwarden WatchKit App`: Main Watch app where we set assets. + - `bitwarden WatchKit Extension`: All the logic and presentation logic for the Watch app is here + +## Dependencies diagram + +Below is a simplified dependencies diagram of the mobile repository. + +```kroki type=plantuml +@startuml +skinparam BackgroundColor transparent +skinparam componentStyle rectangle +skinparam linetype ortho + +title Simplified Dependencies Diagram + +component "Core" +component "App" +component "iOS.Core" +component "iOS.Autofill" +component "iOS.Extension" +component "iOS.ShareExtension" +component "watchOS" { + component "bitwarden" + component "bitwarden WatchKit App" + component "bitwarden WatchKit Extension" +} + +[App] --> [Core] + +[iOS.Core] --> [App] + +[App] --> [iOS.Core] +[App] --> [iOS.Autofill] +[App] --> [iOS.Extension] +[App] --> [iOS.ShareExtension] +[App] --> [bitwarden WatchKit App] + +[iOS.Autofill] --> [Core] +[iOS.Autofill] --> [iOS.Core] + +[iOS.Extension] --> [Core] +[iOS.Extension] --> [iOS.Core] + +[iOS.ShareExtension] --> [Core] +[iOS.ShareExtension] --> [iOS.Core] + +[bitwarden] --> [bitwarden WatchKit App] +[bitwarden WatchKit App] --> [bitwarden WatchKit Extension] + +@enduml +``` diff --git a/docs/architecture/overview.md b/docs/architecture/overview.md new file mode 100644 index 000000000..8a1a21f0b --- /dev/null +++ b/docs/architecture/overview.md @@ -0,0 +1,26 @@ +--- +sidebar_position: 1 +--- + +# Overview + +:::warning Legacy + +This represents the **legacy** mobile app overview architecture done in .NET MAUI. + +::: + +The overall architecture of the mobile applications is pretty similar to the +[web clients](../../clients/overview.md) one following a layered architecture: + +- State +- Services +- Presentation + +Even though the State and Services layers are pretty similar to the web ones the Presentation layer +differs: + +## Presentation + +The presentation layer is implemented using .NET MAUI for the mobile apps, except for the watchOS +one which uses SwiftUI [see ADR](../../adr/0017-watchOS-use-swift.md) diff --git a/docs/architecture/watchOS.md b/docs/architecture/watchOS.md new file mode 100644 index 000000000..9f522a4de --- /dev/null +++ b/docs/architecture/watchOS.md @@ -0,0 +1,186 @@ +# watchOS + +:::warning Legacy + +This represents the **legacy** watchOS app architecture done in .NET MAUI. + +::: + +## Overall architecture + +The watchOS application is organized as follows: + +- `src/watchOS`: All the code specific to the watchOS platform + - `bitwarden`: Stub iOS app so that the watchOS app has a companion app on Xcode + - `bitwarden WatchKit App`: Main Watch app where we set assets. + - `bitwarden WatchKit Extension`: All the logic and presentation logic for the Watch app is here + +So almost all the things related to the watch app will be in the **WatchKit Extension**, the +WatchKit App one will be only for assets and some configs. + +Then in the Extension we have a layered architecture: + +- State (it's a really simplified version of the iOS state) +- Persistence (here we use `CoreData` to interact with the Database) +- Services (totp generation, crypto services and business logic) +- Presentation (use `SwiftUI` for the UI with an MVVM pattern) + +## Integration with iOS + +The watchOS app is developed using `Xcode` and `Swift` and we need to integrate it to the .NET MAUI +iOS application. + +For this, the `iOS.csproj` has been adapted taking a +[solution](https://github.com/xamarin/xamarin-macios/issues/10070#issuecomment-1033428823) provided +in the `Xamarin.Forms` GitHub repository and modified to our needs: + +```xml + + $(Home)/Library/Developer/Xcode/DerivedData/bitwarden-cbtqsueryycvflfzbsoteofskiyr/Build/Products + $([System.IO.Path]::GetFullPath('$(MSBuildProjectDirectory)\..'))/watchOS/bitwarden.xcarchive/Products/Applications/bitwarden.app/Watch + Bitwarden.app + watchsimulator + watchos + $(WatchAppBuildPath)/$(Configuration)-$(WatchAppConfiguration)/$(WatchAppBundle) + $(WatchAppBuildPath)/$(WatchAppBundle) + + +... + + + <_ResolvedWatchAppReferences Include="$(WatchAppBundleFullPath)" /> + + + <_ResolvedWatchAppReferences Include="$(WatchAppBundleFullPath)" /> + + + --deep + + + + + +``` + +So on the `PropertyGroup` the `WatchAppBundleFullPath` is assembled together depending on the +Configuration and the Platform taking the output of the Xcode watchOS app build. Then there are some +`ItemGroup` to include the watch app depending on if it exists and the Configuration. The task +`_ResolvedWatchAppReferences` is the one responsible to peek into the `Bitwarden.app` built by Xcode +and if it finds a Watch app, it will just bundle it to the Xamarin iOS application. Finally, if the +Watch app is bundled, deep signing is enabled and the build path is printed. + +:::caution + +As one can see in the csproj, to bundle the watchOS app into the iOS app one needs to target the +correct platform. So if one is going to use a device, target the device on Xcode to build the +watchOS app and after the build is done one can go to VS4M to build the iOS app (which will bundle +the watchOS one) and run it on the device. + +::: + +## Synchronization between iPhone and Watch + +In order to sync data between the iPhone and the Watch apps the +[Watch Connectivity Framework](https://developer.apple.com/documentation/watchconnectivity) is used. + +So there is a Watch Connectivity Manager on each side that is the interface used for the services on +each platform to communicate. + +For the sync communication, mainly +[updateApplicationContext](https://developer.apple.com/documentation/watchconnectivity/wcsession/1615621-updateapplicationcontext) +is used given that it always have the latest data sent available, it's sent in the background and +the counterpart device doesn't necessarily needs to be in range (so it's cached until it can be +delivered). Additionally, +[sendMessage](https://developer.apple.com/documentation/watchconnectivity/wcsession/1615687-sendmessage) +is also used to signal the counterpart of some action to take quickly (like triggering a sync from +the Watch). + +The `WatchDTO` is the object that is sent in the synchronization that has all the information for +the Watch. + +```kroki type=plantuml +title= iOS part +@startuml + +title iOS + +participant C as "Caller" +participant BWDS as "BaseWatchDeviceService" +participant WDS as "WatchDeviceService" +participant WCSM as "WCSessionManager" +boundary WCF as "Watch Connectivity Framework" + +group Sync +C->>BWDS: SyncDataToWatchAsync(...) +BWDS->BWDS: GetStateAsync(...) +BWDS->>WDS: SendDataToWatchAsync(...) +WDS->>WCSM: SendBackgroundHighPriorityMessage(...) +WCSM->>WCF: UpdateApplicationContext(...) +end +@enduml +``` + +```kroki type=plantuml +title= iOS part +@startuml + +title watchOS + +boundary WCF as "Watch Connectivity Framework" +participant WCM as "WatchConnectivityManager" +participant SS as "StateService" +participant ES as "EnvironmentService" +participant CS as "CipherService" +participant WCS as "watchConnectivitySubject" + +group Sync +WCF->>WCM: didReceiveApplicationContext(...) +WCM->>SS: update state +WCM->>ES: update environment +WCM->>CS: saveCiphers(...) +WCM->>WCS: fire notification change to subscribers +end +@enduml +``` + +## States + +The next ones are the states in which the Watch application can be at a given time: + +- **Valid:** Everything it's ok and the user can see the vault ciphers with TOTP +- **Need Login:** The user needs to log in using the iPhone +- **Need Setup:** The user needs to set up an account with "Connect to Watch" enabled on their + iPhone +- **Need Premium:** The current account is not a premium account +- **Need 2FA item:** The current account doesn't have any cipher with TOTP set up +- **Syncing:** Displayed when changing accounts and syncing the new vault TOTPs +- **Need Device Owner Auth:** The user needs to set up an Apple Watch Passcode in order to use the + app + +## Persistence and encryption + +On the Watch [CoreData](https://developer.apple.com/documentation/coredata) is used as persistence +for the ciphers. So in order to encrypt the data in them a Value Transformer in each encrypted +attribute is used: `StringEncryptionTransformer`. + +Inside the transformer a call to the `CryptoService` is used that ends up using +[AES.GCM](https://developer.apple.com/documentation/cryptokit/aes/gcm) to encrypt the data with a +256 bits [SymmetricKey](https://developer.apple.com/documentation/cryptokit/symmetrickey). The key +is generated/loaded the first time something needs to be encrypted and stored in the device +Keychain. + +## Crash reporting + +On all the other mobile applications, [AppCenter](https://appcenter.ms/) is being used as Crash +reporting tool. However, it doesn't have support for watchOS (nor its internal library to handle +crashes). + +So, on the watchOS app [Firebase Crashlytics](https://firebase.google.com/docs/crashlytics) is used +with basic crash reporting enabled (there is no handled error logging here yet). For this to work a +`GoogleService-Info.plist` file is needed which is injected on the CI. + +At the moment of writing this document, no plist is configured for dev environment so `Crashlytics` +is enabled on **non-DEBUG** configurations. + +There is a `Log` class to log errors happened in the app, but it's only enabled in **DEBUG** +configuration. diff --git a/docs/getting-started/android/android-sdk.png b/docs/getting-started/android/android-sdk.png new file mode 100644 index 000000000..f35250432 Binary files /dev/null and b/docs/getting-started/android/android-sdk.png differ diff --git a/docs/getting-started/android/index.md b/docs/getting-started/android/index.md new file mode 100644 index 000000000..d4e9d5c30 --- /dev/null +++ b/docs/getting-started/android/index.md @@ -0,0 +1,177 @@ +# Android + +:::warning Legacy + +Getting started the **legacy** Android app done in .NET MAUI. + +::: + +## Requirements + +Before you start, you should have the recommended [Tools and Libraries](../../../tools/index.md) +installed. You will also need to install: + +1. Visual Studio 2022 / VS Code +2. [.NET 8 (latest)](https://dotnet.microsoft.com/en-us/download/dotnet/8.0) + - Note: Even if you have an ARM64 based Mac (M1, M2, M3, etc.), you can install all x64 SDKs to + run Android + - On Visual Studio for Mac you may need to turn on the feature for .NET 8 by going to Visual + Studio > Preferences > Preview Features > Use the .NET 8 SDK +3. .NET MAUI Workload + - You can install this by running `dotnet workload install maui` +4. Android SDK 34 + - You can use the SDK manager in [Visual Studio][xamarin-vs], or [Android + Studio][android-studio] to install this + +To make sure you have the Android SDK and Emulator installed: + +1. Open Visual Studio +2. Click Tools > SDK Manager (under the Android subheading) +3. Click the Tools tab +4. Make sure the following items are installed: + + - Android SDK tools (at least one version of the command-line tools) + - Android SDK Platform-Tools + - Android SDK Build Tools (at least one version) + - Android Emulator + +5. Click Apply Changes if you've marked anything for installation + +If you've missed anything, Visual Studio should prompt you anyway. + +## Android Development Setup + +To set up a new virtual Android device for debugging: + +1. Click Tools > Device Manager (under the Android subheading) +2. Click New Device +3. Set up the device you want to emulate - you can just choose the Base Device and leave the + default settings if you're unsure +4. Visual Studio will then download the image for that device. The download progress is shown in + the progress in the Android Device Manager dialog. +5. Once this has completed, the emulated Android device will be available as a build target under + App > Debug > (name of device) + +### ARM64 Macs + +1. Install and open Android Studio +2. In the top navbar, click on Android Studio > Settings > Appearance & Behavior (tab) > System + Settings > Android SDK +3. In the SDK Platforms tab, ensure the "Show Package Details" checkbox is checked (located in the + bottom-right) +4. Bellow each Android API you'll see several System Images, pick one of the `ARM 64 v8a` and wait + for it to download +5. Go to View > Tool Windows > Device Manager +6. Inside Device Manager, create a device using the previously downloaded system image + +![Android SDK configuration](android-sdk.png) + +## F-Droid + +On `App.csproj` and `Core.csproj` we can now pass `/p:CustomConstants=FDROID` when +building/releasing so that the `FDROID` constant is added to the defined ones at the project level +and we can use that with precompiler directives, e.g.: + +```c# +#if FDROID + // perform operation only for FDROID. +#endif +``` + +## Building + +There are currently a few problems on Visual Studio for Mac for building correctly the projects, so +if you encounter some errors build using the CLI (previously removing bin/obj folders): + +``` +dotnet build -f net8.0-android -c Debug +``` + +## Testing and Debugging + +### Using the Android Emulator + +In order to access `localhost:` resources in the Android Emulator when debugging using Visual +Studio on your Mac natively, you'll need to configure the endpoint addresses using +``\> in order to access `localhost`, which maps the Android proxy by design. + +[xamarin-vs]: https://learn.microsoft.com/en-us/xamarin/android/get-started/installation/android-sdk +[android-studio]: https://developer.android.com/studio/releases/platforms + +### Using Server Tunneling + +Instead of configuring your device or emulator, you can instead use a +[proxy tunnel to your local server](../../../server/tunnel.md) and have your app connect to it +directly. + +### Push Notifications + +The default configuration for the Android app is to register itself to the same environment as +Bitwarden's QA Cloud. This means that if you try to debug the app using the production endpoints you +won't be able to receive Live Sync updates or Passwordless login requests. + + + +So, in order to receive notifications while debugging, you have two options: + +- Use QA Cloud endpoints for the Api and Identity, or +- Use a local server setup where the Api is connected to QA Azure Notification Hub + + + +### Testing Passwordless Locally + +Before you can start testing and debugging passwordless logins, make sure your local server setup is +running correctly ([server setup](../../../server/guide.md)). You should also be able to deploy your +Android app to your device or emulator. + +:::note + +Debugging and testing passwordless authentication is limited by +[push notifications](#push-notifications). + +::: + +Testing passwordless notifications: + +1. Start your local server (`Api`, `Identity`, `Notifications`) +2. Make sure your mobile device can [connect to your local server](#using-server-tunneling) +3. [Start the web client](../../../clients/web-vault/index.mdx), as you will need it to make login + requests +4. Deploy the Android app to your device or emulator +5. After deployment, open the app, login to your QA account and activate passwordless login requests + in settings +6. Open the web vault using your preferred browser (ex: http://localhost:8080) +7. Enter the email address of an account that has previously authenticated on that device (i.e. is a + "known device") and click Continue. When presented with the login options, click click Login with + Device. +8. Check mobile device for the notification + + + +## AndroidX Credentials + +Currently, the +[androidx.credentials](https://developer.android.com/jetpack/androidx/releases/credentials) official +binding has some bugs and we cannot use it yet. Because of this, we made a binding ourselves which +is located in here: +[Xamarin.AndroidX.Credentials](https://github.com/bitwarden/xamarin.androidx.credentials). + +As of today, we are using version 1.2.0. + +In the projects, the package is added as a local NuGet package located in +`lib/android/Xamarin.AndroidX.Credentials` and this source is already configured in the +`nuget.config` file. + +In the case a change is needed on the binding, create a new local NuGet package and replace it in +the aforementioned source. + +:::warning + +Do not add the project to the solution and as a project reference to the `App.csproj` / +`Core.csproj` this will strangely make the iOS app crash on start because of solution configuration. +Even though we couldn't find the root cause, this is the effect caused by this action. + +::: + + diff --git a/docs/getting-started/index.md b/docs/getting-started/index.md new file mode 100644 index 000000000..d8988ba81 --- /dev/null +++ b/docs/getting-started/index.md @@ -0,0 +1,107 @@ +--- +sidebar_position: 4 +--- + +# .NET MAUI (legacy) + +:::warning Legacy + +Getting started the **legacy** mobile app done in .NET MAUI. + +::: + +## Configure Git blame + +We recommend that you configure git to ignore the Prettier revision: + +```bash +git config blame.ignoreRevsFile .git-blame-ignore-revs +``` + +## Android Development + +See the [Android Mobile app](./android/index.md) page to set up an Android development environment. + +## iOS Development + + + +See the [iOS Mobile app](./ios/index.mdx) page to set up an iOS development environment. + + + + + +Unfortunately, iOS development requires provisioning profiles and other capabilities only available +to internal team members. We do not have any documentation for community developers at this time. + + + +## watchOS Development + + + +See the [watchOS app](./watchos) page to set up an watchOS development environment. + + + + + +Unfortunately, watchOS development requires provisioning profiles and other capabilities only +available to internal team members. We do not have any documentation for community developers at +this time. + + + +## Unit tests + +:::info TL;DR; + +In order to run unit tests add the argument `/p:CustomConstants=UT` on the `dotnet` command for +building/running. To work on Unit testing or use a Test runner uncomment the `CustomConstants` line +on the `Directory.Build.props` + +::: + +Given that the `Core.csproj` is a MAUI project with `net8.0-android;net8.0-ios` target frameworks +and we need `net8.0` for the tests we need a way to add that. The `Core.Test.csproj` has `net8.0` as +a target so by adding the the argument `/p:CustomConstants=UT` we add `UT` as a constant to use in +the projects. With that in place the next things happen: + +- `UT` is added as a constant to use by precompiler directives +- `Core.csproj` is changed to add `net8.0` as a target framework for unit tests +- `FFImageLoading` is removed as a reference given that it doesn't support `net8.0`. Because of + this, now we have a wrapped `CachedImage` that uses the library one if it's not `UT` and a custom + one with NOOP implementation for `UT` + +So if one wants to build the test project, one needs to go to `test/Core.Test` and run: + +```bash +dotnet build -f net8.0 /p:CustomConstants=UT +``` + +and to run the tests go to the same folder and run: + +```bash +dotnet test -f net8.0 /p:CustomConstants=UT +``` + +Finally, when working on the `Core.Test` project or when wanting to use a Test runner, go to the +`Directory.Build.props` (located in the root) and uncomment the line referencing `CustomConstants` +so that everything is loaded accordingly in the project. Because of some issues, the referenced +projects, e.g. `Core`, are only included when the `UT` constant is in place. By uncommenting this +line the projects will be referenced and one can work on that project or run the tests from a Test +runner. + +## Custom constants + +There are custom constants to be used by the parameter `/p:CustomConstants={Value}` when +building/running/releasing: + +- `FDROID`: This is used to indicate that it's and F-Droid build/release + ([want to know more?](./android/index.md#f-droid)) +- `UT`: This is used when building/running the test projects or when working on one of them + ([want to know more?](#unit-tests)) + +These constants are added to the defined ones, so anyone can use them in the code with precompiler +directives. diff --git a/docs/getting-started/ios/index.mdx b/docs/getting-started/ios/index.mdx new file mode 100644 index 000000000..0406b1101 --- /dev/null +++ b/docs/getting-started/ios/index.mdx @@ -0,0 +1,440 @@ +--- +sidebar_custom_props: + access: bitwarden +--- + +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + +# iOS + +:::warning Legacy + +Getting started the **legacy** iOS app done in .NET MAUI. + +::: + +## Requirements + +1. Visual Studio 2022 / VS Code +2. [.NET 8 (latest)](https://dotnet.microsoft.com/en-us/download/dotnet/8.0) + - On Visual Studio for Mac you may need to turn on the feature for .NET 8 by going to Visual + Studio > Preferences > Preview Features > Use the .NET 8 SDK +3. .NET MAUI Workload + - You can install this by running `dotnet workload install maui` +4. A Mac with Xcode 15.0 installed + +## Apple Developer Account Setup + +1. Accept your invite to the Bitwarden Apple Developer team. You should get a request in your email + with the subject "You're invited to join a development team." Click the link, "Accept Invitation" + and you'll be prompted to create an Apple ID for your Bitwarden email address. If you didn't + receive this email, contact the IT department (@IT in slack). Accept the terms and conditions and + complete the sign up flow + +2. Go to [Apple ID Online](https://appleid.apple.com/) and log in with your new Apple ID. Set up + 2-factor authentication (using mobile phone and/or trusted device) - this is critical because + Apple no longer allows "developer" accounts without MFA, but it won't tell you that when your + build fails locally + +3. Go to [App Store Connect](https://appstoreconnect.apple.com/) and accept the terms and conditions + +4. Ensure you have access to the Bitwarden team and team app profiles + +5. Go to [Apple Developer Account](https://developer.apple.com/account/) and go to the + "Certificates, IDs & Profiles" menu item. Check that you can see the 8bit Solutions LLC + Certificates in the Certificates section, and the Bitwarden profiles in the Profiles section. If + any of this is missing, ask the IT department (@IT #tech-support in slack) for the additional + roles / permissions + +## macOS Setup + +Next, you need to get your Mac environment set up for building and running the Bitwarden iOS mobile +project. This requires creating the necessary developer provisioning profiles for code signing and +execution on your Mac through Xcode. Visual Studio has a simple process to get all of the +provisioning profiles, however this is prone to fail without much feedback. Try the Visual Studio +instructions ("The Easy Way") first, and fallback to the Xcode instructions (“The Hard Way”) if +required. + +### Visual Studio: The Easy Way + +1. Open Visual Studio for Mac + +2. Go to Preferences > Publishing > Apple Developer Accounts + +3. Click “Add”, choose "Enterprise Account", and sign in with your previously configured Apple + Developer account + + :::note + + If you receive a "Failed to synchronize with Apple Developer Portal" error, you’re missing + additional roles / permissions. + + ::: + + After signing in successfully, you should see your account in the list and “Bitwarden Inc” in + the account teams list + +4. Click “View Details…” + +5. If you don’t have a valid Apple Development certificate, click Create certificate > Apple + Development + +6. Click “Download All Profiles” + +7. You should now be able to run the app by setting + `iOS > Debug | iPhone Simulator > [pick any iOS Simulator]` in the top left corner and pressing + Play + + ![](./run-debug.png) + +If this worked, you can skip the next section. + +If you only have the option "Generic Simulator", with a message to lower the 'Deployment Target', +your version of MAUI may not yet support the version of Xcode that you are using (as discussed +[here](https://github.com/xamarin/xamarin-macios/issues/15954#issuecomment-1246025735)). + +![](./troubleshoot-generic-simulator.png) + +To work around this issue, try [downloading](https://developer.apple.com/download/all/) and +installing an older version of Xcode from Apple (you can look for guidance on which Xcode version to +use from the Xamarin.iOS [release notes](https://github.com/xamarin/xamarin-macios/releases) (this +applies to MAUI as well). After installing the new version of Xcode, restart Visual Studio and load +your project to verify your available simulator options. + +:::note + +If you need multiple versions of Xcode installed on your development machine, you can rename the +`Xcode.app` file extracted from your download to something else (e.g. "Xcode_14_2.app") before +placing it in your Applications folder. You can then switch between Xcode versions by using +`xcode-select` from the command line. e.g.: + +```shell +sudo xcode-select -s /Applications/Xcode_14_2.app +``` + +You may achieve similar results with tooling such as +[Xcodes.app](https://github.com/XcodesOrg/XcodesApp) + +::: + +### Xcode: The Hard Way + +:::note + +If you're the next person to follow these instructions, please commit and upload the Xcode project +files you create so we can streamline this process. + +::: + +Only try these instructions if the Visual Studio instructions above didn't work for you. + +1. Open Xcode + +2. Accept any defaults, ensure any extensions/add-ons have been installed, etc. + +3. Create new project... > iOS > App + +4. Use the following options for your new project: + + - Product Name: "bitwarden" + + - Team: Bitwarden Inc (if this is missing, double check your Apple Developer Account setup + above) + + - Organization Identifier: "com.8bit" + + - Bundle Identifier (automatically generated): "com.8bit.bitwarden" + + - Language: Objective-C + + - User Interface: Storyboard + + - Leave all other checkboxes unchecked (or uncheck them) + + ![Example configuration for new Xcode project](./new-project-options.png) + +5. Click Next, save to the default location and then click "Create" + +6. On the project configuration page, click the "Signing & Capabilities" tab + +7. Make sure you have the following defaults: + + - Automatically manage signing: (checked) + + - Team: Bitwarden Inc + + - Provisioning Profile: Xcode Managed Profile + + - Signing Certificate: your Apple ID/Name + + ![Example configuration for Signing & Capabilities screen](./signing-and-capabilities.png) + +8. From the menu bar, click Product > Build + +9. Repeat Steps 3-8, with the following changes in step 4: + + - Product Name: "find-login-action-extension" + + - Organization Identifier: "com.8bit.bitwarden" + + - Bundle Identifier (automatically generated): "com.8bit.bitwarden.find-login-action-extension" + +10. Repeat Steps 3-8, with the following changes in step 4: + + - Product Name: "autofill" + + - Organization Identifier: "com.8bit.bitwarden" + + - Bundle Identifier (automatically generated): "com.8bit.bitwarden.autofill" + +11. Repeat Steps 3-8, with the following changes in step 4: + + - Product Name: "share-extension" + + - Organization Identifier: "com.8bit.bitwarden" + + - Bundle Identifier (automatically generated): "com.8bit.bitwarden.share-extension" + +12. If you have a physical device (e.g. iPhone or iPad) that you want to use for testing, you will + also need to do the following for each of the Xcode projects you just created: + + - connect the device with a cable + + - select your device as as the build target in Xcode + + - from the menu bar, click Product > Build + + - agree to register your device if asked + + :::note + + Sometimes these profiles can mess up. If you have issues running on your physical device (or + simulator) try running `rm -r ~/Library/MobileDevice/Provisioning\ Profiles` to clear them out. + Build each Xcode project again to regenerate them. + + ::: + +## Visual Studio + +Next, we need to configure your Visual Studio environment for development. + + + + +1. Connect to the Mac that you just completed the above steps on + +2. Open Visual Studio and click Tools > iOS > Pair to Mac + +3. Scan for and select your machine. If you don't see it, click the "Add Mac..." button and put in + the Mac name or IP address. If you don't know your Mac name (or you're in a Windows VM on your + Mac), go to your Mac and open System Preferences > Sharing and look for the ".local" address of + your machine + +4. Provide your Username and Password for macOS when prompted + +5. Once paired, close the Pair Mac window + +6. Change your active build profile to Debug > iPhoneSimulator > iOS + +7. Rebuild the iOS project from Solution Explorer + +8. You can now debug using the iOS Simulator + + + + +1. Check that command line tools are installed: + + 1. Open Xcode + + 2. From the menu bar, click Xcode > Preferences > Locations + + 3. Make sure an Xcode version is selected under "Command Line Tools" + +2. Open Visual Studio for Mac + +3. Open the mobile solution file (`bitwarden-mobile.sln`) in the root of your local mobile + repository + +4. In the top bar, you should be able to select App > Debug > select your model and click run (or + your physical device if you set one up) + + + + +## Building + +To build from the CLI, navigate to the application directory: + +For device: + +``` +cd src/App +dotnet build -f net8.0-ios -c Debug -r ios-arm64 +``` + +For simulator: + +``` +cd src/App +dotnet build -f net8.0-ios -c Debug -r iossimulator-x64 +``` + +You can also use the IDE but keep in mind: + +:::tip Visual Studio for Mac + +There are currently a few problems on Visual Studio for Mac for building correctly the projects, so +if you encounter some errors, build using the CLI being into the `src/App` folder (previously +removing bin/obj folders). + +::: + +:::tip Argon2Id + +If you find any errors regarding argon2Id library when building for simulator, please be sure that +you are building for runtime identifier `iossimulator-x64` as currently the library doesn't support +`iossimulator-arm64`. + +::: + +:::tip Troubleshooting common mistakes + +If you find the next error: + +> `error NETSDK1134`: Building a solution with a specific RuntimeIdentifier is not supported. If you +> would like to publish for a single RID, specify the RID at the individual project level instead + +you almost surely are trying to build the app from the root folder. Instead go to `src/App` and try +building again. + +::: + +### Argon2Id library loading + +The Argon2Id library (`libargon2.a`) is loaded using `MTouchExtraArgs` in almost all projects of the +solution. In order to make this simpler a property was added into **Directory.Build.props** called +`Argon2IdLoadMtouchExtraArgs` which has the code to fill in the extra args parameter. Each project +is configured with this property so this is only added on the correct runtime identifiers and we can +build the app successfully on each case. + +### Ignoring extensions / watchOS app + +Sometimes we need to quickly build the app or maybe some configuration on the iOS extensions or the +watchOS app gets in the way. In order to have a fast way to only care about the main app two +properties were added to the **Directory.Build.Props** to help with this: + +- `IncludeBitwardeniOSExtensions`: If `True` then all the iOS extensions will be included on the + building of the main app, otherwise they will be skipped. +- `IncludeBitwardenWatchOSApp`: If `True` then the watchOS app will be included on the building of + the main app, otherwise it will be skipped. + +:::warning Shared code + +Toggling these off can provide a faster developer experience which is really useful in a lot of +scenarios, but always bear in mind that a lot of things are shared between the main app and the +extensions so before pushing your work, test again with everything enabled just in case. + +::: + +### Release mode locally + +There are some issues that require us to build the app on **Release** configuration but locally +without going through the CI/CD pipeline. The problem is that we don't have the code signing details +for Distribution locally. To overcome this we can use the same `CodesignProvision` and `CodesignKey` +we use for **Debug** but on the **Release** config. The thing is that it's a bit cumbersome to +change that on every project so two properties were added to the **Directory.Build.Props** to help +with this: + +- `ReleaseCodesignProvision`: `CodesignProvision` for Release config on all projects +- `ReleaseCodesignKey`: `CodesignKey` for Release config on all projects + +By replacing their values, all projects will have their values applied so it's easier to build the +app in **Release** mode locally. + +## Debugging + +### iPhone Simulator + +The iPhone Simulator has access to localhost and you can point the client at your local dev server +as usual. However, the app will require https by default. To allow http for testing purposes, follow +these steps. + +1. Open `src/App/Platforms/iOS/Info.plist` in Visual Studio Code or another editor so that you can + edit the raw XML. (Don't use the Property List Editor in Visual Studio.) + +2. Add the following code in the top-level `` element: + + ```xml + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + NSExceptionDomains + + localhost + + NSExceptionAllowsInsecureHTTPLoads + + NSIncludesSubdomains + + + + + ``` + +3. Save and exit `Info.plist` + +4. Press Command + B to force a new build before launching + +5. Don't push these changes :) + +### iPhone device + +The device doesn’t have direct access to your Mac’s localhost, so you can follow +[this guide to connect them](https://ymoondhra.medium.com/how-to-run-localhost-on-your-iphone-4110a54d1896). + +After you do that, you’ll have to also modify the `Info.plist` to allow http for testing purposes as +explained before on the simulator testing. + +It’s also highly likely that you need to change the `launchSettings.json` on Server, on `Properties` +of each project. There you need to change the `applicationUrl` of `iisSettings -> iisExpress` and of +`profiles -> Identify` so that instead of `localhost` it says `name.local` where `name` is the +computer name you set on Mac’s Sharing config. + +Before you actually test on the app, open a browser and try to connect to the `Api` by going to +`http://name.local:4000/alive` . If this doesn’t work then review the steps on the guide or the +server configuration. Make sure you have your `User secrets` up to date as well. + +Finally, you’ll have to configure the `Api` and `Identity` urls on the phone to use +`http://name.local:4000` and `http://name.local:33656` where `name` is the computer name you set on +Mac’s Sharing config. + +### iOS Extensions + +1. Set the iOS Extension project as Startup project + +2. Press Run + +3. You will receive a popup saying "Waiting for the debugger to connect..." + +4. Don’t open the Bitwarden app (otherwise the debugger will connect to it instead of the + extension). Instead trigger the extension + +5. Your extension breakpoints should now be hit + +For example: if you want to debug the **iOS.Autofill** extension, you would complete steps 1 - 3, +then go to your iOS device, open a browser, go to a login, tap the key icon and open Bitwarden from +the bottom popup. + +### Using Server Tunneling + +Instead of configuring your device or emulator to ignore SSL certificates, you can instead use a +[proxy tunnel to your local server](../../../server/tunnel.md) and have your app connect to it +directly. + +### Push Notifications (Live Sync & Passwordless) + +Push notifications are not currently available for debug deployments. They are only supported on +TestFlight and production builds. diff --git a/docs/getting-started/ios/new-project-options.png b/docs/getting-started/ios/new-project-options.png new file mode 100644 index 000000000..628ac25dc Binary files /dev/null and b/docs/getting-started/ios/new-project-options.png differ diff --git a/docs/getting-started/ios/run-debug.png b/docs/getting-started/ios/run-debug.png new file mode 100644 index 000000000..e86b8cb66 Binary files /dev/null and b/docs/getting-started/ios/run-debug.png differ diff --git a/docs/getting-started/ios/signing-and-capabilities.png b/docs/getting-started/ios/signing-and-capabilities.png new file mode 100644 index 000000000..db8fb4d7c Binary files /dev/null and b/docs/getting-started/ios/signing-and-capabilities.png differ diff --git a/docs/getting-started/ios/troubleshoot-generic-simulator.png b/docs/getting-started/ios/troubleshoot-generic-simulator.png new file mode 100644 index 000000000..50bd1bc44 Binary files /dev/null and b/docs/getting-started/ios/troubleshoot-generic-simulator.png differ diff --git a/docs/getting-started/watchos/index.mdx b/docs/getting-started/watchos/index.mdx new file mode 100644 index 000000000..a14e405b0 --- /dev/null +++ b/docs/getting-started/watchos/index.mdx @@ -0,0 +1,101 @@ +--- +sidebar_custom_props: + access: bitwarden +--- + +# watchOS + +:::warning Legacy + +Getting started the **legacy** watchOS app done in .NET MAUI. + +::: + +## Requirements + +Follow the [iOS Setup](../ios/index.mdx). + +In order for everything to work properly **devices** are needed. On simulators the synchronization +won't work (and some other parts may not work as well). Also, have Bluetooth enabled if possible to +ease the sync between devices and the debugging communication. + +It's recommended to read the +[Watch Architecture](../../../../../architecture/mobile-clients/net-maui-legacy/watchOS) as well. + +## macOS Setup + +Having followed the macOS setup of iOS, no additional configuration is needed given that when the +project is opened in Xcode it will automatically have the provisioning profiles set up. + +## Debugging + +There are two parts from where to debug: + +- From Visual Studio for Mac (the iOS app) +- From Xcode (the watchOS app) + +For now, there is no way to debug both apps (iOS and watchOS) at the same time given that from MAUI +there is no access to debug information of the watchOS app and from Xcode an iOS stub app is +installed on the iPhone to debug it. So, at the moment of debugging one needs to choose which part +to have information about, therefore whether to debug from VS4M or from Xcode. + +:::caution + +When debugging from Xcode the MAUI iOS app will be replaced with the stub one from Xcode. So any +configuration on the iOS app will be lost (like server urls) + +When debugging from VS4M, uninstall the previous watchOS app (if any) from the Apple Watch in +between builds to have it always up to date (there are times that if one doesn't uninstall the +previous watchOS app it doesn't get updated) + +::: + +:::tip + +If one needs to get the logs or use the _Console_ app to see the logs from the watch then one needs +to install the `sysdiagnose` profile for watchOS from Apple Developer site +[here](https://developer.apple.com/bug-reporting/profiles-and-logs/?name=sysdiagnose) into the +paired iPhone and after that restart both devices in order for the logs to work. + +::: + +### Building + +Given that the MAUI iOS app needs the output of the build of Xcode, one needs to build the watchOS +app from Xcode first and then from VS4M build the iOS app to run it on the device. + +The output of Xcode build is stored in a location pretty similar to the next one that is configured +in the `iOS.csproj`: + +```xml + + $(Home)/Library/Developer/Xcode/DerivedData/bitwarden-cbtqsueryycvflfzbsoteofskiyr/Build/Products +``` + +It's highly likely that the folder `bitwarden-cbtqsueryycvflfzbsoteofskiyr` won't be the same on +every Mac. So one needs to change that part in `iOS.csproj` to the one created automatically by +Xcode locally. + +To know exactly which is the path: Open the Project in Xcode -> Go to Product -> Show Build Folder +in Finder. + +_This needs to be improved to have a fixed location or an easier way to get it automatically._ + +:::caution + +One needs to take special attention to target the same platform on both IDEs. Therefore when running +on a device, target the device both in Xcode and on VS4M when building so that the watchOS app is +bundled correctly. Also one needs to make sure that "bitwarden WatchKit app" scheme is selected. + +::: + +### Synchronization + +There is no way to debug the synchronization completely at the same time for the reasons +aforementioned. + +So one can debug one end (iOS) or the other (watchOS). + +If needed to check something on both ends "at the same time" (like to check why a message is not +sent/arrived), one needs to use console logging or adapt part of the MAUI code to the iOS stub app +on Xcode and debug the synchronization from Xcode.