1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-07 20:24:01 +00:00
This commit is contained in:
adudek-bw
2025-05-29 14:41:56 -04:00
parent 6a0be69fb3
commit c47bef2f6d
6 changed files with 60 additions and 26 deletions

View File

@@ -51,6 +51,7 @@ export enum FeatureFlag {
/* Tools */
ItemShare = "item-share",
DesktopSendUIRefresh = "desktop-send-ui-refresh",
UseSdkPasswordGenerators = "use-sdk-password-generators",
/* Vault */
PM8851_BrowserOnboardingNudge = "pm-8851-browser-onboarding-nudge",
@@ -104,6 +105,7 @@ export const DefaultFeatureFlagValue = {
/* Tools */
[FeatureFlag.ItemShare]: FALSE,
[FeatureFlag.DesktopSendUIRefresh]: FALSE,
[FeatureFlag.UseSdkPasswordGenerators]: FALSE,
/* Vault */
[FeatureFlag.PM8851_BrowserOnboardingNudge]: FALSE,

View File

@@ -1,4 +1,5 @@
import { PolicyService } from "../admin-console/abstractions/policy/policy.service.abstraction";
import { ConfigService } from "../platform/abstractions/config/config.service";
import { ExtensionService } from "./extension/extension.service";
import { LogProvider } from "./log";
@@ -13,4 +14,7 @@ export type SystemServiceProvider = {
/** Event monitoring and diagnostic interfaces */
readonly log: LogProvider;
/** Event monitoring and diagnostic interfaces */
readonly configService: ConfigService;
};

View File

@@ -4,6 +4,7 @@ import {
PasswordGeneratorRequest,
} from "@bitwarden/sdk-internal";
import { Type } from "../metadata";
import {
CredentialGenerator,
GenerateRequest,
@@ -12,16 +13,20 @@ import {
PasswordGenerationOptions,
} from "../types";
/** Generation algorithms that produce randomized secrets */
/** Generation algorithms that produce randomized secrets by calling on functionality from the SDK */
export class SdkPasswordRandomizer
implements
CredentialGenerator<PassphraseGenerationOptions>,
CredentialGenerator<PasswordGenerationOptions>
{
/** Instantiates the password randomizer
* @param randomizer data source for random data
* @param client access to SDK client to call upon password/passphrase generation
* @param currentTime gets the current datetime in epoch time
*/
constructor(private client: BitwardenClient) {}
constructor(
private client: BitwardenClient,
private currentTime: () => number,
) {}
generate(
request: GenerateRequest,
@@ -40,8 +45,8 @@ export class SdkPasswordRandomizer
return new GeneratedCredential(
password,
"password",
Date.now(),
Type.password,
this.currentTime(),
request.source,
request.website,
);
@@ -52,8 +57,8 @@ export class SdkPasswordRandomizer
return new GeneratedCredential(
passphrase,
"password",
Date.now(),
Type.password,
this.currentTime(),
request.source,
request.website,
);
@@ -65,16 +70,16 @@ export class SdkPasswordRandomizer
function convertPasswordRequest(settings: PasswordGenerationOptions): PasswordGeneratorRequest {
return {
lowercase: settings.lowercase,
uppercase: settings.uppercase,
numbers: settings.number,
special: settings.special,
length: settings.length,
avoidAmbiguous: settings.ambiguous,
minLowercase: settings.minLowercase,
minUppercase: settings.minUppercase,
minNumber: settings.minNumber,
minSpecial: settings.minSpecial,
lowercase: settings.lowercase!,
uppercase: settings.uppercase!,
numbers: settings.number!,
special: settings.special!,
length: settings.length!,
avoidAmbiguous: settings.ambiguous!,
minLowercase: settings.minLowercase!,
minUppercase: settings.minUppercase!,
minNumber: settings.minNumber!,
minSpecial: settings.minSpecial!,
};
}
@@ -82,10 +87,10 @@ function convertPassphraseRequest(
settings: PassphraseGenerationOptions,
): PassphraseGeneratorRequest {
return {
numWords: settings.numWords,
wordSeparator: settings.wordSeparator,
capitalize: settings.capitalize,
includeNumber: settings.includeNumber,
numWords: settings.numWords!,
wordSeparator: settings.wordSeparator!,
capitalize: settings.capitalize!,
includeNumber: settings.includeNumber!,
};
}

View File

@@ -9,10 +9,10 @@ export const Algorithm = Object.freeze({
passphrase: "passphrase",
/** A password composed of random characters, retrieved from SDK */
sdkPassword: "sdkpassword",
sdkPassword: "sdkPassword",
/** A password composed of random words from the EFF word list, retrieved from SDK */
sdkPassphrase: "sdkpassphrase",
sdkPassphrase: "sdkPassphrase",
/** A username composed of words from the EFF word list */
username: "username",

View File

@@ -22,7 +22,7 @@ export function availableAlgorithms(policies: Policy[]): CredentialAlgorithm[] {
...AlgorithmsByType[Type.username],
];
if (overridePassword) {
policy.push(overridePassword);
policy.push(overridePassword); //introduce additional password/passphrase stuff
} else {
policy.push(...AlgorithmsByType[Type.password]);
}

View File

@@ -2,6 +2,7 @@ import {
Observable,
combineLatestWith,
distinctUntilChanged,
first,
map,
shareReplay,
switchMap,
@@ -29,6 +30,8 @@ import {
Algorithms,
Types,
} from "../metadata";
import sdkPassphrase from "../metadata/password/sdk-eff-word-list";
import sdkPassword from "../metadata/password/sdk-random-password";
import { availableAlgorithms } from "../policies/available-algorithms-policy";
import { CredentialPreference } from "../types";
import {
@@ -41,6 +44,7 @@ import {
import { PREFERENCES } from "./credential-preferences";
/** Surfaces contextual information to credential generators */
export class GeneratorMetadataProvider {
/** Instantiates the context provider
@@ -83,7 +87,7 @@ export class GeneratorMetadataProvider {
result = toForwarderMetadata(extension);
} else {
result = this._metadata.get(algorithm);
result = this._metadata.get(algorithm).pipe(first());
}
if (!result) {
@@ -93,6 +97,25 @@ export class GeneratorMetadataProvider {
return result;
}
private metadataBySdkFlag(
algorithm: GeneratorMetadata<unknown & object>,
useSdkService: boolean,
): GeneratorMetadata<unknown & object> {
if (useSdkService) {
if (algorithm.id == "password") {
return sdkPassword;
} else if (algorithm.id == "passphrase") {
return sdkPassphrase;
}
}
return algorithm;
}
// metadata$ built by reading config service
// use memoizedMap() to wrap call (creating the map)
// 86 _metadata, new metadata will be encapsulated in observable
// distinctUntilChanged() after memoized map
/** retrieve credential types */
types(): ReadonlyArray<CredentialType> {
return Types;
@@ -148,7 +171,7 @@ export class GeneratorMetadataProvider {
const policies$ = this.application.policy
.policiesByType$(PolicyType.PasswordGenerator, id)
.pipe(
map((p) => availableAlgorithms(p).filter((a) => this._metadata.has(a))),
map((p) => availableAlgorithms(p).filter((a) => this._metadata.has(a))), // filter the list down based on feature flag, withLatestReady to pull in config
memoizedMap((p) => new Set(p), { key: (p) => JSON.stringify(p) }),
distinctUntilChanged(),
// complete policy emissions otherwise `switchMap` holds `available$` open indefinitely