mirror of
https://github.com/bitwarden/jslib
synced 2025-12-14 15:23:37 +00:00
Break tokenRequest into subclasses
This commit is contained in:
@@ -75,7 +75,6 @@ import { SendRequest } from '../models/request/sendRequest';
|
|||||||
import { SetPasswordRequest } from '../models/request/setPasswordRequest';
|
import { SetPasswordRequest } from '../models/request/setPasswordRequest';
|
||||||
import { StorageRequest } from '../models/request/storageRequest';
|
import { StorageRequest } from '../models/request/storageRequest';
|
||||||
import { TaxInfoUpdateRequest } from '../models/request/taxInfoUpdateRequest';
|
import { TaxInfoUpdateRequest } from '../models/request/taxInfoUpdateRequest';
|
||||||
import { TokenRequest } from '../models/request/tokenRequest';
|
|
||||||
import { TwoFactorEmailRequest } from '../models/request/twoFactorEmailRequest';
|
import { TwoFactorEmailRequest } from '../models/request/twoFactorEmailRequest';
|
||||||
import { TwoFactorProviderRequest } from '../models/request/twoFactorProviderRequest';
|
import { TwoFactorProviderRequest } from '../models/request/twoFactorProviderRequest';
|
||||||
import { TwoFactorRecoveryRequest } from '../models/request/twoFactorRecoveryRequest';
|
import { TwoFactorRecoveryRequest } from '../models/request/twoFactorRecoveryRequest';
|
||||||
@@ -93,6 +92,10 @@ import { VerifyBankRequest } from '../models/request/verifyBankRequest';
|
|||||||
import { VerifyDeleteRecoverRequest } from '../models/request/verifyDeleteRecoverRequest';
|
import { VerifyDeleteRecoverRequest } from '../models/request/verifyDeleteRecoverRequest';
|
||||||
import { VerifyEmailRequest } from '../models/request/verifyEmailRequest';
|
import { VerifyEmailRequest } from '../models/request/verifyEmailRequest';
|
||||||
|
|
||||||
|
import { ApiTokenRequest } from '../models/request/identityToken/apiTokenRequest';
|
||||||
|
import { PasswordTokenRequest } from '../models/request/identityToken/passwordTokenRequest';
|
||||||
|
import { SsoTokenRequest } from '../models/request/identityToken/ssoTokenRequest';
|
||||||
|
|
||||||
import { ApiKeyResponse } from '../models/response/apiKeyResponse';
|
import { ApiKeyResponse } from '../models/response/apiKeyResponse';
|
||||||
import { AttachmentResponse } from '../models/response/attachmentResponse';
|
import { AttachmentResponse } from '../models/response/attachmentResponse';
|
||||||
import { AttachmentUploadDataResponse } from '../models/response/attachmentUploadDataResponse';
|
import { AttachmentUploadDataResponse } from '../models/response/attachmentUploadDataResponse';
|
||||||
@@ -164,7 +167,8 @@ import { UserKeyResponse } from '../models/response/userKeyResponse';
|
|||||||
import { SendAccessView } from '../models/view/sendAccessView';
|
import { SendAccessView } from '../models/view/sendAccessView';
|
||||||
|
|
||||||
export abstract class ApiService {
|
export abstract class ApiService {
|
||||||
postIdentityToken: (request: TokenRequest) => Promise<IdentityTokenResponse | IdentityTwoFactorResponse | IdentityCaptchaResponse>;
|
postIdentityToken: (request: PasswordTokenRequest | SsoTokenRequest | ApiTokenRequest) =>
|
||||||
|
Promise<IdentityTokenResponse | IdentityTwoFactorResponse | IdentityCaptchaResponse>;
|
||||||
refreshIdentityToken: () => Promise<any>;
|
refreshIdentityToken: () => Promise<any>;
|
||||||
|
|
||||||
getProfile: () => Promise<ProfileResponse>;
|
getProfile: () => Promise<ProfileResponse>;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export abstract class TokenService {
|
|||||||
toggleTokens: () => Promise<any>;
|
toggleTokens: () => Promise<any>;
|
||||||
setTwoFactorToken: (token: string, email: string) => Promise<any>;
|
setTwoFactorToken: (token: string, email: string) => Promise<any>;
|
||||||
getTwoFactorToken: (email: string) => Promise<string>;
|
getTwoFactorToken: (email: string) => Promise<string>;
|
||||||
clearTwoFactorToken: (email: string) => Promise<any>;
|
clearTwoFactorToken: () => Promise<any>;
|
||||||
clearToken: (userId?: string) => Promise<any>;
|
clearToken: (userId?: string) => Promise<any>;
|
||||||
decodeToken: (token?: string) => any;
|
decodeToken: (token?: string) => any;
|
||||||
getTokenExpirationDate: () => Promise<Date>;
|
getTokenExpirationDate: () => Promise<Date>;
|
||||||
|
|||||||
29
common/src/models/request/identityToken/apiTokenRequest.ts
Normal file
29
common/src/models/request/identityToken/apiTokenRequest.ts
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import { TokenRequest } from './tokenRequest';
|
||||||
|
|
||||||
|
import { TwoFactorProviderType } from '../../../enums/twoFactorProviderType';
|
||||||
|
|
||||||
|
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, device?: DeviceRequest) {
|
||||||
|
super(provider, token, remember, captchaResponse, device);
|
||||||
|
|
||||||
|
this.clientId = clientId
|
||||||
|
this.clientSecret = clientSecret;
|
||||||
|
}
|
||||||
|
|
||||||
|
toIdentityToken(clientId: string) {
|
||||||
|
const obj = super.toIdentityToken(clientId);
|
||||||
|
|
||||||
|
obj.clientId = this.clientId;
|
||||||
|
obj.scope = clientId.startsWith('organization') ? 'api.organization' : 'api';
|
||||||
|
obj.grant_type = 'client_credentials';
|
||||||
|
obj.client_secret = this.clientSecret;
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import { TokenRequest } from './tokenRequest';
|
||||||
|
|
||||||
|
import { TwoFactorProviderType } from '../../../enums/twoFactorProviderType';
|
||||||
|
|
||||||
|
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, device?: DeviceRequest) {
|
||||||
|
super(provider, token, remember, captchaResponse, device);
|
||||||
|
|
||||||
|
this.email = email;
|
||||||
|
this.masterPasswordHash = masterPasswordHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
toIdentityToken(clientId: string) {
|
||||||
|
const obj = super.toIdentityToken(clientId);
|
||||||
|
|
||||||
|
obj.grant_type = 'password';
|
||||||
|
obj.username = this.email;
|
||||||
|
obj.password = this.masterPasswordHash;
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
alterIdentityTokenHeaders(headers: Headers) {
|
||||||
|
headers.set('Auth-Email', Utils.fromUtf8ToUrlB64(this.email));
|
||||||
|
}
|
||||||
|
}
|
||||||
31
common/src/models/request/identityToken/ssoTokenRequest.ts
Normal file
31
common/src/models/request/identityToken/ssoTokenRequest.ts
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import { TokenRequest } from './tokenRequest';
|
||||||
|
|
||||||
|
import { TwoFactorProviderType } from '../../../enums/twoFactorProviderType';
|
||||||
|
|
||||||
|
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, device?: DeviceRequest) {
|
||||||
|
super(provider, token, remember, captchaResponse, device);
|
||||||
|
|
||||||
|
this.code = code;
|
||||||
|
this.codeVerifier = codeVerifier;
|
||||||
|
this.redirectUri = redirectUri;
|
||||||
|
}
|
||||||
|
|
||||||
|
toIdentityToken(clientId: string) {
|
||||||
|
const obj = super.toIdentityToken(clientId);
|
||||||
|
|
||||||
|
obj.grant_type = 'authorization_code';
|
||||||
|
obj.code = this.code;
|
||||||
|
obj.code_verifier = this.codeVerifier;
|
||||||
|
obj.redirect_uri = this.redirectUri;
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
}
|
||||||
44
common/src/models/request/identityToken/tokenRequest.ts
Normal file
44
common/src/models/request/identityToken/tokenRequest.ts
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import { TwoFactorProviderType } from '../../../enums/twoFactorProviderType';
|
||||||
|
|
||||||
|
import { CaptchaProtectedRequest } from '../captchaProtectedRequest';
|
||||||
|
import { DeviceRequest } from '../deviceRequest';
|
||||||
|
|
||||||
|
export abstract class TokenRequest implements CaptchaProtectedRequest {
|
||||||
|
device?: DeviceRequest;
|
||||||
|
|
||||||
|
constructor(public provider: TwoFactorProviderType, public token: string, public remember: boolean,
|
||||||
|
public captchaResponse: string, device?: DeviceRequest) {
|
||||||
|
this.device = device != null ? device : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
toIdentityToken(clientId: string) {
|
||||||
|
const obj: any = {
|
||||||
|
scope: 'api offline_access',
|
||||||
|
client_id: clientId,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (this.device) {
|
||||||
|
obj.deviceType = this.device.type;
|
||||||
|
obj.deviceIdentifier = this.device.identifier;
|
||||||
|
obj.deviceName = this.device.name;
|
||||||
|
// no push tokens for browser apps yet
|
||||||
|
// 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.captchaResponse != null) {
|
||||||
|
obj.captchaResponse = this.captchaResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
alterIdentityTokenHeaders(headers: Headers) {
|
||||||
|
// Implemented in subclass if required
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
import { TwoFactorProviderType } from '../../enums/twoFactorProviderType';
|
|
||||||
|
|
||||||
import { CaptchaProtectedRequest } from './captchaProtectedRequest';
|
|
||||||
import { DeviceRequest } from './deviceRequest';
|
|
||||||
|
|
||||||
import { Utils } from '../../misc/utils';
|
|
||||||
|
|
||||||
export class TokenRequest implements CaptchaProtectedRequest {
|
|
||||||
email: string;
|
|
||||||
masterPasswordHash: string;
|
|
||||||
code: string;
|
|
||||||
codeVerifier: string;
|
|
||||||
redirectUri: string;
|
|
||||||
clientId: string;
|
|
||||||
clientSecret: string;
|
|
||||||
device?: DeviceRequest;
|
|
||||||
|
|
||||||
constructor(credentials: string[], codes: string[], clientIdClientSecret: string[], public provider: TwoFactorProviderType,
|
|
||||||
public token: string, public remember: boolean, public captchaResponse: string, device?: DeviceRequest) {
|
|
||||||
if (credentials != null && credentials.length > 1) {
|
|
||||||
this.email = credentials[0];
|
|
||||||
this.masterPasswordHash = credentials[1];
|
|
||||||
} else if (codes != null && codes.length > 2) {
|
|
||||||
this.code = codes[0];
|
|
||||||
this.codeVerifier = codes[1];
|
|
||||||
this.redirectUri = codes[2];
|
|
||||||
} else if (clientIdClientSecret != null && clientIdClientSecret.length > 1) {
|
|
||||||
this.clientId = clientIdClientSecret[0];
|
|
||||||
this.clientSecret = clientIdClientSecret[1];
|
|
||||||
}
|
|
||||||
this.device = device != null ? device : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
toIdentityToken(clientId: string) {
|
|
||||||
const obj: any = {
|
|
||||||
scope: 'api offline_access',
|
|
||||||
client_id: clientId,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (this.clientSecret != null) {
|
|
||||||
obj.scope = clientId.startsWith('organization') ? 'api.organization' : 'api';
|
|
||||||
obj.grant_type = 'client_credentials';
|
|
||||||
obj.client_secret = this.clientSecret;
|
|
||||||
} else if (this.masterPasswordHash != null && this.email != null) {
|
|
||||||
obj.grant_type = 'password';
|
|
||||||
obj.username = this.email;
|
|
||||||
obj.password = this.masterPasswordHash;
|
|
||||||
} else if (this.code != null && this.codeVerifier != null && this.redirectUri != null) {
|
|
||||||
obj.grant_type = 'authorization_code';
|
|
||||||
obj.code = this.code;
|
|
||||||
obj.code_verifier = this.codeVerifier;
|
|
||||||
obj.redirect_uri = this.redirectUri;
|
|
||||||
} else {
|
|
||||||
throw new Error('must provide credentials or codes');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.device) {
|
|
||||||
obj.deviceType = this.device.type;
|
|
||||||
obj.deviceIdentifier = this.device.identifier;
|
|
||||||
obj.deviceName = this.device.name;
|
|
||||||
// no push tokens for browser apps yet
|
|
||||||
// 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.captchaResponse != null) {
|
|
||||||
obj.captchaResponse = this.captchaResponse;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
alterIdentityTokenHeaders(headers: Headers) {
|
|
||||||
if (this.clientSecret == null && this.masterPasswordHash != null && this.email != null) {
|
|
||||||
headers.set('Auth-Email', Utils.fromUtf8ToUrlB64(this.email));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -76,7 +76,7 @@ import { SendRequest } from '../models/request/sendRequest';
|
|||||||
import { SetPasswordRequest } from '../models/request/setPasswordRequest';
|
import { SetPasswordRequest } from '../models/request/setPasswordRequest';
|
||||||
import { StorageRequest } from '../models/request/storageRequest';
|
import { StorageRequest } from '../models/request/storageRequest';
|
||||||
import { TaxInfoUpdateRequest } from '../models/request/taxInfoUpdateRequest';
|
import { TaxInfoUpdateRequest } from '../models/request/taxInfoUpdateRequest';
|
||||||
import { TokenRequest } from '../models/request/tokenRequest';
|
import { TokenRequest } from '../models/request/identityToken/tokenRequest';
|
||||||
import { TwoFactorEmailRequest } from '../models/request/twoFactorEmailRequest';
|
import { TwoFactorEmailRequest } from '../models/request/twoFactorEmailRequest';
|
||||||
import { TwoFactorProviderRequest } from '../models/request/twoFactorProviderRequest';
|
import { TwoFactorProviderRequest } from '../models/request/twoFactorProviderRequest';
|
||||||
import { TwoFactorRecoveryRequest } from '../models/request/twoFactorRecoveryRequest';
|
import { TwoFactorRecoveryRequest } from '../models/request/twoFactorRecoveryRequest';
|
||||||
@@ -209,7 +209,7 @@ export class ApiService implements ApiServiceAbstraction {
|
|||||||
}
|
}
|
||||||
request.alterIdentityTokenHeaders(headers);
|
request.alterIdentityTokenHeaders(headers);
|
||||||
const response = await this.fetch(new Request(this.environmentService.getIdentityUrl() + '/connect/token', {
|
const response = await this.fetch(new Request(this.environmentService.getIdentityUrl() + '/connect/token', {
|
||||||
body: this.qsStringify(request.toIdentityToken(request.clientId ?? this.platformUtilsService.identityClientId)),
|
body: this.qsStringify(request.toIdentityToken(this.platformUtilsService.identityClientId)),
|
||||||
credentials: this.getCredentials(),
|
credentials: this.getCredentials(),
|
||||||
cache: 'no-store',
|
cache: 'no-store',
|
||||||
headers: headers,
|
headers: headers,
|
||||||
@@ -226,7 +226,7 @@ export class ApiService implements ApiServiceAbstraction {
|
|||||||
return new IdentityTokenResponse(responseJson);
|
return new IdentityTokenResponse(responseJson);
|
||||||
} else if (response.status === 400 && responseJson.TwoFactorProviders2 &&
|
} else if (response.status === 400 && responseJson.TwoFactorProviders2 &&
|
||||||
Object.keys(responseJson.TwoFactorProviders2).length) {
|
Object.keys(responseJson.TwoFactorProviders2).length) {
|
||||||
await this.tokenService.clearTwoFactorToken(request.email);
|
await this.tokenService.clearTwoFactorToken();
|
||||||
return new IdentityTwoFactorResponse(responseJson);
|
return new IdentityTwoFactorResponse(responseJson);
|
||||||
} else if (response.status === 400 && responseJson.HCaptcha_SiteKey &&
|
} else if (response.status === 400 && responseJson.HCaptcha_SiteKey &&
|
||||||
Object.keys(responseJson.HCaptcha_SiteKey).length) {
|
Object.keys(responseJson.HCaptcha_SiteKey).length) {
|
||||||
|
|||||||
@@ -11,7 +11,10 @@ import { DeviceRequest } from '../models/request/deviceRequest';
|
|||||||
import { KeyConnectorUserKeyRequest } from '../models/request/keyConnectorUserKeyRequest';
|
import { KeyConnectorUserKeyRequest } from '../models/request/keyConnectorUserKeyRequest';
|
||||||
import { KeysRequest } from '../models/request/keysRequest';
|
import { KeysRequest } from '../models/request/keysRequest';
|
||||||
import { PreloginRequest } from '../models/request/preloginRequest';
|
import { PreloginRequest } from '../models/request/preloginRequest';
|
||||||
import { TokenRequest } from '../models/request/tokenRequest';
|
|
||||||
|
import { ApiTokenRequest } from '../models/request/identityToken/apiTokenRequest';
|
||||||
|
import { PasswordTokenRequest } from '../models/request/identityToken/passwordTokenRequest';
|
||||||
|
import { SsoTokenRequest } from '../models/request/identityToken/ssoTokenRequest';
|
||||||
|
|
||||||
import { IdentityTokenResponse } from '../models/response/identityTokenResponse';
|
import { IdentityTokenResponse } from '../models/response/identityTokenResponse';
|
||||||
import { IdentityTwoFactorResponse } from '../models/response/identityTwoFactorResponse';
|
import { IdentityTwoFactorResponse } from '../models/response/identityTwoFactorResponse';
|
||||||
@@ -142,6 +145,7 @@ export class AuthService implements AuthServiceAbstraction {
|
|||||||
}
|
}
|
||||||
return this.cryptoService.makeKey(masterPassword, email, kdf, kdfIterations);
|
return this.cryptoService.makeKey(masterPassword, email, kdf, kdfIterations);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async logInHelper(email: string, hashedPassword: string, localHashedPassword: string, code: string,
|
private async logInHelper(email: string, hashedPassword: string, localHashedPassword: string, code: string,
|
||||||
codeVerifier: string, redirectUrl: string, clientId: string, clientSecret: string, key: SymmetricCryptoKey,
|
codeVerifier: string, redirectUrl: string, clientId: string, clientSecret: string, key: SymmetricCryptoKey,
|
||||||
twoFactorProvider?: TwoFactorProviderType, twoFactorToken?: string, remember?: boolean, captchaToken?: string,
|
twoFactorProvider?: TwoFactorProviderType, twoFactorToken?: string, remember?: boolean, captchaToken?: string,
|
||||||
@@ -223,39 +227,31 @@ export class AuthService implements AuthServiceAbstraction {
|
|||||||
const storedTwoFactorToken = await this.tokenService.getTwoFactorToken(email);
|
const storedTwoFactorToken = await this.tokenService.getTwoFactorToken(email);
|
||||||
const deviceRequest = new DeviceRequest(appId, this.platformUtilsService);
|
const deviceRequest = new DeviceRequest(appId, this.platformUtilsService);
|
||||||
|
|
||||||
let emailPassword: string[] = [];
|
let effectiveToken = null;
|
||||||
let codeCodeVerifier: string[] = [];
|
let effectiveProvider = null;
|
||||||
let clientIdClientSecret: [string, string] = [null, null];
|
let effectiveRemember = false;
|
||||||
|
|
||||||
|
if (twoFactorToken != null && twoFactorProvider != null) {
|
||||||
|
effectiveToken = twoFactorToken;
|
||||||
|
effectiveProvider = twoFactorProvider;
|
||||||
|
effectiveRemember = remember;
|
||||||
|
} else if (storedTwoFactorToken != null) {
|
||||||
|
effectiveToken = storedTwoFactorToken;
|
||||||
|
effectiveProvider = TwoFactorProviderType.Remember;
|
||||||
|
}
|
||||||
|
|
||||||
if (email != null && hashedPassword != null) {
|
if (email != null && hashedPassword != null) {
|
||||||
emailPassword = [email, hashedPassword];
|
return new PasswordTokenRequest(email, hashedPassword, effectiveProvider, effectiveToken,
|
||||||
|
effectiveRemember, captchaToken, deviceRequest);
|
||||||
|
} else if (code != null && codeVerifier != null && redirectUrl != null) {
|
||||||
|
return new SsoTokenRequest(code, codeVerifier, redirectUrl, effectiveProvider, effectiveToken,
|
||||||
|
effectiveRemember, captchaToken, deviceRequest);
|
||||||
|
} else if (clientId != null && clientSecret != null) {
|
||||||
|
return new ApiTokenRequest(clientId, clientSecret, effectiveProvider, effectiveToken, effectiveRemember,
|
||||||
|
captchaToken, deviceRequest);
|
||||||
} else {
|
} else {
|
||||||
emailPassword = null;
|
throw new Error('No credentials provided.');
|
||||||
}
|
}
|
||||||
if (code != null && codeVerifier != null && redirectUrl != null) {
|
|
||||||
codeCodeVerifier = [code, codeVerifier, redirectUrl];
|
|
||||||
} else {
|
|
||||||
codeCodeVerifier = null;
|
|
||||||
}
|
|
||||||
if (clientId != null && clientSecret != null) {
|
|
||||||
clientIdClientSecret = [clientId, clientSecret];
|
|
||||||
} else {
|
|
||||||
clientIdClientSecret = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
let request: TokenRequest;
|
|
||||||
if (twoFactorToken != null && twoFactorProvider != null) {
|
|
||||||
request = new TokenRequest(emailPassword, codeCodeVerifier, clientIdClientSecret, twoFactorProvider,
|
|
||||||
twoFactorToken, remember, captchaToken, deviceRequest);
|
|
||||||
} else if (storedTwoFactorToken != null) {
|
|
||||||
request = new TokenRequest(emailPassword, codeCodeVerifier, clientIdClientSecret,
|
|
||||||
TwoFactorProviderType.Remember, storedTwoFactorToken, false, captchaToken, deviceRequest);
|
|
||||||
} else {
|
|
||||||
request = new TokenRequest(emailPassword, codeCodeVerifier, clientIdClientSecret, null,
|
|
||||||
null, false, captchaToken, deviceRequest);
|
|
||||||
}
|
|
||||||
|
|
||||||
return request;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async saveAccountInformation(tokenResponse: IdentityTokenResponse, clientId: string, clientSecret: string) {
|
private async saveAccountInformation(tokenResponse: IdentityTokenResponse, clientId: string, clientSecret: string) {
|
||||||
|
|||||||
@@ -28,6 +28,9 @@ import { IdentityTokenResponse } from 'jslib-common/models/response/identityToke
|
|||||||
import { TwoFactorService } from 'jslib-common/abstractions/twoFactor.service';
|
import { TwoFactorService } from 'jslib-common/abstractions/twoFactor.service';
|
||||||
import { HashPurpose } from 'jslib-common/enums/hashPurpose';
|
import { HashPurpose } from 'jslib-common/enums/hashPurpose';
|
||||||
import { TwoFactorProviderType } from 'jslib-common/enums/twoFactorProviderType';
|
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', () => {
|
describe('Cipher Service', () => {
|
||||||
let cryptoService: SubstituteOf<CryptoService>;
|
let cryptoService: SubstituteOf<CryptoService>;
|
||||||
@@ -178,13 +181,15 @@ describe('Cipher Service', () => {
|
|||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
// Api call:
|
// Api call:
|
||||||
apiService.received(1).postIdentityToken(Arg.is(actual =>
|
apiService.received(1).postIdentityToken(Arg.is(actual => {
|
||||||
actual.email === email &&
|
const passwordTokenRequest = actual as PasswordTokenRequest;
|
||||||
actual.masterPasswordHash === hashedPassword &&
|
return passwordTokenRequest.email === email &&
|
||||||
actual.device.identifier === deviceId &&
|
passwordTokenRequest.masterPasswordHash === hashedPassword &&
|
||||||
actual.provider == null &&
|
actual.device.identifier === deviceId &&
|
||||||
actual.token == null &&
|
actual.provider == null &&
|
||||||
actual.captchaResponse == null));
|
actual.token == null &&
|
||||||
|
actual.captchaResponse == null
|
||||||
|
}));
|
||||||
|
|
||||||
// Sets local environment:
|
// Sets local environment:
|
||||||
commonSuccessAssertions();
|
commonSuccessAssertions();
|
||||||
@@ -302,14 +307,16 @@ describe('Cipher Service', () => {
|
|||||||
|
|
||||||
await authService.logInTwoFactor(twoFactorProviderType, twoFactorToken, twoFactorRemember);
|
await authService.logInTwoFactor(twoFactorProviderType, twoFactorToken, twoFactorRemember);
|
||||||
|
|
||||||
apiService.received(1).postIdentityToken(Arg.is(actual =>
|
apiService.received(1).postIdentityToken(Arg.is(actual => {
|
||||||
actual.email === email &&
|
const passwordTokenRequest = actual as PasswordTokenRequest;
|
||||||
actual.masterPasswordHash === hashedPassword &&
|
return passwordTokenRequest.email === email &&
|
||||||
actual.device.identifier === deviceId &&
|
passwordTokenRequest.masterPasswordHash === hashedPassword &&
|
||||||
actual.provider === twoFactorProviderType &&
|
actual.device.identifier === deviceId &&
|
||||||
actual.token === twoFactorToken &&
|
actual.provider === twoFactorProviderType &&
|
||||||
actual.remember === twoFactorRemember &&
|
actual.token === twoFactorToken &&
|
||||||
actual.captchaResponse == null));
|
actual.remember === twoFactorRemember &&
|
||||||
|
actual.captchaResponse == null
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
// SSO
|
// SSO
|
||||||
@@ -325,14 +332,16 @@ describe('Cipher Service', () => {
|
|||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
// Api call:
|
// Api call:
|
||||||
apiService.received(1).postIdentityToken(Arg.is(actual =>
|
apiService.received(1).postIdentityToken(Arg.is(actual => {
|
||||||
actual.code === ssoCode &&
|
const ssoTokenRequest = actual as SsoTokenRequest;
|
||||||
actual.codeVerifier === ssoCodeVerifier &&
|
return ssoTokenRequest.code === ssoCode &&
|
||||||
actual.redirectUri === ssoRedirectUrl &&
|
ssoTokenRequest.codeVerifier === ssoCodeVerifier &&
|
||||||
actual.device.identifier === deviceId &&
|
ssoTokenRequest.redirectUri === ssoRedirectUrl &&
|
||||||
actual.provider == null &&
|
actual.device.identifier === deviceId &&
|
||||||
actual.token == null &&
|
actual.provider == null &&
|
||||||
actual.captchaResponse == null));
|
actual.token == null &&
|
||||||
|
actual.captchaResponse == null
|
||||||
|
}));
|
||||||
|
|
||||||
// Sets local environment:
|
// Sets local environment:
|
||||||
commonSuccessAssertions();
|
commonSuccessAssertions();
|
||||||
@@ -427,13 +436,15 @@ describe('Cipher Service', () => {
|
|||||||
|
|
||||||
const result = await authService.logInApiKey(apiClientId, apiClientSecret);
|
const result = await authService.logInApiKey(apiClientId, apiClientSecret);
|
||||||
|
|
||||||
apiService.received(1).postIdentityToken(Arg.is(actual =>
|
apiService.received(1).postIdentityToken(Arg.is(actual => {
|
||||||
actual.clientId === apiClientId &&
|
const apiTokenRequest = actual as ApiTokenRequest;
|
||||||
actual.clientSecret === apiClientSecret &&
|
return apiTokenRequest.clientId === apiClientId &&
|
||||||
actual.device.identifier === deviceId &&
|
apiTokenRequest.clientSecret === apiClientSecret &&
|
||||||
actual.provider == null &&
|
actual.device.identifier === deviceId &&
|
||||||
actual.token == null &&
|
actual.provider == null &&
|
||||||
actual.captchaResponse == null));
|
actual.token == null &&
|
||||||
|
actual.captchaResponse == null
|
||||||
|
}));
|
||||||
|
|
||||||
// Sets local environment:
|
// Sets local environment:
|
||||||
stateService.received(1).addAccount({
|
stateService.received(1).addAccount({
|
||||||
|
|||||||
Reference in New Issue
Block a user