1 import { getRandomSrpVerifier, getSrp } from '@proton/srp';
3 import { getInfo, getModulus } from './api/auth';
4 import type { Fido2Data, InfoResponse, ModulusResponse } from './authentication/interface';
5 import type { Api } from './interfaces';
7 export interface AuthCredentials {
12 export type Credentials =
14 | (AuthCredentials & { totp: string })
15 | (AuthCredentials & { fido2: Fido2Data });
17 interface SrpAuthData {
19 ClientEphemeral: string;
20 TwoFactorCode?: string;
24 export interface SrpConfig {
29 * Call the API with the SRP parameters and validate the server proof.
31 interface CallAndValidateArguments {
34 authData: SrpAuthData;
35 expectedServerProof: string;
38 const callAndValidate = async ({
40 config: { data, ...restConfig },
43 }: CallAndValidateArguments) => {
44 const response: Response = await api({
52 const clonedResponse = response.clone();
53 const result = await clonedResponse.json();
55 const { ServerProof } = result;
56 if (ServerProof !== expectedServerProof) {
57 throw new Error('Unexpected server proof');
64 * Perform an API call with SRP auth.
66 interface SrpAuthArguments {
68 credentials: Credentials;
74 export const srpAuth = async ({ api, credentials, config, info, version }: SrpAuthArguments) => {
75 const actualInfo = info || (await api<InfoResponse>(getInfo({ username: credentials.username })));
76 const { expectedServerProof, clientProof, clientEphemeral } = await getSrp(actualInfo, credentials, version);
78 ClientProof: clientProof,
79 ClientEphemeral: clientEphemeral,
80 SRPSession: actualInfo.SRPSession,
81 ...('totp' in credentials ? { TwoFactorCode: credentials.totp } : undefined),
82 ...('fido2' in credentials ? { FIDO2: credentials.fido2 } : undefined),
84 return callAndValidate({
93 * Get initialization parameters for SRP.
95 export const srpGetVerify = async ({ api, credentials }: { api: Api; credentials: Credentials }) => {
96 const data = await api<ModulusResponse>(getModulus());
97 const { version, salt, verifier } = await getRandomSrpVerifier(data, credentials);
99 ModulusID: data.ModulusID,
110 * Perform an SRP call with the random verifier.
112 export const srpVerify = async <T = any>({
115 config: { data, ...restConfig },
118 credentials: Credentials;
121 const authData = await srpGetVerify({ api, credentials });