diff --git a/jslib b/jslib index 57ace408..14b01f2e 160000 --- a/jslib +++ b/jslib @@ -1 +1 @@ -Subproject commit 57ace4084556758fdc2989cf1a8cf6a5d1736a29 +Subproject commit 14b01f2e5da839ffc312deb68e5b298d8fadb363 diff --git a/package-lock.json b/package-lock.json index 5c9e045b..49aac3b7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9906,6 +9906,11 @@ } } }, + "is-docker": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.0.0.tgz", + "integrity": "sha512-pJEdRugimx4fBMra5z2/5iRdZ63OhYV0vr0Dwm5+xtW4D1FvRkB8hamMIhnWfyJeDdyr/aa7BDyNbtG38VxgoQ==" + }, "is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", @@ -10102,6 +10107,14 @@ "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true }, + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "requires": { + "is-docker": "^2.0.0" + } + }, "is-yarn-global": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", @@ -12077,6 +12090,15 @@ "mimic-fn": "^1.0.0" } }, + "open": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/open/-/open-7.1.0.tgz", + "integrity": "sha512-lLPI5KgOwEYCDKXf4np7y1PBEkj7HYIyP2DY8mVDRnx0VIIu6bNrRB0R66TuO7Mack6EnTNLm4uvcl1UoklTpA==", + "requires": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + } + }, "optionator": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", @@ -17324,6 +17346,11 @@ "version": "0.8.28", "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.8.28.tgz", "integrity": "sha512-MjwlvV0wr65IQiT0WSHedo/zUhAqtypMdTUjqroV81RohGj1XANwHuC37dwYxphTRbZBYidk0gNS0dQrU2Q3Pw==" + }, + "zxcvbn": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/zxcvbn/-/zxcvbn-4.4.2.tgz", + "integrity": "sha1-KOwXzwl0PtyrBW3dixsGJizHPDA=" } } } diff --git a/package.json b/package.json index a0f0a929..e505a065 100644 --- a/package.json +++ b/package.json @@ -220,7 +220,9 @@ "lunr": "2.3.3", "node-fetch": "2.2.0", "node-forge": "0.7.6", + "open": "7.1.0", "rxjs": "6.3.3", - "zone.js": "0.8.28" + "zone.js": "0.8.28", + "zxcvbn": "4.4.2" } } diff --git a/src/app/accounts/environment.component.html b/src/app/accounts/environment.component.html index 884871c7..8f541ae3 100644 --- a/src/app/accounts/environment.component.html +++ b/src/app/accounts/environment.component.html @@ -17,6 +17,11 @@

{{'customEnvironment' | i18n}}

{{'customEnvironmentFooter' | i18n}}

