1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-12-22 16:29:09 +01:00

[EC-781] User can bypass master password requirements policy by canceling password reset and pasting invite link (#4218)

* [EC-781] Forcing the user to login to evaluate if the user's password meets the Organization password policy requirements

* [EC-781] Fix bug preventing from submitting update password form

* Revert "[EC-781] Forcing the user to login to evaluate if the user's password meets the Organization password policy requirements"

This reverts commit f09d74b4fc.

* [EC-781] Get email value from query parameters also for authenticated requests

* [EC-781] Forcing the user to login to evaluate if the user's current password meets the Organization password policy requirements

* [EC-781] Logging out the user using messagingService on accept-organization component

* [EC-781] Refactored accept-organization component to be simpler to read
This commit is contained in:
Rui Tomé 2022-12-29 16:20:19 +00:00 committed by GitHub
parent 2ac8e27b31
commit bf67493663
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 31 additions and 15 deletions

View File

@ -11,7 +11,7 @@
</p> </p>
</div> </div>
</div> </div>
<div class="container" *ngIf="!loading && !authed"> <div class="container" *ngIf="!loading">
<div class="row justify-content-md-center mt-5"> <div class="row justify-content-md-center mt-5">
<div class="col-5"> <div class="col-5">
<p class="lead text-center mb-4">{{ "joinOrganization" | i18n }}</p> <p class="lead text-center mb-4">{{ "joinOrganization" | i18n }}</p>

View File

@ -1,10 +1,10 @@
import { Component } from "@angular/core"; import { Component } from "@angular/core";
import { ActivatedRoute, Params, Router } from "@angular/router"; import { ActivatedRoute, Params, Router } from "@angular/router";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service"; import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/abstractions/log.service"; import { LogService } from "@bitwarden/common/abstractions/log.service";
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
import { OrganizationUserService } from "@bitwarden/common/abstractions/organization-user/organization-user.service"; import { OrganizationUserService } from "@bitwarden/common/abstractions/organization-user/organization-user.service";
import { OrganizationUserAcceptRequest } from "@bitwarden/common/abstractions/organization-user/requests"; import { OrganizationUserAcceptRequest } from "@bitwarden/common/abstractions/organization-user/requests";
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/abstractions/organization/organization-api.service.abstraction"; import { OrganizationApiServiceAbstraction } from "@bitwarden/common/abstractions/organization/organization-api.service.abstraction";
@ -31,19 +31,28 @@ export class AcceptOrganizationComponent extends BaseAcceptComponent {
platformUtilsService: PlatformUtilsService, platformUtilsService: PlatformUtilsService,
i18nService: I18nService, i18nService: I18nService,
route: ActivatedRoute, route: ActivatedRoute,
private apiService: ApiService,
stateService: StateService, stateService: StateService,
private cryptoService: CryptoService, private cryptoService: CryptoService,
private policyApiService: PolicyApiServiceAbstraction, private policyApiService: PolicyApiServiceAbstraction,
private policyService: PolicyService, private policyService: PolicyService,
private logService: LogService, private logService: LogService,
private organizationApiService: OrganizationApiServiceAbstraction, private organizationApiService: OrganizationApiServiceAbstraction,
private organizationUserService: OrganizationUserService private organizationUserService: OrganizationUserService,
private messagingService: MessagingService
) { ) {
super(router, platformUtilsService, i18nService, route, stateService); super(router, platformUtilsService, i18nService, route, stateService);
} }
async authedHandler(qParams: Params): Promise<void> { async authedHandler(qParams: Params): Promise<void> {
const needsReAuth = (await this.stateService.getOrganizationInvitation()) != null;
if (!needsReAuth) {
// Accepting an org invite requires authentication from a logged out state
this.messagingService.send("logout", { redirect: false });
await this.prepareOrganizationInvitation(qParams);
return;
}
// User has already logged in and passed the Master Password policy check
this.actionPromise = this.prepareAcceptRequest(qParams).then(async (request) => { this.actionPromise = this.prepareAcceptRequest(qParams).then(async (request) => {
await this.organizationUserService.postOrganizationUserAccept( await this.organizationUserService.postOrganizationUserAccept(
qParams.organizationId, qParams.organizationId,
@ -52,6 +61,7 @@ export class AcceptOrganizationComponent extends BaseAcceptComponent {
); );
}); });
await this.stateService.setOrganizationInvitation(null);
await this.actionPromise; await this.actionPromise;
this.platformUtilService.showToast( this.platformUtilService.showToast(
"success", "success",
@ -60,17 +70,11 @@ export class AcceptOrganizationComponent extends BaseAcceptComponent {
{ timeout: 10000 } { timeout: 10000 }
); );
await this.stateService.setOrganizationInvitation(null);
this.router.navigate(["/vault"]); this.router.navigate(["/vault"]);
} }
async unauthedHandler(qParams: Params): Promise<void> { async unauthedHandler(qParams: Params): Promise<void> {
this.orgName = qParams.organizationName; await this.prepareOrganizationInvitation(qParams);
if (this.orgName != null) {
// Fix URL encoding of space issue with Angular
this.orgName = this.orgName.replace(/\+/g, " ");
}
await this.stateService.setOrganizationInvitation(qParams);
} }
private async prepareAcceptRequest(qParams: Params): Promise<OrganizationUserAcceptRequest> { private async prepareAcceptRequest(qParams: Params): Promise<OrganizationUserAcceptRequest> {
@ -121,4 +125,13 @@ export class AcceptOrganizationComponent extends BaseAcceptComponent {
return false; return false;
} }
private async prepareOrganizationInvitation(qParams: Params): Promise<void> {
this.orgName = qParams.organizationName;
if (this.orgName != null) {
// Fix URL encoding of space issue with Angular
this.orgName = this.orgName.replace(/\+/g, " ");
}
await this.stateService.setOrganizationInvitation(qParams);
}
} }

View File

@ -52,6 +52,7 @@
[password]="masterPassword" [password]="masterPassword"
[email]="email" [email]="email"
[showText]="true" [showText]="true"
(passwordStrengthResult)="getStrengthResult($event)"
></app-password-strength> ></app-password-strength>
</div> </div>
</div> </div>

View File

@ -112,7 +112,7 @@ export class AppComponent implements OnDestroy, OnInit {
this.router.navigate(["/"]); this.router.navigate(["/"]);
break; break;
case "logout": case "logout":
this.logOut(!!message.expired); this.logOut(!!message.expired, message.redirect);
break; break;
case "lockVault": case "lockVault":
await this.vaultTimeoutService.lock(); await this.vaultTimeoutService.lock();
@ -220,7 +220,7 @@ export class AppComponent implements OnDestroy, OnInit {
this.destroy$.complete(); this.destroy$.complete();
} }
private async logOut(expired: boolean) { private async logOut(expired: boolean, redirect = true) {
await this.eventUploadService.uploadEvents(); await this.eventUploadService.uploadEvents();
const userId = await this.stateService.getUserId(); const userId = await this.stateService.getUserId();
await Promise.all([ await Promise.all([
@ -247,7 +247,9 @@ export class AppComponent implements OnDestroy, OnInit {
await this.stateService.clean({ userId: userId }); await this.stateService.clean({ userId: userId });
Swal.close(); Swal.close();
this.router.navigate(["/"]); if (redirect) {
this.router.navigate(["/"]);
}
}); });
} }

View File

@ -35,6 +35,7 @@ export abstract class BaseAcceptComponent implements OnInit {
let errorMessage: string = null; let errorMessage: string = null;
if (!error) { if (!error) {
this.authed = await this.stateService.getIsAuthenticated(); this.authed = await this.stateService.getIsAuthenticated();
this.email = qParams.email;
if (this.authed) { if (this.authed) {
try { try {
@ -44,7 +45,6 @@ export abstract class BaseAcceptComponent implements OnInit {
errorMessage = e.message; errorMessage = e.message;
} }
} else { } else {
this.email = qParams.email;
await this.unauthedHandler(qParams); await this.unauthedHandler(qParams);
} }
} }