Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(metrics): Add scopes to Glean access token check event #17847

Merged
merged 1 commit into from
Oct 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions packages/fxa-auth-server/lib/metrics/glean/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ type MetricsData = {
uid?: string;
reason?: string;
oauthClientId?: string;
scopes?: string;
};

type AdditionalMetricsCallback = (
Expand Down Expand Up @@ -162,6 +163,7 @@ const createEventFn =
utm_medium: metricsContext.utmMedium || '',
utm_source: metricsContext.utmSource || '',
utm_term: metricsContext.utmTerm || '',
scopes: metricsData?.scopes || '',
};

// reason is sent in access_token_created, login_submit_backend_error, and reg_submit_error
Expand Down Expand Up @@ -259,6 +261,13 @@ export function gleanMetrics(config: ConfigType) {
}),
tokenChecked: createEventFn('access_token_checked', {
skipClientIp: true,
additionalMetrics: (metrics) => ({
scopes: metrics.scopes
? Array.isArray(metrics.scopes)
? metrics.scopes.sort().join(',')
: metrics.scopes
: '',
}),
}),
},

Expand Down
6 changes: 6 additions & 0 deletions packages/fxa-auth-server/lib/metrics/glean/server_events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,7 @@ class EventsServerEventLogger {
* @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..
* @param {string} scopes - The scopes of the access token.
*/
recordAccessTokenChecked({
user_agent,
Expand All @@ -338,6 +339,7 @@ class EventsServerEventLogger {
utm_medium,
utm_source,
utm_term,
scopes,
}: {
user_agent: string;
ip_address: string;
Expand All @@ -355,10 +357,14 @@ class EventsServerEventLogger {
utm_medium: string;
utm_source: string;
utm_term: string;
scopes: string;
}) {
const event = {
category: 'access_token',
name: 'checked',
extra: {
scopes: String(scopes),
},
};
this.#record({
user_agent,
Expand Down
1 change: 1 addition & 0 deletions packages/fxa-auth-server/lib/routes/oauth/verify.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ module.exports = ({ log, glean }) => ({
glean.oauth.tokenChecked(req, {
uid: info.user,
oauthClientId: info.client_id,
scopes: info.scope,
});
return info;
},
Expand Down
31 changes: 31 additions & 0 deletions packages/fxa-auth-server/test/local/metrics/glean.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ describe('Glean server side events', () => {
recordRegAccVerifiedStub.reset();
recordRegCompleteStub.reset();
recordRegSubmitErrorStub.reset();
recordAccessTokenCheckedStub.reset();
});

describe('enabled state', () => {
Expand Down Expand Up @@ -559,6 +560,36 @@ describe('Glean server side events', () => {
const metrics = recordStub.args[0][0];
assert.equal(metrics['ip_address'], '');
});

it('handles undefined scopes', async () => {
const glean = gleanMetrics(config);
await glean.oauth.tokenChecked(request, {
scopes: undefined,
});
sinon.assert.calledOnce(recordAccessTokenCheckedStub);
const metrics = recordAccessTokenCheckedStub.args[0][0];
assert.equal(metrics['scopes'], '');
});

it('handles empty scopes', async () => {
const glean = gleanMetrics(config);
await glean.oauth.tokenChecked(request, {
scopes: '',
});
sinon.assert.calledOnce(recordAccessTokenCheckedStub);
const metrics = recordAccessTokenCheckedStub.args[0][0];
assert.equal(metrics['scopes'], '');
});

it('includes sorted comma separated scopes', async () => {
const glean = gleanMetrics(config);
await glean.oauth.tokenChecked(request, {
scopes: ['profile', 'openid'],
});
sinon.assert.calledOnce(recordAccessTokenCheckedStub);
const metrics = recordAccessTokenCheckedStub.args[0][0];
assert.equal(metrics['scopes'], 'openid,profile');
});
});
});

Expand Down
1 change: 1 addition & 0 deletions packages/fxa-auth-server/test/oauth/routes/verify.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ describe('/verify POST', () => {
sinon.assert.calledOnceWithExactly(mocks.glean.oauth.tokenChecked, req, {
uid: 'bar',
oauthClientId: 'foo',
scopes: ['bar:foo', 'clients:write'],
});
});
});
Expand Down
135 changes: 135 additions & 0 deletions packages/fxa-content-server/server/lib/glean/server_events.js
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ class EventsServerEventLogger {
* @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..
* @param {string} scopes - The scopes of the access token.
*/
recordAccessTokenChecked({
user_agent,
Expand All @@ -272,10 +273,14 @@ class EventsServerEventLogger {
utm_medium,
utm_source,
utm_term,
scopes,
}) {
const event = {
category: 'access_token',
name: 'checked',
extra: {
scopes: String(scopes),
},
};
this.#record({
user_agent,
Expand Down Expand Up @@ -1282,6 +1287,71 @@ class EventsServerEventLogger {
event,
});
}
/**
* Record and submit a password_reset_recovery_code_success event:
* User successfully verified their recovery code before password reset
* 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 - The firefox/mozilla account id.
* @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..
*/
recordPasswordResetRecoveryCodeSuccess({
user_agent,
ip_address,
account_user_id,
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,
}) {
const event = {
category: 'password_reset',
name: 'recovery_code_success',
};
this.#record({
user_agent,
ip_address,
account_user_id,
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,
});
}
/**
* Record and submit a password_reset_recovery_key_create_success event:
* Forgot Password w/ Recovery Key Create New Password Success (BE) User successfully submits the form to create a new password'
Expand Down Expand Up @@ -1412,6 +1482,71 @@ class EventsServerEventLogger {
event,
});
}
/**
* Record and submit a password_reset_two_factor_success event:
* User successfully verified their two factor authentication code before password reset
* 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 - The firefox/mozilla account id.
* @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..
*/
recordPasswordResetTwoFactorSuccess({
user_agent,
ip_address,
account_user_id,
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,
}) {
const event = {
category: 'password_reset',
name: 'two_factor_success',
};
this.#record({
user_agent,
ip_address,
account_user_id,
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,
});
}
/**
* Record and submit a reg_acc_created event:
* Registration Submission Success Event that indicates registration was successful.
Expand Down
4 changes: 4 additions & 0 deletions packages/fxa-shared/metrics/glean/fxa-backend-metrics.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,10 @@ access_token:
expires: never
data_sensitivity:
- interaction
extra_keys:
scopes:
description: The scopes of the access token
type: string
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does Glean support Array types? Would that allow for easier sorting and graphs?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, the String List type is not support for the extra keys. 😞

created:
type: event
description: |
Expand Down