mirror of
https://github.com/bitwarden/browser.git
synced 2024-11-11 10:10:25 +01:00
Auth/PM-11969 - Registration with Email Verification - Accept Emergency Access Invite Flow (#11018)
* PM-11969 - Registration with Email Verification - Accept Emergency Access Invite Fixed * PM-11969 - Fix PR feedback * PM-11969 - AcceptEmergencyComponent - remove prop
This commit is contained in:
parent
fe96aa85f2
commit
bd3863c313
@ -71,6 +71,8 @@ export class WebRegistrationFinishService
|
|||||||
userAsymmetricKeys: [string, EncString],
|
userAsymmetricKeys: [string, EncString],
|
||||||
emailVerificationToken?: string,
|
emailVerificationToken?: string,
|
||||||
orgSponsoredFreeFamilyPlanToken?: string,
|
orgSponsoredFreeFamilyPlanToken?: string,
|
||||||
|
acceptEmergencyAccessInviteToken?: string,
|
||||||
|
emergencyAccessId?: string,
|
||||||
): Promise<RegisterFinishRequest> {
|
): Promise<RegisterFinishRequest> {
|
||||||
const registerRequest = await super.buildRegisterRequest(
|
const registerRequest = await super.buildRegisterRequest(
|
||||||
email,
|
email,
|
||||||
@ -94,6 +96,11 @@ export class WebRegistrationFinishService
|
|||||||
registerRequest.orgSponsoredFreeFamilyPlanToken = orgSponsoredFreeFamilyPlanToken;
|
registerRequest.orgSponsoredFreeFamilyPlanToken = orgSponsoredFreeFamilyPlanToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (acceptEmergencyAccessInviteToken && emergencyAccessId) {
|
||||||
|
registerRequest.acceptEmergencyAccessInviteToken = acceptEmergencyAccessInviteToken;
|
||||||
|
registerRequest.acceptEmergencyAccessId = emergencyAccessId;
|
||||||
|
}
|
||||||
|
|
||||||
return registerRequest;
|
return registerRequest;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,14 +26,8 @@
|
|||||||
>
|
>
|
||||||
{{ "logIn" | i18n }}
|
{{ "logIn" | i18n }}
|
||||||
</a>
|
</a>
|
||||||
<a
|
<button type="button" bitButton buttonType="primary" (click)="register()" [block]="true">
|
||||||
bitButton
|
|
||||||
buttonType="primary"
|
|
||||||
[routerLink]="registerRoute$ | async"
|
|
||||||
[queryParams]="{ email: email }"
|
|
||||||
[block]="true"
|
|
||||||
>
|
|
||||||
{{ "createAccount" | i18n }}
|
{{ "createAccount" | i18n }}
|
||||||
</a>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
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 { firstValueFrom } from "rxjs";
|
||||||
|
|
||||||
import { RegisterRouteService } from "@bitwarden/auth/common";
|
import { RegisterRouteService } from "@bitwarden/auth/common";
|
||||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||||
@ -18,6 +19,8 @@ import { EmergencyAccessService } from "../services/emergency-access.service";
|
|||||||
})
|
})
|
||||||
export class AcceptEmergencyComponent extends BaseAcceptComponent {
|
export class AcceptEmergencyComponent extends BaseAcceptComponent {
|
||||||
name: string;
|
name: string;
|
||||||
|
emergencyAccessId: string;
|
||||||
|
acceptEmergencyAccessInviteToken: string;
|
||||||
|
|
||||||
protected requiredParameters: string[] = ["id", "name", "email", "token"];
|
protected requiredParameters: string[] = ["id", "name", "email", "token"];
|
||||||
protected failedShortMessage = "emergencyInviteAcceptFailedShort";
|
protected failedShortMessage = "emergencyInviteAcceptFailedShort";
|
||||||
@ -55,5 +58,36 @@ export class AcceptEmergencyComponent extends BaseAcceptComponent {
|
|||||||
// Fix URL encoding of space issue with Angular
|
// Fix URL encoding of space issue with Angular
|
||||||
this.name = this.name.replace(/\+/g, " ");
|
this.name = this.name.replace(/\+/g, " ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (qParams.id) {
|
||||||
|
this.emergencyAccessId = qParams.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qParams.token) {
|
||||||
|
this.acceptEmergencyAccessInviteToken = qParams.token;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async register() {
|
||||||
|
let queryParams: Params;
|
||||||
|
let registerRoute = await firstValueFrom(this.registerRoute$);
|
||||||
|
if (registerRoute === "/register") {
|
||||||
|
queryParams = {
|
||||||
|
email: this.email,
|
||||||
|
};
|
||||||
|
} else if (registerRoute === "/signup") {
|
||||||
|
// We have to override the base component route as we don't need users to
|
||||||
|
// complete email verification if they are coming directly an emailed invite.
|
||||||
|
registerRoute = "/finish-signup";
|
||||||
|
queryParams = {
|
||||||
|
email: this.email,
|
||||||
|
acceptEmergencyAccessInviteToken: this.acceptEmergencyAccessInviteToken,
|
||||||
|
emergencyAccessId: this.emergencyAccessId,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.router.navigate([registerRoute], {
|
||||||
|
queryParams: queryParams,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,8 @@ export class DefaultRegistrationFinishService implements RegistrationFinishServi
|
|||||||
passwordInputResult: PasswordInputResult,
|
passwordInputResult: PasswordInputResult,
|
||||||
emailVerificationToken?: string,
|
emailVerificationToken?: string,
|
||||||
orgSponsoredFreeFamilyPlanToken?: string,
|
orgSponsoredFreeFamilyPlanToken?: string,
|
||||||
|
acceptEmergencyAccessInviteToken?: string,
|
||||||
|
emergencyAccessId?: string,
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
const [newUserKey, newEncUserKey] = await this.cryptoService.makeUserKey(
|
const [newUserKey, newEncUserKey] = await this.cryptoService.makeUserKey(
|
||||||
passwordInputResult.masterKey,
|
passwordInputResult.masterKey,
|
||||||
@ -41,6 +43,8 @@ export class DefaultRegistrationFinishService implements RegistrationFinishServi
|
|||||||
userAsymmetricKeys,
|
userAsymmetricKeys,
|
||||||
emailVerificationToken,
|
emailVerificationToken,
|
||||||
orgSponsoredFreeFamilyPlanToken,
|
orgSponsoredFreeFamilyPlanToken,
|
||||||
|
acceptEmergencyAccessInviteToken,
|
||||||
|
emergencyAccessId,
|
||||||
);
|
);
|
||||||
|
|
||||||
const capchaBypassToken = await this.accountApiService.registerFinish(registerRequest);
|
const capchaBypassToken = await this.accountApiService.registerFinish(registerRequest);
|
||||||
@ -55,6 +59,8 @@ export class DefaultRegistrationFinishService implements RegistrationFinishServi
|
|||||||
userAsymmetricKeys: [string, EncString],
|
userAsymmetricKeys: [string, EncString],
|
||||||
emailVerificationToken?: string,
|
emailVerificationToken?: string,
|
||||||
orgSponsoredFreeFamilyPlanToken?: string, // web only
|
orgSponsoredFreeFamilyPlanToken?: string, // web only
|
||||||
|
acceptEmergencyAccessInviteToken?: string, // web only
|
||||||
|
emergencyAccessId?: string, // web only
|
||||||
): Promise<RegisterFinishRequest> {
|
): Promise<RegisterFinishRequest> {
|
||||||
const userAsymmetricKeysRequest = new KeysRequest(
|
const userAsymmetricKeysRequest = new KeysRequest(
|
||||||
userAsymmetricKeys[0],
|
userAsymmetricKeys[0],
|
||||||
|
@ -44,6 +44,10 @@ export class RegistrationFinishComponent implements OnInit, OnDestroy {
|
|||||||
// setup a free family plan sponsored by an organization but they don't have an account yet.
|
// setup a free family plan sponsored by an organization but they don't have an account yet.
|
||||||
orgSponsoredFreeFamilyPlanToken: string;
|
orgSponsoredFreeFamilyPlanToken: string;
|
||||||
|
|
||||||
|
// this token is provided when the user is coming from an emailed invite to accept an emergency access invite
|
||||||
|
acceptEmergencyAccessInviteToken: string;
|
||||||
|
emergencyAccessId: string;
|
||||||
|
|
||||||
masterPasswordPolicyOptions: MasterPasswordPolicyOptions | null = null;
|
masterPasswordPolicyOptions: MasterPasswordPolicyOptions | null = null;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@ -79,6 +83,11 @@ export class RegistrationFinishComponent implements OnInit, OnDestroy {
|
|||||||
if (qParams.orgSponsoredFreeFamilyPlanToken != null) {
|
if (qParams.orgSponsoredFreeFamilyPlanToken != null) {
|
||||||
this.orgSponsoredFreeFamilyPlanToken = qParams.orgSponsoredFreeFamilyPlanToken;
|
this.orgSponsoredFreeFamilyPlanToken = qParams.orgSponsoredFreeFamilyPlanToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (qParams.acceptEmergencyAccessInviteToken != null && qParams.emergencyAccessId) {
|
||||||
|
this.acceptEmergencyAccessInviteToken = qParams.acceptEmergencyAccessInviteToken;
|
||||||
|
this.emergencyAccessId = qParams.emergencyAccessId;
|
||||||
|
}
|
||||||
}),
|
}),
|
||||||
switchMap((qParams: Params) => {
|
switchMap((qParams: Params) => {
|
||||||
if (
|
if (
|
||||||
@ -111,6 +120,8 @@ export class RegistrationFinishComponent implements OnInit, OnDestroy {
|
|||||||
passwordInputResult,
|
passwordInputResult,
|
||||||
this.emailVerificationToken,
|
this.emailVerificationToken,
|
||||||
this.orgSponsoredFreeFamilyPlanToken,
|
this.orgSponsoredFreeFamilyPlanToken,
|
||||||
|
this.acceptEmergencyAccessInviteToken,
|
||||||
|
this.emergencyAccessId,
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.validationService.showError(e);
|
this.validationService.showError(e);
|
||||||
|
@ -16,6 +16,8 @@ export abstract class RegistrationFinishService {
|
|||||||
* @param passwordInputResult The password input result.
|
* @param passwordInputResult The password input result.
|
||||||
* @param emailVerificationToken The optional email verification token. Not present in emailed invite scenarios (ex: org invite).
|
* @param emailVerificationToken The optional email verification token. Not present in emailed invite scenarios (ex: org invite).
|
||||||
* @param orgSponsoredFreeFamilyPlanToken The optional org sponsored free family plan token.
|
* @param orgSponsoredFreeFamilyPlanToken The optional org sponsored free family plan token.
|
||||||
|
* @param acceptEmergencyAccessInviteToken The optional accept emergency access invite token.
|
||||||
|
* @param emergencyAccessId The optional emergency access id which is required to validate the emergency access invite token.
|
||||||
* Returns a promise which resolves to the captcha bypass token string upon a successful account creation.
|
* Returns a promise which resolves to the captcha bypass token string upon a successful account creation.
|
||||||
*/
|
*/
|
||||||
abstract finishRegistration(
|
abstract finishRegistration(
|
||||||
@ -23,5 +25,7 @@ export abstract class RegistrationFinishService {
|
|||||||
passwordInputResult: PasswordInputResult,
|
passwordInputResult: PasswordInputResult,
|
||||||
emailVerificationToken?: string,
|
emailVerificationToken?: string,
|
||||||
orgSponsoredFreeFamilyPlanToken?: string,
|
orgSponsoredFreeFamilyPlanToken?: string,
|
||||||
|
acceptEmergencyAccessInviteToken?: string,
|
||||||
|
emergencyAccessId?: string,
|
||||||
): Promise<string>;
|
): Promise<string>;
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,8 @@ export class RegisterFinishRequest {
|
|||||||
|
|
||||||
public emailVerificationToken?: string,
|
public emailVerificationToken?: string,
|
||||||
public orgSponsoredFreeFamilyPlanToken?: string,
|
public orgSponsoredFreeFamilyPlanToken?: string,
|
||||||
|
public acceptEmergencyAccessInviteToken?: string,
|
||||||
|
public acceptEmergencyAccessId?: string,
|
||||||
|
|
||||||
// Org Invite data (only applies on web)
|
// Org Invite data (only applies on web)
|
||||||
public organizationUserId?: string,
|
public organizationUserId?: string,
|
||||||
|
Loading…
Reference in New Issue
Block a user