mirror of
https://github.com/bitwarden/jslib
synced 2025-12-15 15:53:51 +00:00
Refactor TokenRequest to take TwoFactorData
This commit is contained in:
@@ -1,26 +1,16 @@
|
||||
import { TokenRequest } from "./tokenRequest";
|
||||
|
||||
import { TwoFactorProviderType } from "../../../enums/twoFactorProviderType";
|
||||
import { TokenRequest, TwoFactorData } from "./tokenRequest";
|
||||
|
||||
import { DeviceRequest } from "../deviceRequest";
|
||||
|
||||
export class ApiTokenRequest extends TokenRequest {
|
||||
clientId: string;
|
||||
clientSecret: string;
|
||||
|
||||
constructor(
|
||||
clientId: string,
|
||||
clientSecret: string,
|
||||
public provider: TwoFactorProviderType,
|
||||
public token: string,
|
||||
public remember: boolean,
|
||||
public captchaResponse: string,
|
||||
private clientId: string,
|
||||
private clientSecret: string,
|
||||
protected twoFactor: TwoFactorData,
|
||||
captchaResponse: string,
|
||||
device?: DeviceRequest
|
||||
) {
|
||||
super(provider, token, remember, captchaResponse, device);
|
||||
|
||||
this.clientId = clientId;
|
||||
this.clientSecret = clientSecret;
|
||||
super(twoFactor, captchaResponse, device);
|
||||
}
|
||||
|
||||
toIdentityToken(clientId: string) {
|
||||
|
||||
@@ -1,25 +1,18 @@
|
||||
import { TokenRequest } from "./tokenRequest";
|
||||
|
||||
import { TwoFactorProviderType } from "../../../enums/twoFactorProviderType";
|
||||
import { TokenRequest, TwoFactorData } from "./tokenRequest";
|
||||
|
||||
import { DeviceRequest } from "../deviceRequest";
|
||||
|
||||
import { Utils } from "../../../misc/utils";
|
||||
|
||||
export class PasswordTokenRequest extends TokenRequest {
|
||||
email: string;
|
||||
masterPasswordHash: string;
|
||||
|
||||
constructor(
|
||||
email: string,
|
||||
masterPasswordHash: string,
|
||||
public provider: TwoFactorProviderType,
|
||||
public token: string,
|
||||
public remember: boolean,
|
||||
public captchaResponse: string,
|
||||
private email: string,
|
||||
private masterPasswordHash: string,
|
||||
protected twoFactor: TwoFactorData,
|
||||
captchaResponse: string,
|
||||
device?: DeviceRequest
|
||||
) {
|
||||
super(provider, token, remember, captchaResponse, device);
|
||||
super(twoFactor, captchaResponse, device);
|
||||
|
||||
this.email = email;
|
||||
this.masterPasswordHash = masterPasswordHash;
|
||||
|
||||
@@ -1,25 +1,17 @@
|
||||
import { TokenRequest } from "./tokenRequest";
|
||||
|
||||
import { TwoFactorProviderType } from "../../../enums/twoFactorProviderType";
|
||||
import { TokenRequest, TwoFactorData } from "./tokenRequest";
|
||||
|
||||
import { DeviceRequest } from "../deviceRequest";
|
||||
|
||||
export class SsoTokenRequest extends TokenRequest {
|
||||
code: string;
|
||||
codeVerifier: string;
|
||||
redirectUri: string;
|
||||
|
||||
constructor(
|
||||
code: string,
|
||||
codeVerifier: string,
|
||||
redirectUri: string,
|
||||
public provider: TwoFactorProviderType,
|
||||
public token: string,
|
||||
public remember: boolean,
|
||||
public captchaResponse: string,
|
||||
private code: string,
|
||||
private codeVerifier: string,
|
||||
private redirectUri: string,
|
||||
protected twoFactor: TwoFactorData,
|
||||
captchaResponse: string,
|
||||
device?: DeviceRequest
|
||||
) {
|
||||
super(provider, token, remember, captchaResponse, device);
|
||||
super(twoFactor, captchaResponse, device);
|
||||
|
||||
this.code = code;
|
||||
this.codeVerifier = codeVerifier;
|
||||
|
||||
@@ -3,13 +3,17 @@ import { TwoFactorProviderType } from "../../../enums/twoFactorProviderType";
|
||||
import { CaptchaProtectedRequest } from "../captchaProtectedRequest";
|
||||
import { DeviceRequest } from "../deviceRequest";
|
||||
|
||||
export interface TwoFactorData {
|
||||
provider: TwoFactorProviderType;
|
||||
token: string;
|
||||
remember: boolean;
|
||||
}
|
||||
|
||||
export abstract class TokenRequest implements CaptchaProtectedRequest {
|
||||
device?: DeviceRequest;
|
||||
protected device?: DeviceRequest;
|
||||
|
||||
constructor(
|
||||
public provider: TwoFactorProviderType,
|
||||
public token: string,
|
||||
public remember: boolean,
|
||||
protected twoFactor: TwoFactorData,
|
||||
public captchaResponse: string,
|
||||
device?: DeviceRequest
|
||||
) {
|
||||
@@ -30,10 +34,10 @@ export abstract class TokenRequest implements CaptchaProtectedRequest {
|
||||
// obj.devicePushToken = this.device.pushToken;
|
||||
}
|
||||
|
||||
if (this.token && this.provider != null) {
|
||||
obj.twoFactorToken = this.token;
|
||||
obj.twoFactorProvider = this.provider;
|
||||
obj.twoFactorRemember = this.remember ? "1" : "0";
|
||||
if (this.twoFactor.token && this.twoFactor.provider != null) {
|
||||
obj.twoFactorToken = this.twoFactor.token;
|
||||
obj.twoFactorProvider = this.twoFactor.provider;
|
||||
obj.twoFactorRemember = this.twoFactor.remember ? "1" : "0";
|
||||
}
|
||||
|
||||
if (this.captchaResponse != null) {
|
||||
|
||||
@@ -15,6 +15,7 @@ import { PreloginRequest } from "../models/request/preloginRequest";
|
||||
import { ApiTokenRequest } from "../models/request/identityToken/apiTokenRequest";
|
||||
import { PasswordTokenRequest } from "../models/request/identityToken/passwordTokenRequest";
|
||||
import { SsoTokenRequest } from "../models/request/identityToken/ssoTokenRequest";
|
||||
import { TwoFactorData } from "../models/request/identityToken/tokenRequest";
|
||||
|
||||
import { IdentityTokenResponse } from "../models/response/identityTokenResponse";
|
||||
import { IdentityTwoFactorResponse } from "../models/response/identityTwoFactorResponse";
|
||||
@@ -386,6 +387,11 @@ export class AuthService implements AuthServiceAbstraction {
|
||||
return result;
|
||||
}
|
||||
|
||||
private async createDeviceRequest() {
|
||||
const appId = await this.appIdService.getAppId();
|
||||
return new DeviceRequest(appId, this.platformUtilsService);
|
||||
}
|
||||
|
||||
private async createTokenRequest(
|
||||
email: string,
|
||||
hashedPassword: string,
|
||||
@@ -399,30 +405,29 @@ export class AuthService implements AuthServiceAbstraction {
|
||||
remember: boolean,
|
||||
captchaToken: string
|
||||
) {
|
||||
const appId = await this.appIdService.getAppId();
|
||||
const deviceRequest = await this.createDeviceRequest();
|
||||
const storedTwoFactorToken = await this.tokenService.getTwoFactorToken(email);
|
||||
const deviceRequest = new DeviceRequest(appId, this.platformUtilsService);
|
||||
|
||||
let effectiveToken = null;
|
||||
let effectiveProvider = null;
|
||||
let effectiveRemember = false;
|
||||
const twoFactor: TwoFactorData = {
|
||||
token: null,
|
||||
provider: null,
|
||||
remember: false,
|
||||
};
|
||||
|
||||
if (twoFactorToken != null && twoFactorProvider != null) {
|
||||
effectiveToken = twoFactorToken;
|
||||
effectiveProvider = twoFactorProvider;
|
||||
effectiveRemember = remember;
|
||||
twoFactor.token = twoFactorToken;
|
||||
twoFactor.provider = twoFactorProvider;
|
||||
twoFactor.remember = remember;
|
||||
} else if (storedTwoFactorToken != null) {
|
||||
effectiveToken = storedTwoFactorToken;
|
||||
effectiveProvider = TwoFactorProviderType.Remember;
|
||||
twoFactor.token = storedTwoFactorToken;
|
||||
twoFactor.provider = TwoFactorProviderType.Remember;
|
||||
}
|
||||
|
||||
if (email != null && hashedPassword != null) {
|
||||
return new PasswordTokenRequest(
|
||||
email,
|
||||
hashedPassword,
|
||||
effectiveProvider,
|
||||
effectiveToken,
|
||||
effectiveRemember,
|
||||
twoFactor,
|
||||
captchaToken,
|
||||
deviceRequest
|
||||
);
|
||||
@@ -431,22 +436,12 @@ export class AuthService implements AuthServiceAbstraction {
|
||||
code,
|
||||
codeVerifier,
|
||||
redirectUrl,
|
||||
effectiveProvider,
|
||||
effectiveToken,
|
||||
effectiveRemember,
|
||||
twoFactor,
|
||||
captchaToken,
|
||||
deviceRequest
|
||||
);
|
||||
} else if (clientId != null && clientSecret != null) {
|
||||
return new ApiTokenRequest(
|
||||
clientId,
|
||||
clientSecret,
|
||||
effectiveProvider,
|
||||
effectiveToken,
|
||||
effectiveRemember,
|
||||
captchaToken,
|
||||
deviceRequest
|
||||
);
|
||||
return new ApiTokenRequest(clientId, clientSecret, twoFactor, captchaToken, deviceRequest);
|
||||
} else {
|
||||
throw new Error("No credentials provided.");
|
||||
}
|
||||
|
||||
@@ -5,14 +5,12 @@ import { AppIdService } from "jslib-common/abstractions/appId.service";
|
||||
import { CryptoService } from "jslib-common/abstractions/crypto.service";
|
||||
import { CryptoFunctionService } from "jslib-common/abstractions/cryptoFunction.service";
|
||||
import { EnvironmentService } from "jslib-common/abstractions/environment.service";
|
||||
import { I18nService } from "jslib-common/abstractions/i18n.service";
|
||||
import { KeyConnectorService } from "jslib-common/abstractions/keyConnector.service";
|
||||
import { LogService } from "jslib-common/abstractions/log.service";
|
||||
import { MessagingService } from "jslib-common/abstractions/messaging.service";
|
||||
import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service";
|
||||
import { StateService } from "jslib-common/abstractions/state.service";
|
||||
import { TokenService } from "jslib-common/abstractions/token.service";
|
||||
import { VaultTimeoutService } from "jslib-common/abstractions/vaultTimeout.service";
|
||||
|
||||
import { AuthService } from "jslib-common/services/auth.service";
|
||||
|
||||
@@ -28,9 +26,6 @@ import { IdentityTokenResponse } from "jslib-common/models/response/identityToke
|
||||
import { TwoFactorService } from "jslib-common/abstractions/twoFactor.service";
|
||||
import { HashPurpose } from "jslib-common/enums/hashPurpose";
|
||||
import { TwoFactorProviderType } from "jslib-common/enums/twoFactorProviderType";
|
||||
import { SsoTokenRequest } from "jslib-common/models/request/identityToken/ssoTokenRequest";
|
||||
import { ApiTokenRequest } from "jslib-common/models/request/identityToken/apiTokenRequest";
|
||||
import { PasswordTokenRequest } from "jslib-common/models/request/identityToken/passwordTokenRequest";
|
||||
|
||||
describe("Cipher Service", () => {
|
||||
let cryptoService: SubstituteOf<CryptoService>;
|
||||
@@ -201,14 +196,14 @@ describe("Cipher Service", () => {
|
||||
// Api call:
|
||||
apiService.received(1).postIdentityToken(
|
||||
Arg.is((actual) => {
|
||||
const passwordTokenRequest = actual as PasswordTokenRequest;
|
||||
const passwordTokenRequest = actual as any; // Need to access private fields
|
||||
return (
|
||||
passwordTokenRequest.email === email &&
|
||||
passwordTokenRequest.masterPasswordHash === hashedPassword &&
|
||||
actual.device.identifier === deviceId &&
|
||||
actual.provider == null &&
|
||||
actual.token == null &&
|
||||
actual.captchaResponse == null
|
||||
passwordTokenRequest.device.identifier === deviceId &&
|
||||
passwordTokenRequest.twoFactor.provider == null &&
|
||||
passwordTokenRequest.twoFactor.token == null &&
|
||||
passwordTokenRequest.captchaResponse == null
|
||||
);
|
||||
})
|
||||
);
|
||||
@@ -341,15 +336,15 @@ describe("Cipher Service", () => {
|
||||
|
||||
apiService.received(1).postIdentityToken(
|
||||
Arg.is((actual) => {
|
||||
const passwordTokenRequest = actual as PasswordTokenRequest;
|
||||
const passwordTokenRequest = actual as any;
|
||||
return (
|
||||
passwordTokenRequest.email === email &&
|
||||
passwordTokenRequest.masterPasswordHash === hashedPassword &&
|
||||
actual.device.identifier === deviceId &&
|
||||
actual.provider === twoFactorProviderType &&
|
||||
actual.token === twoFactorToken &&
|
||||
actual.remember === twoFactorRemember &&
|
||||
actual.captchaResponse == null
|
||||
passwordTokenRequest.device.identifier === deviceId &&
|
||||
passwordTokenRequest.twoFactor.provider == twoFactorProviderType &&
|
||||
passwordTokenRequest.twoFactor.token == twoFactorToken &&
|
||||
passwordTokenRequest.twoFactor.remember == twoFactorRemember &&
|
||||
passwordTokenRequest.captchaResponse == null
|
||||
);
|
||||
})
|
||||
);
|
||||
@@ -370,14 +365,14 @@ describe("Cipher Service", () => {
|
||||
// Api call:
|
||||
apiService.received(1).postIdentityToken(
|
||||
Arg.is((actual) => {
|
||||
const ssoTokenRequest = actual as SsoTokenRequest;
|
||||
const ssoTokenRequest = actual as any;
|
||||
return (
|
||||
ssoTokenRequest.code === ssoCode &&
|
||||
ssoTokenRequest.codeVerifier === ssoCodeVerifier &&
|
||||
ssoTokenRequest.redirectUri === ssoRedirectUrl &&
|
||||
actual.device.identifier === deviceId &&
|
||||
actual.provider == null &&
|
||||
actual.token == null &&
|
||||
ssoTokenRequest.device.identifier === deviceId &&
|
||||
ssoTokenRequest.twoFactor.provider == null &&
|
||||
ssoTokenRequest.twoFactor.token == null &&
|
||||
actual.captchaResponse == null
|
||||
);
|
||||
})
|
||||
@@ -491,14 +486,14 @@ describe("Cipher Service", () => {
|
||||
|
||||
apiService.received(1).postIdentityToken(
|
||||
Arg.is((actual) => {
|
||||
const apiTokenRequest = actual as ApiTokenRequest;
|
||||
const apiTokenRequest = actual as any;
|
||||
return (
|
||||
apiTokenRequest.clientId === apiClientId &&
|
||||
apiTokenRequest.clientSecret === apiClientSecret &&
|
||||
actual.device.identifier === deviceId &&
|
||||
actual.provider == null &&
|
||||
actual.token == null &&
|
||||
actual.captchaResponse == null
|
||||
apiTokenRequest.device.identifier === deviceId &&
|
||||
apiTokenRequest.twoFactor.provider == null &&
|
||||
apiTokenRequest.twoFactor.token == null &&
|
||||
apiTokenRequest.captchaResponse == null
|
||||
);
|
||||
})
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user