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

View File

@ -1,10 +1,10 @@
import { Component } from "@angular/core";
import { ActivatedRoute, Params, Router } from "@angular/router";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
import { I18nService } from "@bitwarden/common/abstractions/i18n.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 { OrganizationUserAcceptRequest } from "@bitwarden/common/abstractions/organization-user/requests";
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/abstractions/organization/organization-api.service.abstraction";
@ -31,19 +31,28 @@ export class AcceptOrganizationComponent extends BaseAcceptComponent {
platformUtilsService: PlatformUtilsService,
i18nService: I18nService,
route: ActivatedRoute,
private apiService: ApiService,
stateService: StateService,
private cryptoService: CryptoService,
private policyApiService: PolicyApiServiceAbstraction,
private policyService: PolicyService,
private logService: LogService,
private organizationApiService: OrganizationApiServiceAbstraction,
private organizationUserService: OrganizationUserService
private organizationUserService: OrganizationUserService,
private messagingService: MessagingService
) {
super(router, platformUtilsService, i18nService, route, stateService);
}
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) => {
await this.organizationUserService.postOrganizationUserAccept(
qParams.organizationId,
@ -52,6 +61,7 @@ export class AcceptOrganizationComponent extends BaseAcceptComponent {
);
});
await this.stateService.setOrganizationInvitation(null);
await this.actionPromise;
this.platformUtilService.showToast(
"success",
@ -60,17 +70,11 @@ export class AcceptOrganizationComponent extends BaseAcceptComponent {
{ timeout: 10000 }
);
await this.stateService.setOrganizationInvitation(null);
this.router.navigate(["/vault"]);
}
async unauthedHandler(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);
await this.prepareOrganizationInvitation(qParams);
}
private async prepareAcceptRequest(qParams: Params): Promise<OrganizationUserAcceptRequest> {
@ -121,4 +125,13 @@ export class AcceptOrganizationComponent extends BaseAcceptComponent {
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"
[email]="email"
[showText]="true"
(passwordStrengthResult)="getStrengthResult($event)"
></app-password-strength>
</div>
</div>

View File

@ -112,7 +112,7 @@ export class AppComponent implements OnDestroy, OnInit {
this.router.navigate(["/"]);
break;
case "logout":
this.logOut(!!message.expired);
this.logOut(!!message.expired, message.redirect);
break;
case "lockVault":
await this.vaultTimeoutService.lock();
@ -220,7 +220,7 @@ export class AppComponent implements OnDestroy, OnInit {
this.destroy$.complete();
}
private async logOut(expired: boolean) {
private async logOut(expired: boolean, redirect = true) {
await this.eventUploadService.uploadEvents();
const userId = await this.stateService.getUserId();
await Promise.all([
@ -247,7 +247,9 @@ export class AppComponent implements OnDestroy, OnInit {
await this.stateService.clean({ userId: userId });
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;
if (!error) {
this.authed = await this.stateService.getIsAuthenticated();
this.email = qParams.email;
if (this.authed) {
try {
@ -44,7 +45,6 @@ export abstract class BaseAcceptComponent implements OnInit {
errorMessage = e.message;
}
} else {
this.email = qParams.email;
await this.unauthedHandler(qParams);
}
}