---
title: User Management
description: 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

```go
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`

```json
{
  "email": "alice@example.com",
  "password": "Secure!Pass99",
  "name": "Alice Liddell",
  "username": "alice",
  "app_id": "myapp",
  "metadata": {
    "company": "Acme Corp",
    "plan": "pro"
  }
}
```

See [Password Authentication](/docs/authsome/authentication/password) for the full sign-up response and flow details.

### Via Go SDK

```go
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:**

```json
{
  "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

```go
u, err := engine.GetMe(ctx, userID)
```

## Update user profile

Authenticated users can update their own profile fields:

`PATCH /v1/auth/me`

```json
{
  "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

```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

```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:**

```json
{
  "user": { "...": "full user record" },
  "sessions": [ "...active sessions..." ],
  "devices": [ "...tracked devices..." ],
  "organizations": [ "...memberships..." ],
  "mfa_enrollments": [ "...MFA enrollment records..." ]
}
```

### In Go

```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.

```json
{
  "metadata": {
    "company": "Acme Corp",
    "plan": "pro",
    "department": "Engineering",
    "employee_id": "E12345"
  }
}
```

Metadata keys correspond to the `key` field in [FormConfig fields](/docs/authsome/dynamic-forms/custom-schemas). 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

```go
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

```go
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:

```go
// 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

```go
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:

```go
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) |
