1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-15 07:43:35 +00:00

[SG-168] Passwordless login web MVP (#3424)

* passwordless login page redesign

* passwordless login page redesign

* restyled login form to use tailwind

* restyled login form to use tailwind

* moved texts on login device template to locales

* made reactive form changes for clients

* added request model

* made more changes

* added implmentation to auth request api

* fixed refrencing issue

* renamed model property

* Added resend notification functionality

* Added new file

* login with device first draft

* login with device first draft

* login with device first draft

* login with device first draft

* connection to anonymous hub

* connection to anonymous hub

* refactored confirm login response

* removed comment

* cleaned up login

* changed uptyped form builder

* changed uptyped form builder

* [SG-168] Update login strategy with passwordless login credentials.

* [SG-168] Removed logs. Changed inputs for passwordless logic strategy. Removed tokenRequestPasswordless it is using the same as password.

* code cleanup

* code cleanup

* removed login with device from self hosted

* fixed PR comments

* added module for login

* fixed post request bug

* added feature flag

* added feature flag

* added feature flag

Co-authored-by: André Bispo <abispo@bitwarden.com>
This commit is contained in:
Gbubemi Smith
2022-09-26 23:26:10 +01:00
committed by GitHub
parent debaef2941
commit 22a878792e
38 changed files with 907 additions and 240 deletions

View File

@@ -1,3 +1,5 @@
import { SymmetricCryptoKey } from "@bitwarden/common/models/domain/symmetricCryptoKey";
import { AuthenticationType } from "../../enums/authenticationType";
import { TokenRequestTwoFactor } from "../request/identityToken/tokenRequestTwoFactor";
@@ -29,3 +31,16 @@ export class ApiLogInCredentials {
constructor(public clientId: string, public clientSecret: string) {}
}
export class PasswordlessLogInCredentials {
readonly type = AuthenticationType.Passwordless;
constructor(
public email: string,
public accessCode: string,
public authRequestId: string,
public decKey: SymmetricCryptoKey,
public localPasswordHash: string,
public twoFactor?: TokenRequestTwoFactor
) {}
}

View File

@@ -4,6 +4,7 @@ import { TokenRequestTwoFactor } from "./tokenRequestTwoFactor";
export abstract class TokenRequest {
protected device?: DeviceRequest;
protected passwordlessAuthRequest: string;
constructor(protected twoFactor: TokenRequestTwoFactor, device?: DeviceRequest) {
this.device = device != null ? device : null;
@@ -18,6 +19,10 @@ export abstract class TokenRequest {
this.twoFactor = twoFactor;
}
setPasswordlessAccessCode(accessCode: string) {
this.passwordlessAuthRequest = accessCode;
}
protected toIdentityToken(clientId: string) {
const obj: any = {
scope: "api offline_access",
@@ -32,6 +37,11 @@ export abstract class TokenRequest {
// obj.devicePushToken = this.device.pushToken;
}
//passswordless login
if (this.passwordlessAuthRequest) {
obj.authRequest = this.passwordlessAuthRequest;
}
if (this.twoFactor.token && this.twoFactor.provider != null) {
obj.twoFactorToken = this.twoFactor.token;
obj.twoFactorProvider = this.twoFactor.provider;

View File

@@ -0,0 +1,12 @@
import { AuthRequestType } from "../../enums/authRequestType";
export class PasswordlessCreateAuthRequest {
constructor(
readonly email: string,
readonly deviceIdentifier: string,
readonly publicKey: string,
readonly type: AuthRequestType,
readonly accessCode: string,
readonly fingerprintPhrase: string
) {}
}

View File

@@ -0,0 +1,26 @@
import { DeviceType } from "@bitwarden/common/enums/deviceType";
import { BaseResponse } from "./baseResponse";
export class AuthRequestResponse extends BaseResponse {
id: string;
publicKey: string;
requestDeviceType: DeviceType;
requestIpAddress: string;
key: string;
masterPasswordHash: string;
creationDate: string;
requestApproved: boolean;
constructor(response: any) {
super(response);
this.id = this.getResponseProperty("Id");
this.publicKey = this.getResponseProperty("PublicKey");
this.requestDeviceType = this.getResponseProperty("RequestDeviceType");
this.requestIpAddress = this.getResponseProperty("RequestIpAddress");
this.key = this.getResponseProperty("Key");
this.masterPasswordHash = this.getResponseProperty("MasterPasswordHash");
this.creationDate = this.getResponseProperty("CreationDate");
this.requestApproved = this.getResponseProperty("RequestApproved");
}
}

View File

@@ -37,6 +37,10 @@ export class NotificationResponse extends BaseResponse {
case NotificationType.SyncSendDelete:
this.payload = new SyncSendNotification(payload);
break;
case NotificationType.AuthRequest:
case NotificationType.AuthRequestResponse:
this.payload = new AuthRequestPushNotification(payload);
break;
default:
break;
}
@@ -96,3 +100,14 @@ export class SyncSendNotification extends BaseResponse {
this.revisionDate = new Date(this.getResponseProperty("RevisionDate"));
}
}
export class AuthRequestPushNotification extends BaseResponse {
id: string;
userId: string;
constructor(response: any) {
super(response);
this.id = this.getResponseProperty("Id");
this.userId = this.getResponseProperty("UserId");
}
}