Skip to main content

Database Schema

Autentico uses a single SQLite database file. Schema versioning uses SQLite's built-in PRAGMA user_version. The current schema version is defined as SchemaVersion in pkg/db/migrations/migrations.go (currently version 7). Fresh databases run all migrations from scratch; existing databases run only pending ones. Migrations are applied automatically on startup by default, or can be applied interactively via autentico migrate.

Tables​

users​

Stores all user accounts.

ColumnTypeNotes
idTEXT PKUUID -- the sub claim in tokens
usernameTEXT UNIQUELogin name
emailTEXT UNIQUEOptional; enforced unique if set
passwordTEXTbcrypt hash (NULL for passkey-only users)
roleTEXTuser or admin
two_factor_enabledBOOLEANWhether 2FA is enabled
totp_secretTEXTbase32-encoded TOTP shared secret
totp_verifiedBOOLEANWhether enrollment is complete
last_loginDATETIMETimestamp of last successful login
failed_login_attemptsINTEGERResets on successful login
locked_untilDATETIMENULL = not locked
password_last_changedDATETIMEWhen password was last updated
is_email_verifiedBOOLEAN
email_verification_tokenTEXTToken used for email verification
email_verification_expires_atDATETIMEExpiration of verification token
deactivated_atDATETIMENULL = active
registered_atDATETIMENULL only for passkey users mid-ceremony
created_atDATETIME
updated_atDATETIME
given_nameTEXTOIDC standard claim
family_nameTEXTOIDC standard claim
middle_nameTEXTOIDC standard claim
nicknameTEXTOIDC standard claim
websiteTEXTOIDC standard claim
genderTEXTOIDC standard claim
birthdateTEXTOIDC standard claim
profileTEXTOIDC standard claim
phone_numberTEXTOIDC standard claim
phone_number_verifiedBOOLEANOIDC standard claim
pictureTEXTOIDC standard claim
localeTEXTOIDC standard claim
zoneinfoTEXTOIDC standard claim
address_streetTEXTOIDC address claim
address_localityTEXTOIDC address claim
address_regionTEXTOIDC address claim
address_postal_codeTEXTOIDC address claim
address_countryTEXTOIDC address claim

clients​

Registered OAuth2 clients.

ColumnTypeNotes
idTEXT PKInternal UUID
client_idTEXT UNIQUEPublic identifier
client_secretTEXTNULL for public clients
client_nameTEXT
client_typeTEXTconfidential or public
redirect_urisTEXTJSON array
grant_typesTEXTJSON array
response_typesTEXTJSON array
scopesTEXTSpace-separated
token_endpoint_auth_methodTEXT
is_activeBOOLEAN
created_atDATETIME
updated_atDATETIME
access_token_expirationTEXTNULL = use global
refresh_token_expirationTEXTNULL = use global
authorization_code_expirationTEXTNULL = use global
allowed_audiencesTEXTJSON array or NULL
allow_self_signupINTEGERNULL = use global
sso_session_idle_timeoutTEXTNULL = use global
trust_device_enabledINTEGERNULL = use global
trust_device_expirationTEXTNULL = use global
post_logout_redirect_urisTEXTJSON array
consent_requiredINTEGER0 = no consent screen (added in migration 007)

tokens​

Issued access and refresh token records.

ColumnTypeNotes
idTEXT PK
user_idTEXT FK-> users (nullable for client_credentials grant, changed in migration 005)
access_tokenTEXTJWT
refresh_tokenTEXTJWT
access_token_typeTEXTBearer
access_token_expires_atDATETIME
refresh_token_expires_atDATETIME
refresh_token_last_used_atDATETIMETracks when refresh token was last used
issued_atDATETIME
scopeTEXT
grant_typeTEXT
revoked_atDATETIMENULL = not revoked

sessions​

OAuth sessions linking a user to a specific access/refresh token pair and device.

