diff --git a/apps/desktop/electron-builder.json b/apps/desktop/electron-builder.json
index 83bd2921551..481d12f02b4 100644
--- a/apps/desktop/electron-builder.json
+++ b/apps/desktop/electron-builder.json
@@ -85,7 +85,8 @@
"signIgnore": [
"MacOS/desktop_proxy",
"MacOS/desktop_proxy.inherit",
- "Contents/Plugins/autofill-extension.appex"
+ "Contents/Plugins/autofill-extension.appex",
+ "Frameworks/Electron Framework.framework/(Electron Framework|Libraries|Resources|Versions/Current)/.*"
],
"target": ["dmg", "zip"]
},
diff --git a/apps/desktop/macos/autofill-extension/autofill_extension_enabled.entitlements b/apps/desktop/macos/autofill-extension/autofill_extension_enabled.entitlements
new file mode 100644
index 00000000000..49fda8f8af8
--- /dev/null
+++ b/apps/desktop/macos/autofill-extension/autofill_extension_enabled.entitlements
@@ -0,0 +1,14 @@
+
+
+
+
+ com.apple.security.app-sandbox
+
+ com.apple.security.application-groups
+
+ LTZ2PFU5D6.com.bitwarden.desktop
+
+ com.apple.developer.authentication-services.autofill-credential-provider
+
+
+
diff --git a/apps/desktop/macos/desktop.xcodeproj/project.pbxproj b/apps/desktop/macos/desktop.xcodeproj/project.pbxproj
index ed19fc9ef5d..c3cb34b6bea 100644
--- a/apps/desktop/macos/desktop.xcodeproj/project.pbxproj
+++ b/apps/desktop/macos/desktop.xcodeproj/project.pbxproj
@@ -256,7 +256,7 @@
isa = XCBuildConfiguration;
baseConfigurationReference = D83832AD2D67B9D0003FB9F8 /* ReleaseDeveloper.xcconfig */;
buildSettings = {
- CODE_SIGN_ENTITLEMENTS = "autofill-extension/autofill_extension.entitlements";
+ CODE_SIGN_ENTITLEMENTS = "autofill-extension/autofill_extension_enabled.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Mac Developer";
CODE_SIGN_STYLE = Manual;
@@ -409,7 +409,7 @@
isa = XCBuildConfiguration;
baseConfigurationReference = D83832AB2D67B9AE003FB9F8 /* Debug.xcconfig */;
buildSettings = {
- CODE_SIGN_ENTITLEMENTS = "autofill-extension/autofill_extension.entitlements";
+ CODE_SIGN_ENTITLEMENTS = "autofill-extension/autofill_extension_enabled.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Mac Developer";
CODE_SIGN_STYLE = Manual;
diff --git a/apps/desktop/macos/desktop.xcodeproj/xcshareddata/xcschemes/autofill-extension.xcscheme b/apps/desktop/macos/desktop.xcodeproj/xcshareddata/xcschemes/autofill-extension.xcscheme
new file mode 100644
index 00000000000..18357be4570
--- /dev/null
+++ b/apps/desktop/macos/desktop.xcodeproj/xcshareddata/xcschemes/autofill-extension.xcscheme
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/desktop/package.json b/apps/desktop/package.json
index ad20e7c0e69..174f3a22a23 100644
--- a/apps/desktop/package.json
+++ b/apps/desktop/package.json
@@ -46,7 +46,7 @@
"pack:mac:with-extension": "npm run clean:dist && npm run build:macos-extension:mac && electron-builder --mac --universal -p never",
"pack:mac:arm64": "npm run clean:dist && electron-builder --mac --arm64 -p never",
"pack:mac:mas": "npm run clean:dist && npm run build:macos-extension:mas && electron-builder --mac mas --universal -p never",
- "pack:mac:masdev": "npm run clean:dist && npm run build:macos-extension:masdev && electron-builder --mac mas-dev --universal -p never",
+ "pack:mac:masdev": "npm run clean:dist && electron-builder --mac mas-dev --universal -p never -c.mac.identity=null -c.mas.identity=$CSC_NAME -c.mas.provisioningProfile=bitwarden_desktop_developer_id.provisionprofile -c.mas.entitlements=resources/entitlements.mas.autofill-enabled.plist",
"pack:local:mac": "npm run clean:dist && npm run build:macos-extension:masdev && electron-builder --mac mas-dev --universal -p never -c.mac.provisioningProfile=\"\" -c.mas.provisioningProfile=\"\"",
"pack:win": "npm run clean:dist && electron-builder --win --x64 --arm64 --ia32 -p never",
"pack:win:beta": "npm run clean:dist && electron-builder --config electron-builder.beta.json --win --x64 --arm64 --ia32 -p never",
diff --git a/apps/desktop/resources/entitlements.mas.autofill-enabled.plist b/apps/desktop/resources/entitlements.mas.autofill-enabled.plist
new file mode 100644
index 00000000000..f25780e5c12
--- /dev/null
+++ b/apps/desktop/resources/entitlements.mas.autofill-enabled.plist
@@ -0,0 +1,42 @@
+
+
+
+
+ com.apple.application-identifier
+ LTZ2PFU5D6.com.bitwarden.desktop
+ com.apple.developer.team-identifier
+ LTZ2PFU5D6
+ com.apple.security.app-sandbox
+
+ com.apple.security.application-groups
+
+ LTZ2PFU5D6.com.bitwarden.desktop
+
+ com.apple.security.cs.allow-jit
+
+ com.apple.security.device.usb
+
+ com.apple.security.files.user-selected.read-write
+
+ com.apple.security.network.client
+
+ com.apple.security.temporary-exception.files.home-relative-path.read-write
+
+ /Library/Application Support/Mozilla/NativeMessagingHosts/
+ /Library/Application Support/Google/Chrome/NativeMessagingHosts/
+ /Library/Application Support/Google/Chrome Beta/NativeMessagingHosts/
+ /Library/Application Support/Google/Chrome Dev/NativeMessagingHosts/
+ /Library/Application Support/Google/Chrome Canary/NativeMessagingHosts/
+ /Library/Application Support/Chromium/NativeMessagingHosts/
+ /Library/Application Support/Microsoft Edge/NativeMessagingHosts/
+ /Library/Application Support/Microsoft Edge Beta/NativeMessagingHosts/
+ /Library/Application Support/Microsoft Edge Dev/NativeMessagingHosts/
+ /Library/Application Support/Microsoft Edge Canary/NativeMessagingHosts/
+ /Library/Application Support/Vivaldi/NativeMessagingHosts/
+ /Library/Application Support/Zen/NativeMessagingHosts/
+ /Library/Application Support/net.imput.helium
+
+ com.apple.developer.authentication-services.autofill-credential-provider
+
+
+
diff --git a/apps/desktop/scripts/after-sign.js b/apps/desktop/scripts/after-sign.js
index 4275ec7d051..0e0e22fc24a 100644
--- a/apps/desktop/scripts/after-sign.js
+++ b/apps/desktop/scripts/after-sign.js
@@ -16,7 +16,9 @@ async function run(context) {
const appPath = `${context.appOutDir}/${appName}.app`;
const macBuild = context.electronPlatformName === "darwin";
const copySafariExtension = ["darwin", "mas"].includes(context.electronPlatformName);
- const copyAutofillExtension = ["darwin"].includes(context.electronPlatformName); // Disabled for mas builds
+ const isMasDevBuild =
+ context.electronPlatformName === "mas" && context.targets.at(0)?.name === "mas-dev";
+ const copyAutofillExtension = ["darwin"].includes(context.electronPlatformName) || isMasDevBuild;
let shouldResign = false;
@@ -31,7 +33,6 @@ async function run(context) {
fse.mkdirSync(path.join(appPath, "Contents/PlugIns"));
}
fse.copySync(extensionPath, path.join(appPath, "Contents/PlugIns/autofill-extension.appex"));
- shouldResign = true;
}
}
diff --git a/apps/desktop/src/autofill/services/desktop-autofill.service.ts b/apps/desktop/src/autofill/services/desktop-autofill.service.ts
index c50964e31e3..e5cd85aa7a3 100644
--- a/apps/desktop/src/autofill/services/desktop-autofill.service.ts
+++ b/apps/desktop/src/autofill/services/desktop-autofill.service.ts
@@ -10,6 +10,7 @@ import {
mergeMap,
switchMap,
takeUntil,
+ tap,
} from "rxjs";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
@@ -52,6 +53,8 @@ import type { NativeWindowObject } from "./desktop-fido2-user-interface.service"
export class DesktopAutofillService implements OnDestroy {
private destroy$ = new Subject();
private registrationRequest: autofill.PasskeyRegistrationRequest;
+ private featureFlag?: FeatureFlag;
+ private isEnabled: boolean = false;
constructor(
private logService: LogService,
@@ -60,19 +63,26 @@ export class DesktopAutofillService implements OnDestroy {
private fido2AuthenticatorService: Fido2AuthenticatorServiceAbstraction,
private accountService: AccountService,
private authService: AuthService,
- private platformUtilsService: PlatformUtilsService,
- ) {}
+ platformUtilsService: PlatformUtilsService,
+ ) {
+ const deviceType = platformUtilsService.getDevice();
+ if (deviceType === DeviceType.MacOsDesktop) {
+ this.featureFlag = FeatureFlag.MacOsNativeCredentialSync;
+ }
+ }
async init() {
- // Currently only supported for MacOS
- if (this.platformUtilsService.getDevice() !== DeviceType.MacOsDesktop) {
+ this.isEnabled =
+ this.featureFlag && (await this.configService.getFeatureFlag(this.featureFlag));
+ if (!this.isEnabled) {
return;
}
this.configService
- .getFeatureFlag$(FeatureFlag.MacOsNativeCredentialSync)
+ .getFeatureFlag$(this.featureFlag)
.pipe(
distinctUntilChanged(),
+ tap((enabled) => (this.isEnabled = enabled)),
filter((enabled) => enabled === true), // Only proceed if feature is enabled
switchMap(() => {
return combineLatest([
@@ -199,11 +209,11 @@ export class DesktopAutofillService implements OnDestroy {
listenIpc() {
ipc.autofill.listenPasskeyRegistration(async (clientId, sequenceNumber, request, callback) => {
- if (!(await this.configService.getFeatureFlag(FeatureFlag.MacOsNativeCredentialSync))) {
+ if (!this.isEnabled) {
this.logService.debug(
- "listenPasskeyRegistration: MacOsNativeCredentialSync feature flag is disabled",
+ `listenPasskeyRegistration: Native credential sync feature flag (${this.featureFlag}) is disabled`,
);
- callback(new Error("MacOsNativeCredentialSync feature flag is disabled"), null);
+ callback(new Error("Native credential sync feature flag is disabled"), null);
return;
}
@@ -230,11 +240,11 @@ export class DesktopAutofillService implements OnDestroy {
ipc.autofill.listenPasskeyAssertionWithoutUserInterface(
async (clientId, sequenceNumber, request, callback) => {
- if (!(await this.configService.getFeatureFlag(FeatureFlag.MacOsNativeCredentialSync))) {
+ if (!this.isEnabled) {
this.logService.debug(
- "listenPasskeyAssertionWithoutUserInterface: MacOsNativeCredentialSync feature flag is disabled",
+ `listenPasskeyAssertionWithoutUserInterface: Native credential sync feature flag (${this.featureFlag}) is disabled`,
);
- callback(new Error("MacOsNativeCredentialSync feature flag is disabled"), null);
+ callback(new Error("Native credential sync feature flag is disabled"), null);
return;
}
@@ -297,11 +307,11 @@ export class DesktopAutofillService implements OnDestroy {
);
ipc.autofill.listenPasskeyAssertion(async (clientId, sequenceNumber, request, callback) => {
- if (!(await this.configService.getFeatureFlag(FeatureFlag.MacOsNativeCredentialSync))) {
+ if (!this.isEnabled) {
this.logService.debug(
- "listenPasskeyAssertion: MacOsNativeCredentialSync feature flag is disabled",
+ `listenPasskeyAssertion: Native credential sync feature flag (${this.featureFlag}) is disabled`,
);
- callback(new Error("MacOsNativeCredentialSync feature flag is disabled"), null);
+ callback(new Error("Native credential sync feature flag is disabled"), null);
return;
}
@@ -324,9 +334,9 @@ export class DesktopAutofillService implements OnDestroy {
// Listen for native status messages
ipc.autofill.listenNativeStatus(async (clientId, sequenceNumber, status) => {
- if (!(await this.configService.getFeatureFlag(FeatureFlag.MacOsNativeCredentialSync))) {
+ if (!this.isEnabled) {
this.logService.debug(
- "listenNativeStatus: MacOsNativeCredentialSync feature flag is disabled",
+ `listenNativeStatus: Native credential sync feature flag (${this.featureFlag}) is disabled`,
);
return;
}