Merge pull request #17471 from mozilla/FXA-9587

feat(glean): Add backend two_factor_auth_code_complete event
This commit is contained in:
Lauren Zugai 2024-08-26 17:28:57 -05:00 коммит произвёл GitHub
Родитель c11086aa7e 92ecc98952
Коммит ec0529e1c4
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
6 изменённых файлов: 130 добавлений и 10 удалений

Просмотреть файл

@ -282,6 +282,10 @@ export function gleanMetrics(config: ConfigType) {
account: { account: {
deleteComplete: createEventFn('account_delete_complete'), deleteComplete: createEventFn('account_delete_complete'),
}, },
twoFactorAuth: {
codeComplete: createEventFn('two_factor_auth_code_complete'),
},
}; };
} }
@ -307,7 +311,11 @@ export const logErrorWithGlean = ({
glean[ glean[
funnel as keyof Omit< funnel as keyof Omit<
ReturnType<typeof gleanMetrics>, ReturnType<typeof gleanMetrics>,
'resetPassword' | 'oauth' | 'thirdPartyAuth' | 'account' | 'resetPassword'
| 'oauth'
| 'thirdPartyAuth'
| 'account'
| 'twoFactorAuth'
> >
]; ];
funnelFns[event as keyof typeof funnelFns](request, { funnelFns[event as keyof typeof funnelFns](request, {

Просмотреть файл

@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// AUTOGENERATED BY glean_parser v14.3.0. DO NOT EDIT. DO NOT COMMIT. // AUTOGENERATED BY glean_parser v14.5.2. DO NOT EDIT. DO NOT COMMIT.
// This requires `uuid` and `mozlog` libraries to be in the environment // This requires `uuid` and `mozlog` libraries to be in the environment
// @types/uuid and mozlog types definitions are required in devDependencies // @types/uuid and mozlog types definitions are required in devDependencies
@ -142,7 +142,7 @@ class AccountsEventsServerEvent {
}, },
// `Unknown` fields below are required in the Glean schema, however they are not useful in server context // `Unknown` fields below are required in the Glean schema, however they are not useful in server context
client_info: { client_info: {
telemetry_sdk_build: 'glean_parser v14.3.0', telemetry_sdk_build: 'glean_parser v14.5.2',
first_run_date: 'Unknown', first_run_date: 'Unknown',
os: 'Unknown', os: 'Unknown',
os_version: 'Unknown', os_version: 'Unknown',
@ -265,7 +265,7 @@ class EventsServerEventLogger {
}, },
// `Unknown` fields below are required in the Glean schema, however they are not useful in server context // `Unknown` fields below are required in the Glean schema, however they are not useful in server context
client_info: { client_info: {
telemetry_sdk_build: 'glean_parser v14.3.0', telemetry_sdk_build: 'glean_parser v14.5.2',
first_run_date: 'Unknown', first_run_date: 'Unknown',
os: 'Unknown', os: 'Unknown',
os_version: 'Unknown', os_version: 'Unknown',
@ -431,7 +431,7 @@ class EventsServerEventLogger {
category: 'access_token', category: 'access_token',
name: 'created', name: 'created',
extra: { extra: {
reason: reason, reason: String(reason),
}, },
}; };
this.#record({ this.#record({
@ -983,7 +983,7 @@ class EventsServerEventLogger {
category: 'login', category: 'login',
name: 'submit_backend_error', name: 'submit_backend_error',
extra: { extra: {
reason: reason, reason: String(reason),
}, },
}; };
this.#record({ this.#record({
@ -2081,7 +2081,7 @@ class EventsServerEventLogger {
category: 'reg', category: 'reg',
name: 'submit_error', name: 'submit_error',
extra: { extra: {
reason: reason, reason: String(reason),
}, },
}; };
this.#record({ this.#record({
@ -2165,7 +2165,7 @@ class EventsServerEventLogger {
category: 'relying_party', category: 'relying_party',
name: 'form_view', name: 'form_view',
extra: { extra: {
type: type, type: String(type),
}, },
}; };
this.#record({ this.#record({
@ -2249,7 +2249,7 @@ class EventsServerEventLogger {
category: 'third_party_auth', category: 'third_party_auth',
name: 'apple_login_complete', name: 'apple_login_complete',
extra: { extra: {
linking: linking, linking: String(linking),
}, },
}; };
this.#record({ this.#record({
@ -2411,7 +2411,7 @@ class EventsServerEventLogger {
category: 'third_party_auth', category: 'third_party_auth',
name: 'google_login_complete', name: 'google_login_complete',
extra: { extra: {
linking: linking, linking: String(linking),
}, },
}; };
this.#record({ this.#record({
@ -2589,6 +2589,84 @@ class EventsServerEventLogger {
event, event,
}); });
} }
/**
* Record and submit a two_factor_auth_code_complete event:
* User successfully submitted a backup authentication code to complete two factor auth setup.
* Event is logged using internal mozlog logger.
*
* @param {string} user_agent - The user agent.
* @param {string} ip_address - The IP address. Will be used to decode Geo
* information and scrubbed at ingestion.
* @param {string} account_user_id_sha256 - A hex string of a sha256 hash of the account's uid.
* @param {string} relying_party_oauth_client_id - The client id of the relying party.
* @param {string} relying_party_service - The service name of the relying party.
* @param {string} session_device_type - one of 'mobile', 'tablet', or ''.
* @param {string} session_entrypoint - Entrypoint to the service.
* @param {string} session_entrypoint_experiment - Identifier for the experiment the user is part of at the entrypoint.
* @param {string} session_entrypoint_variation - Identifier for the experiment variation the user is part of at the entrypoint.
* @param {string} session_flow_id - an ID generated by FxA for its flow metrics.
* @param {string} utm_campaign - A marketing campaign. For example, if a user signs into FxA from selecting a Mozilla VPN plan on Mozilla VPN's product site, then the value of this metric could be 'vpn-product-page'. The value has a max length of 128 characters with the alphanumeric characters, _ (underscore), forward slash (/), . (period), % (percentage sign), and - (hyphen) in the allowed set of characters. The special value of 'page+referral+-+not+part+of+a+campaign' is also allowed..
* @param {string} utm_content - The content on which the user acted. For example, if the user clicked on the (previously available) "Get started here" link in "Looking for Firefox Sync? Get started here", then the value for this metric would be 'fx-sync-get-started'. The value has a max length of 128 characters with the alphanumeric characters, _ (underscore), forward slash (/), . (period), % (percentage sign), and - (hyphen) in the allowed set of characters..
* @param {string} utm_medium - The "medium" on which the user acted. For example, if the user clicked on a link in an email, then the value of this metric would be 'email'. The value has a max length of 128 characters with the alphanumeric characters, _ (underscore), forward slash (/), . (period), % (percentage sign), and - (hyphen) in the allowed set of characters..
* @param {string} utm_source - The source from where the user started. For example, if the user clicked on a link on the Mozilla accounts web site, this value could be 'fx-website'. The value has a max length of 128 characters with the alphanumeric characters, _ (underscore), forward slash (/), . (period), % (percentage sign), and - (hyphen) in the allowed set of characters..
* @param {string} utm_term - This metric is similar to the `utm.source`; it is used in the Firefox browser. For example, if the user started from about:welcome, then the value could be 'aboutwelcome-default-screen'. The value has a max length of 128 characters with the alphanumeric characters, _ (underscore), forward slash (/), . (period), % (percentage sign), and - (hyphen) in the allowed set of characters..
*/
recordTwoFactorAuthCodeComplete({
user_agent,
ip_address,
account_user_id_sha256,
relying_party_oauth_client_id,
relying_party_service,
session_device_type,
session_entrypoint,
session_entrypoint_experiment,
session_entrypoint_variation,
session_flow_id,
utm_campaign,
utm_content,
utm_medium,
utm_source,
utm_term,
}: {
user_agent: string;
ip_address: string;
account_user_id_sha256: string;
relying_party_oauth_client_id: string;
relying_party_service: string;
session_device_type: string;
session_entrypoint: string;
session_entrypoint_experiment: string;
session_entrypoint_variation: string;
session_flow_id: string;
utm_campaign: string;
utm_content: string;
utm_medium: string;
utm_source: string;
utm_term: string;
}) {
const event = {
category: 'two_factor_auth',
name: 'code_complete',
};
this.#record({
user_agent,
ip_address,
account_user_id_sha256,
relying_party_oauth_client_id,
relying_party_service,
session_device_type,
session_entrypoint,
session_entrypoint_experiment,
session_entrypoint_variation,
session_flow_id,
utm_campaign,
utm_content,
utm_medium,
utm_source,
utm_term,
event,
});
}
} }
/** /**

Просмотреть файл

@ -306,6 +306,8 @@ module.exports = (log, db, mailer, customs, config, glean) => {
tokenId: sessionToken && sessionToken.id, tokenId: sessionToken && sessionToken.id,
}); });
glean.twoFactorAuth.codeComplete(request, { uid });
await log.notifyAttachedServices('profileDataChange', request, { await log.notifyAttachedServices('profileDataChange', request, {
uid: sessionToken.uid, uid: sessionToken.uid,
}); });

Просмотреть файл

@ -38,6 +38,7 @@ const recordThirdPartyAuthSetPasswordCompleteStub = sinon.stub();
const recordAccountDeleteCompleteStub = sinon.stub(); const recordAccountDeleteCompleteStub = sinon.stub();
const recordPasswordResetEmailConfirmationSentStub = sinon.stub(); const recordPasswordResetEmailConfirmationSentStub = sinon.stub();
const recordPasswordResetEmailConfirmationSuccessStub = sinon.stub(); const recordPasswordResetEmailConfirmationSuccessStub = sinon.stub();
const recordTwoFactorAuthCodeCompleteStub = sinon.stub();
const { gleanMetrics, logErrorWithGlean } = proxyquire( const { gleanMetrics, logErrorWithGlean } = proxyquire(
'../../../lib/metrics/glean', '../../../lib/metrics/glean',
@ -84,6 +85,7 @@ const { gleanMetrics, logErrorWithGlean } = proxyquire(
recordPasswordResetEmailConfirmationSentStub, recordPasswordResetEmailConfirmationSentStub,
recordPasswordResetEmailConfirmationSuccess: recordPasswordResetEmailConfirmationSuccess:
recordPasswordResetEmailConfirmationSuccessStub, recordPasswordResetEmailConfirmationSuccessStub,
recordTwoFactorAuthCodeComplete: recordTwoFactorAuthCodeCompleteStub,
}), }),
}, },
} }
@ -413,6 +415,14 @@ describe('Glean server side events', () => {
assert.equal(metrics['event_name'], 'account_delete_complete'); assert.equal(metrics['event_name'], 'account_delete_complete');
sinon.assert.calledOnce(recordAccountDeleteCompleteStub); sinon.assert.calledOnce(recordAccountDeleteCompleteStub);
}); });
it('logs a "two_factor_auth_code_complete" event', async () => {
await glean.twoFactorAuth.codeComplete(request);
sinon.assert.calledOnce(recordStub);
const metrics = recordStub.args[0][0];
assert.equal(metrics['event_name'], 'two_factor_auth_code_complete');
sinon.assert.calledOnce(recordTwoFactorAuthCodeCompleteStub);
});
}); });
describe('registration', () => { describe('registration', () => {

Просмотреть файл

@ -200,6 +200,7 @@ describe('totp', () => {
describe('/session/verify/totp', () => { describe('/session/verify/totp', () => {
afterEach(() => { afterEach(() => {
glean.login.totpSuccess.reset(); glean.login.totpSuccess.reset();
glean.twoFactorAuth.codeComplete();
}); });
it('should enable and verify TOTP token', () => { it('should enable and verify TOTP token', () => {
@ -286,6 +287,8 @@ describe('totp', () => {
tokenId: 'id', tokenId: 'id',
}); });
sinon.assert.calledOnce(glean.twoFactorAuth.codeComplete);
assert.calledWithExactly(accountEventsManager.recordSecurityEvent, db, { assert.calledWithExactly(accountEventsManager.recordSecurityEvent, db, {
name: 'account.two_factor_challenge_success', name: 'account.two_factor_challenge_success',
uid: 'uid', uid: 'uid',

Просмотреть файл

@ -873,3 +873,22 @@ third_party_auth:
expires: never expires: never
data_sensitivity: data_sensitivity:
- interaction - interaction
two_factor_auth:
code_complete:
type: event
description: |
User successfully submitted a backup authentication code to complete two factor auth setup.
lifetime: ping
send_in_pings:
- events
notification_emails:
- vzare@mozilla.com
- fxa-staff@mozilla.com
bugs:
- https://mozilla-hub.atlassian.net/browse/FXA-9587
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1830504
expires: never
data_sensitivity:
- interaction