ColumnTypeNotes
idTEXT PK
user_idTEXT FK-> users
access_tokenTEXTAssociated access token
refresh_tokenTEXTAssociated refresh token
user_agentTEXTBrowser/device info
ip_addressTEXTClient IP at session creation
device_idTEXTUnique device identifier
locationTEXTLocation where session was initiated
last_activity_atDATETIME
created_atDATETIME
expires_atDATETIME
deactivated_atDATETIMENULL = active
idp_session_idTEXT FK-> idp_sessions (added in migration 006; nullable for non-browser grants)

idp_sessions​

SSO sessions (browser-facing, managed by session cookie).

ColumnTypeNotes
idTEXT PKStored in browser cookie
user_idTEXT FK-> users
user_agentTEXT
ip_addressTEXT
last_activity_atDATETIMEUpdated on each auto-login
created_atDATETIME
deactivated_atDATETIMENULL = active

auth_codes​

Short-lived authorization codes (typically 1-5 min).

ColumnTypeNotes
codeTEXT PK
user_idTEXT FK-> users
client_idTEXT
redirect_uriTEXT
scopeTEXT
nonceTEXTOIDC replay protection
code_challengeTEXTPKCE
code_challenge_methodTEXTS256 or plain
expires_atDATETIME
usedBOOLEANSingle-use
idp_session_idTEXT FK-> idp_sessions (added in migration 006; carried to session at code exchange)

mfa_challenges​

Pending MFA challenges (TOTP or email OTP).

ColumnTypeNotes
idTEXT PKChallenge token -- included in redirect URL
user_idTEXT FK-> users
methodTEXTtotp or email
codeTEXTOTP code (email OTP only)
login_stateTEXTJSON blob with OAuth params to resume after MFA
created_atDATETIME
expires_atDATETIME5 minutes
usedBOOLEANSingle-use
failed_attemptsINTEGERFailed verification counter
otp_sent_atDATETIMEWhen the OTP email was last sent

trusted_devices​

Trusted device records for MFA bypass.

ColumnTypeNotes
idTEXT PKToken stored in browser cookie
user_idTEXT FK-> users
device_nameTEXTUser-agent at trust time
created_atDATETIME
last_used_atDATETIME
expires_atDATETIMEConfigurable via trust_device_expiration

passkey_challenges​

Pending WebAuthn authentication or registration challenges.

ColumnTypeNotes
idTEXT PKChallenge ID returned to the browser
user_idTEXT FK-> users (ON DELETE CASCADE)
challenge_dataTEXTJSON SessionData from go-webauthn
typeTEXTauthentication or registration
login_stateTEXTJSON OAuth params to resume after passkey
created_atDATETIME
expires_atDATETIME5 minutes
usedBOOLEANSingle-use

passkey_credentials​

Registered WebAuthn credentials.

ColumnTypeNotes
idTEXT PKCredential ID (from WebAuthn)
user_idTEXT FK-> users (ON DELETE CASCADE)
nameTEXTOptional user-visible name
credentialTEXTJSON blob (full Credential from go-webauthn)
created_atDATETIME
last_used_atDATETIME

settings​

Key-value store for runtime settings.

ColumnTypeNotes
keyTEXT PKSetting name (e.g. mfa_enabled)
valueTEXTString value
updated_atDATETIME

federation_providers​

External identity provider configurations for federated/social login.

ColumnTypeNotes
idTEXT PK
nameTEXTDisplay name of the provider
issuerTEXTOIDC issuer URL of the external IdP
client_idTEXTOAuth2 client ID at the external IdP
client_secretTEXTOAuth2 client secret
icon_svgTEXTOptional SVG icon for the login button
enabledBOOLEANWhether this provider is active
sort_orderINTEGERDisplay order on the login page
created_atDATETIME

federated_identities​

Links between local user accounts and external identity provider accounts.

ColumnTypeNotes
idTEXT PK
provider_idTEXT FK-> federation_providers
provider_user_idTEXTUser ID at the external IdP (unique per provider)
user_idTEXT FK-> users
emailTEXTEmail from the external IdP
created_atDATETIME

Unique constraint on (provider_id, provider_user_id).

