Skip to main content

Custom Log Streams, Emails and Log Retention

Overview

As described in Auth0 Custom Log Streams, Auth0 Webhooks allow events to be delivered to an external web server. Auth0 offers several integrations that automatically push events to third-party log management and analysis systems. Webhooks are useful for events that are not covered by actions. We will touch on the different scenarios in this proposal.

Proposal

Below are three proposals on the architecture that can achieve log retention but can also be used to forward events onto the email bus. At a high level we have included other services which should be evaluated. They include QuickSight and Athena. More details about each can be found below.

Uses Cases

  • View actions performed by tenant administrators.
    • Are admins using the UI rather than custom integrations.
  • View operations performed via the Management API.
    • How many email change requests have happened via Dixa.
    • How many password resets have happened via Dixa.
  • View authentications made by your users.
  • Capture forensic data for security purposes and to identify anomaly detection triggers.
    • Malicious IP addresses
    • Attempted logins with leaked passwords
  • Identify patterns in usage trends.
  • Check for authentication errors and Management API call errors.
    • Are we having issues with our progressive profiling application?
    • Are we having issues with our Auth0 + Dixa Custom Card
  • Track how many migrations have happened
  • Track how many emails have been sent

Options

Option 1 breaks down transformations by lambda which is advantegous as each detail structure is different. This means that each lambda can be tailored to the event. This is true microservice architecture. However, the downside to this approach is that there are over 100 different event types. This is NOT scalable.

Option 1

Option 2 uses a step function to orchestrate our workflow. This means there is a signle lambda responsible for transformation which will contain a lot of complexity. Complexity generally leads to technical debt and more cognative load for developers.

Option 2

Option 3 highlights how we can use nested step function workflows within a step function that trigger depending on the type of event. This means we can trigger a workflow for all events that require us to send an email. We can also trigger a seperate workflow for success events and another for limit or blocked events.

Option 3

Considerations

  • All proposals assume we will store event objects in S3. This is only useful if we wish to retain any for historical analysis. This is NOT a prerequisite. First we must determine our use cases for saving event logs.
  • Instead of storing objects we can add them to a CloudWatch Log Group. This however has the same retention period as Auth0.
  • Are we going to use Grafana to display our events in a meaningful way?
  • Do we want to store events so they can later be ingested by BI?
Athena

Amazon Athena is an interactive query service that makes it easy to analyze data directly in Amazon Simple Storage Service (Amazon S3) using standard SQL. With a few actions in the AWS Management Console, you can point Athena at your data stored in Amazon S3 and begin using standard SQL to run ad-hoc queries and get results in seconds. This could be advantageous if we want to query to health of our auth whilst we have a lack of BI.

QuickSight

Amazon QuickSight is a cloud-scale business intelligence (BI) service that you can use to deliver easy-to-understand insights. The main advantage here is we are able to quickly build dashboards and reports on the health of auth. As we do not have capacity to stream logs into BI this can be seen as an interim solution as Auth0 does not offer anything out of the box.

Emails

As we cannot use Actions to trigger all of our emails we should process them via our custom log stream. In our instance that is the:

  • Email change notification (old email). A notification to the old email that the users email has changed.
  • Email change notification (new email). A notification to the new email that the users email has changed.

We may also consider other emails such as:

  • New sign-on notification email. End users receive an email notification if they sign in from a new or unrecognized client. This email contains user sign-on details such as the web browser and operating system used to sign in, in addition to the time and location of authentication.
  • Report suspicious activity. Suspicious Activity Reporting provides an end user with the option to report unrecognized activity from an account activity email notification.

Log Retention

Log retention periods are short lived. On an Enterprise subscription we only have access to 30 days of logs. Auth0 support can help integrate with external logging services. However, as we are already pushing logs into EventBridge we have a few options available to us.

S3

In order to store event context in S3 we must perform some transformation as each of the Auth0 event details schemas are different depending on the type. Looking at the Log Interface you can see that the details key is unknown and it has the comment that the structure is dependent upon event type.

