mirror of
https://github.com/bitwarden/browser.git
synced 2025-02-20 02:01:47 +01:00
Add support for crypto agent (#520)
This commit is contained in:
parent
bc55557052
commit
71f8ef601f
@ -140,7 +140,7 @@ export class SsoComponent {
|
|||||||
private async logIn(code: string, codeVerifier: string, orgIdFromState: string) {
|
private async logIn(code: string, codeVerifier: string, orgIdFromState: string) {
|
||||||
this.loggingIn = true;
|
this.loggingIn = true;
|
||||||
try {
|
try {
|
||||||
this.formPromise = this.authService.logInSso(code, codeVerifier, this.redirectUri);
|
this.formPromise = this.authService.logInSso(code, codeVerifier, this.redirectUri, orgIdFromState);
|
||||||
const response = await this.formPromise;
|
const response = await this.formPromise;
|
||||||
if (response.twoFactor) {
|
if (response.twoFactor) {
|
||||||
if (this.onSuccessfulLoginTwoFactorNavigate != null) {
|
if (this.onSuccessfulLoginTwoFactorNavigate != null) {
|
||||||
@ -183,6 +183,9 @@ export class SsoComponent {
|
|||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.logService.error(e);
|
this.logService.error(e);
|
||||||
|
if (e.message === 'Unable to reach crypto agent') {
|
||||||
|
this.platformUtilsService.showToast('error', null, this.i18nService.t('ssoCryptoAgentUnavailable'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.loggingIn = false;
|
this.loggingIn = false;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { PolicyType } from '../enums/policyType';
|
import { PolicyType } from '../enums/policyType';
|
||||||
|
import { SetCryptoAgentKeyRequest } from '../models/request/account/setCryptoAgentKeyRequest';
|
||||||
|
|
||||||
import { AttachmentRequest } from '../models/request/attachmentRequest';
|
import { AttachmentRequest } from '../models/request/attachmentRequest';
|
||||||
|
|
||||||
@ -12,6 +13,7 @@ import { CipherCreateRequest } from '../models/request/cipherCreateRequest';
|
|||||||
import { CipherRequest } from '../models/request/cipherRequest';
|
import { CipherRequest } from '../models/request/cipherRequest';
|
||||||
import { CipherShareRequest } from '../models/request/cipherShareRequest';
|
import { CipherShareRequest } from '../models/request/cipherShareRequest';
|
||||||
import { CollectionRequest } from '../models/request/collectionRequest';
|
import { CollectionRequest } from '../models/request/collectionRequest';
|
||||||
|
import { CryptoAgentUserKeyRequest } from '../models/request/cryptoAgentUserKeyRequest';
|
||||||
import { DeleteRecoverRequest } from '../models/request/deleteRecoverRequest';
|
import { DeleteRecoverRequest } from '../models/request/deleteRecoverRequest';
|
||||||
import { EmailRequest } from '../models/request/emailRequest';
|
import { EmailRequest } from '../models/request/emailRequest';
|
||||||
import { EmailTokenRequest } from '../models/request/emailTokenRequest';
|
import { EmailTokenRequest } from '../models/request/emailTokenRequest';
|
||||||
@ -98,6 +100,7 @@ import {
|
|||||||
CollectionGroupDetailsResponse,
|
CollectionGroupDetailsResponse,
|
||||||
CollectionResponse,
|
CollectionResponse,
|
||||||
} from '../models/response/collectionResponse';
|
} from '../models/response/collectionResponse';
|
||||||
|
import { CryptoAgentUserKeyResponse } from '../models/response/cryptoAgentUserKeyResponse';
|
||||||
import { DomainsResponse } from '../models/response/domainsResponse';
|
import { DomainsResponse } from '../models/response/domainsResponse';
|
||||||
import {
|
import {
|
||||||
EmergencyAccessGranteeDetailsResponse,
|
EmergencyAccessGranteeDetailsResponse,
|
||||||
@ -172,6 +175,7 @@ export abstract class ApiService {
|
|||||||
postEmail: (request: EmailRequest) => Promise<any>;
|
postEmail: (request: EmailRequest) => Promise<any>;
|
||||||
postPassword: (request: PasswordRequest) => Promise<any>;
|
postPassword: (request: PasswordRequest) => Promise<any>;
|
||||||
setPassword: (request: SetPasswordRequest) => Promise<any>;
|
setPassword: (request: SetPasswordRequest) => Promise<any>;
|
||||||
|
postSetCryptoAgentKey: (request: SetCryptoAgentKeyRequest) => Promise<any>;
|
||||||
postSecurityStamp: (request: PasswordVerificationRequest) => Promise<any>;
|
postSecurityStamp: (request: PasswordVerificationRequest) => Promise<any>;
|
||||||
deleteAccount: (request: PasswordVerificationRequest) => Promise<any>;
|
deleteAccount: (request: PasswordVerificationRequest) => Promise<any>;
|
||||||
getAccountRevisionDate: () => Promise<number>;
|
getAccountRevisionDate: () => Promise<number>;
|
||||||
@ -444,4 +448,7 @@ export abstract class ApiService {
|
|||||||
nativeFetch: (request: Request) => Promise<Response>;
|
nativeFetch: (request: Request) => Promise<Response>;
|
||||||
|
|
||||||
preValidateSso: (identifier: string) => Promise<boolean>;
|
preValidateSso: (identifier: string) => Promise<boolean>;
|
||||||
|
|
||||||
|
getUserKeyFromCryptoAgent: (cryptoAgentUrl: string) => Promise<CryptoAgentUserKeyResponse>;
|
||||||
|
postUserKeyToCryptoAgent: (cryptoAgentUrl: string, request: CryptoAgentUserKeyRequest) => Promise<void>;
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ export abstract class AuthService {
|
|||||||
selectedTwoFactorProviderType: TwoFactorProviderType;
|
selectedTwoFactorProviderType: TwoFactorProviderType;
|
||||||
|
|
||||||
logIn: (email: string, masterPassword: string, captchaToken?: string) => Promise<AuthResult>;
|
logIn: (email: string, masterPassword: string, captchaToken?: string) => Promise<AuthResult>;
|
||||||
logInSso: (code: string, codeVerifier: string, redirectUrl: string) => Promise<AuthResult>;
|
logInSso: (code: string, codeVerifier: string, redirectUrl: string, orgId: string) => Promise<AuthResult>;
|
||||||
logInApiKey: (clientId: string, clientSecret: string) => Promise<AuthResult>;
|
logInApiKey: (clientId: string, clientSecret: string) => Promise<AuthResult>;
|
||||||
logInTwoFactor: (twoFactorProvider: TwoFactorProviderType, twoFactorToken: string,
|
logInTwoFactor: (twoFactorProvider: TwoFactorProviderType, twoFactorToken: string,
|
||||||
remember?: boolean) => Promise<AuthResult>;
|
remember?: boolean) => Promise<AuthResult>;
|
||||||
|
@ -37,6 +37,9 @@ enum Saml2SigningBehavior {
|
|||||||
export class SsoConfigApi extends BaseResponse {
|
export class SsoConfigApi extends BaseResponse {
|
||||||
configType: SsoType;
|
configType: SsoType;
|
||||||
|
|
||||||
|
useCryptoAgent: boolean;
|
||||||
|
cryptoAgentUrl: string;
|
||||||
|
|
||||||
// OpenId
|
// OpenId
|
||||||
authority: string;
|
authority: string;
|
||||||
clientId: string;
|
clientId: string;
|
||||||
@ -78,6 +81,9 @@ export class SsoConfigApi extends BaseResponse {
|
|||||||
|
|
||||||
this.configType = this.getResponseProperty('ConfigType');
|
this.configType = this.getResponseProperty('ConfigType');
|
||||||
|
|
||||||
|
this.useCryptoAgent = this.getResponseProperty('UseCryptoAgent');
|
||||||
|
this.cryptoAgentUrl = this.getResponseProperty('CryptoAgentUrl');
|
||||||
|
|
||||||
this.authority = this.getResponseProperty('Authority');
|
this.authority = this.getResponseProperty('Authority');
|
||||||
this.clientId = this.getResponseProperty('ClientId');
|
this.clientId = this.getResponseProperty('ClientId');
|
||||||
this.clientSecret = this.getResponseProperty('ClientSecret');
|
this.clientSecret = this.getResponseProperty('ClientSecret');
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
import { KeysRequest } from '../keysRequest';
|
||||||
|
|
||||||
|
import { KdfType } from '../../../enums/kdfType';
|
||||||
|
|
||||||
|
export class SetCryptoAgentKeyRequest {
|
||||||
|
key: string;
|
||||||
|
keys: KeysRequest;
|
||||||
|
kdf: KdfType;
|
||||||
|
kdfIterations: number;
|
||||||
|
orgIdentifier: string;
|
||||||
|
|
||||||
|
constructor(key: string, kdf: KdfType, kdfIterations: number, orgIdentifier: string, keys: KeysRequest) {
|
||||||
|
this.key = key;
|
||||||
|
this.kdf = kdf;
|
||||||
|
this.kdfIterations = kdfIterations;
|
||||||
|
this.orgIdentifier = orgIdentifier;
|
||||||
|
this.keys = keys;
|
||||||
|
}
|
||||||
|
}
|
7
common/src/models/request/cryptoAgentUserKeyRequest.ts
Normal file
7
common/src/models/request/cryptoAgentUserKeyRequest.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
export class CryptoAgentUserKeyRequest {
|
||||||
|
key: string;
|
||||||
|
|
||||||
|
constructor(key: string) {
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
}
|
10
common/src/models/response/cryptoAgentUserKeyResponse.ts
Normal file
10
common/src/models/response/cryptoAgentUserKeyResponse.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { BaseResponse } from './baseResponse';
|
||||||
|
|
||||||
|
export class CryptoAgentUserKeyResponse extends BaseResponse {
|
||||||
|
key: string;
|
||||||
|
|
||||||
|
constructor(response: any) {
|
||||||
|
super(response);
|
||||||
|
this.key = this.getResponseProperty('Key');
|
||||||
|
}
|
||||||
|
}
|
@ -15,6 +15,7 @@ export class IdentityTokenResponse extends BaseResponse {
|
|||||||
kdf: KdfType;
|
kdf: KdfType;
|
||||||
kdfIterations: number;
|
kdfIterations: number;
|
||||||
forcePasswordReset: boolean;
|
forcePasswordReset: boolean;
|
||||||
|
cryptoAgentUrl: string;
|
||||||
|
|
||||||
constructor(response: any) {
|
constructor(response: any) {
|
||||||
super(response);
|
super(response);
|
||||||
@ -30,5 +31,6 @@ export class IdentityTokenResponse extends BaseResponse {
|
|||||||
this.kdf = this.getResponseProperty('Kdf');
|
this.kdf = this.getResponseProperty('Kdf');
|
||||||
this.kdfIterations = this.getResponseProperty('KdfIterations');
|
this.kdfIterations = this.getResponseProperty('KdfIterations');
|
||||||
this.forcePasswordReset = this.getResponseProperty('ForcePasswordReset');
|
this.forcePasswordReset = this.getResponseProperty('ForcePasswordReset');
|
||||||
|
this.cryptoAgentUrl = this.getResponseProperty('CryptoAgentUrl');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -166,6 +166,9 @@ import { ChallengeResponse } from '../models/response/twoFactorWebAuthnResponse'
|
|||||||
import { TwoFactorYubiKeyResponse } from '../models/response/twoFactorYubiKeyResponse';
|
import { TwoFactorYubiKeyResponse } from '../models/response/twoFactorYubiKeyResponse';
|
||||||
import { UserKeyResponse } from '../models/response/userKeyResponse';
|
import { UserKeyResponse } from '../models/response/userKeyResponse';
|
||||||
|
|
||||||
|
import { SetCryptoAgentKeyRequest } from '../models/request/account/setCryptoAgentKeyRequest';
|
||||||
|
import { CryptoAgentUserKeyRequest } from '../models/request/cryptoAgentUserKeyRequest';
|
||||||
|
import { CryptoAgentUserKeyResponse } from '../models/response/cryptoAgentUserKeyResponse';
|
||||||
import { SendAccessView } from '../models/view/sendAccessView';
|
import { SendAccessView } from '../models/view/sendAccessView';
|
||||||
|
|
||||||
export class ApiService implements ApiServiceAbstraction {
|
export class ApiService implements ApiServiceAbstraction {
|
||||||
@ -289,6 +292,10 @@ export class ApiService implements ApiServiceAbstraction {
|
|||||||
return this.send('POST', '/accounts/set-password', request, true, false);
|
return this.send('POST', '/accounts/set-password', request, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
postSetCryptoAgentKey(request: SetCryptoAgentKeyRequest): Promise<any> {
|
||||||
|
return this.send('POST', '/accounts/set-crypto-agent-key', request, true, false);
|
||||||
|
}
|
||||||
|
|
||||||
postSecurityStamp(request: PasswordVerificationRequest): Promise<any> {
|
postSecurityStamp(request: PasswordVerificationRequest): Promise<any> {
|
||||||
return this.send('POST', '/accounts/security-stamp', request, true, false);
|
return this.send('POST', '/accounts/security-stamp', request, true, false);
|
||||||
}
|
}
|
||||||
@ -1429,6 +1436,49 @@ export class ApiService implements ApiServiceAbstraction {
|
|||||||
return r as string;
|
return r as string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Crypto Agent
|
||||||
|
|
||||||
|
async getUserKeyFromCryptoAgent(cryptoAgentUrl: string): Promise<CryptoAgentUserKeyResponse> {
|
||||||
|
const authHeader = await this.getActiveBearerToken();
|
||||||
|
|
||||||
|
const response = await this.fetch(new Request(cryptoAgentUrl + '/user-keys', {
|
||||||
|
cache: 'no-store',
|
||||||
|
method: 'GET',
|
||||||
|
headers: new Headers({
|
||||||
|
'Accept': 'application/json',
|
||||||
|
'Authorization': 'Bearer ' + authHeader,
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (response.status !== 200) {
|
||||||
|
const error = await this.handleError(response, false, true);
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CryptoAgentUserKeyResponse(await response.json());
|
||||||
|
}
|
||||||
|
|
||||||
|
async postUserKeyToCryptoAgent(cryptoAgentUrl: string, request: CryptoAgentUserKeyRequest): Promise<void> {
|
||||||
|
const authHeader = await this.getActiveBearerToken();
|
||||||
|
|
||||||
|
const response = await this.fetch(new Request(cryptoAgentUrl + '/user-keys', {
|
||||||
|
cache: 'no-store',
|
||||||
|
method: 'POST',
|
||||||
|
headers: new Headers({
|
||||||
|
'Accept': 'application/json',
|
||||||
|
'Authorization': 'Bearer ' + authHeader,
|
||||||
|
'Content-Type': 'application/json; charset=utf-8',
|
||||||
|
}),
|
||||||
|
body: JSON.stringify(request),
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (response.status !== 200) {
|
||||||
|
const error = await this.handleError(response, false, true);
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Helpers
|
// Helpers
|
||||||
|
|
||||||
async getActiveBearerToken(): Promise<string> {
|
async getActiveBearerToken(): Promise<string> {
|
||||||
|
@ -5,6 +5,8 @@ import { TwoFactorProviderType } from '../enums/twoFactorProviderType';
|
|||||||
import { AuthResult } from '../models/domain/authResult';
|
import { AuthResult } from '../models/domain/authResult';
|
||||||
import { SymmetricCryptoKey } from '../models/domain/symmetricCryptoKey';
|
import { SymmetricCryptoKey } from '../models/domain/symmetricCryptoKey';
|
||||||
|
|
||||||
|
import { SetCryptoAgentKeyRequest } from '../models/request/account/setCryptoAgentKeyRequest';
|
||||||
|
import { CryptoAgentUserKeyRequest } from '../models/request/cryptoAgentUserKeyRequest';
|
||||||
import { DeviceRequest } from '../models/request/deviceRequest';
|
import { DeviceRequest } from '../models/request/deviceRequest';
|
||||||
import { KeysRequest } from '../models/request/keysRequest';
|
import { KeysRequest } from '../models/request/keysRequest';
|
||||||
import { PreloginRequest } from '../models/request/preloginRequest';
|
import { PreloginRequest } from '../models/request/preloginRequest';
|
||||||
@ -17,6 +19,7 @@ import { ApiService } from '../abstractions/api.service';
|
|||||||
import { AppIdService } from '../abstractions/appId.service';
|
import { AppIdService } from '../abstractions/appId.service';
|
||||||
import { AuthService as AuthServiceAbstraction } from '../abstractions/auth.service';
|
import { AuthService as AuthServiceAbstraction } from '../abstractions/auth.service';
|
||||||
import { CryptoService } from '../abstractions/crypto.service';
|
import { CryptoService } from '../abstractions/crypto.service';
|
||||||
|
import { CryptoFunctionService } from '../abstractions/cryptoFunction.service';
|
||||||
import { I18nService } from '../abstractions/i18n.service';
|
import { I18nService } from '../abstractions/i18n.service';
|
||||||
import { LogService } from '../abstractions/log.service';
|
import { LogService } from '../abstractions/log.service';
|
||||||
import { MessagingService } from '../abstractions/messaging.service';
|
import { MessagingService } from '../abstractions/messaging.service';
|
||||||
@ -25,6 +28,8 @@ import { TokenService } from '../abstractions/token.service';
|
|||||||
import { UserService } from '../abstractions/user.service';
|
import { UserService } from '../abstractions/user.service';
|
||||||
import { VaultTimeoutService } from '../abstractions/vaultTimeout.service';
|
import { VaultTimeoutService } from '../abstractions/vaultTimeout.service';
|
||||||
|
|
||||||
|
import { Utils } from '../misc/utils';
|
||||||
|
|
||||||
export const TwoFactorProviders = {
|
export const TwoFactorProviders = {
|
||||||
[TwoFactorProviderType.Authenticator]: {
|
[TwoFactorProviderType.Authenticator]: {
|
||||||
type: TwoFactorProviderType.Authenticator,
|
type: TwoFactorProviderType.Authenticator,
|
||||||
@ -96,7 +101,7 @@ export class AuthService implements AuthServiceAbstraction {
|
|||||||
protected appIdService: AppIdService, private i18nService: I18nService,
|
protected appIdService: AppIdService, private i18nService: I18nService,
|
||||||
protected platformUtilsService: PlatformUtilsService, private messagingService: MessagingService,
|
protected platformUtilsService: PlatformUtilsService, private messagingService: MessagingService,
|
||||||
private vaultTimeoutService: VaultTimeoutService, private logService: LogService,
|
private vaultTimeoutService: VaultTimeoutService, private logService: LogService,
|
||||||
private setCryptoKeys = true) {
|
private cryptoFunctionService: CryptoFunctionService, private setCryptoKeys = true) {
|
||||||
}
|
}
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
@ -128,26 +133,26 @@ export class AuthService implements AuthServiceAbstraction {
|
|||||||
const localHashedPassword = await this.cryptoService.hashPassword(masterPassword, key,
|
const localHashedPassword = await this.cryptoService.hashPassword(masterPassword, key,
|
||||||
HashPurpose.LocalAuthorization);
|
HashPurpose.LocalAuthorization);
|
||||||
return await this.logInHelper(email, hashedPassword, localHashedPassword, null, null, null, null, null,
|
return await this.logInHelper(email, hashedPassword, localHashedPassword, null, null, null, null, null,
|
||||||
key, null, null, null, captchaToken);
|
key, null, null, null, captchaToken, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
async logInSso(code: string, codeVerifier: string, redirectUrl: string): Promise<AuthResult> {
|
async logInSso(code: string, codeVerifier: string, redirectUrl: string, orgId: string): Promise<AuthResult> {
|
||||||
this.selectedTwoFactorProviderType = null;
|
this.selectedTwoFactorProviderType = null;
|
||||||
return await this.logInHelper(null, null, null, code, codeVerifier, redirectUrl, null, null,
|
return await this.logInHelper(null, null, null, code, codeVerifier, redirectUrl, null, null,
|
||||||
null, null, null, null);
|
null, null, null, null, null, orgId);
|
||||||
}
|
}
|
||||||
|
|
||||||
async logInApiKey(clientId: string, clientSecret: string): Promise<AuthResult> {
|
async logInApiKey(clientId: string, clientSecret: string): Promise<AuthResult> {
|
||||||
this.selectedTwoFactorProviderType = null;
|
this.selectedTwoFactorProviderType = null;
|
||||||
return await this.logInHelper(null, null, null, null, null, null, clientId, clientSecret,
|
return await this.logInHelper(null, null, null, null, null, null, clientId, clientSecret,
|
||||||
null, null, null, null);
|
null, null, null, null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
async logInTwoFactor(twoFactorProvider: TwoFactorProviderType, twoFactorToken: string,
|
async logInTwoFactor(twoFactorProvider: TwoFactorProviderType, twoFactorToken: string,
|
||||||
remember?: boolean): Promise<AuthResult> {
|
remember?: boolean): Promise<AuthResult> {
|
||||||
return await this.logInHelper(this.email, this.masterPasswordHash, this.localMasterPasswordHash, this.code,
|
return await this.logInHelper(this.email, this.masterPasswordHash, this.localMasterPasswordHash, this.code,
|
||||||
this.codeVerifier, this.ssoRedirectUrl, this.clientId, this.clientSecret, this.key, twoFactorProvider,
|
this.codeVerifier, this.ssoRedirectUrl, this.clientId, this.clientSecret, this.key, twoFactorProvider,
|
||||||
twoFactorToken, remember, this.captchaToken);
|
twoFactorToken, remember, this.captchaToken, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
async logInComplete(email: string, masterPassword: string, twoFactorProvider: TwoFactorProviderType,
|
async logInComplete(email: string, masterPassword: string, twoFactorProvider: TwoFactorProviderType,
|
||||||
@ -158,21 +163,21 @@ export class AuthService implements AuthServiceAbstraction {
|
|||||||
const localHashedPassword = await this.cryptoService.hashPassword(masterPassword, key,
|
const localHashedPassword = await this.cryptoService.hashPassword(masterPassword, key,
|
||||||
HashPurpose.LocalAuthorization);
|
HashPurpose.LocalAuthorization);
|
||||||
return await this.logInHelper(email, hashedPassword, localHashedPassword, null, null, null, null, null, key,
|
return await this.logInHelper(email, hashedPassword, localHashedPassword, null, null, null, null, null, key,
|
||||||
twoFactorProvider, twoFactorToken, remember, captchaToken);
|
twoFactorProvider, twoFactorToken, remember, captchaToken, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
async logInSsoComplete(code: string, codeVerifier: string, redirectUrl: string,
|
async logInSsoComplete(code: string, codeVerifier: string, redirectUrl: string,
|
||||||
twoFactorProvider: TwoFactorProviderType, twoFactorToken: string, remember?: boolean): Promise<AuthResult> {
|
twoFactorProvider: TwoFactorProviderType, twoFactorToken: string, remember?: boolean): Promise<AuthResult> {
|
||||||
this.selectedTwoFactorProviderType = null;
|
this.selectedTwoFactorProviderType = null;
|
||||||
return await this.logInHelper(null, null, null, code, codeVerifier, redirectUrl, null,
|
return await this.logInHelper(null, null, null, code, codeVerifier, redirectUrl, null,
|
||||||
null, null, twoFactorProvider, twoFactorToken, remember);
|
null, null, twoFactorProvider, twoFactorToken, remember, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
async logInApiKeyComplete(clientId: string, clientSecret: string, twoFactorProvider: TwoFactorProviderType,
|
async logInApiKeyComplete(clientId: string, clientSecret: string, twoFactorProvider: TwoFactorProviderType,
|
||||||
twoFactorToken: string, remember?: boolean): Promise<AuthResult> {
|
twoFactorToken: string, remember?: boolean): Promise<AuthResult> {
|
||||||
this.selectedTwoFactorProviderType = null;
|
this.selectedTwoFactorProviderType = null;
|
||||||
return await this.logInHelper(null, null, null, null, null, null, clientId, clientSecret, null,
|
return await this.logInHelper(null, null, null, null, null, null, clientId, clientSecret, null,
|
||||||
twoFactorProvider, twoFactorToken, remember);
|
twoFactorProvider, twoFactorToken, remember, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
logOut(callback: Function) {
|
logOut(callback: Function) {
|
||||||
@ -273,7 +278,8 @@ export class AuthService implements AuthServiceAbstraction {
|
|||||||
|
|
||||||
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): Promise<AuthResult> {
|
twoFactorProvider?: TwoFactorProviderType, twoFactorToken?: string, remember?: boolean, captchaToken?: string,
|
||||||
|
orgId?: string): Promise<AuthResult> {
|
||||||
const storedTwoFactorToken = await this.tokenService.getTwoFactorToken(email);
|
const storedTwoFactorToken = await this.tokenService.getTwoFactorToken(email);
|
||||||
const appId = await this.appIdService.getAppId();
|
const appId = await this.appIdService.getAppId();
|
||||||
const deviceRequest = new DeviceRequest(appId, this.platformUtilsService);
|
const deviceRequest = new DeviceRequest(appId, this.platformUtilsService);
|
||||||
@ -358,6 +364,19 @@ export class AuthService implements AuthServiceAbstraction {
|
|||||||
|
|
||||||
// Skip this step during SSO new user flow. No key is returned from server.
|
// Skip this step during SSO new user flow. No key is returned from server.
|
||||||
if (code == null || tokenResponse.key != null) {
|
if (code == null || tokenResponse.key != null) {
|
||||||
|
|
||||||
|
if (tokenResponse.cryptoAgentUrl != null) {
|
||||||
|
try {
|
||||||
|
const userKeyResponse = await this.apiService.getUserKeyFromCryptoAgent(tokenResponse.cryptoAgentUrl);
|
||||||
|
const keyArr = Utils.fromB64ToArray(userKeyResponse.key);
|
||||||
|
const k = new SymmetricCryptoKey(keyArr);
|
||||||
|
await this.cryptoService.setKey(k);
|
||||||
|
} catch (e) {
|
||||||
|
this.logService.error(e);
|
||||||
|
throw new Error('Unable to reach crypto agent');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
await this.cryptoService.setEncKey(tokenResponse.key);
|
await this.cryptoService.setEncKey(tokenResponse.key);
|
||||||
|
|
||||||
// User doesn't have a key pair yet (old account), let's generate one for them
|
// User doesn't have a key pair yet (old account), let's generate one for them
|
||||||
@ -367,12 +386,34 @@ export class AuthService implements AuthServiceAbstraction {
|
|||||||
await this.apiService.postAccountKeys(new KeysRequest(keyPair[0], keyPair[1].encryptedString));
|
await this.apiService.postAccountKeys(new KeysRequest(keyPair[0], keyPair[1].encryptedString));
|
||||||
tokenResponse.privateKey = keyPair[1].encryptedString;
|
tokenResponse.privateKey = keyPair[1].encryptedString;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// tslint:disable-next-line
|
|
||||||
this.logService.error(e);
|
this.logService.error(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.cryptoService.setEncPrivateKey(tokenResponse.privateKey);
|
await this.cryptoService.setEncPrivateKey(tokenResponse.privateKey);
|
||||||
|
} else if (tokenResponse.cryptoAgentUrl != null) {
|
||||||
|
const password = await this.cryptoFunctionService.randomBytes(64);
|
||||||
|
|
||||||
|
const k = await this.cryptoService.makeKey(Utils.fromBufferToB64(password), this.tokenService.getEmail(), tokenResponse.kdf, tokenResponse.kdfIterations);
|
||||||
|
const cryptoAgentRequest = new CryptoAgentUserKeyRequest(k.encKeyB64);
|
||||||
|
await this.cryptoService.setKey(k);
|
||||||
|
|
||||||
|
const encKey = await this.cryptoService.makeEncKey(k);
|
||||||
|
await this.cryptoService.setEncKey(encKey[1].encryptedString);
|
||||||
|
|
||||||
|
const [pubKey, privKey] = await this.cryptoService.makeKeyPair();
|
||||||
|
|
||||||
|
try {
|
||||||
|
await this.apiService.postUserKeyToCryptoAgent(tokenResponse.cryptoAgentUrl, cryptoAgentRequest);
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error('Unable to reach crypto agent');
|
||||||
|
}
|
||||||
|
|
||||||
|
const keys = new KeysRequest(pubKey, privKey.encryptedString);
|
||||||
|
const setPasswordRequest = new SetCryptoAgentKeyRequest(
|
||||||
|
encKey[1].encryptedString, tokenResponse.kdf, tokenResponse.kdfIterations, orgId, keys
|
||||||
|
);
|
||||||
|
await this.apiService.postSetCryptoAgentKey(setPasswordRequest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user