Add audit logging to authserver
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 2.2k
- Forks
- 300
- Avg merge
- 1d 15h
- Merged PRs (30d)
- 184
Description
Context
The authserver is the most security-sensitive component in ToolHive (token issuance, client registration, upstream IDP interaction) yet has zero audit logging. The rest of the codebase has a mature NIST SP 800-53 compliant audit system in pkg/audit/ with structured event types, subjects, targets, and outcomes.
Scope
Define auth event types
New EventType constants in pkg/audit/ (new file authserver_events.go, following mcp_events.go pattern). Failures are NOT separate event types — they are captured via the existing Outcome field (success, failure, error, denied) on each event.
| Constant | Value | When emitted |
|---|---|---|
EventTypeOAuthAuthorizeRequest |
oauth_authorize_request |
Client initiates authorization. Outcome: success (redirect issued) / denied (invalid client/redirect) |
EventTypeOAuthAuthCodeIssued |
oauth_auth_code_issued |
Auth code generated after successful upstream callback |
EventTypeOAuthTokenIssued |
oauth_token_issued |
Access/refresh token issued via authorization_code grant |
EventTypeOAuthTokenRefreshed |
oauth_token_refreshed |
Token refreshed via refresh_token grant (distinct security properties from initial issuance) |
EventTypeOAuthSessionRevoked |
oauth_session_revoked |
Session forcibly revoked (e.g., upstream refresh permanently failed with invalid_grant) |
EventTypeOAuthClientRegistered |
oauth_client_registered |
DCR: new client registered (RFC 7591) |
EventTypeOAuthUpstreamAuthComplete |
oauth_upstream_auth_complete |
Upstream IDP callback received confirming user authentication |
EventTypeOAuthUpstreamTokenRefreshed |
oauth_upstream_token_refreshed |
ToolHive transparently refreshed an upstream IDP token on behalf of a session |
EventTypeOAuthUserCreated |
oauth_user_created |
New internal user provisioned on first login |
Plus supporting subject keys (oauth_client_id, upstream_issuer, upstream_subject), target keys (session_id, scope, resource, grant_type, revocation_reason), and component constant (toolhive-authserver).
NIST SP 800-53 AU-2 coverage
| AU-2 Category | Events covering it |
|---|---|
| Logon/logoff events | oauth_authorize_request, oauth_upstream_auth_complete |
| Privileged access | oauth_client_registered |
| Non-privileged access | oauth_token_issued, oauth_token_refreshed |
| Account management | oauth_user_created, oauth_session_revoked |
| Third-party interactions | oauth_upstream_auth_complete, oauth_upstream_token_refreshed |
Future events (oauth_token_introspected, oauth_mtls_auth_attempted, oauth_client_updated/deleted) should be added when their corresponding features land.
Create AuthServerAuditor and wire into handlers
Follow the WorkflowAuditor pattern (pkg/audit/workflow_auditor.go) — a direct auditor that handlers call, rather than generic HTTP middleware. This is preferred because auth operations have rich semantic context (client_id, grant_type, upstream_provider) that HTTP middleware can't capture, and different endpoints need very different audit data.
Wire into each handler:
- AuthorizeHandler:
oauth_authorize_requestwith subjects={client_id}, target={redirect_uri, scope, resource} - CallbackHandler success:
oauth_upstream_auth_complete+oauth_auth_code_issued+ optionallyoauth_user_created - CallbackHandler failure:
oauth_upstream_auth_completewith outcome=failure/error - TokenHandler authorization_code:
oauth_token_issuedwith subjects={client_id, user_id, session_id}, target={grant_type, scope} - TokenHandler refresh_token:
oauth_token_refreshedwith subjects={client_id, user_id}, target={grant_type} - TokenHandler failure: relevant event type with outcome=failure
- RegisterClientHandler:
oauth_client_registeredwith subjects={client_id, client_name} - Upstream token refresh (when implemented):
oauth_upstream_token_refreshedwith target={upstream_issuer, session_id} - Session revocation (when implemented):
oauth_session_revokedwith target={session_id, revocation_reason}
Acceptance criteria
- Auth event type constants defined in
pkg/audit/authserver_events.go -
AuthServerAuditorcreated followingWorkflowAuditorpattern - Auditor injected into
Handlervia constructor - Audit events emitted for all handler success and failure paths
- Sensitive data (tokens, PKCE verifiers, authorization codes) NEVER included in audit events
- Source information (client IP, user agent) included in events
- Configuration follows
pkg/audit.Configpatterns (enable/disable, event type filtering) - Unit tests verify correct event types, subjects, and outcomes per handler path
Dependencies
- Depends on #3918 (HTTP middleware — request IDs needed for audit event correlation)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading pkg/audit/mcp_events.go and pkg/audit/workflow_auditor.go, then trace AuthorizeHandler, CallbackHandler, TokenHandler, and RegisterClientHandler. Define the event constants and auditor, inject it into Handler, and add tests for success and failure paths; done means all listed events include the required context without sensitive data and follow pkg/audit.Config filtering.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- authentication, backend, security
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100