deletion_requests​

User-initiated account deletion requests (reviewed by admins).

ColumnTypeNotes
idTEXT PK
user_idTEXT FK-> users
reasonTEXTOptional reason provided by the user
requested_atDATETIME

password_reset_tokens​

Time-limited tokens for the password reset flow. Added in migration 002.

ColumnTypeNotes
idTEXT PK
user_idTEXT FK-> users
token_hashTEXT UNIQUESHA-256 hash of the reset token
expires_atDATETIME
used_atDATETIMENULL until the token is consumed
created_atDATETIME

audit_logs​

Security event audit trail. Added in migration 003.

ColumnTypeNotes
idTEXT PK
eventTEXTEvent type (e.g. login_success, mfa_verify)
actor_idTEXTUser ID of the actor (nullable for unauthenticated events)
actor_usernameTEXTUsername at the time of the event
target_typeTEXTType of resource affected (e.g. user, client)
target_idTEXTID of the affected resource
detailTEXTAdditional context (JSON or free text)
ip_addressTEXTClient IP address
created_atDATETIME

Indexed on created_at, actor_id, and event.

groups​

User groups for organizing users. Added in migration 004.

ColumnTypeNotes
idTEXT PK
nameTEXT UNIQUEGroup name
descriptionTEXT
created_atDATETIME
updated_atDATETIME

user_groups​

Group membership join table. Added in migration 004.

ColumnTypeNotes
user_idTEXT FK-> users (ON DELETE CASCADE)
group_idTEXT FK-> groups (ON DELETE CASCADE)
created_atDATETIME

Composite primary key on (user_id, group_id).

user_consents​

Stored OAuth2 consent decisions per user and client. Added in migration 007.

ColumnTypeNotes
idTEXT PK
user_idTEXT
client_idTEXT
scopesTEXTSpace-separated scopes that were granted
granted_atDATETIME

Unique constraint on (user_id, client_id). When a user approves a consent screen, the decision is stored here. Subsequent logins skip the consent screen unless the requested scopes change.

Migrations​

VersionFileDescription
1001_initial_schema.goCreates all base tables: users, tokens, sessions, auth_codes, idp_sessions, mfa_challenges, trusted_devices, passkey_challenges, passkey_credentials, clients, settings, federation_providers, federated_identities, deletion_requests
2002_password_reset_tokens.goAdds password_reset_tokens table
3003_audit_logs.goAdds audit_logs table
4004_groups.goAdds groups and user_groups tables
5005_nullable_token_user_id.goRebuilds tokens table to make user_id nullable (for client_credentials grant)
6006_idp_session_linkage.goAdds idp_session_id column to auth_codes and sessions tables
7007_user_consents.goAdds consent_required column to clients and creates user_consents table

Indexes​

The following indexes are created across migrations:

  • idx_tokens_refresh_token on tokens(refresh_token)
  • idx_tokens_access_token on tokens(access_token)
  • idx_sessions_access_token on sessions(access_token)
  • idx_sessions_user_id on sessions(user_id)
  • idx_sessions_idp_session_id on sessions(idp_session_id)
  • idx_idp_sessions_user_id on idp_sessions(user_id)
  • idx_passkey_credentials_user_id on passkey_credentials(user_id)
  • idx_federated_identities_user_id on federated_identities(user_id)
  • idx_deletion_requests_user_id on deletion_requests(user_id)
  • idx_password_reset_tokens_hash on password_reset_tokens(token_hash)
  • idx_password_reset_tokens_user on password_reset_tokens(user_id)
  • idx_audit_logs_created_at on audit_logs(created_at)
  • idx_audit_logs_actor_id on audit_logs(actor_id)
  • idx_audit_logs_event on audit_logs(event)
  • idx_user_groups_user_id on user_groups(user_id)
  • idx_user_groups_group_id on user_groups(group_id)
  • idx_auth_codes_idp_session_id on auth_codes(idp_session_id)
  • idx_user_consents_user_client on user_consents(user_id, client_id)