Login history
Auth Service records every successful login in the login_history table, which gives a history of successful authentication events (failed attempts are not recorded).
Data model
| Field | Type | Description |
|---|---|---|
id | UUID | Primary key |
userId | string | User identifier |
applicationId | UUID | null | Application id (null for a direct sign-in that is not an OAuth token issuance). Set to null when the application is deleted |
sessionId | string | null | Associated session ID (set on direct sign-ins, null on OAuth token issuance rows) |
ipAddress | string | null | Client IP address, as captured on the session |
userAgent | string | null | Client user-agent string |
loggedAt | timestamp | Login timestamp (UTC) |
How it works
Every successful login triggers an insert into login_history, updates the denormalised user.last_login_at timestamp and publishes a login.recorded event on the live-event channel. Both database writes happen in recordLogin(); the callers wrap it in a try/catch, so a failure is logged at warn level and does not block authentication. Auth Service does not purge login_history rows itself.
Two paths record a login:
- Direct session creation — the BetterAuth
session.createhook (admin dashboard sign-in, password login, social provider callback) records a row with the session id, IP and user agent from the new session, andapplicationIdnull. - OAuth token issuance to an application —
customAccessTokenClaimshas no request context, so the row is written withapplicationIdset to the target application and no session id, IP or user-agent.recordLogin()then falls back to the user's most recent session (the same client that is signing in) to fill in the IP and user agent.
Admin API endpoints
List login history for a user in an application
GET /api/admin/applications/:id/users/:userId/history
Requires an admin or superadmin session. Returns paginated login history for the specified user within the specified application, newest first:
{
"entries": [
{
"id": "uuid-1",
"loggedAt": "2026-06-15T14:30:00Z",
"ipAddress": "192.168.1.1",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)...",
"sessionId": null
},
{
"id": "uuid-2",
"loggedAt": "2026-06-14T09:15:00Z",
"ipAddress": "10.0.0.1",
"userAgent": "Mozilla/5.0 (Macintosh; Intel...)",
"sessionId": null
}
],
"total": 42,
"page": 1,
"limit": 20
}
Query parameters
| Parameter | Default | Description |
|---|---|---|
page | 1 | Page number |
limit | 20 | Results per page (max 100) |
Admin dashboard
The user detail view (/users/:id) lists the user's applications with the date of the last login on each. It has no login-history list of its own.
The application detail view (/applications/:id) has a Users tab whose rows carry the last login date, IP and device for that application, plus a per-row history icon that opens the paginated Login history modal (GET /api/admin/applications/:id/users/:userId/history). The modal shows each entry's time, IP address and browser / operating system, with a selectable page size. These are read from login_history filtered by applicationId, so a login on another application — or a direct sign-in with no application — never appears here.
The tab stays live while it is open: a login.recorded event (published on every successful login) refreshes the last-login columns, and the activity strip at the top of the page (online count, 7-day logins, sparkline) is refreshed both by that event and by a 30 s poll that absorbs session-expiry drift. The online figure of that strip counts the distinct users with a login event for the application in the last 24 hours.
Statistics endpoint
The login statistics endpoint provides a dense daily series, platform-wide or for one application:
GET /api/admin/stats/logins?range=7d|30d&appId=<uuid>
Requires an admin or superadmin session. Response:
{
"range": "7d",
"series": [
{ "date": "2026-06-11", "count": 42 },
{ "date": "2026-06-12", "count": 38 },
{ "date": "2026-06-13", "count": 55 },
{ "date": "2026-06-14", "count": 61 },
{ "date": "2026-06-15", "count": 47 },
{ "date": "2026-06-16", "count": 33 },
{ "date": "2026-06-17", "count": 28 }
],
"total": 304
}
| Parameter | Default | Description |
|---|---|---|
range | 7d | Time range: 7d or 30d |
appId | — | Filter by application UUID |
The series is dense — days with no logins are filled with count: 0 so chart libraries render a continuous axis. Days are UTC days, and total is the sum of the series.
Use cases
- Security auditing — review the IP addresses and user agents of past logins for a user on an application.
- Compliance — keep a record of successful authentication events. Failed attempts are not recorded here.
- Analytics — track login trends over time via the statistics endpoint.
- Forensics — investigate a suspect account by reviewing its login history per application.