Authsome

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:

  • PasswordHash is tagged json:"-" and never appears in API responses.
  • Metadata is a map[string]string for storing arbitrary custom fields (populated from dynamic form fields during signup).
  • DeletedAt enables 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:

  1. Soft-deletes the user record (sets deleted_at)
  2. Revokes all active sessions
  3. Removes associated devices, enrollments, and recovery codes
  4. Emits ActionDeleteAccount on 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

FieldTypeDescription
AppIDid.AppIDRequired. Scope to an application
EnvIDid.EnvironmentIDOptional. Scope to an environment
EmailstringFilter by email (partial match)
UsernamestringFilter by username (partial match)
PhonestringFilter by phone number
SearchstringFull-text search across name, email, username
Banned*boolFilter by ban status
EmailVerified*boolFilter by email verification status
LimitintMax results (default 20, max 100)
OffsetintPagination offset
SortBystringSort field: created_at, updated_at, email, name
SortOrderstringasc 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

MethodPathDescription
GET/meGet authenticated user's profile
PATCH/meUpdate authenticated user's profile
DELETE/meDelete authenticated user's account
GET/me/exportExport all user data (GDPR)

On this page