Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@ CIRCLE_USDC_TOKEN_ID=15dc2b5d-0994-58b0-bf8c-3a0501148ee8

# Misc
ADMIN_EMAIL=admin@admin.com
# Required to auto-provision the admin user. Must be strong (>= 8 chars, not a
# common password). Leave blank to skip automatic admin creation.
ADMIN_PASSWORD=
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ CIRCLE_USDC_TOKEN_ID=

# Misc
ADMIN_EMAIL=admin@admin.com
ADMIN_PASSWORD=
```

| Variable | Scope | Purpose |
Expand All @@ -125,16 +126,19 @@ ADMIN_EMAIL=admin@admin.com
| `CIRCLE_ENTITY_SECRET` | Server-side | Circle entity secret for wallet operations. |
| `CIRCLE_BLOCKCHAIN` | Server-side | Blockchain network identifier (e.g., "ARC-TESTNET"). |
| `CIRCLE_USDC_TOKEN_ID` | Server-side | USDC token ID for the specified blockchain. Pre-filled for ARC-TESTNET. |
| `ADMIN_EMAIL` | Server-side | Admin user email address. |
| `ADMIN_EMAIL` | Server-side | Admin user email address. Defaults to `admin@admin.com`. |
| `ADMIN_PASSWORD` | Server-side | Password for the auto-provisioned admin user. Required to create it; must be strong (>= 8 chars, not a common password). Leave blank to skip admin creation. |

## User Accounts

### Admin Account

On first startup, an admin user is automatically created with the following credentials:
On first startup, an admin user is automatically created **only if** `ADMIN_PASSWORD` is set to a strong value (see the environment table above):

- **Email:** `admin@admin.com`
- **Password:** `123456`
- **Email:** `ADMIN_EMAIL` (defaults to `admin@admin.com`)
- **Password:** the value of `ADMIN_PASSWORD` — choose a strong, unique password

If `ADMIN_PASSWORD` is unset, or weak (shorter than 8 characters or a well-known password), admin creation is skipped and a message is logged — so a publicly reachable deployment never ships with a guessable default.

The admin account has access to the **Admin Dashboard**, which provides an overview of all users, wallets, and transactions in the system.

Expand Down
42 changes: 40 additions & 2 deletions lib/supabase/initialize-admin-user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,51 @@ if (supabaseUrl && supabaseServiceRoleKey) {
);
}

// Passwords that must never guard a privileged account, even if set explicitly.
const COMMON_WEAK_PASSWORDS = new Set([
"123456",
"12345678",
"123456789",
"password",
"admin",
"admin123",
"qwerty",
"letmein",
"changeme",
"welcome",
]);

const isWeakPassword = (password: string): boolean =>
password.length < 8 || COMMON_WEAK_PASSWORDS.has(password.toLowerCase());

const createAdminUserIfNotExists = async () => {
if (!adminAuthClient) {
return;
}

const adminEmail = "admin@admin.com";
const adminPassword = "123456";
// Never provision the admin account with a hardcoded, publicly known
// password. Require the deployment to supply one explicitly via
// ADMIN_PASSWORD and reject obviously weak values, so an exposed instance
// cannot be taken over with a guessable default. ADMIN_EMAIL keeps its
// documented default because the database RLS policies key off that address.
const adminEmail = process.env.ADMIN_EMAIL ?? "admin@admin.com";
const adminPassword = process.env.ADMIN_PASSWORD;

if (!adminPassword) {
console.warn(
"ADMIN_PASSWORD is not set. Skipping admin user creation. " +
"Set a strong ADMIN_PASSWORD to enable automatic admin provisioning."
);
return;
}

if (isWeakPassword(adminPassword)) {
console.error(
"ADMIN_PASSWORD is too weak (must be at least 8 characters and not a " +
"well-known password). Skipping admin user creation."
);
return;
}

// We call our custom database function via RPC (Remote Procedure Call).
// This is a single, fast, and scalable database query.
Expand Down
1 change: 1 addition & 0 deletions types/environment.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,6 @@ namespace NodeJS {

// Misc
ADMIN_EMAIL: string
ADMIN_PASSWORD?: string
}
}