It is important in this instance to define which events we will filter and store so we are able to have a consistent transformation.

Below are some example logs to show the difference in detail structure:

{
"date": "2023-03-21T10:30:26.538Z",
"type": "sce",
"description": "You can now login to the application with the new email.",
"connection": "Username-Password-Authentication",
"connection_id": "con_6QtSC4UxbO4iCVAQ",
"client_id": "z96bsTbkfddU9dozpS9HrGsiDRCjqPBf",
"client_name": "All Applications",
"ip": "35.167.74.121",
"user_agent": "Other 0.0.0 / Other 0.0.0",
"details": {
"body": {
"tenant": "rapha",
"client_id": "z96bsTbkfddU9dozpS9HrGsiDRCjqPBf",
"user_id": "6414a39713a5c42d363c6b3c",
"connection": "Username-Password-Authentication",
"email": "john.kilpatrick+test@rapha.cc",
"newEmail": "john.kilpatrick@rapha.cc",
"verify": false,
"email_verified": false
}
},
"user_id": "auth0|6414a39713a5c42d363c6b3c",
"user_name": "john.kilpatrick+test@rapha.cc",
"strategy": "auth0",
"strategy_type": "database",
"log_id": "90020230321103031806177000000000000001223372036885584547",
"isMobile": false,
"_id": "90020230321103031806177000000000000001223372036885584547",
"id": "90020230321103031806177000000000000001223372036885584547"
}
{
"date": "2023-03-21T10:38:42.372Z",
"type": "sapi",
"description": "Update a User",
"client_id": "CddQRyor0hjPpLR5rffmByI8ONiUGe1G",
"client_name": "",
"ip": "212.132.236.38",
"user_agent": "Chrome 110.0.0 / Mac OS X 10.15.7",
"details": {
"request": {
"method": "patch",
"path": "/api/v2/users/auth0%7C6414a39713a5c42d363c6b3c",
"query": {},
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36",
"body": {
"email_verified": true
},
"channel": "api",
"ip": "212.132.236.38",
"auth": {
"user": {},
"strategy": "jwt",
"credentials": {
"scopes": [
"read:client_grants"
]
}
}
},
"response": {
"statusCode": 200,
"body": {
"created_at": "2023-03-17T17:29:59.041Z",
"email": "john.kilpatrick@rapha.cc",
"email_verified": true,
"identities": [
{
"connection": "Username-Password-Authentication",
"provider": "auth0",
"user_id": "6414a39713a5c42d363c6b3c",
"isSocial": false
}
],
"name": "john.kilpatrick@rapha.cc",
"nickname": "john.kilpatrick",
"picture": "https://s.gravatar.com/avatar/46d15faf6a778cc1e16c97d3c509c67c?s=480&r=pg&d=https%3A%2F%2Fcdn.auth0.com%2Favatars%2Fjo.png",
"updated_at": "2023-03-21T10:38:42.362Z",
"user_id": "auth0|6414a39713a5c42d363c6b3c",
"last_ip": "212.132.236.38",
"last_login": "2023-03-17T17:29:59.038Z",
"logins_count": 1
}
}
},
"log_id": "90020230321103847497591000000000000001223372036885602199",
"isMobile": false,
"_id": "90020230321103847497591000000000000001223372036885602199",
"id": "90020230321103847497591000000000000001223372036885602199"
}
Unknown Type

The unknown type was introduced in version 3 of typescript as an accompanying type to any. The unknown type, when assigned to a variable, means that a variable type is not known.

And typescript doesn't allow you to use a variable of unknown type unless you either cast the variable to a known type or narrow its type. Type narrowing is the process of moving a less precise type to a more precise type.

Export Logs to AWS CloudWatch

The Auth0 Logs to AWS CloudWatch extension consists of a scheduled job that exports your Auth0 logs to CloudWatch. Whilst this would be a releativel easy extension to implement; Auth0 are in the process of deprecating the extension with an End of Life set at May 2, 2023. Therefore it is advised to stick to the original proposal above.

Resources