├── .nvmrc ├── static ├── .nojekyll └── img │ └── favicon.png ├── .husky └── pre-commit ├── docs ├── contributing │ ├── testing │ │ ├── _category_.yml │ │ └── unit │ │ │ ├── _category_.yml │ │ │ └── structure.mdx │ ├── database-migrations │ │ ├── _category_.yml │ │ ├── rename-column.gif │ │ ├── transitions.png │ │ ├── edd_state_machine.jpg │ │ ├── ef.md │ │ └── transitions.drawio │ ├── commit-signing.png │ ├── dependencies │ │ ├── image.png │ │ └── renovate-pr.png │ ├── pull-requests │ │ ├── ui-tests.png │ │ ├── publish-review.png │ │ ├── chromatic.md │ │ └── community-pr-process.md │ ├── vscode-preferences-settings-commit-signing.png │ ├── code-style │ │ ├── web │ │ │ ├── index.md │ │ │ ├── html.md │ │ │ └── tailwind.md │ │ └── index.md │ └── user-secrets.md ├── getting-started │ ├── server │ │ ├── _category_.yml │ │ ├── database │ │ │ ├── _category_.yml │ │ │ └── mssql │ │ │ │ └── index.md │ │ ├── secrets │ │ │ ├── _category_.yml │ │ │ ├── secrets.png │ │ │ └── index.md │ │ ├── self-hosted │ │ │ ├── _category_.yml │ │ │ ├── vs-code.png │ │ │ └── visual-studio.png │ │ ├── sso │ │ │ ├── _category_.yml │ │ │ └── devtools.png │ │ ├── troubleshooting.md │ │ ├── tunnel.md │ │ ├── public-api.md │ │ ├── scim.md │ │ └── portal.md │ ├── business │ │ ├── _category_.yml │ │ ├── directory-connector │ │ │ ├── index.mdx │ │ │ └── jumpcloud.md │ │ └── splunk-app.md │ ├── sdk │ │ ├── secrets-manager │ │ │ ├── integrations │ │ │ │ └── _category_.yml │ │ │ ├── enable-sm.png │ │ │ ├── sm-product-switcher.png │ │ │ └── index.mdx │ │ ├── index.md │ │ └── internal │ │ │ └── index.md │ ├── clients │ │ ├── browser │ │ │ ├── extension-id.png │ │ │ ├── custom-local-environment.png │ │ │ ├── disable-popup-auto-hide.png │ │ │ └── ff-private.md │ │ ├── desktop │ │ │ ├── minio-access-rule.png │ │ │ ├── minio-create-bucket.png │ │ │ ├── minio-manifest-rollout.png │ │ │ ├── native-messaging │ │ │ │ ├── connect.png │ │ │ │ ├── settings.png │ │ │ │ └── module-not-found.png │ │ │ ├── mac │ │ │ │ ├── app-specific-passwords.png │ │ │ │ ├── app-specific-passwords2.png │ │ │ │ └── index.md │ │ │ └── microsoft-store.md │ │ ├── troubleshooting.md │ │ ├── index.md │ │ ├── cli │ │ │ └── index.md │ │ └── web-vault │ │ │ └── webauthn.mdx │ └── mobile │ │ └── index.md ├── architecture │ ├── clients │ │ ├── services │ │ │ └── _category_.yml │ │ ├── presentation │ │ │ ├── _category_.yml │ │ │ ├── angular.md │ │ │ └── cli.md │ │ ├── data-model.md │ │ ├── index.md │ │ └── overview.md │ ├── security │ │ ├── principles │ │ │ ├── _category_.yml │ │ │ ├── 05-controlled-access.mdx │ │ │ ├── 06-minimized-impact-of-security-breaches.mdx │ │ │ ├── 04-no-security-on-fully-compromised.mdx │ │ │ ├── 03-limited-security-on-semi-compromised.mdx │ │ │ ├── 02-locked-vault-is-secure.mdx │ │ │ └── 01-servers-are-zero-knowledge.mdx │ │ └── index.mdx │ ├── mobile-clients │ │ └── _category_.yml │ ├── deep-dives │ │ ├── passkeys │ │ │ ├── implementations │ │ │ │ ├── relying-party │ │ │ │ │ ├── image.png │ │ │ │ │ └── index.md │ │ │ │ ├── index.md │ │ │ │ └── provider │ │ │ │ │ └── index.md │ │ │ ├── naming-convention.md │ │ │ └── glossary.md │ │ ├── index.md │ │ ├── push-notifications │ │ │ ├── index.md │ │ │ └── non-mobile.md │ │ ├── ssh │ │ │ └── index.md │ │ ├── database-replicas.md │ │ ├── autofill │ │ │ ├── form-submission-detection.md │ │ │ └── shadow-dom.md │ │ └── authentication │ │ │ └── two-factor-auth.md │ ├── cryptography │ │ └── index.md │ ├── sdk │ │ ├── internal │ │ │ └── web │ │ │ │ └── index.md │ │ ├── index.md │ │ ├── secrets-manager.md │ │ ├── versioning.md │ │ ├── data-models.md │ │ ├── dependencies.md │ │ └── server-bindings.md │ ├── index.md │ └── adr │ │ ├── 0009-angular-composition-over-inheritance.md │ │ ├── 0002-public-module-npm-packages.md │ │ ├── 0001-reactive-forms.md │ │ ├── 0013-deprecate-global-request-response-models.md │ │ ├── 0005-refactor-api-service.md │ │ ├── 0007-manifest-v3-browser-memory-caching.md │ │ ├── 0012-angular-filename-convention.md │ │ ├── 0004-refactor-state-service.md │ │ ├── 0006-clients-use-jest-mocks.md │ │ ├── 0029-angular-signals.md │ │ ├── 0017-watchOS-use-swift.md │ │ ├── 0011-angular-folder-structure.md │ │ ├── 0008-server-CQRS-pattern.md │ │ ├── 0003-observable-data-services.md │ │ └── 0010-angular-ngmodules.md └── index.mdx ├── .vscode └── settings.json ├── .prettierrc.json ├── .github ├── dropdown.png ├── labeler.yml ├── workflows │ ├── label.yml │ ├── review-code.yml │ ├── respond.yml │ ├── build.yml │ ├── lint.yml │ └── scan.yml ├── renovate.json ├── ISSUE_TEMPLATE │ ├── config.yml │ └── issue.yml ├── CODEOWNERS └── PULL_REQUEST_TEMPLATE.md ├── babel.config.js ├── .prettierignore ├── .env.example ├── tsconfig.json ├── scripts ├── docusaurus-start.sh └── generate-certs.sh ├── src ├── theme │ ├── NavbarItem │ │ └── ComponentTypes.tsx │ ├── MDXComponents.tsx │ ├── DocSidebarItem │ │ └── index.js │ └── Layout │ │ └── Provider │ │ └── index.tsx ├── components │ ├── Bitwarden.tsx │ ├── Community.tsx │ ├── DevDropdown │ │ └── index.tsx │ └── AdrTable.tsx ├── pages │ └── index.module.css ├── css │ └── custom.css └── contexts │ └── devMode.tsx ├── CONTRIBUTING ├── .gitignore ├── .editorconfig ├── sidebars.js ├── LICENSE.txt ├── .claude └── prompts │ └── review-code.md ├── cspell.yaml ├── custom-words.txt └── package.json /.nvmrc: -------------------------------------------------------------------------------- 1 | 22 2 | -------------------------------------------------------------------------------- /static/.nojekyll: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | npx lint-staged 2 | -------------------------------------------------------------------------------- /docs/contributing/testing/_category_.yml: -------------------------------------------------------------------------------- 1 | label: "Testing" 2 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cSpell.words": ["Bitwarden"] 3 | } 4 | -------------------------------------------------------------------------------- /docs/contributing/testing/unit/_category_.yml: -------------------------------------------------------------------------------- 1 | label: "Unit Tests" 2 | -------------------------------------------------------------------------------- /docs/getting-started/server/_category_.yml: -------------------------------------------------------------------------------- 1 | label: "Server" 2 | position: 2 3 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 100, 3 | "proseWrap": "always" 4 | } 5 | -------------------------------------------------------------------------------- /docs/architecture/clients/services/_category_.yml: -------------------------------------------------------------------------------- 1 | label: "Services" 2 | position: 4 3 | -------------------------------------------------------------------------------- /docs/getting-started/business/_category_.yml: -------------------------------------------------------------------------------- 1 | label: "Business apps" 2 | position: 6 3 | -------------------------------------------------------------------------------- /docs/architecture/security/principles/_category_.yml: -------------------------------------------------------------------------------- 1 | label: "Principles" 2 | position: 3 3 | -------------------------------------------------------------------------------- /docs/getting-started/server/database/_category_.yml: -------------------------------------------------------------------------------- 1 | label: "Databases" 2 | position: 3 3 | -------------------------------------------------------------------------------- /docs/getting-started/server/secrets/_category_.yml: -------------------------------------------------------------------------------- 1 | label: "User Secrets" 2 | position: 11 3 | -------------------------------------------------------------------------------- /docs/architecture/clients/presentation/_category_.yml: -------------------------------------------------------------------------------- 1 | label: "Presentation" 2 | position: 3 3 | -------------------------------------------------------------------------------- /docs/getting-started/server/self-hosted/_category_.yml: -------------------------------------------------------------------------------- 1 | label: "Self-Hosted" 2 | position: 7 3 | -------------------------------------------------------------------------------- /docs/getting-started/server/sso/_category_.yml: -------------------------------------------------------------------------------- 1 | label: "Single Sign-On (SSO)" 2 | position: 8 3 | -------------------------------------------------------------------------------- /.github/dropdown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitwarden/contributing-docs/HEAD/.github/dropdown.png -------------------------------------------------------------------------------- /docs/contributing/database-migrations/_category_.yml: -------------------------------------------------------------------------------- 1 | label: "Database Migrations" 2 | position: 2 3 | -------------------------------------------------------------------------------- /docs/architecture/mobile-clients/_category_.yml: -------------------------------------------------------------------------------- 1 | label: "Mobile Clients Architecture" 2 | position: 2 3 | -------------------------------------------------------------------------------- /static/img/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitwarden/contributing-docs/HEAD/static/img/favicon.png -------------------------------------------------------------------------------- /.github/labeler.yml: -------------------------------------------------------------------------------- 1 | adr: 2 | - changed-files: 3 | - any-glob-to-any-file: docs/architecture/adr/** 4 | -------------------------------------------------------------------------------- /docs/getting-started/sdk/secrets-manager/integrations/_category_.yml: -------------------------------------------------------------------------------- 1 | label: "Integrations" 2 | position: 1 3 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [require.resolve("@docusaurus/core/lib/babel/preset")], 3 | }; 4 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | .github/CODEOWNERS 2 | 3 | # Production 4 | /build 5 | 6 | # Generated files 7 | .docusaurus 8 | .cache-loader 9 | -------------------------------------------------------------------------------- /docs/contributing/commit-signing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitwarden/contributing-docs/HEAD/docs/contributing/commit-signing.png -------------------------------------------------------------------------------- /docs/contributing/dependencies/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitwarden/contributing-docs/HEAD/docs/contributing/dependencies/image.png -------------------------------------------------------------------------------- /docs/contributing/pull-requests/ui-tests.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitwarden/contributing-docs/HEAD/docs/contributing/pull-requests/ui-tests.png -------------------------------------------------------------------------------- /docs/getting-started/server/sso/devtools.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitwarden/contributing-docs/HEAD/docs/getting-started/server/sso/devtools.png -------------------------------------------------------------------------------- /docs/contributing/dependencies/renovate-pr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitwarden/contributing-docs/HEAD/docs/contributing/dependencies/renovate-pr.png -------------------------------------------------------------------------------- /docs/getting-started/server/secrets/secrets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitwarden/contributing-docs/HEAD/docs/getting-started/server/secrets/secrets.png -------------------------------------------------------------------------------- /docs/contributing/pull-requests/publish-review.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitwarden/contributing-docs/HEAD/docs/contributing/pull-requests/publish-review.png -------------------------------------------------------------------------------- /docs/getting-started/server/self-hosted/vs-code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitwarden/contributing-docs/HEAD/docs/getting-started/server/self-hosted/vs-code.png -------------------------------------------------------------------------------- /docs/contributing/database-migrations/rename-column.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitwarden/contributing-docs/HEAD/docs/contributing/database-migrations/rename-column.gif -------------------------------------------------------------------------------- /docs/contributing/database-migrations/transitions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitwarden/contributing-docs/HEAD/docs/contributing/database-migrations/transitions.png -------------------------------------------------------------------------------- /docs/getting-started/clients/browser/extension-id.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitwarden/contributing-docs/HEAD/docs/getting-started/clients/browser/extension-id.png -------------------------------------------------------------------------------- /docs/getting-started/sdk/secrets-manager/enable-sm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitwarden/contributing-docs/HEAD/docs/getting-started/sdk/secrets-manager/enable-sm.png -------------------------------------------------------------------------------- /docs/architecture/clients/presentation/angular.md: -------------------------------------------------------------------------------- 1 | # Angular 2 | 3 | See the [Angular Code Style Guide](../../../contributing/code-style/web/angular.md) for more 4 | details. 5 | -------------------------------------------------------------------------------- /docs/getting-started/server/self-hosted/visual-studio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitwarden/contributing-docs/HEAD/docs/getting-started/server/self-hosted/visual-studio.png -------------------------------------------------------------------------------- /docs/contributing/database-migrations/edd_state_machine.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitwarden/contributing-docs/HEAD/docs/contributing/database-migrations/edd_state_machine.jpg -------------------------------------------------------------------------------- /docs/getting-started/clients/desktop/minio-access-rule.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitwarden/contributing-docs/HEAD/docs/getting-started/clients/desktop/minio-access-rule.png -------------------------------------------------------------------------------- /docs/getting-started/clients/desktop/minio-create-bucket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitwarden/contributing-docs/HEAD/docs/getting-started/clients/desktop/minio-create-bucket.png -------------------------------------------------------------------------------- /docs/contributing/vscode-preferences-settings-commit-signing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitwarden/contributing-docs/HEAD/docs/contributing/vscode-preferences-settings-commit-signing.png -------------------------------------------------------------------------------- /docs/getting-started/clients/browser/custom-local-environment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitwarden/contributing-docs/HEAD/docs/getting-started/clients/browser/custom-local-environment.png -------------------------------------------------------------------------------- /docs/getting-started/clients/browser/disable-popup-auto-hide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitwarden/contributing-docs/HEAD/docs/getting-started/clients/browser/disable-popup-auto-hide.png -------------------------------------------------------------------------------- /docs/getting-started/clients/desktop/minio-manifest-rollout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitwarden/contributing-docs/HEAD/docs/getting-started/clients/desktop/minio-manifest-rollout.png -------------------------------------------------------------------------------- /docs/getting-started/clients/desktop/native-messaging/connect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitwarden/contributing-docs/HEAD/docs/getting-started/clients/desktop/native-messaging/connect.png -------------------------------------------------------------------------------- /docs/getting-started/sdk/secrets-manager/sm-product-switcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitwarden/contributing-docs/HEAD/docs/getting-started/sdk/secrets-manager/sm-product-switcher.png -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | HTTPS=true 2 | 3 | # Generate via ./scripts/generate-certs, or mkcert 4 | # (see: https://docusaurus.io/docs/cli#enabling-https) 5 | SSL_CRT_FILE=ssl.crt 6 | SSL_KEY_FILE=ssl.key 7 | -------------------------------------------------------------------------------- /docs/getting-started/clients/desktop/mac/app-specific-passwords.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitwarden/contributing-docs/HEAD/docs/getting-started/clients/desktop/mac/app-specific-passwords.png -------------------------------------------------------------------------------- /docs/getting-started/clients/desktop/native-messaging/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitwarden/contributing-docs/HEAD/docs/getting-started/clients/desktop/native-messaging/settings.png -------------------------------------------------------------------------------- /docs/getting-started/clients/desktop/mac/app-specific-passwords2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitwarden/contributing-docs/HEAD/docs/getting-started/clients/desktop/mac/app-specific-passwords2.png -------------------------------------------------------------------------------- /docs/getting-started/clients/desktop/native-messaging/module-not-found.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitwarden/contributing-docs/HEAD/docs/getting-started/clients/desktop/native-messaging/module-not-found.png -------------------------------------------------------------------------------- /docs/architecture/deep-dives/passkeys/implementations/relying-party/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitwarden/contributing-docs/HEAD/docs/architecture/deep-dives/passkeys/implementations/relying-party/image.png -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // This file is not used in compilation. It is here just for a nice editor experience. 3 | "extends": "@docusaurus/tsconfig", 4 | "compilerOptions": { 5 | "baseUrl": "." 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /docs/architecture/cryptography/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 7 3 | --- 4 | 5 | # Cryptography 6 | 7 | The cryptography section contains a high level guide for teams wanting to use cryptography to build 8 | their features. 9 | -------------------------------------------------------------------------------- /docs/contributing/code-style/web/index.md: -------------------------------------------------------------------------------- 1 | # Web 2 | 3 | This section covers code style specific to web technologies. While it's primarily aimed at the 4 | `clients` repository, subsets of these guidelines applies to other repositories as well. 5 | -------------------------------------------------------------------------------- /scripts/docusaurus-start.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ROOT_DIR=$(git rev-parse --show-toplevel) 4 | 5 | # shellcheck source=.env 6 | set -o allexport 7 | source $ROOT_DIR/.env 8 | set +o allexport 9 | 10 | npm run docusaurus start 11 | -------------------------------------------------------------------------------- /docs/architecture/deep-dives/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 7 3 | --- 4 | 5 | # Deep Dives 6 | 7 | Deep dives covers interesting segments of the Bitwarden products. And serves as a good reference 8 | point for understanding features more in-depth. 9 | -------------------------------------------------------------------------------- /src/theme/NavbarItem/ComponentTypes.tsx: -------------------------------------------------------------------------------- 1 | import ComponentTypes from "@theme-original/NavbarItem/ComponentTypes"; 2 | import DevDropdown from "@site/src/components/DevDropdown"; 3 | 4 | export default { 5 | ...ComponentTypes, 6 | "custom-dev": DevDropdown, 7 | }; 8 | -------------------------------------------------------------------------------- /docs/contributing/testing/unit/structure.mdx: -------------------------------------------------------------------------------- 1 | # Test Structure 2 | 3 | :::caution 4 | 5 | This section is still a work in progress. 6 | 7 | ::: 8 | 9 | A commonly used convention is AAA: Arrange Act Assert. This type of convention makes it much easier 10 | to read/understand tests while also promoting better testing. 11 | -------------------------------------------------------------------------------- /CONTRIBUTING: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | Our [Contributing Guidelines](https://contributing.bitwarden.com/contributing/) are located in our 4 | [Contributing Documentation](https://contributing.bitwarden.com/). The documentation also includes 5 | recommended tooling, code style tips, and lots of other great information to get you started. 6 | -------------------------------------------------------------------------------- /src/components/Bitwarden.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useDevMode } from "../contexts/devMode"; 3 | 4 | export default function Bitwarden({ children }): JSX.Element { 5 | const { devMode } = useDevMode(); 6 | 7 | if (devMode === "bitwarden") { 8 | return <>{children}; 9 | } 10 | 11 | return <>; 12 | } 13 | -------------------------------------------------------------------------------- /src/components/Community.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useDevMode } from "../contexts/devMode"; 3 | 4 | export default function Community({ children }): JSX.Element { 5 | const { devMode } = useDevMode(); 6 | 7 | if (devMode === "community") { 8 | return <>{children}; 9 | } 10 | 11 | return <>; 12 | } 13 | -------------------------------------------------------------------------------- /docs/getting-started/mobile/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 4 3 | --- 4 | 5 | # Mobile 6 | 7 | ## Android development 8 | 9 | See the [Android Mobile app](./android/index.md) page to set up a Kotlin development environment. 10 | 11 | ## iOS Development 12 | 13 | See the [iOS Mobile app](./ios/index.md) page to set up a Swift development environment. 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /node_modules 3 | 4 | # Production 5 | /build 6 | 7 | # Generated files 8 | .docusaurus 9 | .cache-loader 10 | 11 | # Misc 12 | .DS_Store 13 | *.crt 14 | *.key 15 | *.pem 16 | .env 17 | .env.local 18 | .env.development.local 19 | .env.test.local 20 | .env.production.local 21 | .idea/ 22 | 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: https://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | end_of_line = lf 9 | insert_final_newline = true 10 | trim_trailing_whitespace = true 11 | 12 | # Set default charset 13 | [*.{js,ts,scss,html,md}] 14 | charset = utf-8 15 | indent_style = space 16 | indent_size = 2 17 | 18 | [*.{ts}] 19 | quote_type = single 20 | -------------------------------------------------------------------------------- /.github/workflows/label.yml: -------------------------------------------------------------------------------- 1 | name: Label 2 | 3 | on: 4 | pull_request: 5 | 6 | jobs: 7 | label: 8 | name: Label 9 | runs-on: ubuntu-22.04 10 | permissions: 11 | contents: read 12 | pull-requests: write 13 | 14 | steps: 15 | - name: Label pull request 16 | uses: actions/labeler@634933edcd8ababfe52f92936142cc22ac488b1b # v6.0.1 17 | with: 18 | sync-labels: true # Remove labels if matches are removed 19 | -------------------------------------------------------------------------------- /src/theme/MDXComponents.tsx: -------------------------------------------------------------------------------- 1 | import MDXComponents from "@theme-original/MDXComponents"; 2 | import Bitwarden from "@site/src/components/Bitwarden"; 3 | import Community from "@site/src/components/Community"; 4 | import AdrTable from "../components/AdrTable"; 5 | 6 | export default { 7 | // Re-use the default mapping 8 | ...MDXComponents, 9 | 10 | // Custom mapping 11 | Bitwarden: Bitwarden, 12 | Community: Community, 13 | AdrTable: AdrTable, 14 | }; 15 | -------------------------------------------------------------------------------- /docs/architecture/sdk/internal/web/index.md: -------------------------------------------------------------------------------- 1 | # Web 2 | 3 | The Password Manager SDK supports web-based clients, allowing developers to integrate core password 4 | management functionality into JavaScript/TypeScript environments. The SDK is packaged as an NPM 5 | module under `@bitwarden/sdk-internal` and uses WebAssembly (`wasm`) to enable interaction with Rust 6 | code. This section will provide guidance and best practices for working with the SDK in a browser 7 | environment. 8 | -------------------------------------------------------------------------------- /docs/architecture/deep-dives/passkeys/implementations/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 5 3 | --- 4 | 5 | # Implementations 6 | 7 | Bitwarden uses passkeys to provide users with a secure and convenient alternative to passwords. In 8 | this context Bitwarden can act as both a Relying Party (RP) and a Passkey Provider (PP). In other 9 | words: You can use passkeys to log in to Bitwarden, and you can use Bitwarden to generate and store 10 | passkeys for logging into other applications. 11 | -------------------------------------------------------------------------------- /src/pages/index.module.css: -------------------------------------------------------------------------------- 1 | /** 2 | * CSS files with the .module.css suffix will be treated as CSS modules 3 | * and scoped locally. 4 | */ 5 | 6 | .heroBanner { 7 | padding: 4rem 0; 8 | text-align: center; 9 | position: relative; 10 | overflow: hidden; 11 | } 12 | 13 | @media screen and (max-width: 996px) { 14 | .heroBanner { 15 | padding: 2rem; 16 | } 17 | } 18 | 19 | .buttons { 20 | display: flex; 21 | align-items: center; 22 | justify-content: center; 23 | } 24 | -------------------------------------------------------------------------------- /src/theme/DocSidebarItem/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import DocSidebarItem from "@theme-original/DocSidebarItem"; 3 | 4 | import { useDevMode } from "@site/src/contexts/devMode"; 5 | 6 | export default function DocSidebarItemWrapper(props) { 7 | const { devMode } = useDevMode(); 8 | 9 | if (props.item?.customProps?.access && props.item.customProps.access != devMode) { 10 | return null; 11 | } 12 | 13 | return ( 14 | <> 15 | 16 | 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /docs/getting-started/sdk/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 5 3 | --- 4 | 5 | # SDK 6 | 7 | Bitwarden provides a public Software Development Kit (SDK) for [Secrets Manager][sm] and an internal 8 | SDK for the Bitwarden [Password Manager][pm]. The SDKs are written in Rust and provides bindings for 9 | multiple languages. 10 | 11 | - [Internal SDK](./internal) 12 | - [Secrets Manager SDK](./secrets-manager) 13 | 14 | [npm-link]: https://docs.npmjs.com/cli/v9/commands/npm-link 15 | [sm]: https://bitwarden.com/products/secrets-manager/ 16 | [pm]: https://bitwarden.com/ 17 | -------------------------------------------------------------------------------- /docs/architecture/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | --- 4 | 5 | # Architecture 6 | 7 | In this section we will cover the high level architecture of Bitwarden, how it is structured, 8 | focusing initially on how the server and clients interact with each other, before diving into the 9 | details of the server and clients. 10 | 11 | Since the web-based clients mostly behave the same, we will focus on the web vault while calling out 12 | client-specific areas for the browser extension, desktop application and CLI. The mobile 13 | applications have their own codebases. 14 | -------------------------------------------------------------------------------- /docs/architecture/security/principles/05-controlled-access.mdx: -------------------------------------------------------------------------------- 1 | # P05 - Controlled access to vault data 2 | 3 | Clients must ensure that vault data, whether at rest or in use, is accessible only to authorized 4 | parties and always under the user's explicit control. Even when unlocked, access to vault data must 5 | be carefully restricted to specific contexts, such as autofill or explicit user actions. Isolation 6 | mechanisms must be employed, particularly in environments prone to unauthorized access—such as 7 | browsers—to prevent exposure to third parties without the user's consent. 8 | -------------------------------------------------------------------------------- /docs/architecture/deep-dives/passkeys/implementations/provider/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Provider 3 | sidebar_position: 1 4 | --- 5 | 6 | # Overview 7 | 8 | Bitwarden can act as a Passkey Provider to generate and store passkeys for other applications. 9 | 10 | ## Storage 11 | 12 | Passkeys are stored alongside and in the same way as passwords, using the same encryption and 13 | security. This includes both the private key and all related metadata. This data can be stored in 14 | both personal and organization vaults. 15 | 16 | Bitwarden only supports the client-side storage modality. 17 | -------------------------------------------------------------------------------- /.github/renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": ["github>bitwarden/renovate-config"], 4 | "enabledManagers": ["github-actions", "npm", "nvm"], 5 | "packageRules": [ 6 | { 7 | "groupName": "gh minor", 8 | "matchManagers": ["github-actions"], 9 | "matchUpdateTypes": ["minor", "patch"] 10 | }, 11 | { 12 | "matchFileNames": ["package.json"], 13 | "description": "Autofill owns general dependencies in contributing docs", 14 | "reviewers": ["team:team-autofill-dev"] 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /src/theme/Layout/Provider/index.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { composeProviders } from "@docusaurus/theme-common"; 3 | import ThemeLayoutProvider from "@theme-original/Layout/Provider"; 4 | 5 | import type { Props } from "@theme/Layout/Provider"; 6 | import { DevModeProvider } from "@site/src/contexts/devMode"; 7 | 8 | const Provider = composeProviders([DevModeProvider]); 9 | 10 | export default function LayoutProvider({ children }: Props): JSX.Element { 11 | return ( 12 | 13 | {children} 14 | 15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /.github/workflows/review-code.yml: -------------------------------------------------------------------------------- 1 | name: Code Review 2 | 3 | on: 4 | pull_request: 5 | types: [opened, synchronize, reopened, ready_for_review] 6 | 7 | permissions: {} 8 | 9 | jobs: 10 | review: 11 | name: Review 12 | uses: bitwarden/gh-actions/.github/workflows/_review-code.yml@main 13 | secrets: 14 | AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} 15 | AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} 16 | AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} 17 | permissions: 18 | actions: read 19 | contents: read 20 | id-token: write 21 | pull-requests: write 22 | -------------------------------------------------------------------------------- /docs/contributing/code-style/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | --- 4 | 5 | # Code Style 6 | 7 | This section contains general Code Style guidelines for the Bitwarden codebase. It is recommended to 8 | read this section thoroughly as it contains many good advices for avoiding common pitfalls. 9 | 10 | ## General 11 | 12 | ### Lists 13 | 14 | - Include trailing commas for multi-line lists when supported by the language. Inline lists do not 15 | have to follow this standard. 16 | 17 | ### Code Regions 18 | 19 | - We do not use code regions in the codebase. If you find yourself needing to use a code region, 20 | consider refactoring the code to be more readable. 21 | -------------------------------------------------------------------------------- /sidebars.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Creating a sidebar enables you to: 3 | - create an ordered group of docs 4 | - render a sidebar for each doc of that group 5 | - provide next/previous navigation 6 | 7 | The sidebars can be generated from the filesystem, or explicitly defined here. 8 | 9 | Create as many sidebars as you want. 10 | */ 11 | 12 | // @ts-check 13 | 14 | /** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ 15 | const sidebars = { 16 | getting_started: ["index", { type: "autogenerated", dirName: "getting-started" }], 17 | contributing: [{ type: "autogenerated", dirName: "contributing" }], 18 | architecture: [{ type: "autogenerated", dirName: "architecture" }], 19 | }; 20 | 21 | module.exports = sidebars; 22 | -------------------------------------------------------------------------------- /docs/architecture/security/principles/06-minimized-impact-of-security-breaches.mdx: -------------------------------------------------------------------------------- 1 | # P06 - Minimized impact of security breaches 2 | 3 | Even with robust security measures in place, user error or unforeseen vulnerabilities can lead to 4 | various security breaches, including the compromise of encryption keys or data leaks. Bitwarden 5 | should take available actions to help users limit the damage caused by such breaches, both in scope 6 | and duration. This includes: 7 | 8 | - Detecting and invalidating compromised device sessions. 9 | - Rotating encryption keys to reduce the risk of “harvest now, decrypt later” attacks (forward 10 | secrecy). 11 | - Ensuring that any data added after a breach remains secure, maintaining post-compromise security. 12 | -------------------------------------------------------------------------------- /.github/workflows/respond.yml: -------------------------------------------------------------------------------- 1 | name: Respond 2 | 3 | on: 4 | issue_comment: 5 | types: [created] 6 | pull_request_review_comment: 7 | types: [created] 8 | issues: 9 | types: [opened, assigned] 10 | pull_request_review: 11 | types: [submitted] 12 | 13 | permissions: {} 14 | 15 | jobs: 16 | respond: 17 | name: Respond 18 | uses: bitwarden/gh-actions/.github/workflows/_respond.yml@main 19 | secrets: 20 | AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} 21 | AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} 22 | AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} 23 | permissions: 24 | actions: read 25 | contents: write 26 | id-token: write 27 | issues: write 28 | pull-requests: write 29 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Source code in this repository is covered by one of two licenses: (i) the GNU General Public License 2 | (GPL) v3.0 (ii) the Creative Commons BY-NC-ND v4.0. Creative Commons licensed documents are found in 3 | the docs directory. Other files are GPL licensed. 4 | 5 | GPL v3.0: https://github.com/bitwarden/contributing-docs/blob/main/LICENSE_GPL.txt 6 | 7 | CC BY-NC-ND v4.0: https://github.com/bitwarden/contributing-docs/blob/main/LICENSE_CC.txt 8 | 9 | No grant of any rights in the trademarks, service marks, or logos of Bitwarden is made (except as 10 | may be necessary to comply with the notice requirements as applicable), and use of any Bitwarden 11 | trademarks must comply with Bitwarden Trademark Guidelines 12 | . 13 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | push: 5 | paths-ignore: 6 | - ".github/workflows/**" 7 | workflow_dispatch: 8 | 9 | permissions: 10 | contents: read 11 | 12 | jobs: 13 | lint: 14 | name: Build 15 | runs-on: ubuntu-22.04 16 | 17 | steps: 18 | - name: Check out repo 19 | uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 20 | with: 21 | persist-credentials: false 22 | 23 | - name: Set up Node 24 | uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 25 | with: 26 | cache: "npm" 27 | cache-dependency-path: "**/package-lock.json" 28 | node-version-file: ".nvmrc" 29 | 30 | - name: Build 31 | run: | 32 | npm ci 33 | npm run build 34 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Feature Requests 4 | url: https://community.bitwarden.com/c/feature-requests/ 5 | about: 6 | Request new features using the Community Forums. Please search existing feature requests 7 | before making a new one. 8 | - name: Bitwarden Community Forums 9 | url: https://community.bitwarden.com 10 | about: 11 | Please visit the community forums for general community discussion, support and the 12 | development roadmap. 13 | - name: Customer Support 14 | url: https://bitwarden.com/contact/ 15 | about: Please contact our customer support for account issues and general customer support. 16 | - name: Security Issues 17 | url: https://hackerone.com/bitwarden 18 | about: We use HackerOne to manage security disclosures. 19 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: Lint 2 | 3 | on: 4 | push: 5 | paths-ignore: 6 | - ".github/workflows/**" 7 | workflow_dispatch: 8 | 9 | permissions: 10 | contents: read 11 | 12 | jobs: 13 | lint: 14 | name: Lint 15 | runs-on: ubuntu-22.04 16 | 17 | steps: 18 | - name: Check out repo 19 | uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 20 | with: 21 | persist-credentials: false 22 | 23 | - name: Set up Node 24 | uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 25 | with: 26 | cache: "npm" 27 | cache-dependency-path: "**/package-lock.json" 28 | node-version-file: ".nvmrc" 29 | 30 | - name: Lint and spellcheck 31 | run: | 32 | npm ci 33 | npm run lint 34 | npm run spellcheck 35 | -------------------------------------------------------------------------------- /docs/getting-started/clients/troubleshooting.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 8 3 | --- 4 | 5 | # Troubleshooting 6 | 7 | ## Build errors / npm dependency errors 8 | 9 | If you're receiving npm dependency errors when you try to build a client app, make sure that you've 10 | run `npm ci` in the root directory of the repository only. You should never run `npm i` or `npm ci` 11 | in any other directory (such as in a client app directory). 12 | 13 | You can double check this by searching for `node_modules` in the `libs` and `apps` directories: 14 | 15 | ```bash 16 | find apps -name node_modules 17 | find libs -name node_modules 18 | ``` 19 | 20 | Delete any results of these searches and try building the app again. 21 | 22 | If you're still encountering build errors, you can try deleting the `node_modules` folder in the 23 | root of you repository, re-running `npm ci`, and then building the app again. 24 | -------------------------------------------------------------------------------- /docs/architecture/sdk/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 3 3 | --- 4 | 5 | # SDK Architecture 6 | 7 | Bitwarden provides a public Software Development Kit (SDK) for [Secrets Manager][sm] and an internal 8 | SDK for the Bitwarden [Password Manager][pm]. The SDK is written in Rust and provides bindings for 9 | multiple languages. The general end goal of the SDK is to own everything up to the presentational 10 | layers. This includes but is not limited to: API calls, data models, encryption, and business logic. 11 | 12 | We have compiled a list of resources for learning Rust in a 13 | [Confluence page](https://bitwarden.atlassian.net/wiki/spaces/DEV/pages/517898288/Rust+Learning+Resources). 14 | For API documentation view the latest 15 | [API documentation](https://sdk-api-docs.bitwarden.com/bitwarden/index.html) that also includes 16 | internal private items. 17 | 18 | [sm]: https://bitwarden.com/products/secrets-manager/ 19 | [pm]: https://bitwarden.com/ 20 | -------------------------------------------------------------------------------- /docs/architecture/security/principles/04-no-security-on-fully-compromised.mdx: -------------------------------------------------------------------------------- 1 | # P04 - No security on fully compromised systems 2 | 3 | :::info Note 4 | 5 | This principle applies only to unlocked vaults. Refer to [P01](./locked-vault-is-secure) for details 6 | on protections for locked vaults. 7 | 8 | ::: 9 | 10 | :::info Note 11 | 12 | Bitwarden does not currently support Trusted Execution Environments (TEEs). While TEEs could 13 | potentially provide a secure processing space for vault data on compromised devices, their use is 14 | limited by the environments in which Bitwarden operates. For this reason, TEEs are not considered 15 | when defining what constitutes a fully compromised device. 16 | 17 | ::: 18 | 19 | When hardware or OS-level integrity is fully compromised, vault data may become accessible to 20 | attackers. While Bitwarden continuously strives to provide robust protections, certain threats fall 21 | beyond the reach of software-based security measures. 22 | -------------------------------------------------------------------------------- /.claude/prompts/review-code.md: -------------------------------------------------------------------------------- 1 | Please review this pull request with a focus on documentation content, clarity, and overall quality. 2 | 3 | Ensure that the documentation is accurate, well-structured, and easy to understand. 4 | 5 | Check for grammar, spelling, and formatting problems. 6 | 7 | Verify that any code examples are correct and follow best practices. 8 | 9 | Assess whether the documentation meets the needs of its intended audience. 10 | 11 | Suggest improvements where necessary and provide detailed feedback using inline comments for 12 | specific feedback. 13 | 14 | When reviewing subsequent commits: 15 | 16 | - Track status of previously identified findings (fixed/unfixed/reopened) 17 | - Identify NEW problems introduced since last review 18 | - Note if changes introduced any new findings 19 | 20 | IMPORTANT: Be comprehensive about findings and improvements. For good practices, be brief - just 21 | note what was done well without explaining why or praising excessively. 22 | -------------------------------------------------------------------------------- /docs/architecture/security/principles/03-limited-security-on-semi-compromised.mdx: -------------------------------------------------------------------------------- 1 | # P03 - Limited security for vaults on semi-compromised devices 2 | 3 | :::info Note 4 | 5 | This principle applies only to unlocked vaults. Refer to [P01](./locked-vault-is-secure) for details 6 | on protections for locked vaults. 7 | 8 | ::: 9 | 10 | A semi-compromised device is one where malware exists in User Space but has not breached Kernel or 11 | OS-level protections. On such devices, clients must leverage available protections to prevent 12 | malware from accessing plaintext vault data while the vault is unlocked. 13 | 14 | - **Technical controls** (e.g., data compartmentalization or HSMs): Clients should maximize the use 15 | of Kernel/OS-level protections or other available system mechanisms to safeguard vault data. 16 | - **Administrative controls** (e.g., biometrics, 2FA, approval flows): Clients should balance 17 | security and usability, avoiding excessive complexity in the user flow. 18 | -------------------------------------------------------------------------------- /docs/getting-started/server/database/mssql/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | --- 4 | 5 | # MSSQL 6 | 7 | Bitwarden primarily stores data in MSSQL (Microsoft SQL Server). The data access layer in the Server 8 | is written using [Dapper](https://github.com/DapperLib/Dapper) which is a lightweight object mapper 9 | for .NET. 10 | 11 | ## Creating the database 12 | 13 | See [Server Setup Guide](../../guide.md). 14 | 15 | ## Updating the database 16 | 17 | The `dev/migrate.ps1` helper script uses our 18 | [MsSql Migrator Utility](https://github.com/bitwarden/server/tree/main/util/MsSqlMigratorUtility) to 19 | run migrations. You should run the helper script whenever you sync with the `main` branch or create 20 | a new migration script. Migrations that have already been run are tracked in the `Migration` table 21 | of your database. 22 | 23 | ## Modifying the database 24 | 25 | The process for modifying the database is described in 26 | [Migrations](./../../../../contributing/database-migrations/mssql.md). 27 | -------------------------------------------------------------------------------- /docs/architecture/sdk/secrets-manager.md: -------------------------------------------------------------------------------- 1 | # Secrets Manager 2 | 3 | The Secrets Manager SDK is designed for external use. The SDK is written in Rust and provides 4 | bindings for multiple languages. 5 | 6 | ## `bitwarden` crate 7 | 8 | The `bitwarden` crate represents the entry point for consumers of the SDK and is responsible for 9 | providing a cohesive interface. The crate re-exports functionality of the internal crates and 10 | contains very little logic itself. 11 | 12 | ## Bindings 13 | 14 | The Secrets Manager SDK provides bindings for multiple languages. Currently we utilize a mix of hand 15 | written bindings for a C API, and generated bindings. 16 | 17 | Many language bindings utilize the `bitwarden-c` crate that exposes a C API. This is then combined 18 | with hand written bindings for the specific language. Since manually writing FFI bindings is time 19 | consuming and difficult, a JSON-based API is provided by the `bitwarden-json` crate. This allows the 20 | language bindings to simply contain three FFI functions, `init`, `run_command` and `free_memory`. 21 | -------------------------------------------------------------------------------- /src/components/DevDropdown/index.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import DropdownNavbarItem from "@theme-original/NavbarItem/DropdownNavbarItem"; 3 | import { useDevMode, DevModes } from "@site/src/contexts/devMode"; 4 | 5 | const dropdownOptions = [ 6 | { 7 | id: DevModes.community, 8 | label: "Community Developer", 9 | }, 10 | { 11 | id: DevModes.bitwarden, 12 | label: "Bitwarden Developer", 13 | }, 14 | ]; 15 | 16 | export default function DevDropdown({ 17 | mobile, 18 | dropdownItemsBefore, 19 | dropdownItemsAfter, 20 | ...props 21 | }): JSX.Element { 22 | const { devMode, setDevMode } = useDevMode(); 23 | 24 | const items = dropdownOptions.map((item) => { 25 | return { 26 | label: item.label, 27 | to: "#", 28 | onClick: (e) => { 29 | setDevMode(item.id); 30 | e.preventDefault(); 31 | }, 32 | }; 33 | }); 34 | 35 | const dropdownLabel = dropdownOptions.find((i) => i.id == devMode).label; 36 | 37 | return ; 38 | } 39 | -------------------------------------------------------------------------------- /src/components/AdrTable.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const formatDate = (date: Date) => { 4 | try { 5 | return date.toISOString().split("T")[0]; 6 | } catch {} 7 | }; 8 | 9 | const badgeColors = { 10 | Proposed: "primary", 11 | Accepted: "success", 12 | Rejected: "danger", 13 | Deprecated: "warning", 14 | Superseded: "warning", 15 | }; 16 | 17 | export default function AdrTable({ frontMatter }): JSX.Element { 18 | return ( 19 | 20 | 21 | 22 | 23 | 24 | 25 | {frontMatter.status && ( 26 | 27 | 28 | 33 | 34 | )} 35 | 36 | 37 | 38 | 39 | 40 |
ID:ADR-{frontMatter.adr}
Status: 29 | 30 | {frontMatter.status?.toUpperCase()} 31 | 32 |
Published:{formatDate(frontMatter.date)}
41 | ); 42 | } 43 | -------------------------------------------------------------------------------- /docs/architecture/sdk/versioning.md: -------------------------------------------------------------------------------- 1 | # Versioning and breaking changes 2 | 3 | The SDK strives towards maintaining backward compatibility for a reasonable time. This ensures that 4 | client applications can safely upgrade to newer versions of the SDK without resolving a large number 5 | of breaking changes. For a more in-depth explanation of what constitutes a breaking change in rust, 6 | see the [SemVer Compatibility section](https://doc.rust-lang.org/cargo/reference/semver.html) in 7 | [the Cargo book](https://doc.rust-lang.org/cargo/index.html). 8 | 9 | There may be certain functionality that is actively being developed and is not yet stable. In these 10 | cases, they should be marked as such and gated behind a `unstable` feature flag. Consuming client 11 | applications should avoid merging changes that depend on these features into `main`. 12 | 13 | ## Public APIs 14 | 15 | To track breaking changes to the public APIs for Secrets Manager, we use a [changelog file in the 16 | `bitwarden` crate][changelog]. This file should be updated with noteworthy changes. 17 | 18 | [changelog]: https://github.com/bitwarden/sdk-sm/blob/main/crates/bitwarden/CHANGELOG.md 19 | -------------------------------------------------------------------------------- /docs/architecture/deep-dives/push-notifications/index.md: -------------------------------------------------------------------------------- 1 | # Push Notifications 2 | 3 | Bitwarden uses push notifications to communicate in real-time from the Bitwarden server to its 4 | clients. 5 | 6 | ## Uses at Bitwarden 7 | 8 | Currently, this functionality is used for: 9 | 10 | - Syncing the vault between clients 11 | - Passwordless login requests 12 | 13 | ## Technology in Use 14 | 15 | The Bitwarden server initiates push notifications when relevant actions are performed, typically 16 | either when a user's data has changed and it needs to be synced, or an action requiring user input 17 | is performed. 18 | 19 | There are currently two different methods being used for push notifications: 20 | 21 | - The mobile applications use Azure Notification Hub, which is an abstraction of the Push 22 | Notification Services (PNSs) for the Apple and Android ecosystems. Self-hosted instances relay 23 | their mobile messages through the Bitwarden cloud-hosted service. 24 | - The other clients use SignalR, which is a two-way RPC usually over WebSockets (but has fallbacks 25 | to other protocols) to establish real-time client communications with our non-mobile clients. 26 | -------------------------------------------------------------------------------- /docs/architecture/clients/presentation/cli.md: -------------------------------------------------------------------------------- 1 | # CLI 2 | 3 | The CLI has a slightly different architecture than the other clients, which matches it's nature. CLI 4 | sessions are short lived and only execute a single task and then exit. This means that the CLI 5 | doesn't need to keep track of the memory state in the same way as the other clients. 6 | 7 | ## Commands 8 | 9 | Since the CLI is a command line interface, everything is structured around commands. Each command 10 | execute a specific task. Similar to _Angular Components_, _Commands_ aims to be as lightweight as 11 | possible with most business logic being handled by services. This allows for code sharing between 12 | different commands, but also with the Angular presentation layer. 13 | 14 | A basic command essentially only implements a single method, `run`. The Command classes are 15 | instantiated by the `Program` class. 16 | 17 | ```ts 18 | export class ConfigCommand { 19 | // Dependencies are manually wired up in the Program class. 20 | constructor(private environmentService: EnvironmentService) {} 21 | 22 | async run(setting: string, value: string, options: program.OptionValues): Promise { 23 | // Set configuration 24 | } 25 | } 26 | ``` 27 | -------------------------------------------------------------------------------- /cspell.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | dictionaries: 3 | - custom-words 4 | dictionaryDefinitions: 5 | - name: custom-words 6 | path: ./custom-words.txt 7 | addWords: true 8 | patterns: 9 | # Ignore multi-line code blocks 10 | # Ref: https://cspell.org/configuration/patterns/ 11 | # Modified to avoid matching line breaks before/after which had unexpected results 12 | - name: markdown_code_block 13 | pattern: | 14 | / 15 | ^[ \t]* # match optional whitespace before the ``` 16 | (`{3}).* # match the ``` and any optional language specification afterwards 17 | [\s\S]*? # the block of code 18 | ^[ \t]* # match optional whitespace before the ``` 19 | \1 # end of the block 20 | /gmx 21 | 22 | # Ignore inline code blocks 23 | - name: markdown_code_inline 24 | pattern: | 25 | / 26 | ` # match the opening ` 27 | .*? # match any characters, lazily (so that we stop at the next tilde) 28 | ` # match the closing ` 29 | /gx 30 | languageSettings: 31 | - languageId: 32 | - markdown 33 | - mdx 34 | ignoreRegExpList: 35 | - markdown_code_block 36 | - markdown_code_inline 37 | -------------------------------------------------------------------------------- /docs/contributing/database-migrations/ef.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 2 3 | --- 4 | 5 | # Entity Framework 6 | 7 | :::info 8 | 9 | For instructions on how to apply database migrations, please refer to the 10 | [Getting Started](../../getting-started/server/database/ef/index.mdx#updating-the-database) 11 | documentation. 12 | 13 | ::: 14 | 15 | If you alter the database schema, you must create an EF migration script to ensure that EF databases 16 | keep pace with these changes. Developers must do this and include the migrations with their PR. 17 | 18 | To create these scripts, you must first update your data model in `Core/Entities` as desired. This 19 | will be used to generate the migrations for each of our EF targets. Additionally, for table changes 20 | it is strongly recommended to define or update an `IEntityTypeConfiguration` to accurately 21 | represent any constraints needed on the data model. 22 | 23 | Once the model is updated, navigate to the `dev` directory in the `server` repo and execute the 24 | `ef_migrate.ps1` PowerShell command. You should provide a name for the migration as the only 25 | parameter: 26 | 27 | ```bash 28 | pwsh ef_migrate.ps1 [NAME_OF_MIGRATION] 29 | ``` 30 | 31 | This will generate the migrations, which should then be included in your PR. 32 | -------------------------------------------------------------------------------- /docs/getting-started/clients/desktop/microsoft-store.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_custom_props: 3 | access: bitwarden 4 | --- 5 | 6 | # Microsoft Store 7 | 8 | To debug the Microsoft Store application you need to generate a Code Signing certificate which can 9 | be done using the following powershell command: 10 | 11 | ```powershell 12 | New-SelfSignedCertificate -Type Custom ` 13 | -Subject "CN=ElectronSign, 0=Your Corporation, C=US" ` 14 | -TextExtension @("2.5.29.19={text}false") ` 15 | -KeyUsage DigitalSignature ` 16 | -TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.3", "2.5.29.19={text}") ` 17 | -FriendlyName ElectronSign ` 18 | -CertStoreLocation "Cert:\CurrentUser\My" 19 | ``` 20 | 21 | The generated certificate needs to be copied into to `Cert:\CurrentUser\Trusted People`, which tells 22 | the OS to trust the certificate. This is easiest done using the `certmgr` tool. 23 | 24 | The [Windows SDK][sdk] is required in order to access the signtool. 25 | 26 | ```powershell 27 | npm run dist:win 28 | 29 | cd dist 30 | "C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0\x64\signtool.exe" sign /v /fd sha256 /n "14D52771-DE3C-4886-B8BF-825BA7690418" .\Bitwarden-2022..appx 31 | ``` 32 | 33 | [sdk]: https://developer.microsoft.com/en-us/windows/downloads/windows-sdk/ 34 | -------------------------------------------------------------------------------- /docs/getting-started/clients/browser/ff-private.md: -------------------------------------------------------------------------------- 1 | # Firefox Private Mode 2 | 3 | You cannot run add-ons in Firefox Private Mode using the normal side-loading technique. This is 4 | because only they appear in the `about:debugging` page, which doesn’t give you the option to enable 5 | the extension in Private Mode. 6 | 7 | As an alternative, you can install the development build as an unsigned add-on using the steps 8 | below. 9 | 10 | ## Prerequisites 11 | 12 | 1. Install Firefox Developer Edition 13 | 2. Configure Firefox Developer Edition: 14 | 1. Open Firefox Developer Edition 15 | 2. Navigate to `about:config` 16 | 3. Set the `xpinstall.signatures.required` setting to `false` (add the setting if it’s not in 17 | the list already) 18 | 19 | ## Steps 20 | 21 | 1. Open your local browser repository on the command line 22 | 2. Build and package the browser extension with `npm run dist:firefox` 23 | 3. Open Firefox Developer Edition and navigate to `about:addons` 24 | 4. Click the cog in the top-right next to “Manage Your Extensions” 25 | 5. Click “Install Add-on From File” 26 | 6. Open `dist/dist-firefox.zip` in your local repository 27 | 7. The extension will now be the `about:addons` page. Click on the name of the extension to expand 28 | it, and then toggle “Run in Private Windows”. 29 | -------------------------------------------------------------------------------- /docs/architecture/adr/0009-angular-composition-over-inheritance.md: -------------------------------------------------------------------------------- 1 | --- 2 | adr: "0009" 3 | status: Accepted 4 | date: 2022-07-25 5 | tags: [clients, angular] 6 | --- 7 | 8 | # 0009 - Composition over inheritance 9 | 10 | 11 | 12 | ## Context and problem statement 13 | 14 | We currently rely heavily on inheritance for our Angular applications. While this seemed like a 15 | natural decision at the time since it allowed us to quickly share code between different areas. It 16 | has also lead to tight coupling and therefore difficulty in understanding the impact a change will 17 | have. It also encourages large page-level components. 18 | 19 | ## Considered options 20 | 21 | - **Do nothing** - Maintain the status quo, not really an option. 22 | - **Prefer composition over inheritance** - Split up components into small components that do one 23 | thing and one thing only. Keep components thin, and share functionality primarily using 24 | _Services_. 25 | 26 | ## Decision outcome 27 | 28 | Chosen option: **Prefer composition over inheritance** 29 | 30 | ### Positive consequences 31 | 32 | - Thinner components 33 | - Better understanding of the impact a change has since it will now be isolated to a single 34 | component only. 35 | 36 | ### Negative consequences 37 | 38 | - Inheritance tends to be well understood. 39 | -------------------------------------------------------------------------------- /docs/contributing/code-style/web/html.md: -------------------------------------------------------------------------------- 1 | # HTML 2 | 3 | Please ensure each input field and button has a descriptive ID. This will allow QA to more 4 | efficiently write test automation. 5 | 6 | The IDs should have the three following _components_: 7 | 8 | - **Component Name**: To ensure IDs stay unique we prefix them with the component name. While this 9 | may change it rarely does and since we avoid re-using the same component name multiple times this 10 | should be unique. 11 | - **HTML Element**: This allows you at a quick glance understand what we're accessing. 12 | - **Readable name**: Descriptive name of what we're accessing. 13 | 14 | Please use dashes within components, and separate the _components_ using underscore. 15 | 16 | ``` 17 | __ 18 | 19 | register_button_submit 20 | register-form_input_email 21 | ``` 22 | 23 | When writing components for the component library it's sometimes necessary to ensure an ID exists in 24 | order to properly handle accessibility with references to other elements. Consider using an auto 25 | generated ID but ensure it can be overridden. Use the following naming convention for automatic IDs: 26 | 27 | ``` 28 | - 29 | 30 | bit-input-0 31 | ``` 32 | 33 | Please ensure words in the selector are separated using dash and not camelCase. 34 | -------------------------------------------------------------------------------- /.github/workflows/scan.yml: -------------------------------------------------------------------------------- 1 | name: Scan 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - "main" 8 | pull_request: 9 | types: [opened, synchronize, reopened] 10 | branches-ignore: 11 | - "main" 12 | pull_request_target: 13 | types: [opened, synchronize, reopened] 14 | branches: 15 | - "main" 16 | 17 | permissions: {} 18 | 19 | jobs: 20 | check-run: 21 | name: Check PR run 22 | uses: bitwarden/gh-actions/.github/workflows/check-run.yml@main 23 | permissions: 24 | contents: read 25 | 26 | sast: 27 | name: Checkmarx 28 | uses: bitwarden/gh-actions/.github/workflows/_checkmarx.yml@main 29 | needs: check-run 30 | secrets: 31 | AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} 32 | AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} 33 | AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} 34 | permissions: 35 | contents: read 36 | pull-requests: write 37 | security-events: write 38 | id-token: write 39 | 40 | quality: 41 | name: Sonar 42 | uses: bitwarden/gh-actions/.github/workflows/_sonar.yml@main 43 | needs: check-run 44 | secrets: 45 | AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} 46 | AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} 47 | AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} 48 | permissions: 49 | contents: read 50 | pull-requests: write 51 | id-token: write 52 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Please sort into logical groups with comment headers. Sort groups in order of specificity. 2 | # For example, default owners should always be the first group. 3 | # Sort lines alphabetically within these groups to avoid accidentally adding duplicates. 4 | # 5 | # https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners 6 | 7 | # Leads for all reviews of documentation 8 | * @bitwarden/tech-leads 9 | 10 | # Unowned files 11 | package.json 12 | package-lock.json 13 | 14 | # Architecture department for architecture content 15 | docs/architecture @bitwarden/dept-architecture 16 | 17 | # Key management and Architecture for crypto concepts 18 | docs/architecture/cryptography @bitwarden/team-key-management-dev @bitwarden/dept-architecture 19 | 20 | # Architecture and AppSec for security concepts 21 | docs/architecture/security @bitwarden/team-appsec @bitwarden/dept-architecture 22 | 23 | # Shared workflows ownership 24 | .github/workflows/build.yml @bitwarden/dept-bre @bitwarden/tech-leads 25 | 26 | # Docker-related files 27 | **/Dockerfile @bitwarden/team-appsec @bitwarden/dept-bre 28 | **/*.dockerignore @bitwarden/team-appsec @bitwarden/dept-bre 29 | **/entrypoint.sh @bitwarden/team-appsec @bitwarden/dept-bre 30 | **/docker-compose.yml @bitwarden/team-appsec @bitwarden/dept-bre 31 | 32 | # Claude related files 33 | .claude/ @bitwarden/team-ai-sme 34 | .github/workflows/respond.yml @bitwarden/team-ai-sme 35 | .github/workflows/review-code.yml @bitwarden/team-ai-sme 36 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## 🎟️ Tracking 2 | 3 | 4 | 5 | ## 📔 Objective 6 | 7 | 8 | 9 | ## ⏰ Reminders before review 10 | 11 | - Contributor guidelines followed 12 | - All formatters and local linters executed and passed 13 | - Written new unit and / or integration tests where applicable 14 | - Protected functional changes with optionality (feature flags) 15 | - Used internationalization (i18n) for all UI strings 16 | - CI builds passed 17 | - Communicated to DevOps any deployment requirements 18 | - Updated any necessary documentation (Confluence, contributing docs) or informed the documentation 19 | team 20 | 21 | ## 🦮 Reviewer guidelines 22 | 23 | 24 | 25 | - 👍 (`:+1:`) or similar for great changes 26 | - 📝 (`:memo:`) or ℹ️ (`:information_source:`) for notes or general info 27 | - ❓ (`:question:`) for questions 28 | - 🤔 (`:thinking:`) or 💭 (`:thought_balloon:`) for more open inquiry that's not quite a confirmed 29 | issue and could potentially benefit from discussion 30 | - 🎨 (`:art:`) for suggestions / improvements 31 | - ❌ (`:x:`) or ⚠️ (`:warning:`) for more significant problems or concerns needing attention 32 | - 🌱 (`:seedling:`) or ♻️ (`:recycle:`) for future improvements or indications of technical debt 33 | - ⛏ (`:pick:`) for minor or nitpick changes 34 | -------------------------------------------------------------------------------- /docs/architecture/adr/0002-public-module-npm-packages.md: -------------------------------------------------------------------------------- 1 | --- 2 | adr: "0002" 3 | status: Accepted 4 | date: 2022-06-02 5 | tags: [clients] 6 | --- 7 | 8 | # 0002 - Public API for modules 9 | 10 | 11 | 12 | ## Context and problem statement 13 | 14 | We currently use direct file reference across different packages. This had led to everything in the 15 | packages being available to any other package across our projects. Which makes it difficult to 16 | identity what potential side effects a change might have as they are not isolated to the individual 17 | package. Traditionally only a specific subset of a package is exposed as a public module, which 18 | provides safety that changes will be internal to the package and ideally covered by it's unit tests. 19 | 20 | ## Considered options 21 | 22 | - **Direct references** - We can decide to continue as is. Without a public API. 23 | - **Define public modules using index.ts** - We add `index.ts` to each folder that defines the 24 | "public" interfaces. The other packages then imports the root index file and are forbidden from 25 | direct references to internal files. 26 | 27 | ## Decision outcome 28 | 29 | Chosen option: **Define a public module using index.ts**. 30 | 31 | ### Positive consequences 32 | 33 | - The public module is defined. 34 | - Imports can be kept cleaner since not every file needs to be manually imported. 35 | - Safety in knowing that a change is isolated to the package. 36 | 37 | ### Negative consequences 38 | 39 | - We will have to update `index.ts` files whenever we add a new exported API. 40 | -------------------------------------------------------------------------------- /src/css/custom.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Any CSS included here will be global. The classic template 3 | * bundles Infima by default. Infima is a CSS framework designed to 4 | * work well for content-centric websites. 5 | */ 6 | 7 | /* You can override the default Infima variables here. */ 8 | :root { 9 | --ifm-color-primary: #175ddc; 10 | --ifm-color-primary-dark: #1554c6; 11 | --ifm-color-primary-darker: #144fbb; 12 | --ifm-color-primary-darkest: #10419a; 13 | --ifm-color-primary-light: #2369e8; 14 | --ifm-color-primary-lighter: #2e71e9; 15 | --ifm-color-primary-lightest: #4f87ed; 16 | --ifm-code-font-size: 95%; 17 | --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1); 18 | } 19 | 20 | /* For readability concerns, you should choose a lighter palette in dark mode. */ 21 | [data-theme="dark"] { 22 | --ifm-color-primary: #6a99f0; 23 | --ifm-color-primary-dark: #4b83ed; 24 | --ifm-color-primary-darker: #3b79eb; 25 | --ifm-color-primary-darkest: #165cdc; 26 | --ifm-color-primary-light: #89aff3; 27 | --ifm-color-primary-lighter: #99b9f5; 28 | --ifm-color-primary-lightest: #c8daf9; 29 | --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3); 30 | } 31 | 32 | .navbar__brand b { 33 | margin-left: 5px; 34 | } 35 | 36 | .navbar--fixed-top { 37 | height: 4rem; 38 | } 39 | 40 | .navbar__logo { 41 | height: 2.8rem; 42 | } 43 | 44 | .navbar__link--active, 45 | .menu__link--active { 46 | font-weight: bold; 47 | } 48 | 49 | figcaption { 50 | text-align: center; 51 | font-style: italic; 52 | } 53 | 54 | .theme-doc-markdown dt { 55 | font-weight: bold; 56 | } 57 | 58 | .theme-doc-markdown dd { 59 | margin-bottom: 1rem; 60 | } 61 | -------------------------------------------------------------------------------- /docs/architecture/deep-dives/ssh/index.md: -------------------------------------------------------------------------------- 1 | # SSH Keys and Agent 2 | 3 | :::info 4 | 5 | For more information on how Bitwarden implements its SSH agent, see [SSH Agent](./agent). 6 | 7 | ::: 8 | 9 | ## What are SSH Keys? 10 | 11 | SSH keys are asymmetric key pairs that can be used for signing. Historically they were intended for 12 | logging into servers, but recently they can also be used for signing arbitrary data such as Git 13 | commits or even regular files. These key pairs consist of a private key, an associated public key, 14 | and fingerprint; the latter two can be used to verify a signature created using the private key. 15 | 16 | When stored on disk private keys can be stored in different formats. The modern, widely supported 17 | format is `OPENSSH` encoding, which supports all of `RSA`, `ECDSA`, and `Ed25519` keys. Some 18 | applications use the older `PKCS#8` format which is more complex. Further, `PKCS#8` encoded 19 | `Ed25519` keys are not supported by OpenSSH and need to be converted to `OPENSSH` format before they 20 | can be used. 21 | 22 | Private keys may be encrypted with a passphrase when stored on disk or left unprotected. When using 23 | a passphrase, the encryption key is derived from the passphrase using a 24 | [KDF](https://en.wikipedia.org/wiki/Key_derivation_function) such as `bcrypt`. SSH private keys can 25 | be encrypted using different ciphers -- `AES-128`, `AES-192`, `AES-256`, or `3DES`. Keys can be used 26 | directly by applications but more commonly they are loaded and held in an SSH agent. An agent can, 27 | after decrypting, hold the keys in memory and provide signing capabilities. Keys can also be stored 28 | on hardware tokens like YubiKeys (`ed25519-sk`). 29 | -------------------------------------------------------------------------------- /custom-words.txt: -------------------------------------------------------------------------------- 1 | # Custom dictionary for spellchecking. Before adding a word here, consider whether you can put 2 | # it in a single (`) or multiline (```) code snippet instead, as they are automatically ignored 3 | # by the spellchecker. Please keep the list sorted alphabetically. 4 | AndroidX 5 | AOSP 6 | backplane 7 | Bitwarden 8 | bitwardensecret 9 | bytemark 10 | Casbin 11 | clickjacking 12 | codebases 13 | CODEOWNERS 14 | COSE 15 | CQRS 16 | CQS 17 | CTAP2 18 | deinitializer 19 | deinitializers 20 | dockerized 21 | dotfile 22 | F-Droid 23 | frontmatter 24 | Gitter 25 | HKDF 26 | HMAC 27 | hotfix 28 | hotfixed 29 | hotfixes 30 | Hyperscale 31 | iframes 32 | inet 33 | initialisms 34 | IntelliJ 35 | Iterm 36 | Jetpack 37 | jslib 38 | jumpcloud 39 | keychain 40 | keypair 41 | keyserver 42 | Kubebuilder 43 | LDIF 44 | libmagic 45 | LLDB 46 | Mailcatcher 47 | minio 48 | MVVM 49 | NGRX 50 | OIDCS 51 | Omnisharp 52 | onboarded 53 | opid 54 | OTLP 55 | owasp 56 | passcode 57 | passwordless 58 | pinentry 59 | PNSs 60 | POSIX 61 | precompiler 62 | proxied 63 | recompositions 64 | Redis 65 | refactorings 66 | roadmap 67 | roadmaps 68 | rollout 69 | rollouts 70 | rustup 71 | sandboxed 72 | SARIF 73 | SAST 74 | SCIM 75 | SDET 76 | SDLC 77 | Serilog 78 | signtool 79 | signup 80 | sqlcmd 81 | struct 82 | structs 83 | subfolders 84 | subprocessor 85 | toolset 86 | TOTP 87 | typealias 88 | typecheck 89 | typechecks 90 | typesafe 91 | unsynchronized 92 | WCAG 93 | Xcodes.app 94 | xcworkspace 95 | xmldoc 96 | Yellowpages 97 | Yubico 98 | YubiKey 99 | YubiKeys 100 | 101 | # Forbidden words 102 | !auto-fill 103 | !auto-filled 104 | -------------------------------------------------------------------------------- /docs/contributing/user-secrets.md: -------------------------------------------------------------------------------- 1 | # Modifying User Secrets 2 | 3 | ## Manually editing user secrets 4 | 5 | We recommend using the automated helper script described in the 6 | [Server Setup Guide](../getting-started/server/guide.md). However, you can manually edit or 7 | troubleshoot your user secrets using the instructions below. If you are manually editing using 8 | secrets, make sure to remember to copy your changes across to all projects if required. 9 | 10 | ### Editing user secrets - Visual Studio on Windows 11 | 12 | Right-click on the project in the Solution Explorer and click **Manage User Secrets**. 13 | 14 | ### Editing user secrets - Visual Studio on macOS 15 | 16 | Open a terminal and navigate to the project directory. 17 | 18 | Add a user secret by running: 19 | 20 | ```bash 21 | dotnet user-secrets set "" "" 22 | ``` 23 | 24 | View currently set secrets by running: 25 | 26 | ```bash 27 | dotnet user-secrets list 28 | ``` 29 | 30 | By default, user secret files are located in: 31 | 32 | ```bash 33 | ~/.microsoft/usersecrets//secrets.json 34 | ``` 35 | 36 | You can edit this file directly, which is much easier than using the command line tool. 37 | 38 | ### Editing user secrets - Visual Studio Code 39 | 40 | - Install the 41 | [.NET Core User Secrets](https://marketplace.visualstudio.com/items?itemName=adrianwilczynski.user-secrets) 42 | extension 43 | - Right-click on your project's **.csproj** file and select **Manage User Secrets** 44 | 45 | ### Editing user secrets - Rider 46 | 47 | - Navigate to **Preferences -> Plugins** and Install .NET Core User Secrets 48 | - Right click on the a project and click **Tools** > **Open project user secrets** 49 | -------------------------------------------------------------------------------- /docs/getting-started/sdk/secrets-manager/index.mdx: -------------------------------------------------------------------------------- 1 | # Secrets Manager 2 | 3 | This section contains development information for the Bitwarden Secrets Manager CLI, language 4 | wrappers, and integrations based on the SDK. 5 | 6 | For more in-depth documentation please review the [SDK Architecture](../../../architecture/sdk), 7 | Secrets Manager SDK project's [`README`](https://github.com/bitwarden/sdk-sm). 8 | 9 | ## Requirements 10 | 11 | - [Rust](https://www.rust-lang.org/tools/install) latest stable version - (preferably installed via 12 | [rustup](https://rustup.rs/)) 13 | - NodeJS and NPM. 14 | 15 | See the [Tools and Libraries](../../tools/index.md) page for more information. 16 | 17 | ## Setup instructions 18 | 19 | 1. Clone the repository: 20 | 21 | ```bash 22 | git clone https://github.com/bitwarden/sdk-sm.git 23 | cd sdk 24 | ``` 25 | 26 | 2. Install the dependencies: 27 | 28 | ```bash 29 | npm ci 30 | ``` 31 | 32 | ## Building the SDK 33 | 34 | To build the SDK, run the following command: 35 | 36 | ```bash 37 | cargo build 38 | ``` 39 | 40 | ## Web client 41 | 42 | To start the web client, follow the 43 | [Web Vault setup instructions](../../clients/web-vault/index.mdx) and create an organization with 44 | Secrets Manager enabled. Then use the organization switcher to go to Secrets Manager. 45 | 46 | ![Navigate to Secrets Manager](sm-product-switcher.png) 47 | 48 | :::info 49 | 50 | If you have enabled Secrets Manager for your org and do not see Secrets Manager in the product 51 | switcher, you may need to manually enable it for your user by going to **Admin Console** -> 52 | **Members** -> check _"This user can access Secrets Manager"_ for your user. 53 | 54 | ![Enable for user](enable-sm.png) 55 | 56 | ::: 57 | -------------------------------------------------------------------------------- /scripts/generate-certs.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ROOT_DIR=$(git rev-parse --show-toplevel) 4 | 5 | # Load .env values into the environment 6 | set -o allexport 7 | . "$ROOT_DIR/.env" 8 | set +o allexport 9 | 10 | openssl req -x509 -newkey rsa:4096 -keyout $SSL_KEY_FILE -out $SSL_CRT_FILE -sha256 -days 1826 -nodes \ 11 | -subj "/CN=localhost/O=Bitwarden Contributing Docs Local Development" \ 12 | -addext "subjectAltName=DNS:localhost,IP:127.0.0.1" 13 | 14 | chmod +rw $SSL_CRT_FILE 15 | chmod +rw $SSL_KEY_FILE 16 | 17 | printf "Certificate generated! When prompted, enter your password to update your system's secure store with the Certificate Authority.\n\n" 18 | printf "Alternatively, you can manually add it with:\n" 19 | 20 | # Mac OSX 21 | if [[ "$OSTYPE" == "darwin"* ]]; then 22 | printf "\e[30m\e[44m sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain $SSL_CRT_FILE \e[0m\n" 23 | 24 | sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ssl.crt 25 | # If not Mac OS, assume *nix 26 | else 27 | printf "\e[30m\e[44m sudo cp $SSL_CRT_FILE /usr/local/share/ca-certificates/ && sudo update-ca-certificates \e[0m\n\n" 28 | printf "Important Note! Chromium doesn't use 'ca-certificates' on *nix. Instead it uses nssdb for cert storage, and depending on your configuration, may be in the shared system store at '\$HOME/.pki/nssdb', in Chromium's local snap store (e.g. '\$HOME/snap/chromium/current/.pki/nssdb'), or elsewhere. You will need to install the appropriate binary for your distro to run 'certutil -d sql:\$CHROMIUM_SECURE_STORE -A -t "CP,CP," -n DocsLocalDevelopmentSSL -i ./$SSL_CRT_FILE' from the project root." 29 | 30 | sudo cp $SSL_CRT_FILE /usr/local/share/ca-certificates/ 31 | sudo update-ca-certificates 32 | fi 33 | -------------------------------------------------------------------------------- /docs/getting-started/server/secrets/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_custom_props: 3 | access: bitwarden 4 | --- 5 | 6 | # User Secrets 7 | 8 | The server repository comes with it’s own `dev/secrets.json` file for community contributors. 9 | Internal Bitwarden developers will need a different user secrets file in order to properly emulate 10 | the cloud environment. 11 | 12 | The user secrets file that we use for development can be found in the Development collection in the 13 | Bitwarden app. If you don’t have access to this collection, please contact your manager. 14 | 15 | ![Secrets](./secrets.png) 16 | 17 | This secure note has 2 attachments: 18 | 19 | 1. `secrets.json` - the default recommended user secrets for development. This will use the local 20 | Docker services as outlined in the [Server Setup Guide](../guide.md) (e.g. MailCatcher and 21 | Azurite). 22 | 2. `additional-keys-for-cloud-services.json` - these are optional keys you can add to your 23 | `secrets.json` if you want to enable test cloud services instead of the local Docker services. 24 | It is not a complete secrets file and cannot be used on its own. 25 | 26 | ## Updating the shared user secrets 27 | 28 | If you need to update the shared user secrets, please follow these rules: 29 | 30 | - new user secrets should go in one `.json` file only. We want to avoid duplicate keys across both 31 | files. 32 | - avoid creating new `.json` files as a means of version control. Often the information (such as 33 | auth keys) can be retrieved from the original source if we need to roll back. If you feel that you 34 | must create a backup, mark it as "DEPRECATED" with the date. `secrets.json` and 35 | `additional-keys-for-cloud-services.json` should always contain the most up-to-date secrets. 36 | - announce any updates in the `#team-eng` Slack channel so that everyone knows to update their local 37 | instance. 38 | -------------------------------------------------------------------------------- /docs/getting-started/clients/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 3 3 | --- 4 | 5 | # Web clients 6 | 7 | This section contains development information for each of the Bitwarden Typescript client 8 | applications: 9 | 10 | - [Web Vault](./web-vault) 11 | - [Browser](./browser) 12 | - [Desktop](./desktop) 13 | - [CLI](./cli) 14 | 15 | In this context, "clients" generally refers to the Typescript clients, which are located in the 16 | `clients` mono-repository. 17 | 18 | ## Requirements 19 | 20 | Before you start, you should have Node and npm installed. See the [Tools and Libraries](../tools) 21 | page for more information. 22 | 23 | ## Setup instructions 24 | 25 | Before doing work on any of the clients, you need to clone and setup the `clients` mono-repository. 26 | 27 | 1. Clone the repository: 28 | 29 | ```bash 30 | git clone https://github.com/bitwarden/clients.git 31 | ``` 32 | 33 | 2. Install the dependencies: 34 | 35 | ```bash 36 | cd clients 37 | npm ci 38 | ``` 39 | 40 | :::info 41 | 42 | You should only ever install dependencies from the root of the repository. Don't try to install 43 | dependencies for individual client applications. 44 | 45 | ::: 46 | 47 | 3. Configure git blame to ignore certain commits (generally administrative changes, such as 48 | formatting): 49 | 50 | ```bash 51 | git config blame.ignoreRevsFile .git-blame-ignore-revs 52 | ``` 53 | 54 | 4. Open the `clients.code-workspace` file in Visual Studio Code. This has been configured to use 55 | [multi-root workspaces](https://code.visualstudio.com/docs/editor/multi-root-workspaces) to 56 | improve your development experience. Each client will appear as its own workspace in the 57 | Explorer panel on the left-hand side. 58 | 59 | You're now ready to continue with any additional instructions for the particular client you want to 60 | work on. 61 | -------------------------------------------------------------------------------- /docs/architecture/sdk/data-models.md: -------------------------------------------------------------------------------- 1 | # Data models 2 | 3 | The SDK is expected to be used in a variety of projects, and to that end it defines a stable public 4 | interface. Care must be taken to avoid exposing the inner workings on the SDK including its data 5 | model. 6 | 7 | ## Public interface 8 | 9 | The public interface of the SDK is anything that is exposed externally, be it function names, types, 10 | or exposed models. The SDK generally exposes request and response models that contains the expected 11 | data for each API call. 12 | 13 | We can generally group the public models into the following categories: 14 | 15 | - **View models**: Models that generally represents a decrypted state, examples are `CipherView`, 16 | `CipherListView`, `FolderView`, etc. 17 | - **Request models**: Models that are used to send data into the SDK. Some examples are 18 | `ProjectGetRequest`, `ProjectCreateRequest`, etc. 19 | - **Response models**: Returns data from the SDK e.g. `ProjectResponse`. 20 | 21 | ## Internal models 22 | 23 | The SDK also maintains internal models: 24 | 25 | - **API models**: [Auto-generated models](./server-bindings.md) that are used to interact with the 26 | server. 27 | - **Domain models**: General data models used to represent a specific concern in the SDK. For 28 | example, `Cipher`, `Folder`, etc. 29 | - **DTO**: Data Transfer Objects are used to transfer data between layers of the SDK. They are 30 | generally used to decouple the domain models from the API models. 31 | 32 | ```kroki type=plantuml 33 | @startuml 34 | skinparam componentStyle rectangle 35 | component [""""] as Domain 36 | component [""""Requests] As Requests 37 | component [""""Response] as Response 38 | component [""""Views] as Views 39 | component [""""DTOs] as DTOs 40 | 41 | [Response] -r-> [Domain] 42 | [Domain] -r-> [Requests] 43 | [Domain] <--> [Views] 44 | [Domain] <--> [DTOs] 45 | @enduml 46 | ``` 47 | -------------------------------------------------------------------------------- /docs/architecture/security/principles/02-locked-vault-is-secure.mdx: -------------------------------------------------------------------------------- 1 | # P02 - A locked vault is secure 2 | 3 | Clients must ensure that highly sensitive vault data cannot be accessed in plain text once the vault 4 | has been locked, even if the device becomes compromised after the lock occurs. Protections are not 5 | guaranteed if the device is compromised before the vault is locked. 6 | 7 | ## Threat model 8 | 9 | A device has been compromised while the Bitwarden vault is locked (protections are not guaranteed if 10 | device is compromised before the vault is locked). Attacker has full access to userspace, but not 11 | kernel space. 12 | 13 | ## Security goals 14 | 15 | - Attackers cannot retrieve decrypted vault data 16 | - Attackers cannot retrieve user encryption keys 17 | - Attackers cannot inject arbitrary items as vault data 18 | - Attackers cannot edit encrypted vault data without alerting user or breaking items. 19 | 20 | ## Technical considerations 21 | 22 | Achieving this principle depends on the limitations of the platform and environment. For instance, 23 | in environments like JavaScript, where memory management is not fully under the control of the 24 | client, there may be residual plaintext in memory after the vault is locked. While ideal protection 25 | cannot be guaranteed in such cases, efforts must be made to minimize these risks through techniques 26 | such as clearing memory buffers and leveraging platform security features when available. 27 | 28 | ## Key storage mechanisms must provide adequate protection 29 | 30 | Mechanisms used for storing encryption keys when the vault is locked, such as PINs or auto-login, 31 | must provide an appropriate level of security. If encryption keys are stored in less secure 32 | environments (e.g. in the OS's keyring), the associated risks must be carefully considered and 33 | mitigated to ensure that unauthorized access to the vault remains limited, even when convenience 34 | features are used. 35 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/issue.yml: -------------------------------------------------------------------------------- 1 | name: Bug Report 2 | description: File a bug report 3 | labels: [bug] 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: | 8 | Thanks for taking the time to fill out this bug report! 9 | 10 | Please do not submit feature requests. The [Community Forums](https://community.bitwarden.com) has a section for submitting, voting for, and discussing product feature requests. 11 | - type: input 12 | id: page 13 | attributes: 14 | label: Page 15 | description: Full url of the page where the issue was found. 16 | validations: 17 | required: true 18 | - type: textarea 19 | id: expected 20 | attributes: 21 | label: Expected Result 22 | description: A clear and concise description of what you expected to happen. 23 | validations: 24 | required: true 25 | - type: textarea 26 | id: actual 27 | attributes: 28 | label: Actual Result 29 | description: A clear and concise description of what is happening. 30 | validations: 31 | required: true 32 | - type: textarea 33 | id: screenshots 34 | attributes: 35 | label: Screenshots or Videos 36 | description: If applicable, add screenshots and/or a short video to help explain your problem. 37 | - type: textarea 38 | id: additional-context 39 | attributes: 40 | label: Additional Context 41 | description: Add any other context about the problem here. 42 | - type: checkboxes 43 | id: issue-tracking-info 44 | attributes: 45 | label: Issue Tracking Info 46 | description: | 47 | Issue tracking information 48 | options: 49 | - label: 50 | I understand that work is tracked outside of Github. A PR will be linked to this issue 51 | should one be opened to address it, but Bitwarden doesn't use fields like "assigned", 52 | "milestone", or "project" to track progress. 53 | -------------------------------------------------------------------------------- /docs/architecture/adr/0001-reactive-forms.md: -------------------------------------------------------------------------------- 1 | --- 2 | adr: "0001" 3 | status: Accepted 4 | date: 2022-05-28 5 | tags: [clients, angular, forms] 6 | --- 7 | 8 | # 0001 - Angular Reactive Forms 9 | 10 | 11 | 12 | ## Context and problem statement 13 | 14 | Most of the forms in our Angular applications use the template driven forms. Lately we have been 15 | noticing issues scaling and maintaining these forms. And have begun mixing the use of 16 | template-driven with reactive forms. 17 | 18 | Maintaining two ways of handling forms are complex and moving full into a single approach will 19 | ensure a more consistent experience for developers and users. 20 | 21 | ## Considered options 22 | 23 | - **Reactive forms** - Provide direct, explicit access to the underlying forms object model. 24 | Compared to template-driven forms, they are more robust: they're more scalable, reusable, and 25 | testable. If forms are a key part of your application, or you're already using reactive patterns 26 | for building your application, use reactive forms. 27 | - **Template-driven forms** - Rely on directives in the template to create and manipulate the 28 | underlying object model. They are useful for adding a simple form to an app, such as an email list 29 | signup form. They're straightforward to add to an app, but they don't scale as well as reactive 30 | forms. If you have very basic form requirements and logic that can be managed solely in the 31 | template, template-driven forms could be a good fit. 32 | 33 | Source: https://angular.io/guide/forms-overview#choosing-an-approach 34 | 35 | ## Decision outcome 36 | 37 | Chosen option: **Reactive forms**, because our needs exceed what template-driven forms are 38 | recommended for. 39 | 40 | ### Positive consequences 41 | 42 | - You never need to think which form method to use. 43 | 44 | ### Negative consequences 45 | 46 | - Using only reactive form means we might have some additional boilerplate. 47 | -------------------------------------------------------------------------------- /docs/architecture/adr/0013-deprecate-global-request-response-models.md: -------------------------------------------------------------------------------- 1 | --- 2 | adr: "0013" 3 | status: Accepted 4 | date: 2022-09-16 5 | tags: [clients, angular] 6 | --- 7 | 8 | # 0013 - Deprecate global request/response models 9 | 10 | 11 | 12 | ## Context and problem statement 13 | 14 | Our Angular application currently partially uses a layered folder structure. This results in a 15 | domain context being split between multiple folders several levels deep. This causes friction since 16 | modifying services often requires modifying the models belonging to that service. 17 | 18 | Understandably our application uses a lot of models, however the biggest and most isolated part of 19 | the models are the request and responses. Which makes them a good starting point. 20 | 21 | ## Considered options 22 | 23 | - **Continue as is** - We can continue as we are, and continue to put models in 24 | `libs/common/models`. 25 | - **Place models next to their owner** - Request and responses are owned by a single API service. 26 | They can therefore be placed close to their service which keeps connected changes close to each 27 | other. 28 | 29 | ### Decision Outcome 30 | 31 | Use the **Place models next to their owner** for request and response models. 32 | 33 | A rule of thumb is to put any model that is used in the abstraction in the abstraction directory. 34 | And any model used in the service in the service directory. Abstractions are part of the service 35 | public interface, while services are part of the internal interface. 36 | 37 | ### Example 38 | 39 | ```text 40 | libs/common/ 41 | abstractions/folder/ 42 | folder.service.abstraction.ts 43 | folder-api.service.abstraction.ts 44 | responses/ 45 | folder.response.ts (Exposed as public API) 46 | services/folder/ 47 | folder.service.ts 48 | folder-api.service.ts 49 | requests/ 50 | folder.request.ts (Internal, only used within the implementation) 51 | ``` 52 | -------------------------------------------------------------------------------- /docs/architecture/adr/0005-refactor-api-service.md: -------------------------------------------------------------------------------- 1 | --- 2 | adr: "0005" 3 | status: Accepted 4 | date: 2022-07-08 5 | tags: [clients, angular] 6 | --- 7 | 8 | # 0005 - Refactor Api Service 9 | 10 | 11 | 12 | ## Context and problem statement 13 | 14 | The `ApiService` currently handles _all_ API requests. This has resulted in the class evolving into 15 | a Bloater, and as of right now consists of **2021** lines of code, and has **268** methods. 16 | Additionally, since it knows everything related to the servers it also needs to import every request 17 | and response which necessitates that the `ApiService` and request/responses are put in the same npm 18 | package. 19 | 20 | ## Considered options 21 | 22 | - **Extract Class** - We should break up the class using the _Extract Class_ refactor, where each 23 | domain context should have its own _API_ service. The `ApiService` should be converted into a 24 | generic service that doesn't care what the request or response is and should only be used within 25 | other API services. 26 | - **Do nothing** - Leave it as is. 27 | 28 | ## Decision outcome 29 | 30 | Chosen option: **Extract Class** 31 | 32 | The naming of these new classes should be `{Domain}ApiService`, the folder domain for example should 33 | be called `FolderApiService`. 34 | 35 | Example of the refactor: 36 | 37 | - [`folder-api.service.ts`][folder-api]: Create a new service, move the methods from `ApiService` to 38 | the new service. During this refactor we also moved the server knowledge from the `FolderService`, 39 | as it should only be responsible for maintaining it's state. 40 | - [`api.service.ts`][api]: Remove the old methods from the `ApiService`. 41 | 42 | [folder-api]: 43 | https://github.com/bitwarden/clients/pull/3011/files#diff-11b3488b9977f06625349680f81554505613715cfcc9890ebb356a74579c236a 44 | [api]: 45 | https://github.com/bitwarden/clients/pull/3011/files#diff-6c8f3163b688c01f589d1e9ee5b7998aea4a0aedde8333c3939fb6181c301bed 46 | -------------------------------------------------------------------------------- /docs/architecture/deep-dives/passkeys/implementations/relying-party/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Relying Party 3 | sidebar_position: 1 4 | --- 5 | 6 | # Overview 7 | 8 | Bitwarden can act as a Relying Party (RP) for passkeys. This means that you can log in to Bitwarden 9 | using a passkey. Bitwarden supports passkeys as a second factor of authentication (2FA) and as a 10 | primary factor of authentication. When used as a primary factor of authentication, Bitwarden will 11 | not require you to enter a username or password when logging in. In cases where your passkey 12 | [supports encryption](prf.md), your passkey will be able to decrypt your data as well. If your 13 | passkey does not support encryption, Bitwarden will prompt you to enter a password to unlock your 14 | vault. 15 | 16 | ## Implementations 17 | 18 | Bitwarden currently has two implementations for authenticating users using passkeys: 19 | 20 | - Older 2FA "WebAuthn" implementation 21 | - Newer "Log in with Passkeys" implementation 22 | 23 | Both implementations use the same FIDO2 technologies, but are completely separate and share almost 24 | no code. From a user perspective "Log in with Passkeys" is a first-factor authentication method, 25 | while the older "WebAuthn" implementation is a second-factor. "Log in with Passkeys" takes advantage 26 | of FIDO2 User Verification and therefore completely replaces the other existing 2FA methods. 27 | 28 | The 2FA implementation will eventually be consolidated with the newer "Log in with Passkey" 29 | implementation. 30 | 31 | ## Storage modality 32 | 33 | - The 2FA "WebAuthn" implementation supports both client-side and server-side storage mode. 34 | - The "Log in with Passkeys" implementation only supports the client-side storage mode. 35 | 36 | ## Discoverability 37 | 38 | - The 2FA "WebAuthn" implementation does not support discoverability, as it is a second-factor 39 | authentication method and supports the server-side storage mode. 40 | - The "Log in with Passkeys" implementation requires discoverable credentials. 41 | -------------------------------------------------------------------------------- /docs/architecture/clients/data-model.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 2 3 | --- 4 | 5 | # Data Model 6 | 7 | This document describes the internal data model used by the different client applications. We use 8 | several dedicated models to represent our data layer. With a slightly complicated data 9 | transformation pipeline. 10 | 11 | ```kroki type=plantuml 12 | @startuml 13 | skinparam componentStyle rectangle 14 | component [""""] as Domain 15 | component [""""Request] As Request 16 | component [""""Response] as Response 17 | component [""""View] as View 18 | component [""""Export] as Export 19 | component [""""Data] as Data 20 | 21 | [Response] -r-> [Data] 22 | [Data] <-r-> [Domain] 23 | [Domain] -r-> [Request] 24 | [Domain] <--> [View] 25 | [Domain] <--> [Export] 26 | [Export] -r-> [View] 27 | @enduml 28 | ``` 29 | 30 | ## Domain 31 | 32 | The Domain models lies at the center of our data model, and represents encrypted data. 33 | 34 | ## View 35 | 36 | View models represent the decrypted state of the corresponding `Domain` model. They typically match 37 | the `Domain` model but contains a decrypted string for any `EncString` fields. 38 | 39 | ## Data 40 | 41 | The `Data` models are serializable versions of the corresponding `Domain`. In most cases this means 42 | converting `Date` to `string`. It's exclusively used when serializing the `Domain` models to disk 43 | for persisting state or export. This means it also needs to support deserialize older data models, 44 | which is traditionally done by providing good default values. 45 | 46 | ## Export 47 | 48 | Export models built from Domain or View models. Used for importing and exporting Bitwarden data. 49 | 50 | ## Request & Response (Deprecated) 51 | 52 | In the process of being migrated to live next to the the domain's API service. At which point it 53 | will no longer be a central part of our data model. 54 | 55 | ### Api 56 | 57 | Shared API models used to convert from Responses to Data. Essentially an re-usable extension of the 58 | request models. 59 | -------------------------------------------------------------------------------- /docs/getting-started/clients/cli/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 5 3 | --- 4 | 5 | # CLI 6 | 7 | :::tip 8 | 9 | If you’re not familiar with the CLI client, the Bitwarden Help Center has lots of 10 | [great documentation](https://bitwarden.com/help/article/cli/) that will help you get oriented. 11 | 12 | ::: 13 | 14 | ## Requirements 15 | 16 | Before you start, you must complete the [Clients repository setup instructions](../index.md). 17 | 18 | ## Build instructions 19 | 20 | :::tip Nx commands are preferred. 21 | 22 | We now recommend using Nx commands for building projects. For the cli: 23 | 24 | ```bash 25 | # Build and watch (GPL) 26 | npx nx serve cli --configuration=oss-dev 27 | # Build and watch (Bitwarden) 28 | npx nx serve cli --configuration=commercial-dev 29 | ``` 30 | 31 | For complete Nx documentation and all available commands, see 32 | [Using Nx to Build Projects](https://github.com/bitwarden/clients/blob/main/docs/using-nx-to-build-projects.md). 33 | ::: 34 | 35 | Build and run: 36 | 37 | 38 | 39 | ```bash 40 | cd apps/cli 41 | npm run build:bit:watch 42 | ``` 43 | 44 | 45 | 46 | 47 | 48 | ```bash 49 | cd apps/cli 50 | npm run build:oss:watch 51 | ``` 52 | 53 | 54 | 55 | By default, this will use the official Bitwarden servers. You can target your local server by using 56 | the [config command](https://bitwarden.com/help/article/cli/#config). You may need to 57 | [configure node to use your self-signed certificate](https://bitwarden.com/help/article/cli/#using-self-signed-certificates). 58 | 59 | ## Testing and Debugging 60 | 61 | The build is located at `build/bw.js`. You can run this with node, for example: 62 | 63 | ```bash 64 | node build/bw.js login 65 | ``` 66 | 67 | It may be more convenient to make the file executable first: 68 | 69 | ```bash 70 | cd build 71 | chmod +x bw.js 72 | ./bw.js login 73 | ``` 74 | 75 | To debug the CLI client, run it from a 76 | [Javascript Debug Terminal](https://code.visualstudio.com/docs/nodejs/nodejs-debugging#_javascript-debug-terminal) 77 | and place the breakpoints in your Typescript code. 78 | -------------------------------------------------------------------------------- /docs/architecture/deep-dives/passkeys/naming-convention.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 4 3 | --- 4 | 5 | # Naming convention 6 | 7 | Since Bitwarden will both store passkeys in users' vaults and support login with passkeys, it is 8 | important to understand how to refer to these two different concepts in code, regardless of how they 9 | are referred to in the marketplace, especially since the term "passkey" is one that is evolving over 10 | time. 11 | 12 | The current convention is: 13 | 14 | - When working with [Provider](implementations/provider) code (i.e storing a credential in the 15 | vault), use `Fido2`. 16 | - Example: `Fido2Credential`, `Fido2Client`. 17 | - When working with [Relying Party](implementations/relying-party) code (i.e. authenticating to 18 | Bitwarden with a passkey), use `WebAuthn`. 19 | - Example: `WebAuthnLogin` for passkey login, `WebAuthn` for the older 2FA log in. 20 | - Use the term `Credential` (and not `Passkey`) when referring to a FIDO2 Credential in code. 21 | 22 | ## FIDO2 vs WebAuthn 23 | 24 | This naming scheme is not based on any hard rules defined in the specifications, but rather on which 25 | parts of FIDO2 are used to build the Provider and Relying Party code. 26 | 27 | Historically, the Provider code was built on both the WebAuthn and CTAP2 specifications and so 28 | `Fido2` was used to refer to it. Today, the Provider code is almost exclusively based on the 29 | WebAuthn specification. However, if Bitwarden chooses to support any authenticator extensions in the 30 | future (e.g. `hmac-secret`), they will likely be defined in the CTAP2 specification. 31 | 32 | In contrast, the Relying Party code is built exclusively on the WebAuthn specification and does not 33 | need to refer to CTAP2 at all, which is why the term `WebAuthn` was chosen. The older 2FA 34 | implementation is also based on the WebAuthn specification, but it is not a "login method" and so it 35 | is not referred to as `WebAuthnLogin`. 36 | 37 | :::info 38 | 39 | The implementation of 2FA login will eventually be consolidated with the newer passkey login 40 | implementation under the `WebAuthn` namespace. 41 | 42 | ::: 43 | -------------------------------------------------------------------------------- /docs/architecture/clients/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 4 3 | --- 4 | 5 | # Web Clients Architecture 6 | 7 | The Web based clients, henceforth referenced simply as clients, are the _Web Vault_, _Browser 8 | Extension_, _Desktop Application_ (Electron based) and the _CLI_. They all share a common codebase 9 | and a single [Git repository](https://github.com/bitwarden/clients). 10 | 11 | The mono-repository root directory contains three main folders. 12 | 13 | - `apps` - Our different application specific code, consists of `web`, `browser`, `desktop` and 14 | `cli`. 15 | - `bitwarden_license` - Bitwarden Licensed version of the web vault. 16 | - `libs` - Shared code between the different applications. 17 | 18 | `libs` contains the following projects. 19 | 20 | - `Common` - Common code shared between all the clients including CLI. 21 | - `Angular` - Angular specific code used by all the visual clients. 22 | - `Components` - Angular Components Library. 23 | - `Node` - Used to be shared code for CLI and Directory Connector CLI, but since directory connector 24 | no longer uses the same version of libs this module is deprecated. 25 | 26 | ## Package diagram 27 | 28 | Below is a simplified package diagram of the clients repository. 29 | 30 | :::note 31 | 32 | For readability, ubiquitous app dependencies to `common` are hidden. 33 | 34 | ::: 35 | 36 | ```kroki type=plantuml 37 | @startuml 38 | skinparam BackgroundColor transparent 39 | skinparam componentStyle rectangle 40 | skinparam linetype ortho 41 | 42 | title Simplified Package Diagram 43 | 44 | component "Bitwarden License" { 45 | component "Bit Web" 46 | } 47 | 48 | component apps { 49 | component "Web Vault" 50 | component "Desktop" 51 | component "Browser Extension" 52 | component "CLI" 53 | } 54 | 55 | component libs { 56 | component "Common" 57 | component "Angular" 58 | component "Node" 59 | } 60 | 61 | [Bit Web] --> [Web Vault] 62 | [Bit Web] --[norank]> [Angular] 63 | 64 | [Web Vault] --> [Angular] 65 | 66 | [Browser Extension] --> [Angular] 67 | 68 | [CLI] --> [Node] 69 | 70 | [Angular] --> [Common] 71 | 72 | [Desktop] --> [Angular] 73 | 74 | [Node] --> [Common] 75 | @enduml 76 | ``` 77 | -------------------------------------------------------------------------------- /docs/architecture/deep-dives/passkeys/glossary.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 6 3 | --- 4 | 5 | # Glossary 6 | 7 | This page contains some definitions of terms used throughout the passkey documentation. For a more 8 | comprehensive list, see the 9 | [FIDO Alliance Glossary](https://fidoalliance.org/specs/common-specs/fido-glossary-v2.1-rd-20210525.html). 10 | 11 | ## Definitions 12 | 13 |
14 |
Passkey
15 |
Any passwordless FIDO2 credential.
16 | 17 |
Credential
18 |
The technical term for a passkey. The two terms are used interchangeably.
19 | 20 |
Relying Party (RP)
21 |
A web site or other entity that uses a FIDO2 protocol to authenticate users by asking for a passkey.
22 | 23 |
Passkey Provider (PP)
24 |
An app and/or service that is responsible for storing and managing passkeys. Many operating systems include a default passkey provider (first-party), and many also support third-party providers (like Bitwarden).
25 | 26 |
Attestation
27 |
The process used to create a new passkey.
28 |
The process of communicating a cryptographic assertion to a relying party that a key presented during authenticator registration was created and protected by a genuine authenticator with verified characteristics.
29 | 30 |
Attestation Statement
31 |
An optional statement about the exact type (make/model) of the authenticator and its capabilities.
32 |
An optional statement provided by an authenticator which can be used by a Relying Party to identify and verify the provenance of the authenticator. Not to be confused with "attestation" which can be performed without providing a statement about the provenance of the authenticator.
33 | 34 |
Assertion
35 |
The process used to log in.
36 |
The act of proving ownership of the private key, commonly referred to as authentication.
37 | 38 |
Fallback
39 |
Aborting the Bitwarden-side of the authentication process and handing off control to the native browser implementation of WebAuthn, enabling the user to use hardware security keys, etc.
40 |
41 | -------------------------------------------------------------------------------- /docs/architecture/adr/0007-manifest-v3-browser-memory-caching.md: -------------------------------------------------------------------------------- 1 | --- 2 | adr: "0007" 3 | status: Accepted 4 | date: 2022-07-12 5 | tags: [browser, angular] 6 | --- 7 | 8 | # 0007 - Manifest V3 sync Observables 9 | 10 | 11 | 12 | ## Context and problem statement 13 | 14 | Manifest v3 brings ephemeral contexts to web extensions by disallow a long-lived background process. 15 | This means that we need to store and synchronize state through different popup/service worker/web 16 | worker instances. This is done through `LocalBackedMemoryStorageService`. 17 | 18 | Moving away from StateService to observables has made this harder because observables are 19 | fundamentally tied to the extension instance. 20 | 21 | We need to store these observables to maintain state. State should be loaded on init, updated on 22 | next, and updated via a reload message. 23 | 24 | ## Considered options 25 | 26 | - **Init in constructor and update in UpdateObservables** - This is simple and clean, but lacks the 27 | guarantees that we always will update storage and emit messages. It also doesn't provide a way to 28 | sync data live if a side bar is open and a cipher is saved via the content scripts. We could build 29 | a timer to sync these items periodically from memory. 30 | - **Decorator pattern** - Use a decorator to wrap service constructors. This decorator will 31 | - initialize from `LocalBackedMemoryStorage` 32 | - Subscribe to the observer to update `LocalBackedMemoryStorage` and push event to workers to 33 | update observable from memory 34 | - Push `observable.next` on update event 35 | - Avoid a circular event loop here? (loops occur both on message and on observable) 36 | - message can be fixed with a guid 37 | - TODO: issue with message -> `observable.next` -> subscribe -> storage service is unknown 38 | 39 | ## Decision outcome 40 | 41 | Chosen option: **Decorator Pattern**. This will be more reusable and the cleaner solution going 42 | forward. It needs more thought to determine how to avoid circular events, but once solved, it is 43 | solved. 44 | 45 | ### Positive consequences 46 | 47 | - reusable, clean solution 48 | - adheres to observable best practices 49 | 50 | ### Negative consequences 51 | 52 | - some unknown implementation details may cause bumps along development 53 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@bitwarden/contributing-docs", 3 | "version": "0.0.0", 4 | "description": "Bitwarden Contributing Docs", 5 | "repository": { 6 | "type": "git", 7 | "url": "git+https://github.com/bitwarden/contributing-docs.git" 8 | }, 9 | "author": "Bitwarden Inc. (https://bitwarden.com)", 10 | "license": "SEE LICENSE IN LICENSE.txt", 11 | "bugs": { 12 | "url": "https://github.com/bitwarden/contributing-docs/issues" 13 | }, 14 | "homepage": "https://bitwarden.com", 15 | "private": true, 16 | "scripts": { 17 | "docusaurus": "docusaurus", 18 | "start": "./scripts/docusaurus-start.sh", 19 | "start:insecure": "docusaurus start", 20 | "setup:ssl": "./scripts/generate-certs.sh", 21 | "build": "docusaurus build", 22 | "swizzle": "docusaurus swizzle", 23 | "deploy": "docusaurus deploy", 24 | "clear": "docusaurus clear", 25 | "serve": "docusaurus serve", 26 | "write-translations": "docusaurus write-translations", 27 | "write-heading-ids": "docusaurus write-heading-ids", 28 | "typecheck": "tsc", 29 | "prettier": "prettier --write .", 30 | "lint": "prettier --check .", 31 | "prepare": "husky", 32 | "spellcheck": "cspell lint \"**/*.md{x,}\"" 33 | }, 34 | "dependencies": { 35 | "@docusaurus/core": "3.9.2", 36 | "@docusaurus/preset-classic": "3.9.2", 37 | "@mdx-js/react": "3.1.0", 38 | "docusaurus-lunr-search": "3.6.0", 39 | "prism-react-renderer": "2.4.1", 40 | "react": "19.2.0", 41 | "react-dom": "19.2.0", 42 | "remark-kroki": "0.3.7" 43 | }, 44 | "devDependencies": { 45 | "@docusaurus/module-type-aliases": "3.9.2", 46 | "@docusaurus/tsconfig": "3.9.2", 47 | "@types/react": "19.2.2", 48 | "cspell": "9.3.2", 49 | "husky": "9.1.7", 50 | "lint-staged": "16.2.3", 51 | "prettier": "3.6.2", 52 | "typescript": "5.9.2" 53 | }, 54 | "browserslist": { 55 | "production": [ 56 | ">0.5%", 57 | "not dead", 58 | "not op_mini all" 59 | ], 60 | "development": [ 61 | "last 1 chrome version", 62 | "last 1 firefox version", 63 | "last 1 safari version" 64 | ] 65 | }, 66 | "engines": { 67 | "node": "~22.14.0", 68 | "npm": "~11.3.0" 69 | }, 70 | "lint-staged": { 71 | "*": "prettier --cache --write --ignore-unknown", 72 | "*.md{x,}": "cspell lint" 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /docs/architecture/security/index.mdx: -------------------------------------------------------------------------------- 1 | # Security 2 | 3 | Outlines the foundational approach Bitwarden takes to ensure the safety and integrity of user data. 4 | It provides a structured framework for understanding Bitwarden's security philosophy, the principles 5 | it adheres to, and the specific requirements it implements to meet its commitments. 6 | 7 | ## Conventions 8 | 9 | ### Keywords 10 | 11 | The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", 12 | "RECOMMENDED", "MAY", and "OPTIONAL" in this section are to be interpreted as described in 13 | [RFC2119](https://datatracker.ietf.org/doc/html/rfc2119). 14 | 15 | ### References 16 | 17 | Principles in this documentation are labeled with unique identifiers (e.g., P01, P02, etc.) for easy 18 | reference throughout the document and in related discussions. When referencing a principle, simply 19 | use its identifier (e.g. P01). 20 | 21 | Requirements in this documentation use a shorthand format (e.g. XX.N.y) to indicate their specific 22 | location and context (e.g. VD.3.b). 23 | 24 | ## Structure 25 | 26 | This structure is meant to avoid unnecessary repetition and establish a logical flow from high-level 27 | philosophies to specific actions. It ensures that every requirement is tied to a well-defined 28 | principle, making it clear why it exists and what it is meant to achieve. The document is designed 29 | for both internal stakeholders and external users who seek to understand the company's security 30 | model. 31 | 32 | ### Definitions 33 | 34 | Establishes the foundational terminology used throughout the document. By clearly defining key 35 | concepts -- such as what constitutes "vault data" -- it ensures that the rest of the document is 36 | precise and unambiguous. 37 | 38 | ### Principles 39 | 40 | Describes the overarching philosophies and commitments that guide Bitwarden's approach to security. 41 | These principles are not actionable rules but rather serve as the justifications for the 42 | requirements that follow. They define what Bitwarden aims to achieve in its security posture and why 43 | certain decisions are made. 44 | 45 | ### Requirements 46 | 47 | Building on the principles, the requirements are concrete, actionable steps that Bitwarden is 48 | required to implement. These requirements ensure that the principles are upheld in practice and 49 | provide a measurable way to assess Bitwarden's security efforts. 50 | -------------------------------------------------------------------------------- /docs/architecture/adr/0012-angular-filename-convention.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 0012 - Angular filename convention 3 | adr: "0012" 4 | status: Accepted 5 | date: 2022-08-23 6 | tags: [clients, angular] 7 | --- 8 | 9 | # 0012 - Angular Filename convention 10 | 11 | 12 | 13 | ## Context and problem statement 14 | 15 | We currently use a mixed filename convention where some files follows the Angular style guide, and 16 | other files use camelCase. This causes some confusion as to which convention to follow, and we 17 | should standardize on one convention to avoid confusion. 18 | 19 | ## Considered options 20 | 21 | - **Angular coding style guide** - The Angular coding style guide specifies "Separate file names 22 | with dots and dashes". 23 | - **camelCase** - Our own convention has for a long time been to use camelCase. 24 | 25 | ### Decision Outcome 26 | 27 | Use the [**Angular coding style guide**][naming]. More specifically [Style 02-02][style-02-02] and 28 | [Style 02-03][style-02-03]. 29 | 30 | These two style rules focuses on using dashes to separate words in the descriptive name, and dots to 31 | separate name from the type. Angular typically has the following types: 32 | 33 | - `service` - Abstract Service 34 | - `component` - Angular Components 35 | - `pipe` - Angular Pipe 36 | - `module` - Angular Module 37 | - `directive` - Angular Directive 38 | 39 | At Bitwarden we also use a couple of more types: 40 | 41 | - `.api` - Api Model 42 | - `.data` - Data Model (used for serializing domain model) 43 | - `.view` - View Model (decrypted domain model) 44 | - `.export` - Export Model 45 | - `.request` - Api Request 46 | - `.response` - Api Response 47 | - `.type` - Enum 48 | 49 | The class names are expected to use the suffix as part of their class name as well. I.e. a service 50 | implementation will be named `FolderService`, a request model will be named `FolderRequest`. 51 | 52 | ### Positive consequences 53 | 54 | - Since most of our code is written in Angular, we should use the Angular coding style guide. 55 | - Not using camelCase will avoid issues with case-sensitive file systems. 56 | 57 | ### Negative consequences 58 | 59 | - We need to update a lot of files to be consistent. 60 | 61 | [naming]: https://angular.io/guide/styleguide#naming 62 | [style-02-02]: https://angular.io/guide/styleguide#style-02-02 63 | [style-02-03]: https://angular.io/guide/styleguide#style-02-03 64 | -------------------------------------------------------------------------------- /docs/architecture/adr/0004-refactor-state-service.md: -------------------------------------------------------------------------------- 1 | --- 2 | adr: "0004" 3 | status: Accepted 4 | date: 2022-06-30 5 | tags: [clients, angular] 6 | --- 7 | 8 | # 0004 - Refactor State Service 9 | 10 | 11 | 12 | ## Context and problem statement 13 | 14 | This ADR builds upon [Adopt Observable Data Services for Angular][observable]. 15 | 16 | The Bitwarden clients currently have a quite complex state architecture, where all the state is 17 | handled by a single service. This has resulted in everything being tightly coupled to the 18 | `StateService` essentially making it a God object. 19 | 20 | Additionally any service or component can directly access any state using the state service. Which 21 | makes it difficult to follow the state lifecycle of each data type, and introduces uncertainty in 22 | how the data is accessed. 23 | 24 | ## Decision outcome 25 | 26 | We should refactor the state service to be a generic storage container. 27 | 28 | - Good: Eliminates the "good" functionality of the state service 29 | - Good: State is maintained by the service which owns it. 30 | - Good: No arbitrary access of data. 31 | - Bad: Brings back arbitrary keys that must be unique. 32 | 33 | ### Example 34 | 35 | ```ts 36 | interface StateService { 37 | getAccountData: (account: Account, key: string, options?: StorageOptions) => Promise; 38 | saveAccountData: (account: Account, key: string, options?: StorageOptions) => Promise; 39 | deleteAccountData: (account: Account, key: string, options?: StorageOptions) => Promise; 40 | 41 | deleteAllAccountData: (account: Account); 42 | 43 | getGlobalData: (key: string, options?: StorageOptions) => Promise; 44 | saveGlobalData: (key: string, options?: StorageOptions) => Promise; 45 | deleteGlobalData: (key: string, options?: StorageOptions) => Promise; 46 | } 47 | ``` 48 | 49 | ```ts 50 | // StorageKey is an internal constant, and should be prefixed with the domain. 51 | // DO NOT EXPORT IT. 52 | const StorageKey = "organizations"; 53 | 54 | class OrganizationService { 55 | async save(organizations: { [adr: string]: OrganizationData }) { 56 | await this._stateService.saveAccountData(this._activeAccount, StorageKey, organizations); 57 | await this._organizations$.next(await this.decryptOrgs(this._activeAccount, organizations)); 58 | } 59 | } 60 | ``` 61 | 62 | [observable]: ./0003-observable-data-services.md 63 | -------------------------------------------------------------------------------- /docs/architecture/deep-dives/database-replicas.md: -------------------------------------------------------------------------------- 1 | # Read-Only Database Replicas 2 | 3 | ## Context 4 | 5 | Bitwarden utilizes 6 | [Azure SQL Hyperscale](https://learn.microsoft.com/en-us/azure/azure-sql/database/service-tier-hyperscale?view=azuresql) 7 | and its 8 | [high-availability replica](https://learn.microsoft.com/en-us/azure/azure-sql/database/service-tier-hyperscale-replicas?view=azuresql#high-availability-replica) 9 | available as a _read_ replica. This allows Bitwarden to double the max worker limit (along with 10 | compute, memory, and network throughput) without needing to scale up the primary database. The HA 11 | replica replicates the primary instance by mirroring the transaction log records. 12 | 13 | ## Vision 14 | 15 | More read-only capabilities should be used in conjunction with read-only replicas, especially after 16 | stored procedures have been tuned and there are prominent performance bottlenecks relating to 17 | read-only queries. 18 | 19 | ## Usage 20 | 21 | We currently use the read-only replica in two areas: 22 | 23 | 1. [Methods within the Dapper repositories](https://github.com/search?q=repo%3Abitwarden%2Fserver+%22using+%28var+connection+%3D+new+SqlConnection%28ReadOnlyConnectionString%29%29%22&type=code) 24 | with `using (var connection = new SqlConnection(ReadOnlyConnectionString))` defined. 25 | 2. Data engineering pipelines that require direct connection to the database. 26 | 27 | ## Gotchas / Considerations 28 | 29 | - [CAP Theorem](https://en.wikipedia.org/wiki/CAP_theorem) applies here. Microsoft does not 30 | guarantee data consistency and 31 | [propagation latency](https://learn.microsoft.com/en-us/azure/azure-sql/database/read-scale-out?view=azuresql#data-consistency) 32 | could vary greatly. For business logic that need consistency, read-only replicas are not a viable 33 | solution. 34 | - Lack of observability -- currently there is limited visibility into query performance metrics as 35 | well as resource utilization on the replica itself. 36 | - Long-running queries on read-only replicas can cause 37 | [blocking](https://learn.microsoft.com/en-us/azure/azure-sql/database/read-scale-out?view=azuresql#long-running-queries-on-read-only-replicas). 38 | - The HA replica is not a backup and should not be treated as such. If a destructive migration had 39 | been run on the primary instance it will be reflected on the HA replica. DR procedures will have 40 | to be carried out in this scenario and there will be data loss. 41 | -------------------------------------------------------------------------------- /docs/contributing/code-style/web/tailwind.md: -------------------------------------------------------------------------------- 1 | # Tailwind 2 | 3 | Before starting working with Tailwind we recommend that you get familiar with 4 | [Utility-First Fundamentals](https://tailwindcss.com/docs/utility-first). The blog article 5 | [_CSS Utility Classes and "Separation of Concerns"_](https://adamwathan.me/css-utility-classes-and-separation-of-concerns/) 6 | is also a good read to better understand the motivation and goals behind Utility first CSS 7 | frameworks. 8 | 9 | We also recommend using the search functionality of the 10 | [tailwind documentation](https://tailwindcss.com/) to lookup classes and examples. 11 | 12 | ## Tailwind at Bitwarden 13 | 14 | We have defined our own 15 | [tailwind config](https://github.com/bitwarden/clients/blob/main/libs/components/tailwind.config.base.js), 16 | which heavily restricts the color usage as a way to support multiple themes. To achieve this we use 17 | [CSS variables](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties) in 18 | combination with the tailwind config. This allows us to support more than the built in dark/light 19 | support in Tailwind. 20 | 21 | To this effort we heavily discourage the use of 22 | [arbitrary values](https://tailwindcss.com/docs/adding-custom-styles#using-arbitrary-values) with 23 | the only exception being to support existing Bootstrap styles. In which case it should be documented 24 | and added as a tech debt to be tackled as part of the migration away from Bootstrap. 25 | 26 | :::note 27 | 28 | All Tailwind classes need to be prefixed by `tw-` as defined in the tailwind config. 29 | 30 | Example usage: `
...
` 31 | 32 | ::: 33 | 34 | ### Components 35 | 36 | Since Tailwind is a Utility-First CSS framework to avoid code duplication which would make the 37 | design difficult to maintain we make heavy use of Angular Components to encapsulate isolated design 38 | blocks. In most cases these blocks are 39 | [presentational components](https://angular-training-guide.rangle.io/state-management/ngrx/component_architecture). 40 | 41 | ### Component Library 42 | 43 | One of the engineering initiatives at Bitwarden is the 44 | [Component Library](https://github.com/bitwarden/clients/tree/main/libs/components) which aims to 45 | encapsulate the most commonly used core components. 46 | 47 | #### Storybook 48 | 49 | We use [Storybook](https://storybook.js.org/) to develop components in isolation. To launch 50 | storybook run the `npm run storybook` command in the root of `clients` repository. 51 | -------------------------------------------------------------------------------- /docs/getting-started/server/troubleshooting.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 10 3 | --- 4 | 5 | # Troubleshooting 6 | 7 | ## macOS 8 | 9 | ### AppleCFErrorCryptographicException 10 | 11 | Error: 12 | `Interop.AppleCrypto.AppleCFErrorCryptographicException: The operation couldn't be completed.` 13 | 14 | There could be a couple fixes to this problem, the most likely is you need to restart your device. 15 | 16 | If that doesn't work, you could try force unlocking your login keychain with: 17 | 18 | ```bash 19 | security -v unlock-keychain /Users/$USER/Library/Keychains/login.keychain 20 | ``` 21 | 22 | If that doesn't work either, Mac can sometimes set trust settings for your certificates as admin 23 | instead of as user. If you don't see your certificates by running: 24 | 25 | ```bash 26 | security dump-trust-settings 27 | ``` 28 | 29 | Then try running: 30 | 31 | ```bash 32 | security dump-trust-settings -d 33 | ``` 34 | 35 | If your certificates show up here you will have to export the trust settings to user using the 36 | [security command](https://ss64.com/osx/security.html), as there is no way to specify this in the 37 | Keychain Access Application. 38 | 39 | To do this, run `security trust-settings-export -d ` to export the admin certificates. 40 | Then import them into user with `security trust-settings-import `. 41 | 42 | See the related [Github Issue](https://github.com/dotnet/runtime/issues/59703) for more information. 43 | 44 | ### Error NU1403: Package content hash validation failed 45 | 46 | Following commands should fix the problem: 47 | 48 | ```bash 49 | dotnet nuget locals all --clear 50 | git clean -xfd 51 | git rm \*\*/packages.lock.json -f 52 | dotnet restore 53 | ``` 54 | 55 | For more details read 56 | [https://github.com/NuGet/Home/issues/7921#issuecomment-478152479](https://github.com/NuGet/Home/issues/7921#issuecomment-478152479) 57 | 58 | ## Windows 59 | 60 | ### An attempt was made to access a socket in a way forbidden by its access permissions 61 | 62 | This error typically occurs when the application attempts to use a port that is either already in 63 | use or reserved. Newer Windows with Hyper-V reserves many ports 50 000+. 64 | 65 | Luckily it’s possible to manually mark the ports as reversed to prevent Hyper-V from reserving them. 66 | Start a CMD session in an elevated mode and run the following commands, and restart the computer. 67 | 68 | ```bash 69 | net stop winnat 70 | 71 | netsh int ipv4 add excludedportrange protocol=tcp startport= numberofports=1 store=persistent 72 | 73 | net start winnat 74 | ``` 75 | -------------------------------------------------------------------------------- /docs/getting-started/business/directory-connector/index.mdx: -------------------------------------------------------------------------------- 1 | import Tabs from "@theme/Tabs"; 2 | import TabItem from "@theme/TabItem"; 3 | 4 | # Directory Connector 5 | 6 | The Bitwarden Directory Connector is a a desktop application used to sync your Bitwarden enterprise 7 | organization to an existing directory of users and groups. 8 | 9 | Directory Connector receives fewer updates than the main clients. To reduce maintenance costs, it 10 | has its own copy of our shared Javascript libraries (formerly known as jslib), located in the 11 | `jslib` subdirectory. 12 | 13 | ## Requirements 14 | 15 | - [Node.js](https://nodejs.org/) v20 16 | 17 | - Windows users: To compile the native node modules used in the app you will need the Visual C++ 18 | toolset, available through the standard Visual Studio installer (recommended) or by installing 19 | `windows-build-tools` through `npm`. See more at 20 | [Compiling native Addon modules](https://github.com/Microsoft/nodejs-guidelines/blob/master/windows-environment.md#compiling-native-addon-modules). 21 | 22 | # Build Instructions 23 | 24 | 1. Clone the repository: 25 | 26 | ```bash 27 | git clone https://github.com/bitwarden/directory-connector.git 28 | ``` 29 | 30 | 2. Install the dependencies: 31 | 32 | ```bash 33 | cd directory-connector 34 | npm ci 35 | ``` 36 | 37 | 3. Run the app: 38 | 39 | 40 | 41 | 42 | 43 | ```bash 44 | npm run electron 45 | ``` 46 | 47 | 48 | 49 | 50 | 51 | ```bash 52 | npm run build:cli:watch 53 | ``` 54 | 55 | You can then run commands from the `./build-cli` folder: 56 | 57 | ```bash 58 | cd ./build-cli 59 | 60 | node ./bwdc.js --help 61 | 62 | # Test sync 63 | node ./bwdc.js test 64 | 65 | # Real sync 66 | node bwdc.js sync 67 | ``` 68 | 69 | 70 | 71 | 72 | 73 | ## Syncing from a directory service 74 | 75 | To properly test Directory Connector, you'll need a directory to sync. We have instructions for 76 | setting up: 77 | 78 | - an [Open LDAP Docker image](./open-ldap.md) (recommended) 79 | 80 | - [JumpCloud](./jumpcloud.md) 81 | 82 | These are both LDAP directory services. If you need to test another type, you should be able to find 83 | a platform offering a free tier of that service. 84 | 85 | 86 | 87 | If you need to test Active Directory, contact the Integration Engineering team for remote access to 88 | a test AD instance. 89 | 90 | 91 | -------------------------------------------------------------------------------- /docs/getting-started/clients/web-vault/webauthn.mdx: -------------------------------------------------------------------------------- 1 | import Tabs from "@theme/Tabs"; 2 | import TabItem from "@theme/TabItem"; 3 | import CodeBlock from "@theme/CodeBlock"; 4 | 5 | # WebAuthn 6 | 7 | :::info 8 | 9 | This page contains additional setup instructions if you need to test WebAuthn authentication 10 | locally. 11 | 12 | ::: 13 | 14 | The [WebAuthn](https://webauthn.guide/) spec requires that a valid domain name is used. Since 15 | `localhost` does not satisfy this requirement, you need to configure your local instance to use a 16 | domain name. 17 | 18 | There are multiple ways of doing this. However, the simplest method is to modify the operating 19 | system's host file with a loopback to `127.0.0.1`. 20 | 21 | ## Configuration 22 | 23 | Webpack protects against DNS rebind attacks by blocking hostnames by default. However, we can 24 | specify specific hostnames to be allowed in the web environment configuration JSON files. 25 | 26 | 1. Create a `local.json` file in the `web/config/` folder 27 | 2. Add "bitwarden.test" as an `allowedHosts` entry: 28 | 29 | ```json 30 | { 31 | "dev": { 32 | "allowedHosts": ["bitwarden.test"] 33 | } 34 | } 35 | ``` 36 | 37 | :::note 38 | 39 | If you are running the app, you must restart it for the config change to take effect. 40 | 41 | ::: 42 | 43 | ### Hosts file 44 | 45 | :::note 46 | 47 | You will need administrator access to edit this file. 48 | 49 | ::: 50 | 51 | The location of the host file differs slightly between operating systems. 52 | 53 | 54 | 55 | {`C:\\Windows\\System32\\drivers\\etc\\hosts`} 56 | 57 | 58 | {`/etc/hosts`} 59 | 60 | 61 | 62 | Open the file with the text editor of your choice. And append the following line. 63 | 64 | ```plain 65 | 127.0.0.1 bitwarden.test 66 | ``` 67 | 68 | ### User Secrets 69 | 70 | In addition to modifying the host file, the [user secret](../../../contributing/user-secrets.md) 71 | `globalSettings:baseServiceUri:vault` for API and Identity projects in the server needs to be 72 | created or updated to reflect the domain name. For example: 73 | 74 | ```json 75 | { 76 | ... 77 | "globalSettings":{ 78 | "baseServiceUri":{ 79 | "vault":"https://bitwarden.test:8080" 80 | } 81 | }, 82 | ... 83 | } 84 | ``` 85 | 86 | ### Testing 87 | 88 | You should now be ready to test WebAuthn on your local instance by going to 89 | [https://bitwarden.test:8080](https://bitwarden.test:8080). 90 | -------------------------------------------------------------------------------- /docs/architecture/deep-dives/autofill/form-submission-detection.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 3 3 | --- 4 | 5 | # Form Submission Detection 6 | 7 | ## Why is Form submission detection important? 8 | 9 | Form submission detection is important for several reasons: 10 | 11 | - It allows the Bitwarden extension to prompt the user to add new credentials to their vault, 12 | increasing the user's footprint in Bitwarden. 13 | - It allows us to accurately handle password change detection and help the user keep their data in 14 | sync, providing a better user experience. 15 | 16 | ## Why is Form submission detection difficult? 17 | 18 | The reason why the detection of forms and their submission is difficult because of the flexibility 19 | of modern progressive web apps (PWAs) and single-page applications (SPAs). In classic HTML, a 20 | `
` element is defined along with a `` that submits all of the form data to the user. 21 | 22 | On the other hand, in modern applications a `` element can be used to collect user data, but a 23 | completely separate API request sends the form data to the server. For a good overview of the 24 | complexities, see 25 | [this](https://developer.mozilla.org/en-US/docs/Learn/Forms/Sending_forms_through_JavaScript) 26 | excellent documentation. 27 | 28 | ## What is involved in Form submission detection? 29 | 30 | ### Initial Collection 31 | 32 | We must accurately collect the page details to capture the fact that there are forms on the page. 33 | 34 | ### DOM Manipulation 35 | 36 | We must handle cases where the application is modifying the DOM based on user interaction. 37 | 38 | ### Submission Detection 39 | 40 | We must be able to detect when a Form is submitted so that we can properly notify the user to save 41 | their credentials. 42 | 43 | ## How is this handled today? 44 | 45 | The form submission detection is handled in the `notificationBar.ts` content script. 46 | 47 | ### Detecting DOM changes for new forms 48 | 49 | A `MutationObserver` is attached to the window and runs every 1000 milliseconds. It observes the DOM 50 | for any changes that include a form element has not yet been collected (using the 51 | `data-bitwarden-watching` data element on the form to see whether it has been collected). 52 | 53 | If a form element is detected that is new, the [Page Detail collection](collecting-page-details.md) 54 | process is triggered to retrieve the page details. 55 | 56 | ### Detecting form submission 57 | 58 | Form submission is detected by attaching an event to each form `submit()` button on the DOM. This is 59 | done upon receipt of the `notificationBarPageDetails` command by the `notificationBar.ts` content 60 | script. 61 | -------------------------------------------------------------------------------- /docs/contributing/pull-requests/chromatic.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 3 3 | sidebar_custom_props: 4 | access: bitwarden 5 | --- 6 | 7 | # UI Review - Chromatic 8 | 9 | We use a tool called [Chromatic][chromatic] to run automated snapshot tests for all Storybook 10 | stories. This allows us to quickly catch design regressions in an automated fashion. As part of this 11 | we use Chromatic to also review and approve the visual changes. Members of the Bitwarden GitHub 12 | organization can login to Chromatic using their GitHub account. 13 | 14 | ## Checks 15 | 16 | Chromatic splits the review process into two parts, _UI Tests_ and _UI Review_. These appear as two 17 | different checks on the PR and need to be handled differently. The expectations for handling each 18 | one are broken down in detail below. 19 | 20 | ### UI Tests 21 | 22 | > UI tests capture a visual snapshot of every story in a cloud browser environment. Whenever you 23 | > push code, Chromatic generates a new set of snapshots and compares them against baselines. If 24 | > there are visual changes, you verify if they’re intentional. 25 | > 26 | > https://www.chromatic.com/docs/test 27 | 28 | ### UI Review 29 | 30 | > UI tests protect you from accidental regressions. But, before you ship, you’ll want to invite 31 | > developers, designers, and PMs to review the UI to make sure it’s correct. 32 | > 33 | > UI Review creates a changeset of the exact visual changes introduced by a PR. You assign reviewers 34 | > who can comment and request tweaks on changes that aren’t quite right. Think of it like a code 35 | > review, but for your UI. 36 | > 37 | > https://www.chromatic.com/docs/review 38 | 39 | ## Reviewing 40 | 41 | Chromatic will mark a pull request as pending if there are visual changes. Each pull request author 42 | is responsible for reviewing the _UI Tests_ results in Chromatic and approve that the changes are 43 | intentional. 44 | 45 | The tests can easily be accessed by clicking on the **UI Tests** check in the pull request. 46 | 47 | ![Chromatic UI Tests](ui-tests.png) 48 | 49 | The action required for _UI Review_ depends on the failing stories: 50 | 51 | - Component Library should be reviewed by the design department, which is done by requesting a 52 | review of `bitwarden/dept-design` in GitHub. 53 | - Other changes should be reviewed by the reviewing developer(s). 54 | 55 | The review can be accessed by clicking on the **UI Review** check. 56 | 57 | ![Chromatic UI Review & Publish](publish-review.png) 58 | 59 | It's also possible to browse the Storybook for the pull request by clicking on the **Storybook 60 | Publish** check. 61 | 62 | [chromatic]: https://www.chromatic.com/ 63 | -------------------------------------------------------------------------------- /docs/index.mdx: -------------------------------------------------------------------------------- 1 | # Overview 2 | 3 |
4 |
5 |

Welcome!

6 |

7 | The Bitwarden Contributing Docs contains all the information you need to get started 8 | contributing to Bitwarden! 9 |

10 |
11 |
12 | 13 | ## Getting started 14 | 15 | It's likely the first thing you'll need to do is set up a local development environment; to do so, 16 | we recommend progressing through the documentation in the following order. 17 | 18 | 1. Install all the recommended [Tools and Libraries](./getting-started/tools/index.md) for 19 | development. 20 | 2. Follow the [Server Setup Guide](./getting-started/server/guide.md) to setup your local server and 21 | related services 22 | 3. Build and run each [Clients](./getting-started/clients/index.md) from source and connect them to 23 | your local server 24 | 4. Read our [Contributing Guidelines](./contributing/index.md) and 25 | [Coding Style](./contributing/code-style/index.md) 26 | 27 | ## Help! 28 | 29 | If you're having trouble following these instructions, don't panic. 30 | 31 | 32 | 33 | - The [Bitwarden Help Center](https://bitwarden.com/help/) is an excellent resource to learn about 34 | the different features of our software and configuration options. 35 | - If you're new, ask your onboarding buddy for help! This is an expected part of our onboarding 36 | buddy program 37 | - Ask in the `#team-eng` Slack channel for general setup help 38 | - Ask in the `#code` Slack channel for questions about coding architecture, patterns and problems 39 | 40 | 41 | 42 | 43 | 44 | - The [Bitwarden Help Center](https://bitwarden.com/help/) is an excellent resource to learn about 45 | the different features of our software and configuration options. 46 | - Ask for help from the community in the [Community Forums](https://community.bitwarden.com) 47 | - Ask the dev team on the official [Gitter chat](https://gitter.im/bitwarden/Lobby) 48 | 49 | 50 | 51 | ## Help make this documentation better 52 | 53 | We want a culture of shared knowledge, and documentation is one of the best ways to do that. 54 | 55 | - If you have trouble following some instructions, please improve them. 56 | - If you add or change a feature that requires setup for development, please update the 57 | documentation. 58 | - If you're reviewing a PR that requires a change to this documentation, ask the author to do that 59 | as part of your review. 60 | 61 | To contribute to this documentation, follow the instructions in the [Contributing Docs 62 | repository][repo]. 63 | 64 | [repo]: https://github.com/bitwarden/contributing-docs/ 65 | -------------------------------------------------------------------------------- /docs/getting-started/server/tunnel.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_custom_props: 3 | access: bitwarden 4 | sidebar_position: 5 5 | --- 6 | 7 | # Ingress Tunnels 8 | 9 | Sometimes it can be beneficial to allow other team members access to your locally running Bitwarden 10 | instance. Usually this involves opening ports in firewalls, and even then you can usually only 11 | connect through the IP address. 12 | 13 | ## Configure web vault 14 | 15 | If the goal is to expose the local web vault (which includes access to most services) then the web 16 | vault needs to be configured to not use `https` and instead serve it’s content unencrypted. 17 | 18 | Open `webpack.config.js` and comment out the following lines from `const devServer = {` 19 | 20 | ```ts 21 | https: { 22 | key: fs.readFileSync('dev-server' + certSuffix + '.pem'), 23 | cert: fs.readFileSync('dev-server' + certSuffix + '.pem'), 24 | }, 25 | ``` 26 | 27 | And add the domain to `allowedHosts` in `local.json`: 28 | 29 | ```json 30 | { 31 | "allowedHosts": [""] 32 | } 33 | ``` 34 | 35 | ## Cloudflare Argo Tunnels 36 | 37 | An alternative method which provides a few benefits are to use 38 | [Cloudflare Argo Tunnels](https://www.cloudflare.com/products/tunnel/). Which works by setting up a 39 | local tunnel between Cloudflare and your local machine, which provides access to a locally running 40 | service. The tunnel can additionally be placed behind a cloudflare proxy which provides a valid SSL 41 | certificate, making it perfect for testing with the mobile applications. 42 | 43 | ### Setup 44 | 45 | 1. [Download](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/) 46 | and install `cloudflared` 47 | 2. Start you local web server and take note of the `$PORT` it is running on 48 | 3. Start the tunnel using `cloudflared tunnel --url http://127.0.0.1:$PORT` 49 | 50 | Cloudflare will build you a tunnel and provide the url to it: `*.trycloudflare.com`. Wait for the 51 | DNS to start resolving before trying to access it. 52 | 53 | **Note**, anyone with this URL can access the forwarded URL on your machine. 54 | 55 | ## Ngrok 56 | 57 | 1. Sign up for a free ngrok account 58 | 59 | 2. Follow the [official instructions](https://dashboard.ngrok.com/get-started/setup) to download. Or 60 | install using [brew](https://formulae.brew.sh/cask/ngrok) which supports multiple instances per 61 | account. 62 | 3. Expose your local port using ngrok: 63 | 64 | ```bash 65 | ngrok http 66 | ``` 67 | 68 | 4. ngrok's interface should display a "Forwarding" url, for example: 69 | 70 | ``` 71 | https://abcd-123-456-789.au.ngrok.io -> http://localhost: 72 | ``` 73 | 74 | 5. Verify that the forwarding url works by navigating to the forwarding url with `/alive` on the 75 | end. For example, `https://abcd-123-456-789.au.ngrok.io/alive`. 76 | 77 | :::note 78 | 79 | Anyone with this URL can access the forwarded URL on your machine. 80 | 81 | ::: 82 | -------------------------------------------------------------------------------- /docs/architecture/deep-dives/autofill/shadow-dom.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 4 3 | --- 4 | 5 | # Shadow DOM 6 | 7 | ## Introduction 8 | 9 | The Shadow DOM API allows a separate, encapsulated DOM tree to be embedded in a page. 10 | 11 | [From MDN](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM): 12 | 13 | > An important aspect of web components is encapsulation — being able to keep the markup structure, 14 | > style, and behavior hidden and separate from other code on the page so that different parts do not 15 | > clash, and the code can be kept nice and clean. The Shadow DOM API is a key part of this, 16 | > providing a way to attach a hidden separated DOM to an element. 17 | > 18 | > [...] 19 | > 20 | > Shadow DOM allows hidden DOM trees to be attached to elements in the regular DOM tree — this 21 | > shadow DOM tree starts with a shadow root, underneath which you can attach any element, in the 22 | > same way as the normal DOM. 23 | 24 | The Shadow DOM API is relevant to our autofill logic, because common DOM query methods such as 25 | `document.querySelector` and `document.querySelectorAll` do not return results that are located in a 26 | Shadow DOM. 27 | 28 | The shadow root node has a `mode` property, which can be set to `"open"` or `"closed"`. The `mode` 29 | is intended to (dis)allow access to the Shadow DOM tree by the main DOM, although some browsers 30 | provide specific APIs which can ignore this property. 31 | 32 | ## How we handle Shadow DOMs 33 | 34 | Instead of using `querySelector` methods, we implement similar logic using the 35 | [TreeWalker](https://developer.mozilla.org/en-US/docs/Web/API/TreeWalker) API. The TreeWalker API 36 | provides an interface to traverse nodes individually, which means we can run arbitrary logic against 37 | each node. In practice, we check each visited node for two criteria: 38 | 39 | 1. Whether the node satisfies the filter callback provided - this allows us to filter for specific 40 | node(s), as with `querySelector`, but using a callback with full access to the `Element` object 41 | instead of a selector string 42 | 2. Whether the node is a shadow root 43 | 44 | If the node is a shadow root, we try to recursively descend into it using the browser API available: 45 | 46 | - **Chrome: ** 47 | [chrome.dom.openOrClosedShadowRoot](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/dom/openOrClosedShadowRoot) - 48 | ignores the `mode` property and works for open and closed shadow roots 49 | - **Firefox: ** 50 | [Element.openOrClosedShadowRoot](https://developer.mozilla.org/en-US/docs/Web/API/Element/openOrClosedShadowRoot) - 51 | ignores the `mode` property and works for open and closed shadow roots 52 | - **Safari and others: ** 53 | [Element.shadowRoot](https://developer.mozilla.org/en-US/docs/Web/API/Element/shadowRoot) - 54 | respects the `mode` property and will only work for `"open"` shadow roots. We fall back to this 55 | method if the other APIs are not available 56 | -------------------------------------------------------------------------------- /src/contexts/devMode.tsx: -------------------------------------------------------------------------------- 1 | // Based on https://github.com/facebook/docusaurus/blob/main/packages/docusaurus-theme-common/src/contexts/colorMode.tsx 2 | import React, { useState, useEffect, useContext, useMemo, type ReactNode } from "react"; 3 | import { createStorageSlot, ReactContextError } from "@docusaurus/theme-common"; 4 | import ExecutionEnvironment from "@docusaurus/ExecutionEnvironment"; 5 | import { useLocation } from "@docusaurus/router"; 6 | 7 | type ContextValue = { 8 | readonly devMode: DevMode; 9 | readonly setDevMode: (devMode: DevMode) => void; 10 | }; 11 | 12 | const Context = React.createContext(undefined); 13 | 14 | const DevModeStorageKey = "bitwarden-dev"; 15 | const DevModeStorage = createStorageSlot(DevModeStorageKey); 16 | 17 | export const DevModes = { 18 | community: "community", 19 | bitwarden: "bitwarden", 20 | } as const; 21 | 22 | export type DevMode = (typeof DevModes)[keyof typeof DevModes]; 23 | 24 | const coerceToDevMode = (devMode?: string | null): DevMode => 25 | devMode === DevModes.bitwarden ? DevModes.bitwarden : DevModes.community; 26 | 27 | const storeDevMode = (newDevMode: DevMode) => { 28 | DevModeStorage.set(coerceToDevMode(newDevMode)); 29 | }; 30 | 31 | const getInitialDevMode = (): DevMode => 32 | ExecutionEnvironment.canUseDOM 33 | ? coerceToDevMode(DevModeStorage.get()) 34 | : coerceToDevMode("community"); 35 | 36 | function useContextValue(): ContextValue { 37 | const [devMode, setDevModeState] = useState(getInitialDevMode()); 38 | 39 | const setDevMode = (newDevMode: DevMode) => { 40 | setDevModeState(newDevMode); 41 | storeDevMode(newDevMode); 42 | }; 43 | 44 | const { search } = useLocation(); 45 | const searchParams = new URLSearchParams(search); 46 | const param = searchParams.get("bitwarden"); 47 | 48 | useEffect(() => { 49 | if (param != null) { 50 | setDevMode("bitwarden"); 51 | } 52 | }, [param]); 53 | 54 | useEffect(() => { 55 | const onChange = (e: StorageEvent) => { 56 | if (e.key !== DevModeStorageKey) { 57 | return; 58 | } 59 | const storedDevMode = DevModeStorage.get(); 60 | if (storedDevMode !== null) { 61 | setDevMode(coerceToDevMode(storedDevMode)); 62 | } 63 | }; 64 | window.addEventListener("storage", onChange); 65 | return () => window.removeEventListener("storage", onChange); 66 | }, [setDevMode]); 67 | 68 | return useMemo( 69 | () => ({ 70 | devMode, 71 | setDevMode, 72 | }), 73 | [devMode, setDevMode], 74 | ); 75 | } 76 | 77 | export function DevModeProvider({ children }: { children: ReactNode }): JSX.Element { 78 | const value = useContextValue(); 79 | return {children}; 80 | } 81 | 82 | export function useDevMode(): ContextValue { 83 | const context = useContext(Context); 84 | if (context == null) { 85 | throw new ReactContextError("DevModeProvider"); 86 | } 87 | return context; 88 | } 89 | -------------------------------------------------------------------------------- /docs/architecture/sdk/dependencies.md: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | 3 | The SDK is structured as several standalone crates. Each crate can have their own dependencies and 4 | versions of dependencies. It's worth reading the [Dependency Resolution][dep-res] article in the 5 | Cargo Book to better understand how dependencies are resolved in Rust. 6 | 7 | ## Avoid adding dependencies 8 | 9 | The SDK takes a conservative approach to adding dependencies. The number of direct and indirect 10 | dependencies you have are directly related to the time it takes for a clean build. Dependencies also 11 | permanently increase the base maintenance cost of the project as they require frequent updates to 12 | keep up with security patches and new features. 13 | 14 | To that effort we **must** be conservative with adding dependencies. And we ask that you consider 15 | the following when evaluating a new dependency: 16 | 17 | - Do we already have a dependency or transient dependency that does the same thing? If so we 18 | _should_ use that instead. 19 | - How complex is the desired functionality? 20 | - How much time would it take to implement the functionality yourself? 21 | - Is it likely to change? 22 | - How much of the dependency will we be using? 23 | - Are you only using a small part of the dependency? 24 | - Are you using the dependency in a way that is not intended? 25 | - How well maintained is the dependency? 26 | - How often are new versions released? 27 | - How many open issues does the dependency have? 28 | - Audit the dependency tree. 29 | - How many dependencies does the dependency have? 30 | - How many of those dependencies are we already using? 31 | 32 | If we only ever need a small fraction of the functionality we should consider implementing it 33 | ourselves. 34 | 35 | ## Dependency ranges 36 | 37 | For any library we always use ranges for dependencies. This allows other crates to depend on the the 38 | SDK without requiring the exact same versions. The Cargo lockfile ensures dependencies are 39 | consistent between builds. 40 | 41 | ### Explicit ranges 42 | 43 | We use explicit ranges for dependencies, i.e. we specify the minimum and maximum version of a 44 | dependency. This helps avoiding confusion around how Cargo expands implicit versions. 45 | 46 | ```toml 47 | # Bad 48 | serde = "1.0.0" 49 | serde = "1" 50 | serde = ">1" 51 | 52 | # Good 53 | serde = ">1.0, <2.0" 54 | ``` 55 | 56 | ## Workspace dependencies 57 | 58 | To provide a more developer-friendly experience for managing dependencies we define commonly used 59 | dependencies in our workspace `Cargo.toml`. This allow us to update dependencies across the 60 | workspace by modifying a single file. 61 | 62 | Internal dependencies i.e. dependencies that are part of the same workspace **must** be defined 63 | using workspace definitions. 64 | 65 | ```toml 66 | # Bad 67 | bitwarden-core = { version = "1.0", path = "../bitwarden-core" } 68 | 69 | # Good 70 | bitwarden-core = { workspace = true } 71 | ``` 72 | 73 | [dep-res]: https://doc.rust-lang.org/cargo/reference/resolver.html 74 | -------------------------------------------------------------------------------- /docs/getting-started/business/directory-connector/jumpcloud.md: -------------------------------------------------------------------------------- 1 | # JumpCloud 2 | 3 | [JumpCloud](https://jumpcloud.com/) provides an LDAP-as-a-service with a free tier that you can use 4 | for testing. 5 | 6 | :::info 7 | 8 | The JumpCloud free tier is limited to 10 users and you won't get the nice pre-generated data you get 9 | with the [OpenLDAP](./open-ldap.md) setup. 10 | 11 | ::: 12 | 13 | ## Setup JumpCloud 14 | 15 | 1. Create an account with JumpCloud and log in 16 | 17 | 2. Create a user and bind that user to a directory. There should be a default directory you can use 18 | for this called JumpCloud LDAP. Refer to the 19 | [JumpCloud help documentation](https://support.jumpcloud.com/support/s/article/using-jumpclouds-ldap-as-a-service1#createuser) 20 | for instructions 21 | 22 | 3. Create an Administrator user and bind that user to the same directory. You'll use this user to 23 | authenticate Directory Connector with JumpCloud 24 | 25 | ## Configure Directory Connector 26 | 27 | 1. Run the Directory Connector Electron app (see the [build instructions](./index.mdx)) 28 | 29 | 2. Log in using the [organization API key](https://bitwarden.com/help/public-api/#authentication) 30 | 31 | 3. Use the configuration settings below 32 | 33 | ### Directory Settings 34 | 35 | For these settings, you'll need your JumpCloud organization ID. You can find this in the JumpCloud 36 | Admin Console → User Authentication → LDAP → [your LDAP server]. 37 | 38 | - **Type**: Active Directory / LDAP 39 | 40 | - **Server Hostname**: ldap.jumpcloud.com 41 | 42 | - **Server Port**: 636 43 | 44 | - **Root Path**: o=[Your JumpCloud Organization ID],dc=jumpcloud,dc=com 45 | 46 | - **This server uses Active Directory:** [unchecked] 47 | 48 | - **This server pages search results:** [unchecked] 49 | 50 | - **This server uses an encrypted connection:** [checked] 51 | - **Use SSL** [checked] 52 | 53 | - **Do not verify server certificates** [checked] 54 | 55 | - **Username**: uid=[Admin User],ou=Users,o=[Your JumpCloud organization ID],dc=JumpCloud,dc=com 56 | 57 | - **Password**: [Admin User's password] 58 | 59 | ### Sync Settings 60 | 61 | - **Sync Users**: [checked] 62 | 63 | - **User Path**: ou=Users,o=[Your JumpCloud Organization ID] 64 | 65 | - **User Object Class**: inetOrgPerson 66 | 67 | - **User Email Attribute**: mail 68 | 69 | - **Sync Groups**: [checked] 70 | 71 | - **Group Path**: o=[Your JumpCloud Organization ID] 72 | 73 | - **Group Object Class**: groupOfNames 74 | 75 | - **Group Name Attribute**: memberOf 76 | 77 | ## Sync 78 | 79 | :::caution 80 | 81 | When you do a real sync, invitation emails will be sent out to all synced users. Make sure that 82 | you're using [Mailcatcher](../../server/guide.md#mailcatcher) so you don't send live emails. 83 | 84 | ::: 85 | 86 | 1. Click the "Test Now" button in Directory Connector. You should get a list of users 87 | 88 | 2. When you're ready, click "Sync Now" to perform a real sync. You should receive a confirmation 89 | message in Directory Connector, and see the newly invited users in the web vault 90 | -------------------------------------------------------------------------------- /docs/architecture/deep-dives/authentication/two-factor-auth.md: -------------------------------------------------------------------------------- 1 | # Two-Factor Authentication 2 | 3 | When a user account requires two-factor authentication (2FA), the normal Bitwarden authentication 4 | flow is diverted in order to handle the 2FA request. 5 | 6 | ## Initial authentication request 7 | 8 | When the Identity API receives an authentication request for a user, part of the 9 | [validation process](./#validating-the-request) is to ensure that the user's account does not 10 | require two-factor authentication. 11 | 12 | If the account (or the user's organization) requires 2FA, the `/connect/token` endpoint returns a 13 | response with an HTTP status code `400`, an `Error` value of `invalid_grant`, and an `ErrorMessage` 14 | of "_Two factor required_". The response will also include a `CustomResponse` with the following 15 | JSON data: 16 | 17 | ```json 18 | { 19 | { "TwoFactorProviders", [2FA provider keys] }, 20 | { "TwoFactorProviders2", [2FA provider data] }, 21 | { "MasterPasswordPolicy", [Master password policy] }, 22 | // Only if the user has email 2FA 23 | { "SsoEmail2faSessionToken", [Token to allow email to be passed through SSO flow] } 24 | } 25 | ``` 26 | 27 | ## Handling 2FA response on the client 28 | 29 | If the client detects a 30 | [`IdentityTwoFactorResponse`](https://github.com/bitwarden/clients/blob/main/libs/common/src/auth/models/response/identity-two-factor.response.ts) 31 | when attempting to log in, it extracts the available 2FA providers from the `CustomResponse` and 32 | presents those to the user. 33 | 34 | Each 2FA method has its own UI, but in all cases the user will generate a "token" of some sort to 35 | capture the user's response. This token is captured on the 36 | [`TwoFactorComponent`](https://github.com/bitwarden/clients/blob/main/apps/desktop/src/auth/two-factor.component.ts) 37 | when the user completes the 2FA process. 38 | 39 | Once the user has entered their 2FA, a new authentication request is `POST`ed to the 40 | `/connect/token` endpoint with the same contents as the original, failed request, with the following 41 | additions to the request body: 42 | 43 | - `twoFactorToken` is set to the token generated by the user's 2FA response 44 | - `twoFactorProvider` is set to the provider used for 2FA 45 | - `twoFactorRemember` is set based on whether the user chose to "remember" their 2FA response 46 | 47 | ## Validating request with 2FA response 48 | 49 | When the Identity API receives the second authentication request that includes the additional 2FA 50 | properties, it performs the authentication process again. 51 | 52 | This time, the server is able to validate the 2FA response. To do this, it calls `ValidateAsync` on 53 | the relevant `IUserTwoFactorTokenProvider` implementation for the `twoFactorProvider` sent by the 54 | client in the request. 55 | 56 | If the token is valid, a successful response is 57 | [generated and returned to the client](./index.md#generating-a-response). If the user chose to 58 | remember their 2FA entry, this response includes a token in the `TwoFactorToken` property that can 59 | be included on subsequent requests to bypass 2FA. 60 | -------------------------------------------------------------------------------- /docs/architecture/adr/0006-clients-use-jest-mocks.md: -------------------------------------------------------------------------------- 1 | --- 2 | adr: "0006" 3 | status: Accepted 4 | date: 2022-07-18 5 | tags: [clients, tests] 6 | --- 7 | 8 | # 0006 - Clients: Use Jest Mocks 9 | 10 | 11 | 12 | ## Context and problem statement 13 | 14 | We currently use [Substitute](https://www.npmjs.com/package/@fluffy-spoon/substitute) to create 15 | mocks in our tests. This includes matching arguments, mocking return values, and spying on calls. 16 | However, we also use Jest, which comes with its own mocking, spying and matching functions. This 17 | means we have two libraries that provide the same functionality. 18 | 19 | This is undesirable because: 20 | 21 | - We have duplication of functionality between two competing libraries 22 | - It's not clear which library the team is supposed to use 23 | - Those familiar with Jest will naturally use Jest for their mocks, which is not the pattern we 24 | currently follow 25 | - Substitute is less well-known and used compared to Jest, and is another library to learn 26 | - It requires that we mix syntax, particularly for assertions: we use Jest's `expect` to assert the 27 | test result, but we use Substitute's `Arg` to match arguments within mock calls. 28 | 29 | We should just pick one. 30 | 31 | ## Considered options 32 | 33 | - **Use Substitute and ban developers from using Jest mocks** - we keep both libraries and continue 34 | to use them both in tandem. In this case, we should provide clear guidance and training to 35 | developers to use Substitute for all mocking and argument matching (not Jest). 36 | 37 | - **Deprecate Substitute and use Jest with jest-mock-extended instead** - we deprecate Substitute 38 | and update all existing tests to use Jest mocks instead. We use 39 | [jest-mock-extended](https://github.com/marchaos/jest-mock-extended/) for convenient mocking 40 | syntax and better integration with Typescript. There should not be any loss of functionality 41 | arising from this change. 42 | 43 | - **Use a different mocking library and/or test runner** - we change to something else entirely. 44 | This is not really on the table here, but it is an option. Jest is working well so far, so I don't 45 | propose we change it. 46 | 47 | ## Decision outcome 48 | 49 | Chosen option: **Deprecate Substitute and use Jest with jest-mock-extended instead** 50 | 51 | We should also host a training/learning session to encourage and empower developers to unit test 52 | their code. 53 | 54 | ### Positive consequences 55 | 56 | - Front-end developers are more likely to be familiar with Jest than Substitute 57 | - Jest has more documentation and resources (Medium articles, StackOverflow answers, etc) 58 | - It's an integrated part of Jest 59 | - No mixing different libraries or syntax 60 | 61 | ### Negative consequences 62 | 63 | - Backend developers will have more of a learning curve compared to Substitute, which is a port of 64 | NSubstitute for .NET. However, this is still not a particularly steep learning curve, and it makes 65 | sense to use front-end tools in a front-end environment. 66 | - Some effort involved to change existing tests, but this is not substantial. 67 | -------------------------------------------------------------------------------- /docs/architecture/adr/0029-angular-signals.md: -------------------------------------------------------------------------------- 1 | --- 2 | adr: "0029" 3 | status: "Accepted" 4 | date: 2025-11-24 5 | tags: [clients, angular] 6 | --- 7 | 8 | # 0028 - Adopt Angular Signals for Component State 9 | 10 | 11 | 12 | ## Context and Problem Statement 13 | 14 | Angular has adopted a new reactive primitive, signals. Signals have various improvements over RxJS: 15 | performance, simplicity, and deeper integrations into the rest of the framework. 16 | 17 | RxJS will become an optional dependency of Angular. Certain asynchronous workflows will still 18 | benefit from RxJS (signals are synchronous). Furthermore, being a part of the core Angular library, 19 | Angular signals cannot readily be used in non-Angular environments. 20 | 21 | As such, Signals should be the default when operating _in the view layer_: components, directives, 22 | pipes, and services that are tightly coupled to the UI/Angular. Services that primarily deal with 23 | business logic should prefer RxJS to maximize portability (or, even better, be moved to the Rust 24 | SDK). 25 | 26 | ## Decision 27 | 28 | Signal-based APIs (inputs, outputs, child queries) will be required in components and directives via 29 | linting: 30 | 31 | - `@Input()` → `input()` 32 | - `@Output()` → `output()` 33 | - `@ViewChild`/`@ContentChild` → `viewChild()`/`contentChild()` 34 | 35 | Services tightly coupled to Angular should use signals. Services with non-presentational business 36 | logic should prefer RxJS for portability. Use `toSignal()` and `toObservable()` to bridge between 37 | RxJS and signals when necessary. 38 | 39 | ## Implementation Plan 40 | 41 | New code must use signal-based APIs; existing code will be migrated gradually. Angular provides 42 | automatic code migrations for signal 43 | [inputs](https://angular.dev/reference/migrations/signal-inputs) and 44 | [queries](https://angular.dev/reference/migrations/signal-queries). 45 | 46 | Much of `libs/components` was updated using these migrators: 47 | https://github.com/bitwarden/clients/pull/15340 48 | 49 | See the 50 | [Angular Modernization Guide](https://contributing.bitwarden.com/contributing/code-style/web/angular-migration-guide/#signals) 51 | for more information. 52 | 53 | ## Consequences 54 | 55 | **Positive:** 56 | 57 | - Improved performance and simpler change detection 58 | - Clear path to removing Zone.js dependency 59 | - Better debugging experience 60 | - Aligned with Angular's direction 61 | - Simpler than RxJS for many common use cases 62 | 63 | **Negative:** 64 | 65 | - Temporary complexity during migration with mixed RxJS/Signals patterns 66 | - Learning curve for team members unfamiliar with signals 67 | - Migration effort required for existing codebase 68 | 69 | ## Reasons against other options 70 | 71 | - Disallow usage of signals and only use RxJS for reactivity. 72 | - This is a non-starter. Signals are being built into Angular. 73 | - Continue the status quo of ad hoc usage. 74 | - Having multiple ways to do the same thing leads to analysis paralysis and complicated code. 75 | - Signals + OnPush change detection provide a clear path to removing Zone.js. With that comes 76 | notable performance and debugging improvements. 77 | 78 | ## Further reading 79 | 80 | - [Angular docs](https://angular.dev/guide/signals) 81 | -------------------------------------------------------------------------------- /docs/architecture/clients/overview.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | --- 4 | 5 | # Overview 6 | 7 | The Applications are structured using a layered architecture. The layers are: 8 | 9 | - State 10 | - Services 11 | - Presentation (Components or CLI Commands) 12 | 13 | The different layers primarily use models described in the [Data Model](./data-model.md) when 14 | communicating with each other. 15 | 16 | ## State 17 | 18 | At the core of the application is the state layer. This layer is responsible for keeping track of 19 | the state, state includes things like the current user, vault items and more. The state layer is 20 | also responsible for persisting the state to disk, and loading it from disk. 21 | 22 | Currently the state is primarily implemented in the aptly named `StateService`. Which acts as a god 23 | class for all other services to access the state. _This is not ideal, and we are working on a better 24 | solution._ 25 | 26 | We also have _Storage Services_ which are implementation specific services for persisting the state 27 | to different storage medium. Which are primarily structured in three categories. 28 | 29 | - Persisted storage. 30 | - In memory storage. 31 | - Secure persisted storage. 32 | 33 | The _State Service_ itself should never be called from anything other than individual domain 34 | services, and those should only access their own domain. Additionally only a single service should 35 | access the specific domain in the _State Service_. 36 | 37 | Below is an example how a _domain component_ and _domain service_ interacts with the _State 38 | Service_. 39 | 40 | ```kroki type=plantuml 41 | @startuml 42 | skinparam BackgroundColor transparent 43 | skinparam componentStyle rectangle 44 | 45 | title State Service 46 | 47 | component "Example Domain" { 48 | component "Components" as components 49 | 50 | component "Domain Service" as domain 51 | } 52 | 53 | component "State Service" as state 54 | 55 | component "Storage Service" as storage 56 | component "Secure Storage Service" as secure 57 | component "Memory Storage Service" as memory 58 | 59 | components -d-> domain : subscribe \n observable 60 | domain -> state : retrieve state 61 | 62 | state --> storage 63 | state --> secure 64 | 65 | state --> memory 66 | 67 | @enduml 68 | ``` 69 | 70 | ## Services 71 | 72 | Above the State layer is the Services layer. This layer is primarily responsible for performing 73 | business logic by interacting with the State layer and receiving commands from the Presentation 74 | layer. In this layer we also have the API Services which communicate with the Server. 75 | 76 | Services should primarily use observables for exposing data access, this encourages a reactive 77 | presentation layer, which always shows the latest state. As we continue to break up components into 78 | smaller pieces it also becomes important that they stay up to date, and interact with services for 79 | business logic. 80 | 81 | ## Presentation 82 | 83 | The presentational layer is either implemented using [Angular](./presentation/angular.md), or using 84 | a [Command pattern](./presentation/cli.md) in the CLI. This layer should only focus on 85 | presentational aspects and all business logic should, as previously mentioned be placed in 86 | _Services_. This allows multiple components to provide the same functionality without needing 87 | inheritance. 88 | -------------------------------------------------------------------------------- /docs/architecture/sdk/server-bindings.md: -------------------------------------------------------------------------------- 1 | # Server Bindings 2 | 3 | The SDK currently uses auto-generated bindings for the server. The bindings are generated using the 4 | [`openapi-generator`][openapi] to generate the Rust bindings from the server OpenAPI specifications. 5 | These bindings are regularly updated to ensure they stay in sync with the server. 6 | 7 | The bindings are exposed as multiple crates, one for each backend service: 8 | 9 | - `bitwarden-api-api`: For the `Api` service that contains most of the server side functionality. 10 | - `bitwarden-api-identity`: For the `Identity` service that is used for authentication. 11 | 12 | When performing any API calls the goal is to use the generated bindings as much as possible. This 13 | ensures any changes to the server are accurately reflected in the SDK. The generated bindings are 14 | stateless, and always expects to be provided a `Configuration` instance. The SDK exposes these under 15 | the `get_api_configurations` function on the `Client` struct. `get_api_configurations` also 16 | refreshes the authentication token if required. 17 | 18 | ```rust 19 | // Example API call 20 | let config: &ApiConfigurations = client.get_api_configurations().await; 21 | let response: SyncResponseModel = 22 | bitwarden_api_api::apis::sync_api::sync_get(&config.api, exclude_subdomains).await?; 23 | ``` 24 | 25 | You _should not_ expose the request and response models of the auto generated bindings and _should_ 26 | instead define and use your own models. This ensures the server request / response models are 27 | decoupled from the SDK models, which allows for easier changes in the future without breaking 28 | backwards compatibility. 29 | 30 | We recommend using either the [`From`][from] or [`TryFrom`][tryfrom] [conversion traits][conversion] 31 | depending on if the conversion requires error handling or not. Below are two examples of how this 32 | can be done: 33 | 34 | ```rust 35 | impl TryFrom for LoginUri { 36 | type Error = Error; 37 | 38 | fn try_from(uri: bitwarden_api_api::models::CipherLoginUriModel) -> Result { 39 | Ok(Self { 40 | uri: EncString::try_from_optional(uri.uri)?, 41 | r#match: uri.r#match.map(|m| m.into()), 42 | uri_checksum: EncString::try_from_optional(uri.uri_checksum)?, 43 | }) 44 | } 45 | } 46 | 47 | impl From for UriMatchType { 48 | fn from(value: bitwarden_api_api::models::UriMatchType) -> Self { 49 | match value { 50 | bitwarden_api_api::models::UriMatchType::Domain => Self::Domain, 51 | bitwarden_api_api::models::UriMatchType::Host => Self::Host, 52 | bitwarden_api_api::models::UriMatchType::StartsWith => Self::StartsWith, 53 | bitwarden_api_api::models::UriMatchType::Exact => Self::Exact, 54 | bitwarden_api_api::models::UriMatchType::RegularExpression => Self::RegularExpression, 55 | bitwarden_api_api::models::UriMatchType::Never => Self::Never, 56 | } 57 | } 58 | } 59 | ``` 60 | 61 | [openapi]: https://github.com/OpenAPITools/openapi-generator 62 | [from]: https://doc.rust-lang.org/std/convert/trait.From.html 63 | [tryfrom]: https://doc.rust-lang.org/std/convert/trait.TryFrom.html 64 | [conversion]: https://doc.rust-lang.org/std/convert/index.html 65 | -------------------------------------------------------------------------------- /docs/getting-started/server/public-api.md: -------------------------------------------------------------------------------- 1 | # Public API 2 | 3 | The Bitwarden Public API provides organizations a suite of tools for managing members, collections, 4 | groups, event logs, and policies. More information about the Public API is available in the 5 | [Help Center](https://bitwarden.com/help/public-api/). 6 | 7 | ## Differences with the private API 8 | 9 | Most developers will be more familiar with the private API used by our client applications. The 10 | Public API is different in several key areas: 11 | 12 | 13 | | Private API | Public API | 14 | | --- | --- | 15 | | Located at https://api.bitwarden.com | Located at https://api.bitwarden.com/public | 16 | | Used by official Bitwarden client applications | Used by third parties, usually in custom integrations | 17 | | Broad scope -- can be used for anything | Narrow scope -- can only be used to manage organizations | 18 | | Can be changed without notice (but subject to the official [support cycle](https://bitwarden.com/help/bitwarden-software-release-support/)) | Must give notice (such as deprecation warnings) for certain changes 19 | | Utilizes user credentials for authentication | Utilizes organization API key for authentication | 20 | 21 | ## Development guidelines 22 | 23 | 1. Avoid making breaking changes -- these are any changes that would require existing users of the 24 | API to update their integrations to avoid errors or unexpected behavior -- for example, make new 25 | properties optional, so that existing integrations do not have to supply a value 26 | 2. If you must make breaking changes, consider how to give advance warning to existing users. 27 | Communicate with Engineering, Product, and Customer Success Integration teams to coordinate any 28 | notice required and minimize impact 29 | 3. Do not use the same request/response models as the private API 30 | 4. Use [xmldoc comments](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/xmldoc/) 31 | to add documentation to your endpoints and models. These will be included in the SwaggerUI output 32 | 33 | ## Developing locally 34 | 35 | When running in dev mode the Bitwarden server includes a 36 | [SwaggerUI](https://swagger.io/tools/swagger-ui/) instance, similar to the one found on our 37 | [Help Center](https://bitwarden.com/help/api/). 38 | 39 | SwaggerUI can help you test any changes you make to the Public API without having to write your own 40 | HTTP requests. You can also check how your xmldoc comments will be presented by SwaggerUI when the 41 | Help Center is updated. 42 | 43 | To use SwaggerUI: 44 | 45 | 1. Start your local development server (Api and Identity projects) and Web Vault 46 | 2. Navigate to http://localhost:4000/docs 47 | 3. Click "Authorize" 48 | 4. In a separate tab, open the Web Vault and navigate to your Organization Settings page. Click 49 | "View API Key" 50 | 5. Enter your organization's client_id and client_secret from the Web Vault into Swagger. You can 51 | now close the Web Vault and continue in Swagger 52 | 6. In the Scopes section, click "select all" 53 | 7. Click "Authorize" to close the dialog 54 | 8. You should receive a confirmation dialog. Click "Close" 55 | 56 | You can now test the Public API by expanding any section, clicking "Try it out", editing the 57 | request, and clicking Execute. The response will be displayed below. You can also verify that your 58 | request worked by manually inspecting the organization in the Web Vault. 59 | -------------------------------------------------------------------------------- /docs/architecture/adr/0017-watchOS-use-swift.md: -------------------------------------------------------------------------------- 1 | --- 2 | adr: "0017" 3 | status: Accepted 4 | date: 2022-12-30 5 | tags: [mobile, watchOS] 6 | --- 7 | 8 | # 0017 - Use Swift to build watchOS app 9 | 10 | 11 | 12 | ## Context and problem statement 13 | 14 | We would like to ship a watchOS application bundled together with the regular iOS application. The 15 | watchOS application will act as a companion application and initially offer a way to view TOTP codes 16 | from the watch which were previously synchronized from the iPhone. 17 | 18 | ## Considered options 19 | 20 | - [.Net using Xamarin](https://learn.microsoft.com/en-us/xamarin/ios/watchos/) 21 | - [Swift using WatchKit](https://developer.apple.com/documentation/watchkit/) 22 | - [Swift using SwiftUI](https://developer.apple.com/xcode/swiftui/) 23 | 24 | ## Decision outcome 25 | 26 | Chosen option: **Swift using SwiftUI**. 27 | 28 | ### Positive consequences 29 | 30 | - Supports watchOS fully 31 | - We can build and debug the app properly 32 | - Fast development with declarative UI and Previews to enhance the dev experience 33 | - Code organized using components on the UI 34 | - Updates to the framework and the SDKs are available as soon as Apple ships them 35 | - A lot more documentation, examples and public repositories to check 36 | 37 | ### Negative consequences 38 | 39 | - New tech stack to learn for the team 40 | - Even though we can debug the app properly we can't debug the iOS and the watchOS app at the same 41 | time (when debugging the watchOS app, a stub iOS app is installed on the iPhone so the original 42 | one is overridden by the stub one) 43 | - Set up is harder given that we need to bundle the XCode built watchOS app into the Xamarin iOS app 44 | and update CI accordingly 45 | 46 | ## Pros and Cons of the Options 47 | 48 | ### .Net using Xamarin 49 | 50 | - :white_check_mark: Keeps same tech stack 51 | - :white_check_mark: Shares a lot of code 52 | - :white_check_mark: Easier learning curve and reviews 53 | - :white_check_mark: Easy integration into the regular iOS app 54 | - :no_entry: Several important issues affecting the watchOS dev experience, particularly can't debug 55 | correctly 56 | - :no_entry: watchOS platform not being a priority for the .Net team 57 | - :no_entry: No plans to include watchOS support on MAUI and neither on .Net 7 nor on .Net 8 58 | 59 | ### Swift using WatchKit 60 | 61 | - :white_check_mark: It's the native approach meaning it's always up to date 62 | - :white_check_mark: Lots of documentation and examples/projects to look 63 | - :white_check_mark: Debugging works as expected 64 | - :no_entry: Steep learning curve (language + watch related stuff) 65 | - :no_entry: Hard to integrate to the regular iOS app 66 | 67 | ### Swift using SwiftUI 68 | 69 | - :white_check_mark: It's the native approach meaning it's always up to date 70 | - :white_check_mark: Lots of documentation and examples/projects to look 71 | - :white_check_mark: Debugging works as expected 72 | - :white_check_mark: Fast development with SwiftUI Framework 73 | - :white_check_mark: Previews enhance the development experience to the sky taking a lot less effort 74 | - :no_entry: Steep learning curve (language + watch related stuff + SwiftUI framework) 75 | - :no_entry: Hard to integrate to the regular iOS app 76 | - :no_entry: SwiftUI is not polished enough yet so some things to keep in mind are special 77 | navigation and rendering issues 78 | -------------------------------------------------------------------------------- /docs/contributing/pull-requests/community-pr-process.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 4 3 | sidebar_custom_props: 4 | access: community 5 | --- 6 | 7 | # Contribution Review Process 8 | 9 | Congratulations! You've submitted a pull request for changes to the Bitwarden codebase. 10 | 11 | Bitwarden recognizes the time and effort that community members take to recognize bugs or potential 12 | new features and offer up pull requests to resolve them. 13 | 14 | Transparency is one of our core values, and we feel that it is important that contributors 15 | understand the process that our teams take in evaluating, prioritizing, and reviewing these pull 16 | requests, and why some changes may move more quickly to completion than others. 17 | 18 | ## Product assessment 19 | 20 | When your community contribution is received, the first step is for our Product team to evaluate 21 | whether the change aligns with the vision for the Bitwarden products. This is more relevant for 22 | feature enhancements than bugs, but it is important for us to assess whether the change conflicts 23 | with larger upcoming changes on the roadmap or would potentially replace work already on the backlog 24 | for a team. 25 | 26 | If the Product team has clarifying questions or would like the change to be modified to more closely 27 | align with their vision, they will reach out on the PR and request changes. 28 | 29 | Once Product has signed off on the change, it moves to our Engineering teams. 30 | 31 | ## Engineering assessment 32 | 33 | The Engineering team(s) responsible for the change depend largely on what code was changed. We use 34 | GitHub code owners to manage the areas in our repositories owned by each team, and the responsible 35 | team(s) will be automatically tagged as reviewers on the PR that you raise to merge your changes. 36 | 37 | :::tip Assigned reviewers 38 | 39 | When a Bitwarden developer is assigned to your PR, that does not necessarily mean that the PR is 40 | under active review at that moment. This assignment may take place while the work is still on the 41 | team's backlog. 42 | 43 | ::: 44 | 45 | The responsible Engineering team(s) will review the change and ensure that there are no concerns 46 | around how the change was implemented; this is generally more applicable for larger sets of changes, 47 | where the team needs to ensure that the change aligns with the architectural vision for how the code 48 | should be structured. Community contributors following practices exhibited in the current codebase 49 | may not be aware of existing tech debt or patterns that are no longer encouraged for new 50 | development. Intervening at this point allows us to communicate to you preemptively and request the 51 | desired changes before a formal review starts. 52 | 53 | ## Pull request review and testing 54 | 55 | Once the team has assessed the high-level implementation, your contribution is ready for active code 56 | review. If not done already, the PR will be assigned to a Bitwarden engineer from each responsible 57 | team. 58 | 59 | The reviewer and the team's QA engineers will test the change in all applicable clients or server 60 | environments and ensure that proper test coverage is present. If there are changes required, or 61 | testing is not successful, they will reach out on the PR to request changes. 62 | 63 | Once that is complete, they will approve the changes and contact you on the PR to let you know. They 64 | will merge your PR into the `main` branch, and it will be included in the next release! 65 | -------------------------------------------------------------------------------- /docs/architecture/adr/0011-angular-folder-structure.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 0011 - Angular folder structure 3 | adr: "0011" 4 | status: Accepted 5 | date: 2022-07-25 6 | tags: [clients, angular] 7 | --- 8 | 9 | # 0011 - Scalable Angular Clients folder structure 10 | 11 | 12 | 13 | ## Context and problem statement 14 | 15 | We currently have a very fractured folder structure in the Angular clients with multiple competing 16 | folder structures. We need to standardize on a single folder structure which will allow us to 17 | continue growing without friction. This ADR builds upon 18 | [0010 Use Angular Modules](./0010-angular-ngmodules.md) and proposes a folder structure. 19 | 20 | ### Resources 21 | 22 | This is heavily based on the following resources. 23 | 24 | - [Angular - NgModules](https://angular.io/guide/ngmodules) 25 | - [Angular - Application structure and NgModules](https://angular.io/guide/styleguide#application-structure-and-ngmodules) 26 | - [Angular - Lazy-loading feature modules](https://angular.io/guide/lazy-loading-ngmodules) 27 | - [Using Nx at Enterprises](https://nx.dev/guides/monorepo-nx-enterprise) 28 | 29 | ## Considered options 30 | 31 | - **Nx folder structure** - Seems like a well thought out structure but it essentially requires that 32 | we use nx since it relies heavily on npm packages. We're not yet at a stage where we feel 33 | comfortable adopting such a tool. 34 | - **Lightweight structure inspired by Angular Docs** - Takes inspiration from the Angular docs + Nx 35 | to propose a more lightweight structure that still keeps the features in the `app` directory. 36 | 37 | ### `SharedModule` & `CoreModule` 38 | 39 | The [Angular docs](https://angular.io/guide/module-types#shared-ngmodules) specifies that there 40 | should be a `SharedModule`. It further specifies that the shared module should not provide 41 | providers. A common convention is to create a `CoreModule` which is responsible for setting up the 42 | core providers. 43 | 44 | ### Proposed Folder structure 45 | 46 | This folder structure is based on our existing routing structure, since a common pattern is to use 47 | modules for nested routes in order to support lazy loading. The root folders are mostly based on the 48 | root routing concepts we have, with various public routes being categorized under `accounts`. 49 | 50 | ```text 51 | web/src/app 52 | core 53 | services 54 | core.module.ts 55 | index.ts 56 | shared 57 | shared.module.ts 58 | index.ts 59 | 60 | accounts 61 | providers 62 | reports 63 | sends 64 | settings 65 | tools 66 | vault 67 | shared 68 | vault-shared.module.ts (this gets imported by Organization Vaults) 69 | vault.module.ts 70 | index.ts (exposes the following files:) 71 | vault-shared.module.ts 72 | vault.module.ts 73 | -- 74 | app.component.html 75 | app.component.ts 76 | app.module 77 | oss-routing.module.ts 78 | oss.module.ts 79 | wildcard-routing.module.ts 80 | ``` 81 | 82 | This structure will be implemented in multiple steps. 83 | 84 | 1. Extract unrelated files from `src/app`. https://github.com/bitwarden/clients/pull/3127 85 | 2. Create `CoreModule`. https://github.com/bitwarden/clients/pull/3149 86 | 3. Create `SharedModule`. https://github.com/bitwarden/clients/pull/3222 87 | 4. Migrate all existing loose components to `SharedModule`. 88 | - Any remaining functionality in root should provide a module. 89 | 90 | ### Decision Outcome 91 | 92 | Implementing a file structure modeled after the above example. 93 | -------------------------------------------------------------------------------- /docs/architecture/adr/0008-server-CQRS-pattern.md: -------------------------------------------------------------------------------- 1 | --- 2 | adr: "0008" 3 | status: Accepted 4 | date: 2022-07-15 5 | tags: [server] 6 | --- 7 | 8 | # 0008 - Server: Adopt CQS 9 | 10 | 11 | 12 | :::note Terminology clarification 13 | 14 | This ADR originally used "CQRS" (Command Query Responsibility Segregation) terminology. However, our 15 | implementation more accurately reflects CQS (Command Query Separation), which is a simpler pattern 16 | focused on breaking up large service classes rather than separating read/write data models. The 17 | content has been updated to use the more accurate CQS terminology. 18 | 19 | ::: 20 | 21 | ## Context and problem statement 22 | 23 | In Bitwarden Server, we currently use an `<>Service` pattern to act on our entities. These 24 | classes end up being dumping grounds for all actions involving the entity; leading 25 | [bloaters](https://refactoring.guru/refactoring/smells/bloaters) and 26 | [couplers](https://refactoring.guru/refactoring/smells/couplers). There are two facts which helped 27 | guide us to the current design: 28 | 29 | - We use an entity pattern to represent data stored in our databases and bind these entity classes 30 | automatically using either Dapper or Entity Framework. 31 | 32 | - We use constructor-based Dependency Injection to deliver dependencies to objects. 33 | 34 | The two above facts mean that our Entities cannot act without receiving all necessary state as 35 | method parameters, which goes against our typical DI pattern. 36 | 37 | ## Considered options 38 | 39 | - **`<>Services`** -- Discussed above 40 | - **Queries and Commands** -- Fundamentally our problem is that the `<>Service` name 41 | encapsulates absolutely anything you can do with that entity and excludes any code reuse across 42 | different entities. The CQS pattern creates classes based on the action being taken on the entity. 43 | This naturally limits the classes scope and allows for reuse should two entities need to implement 44 | the same command behavior. 45 | - **Small Feature-based services** -- This design would break `<>Service` into 46 | `<>Service`, but ultimately runs into the same problems. As a feature grows, this service 47 | would become bloated and tightly coupled to other services. 48 | 49 | ## Decision outcome 50 | 51 | Chosen option: **Queries and Commands (CQS pattern)** 52 | 53 | Commands seem all-around the better decision to the incumbent, primarily because it limits class 54 | scope. 55 | 56 | Queries are already basically done through repositories and/or services, but would require some 57 | restructuring to be obvious. 58 | 59 | ## Transition plan 60 | 61 | We will gradually transition to a CQS pattern over time. If a developer is making changes that use 62 | or affect a service method, they should consider whether it can be extracted to a query/command, and 63 | include it in their work as tech debt. 64 | 65 | The current domain services are large and inter-dependent and it may not be practical to break them 66 | up all at once. It's acceptable to refactor "one level deep" and then leave other methods where they 67 | are. This may result in the new query/command still being somewhat coupled with other service 68 | methods. This is acceptable during the transition phase, but these interdependencies should be 69 | removed over time. 70 | 71 | ## Further reading 72 | 73 | - [Server Architecture](../server/index.md) - Practical guide on implementing CQS in the server 74 | codebase 75 | - [Martin Fowler on CQS](https://martinfowler.com/bliki/CommandQuerySeparation.html) - High-level 76 | summary of the CQS principle 77 | -------------------------------------------------------------------------------- /docs/getting-started/sdk/internal/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 5 3 | --- 4 | 5 | # Internal SDK 6 | 7 | For more in-depth documentation please review the [SDK Architecture](../../../architecture/sdk) and 8 | the Internal SDK project's [`README`](https://github.com/bitwarden/sdk-internal). 9 | 10 | ## Requirements 11 | 12 | - [Rust](https://www.rust-lang.org/tools/install) latest stable version - (preferably installed via 13 | [rustup](https://rustup.rs/)) 14 | - NodeJS and NPM. 15 | 16 | See the [Tools and Libraries](../../tools/index.md) page for more information. 17 | 18 | ## Setup instructions 19 | 20 | 1. Clone the repository: 21 | 22 | ```bash 23 | git clone https://github.com/bitwarden/sdk-internal.git 24 | cd sdk 25 | ``` 26 | 27 | 2. Install the dependencies: 28 | 29 | ```bash 30 | npm ci 31 | ``` 32 | 33 | ## Building the SDK 34 | 35 | The SDK is built for different platforms, all of which have their own build instructions. For more 36 | information on how to build for a specific platform, refer to the readmes for the different crates: 37 | 38 | - **Web**: 39 | [`crates/bitwarden-wasm-internal`](https://github.com/bitwarden/sdk-internal/tree/main/crates/bitwarden-wasm-internal) 40 | - **iOS**: 41 | [`crates/bitwarden-uniffi/swift`](https://github.com/bitwarden/sdk-internal/tree/main/crates/bitwarden-uniffi/swift) 42 | - **Android**: 43 | [`crates/bitwarden-uniffi/kotlin`](https://github.com/bitwarden/sdk-internal/tree/main/crates/bitwarden-uniffi/kotlin) 44 | 45 | Please be aware that each platform has its own set of dependencies that need to be installed before 46 | building. Make sure to double check the readme if you encounter any issues. 47 | 48 | ## Linking the SDK to clients 49 | 50 | After modifying the SDK, it can be beneficial to test the changes in the client applications. To do 51 | so you will need to update the SDK reference in the client applications. 52 | 53 | These instructions assumes you have a directory structure similar to: 54 | 55 | ```text 56 | sdk-internal/ 57 | clients/ 58 | ios/ 59 | android/ 60 | ``` 61 | 62 | ### Web clients 63 | 64 | The web clients use NPM to install the SDK as a dependency. NPM offers a dedicated command 65 | [`link`][npm-link] which can be used to temporarily replace the packages with a local version. The 66 | web SDK has two targets (OSS and Bitwarden License) and the following command links both of them: 67 | 68 | ```bash 69 | npm link ../sdk-internal/crates/bitwarden-wasm-internal/npm ../sdk-internal/crates/bitwarden-wasm-internal/bitwarden_license/npm 70 | ``` 71 | 72 | If you only want to link one of the versions, you can run the command with only one of the paths. 73 | Keep in mind that running `npm link` will restore any previously linked packages, so only the paths 74 | in the last run command will be linked. 75 | 76 | :::warning 77 | 78 | Running `npm ci` or `npm install` will replace the linked packages with the published version. 79 | 80 | ::: 81 | 82 | ### Mobile 83 | 84 | #### Android 85 | 86 | 1. Build and publish the SDK to the local Maven repository: 87 | 88 | ```bash 89 | ../sdk-internal/crates/bitwarden-uniffi/kotlin/publish-local.sh 90 | ``` 91 | 92 | 2. Set the user property `localSdk=true` in the `user.properties` file. 93 | 94 | #### iOS 95 | 96 | Run the bootstrap script with the `LOCAL_SDK` environment variable set to true in order to use the 97 | local SDK build: 98 | 99 | ```bash 100 | LOCAL_SDK=true ./Scripts/bootstrap.sh 101 | ``` 102 | 103 | [npm-link]: https://docs.npmjs.com/cli/v9/commands/npm-link 104 | [sm]: https://bitwarden.com/products/secrets-manager/ 105 | [pm]: https://bitwarden.com/ 106 | -------------------------------------------------------------------------------- /docs/architecture/deep-dives/push-notifications/non-mobile.md: -------------------------------------------------------------------------------- 1 | # Other Client Push Notifications 2 | 3 | For non-mobile clients, push notifications are handled with 4 | [SignalR](https://learn.microsoft.com/en-us/aspnet/core/signalr/introduction), Microsoft's library 5 | for real-time client communication over WebSockets. 6 | 7 | ## Server implementations 8 | 9 | When real-time changes must be communicated to the registered non-mobile clients, it is the 10 | responsibility of the Bitwarden API for their configured server instance to distribute the 11 | information. The server abstracts this with the 12 | [`IPushNotificationService`](https://github.com/bitwarden/server/blob/main/src/Core/Services/IPushNotificationService.cs) 13 | interface, which has different implementations based on whether the instance is cloud-hosted or 14 | self-hosted. 15 | 16 | ### Cloud implementation 17 | 18 | ```kroki type=plantuml 19 | @startuml 20 | participant C1 as "Initiating Client" 21 | participant C2 as "Receiving Client" 22 | participant API as "Bitwarden Cloud API" 23 | participant Q as "Azure Queue" 24 | participant NAPI as "Bitwarden Notifications API" 25 | 26 | group Establish SignalR connection 27 | C2->>NAPI: Registers as SignalR client 28 | end 29 | 30 | group Other client updates data 31 | C1->>API: Updates Data 32 | API->>Q: Sends Message to Azure Queue 33 | end 34 | 35 | group Notifications API processes message 36 | NAPI<<-Q: Reads from Azure Queue 37 | NAPI->>C2: Sends SignalR message to registered clients 38 | end 39 | @enduml 40 | ``` 41 | 42 | For the Bitwarden Cloud implementation, the API uses the 43 | [`AzureQueuePushNotificationService`](https://github.com/bitwarden/server/blob/main/src/Core/Services/Implementations/AzureQueuePushNotificationService.cs) 44 | implementation. This service submits the push notification to an Azure Queue in the Bitwarden Azure 45 | tenant. 46 | 47 | The Bitwarden Cloud Notifications API includes a queue processor - the 48 | [`AzureQueueHostedService`](https://github.com/bitwarden/server/blob/main/src/Notifications/AzureQueueHostedService.cs) - 49 | that monitors the Azure Queue for pending push notifications. The processor pulls messages from the 50 | queue and sends them to all clients registered for the initiating user or organization. 51 | 52 | ### Self-hosted implementation 53 | 54 | ```kroki type=plantuml 55 | @startuml 56 | participant C1 as "Initiating Client" 57 | participant C2 as "Receiving Client" 58 | participant SHAPI as "Self-Hosted API" 59 | participant SHNAPI as "Self-Hosted Notifications API" 60 | 61 | group Register 62 | C2->>SHNAPI: Registers as SignalR client 63 | end 64 | 65 | Group Other client updates data 66 | C1->>SHAPI: Updates data 67 | SHAPI->>SHNAPI: Calls Notifications API to distribute the notification 68 | end 69 | 70 | group Update clients 71 | SHNAPI->>C2: Sends Message to registered clients 72 | end 73 | @enduml 74 | ``` 75 | 76 | For a self-hosted implementation, the push notification architecture differs because there is no 77 | Azure Queue available. 78 | 79 | Self-hosted instances have a slightly simplified flow since they don't have access to Azure 80 | resources like Azure Queues. The overall flow is still the same as the cloud-hosted implementation, 81 | with the exception that instead of buffering the notifications using a Azure Queue, the self-hosted 82 | Bitwarden API submits the notifications directly to the self-hosted Notifications API. 83 | 84 | ## Client registration 85 | 86 | When a non-mobile client starts and the user is authenticated, it initiates a WebSocket connection 87 | to the Notification service (`/notifications/hub`) for their configured server instance. This 88 | request includes their JWT `bearer` token, which is used to retrieve the user ID, which in turn 89 | determines which notifications the user receives. 90 | -------------------------------------------------------------------------------- /docs/getting-started/clients/desktop/mac/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_custom_props: 3 | access: bitwarden 4 | --- 5 | 6 | # Mac App Store Dev 7 | 8 | :::warning 9 | 10 | The Mac App Store (MAS) Dev build is only required to test certain features that are exclusive to 11 | the MAS. In general, you should use the main build instructions (using `npm run electron`) unless 12 | you have a specific reason for needing the MAS build. 13 | 14 | ::: 15 | 16 | ## Setup 17 | 18 | These steps can be quite tricky. If you encounter any difficulties, post in the `#team-eng` Slack 19 | channel for assistance. 20 | 21 | ### Xcode 22 | 23 | 1. Install [Xcode from the App Store](https://apps.apple.com/us/app/xcode/id497799835?mt=12). 24 | 25 | 1. Login with your AppleID that is a member of the 8bit solutions LLC organization. This can be done 26 | from `Xcode > Preferences ... > Accounts` 27 | 28 | 1. Ensure you have a personal code signing certificate assigned to Bitwarden Inc by clicking the 29 | `Bitwarden Inc` team and clicking `Manage Certificates...`. 30 | 31 | 1. If no certificate is listed, click the plus sign (`+`) to create one. 32 | 33 | ### Keychain 34 | 35 | Verify that your Apple Keychain contains a value for `AC_PASSWORD`, if not we’ll need to generate 36 | one. 37 | 38 | 1. Login using your Apple Account on the [Apple-ID website](https://appleid.apple.com/). 39 | 40 | 2. Click on “App-Specific Passwords” 41 | 42 | ![App-Specific Passwords](./app-specific-passwords.png) 43 | 44 | 3. And then click on the `+` icon next to `Passwords` to add a new App-Specific Password. 45 | ![image](./app-specific-passwords2.png) 46 | 47 | 4. Save the new App-specific password using 48 | 49 | ```bash 50 | security add-generic-password -a "" -w "" -s "AC_PASSWORD" 51 | ``` 52 | 53 | ### Provisioning Profile 54 | 55 | 1. Ask BRE (@bre in slack) to have your `Apple Development` signing certificate added to the 56 | provisioning profile, and your Mac `Provisioning UDID` added to the whitelist. The 57 | `Provisioning UDID` can be found by going to `About This Mac > System Report...` and copying the 58 | `Provisioning UDID:` row. 59 | 60 | 2. Once everything is added, download the `Bitwarden Desktop Development (2021)` provisioning 61 | profile from https://developer.apple.com/account/resources/profiles/list 62 | 63 | 3. Install the provisioning profile to your device, and place it the `clients/apps/desktop` 64 | repository root. 65 | 66 | ### Building 67 | 68 | 1. Identify the name of your personal development certificate by running: 69 | ```zsh 70 | security find-identity -v | grep 'Apple Development' 71 | ``` 72 | 2. Ensure the CSC_NAME environment variable is set by running export CSC_NAME="", the value should 73 | be the output from find-identity without the Apple Development: portion. 74 | 75 | 3. Run `npm run dist:mac:masdev`. 76 | 77 | :::info 78 | 79 | If this is your first time running desktop locally, be sure to run `npm ci` before 80 | `npm run dist:mac:masdev`. 81 | 82 | ::: 83 | 84 | ### Troubleshooting 85 | 86 | If you receive an error stating `You do not have permission to open the application "Bitwarden".` 87 | ensure the correct provisioning profile is placed in the desktop repository root. 88 | 89 | ## Testing in QA 90 | 91 | Per the SDLC, QA verifies changes before they are merged into main. Currently the GitHub CI 92 | workflows for building the Mac desktop client do not create a build artifact for the Mac App Store 93 | as part of the workflow run. QA can obtain a build through these steps: 94 | 95 | 1. Navigate to the `Build Desktop` workflow under the `GitHub Actions` tab. 96 | 2. Click the `Run workflow` dropbox. 97 | - Select the branch in question. 98 | - Ensure "Force distribute to TestFlight" is checked. 99 | -------------------------------------------------------------------------------- /docs/getting-started/business/splunk-app.md: -------------------------------------------------------------------------------- 1 | # Splunk app 2 | 3 | The Bitwarden Splunk app fetches event log data from the Bitwarden Public API and makes it available 4 | in Splunk. 5 | 6 | ## Requirements 7 | 8 | - Docker. If you're using an Apple Silicon Mac, enable _Docker Desktop_ -> _Settings_ -> _General_ 9 | -> _Use Rosetta for x86_64/amd64 emulation on Apple Silicon_ 10 | - Python 3.7 - 3.10 11 | - [Poetry][poetry] 12 | - Also install Poetry export plugin with `poetry self add poetry-plugin-export` 13 | - libmagic (macOS only), available via homebrew: `brew install libmagic` 14 | - A Bitwarden Teams or Enterprise organization 15 | - If using a local development server - make sure the Events and EventsProcessor projects are 16 | running and [Event Logging](../server/events.md) is working 17 | 18 | ## Set up and configuration 19 | 20 | ### Configure your environment 21 | 22 | 1. Clone the Github repository: 23 | 24 | ``` 25 | git clone https://github.com/bitwarden/splunk.git 26 | ``` 27 | 28 | 2. Navigate to the root of the repository: 29 | 30 | ``` 31 | cd splunk 32 | ``` 33 | 34 | 3. Tell poetry to use the required Python version: 35 | 36 | ``` 37 | poetry env use 38 | ``` 39 | 40 | Where `` is the executable for Python. If this is in your PATH variable then you do 41 | not need to specify the full path. e.g. `poetry env use python3.9`. 42 | 43 | 4. Install dependencies: 44 | 45 | ``` 46 | poetry install --with dev 47 | ``` 48 | 49 | ### Set up Splunk Enterprise 50 | 51 | 1. Run Splunk Enterprise: 52 | 53 | ``` 54 | docker compose -f dev/docker-compose.yml up -d 55 | ``` 56 | 57 | :::warning 58 | 59 | If you are using an Apple Silicon Mac, you must use up to version 9.3 of Splunk. As of version 9.4, 60 | Splunk depends on the use of the AVX instruction set for its KVStore, which is not supported by 61 | Apple Silicon. 62 | 63 | ::: 64 | 65 | Please note this will set the admin password to `password`. This is for development purposes only. 66 | 67 | 2. Confirm that Splunk is running by navigating to http://localhost:8001 68 | 69 | ### Deploy the app 70 | 71 | 1. Package the app: 72 | 73 | ``` 74 | ./package.sh 75 | ``` 76 | 77 | This will produce a packaged Splunk app in `output/bitwarden_event_logs.tar.gz`. 78 | 79 | 2. Deploy the app to Splunk: 80 | 81 | ``` 82 | ./deploy.sh 83 | ``` 84 | 85 | This will restart Splunk and it may take a few seconds to become available again after the script 86 | is finished 87 | 88 | 3. (optional) Check the logs for errors or for debugging purposes later: 89 | ``` 90 | docker exec -u splunk -it splunk tail -f /opt/splunk/var/log/splunk/bitwarden_event_logs.log 91 | ``` 92 | 93 | ### Configure the app in Splunk 94 | 95 | 1. Navigate to the Splunk web app: http://localhost:8001. 96 | 97 | 2. Log in with the username `admin` and the password `password`. 98 | 99 | 3. Click on the _Apps_ -> _Bitwarden Event Logs_. 100 | 101 | 4. Complete the setup. Refer to the [Bitwarden Help Center][Bitwarden Splunk SIEM] for more 102 | information about configuration. 103 | 104 | :::warning 105 | 106 | Splunk uses https and requires additional configuration to work with your local dev server. We don't 107 | have instructions for this yet. In the meantime, we recommend configuring Splunk to use a Bitwarden 108 | cloud deployment (such as production or an internal QA environment). 109 | 110 | ::: 111 | 112 | You should now see your organization events in _Apps_ -> _Bitwarden Event Logs_ -> _Dashboards_. If 113 | no event logs appear, check the Splunk logs (see above). 114 | 115 | [Bitwarden Splunk SIEM]: https://bitwarden.com/help/splunk-siem/ 116 | [poetry]: https://python-poetry.org/docs/#installation 117 | -------------------------------------------------------------------------------- /docs/architecture/security/principles/01-servers-are-zero-knowledge.mdx: -------------------------------------------------------------------------------- 1 | # P01 - Servers are zero knowledge 2 | 3 | There is no possibility for an attacker or Bitwarden employee to access your unencrypted data by 4 | compromising Bitwarden's infrastructure. Bitwarden has no ability to decrypt or add to your data. 5 | Your key, which Bitwarden cannot access, is the only thing that can be used to decrypt your data or 6 | create new encrypted data. 7 | 8 | More precisely, the special status of providing a network sync for client data does not grant the 9 | server, or any intermediary between the server and client, the ability to reduce the effective 10 | security of the protections that guard a user's data. If a user chooses a weaker form of protection 11 | (e.g., a password instead of a passkey), that is an intentional user decision, but the server must 12 | not be able to manipulate or coerce a client into reducing security beyond what the user knowingly 13 | configures. Additionally, the server or it's infrastructure cannot masquerade it's own plaintext 14 | data as belonging in the set of the user's encrypted data. The total sum of a user's encrypted data 15 | is fully isolated from the server and infrastructure; it cannot be read nor expanded outside of the 16 | user's client context. 17 | 18 | This is what we mean when we sometimes refer to "end-to-end encrypted" or "zero knowledge". 19 | 20 | ## Threat model 21 | 22 | - An attacker able to view and/or edit database data belonging to a user they do not own 23 | - An attacker able to create, edit, and fully control network responses to a client 24 | 25 | Some examples of attackers included in this list could be Bitwarden employees, network 26 | administrators, CDNs, and any MITM that can circumvent TLS protection. 27 | 28 | ## Security goals 29 | 30 | - Attackers cannot retrieve decrypted vault data 31 | - Attackers cannot retrieve user encryption keys 32 | - Attackers cannot inject arbitrary items as vault data 33 | - Attackers cannot edit vault data\* 34 | 35 | _\* Availability of vault data is not a security goal as attackers have full control over the 36 | database._ 37 | 38 | ## Account key sharing as a feature 39 | 40 | This principle does not mean that plaintext data is never shared, but rather that any such exposure 41 | requires informed and explicit consent from the user and is exclusively between accounts, never to 42 | the server or infrastructure. 43 | 44 | ## Exceptions 45 | 46 | On occasion, product features require breaking this principle in a controlled manner. These 47 | exceptions are always a last resort, tightly limited scope, and we are always looking for 48 | improvements to remove them. All exceptions are outlined here. 49 | 50 | ### Key Connector 51 | 52 | Key connector is a self-host only feature that allows an organization user to log in and unlock with 53 | SSO and no password input. This feature is specifically limited to self-hosted instances due to this 54 | principle. It is possible for a Bitwarden server to create an authentication token, contact the Key 55 | Connector server, and retrieve key material that will allow decryption of a user's encrypted data. 56 | For these reasons we encourage strict isolation of key connector servers to private networks and 57 | only to be used by advanced self-hosted users. 58 | 59 | ### Icons service 60 | 61 | The Bitwarden icons service provides site favicons to decorate vault items in the Bitwarden clients. 62 | To enable this functionality, clients need to send plaintext domain name information to the service. 63 | Communicated information is limited to vault item URIs. These URIs are part of a user's encrypted 64 | content, but we do this to speed up loading of vaults, ensure favicons accurately represent the 65 | associated URI, and avoid leaking vault contents to local network administrators. This feature is 66 | easily disabled in client settings. 67 | -------------------------------------------------------------------------------- /docs/getting-started/server/scim.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_custom_props: 3 | access: bitwarden 4 | sidebar_position: 6 5 | --- 6 | 7 | # SCIM 8 | 9 | SCIM stands for _System for Cross-domain Identity Management_, and uses a direct link between the 10 | Bitwarden server and an identity provider (IdP) to synchronize users and groups from the IdP to the 11 | Bitwarden server. 12 | 13 | :::note 14 | 15 | In some ways, SCIM is similar to Directory Connector. However, Directory Connector works by polling 16 | for changes (e.g. performing scheduled syncs), whereas SCIM works by pushing changes directly to 17 | Bitwarden as they occur. 18 | 19 | ::: 20 | 21 | ## Requirements 22 | 23 | - A [local development server](./guide.md) 24 | - [Web vault](../clients/web-vault/index.mdx) 25 | - An enterprise organization 26 | - Mailcatcher or a similar local mail service so that you don't spam real email addresses with test 27 | invites (this is included in the server setup guide) 28 | 29 | ## Steps 30 | 31 | ### Enable SCIM for your Organization 32 | 33 | 1. Log in to the web vault and navigate to your organization -> Settings -> SCIM Provisioning 34 | 2. Tick "Enable SCIM" and click save. Your SCIM URL and API Key should appear. Leave this window 35 | open for future reference 36 | 37 | ### Start the SCIM Project 38 | 39 | 3. Start the SCIM project in your local server repository: 40 | 41 | ```bash 42 | cd bitwarden_license/src/Scim 43 | dotnet run 44 | ``` 45 | 46 | 4. Verify that the SCIM project started successfully by navigating to `http://localhost:44559/alive` 47 | 48 | ### Expose your Local Port 49 | 50 | SCIM requires a direct connection between your SCIM project and the IdP. Therefore, you need to 51 | expose your local port to the internet. Please follow any of the guides on 52 | [Ingress Tunnels](./tunnel.md) to do this. The default port to expose is `44559`. 53 | 54 | ### Configure IdP 55 | 56 | This guide uses JumpCloud as a test IdP. Okta is also suitable for testing, although you should be 57 | able to use any IdP that supports SCIM. 58 | 59 | You can also refer to the 60 | [JumpCloud SCIM help documentation](https://support.jumpcloud.com/support/s/article/Custom-SCIM-Identity-Management) 61 | if required. 62 | 63 | 1. Create an account and log in to the 64 | [JumpCloud admin interface](https://console.jumpcloud.com/login/admin) 65 | 66 | 2. Click "SSO" on the left-hand side, then click the Plus button to create a new application. 67 | 68 | 3. Search for "Bitwarden" in the list of applications and click "Configure" 69 | 70 | 4. In the "General Info" tab, add a display name 71 | 72 | 5. In the "Identity Management" tab, scroll down to the "Configuration Settings" section and 73 | complete it as follows: 74 | - **API Type**: SCIM API 75 | - **SCIM Version**: SCIM 2.0 76 | - **Base URL**: use the SCIM URL from your web vault, but replace `localhost` with your ngrok 77 | forwarding url. For example, 78 | `https://abcd-123-456-789.au.ngrok.io/v2/d24f1dcd-d3fb-4810-977e-adf00009f0ca` 79 | - **Token Key**: use the SCIM API Key from your web vault 80 | - **Test user email**: use any email address that doesn't already have a user account. JumpCloud 81 | will use this to perform test operations when you test the connection 82 | 83 | 6. Click "Test Connection" and wait for JumpCloud to complete its tests. You should see the HTTP 84 | requests coming through in your ngrok window. 85 | 86 | 7. Click "Activate" once the tests have passed. 87 | 88 | 8. In the "User Groups" tab, link this connection with the "All Users" group. 89 | 90 | ### Test 91 | 92 | You should be set up and ready to go! You can test your SCIM integration by adding and removing 93 | users in JumpCloud. Make sure that your users belong to the All Users group. You should see your 94 | changes reflected in Bitwarden almost immediately. 95 | 96 | You can also suspend and activate users in JumpCloud, which corresponds to the revoked and restore 97 | operations in Bitwarden. 98 | -------------------------------------------------------------------------------- /docs/architecture/adr/0003-observable-data-services.md: -------------------------------------------------------------------------------- 1 | --- 2 | adr: "0003" 3 | status: Accepted 4 | date: 2022-06-30 5 | tags: [clients, angular] 6 | --- 7 | 8 | # 0003 - Adopt Observable Data Services for Angular 9 | 10 | 11 | 12 | ## Context and problem statement 13 | 14 | Many of our components and services are tightly coupled towards the state of different domains. This 15 | results in tight coupling and difficulty in modifying the different areas. This has lead to 16 | `MessagingService` service being used to synchronize state updates by sending events. While event 17 | sourcing is a perfectly valid way of developing software, our current events are empty, which 18 | results in the components re-fetching their state manually. 19 | 20 | ## Considered options 21 | 22 | - [Observable/Reactive Data Services][observable] 23 | - [NGRX](https://ngrx.io/) - Reactive State for Angular (Redux implementation) 24 | 25 | ## Decision outcome 26 | 27 | Chosen option: **Observable data services**, because 28 | 29 | - Allows us to quickly iterate towards a more reactive data model. 30 | - Reactive data model lets us get rid of the event messages. 31 | - Components will always display the latest state. 32 | - Does not require a significant upfront investment. 33 | - The work towards a reactive data model will allow us to adopt patterns like NGRX in the future 34 | should it be needed. 35 | 36 | :::info Updated Guidance 37 | 38 | This ADR remains valid for business logic services, but [ADR 0029][signals] introduces Angular 39 | Signals as the preferred approach over RxJS for view layer code (components, directives, pipes, and 40 | UI-coupled services). 41 | 42 | ::: 43 | 44 | ### Example 45 | 46 | #### Organizations 47 | 48 | The `OrganizationService` should take ownership of all Organization related data. 49 | 50 | ```ts 51 | class OrganizationService { 52 | private _organizations: new BehaviorSubject([]); 53 | organizations$: Observable = this._organizations$.asObservable(); 54 | 55 | async save(organizations: { [adr: string]: OrganizationData }) { 56 | await this._organizations$.next(await this.decryptOrgs(this._activeAccount, organizations)); 57 | } 58 | } 59 | 60 | class Component implements OnDestroy { 61 | private destroy$: Subject = new Subject(); 62 | 63 | ngInit() { 64 | this._organizationService.organizations$ 65 | .pipe(takeUntil(this.destroy$)) 66 | .subscribe((orgs) => { 67 | this.orgs = orgs; 68 | }); 69 | } 70 | 71 | ngOnDestroy() { 72 | this.destroy$.next(); 73 | this.destroy$.unsubscribe(); 74 | } 75 | } 76 | ``` 77 | 78 | In this example we use the `takeUntil` pattern which can be combined with an eslint rule to ensure 79 | each component cleans up after themselves. 80 | 81 | ## Pros and Cons of the Options 82 | 83 | ### Observable Data Services 84 | 85 | - Good: Lightweight 86 | - Good: Can be refactored incrementally 87 | - Good: Reactive, will notify on changes. 88 | - Bad: No strict standard, more a set of guidelines. 89 | - Bad: State is split into multiple tiny "stores" 90 | 91 | ### NGRX 92 | 93 | NGRX is the most popular Redux implementation for Angular. For more details, read about the 94 | [motivation behind redux][redux-motivation] and view this 95 | [diagram of NGRX architecture](https://ngrx.io/guide/store). 96 | 97 | - Good: Most popular redux library for Angular 98 | - Good: Decouples components 99 | - Good: Single state which simplifies operations 100 | - Bad: Requires a significant rewrite of the whole state layer 101 | - Bad: Adds complexity and can make it difficult to understand the data flow. 102 | 103 | [observable]: 104 | https://blog.angular-university.io/how-to-build-angular2-apps-using-rxjs-observable-data-services-pitfalls-to-avoid/ 105 | [redux-motivation]: https://redux.js.org/understanding/thinking-in-redux/motivation 106 | [signals]: ./0029-angular-signals.md 107 | -------------------------------------------------------------------------------- /docs/architecture/adr/0010-angular-ngmodules.md: -------------------------------------------------------------------------------- 1 | --- 2 | adr: "0010" 3 | status: Deprecated 4 | date: 2022-07-25 5 | tags: [clients, angular] 6 | --- 7 | 8 | # 0010 - Angular Modules 9 | 10 | 11 | 12 | :::warning Deprecated 13 | 14 | Deprecated as of 2025-11-25: Angular has stabilized Standalone Components and has deprecated 15 | NgModules. Standalone is the preferred way of organizing components going forward. 16 | 17 | ::: 18 | 19 | ## Context and problem statement 20 | 21 | > NgModules are containers for a cohesive block of code dedicated to an application domain, a 22 | > workflow, or a closely related set of capabilities. They can contain components, service 23 | > providers, and other code files whose scope is defined by the containing NgModule. They can import 24 | > functionality that is exported from other NgModules, and export selected functionality for use by 25 | > other NgModules. 26 | > 27 | > -- https://angular.io/guide/architecture-modules 28 | 29 | In ADR [0002 Define public module in NPM packages](./0002-public-module-npm-packages.md) we decided 30 | to start using barrel files and restrict imports from other "modules". This solves some of the pain 31 | points we have encountered, however all components are still exported in the barrel files since they 32 | need to be defined in an Angular Module. This limits the usefulness of the barrel files. 33 | 34 | Angular encourages creating many small NgModules, with people advocating for either one Module per 35 | feature, or going so far as defining one module per component. In Angular v14 this was made easier 36 | with the introduction of [standalone components](https://angular.io/guide/standalone-components). 37 | 38 | ## Considered options 39 | 40 | - **Do nothing** - Maintain the status quo and define most components in a single module. This would 41 | mean that each component is still essentially global. 42 | - **[Angular Modules](https://angular.io/guide/architecture-modules)** - Add NgModules alongside our 43 | barrel files. This allows for proper encapsulation of internal components. 44 | - **[Standalone Components](https://angular.io/guide/standalone-components)** - provides the 45 | benefits of NgModules without most of the additional boilerplate. Is still in preview and is 46 | therefore risky to rely on. 47 | 48 | ## Decision outcome 49 | 50 | Chosen option: **Angular Modules** 51 | 52 | ### Positive consequences 53 | 54 | - Internal components cannot be re-used outside of the feature. 55 | - Modules are required for supporting lazy loading. 56 | - Similar structure as _Standalone Components_ which will allow for easy migration in the future 57 | should this be deemed necessary. 58 | 59 | ### Negative consequences 60 | 61 | - Angular error handling for NgModules is awful and provides cryptic errors that are hard to debug. 62 | - Additional boilerplate. 63 | 64 | ## Guidelines 65 | 66 | - Aim to export as few components as possible. In many cases you don't need to export any components 67 | at all, and can instead encapsulate the routing within that module which allows for it to be lazy 68 | loaded should it be deemed useful. 69 | - Functionality that needs to be shared across all modules should be placed in the `Shared` feature. 70 | - Consider creating a `feature/shared` module in case additional functionality needs to be shared 71 | between modules such as the _Individual Vault_ and _Organization Vault_. 72 | 73 | ### Implementation 74 | 75 | An example of a feature module would be the **reports**. We know that reports are used both for the 76 | individual users and for organizations. 77 | 78 | ```text 79 | reports 80 | shared 81 | report-card.component 82 | report-list.component 83 | 84 | reports-shared.module.ts 85 | index.ts 86 | reports 87 | breach-report.component 88 | ... 89 | reports.module.ts -> depends on reports-shared.module.ts 90 | reports.component.ts 91 | index.ts 92 | 93 | organizations 94 | reports 95 | organization-reports.module.ts -> depends on reports-shared.module.ts 96 | ``` 97 | -------------------------------------------------------------------------------- /docs/getting-started/server/portal.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 8 3 | --- 4 | 5 | # System Management Portal 6 | 7 | :::info Portal naming 8 | 9 | This documentation refers to the deployment of the `Admin` application in our `server` repository. 10 | To disambiguate this application from others in the Bitwarden landscape, we refer to it as follows: 11 | 12 | - For **Cloud-Hosted** Instances (internal to Bitwarden) → **Bitwarden Portal** 13 | - For **Self-Hosted** Instances → **System Management Portal** 14 | 15 | ::: 16 | 17 | ## Setup 18 | 19 | 1. Navigate to the `server/src/admin` directory. 20 | 2. Restore nuget packages: 21 | 22 | ```bash 23 | dotnet restore 24 | ``` 25 | 26 | 3. Install npm packages: 27 | 28 | ```bash 29 | npm ci 30 | ``` 31 | 32 | 4. Build the admin project: 33 | 34 | ```bash 35 | dotnet build 36 | ``` 37 | 38 | 5. Build out the `wwwroot` directory with the necessary stylesheets and libraries: 39 | 40 | ```bash 41 | npm run build 42 | ``` 43 | 44 | 6. Start the server: 45 | 46 | ```bash 47 | dotnet run 48 | ``` 49 | 50 | 7. Confirm it's working by using your favorite browser to navigate to the portal URL. By default, 51 | this is [http://localhost:62911](http://localhost:62911). 52 | 53 | ## Configuring access 54 | 55 | ### Authentication 56 | 57 | Portal authentication is done entirely through a passwordless flow, using a link sent through email. 58 | The email address must be listed in the `adminSettings:admins` user secret to be authorized. 59 | 60 | If you’ve followed the [Server Setup Guide](./guide.md) this should already be configured, with the 61 | following accounts having access: 62 | 63 | - `owner@localhost` 64 | - `admin@localhost` 65 | - `cs@localhost` 66 | - `billing@localhost` 67 | - `sales@localhost` 68 | 69 | If not, please go back and configure it now. 70 | 71 | :::tip 72 | 73 | See [User Secrets](../../contributing/user-secrets.md) for how to configure your user secrets. 74 | 75 | ::: 76 | 77 | 78 | 79 | ### Authorization 80 | 81 | The Bitwarden Portal uses role-based access control to restrict access to application functionality. 82 | In order to have access to the features within the Bitwarden Portal, you will need to assign your 83 | account to a role. This is in addition to the authentication setup above. 84 | 85 | Role membership is defined in the `adminSettings:role` section of the server application 86 | configuration. Each role's members are represented as a comma-delimited list of account email 87 | addresses. For local development, your user secrets will be defined with the following account in 88 | each role: 89 | 90 | | Role | Setting | Default `secrets.json` Value | 91 | | ---------------- | ---------------------------- | ---------------------------- | 92 | | Owner | `adminSettings:role:owner` | `owner@localhost` | 93 | | Admin | `adminSettings:role:admin` | `admin@localhost` | 94 | | Customer Success | `adminSettings:role:cs` | `cs@localhost` | 95 | | Billing | `adminSettings:role:billing` | `billing@localhost` | 96 | | Sales | `adminSettings:role:sales` | `sales@localhost` | 97 | 98 | If you wish to change the membership for any role, you can 99 | [edit your user secrets](../../contributing/user-secrets.md) to specify the desired value. 100 | 101 | :::info 102 | 103 | Role-based access control is only enforced on cloud-hosted instances. There is no role-based access 104 | control on self-hosted deployments. 105 | 106 | ::: 107 | 108 | 109 | 110 | ## Logging in 111 | 112 | 1. Navigate to your portal URL. By default, this is 113 | [http://localhost:62911](http://localhost:62911). 114 | 2. Enter `admin@localhost` as the email (or whatever email you’ve configured in your user secrets) 115 | 3. Open MailCatcher (default is [http://localhost:1080](http://localhost:1080)) and click the login 116 | link. 117 | -------------------------------------------------------------------------------- /docs/contributing/database-migrations/transitions.drawio: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | --------------------------------------------------------------------------------