diff --git a/common/src/models/request/identityToken/apiTokenRequest.ts b/common/src/models/request/identityToken/apiTokenRequest.ts index cc367fc4..6a1b4059 100644 --- a/common/src/models/request/identityToken/apiTokenRequest.ts +++ b/common/src/models/request/identityToken/apiTokenRequest.ts @@ -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) { diff --git a/common/src/models/request/identityToken/passwordTokenRequest.ts b/common/src/models/request/identityToken/passwordTokenRequest.ts index 31fd7b7c..d362a95b 100644 --- a/common/src/models/request/identityToken/passwordTokenRequest.ts +++ b/common/src/models/request/identityToken/passwordTokenRequest.ts @@ -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; diff --git a/common/src/models/request/identityToken/ssoTokenRequest.ts b/common/src/models/request/identityToken/ssoTokenRequest.ts index 2e087d8b..e07022f8 100644 --- a/common/src/models/request/identityToken/ssoTokenRequest.ts +++ b/common/src/models/request/identityToken/ssoTokenRequest.ts @@ -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; diff --git a/common/src/models/request/identityToken/tokenRequest.ts b/common/src/models/request/identityToken/tokenRequest.ts index 2d4709fb..25639379 100644 --- a/common/src/models/request/identityToken/tokenRequest.ts +++ b/common/src/models/request/identityToken/tokenRequest.ts @@ -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) { diff --git a/common/src/services/auth.service.ts b/common/src/services/auth.service.ts index ca968ea6..abce0f28 100644 --- a/common/src/services/auth.service.ts +++ b/common/src/services/auth.service.ts @@ -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."); } diff --git a/spec/common/services/auth.service.spec.ts b/spec/common/services/auth.service.spec.ts index 1734a4b9..76b619e4 100644 --- a/spec/common/services/auth.service.spec.ts +++ b/spec/common/services/auth.service.spec.ts @@ -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; @@ -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 ); }) );