+
+ + +
diff --git a/src/app/services/services.module.ts b/src/app/services/services.module.ts index 3897cc18..df4c60ec 100644 --- a/src/app/services/services.module.ts +++ b/src/app/services/services.module.ts @@ -33,6 +33,7 @@ import { ContainerService } from 'jslib/services/container.service'; import { CryptoService } from 'jslib/services/crypto.service'; import { EnvironmentService } from 'jslib/services/environment.service'; import { NodeCryptoFunctionService } from 'jslib/services/nodeCryptoFunction.service'; +import { PasswordGenerationService } from 'jslib/services/passwordGeneration.service'; import { StateService } from 'jslib/services/state.service'; import { TokenService } from 'jslib/services/token.service'; import { UserService } from 'jslib/services/user.service'; @@ -46,6 +47,9 @@ import { EnvironmentService as EnvironmentServiceAbstraction } from 'jslib/abstr import { I18nService as I18nServiceAbstraction } from 'jslib/abstractions/i18n.service'; import { LogService as LogServiceAbstraction } from 'jslib/abstractions/log.service'; import { MessagingService as MessagingServiceAbstraction } from 'jslib/abstractions/messaging.service'; +import { + PasswordGenerationService as PasswordGenerationServiceAbstraction, +} from 'jslib/abstractions/passwordGeneration.service'; import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from 'jslib/abstractions/platformUtils.service'; import { StateService as StateServiceAbstraction } from 'jslib/abstractions/state.service'; import { StorageService as StorageServiceAbstraction } from 'jslib/abstractions/storage.service'; @@ -57,8 +61,8 @@ const i18nService = new I18nService(window.navigator.language, './locales'); const stateService = new StateService(); const broadcasterService = new BroadcasterService(); const messagingService = new ElectronRendererMessagingService(broadcasterService); -const platformUtilsService = new ElectronPlatformUtilsService(i18nService, messagingService, true); const storageService: StorageServiceAbstraction = new ElectronStorageService(remote.app.getPath('userData')); +const platformUtilsService = new ElectronPlatformUtilsService(i18nService, messagingService, true, storageService); const secureStorageService: StorageServiceAbstraction = new ElectronRendererSecureStorageService(); const cryptoFunctionService: CryptoFunctionServiceAbstraction = new NodeCryptoFunctionService(); const cryptoService = new CryptoService(storageService, secureStorageService, cryptoFunctionService); @@ -70,10 +74,11 @@ const environmentService = new EnvironmentService(apiService, storageService, nu const userService = new UserService(tokenService, storageService); const containerService = new ContainerService(cryptoService); const authService = new AuthService(cryptoService, apiService, userService, tokenService, appIdService, - i18nService, platformUtilsService, messagingService, false); + i18nService, platformUtilsService, messagingService, null, false); const configurationService = new ConfigurationService(storageService, secureStorageService); const syncService = new SyncService(configurationService, logService, cryptoFunctionService, apiService, messagingService, i18nService); +const passwordGenerationService = new PasswordGenerationService(cryptoService, storageService, null); const analytics = new Analytics(window, () => true, platformUtilsService, storageService, appIdService); containerService.attachToWindow(window); @@ -134,6 +139,7 @@ export function initFactory(): Function { { provide: LogServiceAbstraction, useValue: logService }, { provide: ConfigurationService, useValue: configurationService }, { provide: SyncService, useValue: syncService }, + { provide: PasswordGenerationServiceAbstraction, useValue: passwordGenerationService }, { provide: APP_INITIALIZER, useFactory: initFactory, diff --git a/src/bwdc.ts b/src/bwdc.ts index b7646d91..606017e6 100644 --- a/src/bwdc.ts +++ b/src/bwdc.ts @@ -22,6 +22,7 @@ import { LowdbStorageService } from 'jslib/services/lowdbStorage.service'; import { NodeApiService } from 'jslib/services/nodeApi.service'; import { NodeCryptoFunctionService } from 'jslib/services/nodeCryptoFunction.service'; import { NoopMessagingService } from 'jslib/services/noopMessaging.service'; +import { PasswordGenerationService } from 'jslib/services/passwordGeneration.service'; import { TokenService } from 'jslib/services/token.service'; import { UserService } from 'jslib/services/user.service'; @@ -52,6 +53,7 @@ export class Main { authService: AuthService; configurationService: ConfigurationService; syncService: SyncService; + passwordGenerationService: PasswordGenerationService; program: Program; constructor() { @@ -92,11 +94,12 @@ export class Main { this.userService = new UserService(this.tokenService, this.storageService); this.containerService = new ContainerService(this.cryptoService); this.authService = new AuthService(this.cryptoService, this.apiService, this.userService, this.tokenService, - this.appIdService, this.i18nService, this.platformUtilsService, this.messagingService, true); + this.appIdService, this.i18nService, this.platformUtilsService, this.messagingService, null, false); this.configurationService = new ConfigurationService(this.storageService, this.secureStorageService, process.env.BITWARDENCLI_CONNECTOR_PLAINTEXT_SECRETS !== 'true'); this.syncService = new SyncService(this.configurationService, this.logService, this.cryptoFunctionService, this.apiService, this.messagingService, this.i18nService); + this.passwordGenerationService = new PasswordGenerationService(this.cryptoService, this.storageService, null); this.program = new Program(this); } diff --git a/src/locales/en/messages.json b/src/locales/en/messages.json index 7a610585..e23335a5 100644 --- a/src/locales/en/messages.json +++ b/src/locales/en/messages.json @@ -140,6 +140,9 @@ "baseUrl": { "message": "Server URL" }, + "webVaultUrl": { + "message": "Web Vault Server URL" + }, "apiUrl": { "message": "API Server URL" }, diff --git a/src/program.ts b/src/program.ts index 5f880fd7..6e56bfb3 100644 --- a/src/program.ts +++ b/src/program.ts @@ -86,6 +86,7 @@ export class Program extends BaseProgram { .description('Log into a user account.') .option('--method ', 'Two-step login method.') .option('--code ', 'Two-step login code.') + .option('--sso', 'Log in with Single-Sign On.') .on('--help', () => { writeLn('\n Notes:'); writeLn(''); @@ -96,11 +97,14 @@ export class Program extends BaseProgram { writeLn(' bw login'); writeLn(' bw login john@example.com myPassword321'); writeLn(' bw login john@example.com myPassword321 --method 1 --code 249213'); + writeLn(' bw login --sso'); writeLn('', true); }) .action(async (email: string, password: string, cmd: program.Command) => { await this.exitIfAuthed(); - const command = new LoginCommand(this.main.authService, this.main.apiService, this.main.i18nService); + const command = new LoginCommand(this.main.authService, this.main.apiService, this.main.i18nService, + this.main.environmentService, this.main.passwordGenerationService, this.main.cryptoFunctionService, + 'connector'); const response = await command.run(email, password, cmd); this.processResponse(response); }); diff --git a/src/services/configuration.service.ts b/src/services/configuration.service.ts index a617da14..7220fc36 100644 --- a/src/services/configuration.service.ts +++ b/src/services/configuration.service.ts @@ -5,8 +5,8 @@ import { AzureConfiguration } from '../models/azureConfiguration'; import { GSuiteConfiguration } from '../models/gsuiteConfiguration'; import { LdapConfiguration } from '../models/ldapConfiguration'; import { OktaConfiguration } from '../models/oktaConfiguration'; +import { OneLoginConfiguration } from '../models/oneLoginConfiguration'; import { SyncConfiguration } from '../models/syncConfiguration'; -import { OneLoginConfiguration } from 'src/models/oneLoginConfiguration'; const StoredSecurely = '[STORED SECURELY]'; const Keys = { diff --git a/src/services/onelogin-directory.service.ts b/src/services/onelogin-directory.service.ts index f03fe2ef..33d7c53a 100644 --- a/src/services/onelogin-directory.service.ts +++ b/src/services/onelogin-directory.service.ts @@ -160,8 +160,8 @@ export class OneLoginDirectoryService extends BaseDirectoryService implements Di const req: RequestInit = { method: 'GET', headers: new Headers({ - 'Authorization': 'bearer:' + this.accessToken, - 'Accept': 'application/json', + Authorization: 'bearer:' + this.accessToken, + Accept: 'application/json', }), }; const response = await fetch(new Request(url, req));