Merge pull request #1353 from bitwarden/feature/sso

Modifications made to support SSO in Browser
This commit is contained in:
Matt Smith 2020-08-20 10:49:27 -05:00 committed by GitHub
commit 07f89963e2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 219 additions and 24 deletions

View File

@ -19,6 +19,9 @@
"login": { "login": {
"message": "Log In" "message": "Log In"
}, },
"enterpriseSingleSignOn": {
"message": "Enterprise Single Sign-On"
},
"cancel": { "cancel": {
"message": "Cancel" "message": "Cancel"
}, },
@ -1297,4 +1300,4 @@
"vaultTimeoutLogOutConfirmationTitle": { "vaultTimeoutLogOutConfirmationTitle": {
"message": "Timeout Action Confirmation" "message": "Timeout Action Confirmation"
} }
} }

View File

@ -4,6 +4,7 @@ import {
ApiService, ApiService,
AppIdService, AppIdService,
AuditService, AuditService,
AuthService,
CipherService, CipherService,
CollectionService, CollectionService,
ConstantsService, ConstantsService,
@ -13,6 +14,7 @@ import {
FolderService, FolderService,
PasswordGenerationService, PasswordGenerationService,
SettingsService, SettingsService,
StateService,
SyncService, SyncService,
TokenService, TokenService,
TotpService, TotpService,
@ -31,6 +33,7 @@ import {
ApiService as ApiServiceAbstraction, ApiService as ApiServiceAbstraction,
AppIdService as AppIdServiceAbstraction, AppIdService as AppIdServiceAbstraction,
AuditService as AuditServiceAbstraction, AuditService as AuditServiceAbstraction,
AuthService as AuthServiceAbstraction,
CipherService as CipherServiceAbstraction, CipherService as CipherServiceAbstraction,
CollectionService as CollectionServiceAbstraction, CollectionService as CollectionServiceAbstraction,
CryptoService as CryptoServiceAbstraction, CryptoService as CryptoServiceAbstraction,
@ -41,6 +44,7 @@ import {
PasswordGenerationService as PasswordGenerationServiceAbstraction, PasswordGenerationService as PasswordGenerationServiceAbstraction,
PlatformUtilsService as PlatformUtilsServiceAbstraction, PlatformUtilsService as PlatformUtilsServiceAbstraction,
SettingsService as SettingsServiceAbstraction, SettingsService as SettingsServiceAbstraction,
StateService as StateServiceAbstraction,
StorageService as StorageServiceAbstraction, StorageService as StorageServiceAbstraction,
SyncService as SyncServiceAbstraction, SyncService as SyncServiceAbstraction,
TokenService as TokenServiceAbstraction, TokenService as TokenServiceAbstraction,
@ -74,6 +78,7 @@ import BrowserMessagingService from '../services/browserMessaging.service';
import BrowserPlatformUtilsService from '../services/browserPlatformUtils.service'; import BrowserPlatformUtilsService from '../services/browserPlatformUtils.service';
import BrowserStorageService from '../services/browserStorage.service'; import BrowserStorageService from '../services/browserStorage.service';
import I18nService from '../services/i18n.service'; import I18nService from '../services/i18n.service';
import { PopupUtilsService } from '../popup/services/popup-utils.service';
import { AutofillService as AutofillServiceAbstraction } from '../services/abstractions/autofill.service'; import { AutofillService as AutofillServiceAbstraction } from '../services/abstractions/autofill.service';
@ -101,13 +106,16 @@ export default class MainBackground {
autofillService: AutofillServiceAbstraction; autofillService: AutofillServiceAbstraction;
containerService: ContainerService; containerService: ContainerService;
auditService: AuditServiceAbstraction; auditService: AuditServiceAbstraction;
authService: AuthServiceAbstraction;
exportService: ExportServiceAbstraction; exportService: ExportServiceAbstraction;
searchService: SearchServiceAbstraction; searchService: SearchServiceAbstraction;
notificationsService: NotificationsServiceAbstraction; notificationsService: NotificationsServiceAbstraction;
stateService: StateServiceAbstraction;
systemService: SystemServiceAbstraction; systemService: SystemServiceAbstraction;
eventService: EventServiceAbstraction; eventService: EventServiceAbstraction;
policyService: PolicyServiceAbstraction; policyService: PolicyServiceAbstraction;
analytics: Analytics; analytics: Analytics;
popupUtilsService: PopupUtilsService;
onUpdatedRan: boolean; onUpdatedRan: boolean;
onReplacedRan: boolean; onReplacedRan: boolean;
@ -147,6 +155,9 @@ export default class MainBackground {
this.apiService = new ApiService(this.tokenService, this.platformUtilsService, this.apiService = new ApiService(this.tokenService, this.platformUtilsService,
(expired: boolean) => this.logout(expired)); (expired: boolean) => this.logout(expired));
this.userService = new UserService(this.tokenService, this.storageService); this.userService = new UserService(this.tokenService, this.storageService);
this.authService = new AuthService(this.cryptoService, this.apiService, this.userService,
this.tokenService, this.appIdService, this.i18nService, this.platformUtilsService,
this.messagingService, this.vaultTimeoutService, null);
this.settingsService = new SettingsService(this.userService, this.storageService); this.settingsService = new SettingsService(this.userService, this.storageService);
this.cipherService = new CipherService(this.cryptoService, this.userService, this.settingsService, this.cipherService = new CipherService(this.cryptoService, this.userService, this.settingsService,
this.apiService, this.storageService, this.i18nService, () => this.searchService); this.apiService, this.storageService, this.i18nService, () => this.searchService);
@ -155,6 +166,7 @@ export default class MainBackground {
this.collectionService = new CollectionService(this.cryptoService, this.userService, this.storageService, this.collectionService = new CollectionService(this.cryptoService, this.userService, this.storageService,
this.i18nService); this.i18nService);
this.searchService = new SearchService(this.cipherService, this.platformUtilsService); this.searchService = new SearchService(this.cipherService, this.platformUtilsService);
this.stateService = new StateService();
this.policyService = new PolicyService(this.userService, this.storageService); this.policyService = new PolicyService(this.userService, this.storageService);
this.vaultTimeoutService = new VaultTimeoutService(this.cipherService, this.folderService, this.vaultTimeoutService = new VaultTimeoutService(this.cipherService, this.folderService,
this.collectionService, this.cryptoService, this.platformUtilsService, this.storageService, this.collectionService, this.cryptoService, this.platformUtilsService, this.storageService,
@ -190,6 +202,7 @@ export default class MainBackground {
this.notificationsService); this.notificationsService);
this.analytics = new Analytics(window, () => BrowserApi.gaFilter(), this.platformUtilsService, this.analytics = new Analytics(window, () => BrowserApi.gaFilter(), this.platformUtilsService,
this.storageService, this.appIdService); this.storageService, this.appIdService);
this.popupUtilsService = new PopupUtilsService(this.platformUtilsService);
this.systemService = new SystemService(this.storageService, this.vaultTimeoutService, this.systemService = new SystemService(this.storageService, this.vaultTimeoutService,
this.messagingService, this.platformUtilsService, () => { this.messagingService, this.platformUtilsService, () => {
const forceWindowReload = this.platformUtilsService.isSafari() || const forceWindowReload = this.platformUtilsService.isSafari() ||
@ -206,7 +219,8 @@ export default class MainBackground {
// Background // Background
this.runtimeBackground = new RuntimeBackground(this, this.autofillService, this.cipherService, this.runtimeBackground = new RuntimeBackground(this, this.autofillService, this.cipherService,
this.platformUtilsService as BrowserPlatformUtilsService, this.storageService, this.i18nService, this.platformUtilsService as BrowserPlatformUtilsService, this.storageService, this.i18nService,
this.analytics, this.notificationsService, this.systemService, this.vaultTimeoutService); this.analytics, this.notificationsService, this.systemService, this.vaultTimeoutService, this.syncService,
this.authService, this.stateService, this.environmentService, this.popupUtilsService);
this.commandsBackground = new CommandsBackground(this, this.passwordGenerationService, this.commandsBackground = new CommandsBackground(this, this.passwordGenerationService,
this.platformUtilsService, this.analytics, this.vaultTimeoutService); this.platformUtilsService, this.analytics, this.vaultTimeoutService);

View File

@ -4,14 +4,18 @@ import { CipherView } from 'jslib/models/view/cipherView';
import { LoginUriView } from 'jslib/models/view/loginUriView'; import { LoginUriView } from 'jslib/models/view/loginUriView';
import { LoginView } from 'jslib/models/view/loginView'; import { LoginView } from 'jslib/models/view/loginView';
import { ConstantsService } from 'jslib/services/constants.service'; import { AuthService } from 'jslib/abstractions/auth.service';
import { AutofillService } from '../services/abstractions/autofill.service';
import { I18nService } from 'jslib/abstractions/i18n.service'; import BrowserPlatformUtilsService from '../services/browserPlatformUtils.service';
import { Analytics } from 'jslib/misc';
import { CipherService } from 'jslib/abstractions/cipher.service'; import { CipherService } from 'jslib/abstractions/cipher.service';
import { ConstantsService } from 'jslib/services/constants.service';
import { EnvironmentService } from 'jslib/abstractions/environment.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { NotificationsService } from 'jslib/abstractions/notifications.service';
import { PopupUtilsService } from '../popup/services/popup-utils.service';
import { StateService } from 'jslib/abstractions/state.service';
import { StorageService } from 'jslib/abstractions/storage.service'; import { StorageService } from 'jslib/abstractions/storage.service';
import { SyncService } from 'jslib/abstractions/sync.service';
import { SystemService } from 'jslib/abstractions/system.service'; import { SystemService } from 'jslib/abstractions/system.service';
import { VaultTimeoutService } from 'jslib/abstractions/vaultTimeout.service'; import { VaultTimeoutService } from 'jslib/abstractions/vaultTimeout.service';
@ -19,11 +23,7 @@ import { BrowserApi } from '../browser/browserApi';
import MainBackground from './main.background'; import MainBackground from './main.background';
import { AutofillService } from '../services/abstractions/autofill.service'; import { Analytics } from 'jslib/misc';
import BrowserPlatformUtilsService from '../services/browserPlatformUtils.service';
import { NotificationsService } from 'jslib/abstractions/notifications.service';
import { Utils } from 'jslib/misc/utils'; import { Utils } from 'jslib/misc/utils';
export default class RuntimeBackground { export default class RuntimeBackground {
@ -37,7 +37,9 @@ export default class RuntimeBackground {
private cipherService: CipherService, private platformUtilsService: BrowserPlatformUtilsService, private cipherService: CipherService, private platformUtilsService: BrowserPlatformUtilsService,
private storageService: StorageService, private i18nService: I18nService, private storageService: StorageService, private i18nService: I18nService,
private analytics: Analytics, private notificationsService: NotificationsService, private analytics: Analytics, private notificationsService: NotificationsService,
private systemService: SystemService, private vaultTimeoutService: VaultTimeoutService) { private systemService: SystemService, private vaultTimeoutService: VaultTimeoutService,
private syncService: SyncService, private authService: AuthService, private stateService: StateService,
private environmentService: EnvironmentService, private popupUtilsService : PopupUtilsService) {
this.isSafari = this.platformUtilsService.isSafari(); this.isSafari = this.platformUtilsService.isSafari();
this.runtime = this.isSafari ? {} : chrome.runtime; this.runtime = this.isSafari ? {} : chrome.runtime;
@ -162,6 +164,27 @@ export default class RuntimeBackground {
break; break;
} }
break; break;
case 'authResult':
var vaultUrl = this.environmentService.webVaultUrl;
if(!vaultUrl) {
vaultUrl = 'https://vault.bitwarden.com';
}
if(!msg.referrer) {
return;
}
if(!vaultUrl.includes(msg.referrer)) {
return;
}
try {
chrome.tabs.create({
url: 'popup/index.html?uilocation=popout#/sso?code=' + msg.code + '&state=' + msg.state
});
}
catch { }
break;
default: default:
break; break;
} }

View File

@ -213,4 +213,15 @@ export class BrowserApi {
return chrome.runtime.reload(); return chrome.runtime.reload();
} }
} }
static reloadOpenWindows() {
if(!BrowserApi.isSafariApi)
{
var sidebarName : string = 'sidebar';
var sidebarWindows = chrome.extension.getViews({ type: sidebarName });
if(sidebarWindows && sidebarWindows.length > 0) {
sidebarWindows[0].location.reload();
}
}
}
} }

13
src/content/sso.ts Normal file
View File

@ -0,0 +1,13 @@
window.addEventListener("message", function(event) {
if (event.source != window)
return;
if (event.data.command && (event.data.command == "authResult")) {
chrome.runtime.sendMessage({
command: event.data.command,
code: event.data.code,
state: event.data.state,
referrer: event.source.location.hostname
});
}
}, false)

View File

@ -41,6 +41,18 @@
], ],
"run_at": "document_start" "run_at": "document_start"
}, },
{
"all_frames": false,
"js": [
"content/sso.js"
],
"matches": [
"http://*/*",
"https://*/*",
"file:///*"
],
"run_at": "document_start"
},
{ {
"all_frames": true, "all_frames": true,
"css": [ "css": [

View File

@ -3,6 +3,9 @@
<div class="logo-image"></div> <div class="logo-image"></div>
<p class="lead text-center">{{'loginOrCreateNewAccount' | i18n}}</p> <p class="lead text-center">{{'loginOrCreateNewAccount' | i18n}}</p>
<a class="btn primary block" routerLink="/login"><b>{{'login' | i18n}}</b></a> <a class="btn primary block" routerLink="/login"><b>{{'login' | i18n}}</b></a>
<a (click)="launchSsoBrowser()" class="btn block">
<i class="fa fa-bank" aria-hidden="true"></i> {{'enterpriseSingleSignOn' | i18n}}
</a>
<a class="btn block" routerLink="/register">{{'createAccount' | i18n}}</a> <a class="btn block" routerLink="/register">{{'createAccount' | i18n}}</a>
</div> </div>
</div> </div>

View File

@ -1,7 +1,55 @@
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { ConstantsService } from 'jslib/services/constants.service'
import { CryptoFunctionService } from 'jslib/abstractions/cryptoFunction.service';
import { EnvironmentService } from 'jslib/abstractions/environment.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { PasswordGenerationService } from 'jslib/abstractions/passwordGeneration.service';
import { StorageService } from 'jslib/abstractions/storage.service';
import { Utils } from 'jslib/misc/utils';
@Component({ @Component({
selector: 'app-home', selector: 'app-home',
templateUrl: 'home.component.html', templateUrl: 'home.component.html',
}) })
export class HomeComponent { } export class HomeComponent {
constructor(
protected platformUtilsService: PlatformUtilsService,
private passwordGenerationService : PasswordGenerationService,
private cryptoFunctionService: CryptoFunctionService,
private environmentService: EnvironmentService,
private storageService : StorageService) { }
async launchSsoBrowser() {
// Generate necessary sso params
const passwordOptions: any = {
type: 'password',
length: 64,
uppercase: true,
lowercase: true,
numbers: true,
special: false,
};
const state = (await this.passwordGenerationService.generatePassword(passwordOptions)) + ':clientId=browser';
let codeVerifier = await this.passwordGenerationService.generatePassword(passwordOptions);
const codeVerifierHash = await this.cryptoFunctionService.hash(codeVerifier, 'sha256');
const codeChallenge = Utils.fromBufferToUrlB64(codeVerifierHash);
await this.storageService.save(ConstantsService.ssoCodeVerifierKey, codeVerifier);
await this.storageService.save(ConstantsService.ssoStateKey, state);
let url = this.environmentService.getWebVaultUrl();
if (url == null) {
url = 'https://vault.bitwarden.com';
}
const redirectUri = url + '/sso-connector.html';
// Launch browser
this.platformUtilsService.launchUri(url + '/#/sso?clientId=browser' +
'&redirectUri=' + encodeURIComponent(redirectUri) +
'&state=' + state + '&codeChallenge=' + codeChallenge);
}
}

View File

@ -19,13 +19,12 @@ import { LoginComponent as BaseLoginComponent } from 'jslib/angular/components/l
}) })
export class LoginComponent extends BaseLoginComponent { export class LoginComponent extends BaseLoginComponent {
constructor(authService: AuthService, router: Router, constructor(authService: AuthService, router: Router,
platformUtilsService: PlatformUtilsService, i18nService: I18nService, protected platformUtilsService: PlatformUtilsService, protected i18nService: I18nService,
syncService: SyncService, storageService: StorageService, protected stateService: StateService, protected environmentService: EnvironmentService,
stateService: StateService, environmentService: EnvironmentService, protected passwordGenerationService: PasswordGenerationService,
passwordGenerationService: PasswordGenerationService, protected cryptoFunctionService: CryptoFunctionService,
cryptoFunctionService: CryptoFunctionService) { storageService: StorageService, syncService : SyncService) {
super(authService, router, platformUtilsService, i18nService, stateService, environmentService, super(authService, router, platformUtilsService, i18nService, stateService, environmentService, passwordGenerationService, cryptoFunctionService, storageService);
passwordGenerationService, cryptoFunctionService, storageService);
super.onSuccessfulLogin = () => { super.onSuccessfulLogin = () => {
return syncService.fullSync(true); return syncService.fullSync(true);
}; };

View File

View File

@ -0,0 +1,51 @@
import { Component } from '@angular/core';
import {
ActivatedRoute,
Router,
} from '@angular/router';
import { ApiService } from 'jslib/abstractions/api.service';
import { AuthService } from 'jslib/abstractions/auth.service';
import { CryptoFunctionService } from 'jslib/abstractions/cryptoFunction.service';
import { EnvironmentService } from 'jslib/abstractions/environment.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { PasswordGenerationService } from 'jslib/abstractions/passwordGeneration.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { StateService } from 'jslib/abstractions/state.service';
import { StorageService } from 'jslib/abstractions/storage.service';
import { SyncService } from 'jslib/abstractions/sync.service';
import { SsoComponent as BaseSsoComponent } from 'jslib/angular/components/sso.component';
import { BrowserApi } from '../../browser/browserApi';
@Component({
selector: 'app-sso',
templateUrl: 'sso.component.html',
})
export class SsoComponent extends BaseSsoComponent {
constructor(authService: AuthService, router: Router,
i18nService: I18nService, route: ActivatedRoute,
storageService: StorageService, stateService: StateService,
platformUtilsService: PlatformUtilsService, apiService: ApiService,
cryptoFunctionService: CryptoFunctionService, passwordGenerationService: PasswordGenerationService,
syncService: SyncService, private environmentService: EnvironmentService ) {
super(authService, router, i18nService, route, storageService, stateService, platformUtilsService,
apiService, cryptoFunctionService, passwordGenerationService);
let url = this.environmentService.getWebVaultUrl();
if (url == null) {
url = 'https://vault.bitwarden.com';
}
this.redirectUri = url + '/sso-connector.html';
this.clientId = 'browser';
super.onSuccessfulLogin = () => {
BrowserApi.reloadOpenWindows();
const thisWindow = window.open('', '_self');
thisWindow.close();
return syncService.fullSync(true);
};
}
}

View File

@ -18,6 +18,7 @@ import { LoginComponent } from './accounts/login.component';
import { RegisterComponent } from './accounts/register.component'; import { RegisterComponent } from './accounts/register.component';
import { TwoFactorOptionsComponent } from './accounts/two-factor-options.component'; import { TwoFactorOptionsComponent } from './accounts/two-factor-options.component';
import { TwoFactorComponent } from './accounts/two-factor.component'; import { TwoFactorComponent } from './accounts/two-factor.component';
import { SsoComponent } from './accounts/sso.component';
import { PasswordGeneratorHistoryComponent } from './generator/password-generator-history.component'; import { PasswordGeneratorHistoryComponent } from './generator/password-generator-history.component';
import { PasswordGeneratorComponent } from './generator/password-generator.component'; import { PasswordGeneratorComponent } from './generator/password-generator.component';
import { PrivateModeComponent } from './private-mode.component'; import { PrivateModeComponent } from './private-mode.component';
@ -79,6 +80,12 @@ const routes: Routes = [
canActivate: [LaunchGuardService], canActivate: [LaunchGuardService],
data: { state: '2fa-options' }, data: { state: '2fa-options' },
}, },
{
path: 'sso',
component: SsoComponent,
canActivate: [LaunchGuardService],
data: { state: 'sso' },
},
{ {
path: 'register', path: 'register',
component: RegisterComponent, component: RegisterComponent,

View File

@ -23,6 +23,7 @@ import { LoginComponent } from './accounts/login.component';
import { RegisterComponent } from './accounts/register.component'; import { RegisterComponent } from './accounts/register.component';
import { TwoFactorOptionsComponent } from './accounts/two-factor-options.component'; import { TwoFactorOptionsComponent } from './accounts/two-factor-options.component';
import { TwoFactorComponent } from './accounts/two-factor.component'; import { TwoFactorComponent } from './accounts/two-factor.component';
import { SsoComponent } from './accounts/sso.component';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
import { PasswordGeneratorHistoryComponent } from './generator/password-generator-history.component'; import { PasswordGeneratorHistoryComponent } from './generator/password-generator-history.component';
import { PasswordGeneratorComponent } from './generator/password-generator.component'; import { PasswordGeneratorComponent } from './generator/password-generator.component';
@ -206,6 +207,7 @@ registerLocaleData(localeZhTw, 'zh-TW');
TrueFalseValueDirective, TrueFalseValueDirective,
TwoFactorOptionsComponent, TwoFactorOptionsComponent,
TwoFactorComponent, TwoFactorComponent,
SsoComponent,
ViewComponent, ViewComponent,
], ],
entryComponents: [], entryComponents: [],

View File

@ -41,6 +41,7 @@ import { TokenService } from 'jslib/abstractions/token.service';
import { TotpService } from 'jslib/abstractions/totp.service'; import { TotpService } from 'jslib/abstractions/totp.service';
import { UserService } from 'jslib/abstractions/user.service'; import { UserService } from 'jslib/abstractions/user.service';
import { VaultTimeoutService } from 'jslib/abstractions/vaultTimeout.service'; import { VaultTimeoutService } from 'jslib/abstractions/vaultTimeout.service';
import { WebCryptoFunctionService } from 'jslib/services/webCryptoFunction.service';
import { AutofillService } from '../../services/abstractions/autofill.service'; import { AutofillService } from '../../services/abstractions/autofill.service';
import BrowserMessagingService from '../../services/browserMessaging.service'; import BrowserMessagingService from '../../services/browserMessaging.service';
@ -68,9 +69,11 @@ export const authService = new AuthService(getBgService<CryptoService>('cryptoSe
getBgService<ApiService>('apiService')(), getBgService<UserService>('userService')(), getBgService<ApiService>('apiService')(), getBgService<UserService>('userService')(),
getBgService<TokenService>('tokenService')(), getBgService<AppIdService>('appIdService')(), getBgService<TokenService>('tokenService')(), getBgService<AppIdService>('appIdService')(),
getBgService<I18nService>('i18nService')(), getBgService<PlatformUtilsService>('platformUtilsService')(), getBgService<I18nService>('i18nService')(), getBgService<PlatformUtilsService>('platformUtilsService')(),
messagingService, getBgService<VaultTimeoutService>('vaultTimeoutService')()); messagingService, getBgService<VaultTimeoutService>('vaultTimeoutService')(), null);
export const searchService = new PopupSearchService(getBgService<SearchService>('searchService')(), export const searchService = new PopupSearchService(getBgService<SearchService>('searchService')(),
getBgService<CipherService>('cipherService')(), getBgService<PlatformUtilsService>('platformUtilsService')()); getBgService<CipherService>('cipherService')(), getBgService<PlatformUtilsService>('platformUtilsService')());
export const cryptoFunctionService: CryptoFunctionService = new WebCryptoFunctionService(window,
getBgService<PlatformUtilsService>('platformUtilsService')());
export function initFactory(i18nService: I18nService, storageService: StorageService, export function initFactory(i18nService: I18nService, storageService: StorageService,
popupUtilsService: PopupUtilsService): Function { popupUtilsService: PopupUtilsService): Function {
@ -122,6 +125,7 @@ export function initFactory(i18nService: I18nService, storageService: StorageSer
{ provide: AuthServiceAbstraction, useValue: authService }, { provide: AuthServiceAbstraction, useValue: authService },
{ provide: StateServiceAbstraction, useValue: stateService }, { provide: StateServiceAbstraction, useValue: stateService },
{ provide: SearchServiceAbstraction, useValue: searchService }, { provide: SearchServiceAbstraction, useValue: searchService },
{ provide: CryptoFunctionService, useValue: cryptoFunctionService },
{ provide: AuditService, useFactory: getBgService<AuditService>('auditService'), deps: [] }, { provide: AuditService, useFactory: getBgService<AuditService>('auditService'), deps: [] },
{ provide: CipherService, useFactory: getBgService<CipherService>('cipherService'), deps: [] }, { provide: CipherService, useFactory: getBgService<CipherService>('cipherService'), deps: [] },
{ provide: FolderService, useFactory: getBgService<FolderService>('folderService'), deps: [] }, { provide: FolderService, useFactory: getBgService<FolderService>('folderService'), deps: [] },

View File

@ -53,6 +53,10 @@
<key>Script</key> <key>Script</key>
<string>app/content/shortcuts.js</string> <string>app/content/shortcuts.js</string>
</dict> </dict>
<dict>
<key>Script</key>
<string>app/content/sso.js</string>
</dict>
</array> </array>
<key>SFSafariToolbarItem</key> <key>SFSafariToolbarItem</key>
<dict> <dict>

View File

@ -295,7 +295,7 @@ export default class BrowserPlatformUtilsService implements PlatformUtilsService
return Promise.resolve(false); return Promise.resolve(false);
} }
private sidebarViewName(): string { sidebarViewName(): string {
if ((window as any).chrome.sidebarAction && this.isFirefox()) { if ((window as any).chrome.sidebarAction && this.isFirefox()) {
return 'sidebar'; return 'sidebar';
} else if (this.isOpera() && (typeof opr !== 'undefined') && opr.sidebarAction) { } else if (this.isOpera() && (typeof opr !== 'undefined') && opr.sidebarAction) {

View File

@ -136,6 +136,7 @@ const config = {
'content/autofiller': './src/content/autofiller.ts', 'content/autofiller': './src/content/autofiller.ts',
'content/notificationBar': './src/content/notificationBar.ts', 'content/notificationBar': './src/content/notificationBar.ts',
'content/shortcuts': './src/content/shortcuts.ts', 'content/shortcuts': './src/content/shortcuts.ts',
'content/sso': './src/content/sso.ts',
'notification/bar': './src/notification/bar.js', 'notification/bar': './src/notification/bar.js',
}, },
optimization: { optimization: {