Skip to content

Instantly share code, notes, and snippets.

@RyAndrew
Created March 11, 2025 05:31
Show Gist options
  • Save RyAndrew/92d51334972105d7d0d5a5b294614bb5 to your computer and use it in GitHub Desktop.
Save RyAndrew/92d51334972105d7d0d5a5b294614bb5 to your computer and use it in GitHub Desktop.
ai experiments - claude sonet 3.7 extended thinking - okta system logs logins per app per day console script
//Prompt:
//Write a clean, efficient JavaScript script for Gabriel Sroka's Okta console tool (https://gabrielsroka.github.io/console/) that fetches Okta system logs for user app login events, count them per app per day, displays the results in a table. Use the tool's native APIs and utilities wherever possible to handle pagination and rate limiting instead of reinventing these mechanisms.
Use he parameters since and until for the okta log api
//paste in source code for console bookmarklet as addl context
//Output:
// Fetch Okta system logs for app login events and count per app per day
// Date range parameters - default to last 7 days
const now = new Date();
const defaultEndDate = now.toISOString().split('T')[0];
const sevenDaysAgo = new Date(now);
sevenDaysAgo.setDate(now.getDate() - 7);
const defaultStartDate = sevenDaysAgo.toISOString().split('T')[0];
// Prompt user for date range
let startDate = prompt("Enter start date (YYYY-MM-DD) or leave blank for 7 days ago:", defaultStartDate);
let endDate = prompt("Enter end date (YYYY-MM-DD) or leave blank for today:", defaultEndDate);
// Validate dates or use defaults
if (startDate && !/^\d{4}-\d{2}-\d{2}$/.test(startDate)) {
log("Invalid start date format. Using default (7 days ago).");
startDate = defaultStartDate;
}
if (endDate && !/^\d{4}-\d{2}-\d{2}$/.test(endDate)) {
log("Invalid end date format. Using default (today).");
endDate = defaultEndDate;
}
// Convert to ISO format required by Okta API
const since = `${startDate || defaultStartDate}T00:00:00Z`;
const until = `${endDate || defaultEndDate}T23:59:59Z`;
log(`Fetching login events from ${startDate || defaultStartDate} to ${endDate || defaultEndDate}`);
// Build the URL with filters for app login events and date range
const filter = `eventType eq "user.authentication.sso"`;
const url = `/api/v1/logs?filter=${encodeURIComponent(filter)}&since=${encodeURIComponent(since)}&until=${encodeURIComponent(until)}`;
// Object to store login counts
const loginsByAppByDay = {};
let totalEvents = 0;
const startTime = Date.now();
// Fetch and process logs
log("Fetching logs, please wait...");
for await (const event of getObjects(url)) {
totalEvents++;
// Update status periodically
if (totalEvents % 100 === 0) {
const elapsedSeconds = Math.round((Date.now() - startTime) / 1000);
log(`Processed ${totalEvents} events (${elapsedSeconds} seconds elapsed)...`);
}
// Extract app name from target objects
let appName = "Unknown App";
if (event.target && event.target.length > 0) {
for (const target of event.target) {
if (target.type === "AppInstance") {
appName = target.displayName || target.alternateId || target.id || "Unknown App";
break;
}
}
}
// Extract date (without time)
const eventDate = event.published.split('T')[0];
// Initialize counter if needed
if (!loginsByAppByDay[appName]) {
loginsByAppByDay[appName] = {};
}
if (!loginsByAppByDay[appName][eventDate]) {
loginsByAppByDay[appName][eventDate] = 0;
}
// Increment counter
loginsByAppByDay[appName][eventDate]++;
if (cancel) {
log("Operation cancelled by user");
break;
}
}
// Calculate processing time
const processingTime = Math.round((Date.now() - startTime) / 1000);
log(`Completed processing ${totalEvents} events in ${processingTime} seconds`);
// Create daily breakdown table data
const dailyData = [];
for (const app in loginsByAppByDay) {
for (const date in loginsByAppByDay[app]) {
dailyData.push({
Application: app,
Date: date,
Logins: loginsByAppByDay[app][date]
});
}
}
// Sort by date (ascending) and then by login count (descending)
dailyData.sort((a, b) => {
if (a.Date === b.Date) {
return b.Logins - a.Logins;
}
return a.Date.localeCompare(b.Date);
});
// Create summary data (total logins per app)
const summaryData = [];
for (const app in loginsByAppByDay) {
let totalLogins = 0;
let daysWithActivity = 0;
for (const date in loginsByAppByDay[app]) {
totalLogins += loginsByAppByDay[app][date];
daysWithActivity++;
}
summaryData.push({
Application: app,
"Total Logins": totalLogins,
"Days With Activity": daysWithActivity,
"Avg Logins/Day": Math.round((totalLogins / daysWithActivity) * 10) / 10
});
}
// Sort summary by total logins (descending)
summaryData.sort((a, b) => b["Total Logins"] - a["Total Logins"]);
// Display results
if (dailyData.length > 0) {
log(`Found ${totalEvents} login events across ${dailyData.length} app/day combinations`);
// Display summary first
log("Summary of app usage:");
table(summaryData);
// Then display daily breakdown
log("Daily breakdown of app logins:");
table(dailyData);
// Add export buttons
results.innerHTML += '<br><button id="exportSummary">Export Summary to CSV</button> ' +
'<button id="exportDaily">Export Daily Breakdown to CSV</button>';
document.getElementById("exportSummary").onclick = function() {
downloadCSV(csv(summaryData), "Okta_App_Login_Summary");
};
document.getElementById("exportDaily").onclick = function() {
downloadCSV(csv(dailyData), "Okta_App_Login_Daily");
};
} else {
log("No login events found for the specified date range");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment