Refactor browser extension MobileLoginUtility flow (#1347)

This commit is contained in:
Leendert de Borst
2025-11-17 23:59:08 +01:00
parent 32fe2156f1
commit a64f7d97e5
3 changed files with 64 additions and 11 deletions

View File

@@ -11,6 +11,7 @@ import { useWebApi } from '@/entrypoints/popup/context/WebApiContext';
import { MobileLoginUtility } from '@/entrypoints/popup/utils/MobileLoginUtility';
import type { VaultResponse } from '@/utils/dist/shared/models/webapi';
import type { MobileLoginResult } from '@/utils/types/messaging/MobileLoginResult';
/**
* Mobile login page - scan QR code with mobile device to login.
@@ -81,19 +82,19 @@ const MobileLogin: React.FC = () => {
// Start polling for response
await mobileLoginRef.current.startPolling(
async (username, token, refreshToken, decryptionKey, salt, encryptionType, encryptionSettings) => {
async (result: MobileLoginResult) => {
showLoading();
try {
// Handle successful authentication
await handleSuccessfulAuth(
username,
token,
refreshToken,
decryptionKey,
result.username,
result.token,
result.refreshToken,
result.decryptionKey,
{
salt,
encryptionType,
encryptionSettings,
salt: result.salt,
encryptionType: result.encryptionType,
encryptionSettings: result.encryptionSettings,
}
);
} catch (err) {

View File

@@ -2,6 +2,7 @@ import { Buffer } from 'buffer';
import type { LoginResponse, MobileLoginInitiateResponse, MobileLoginPollResponse } from '@/utils/dist/shared/models/webapi';
import EncryptionUtility from '@/utils/EncryptionUtility';
import type { MobileLoginResult } from '@/utils/types/messaging/MobileLoginResult';
import type { WebApiService } from '@/utils/WebApiService';
/**
@@ -58,7 +59,7 @@ export class MobileLoginUtility {
* Starts polling the server for mobile login response
*/
public async startPolling(
onSuccess: (username: string, token: string, refreshToken: string, decryptionKey: string, salt: string, encryptionType: string, encryptionSettings: string) => void,
onSuccess: (result: MobileLoginResult) => void,
onError: (error: string) => void
): Promise<void> {
if (!this.requestId || !this.privateKey) {
@@ -134,8 +135,20 @@ export class MobileLoginUtility {
const loginData = await loginResponse.json() as LoginResponse;
// Call success callback with all data
onSuccess(username, token, refreshToken, decryptionKey, loginData.salt, loginData.encryptionType, loginData.encryptionSettings);
// Create result object using the MobileLoginResult type
const result: MobileLoginResult = {
username: username,
token: token,
refreshToken: refreshToken,
decryptionKey: decryptionKey,
salt: loginData.salt,
encryptionType: loginData.encryptionType,
encryptionSettings: loginData.encryptionSettings,
};
// Call success callback with result object
onSuccess(result);
}
} catch (error) {
this.stopPolling();

View File

@@ -0,0 +1,39 @@
/**
* Result of a successful mobile login containing decrypted authentication data.
*/
export type MobileLoginResult = {
/**
* The username.
*/
username: string;
/**
* The JWT access token.
*/
token: string;
/**
* The refresh token.
*/
refreshToken: string;
/**
* The vault decryption key (base64 encoded).
*/
decryptionKey: string;
/**
* The user's salt for key derivation.
*/
salt: string;
/**
* The encryption type (e.g., "Argon2id").
*/
encryptionType: string;
/**
* The encryption settings JSON string.
*/
encryptionSettings: string;
}