in packages/fxa-auth-server/lib/routes/account.ts [123:248]
private async createAccount(options: {
authPW: string;
authPWVersion2?: string;
wrapKb?: string;
wrapKbVersion2?: string;
clientSalt?: string;
authSalt: string;
email: string;
emailCode: string;
preVerified: boolean;
request: AuthRequest;
service?: string;
userAgentString: string;
}) {
const {
authPW,
authPWVersion2,
wrapKb,
wrapKbVersion2,
clientSalt,
authSalt,
email,
emailCode,
preVerified,
request,
service,
userAgentString,
} = options;
const { password, verifyHash } = await this.createPassword(
authPW,
authSalt
);
// Handle authPWVersion2 credentials
let password2: any | undefined = undefined;
let verifyHashVersion2 = undefined;
let wrapWrapKb = await random.hex(32);
let wrapWrapKbVersion2 = undefined;
if (authPWVersion2) {
password2 = new this.Password(
authPWVersion2,
authSalt,
this.config.verifierVersion
);
verifyHashVersion2 = await password2?.verifyHash();
wrapWrapKbVersion2 = await password2?.wrap(wrapKbVersion2);
// When version 2 credentials are supplied, the wrapKb will also be supplied.
// This is necessary to the same kB values are produced for both passwords.
wrapWrapKb = await password.wrap(wrapKb);
}
const kA = await random.hex(32);
const locale = request.app.acceptLanguage;
if (!locale) {
// We're seeing a surprising number of accounts created
// without a proper locale. Log details to help debug this.
this.log.info('account.create.emptyLocale', {
email: email,
locale: locale,
agent: userAgentString,
});
}
const account = await this.db.createAccount({
uid: uuid.v4({}, Buffer.alloc(16)).toString('hex'),
createdAt: Date.now(),
email: email,
emailCode: emailCode,
emailVerified: preVerified,
kA,
wrapWrapKb,
wrapWrapKbVersion2,
accountResetToken: null,
passwordForgotToken: null,
authSalt: authSalt,
clientSalt: clientSalt,
verifierVersion: password.version,
verifyHash: verifyHash,
verifyHashVersion2: verifyHashVersion2,
verifierSetAt: Date.now(),
locale,
});
await request.emitMetricsEvent('account.created', {
uid: account.uid,
});
this.glean.registration.accountCreated(request, {
uid: account.uid,
});
const geoData = request.app.geo;
const country = geoData.location && geoData.location.country;
const countryCode = geoData.location && geoData.location.countryCode;
if (account.emailVerified) {
await this.log.notifyAttachedServices('verified', request, {
email: account.email,
locale: account.locale,
service,
uid: account.uid,
userAgent: userAgentString,
country,
countryCode,
});
}
await this.log.notifyAttachedServices('login', request, {
deviceCount: 1,
country,
countryCode,
email: account.email,
service,
uid: account.uid,
userAgent: userAgentString,
});
await this.profileClient.deleteCache(account.uid);
await this.log.notifyAttachedServices('profileDataChange', request, {
uid: account.uid,
});
return { password, password2, account };
}