User Management
User entity structure, CRUD operations, profile management, metadata, banning, and search.
The User entity is the central identity record in Authsome. Every authenticated person is represented by a user record scoped to an application and environment. Users are created during sign-up (or automatically via social login / phone auth) and can be managed through both the HTTP API and Go SDK.
User entity
type User struct {
ID id.UserID `json:"id"`
AppID id.AppID `json:"app_id"`
EnvID id.EnvironmentID `json:"env_id"`
Email string `json:"email"`
EmailVerified bool `json:"email_verified"`
Name string `json:"name"`
Image string `json:"image,omitempty"`
Username string `json:"username,omitempty"`
DisplayUsername string `json:"display_username,omitempty"`
Phone string `json:"phone,omitempty"`
PhoneVerified bool `json:"phone_verified"`
PasswordHash string `json:"-"`
PasswordChangedAt *time.Time `json:"password_changed_at,omitempty"`
Banned bool `json:"banned"`
BanReason string `json:"ban_reason,omitempty"`
BanExpires *time.Time `json:"ban_expires,omitempty"`
Metadata Metadata `json:"metadata,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt *time.Time `json:"deleted_at,omitempty"`
}Key design decisions:
PasswordHashis taggedjson:"-"and never appears in API responses.Metadatais amap[string]stringfor storing arbitrary custom fields (populated from dynamic form fields during signup).DeletedAtenables soft deletes for data retention compliance.- All IDs are TypeID-based (UUIDv7, K-sortable). User IDs have the prefix
ausr_.
Create a user
Users are typically created through the sign-up flow, but can also be created directly via the admin API or Go SDK.
Via sign-up
POST /v1/auth/signup
{
"email": "alice@example.com",
"password": "Secure!Pass99",
"name": "Alice Liddell",
"username": "alice",
"app_id": "myapp",
"metadata": {
"company": "Acme Corp",
"plan": "pro"
}
}See Password Authentication for the full sign-up response and flow details.
Via Go SDK
import (
"github.com/xraph/authsome/user"
"github.com/xraph/authsome/id"
)
u := &user.User{
ID: id.NewUserID(),
AppID: appID,
Email: "alice@example.com",
Name: "Alice Liddell",
Username: "alice",
Metadata: user.Metadata{
"company": "Acme Corp",
"plan": "pro",
},
}
err := engine.CreateUser(ctx, u)Get current user
Authenticated users can retrieve their own profile:
GET /v1/auth/me
Authorization: Bearer <session_token>Response:
{
"id": "ausr_01j9...",
"app_id": "aapp_01j9...",
"email": "alice@example.com",
"email_verified": true,
"name": "Alice Liddell",
"username": "alice",
"phone": "+15551234567",
"phone_verified": true,
"banned": false,
"metadata": {"company": "Acme Corp", "plan": "pro"},
"created_at": "2024-11-01T10:00:00Z",
"updated_at": "2024-11-15T14:30:00Z"
}In Go
u, err := engine.GetMe(ctx, userID)Update user profile
Authenticated users can update their own profile fields:
PATCH /v1/auth/me
{
"name": "Alice Wonderland",
"username": "alicew",
"image": "https://cdn.example.com/alice.jpg"
}Only the fields provided in the request body are updated. The engine validates username uniqueness before applying the change.
In Go
u, err := engine.GetMe(ctx, userID)
u.Name = "Alice Wonderland"
u.Username = "alicew"
err = engine.UpdateMe(ctx, u)Delete account
Users can permanently delete their own account (GDPR right to erasure):
DELETE /v1/auth/me
Authorization: Bearer <session_token>This operation:
- Soft-deletes the user record (sets
deleted_at) - Revokes all active sessions
- Removes associated devices, enrollments, and recovery codes
- Emits
ActionDeleteAccounton the hook bus
In Go
err := engine.DeleteAccount(ctx, userID)Export user data
For GDPR data portability, users can export all their data:
GET /v1/auth/me/export
Authorization: Bearer <session_token>Response:
{
"user": { "...": "full user record" },
"sessions": [ "...active sessions..." ],
"devices": [ "...tracked devices..." ],
"organizations": [ "...memberships..." ],
"mfa_enrollments": [ "...MFA enrollment records..." ]
}In Go
export, err := engine.ExportUserData(ctx, userID)User metadata
The Metadata field is a map[string]string for storing custom data. Metadata values are populated from dynamic form fields during signup and can be updated via the API.
{
"metadata": {
"company": "Acme Corp",
"plan": "pro",
"department": "Engineering",
"employee_id": "E12345"
}
}Metadata keys correspond to the key field in FormConfig fields. When a user signs up with a custom form, the engine automatically maps form field values to metadata entries.
Ban and unban users
Administrators can ban users to prevent them from signing in. Banned users receive ErrUserBanned (HTTP 403) on any authentication attempt.
Ban a user
u, err := engine.GetUser(ctx, userID)
u.Banned = true
u.BanReason = "Terms of service violation"
u.BanExpires = timePtr(time.Now().Add(30 * 24 * time.Hour)) // optional expiry
err = engine.UpdateUser(ctx, u)When BanExpires is set, the ban automatically lifts after the expiry time. If BanExpires is nil, the ban is permanent until manually removed.
Unban a user
u, err := engine.GetUser(ctx, userID)
u.Banned = false
u.BanReason = ""
u.BanExpires = nil
err = engine.UpdateUser(ctx, u)Ban check during sign-in
The engine checks ban status during every sign-in attempt:
// Simplified engine logic:
if u.Banned {
if u.BanExpires != nil && time.Now().After(*u.BanExpires) {
// Ban expired — auto-unban
u.Banned = false
store.UpdateUser(ctx, u)
} else {
return nil, nil, account.ErrUserBanned
}
}Search and filter users
List users with filtering and pagination:
Via Go SDK
import "github.com/xraph/authsome/user"
result, err := engine.ListUsers(ctx, &user.UserQuery{
AppID: appID,
Email: "alice@", // partial match
Search: "Liddell", // search name, email, username
Banned: boolPtr(false), // filter by ban status
Limit: 20,
Offset: 0,
})
// result.Users → []*user.User
// result.Total → total count (for pagination)UserQuery parameters
| Field | Type | Description |
|---|---|---|
AppID | id.AppID | Required. Scope to an application |
EnvID | id.EnvironmentID | Optional. Scope to an environment |
Email | string | Filter by email (partial match) |
Username | string | Filter by username (partial match) |
Phone | string | Filter by phone number |
Search | string | Full-text search across name, email, username |
Banned | *bool | Filter by ban status |
EmailVerified | *bool | Filter by email verification status |
Limit | int | Max results (default 20, max 100) |
Offset | int | Pagination offset |
SortBy | string | Sort field: created_at, updated_at, email, name |
SortOrder | string | asc or desc (default desc) |
User store interface
The user store is part of the composite store and implements:
type Store interface {
CreateUser(ctx context.Context, u *User) error
GetUser(ctx context.Context, userID id.UserID) (*User, error)
GetUserByEmail(ctx context.Context, appID id.AppID, email string) (*User, error)
GetUserByPhone(ctx context.Context, appID id.AppID, phone string) (*User, error)
GetUserByUsername(ctx context.Context, appID id.AppID, username string) (*User, error)
UpdateUser(ctx context.Context, u *User) error
DeleteUser(ctx context.Context, userID id.UserID) error
ListUsers(ctx context.Context, q *UserQuery) (*UserList, error)
}API routes
| Method | Path | Description |
|---|---|---|
GET | /me | Get authenticated user's profile |
PATCH | /me | Update authenticated user's profile |
DELETE | /me | Delete authenticated user's account |
GET | /me/export | Export all user data (GDPR) |