mirror of
https://github.com/bitwarden/browser.git
synced 2024-12-28 17:27:50 +01:00
Modifications made to support SSO in Browser
This commit is contained in:
parent
679c7780e0
commit
1d0b549123
@ -19,6 +19,9 @@
|
||||
"login": {
|
||||
"message": "Log In"
|
||||
},
|
||||
"enterpriseSingleSignOn": {
|
||||
"message": "Enterprise Single Sign-On"
|
||||
},
|
||||
"cancel": {
|
||||
"message": "Cancel"
|
||||
},
|
||||
@ -1297,4 +1300,4 @@
|
||||
"vaultTimeoutLogOutConfirmationTitle": {
|
||||
"message": "Timeout Action Confirmation"
|
||||
}
|
||||
}
|
||||
}
|
@ -4,6 +4,7 @@ import {
|
||||
ApiService,
|
||||
AppIdService,
|
||||
AuditService,
|
||||
AuthService,
|
||||
CipherService,
|
||||
CollectionService,
|
||||
ConstantsService,
|
||||
@ -13,6 +14,7 @@ import {
|
||||
FolderService,
|
||||
PasswordGenerationService,
|
||||
SettingsService,
|
||||
StateService,
|
||||
SyncService,
|
||||
TokenService,
|
||||
TotpService,
|
||||
@ -31,6 +33,7 @@ import {
|
||||
ApiService as ApiServiceAbstraction,
|
||||
AppIdService as AppIdServiceAbstraction,
|
||||
AuditService as AuditServiceAbstraction,
|
||||
AuthService as AuthServiceAbstraction,
|
||||
CipherService as CipherServiceAbstraction,
|
||||
CollectionService as CollectionServiceAbstraction,
|
||||
CryptoService as CryptoServiceAbstraction,
|
||||
@ -41,6 +44,7 @@ import {
|
||||
PasswordGenerationService as PasswordGenerationServiceAbstraction,
|
||||
PlatformUtilsService as PlatformUtilsServiceAbstraction,
|
||||
SettingsService as SettingsServiceAbstraction,
|
||||
StateService as StateServiceAbstraction,
|
||||
StorageService as StorageServiceAbstraction,
|
||||
SyncService as SyncServiceAbstraction,
|
||||
TokenService as TokenServiceAbstraction,
|
||||
@ -101,9 +105,11 @@ export default class MainBackground {
|
||||
autofillService: AutofillServiceAbstraction;
|
||||
containerService: ContainerService;
|
||||
auditService: AuditServiceAbstraction;
|
||||
authService: AuthServiceAbstraction;
|
||||
exportService: ExportServiceAbstraction;
|
||||
searchService: SearchServiceAbstraction;
|
||||
notificationsService: NotificationsServiceAbstraction;
|
||||
stateService: StateServiceAbstraction;
|
||||
systemService: SystemServiceAbstraction;
|
||||
eventService: EventServiceAbstraction;
|
||||
policyService: PolicyServiceAbstraction;
|
||||
@ -147,6 +153,9 @@ export default class MainBackground {
|
||||
this.apiService = new ApiService(this.tokenService, this.platformUtilsService,
|
||||
(expired: boolean) => this.logout(expired));
|
||||
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.cipherService = new CipherService(this.cryptoService, this.userService, this.settingsService,
|
||||
this.apiService, this.storageService, this.i18nService, () => this.searchService);
|
||||
@ -155,6 +164,7 @@ export default class MainBackground {
|
||||
this.collectionService = new CollectionService(this.cryptoService, this.userService, this.storageService,
|
||||
this.i18nService);
|
||||
this.searchService = new SearchService(this.cipherService, this.platformUtilsService);
|
||||
this.stateService = new StateService();
|
||||
this.policyService = new PolicyService(this.userService, this.storageService);
|
||||
this.vaultTimeoutService = new VaultTimeoutService(this.cipherService, this.folderService,
|
||||
this.collectionService, this.cryptoService, this.platformUtilsService, this.storageService,
|
||||
@ -206,7 +216,8 @@ export default class MainBackground {
|
||||
// Background
|
||||
this.runtimeBackground = new RuntimeBackground(this, this.autofillService, this.cipherService,
|
||||
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.commandsBackground = new CommandsBackground(this, this.passwordGenerationService,
|
||||
this.platformUtilsService, this.analytics, this.vaultTimeoutService);
|
||||
|
||||
|
@ -4,14 +4,18 @@ import { CipherView } from 'jslib/models/view/cipherView';
|
||||
import { LoginUriView } from 'jslib/models/view/loginUriView';
|
||||
import { LoginView } from 'jslib/models/view/loginView';
|
||||
|
||||
import { ConstantsService } from 'jslib/services/constants.service';
|
||||
|
||||
import { I18nService } from 'jslib/abstractions/i18n.service';
|
||||
|
||||
import { Analytics } from 'jslib/misc';
|
||||
|
||||
import { AuthResult } from 'jslib/models/domain/authResult';
|
||||
import { AuthService } from 'jslib/abstractions/auth.service';
|
||||
import { AutofillService } from '../services/abstractions/autofill.service';
|
||||
import BrowserPlatformUtilsService from '../services/browserPlatformUtils.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 { StateService } from 'jslib/abstractions/state.service';
|
||||
import { StorageService } from 'jslib/abstractions/storage.service';
|
||||
import { SyncService } from 'jslib/abstractions/sync.service';
|
||||
import { SystemService } from 'jslib/abstractions/system.service';
|
||||
import { VaultTimeoutService } from 'jslib/abstractions/vaultTimeout.service';
|
||||
|
||||
@ -19,11 +23,7 @@ import { BrowserApi } from '../browser/browserApi';
|
||||
|
||||
import MainBackground from './main.background';
|
||||
|
||||
import { AutofillService } from '../services/abstractions/autofill.service';
|
||||
import BrowserPlatformUtilsService from '../services/browserPlatformUtils.service';
|
||||
|
||||
import { NotificationsService } from 'jslib/abstractions/notifications.service';
|
||||
|
||||
import { Analytics } from 'jslib/misc';
|
||||
import { Utils } from 'jslib/misc/utils';
|
||||
|
||||
export default class RuntimeBackground {
|
||||
@ -33,11 +33,19 @@ export default class RuntimeBackground {
|
||||
private isSafari: boolean;
|
||||
private onInstalledReason: string = null;
|
||||
|
||||
formPromise: Promise<AuthResult>;
|
||||
onSuccessfulLoginNavigate: () => Promise<any>;
|
||||
onSuccessfulLoginTwoFactorNavigate: () => Promise<any>;
|
||||
loggingIn = false;
|
||||
private redirectUri = 'https://localhost:8080/sso-connector.html';
|
||||
|
||||
constructor(private main: MainBackground, private autofillService: AutofillService,
|
||||
private cipherService: CipherService, private platformUtilsService: BrowserPlatformUtilsService,
|
||||
private storageService: StorageService, private i18nService: I18nService,
|
||||
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) {
|
||||
this.isSafari = this.platformUtilsService.isSafari();
|
||||
this.runtime = this.isSafari ? {} : chrome.runtime;
|
||||
|
||||
@ -47,6 +55,52 @@ export default class RuntimeBackground {
|
||||
this.onInstalledReason = details.reason;
|
||||
});
|
||||
}
|
||||
|
||||
chrome.runtime.onMessage.addListener(
|
||||
(request: any) => {
|
||||
|
||||
var vaultUrl = environmentService.webVaultUrl;
|
||||
if(!vaultUrl) {
|
||||
vaultUrl = 'https://vault.bitwarden.com';
|
||||
// vaultUrl = 'https://localhost:8080';
|
||||
}
|
||||
|
||||
if(!request.referrer) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(!vaultUrl.includes(request.referrer)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (request.type == "AUTH_RESULT") {
|
||||
try {
|
||||
this.logIn(request.code, request.codeVerifier);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async logIn(code: string, codeVerifier: string) {
|
||||
this.loggingIn = true;
|
||||
try {
|
||||
this.formPromise = this.authService.logInSso(code, codeVerifier, this.redirectUri);
|
||||
const response = await this.formPromise;
|
||||
|
||||
if (response) {
|
||||
this.syncService.fullSync(true);
|
||||
this.main.openPopup();
|
||||
|
||||
var sidebarName : string = this.platformUtilsService.sidebarViewName();
|
||||
var sidebarWindows = chrome.extension.getViews({ type: sidebarName });
|
||||
if(sidebarWindows && sidebarWindows.length > 0) {
|
||||
sidebarWindows[0].location.reload();
|
||||
}
|
||||
}
|
||||
} catch(error) { console.log(error); }
|
||||
|
||||
this.loggingIn = false;
|
||||
}
|
||||
|
||||
async init() {
|
||||
|
15
src/content/sso.ts
Normal file
15
src/content/sso.ts
Normal file
@ -0,0 +1,15 @@
|
||||
window.addEventListener("message", function(event) {
|
||||
if (event.source != window)
|
||||
return;
|
||||
|
||||
console.log(event.source);
|
||||
|
||||
if (event.data.type && (event.data.type == "AUTH_RESULT")) {
|
||||
chrome.runtime.sendMessage({
|
||||
type: event.data.type,
|
||||
code: event.data.code,
|
||||
codeVerifier: event.data.codeVerifier,
|
||||
referrer: event.source.location.hostname
|
||||
});
|
||||
}
|
||||
}, false)
|
@ -41,6 +41,18 @@
|
||||
],
|
||||
"run_at": "document_start"
|
||||
},
|
||||
{
|
||||
"all_frames": false,
|
||||
"js": [
|
||||
"content/sso.js"
|
||||
],
|
||||
"matches": [
|
||||
"http://*/*",
|
||||
"https://*/*",
|
||||
"file:///*"
|
||||
],
|
||||
"run_at": "document_start"
|
||||
},
|
||||
{
|
||||
"all_frames": true,
|
||||
"css": [
|
||||
|
@ -3,6 +3,9 @@
|
||||
<div class="logo-image"></div>
|
||||
<p class="lead text-center">{{'loginOrCreateNewAccount' | i18n}}</p>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,7 +1,45 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
import { CryptoFunctionService } from 'jslib/abstractions/cryptoFunction.service';
|
||||
import { EnvironmentService } from 'jslib/abstractions/environment.service';
|
||||
import { PlatformUtilsService } from '../../../jslib/src/abstractions/platformUtils.service';
|
||||
import { PasswordGenerationService } from 'jslib/abstractions/passwordGeneration.service';
|
||||
|
||||
import { Utils } from 'jslib/misc/utils';
|
||||
|
||||
@Component({
|
||||
selector: 'app-home',
|
||||
templateUrl: 'home.component.html',
|
||||
})
|
||||
export class HomeComponent { }
|
||||
export class HomeComponent {
|
||||
constructor(
|
||||
protected platformUtilsService: PlatformUtilsService, private passwordGenerationService : PasswordGenerationService,
|
||||
private cryptoFunctionService: CryptoFunctionService, private environmentService: EnvironmentService) { }
|
||||
|
||||
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);
|
||||
let ssoCodeVerifier = await this.passwordGenerationService.generatePassword(passwordOptions);
|
||||
const codeVerifierHash = await this.cryptoFunctionService.hash(ssoCodeVerifier, 'sha256');
|
||||
const codeChallenge = Utils.fromBufferToUrlB64(codeVerifierHash);
|
||||
|
||||
const webUrl = 'https://localhost:8080';
|
||||
const clientId = 'browser';
|
||||
const ssoRedirectUri = 'https://localhost:8080/sso-connector.html';
|
||||
|
||||
// Launch browser
|
||||
this.platformUtilsService.launchUri(webUrl + '/#/sso?clientId=' + clientId +
|
||||
'&redirectUri=' + encodeURIComponent(ssoRedirectUri) +
|
||||
'&state=' + state + '&codeChallenge=' + codeChallenge +
|
||||
'&codeVerifier=' + ssoCodeVerifier);
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import { AuthService as AuthServiceAbstraction } from 'jslib/abstractions/auth.s
|
||||
import { CipherService } from 'jslib/abstractions/cipher.service';
|
||||
import { CollectionService } from 'jslib/abstractions/collection.service';
|
||||
import { CryptoService } from 'jslib/abstractions/crypto.service';
|
||||
import { CryptoFunctionService } from 'jslib/abstractions/cryptoFunction.service'
|
||||
import { EnvironmentService } from 'jslib/abstractions/environment.service';
|
||||
import { EventService } from 'jslib/abstractions/event.service';
|
||||
import { ExportService } from 'jslib/abstractions/export.service';
|
||||
@ -40,6 +41,7 @@ import { TokenService } from 'jslib/abstractions/token.service';
|
||||
import { TotpService } from 'jslib/abstractions/totp.service';
|
||||
import { UserService } from 'jslib/abstractions/user.service';
|
||||
import { VaultTimeoutService } from 'jslib/abstractions/vaultTimeout.service';
|
||||
import { WebCryptoFunctionService } from 'jslib/services/webCryptoFunction.service';
|
||||
|
||||
import { AutofillService } from '../../services/abstractions/autofill.service';
|
||||
import BrowserMessagingService from '../../services/browserMessaging.service';
|
||||
@ -67,9 +69,11 @@ export const authService = new AuthService(getBgService<CryptoService>('cryptoSe
|
||||
getBgService<ApiService>('apiService')(), getBgService<UserService>('userService')(),
|
||||
getBgService<TokenService>('tokenService')(), getBgService<AppIdService>('appIdService')(),
|
||||
getBgService<I18nService>('i18nService')(), getBgService<PlatformUtilsService>('platformUtilsService')(),
|
||||
messagingService, getBgService<VaultTimeoutService>('vaultTimeoutService')());
|
||||
messagingService, getBgService<VaultTimeoutService>('vaultTimeoutService')(), null);
|
||||
export const searchService = new PopupSearchService(getBgService<SearchService>('searchService')(),
|
||||
getBgService<CipherService>('cipherService')(), getBgService<PlatformUtilsService>('platformUtilsService')());
|
||||
export const cryptoFunctionService: CryptoFunctionService = new WebCryptoFunctionService(window,
|
||||
getBgService<PlatformUtilsService>('platformUtilsService')());
|
||||
|
||||
export function initFactory(i18nService: I18nService, storageService: StorageService,
|
||||
popupUtilsService: PopupUtilsService): Function {
|
||||
@ -121,6 +125,7 @@ export function initFactory(i18nService: I18nService, storageService: StorageSer
|
||||
{ provide: AuthServiceAbstraction, useValue: authService },
|
||||
{ provide: StateServiceAbstraction, useValue: stateService },
|
||||
{ provide: SearchServiceAbstraction, useValue: searchService },
|
||||
{ provide: CryptoFunctionService, useValue: cryptoFunctionService },
|
||||
{ provide: AuditService, useFactory: getBgService<AuditService>('auditService'), deps: [] },
|
||||
{ provide: CipherService, useFactory: getBgService<CipherService>('cipherService'), deps: [] },
|
||||
{ provide: FolderService, useFactory: getBgService<FolderService>('folderService'), deps: [] },
|
||||
|
@ -53,6 +53,10 @@
|
||||
<key>Script</key>
|
||||
<string>app/content/shortcuts.js</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>Script</key>
|
||||
<string>app/content/sso.js</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>SFSafariToolbarItem</key>
|
||||
<dict>
|
||||
|
@ -295,7 +295,7 @@ export default class BrowserPlatformUtilsService implements PlatformUtilsService
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
private sidebarViewName(): string {
|
||||
sidebarViewName(): string {
|
||||
if ((window as any).chrome.sidebarAction && this.isFirefox()) {
|
||||
return 'sidebar';
|
||||
} else if (this.isOpera() && (typeof opr !== 'undefined') && opr.sidebarAction) {
|
||||
|
@ -136,6 +136,7 @@ const config = {
|
||||
'content/autofiller': './src/content/autofiller.ts',
|
||||
'content/notificationBar': './src/content/notificationBar.ts',
|
||||
'content/shortcuts': './src/content/shortcuts.ts',
|
||||
'content/sso': './src/content/sso.ts',
|
||||
'notification/bar': './src/notification/bar.js',
|
||||
},
|
||||
optimization: {
|
||||
|
Loading…
Reference in New Issue
Block a user