update the login flow
This commit is contained in:
parent
8acc3d085d
commit
cd5dccaa56
|
@ -80,7 +80,7 @@ export default function Login(props: LoginProps) {
|
|||
token,
|
||||
id,
|
||||
twoFactorSessionID,
|
||||
} = await loginViaSRP(srpAttributes.srpSalt, email, passphrase);
|
||||
} = await loginViaSRP(srpAttributes, passphrase);
|
||||
if (twoFactorSessionID) {
|
||||
setData(LS_KEYS.USER, {
|
||||
email,
|
||||
|
|
|
@ -8,6 +8,7 @@ import SubmitButton from 'components/SubmitButton';
|
|||
import {
|
||||
generateAndSaveIntermediateKeyAttributes,
|
||||
generateKeyAttributes,
|
||||
generateLoginSubKey,
|
||||
generateSRPSetupAttributes,
|
||||
isWeakPassword,
|
||||
saveKeyInSessionStore,
|
||||
|
@ -81,12 +82,15 @@ export default function SignUp(props: SignUpProps) {
|
|||
const { keyAttributes, masterKey } =
|
||||
await generateKeyAttributes(passphrase);
|
||||
|
||||
const srpSetupAttributes = await generateSRPSetupAttributes(
|
||||
const loginSubKey = await generateLoginSubKey(
|
||||
passphrase,
|
||||
keyAttributes.kekSalt,
|
||||
keyAttributes.memLimit,
|
||||
keyAttributes.opsLimit
|
||||
);
|
||||
const srpSetupAttributes = await generateSRPSetupAttributes(
|
||||
loginSubKey
|
||||
);
|
||||
|
||||
setData(LS_KEYS.ORIGINAL_KEY_ATTRIBUTES, keyAttributes);
|
||||
setData(LS_KEYS.SRP_SETUP_ATTRIBUTES, srpSetupAttributes);
|
||||
|
|
|
@ -9,6 +9,7 @@ import { SESSION_KEYS, getKey } from 'utils/storage/sessionStorage';
|
|||
import {
|
||||
decryptAndStoreToken,
|
||||
generateAndSaveIntermediateKeyAttributes,
|
||||
generateLoginSubKey,
|
||||
generateSRPSetupAttributes,
|
||||
saveKeyInSessionStore,
|
||||
} from 'utils/crypto';
|
||||
|
@ -87,12 +88,15 @@ export default function Credentials() {
|
|||
const userSRPSetupPending = getUserSRPSetupPending();
|
||||
addLocalLog(() => `userSRPSetupPending ${userSRPSetupPending}`);
|
||||
if (userSRPSetupPending) {
|
||||
const srpSetupAttributes = await generateSRPSetupAttributes(
|
||||
const loginSubKey = await generateLoginSubKey(
|
||||
passphrase,
|
||||
keyAttributes.kekSalt,
|
||||
keyAttributes.memLimit,
|
||||
keyAttributes.opsLimit
|
||||
);
|
||||
const srpSetupAttributes = await generateSRPSetupAttributes(
|
||||
loginSubKey
|
||||
);
|
||||
// we don't have access to kek here, so we will have to re-derive it from the passphrase
|
||||
await configureSRP(srpSetupAttributes);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,11 @@ import { clearData, getData, LS_KEYS } from 'utils/storage/localStorage';
|
|||
import localForage from 'utils/storage/localForage';
|
||||
import { getToken } from 'utils/common/key';
|
||||
import HTTPService from './HTTPService';
|
||||
import { generateSRPClient, getRecoveryKey } from 'utils/crypto';
|
||||
import {
|
||||
generateLoginSubKey,
|
||||
generateSRPClient,
|
||||
getRecoveryKey,
|
||||
} from 'utils/crypto';
|
||||
import { logError } from 'utils/sentry';
|
||||
import { eventBus, Events } from './events';
|
||||
import {
|
||||
|
@ -19,15 +23,15 @@ import {
|
|||
UserDetails,
|
||||
DeleteChallengeResponse,
|
||||
GetRemoteStoreValueResponse,
|
||||
GetSRPAttributesResponse,
|
||||
SetupSRPRequest,
|
||||
ExchangeSRPABResponse,
|
||||
CreateSRPSessionResponse,
|
||||
EmailVerificationResponse,
|
||||
GetFeatureFlagResponse,
|
||||
SetupSRPResponse,
|
||||
CompleteSRPSetupRequest,
|
||||
CompleteSRPSetupResponse,
|
||||
SRPSetupAttributes,
|
||||
SRPAttributes,
|
||||
} from 'types/user';
|
||||
import { ServerErrorCodes } from 'utils/error';
|
||||
import isElectron from 'is-electron';
|
||||
|
@ -471,7 +475,7 @@ export const getSRPAttributes = async (email: string) => {
|
|||
const resp = await HTTPService.get(`${ENDPOINT}/users/srp/attributes`, {
|
||||
email,
|
||||
});
|
||||
return (resp.data as GetSRPAttributesResponse)?.srpAttributes;
|
||||
return resp.data as SRPAttributes;
|
||||
} catch (e) {
|
||||
if (e.status?.toString() === ServerErrorCodes.NOT_FOUND) {
|
||||
return null;
|
||||
|
@ -594,22 +598,35 @@ export const completeSRPSetup = async (
|
|||
};
|
||||
|
||||
export const loginViaSRP = async (
|
||||
srpSalt: string,
|
||||
email: string,
|
||||
password: string
|
||||
srpAttributes: SRPAttributes,
|
||||
passphrase: string
|
||||
) => {
|
||||
try {
|
||||
const srpClient = await generateSRPClient(srpSalt, email, password);
|
||||
const loginSubKey = await generateLoginSubKey(
|
||||
passphrase,
|
||||
srpAttributes.kekSalt,
|
||||
srpAttributes.memLimit,
|
||||
srpAttributes.opsLimit
|
||||
);
|
||||
const srpClient = await generateSRPClient(
|
||||
srpAttributes.srpSalt,
|
||||
srpAttributes.srpUserID,
|
||||
loginSubKey
|
||||
);
|
||||
const srpA = srpClient.computeA();
|
||||
const { srpB } = await exchangeAB(email, convertBufferToBase64(srpA));
|
||||
const { srpB, sessionID } = await createSRPSession(
|
||||
srpAttributes.srpUserID,
|
||||
convertBufferToBase64(srpA)
|
||||
);
|
||||
srpClient.setB(convertBase64ToBuffer(srpB));
|
||||
|
||||
const k = srpClient.computeK();
|
||||
addLocalLog(() => `srp k: ${convertBufferToBase64(k)}`);
|
||||
const m1 = srpClient.computeM1();
|
||||
addLocalLog(() => `srp m1: ${convertBufferToBase64(m1)}`);
|
||||
const verificationResponse = await verifySRP(
|
||||
email,
|
||||
const verificationResponse = await verifySRPSession(
|
||||
sessionID,
|
||||
srpAttributes.srpUserID,
|
||||
convertBufferToBase64(m1)
|
||||
);
|
||||
addLocalLog(() => `srp verify successful, ${verificationResponse}`);
|
||||
|
@ -620,17 +637,16 @@ export const loginViaSRP = async (
|
|||
}
|
||||
};
|
||||
|
||||
export const exchangeAB = async (email: string, srpA: string) => {
|
||||
export const createSRPSession = async (srpUserID: string, srpA: string) => {
|
||||
try {
|
||||
const resp = await HTTPService.post(
|
||||
`${ENDPOINT}/users/srp/exchange-ab`,
|
||||
{
|
||||
email,
|
||||
srpUserID,
|
||||
srpA,
|
||||
},
|
||||
null
|
||||
}
|
||||
);
|
||||
return resp.data as ExchangeSRPABResponse;
|
||||
return resp.data as CreateSRPSessionResponse;
|
||||
} catch (e) {
|
||||
logError(e, 'exchangeAB failed');
|
||||
throw e;
|
||||
|
@ -657,12 +673,17 @@ export const updateMapEnabledStatus = async (newStatus: boolean) => {
|
|||
}
|
||||
};
|
||||
|
||||
export const verifySRP = async (email: string, srpM1: string) => {
|
||||
export const verifySRPSession = async (
|
||||
sessionID: string,
|
||||
srpUserID: string,
|
||||
srpM1: string
|
||||
) => {
|
||||
try {
|
||||
const resp = await HTTPService.post(
|
||||
`${ENDPOINT}/users/srp/verify`,
|
||||
{
|
||||
email,
|
||||
sessionID,
|
||||
srpUserID,
|
||||
srpM1,
|
||||
},
|
||||
null
|
||||
|
|
|
@ -104,12 +104,11 @@ export interface UpdateRemoteStoreValueRequest {
|
|||
}
|
||||
|
||||
export interface SRPAttributes {
|
||||
srpUserID: string;
|
||||
srpSalt: string;
|
||||
srpGroup: string;
|
||||
}
|
||||
|
||||
export interface GetSRPAttributesResponse {
|
||||
srpAttributes: SRPAttributes;
|
||||
memLimit: number;
|
||||
opsLimit: number;
|
||||
kekSalt: string;
|
||||
}
|
||||
|
||||
export interface SRPSetupAttributes {
|
||||
|
@ -141,7 +140,8 @@ export interface CompleteSRPSetupResponse {
|
|||
srpM2: string;
|
||||
}
|
||||
|
||||
export interface ExchangeSRPABResponse {
|
||||
export interface CreateSRPSessionResponse {
|
||||
sessionID: string;
|
||||
srpB: string;
|
||||
}
|
||||
|
||||
|
|
|
@ -251,12 +251,12 @@ export const isWeakPassword = (password: string) => {
|
|||
return estimatePasswordStrength(password) === PasswordStrength.WEAK;
|
||||
};
|
||||
|
||||
export const generateSRPSetupAttributes = async (
|
||||
export const generateLoginSubKey = async (
|
||||
password: string,
|
||||
kekSalt: string,
|
||||
memLimit: number,
|
||||
opsLimit: number
|
||||
): Promise<SRPSetupAttributes> => {
|
||||
) => {
|
||||
const cryptoWorker = await ComlinkCryptoWorker.getInstance();
|
||||
const kek = await cryptoWorker.deriveKey(
|
||||
password,
|
||||
|
@ -270,6 +270,14 @@ export const generateSRPSetupAttributes = async (
|
|||
LOGIN_SUB_KEY_ID,
|
||||
LOGIN_SUB_KEY_CONTEXT
|
||||
);
|
||||
return loginSubKey;
|
||||
};
|
||||
|
||||
export const generateSRPSetupAttributes = async (
|
||||
loginSubKey: string
|
||||
): Promise<SRPSetupAttributes> => {
|
||||
const cryptoWorker = await ComlinkCryptoWorker.getInstance();
|
||||
|
||||
const srpSalt = await cryptoWorker.generateSaltToDeriveKey();
|
||||
|
||||
const srpUserID = uuidv4();
|
||||
|
|
Loading…
Reference in a new issue