PHPackages                             silverday/nexus-dropin-user - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Authentication &amp; Authorization](/categories/authentication)
4. /
5. silverday/nexus-dropin-user

ActiveLibrary[Authentication &amp; Authorization](/categories/authentication)

silverday/nexus-dropin-user
===========================

Security-first, framework-agnostic PHP 8.2+ drop-in user management module

v0.2.4(2mo ago)20MITPHPPHP ^8.2CI passing

Since Feb 24Pushed 2mo agoCompare

[ Source](https://github.com/SilverDay/nexus)[ Packagist](https://packagist.org/packages/silverday/nexus-dropin-user)[ Docs](https://github.com/SilverDay/nexus)[ RSS](/packages/silverday-nexus-dropin-user/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (6)Dependencies (4)Versions (7)Used By (0)

Nexus Drop-In User Module
=========================

[](#nexus-drop-in-user-module)

[![Security Tests](https://github.com/SilverDay/nexus/actions/workflows/security-tests.yml/badge.svg)](https://github.com/SilverDay/nexus/actions/workflows/security-tests.yml)

Security-first, framework-agnostic PHP 8.2+ user management module for MariaDB/MySQL.

What this is
------------

[](#what-this-is)

A **drop-in auth/user module** you can mount into an existing PHP app.

- Not a full framework
- Not a standalone IAM server
- Built for embedding and extension

What you get
------------

[](#what-you-get)

- Registration + email verification
- Login (username or email) + secure sessions + remember-me
- Password reset + password change
- Role checks (`user`, `admin`, `super_admin`) with permission checks (`can()`)
- TOTP + recovery codes + step-up verification
- Passkeys (WebAuthn) with safe default disabled mode
- Google OIDC login hooks
- Session/device listing and revocation
- Audit logging for security-sensitive actions
- HTML modules and JSON endpoints

Quick start
-----------

[](#quick-start)

1. Install dependencies:

```
composer install
```

2. Configure database (environment mode):

```
export NEXUS_DB_DSN='mysql:host=127.0.0.1;port=3306;dbname=nexus_user;charset=utf8mb4'
export NEXUS_DB_USER='root'
export NEXUS_DB_PASS=''
```

3. Run migrations:

```
php migrations/run.php
```

4. Start demo router:

```
php -S 127.0.0.1:8080 examples/minimal_router.php
```

Lightweight host-app demo
-------------------------

[](#lightweight-host-app-demo)

If you want a cleaner, app-like example (homepage + register/login + restricted user/admin pages), use:

1. Configure the demo in this file:

- `examples/config/module_webapp.config.php`

Set at least:

- `db_dsn`
- `db_user`
- `db_password`

2. Run migrations (uses the same config file by default if `NEXUS_CONFIG_FILE` is not set):

```
php migrations/run.php
```

3. Start the demo app:

```
php -S 127.0.0.1:8081 examples/module_webapp.php
```

Then open `http://127.0.0.1:8081`.

Optional: use a different config file via environment variable:

```
NEXUS_CONFIG_FILE=/absolute/path/to/your.config.php php -S 127.0.0.1:8081 examples/module_webapp.php
```

This example demonstrates the intended drop-in style:

- include the module
- instantiate core services once
- protect host-app routes using session + role checks

Install in a host app
---------------------

[](#install-in-a-host-app)

Use Composer to install this module into your application. This is the recommended approach for production usage.

If the package is available on Packagist:

```
composer require silverday/nexus-dropin-user:^0.2.1
```

If you want to install directly from GitHub (VCS source):

```
{
	"repositories": [
		{
			"type": "vcs",
			"url": "https://github.com/SilverDay/nexus.git"
		}
	]
}
```

Then run:

```
composer require silverday/nexus-dropin-user:^0.2.1
```

Manual unzip/copy into your app directory is possible for experiments, but not recommended because dependency updates, autoloading, and version pinning are harder to maintain.

Configuration modes
-------------------

[](#configuration-modes)

The module now supports **both** environment-based and file-based configuration.

### A) Environment variables

[](#a-environment-variables)

Used by default when no config file is provided.

Primary keys:

- `NEXUS_DB_DSN`
- `NEXUS_DB_USER`
- `NEXUS_DB_PASS`
- `NEXUS_TOTP_KEY`
- `NEXUS_GOOGLE_OIDC_CLIENT_ID`
- `NEXUS_GOOGLE_OIDC_CLIENT_SECRET`
- `NEXUS_GOOGLE_OIDC_REDIRECT_URI`
- `NEXUS_PASSKEY_WEBAUTHN_ENABLED`

### B) Config file (app-local by default)

[](#b-config-file-app-local-by-default)

The demo router and migration runner look for an app-local config file first:

- `examples/minimal_router.php` defaults to `examples/config/module.config.php`
- `migrations/run.php` defaults to `examples/config/module.config.php`

Override options (in precedence order):

1. `NEXUS_CONFIG_FILE_PATH` constant in your entrypoint
2. Web-server scoped `$_SERVER['NEXUS_CONFIG_FILE']`
3. Process environment variable `NEXUS_CONFIG_FILE`
4. App-local default file path

You can still use `NEXUS_CONFIG_FILE` when useful, but for multi-app servers prefer app-local files or per-app entrypoint constants.

Migration runner also accepts an explicit config path argument:

```
php migrations/run.php /path/to/your/module.config.php
```

See the template in `examples/config/module.config.php`.

Supported config keys include:

- Core config: `db_dsn`, `db_user`, `db_password`, `from_email`, `from_name`
- Security behavior: `secure_cookies`, `same_site`, `ip_binding_mode`, `bind_user_agent`
- Phase-2 toggles/secrets: `totp_key`, `google_oidc_*`, `passkey_webauthn_enabled`
- Mail transport: `mail_transport`, `smtp_host`, `smtp_port`, `smtp_username`, `smtp_password`, `smtp_encryption`, `smtp_timeout_seconds`
- Mail template files: `email_template_locale`, `email_template_roots`, `verification_link_template`, `admin_registration_notify_to`
- Optional mail fallback templates: `email_templates`
- UI fields: `profile_fields`

### Email text and transport configuration

[](#email-text-and-transport-configuration)

You can configure both **what is sent** and **how it is sent** from the config file.

Transport options:

- `mail_transport = null` (default; no mail sent)
- `mail_transport = php` (uses PHP `mail()`)
- `mail_transport = smtp` (uses SMTP with optional AUTH/STARTTLS)

Example transport config:

```
'mail_transport' => 'smtp',
'smtp_host' => 'smtp.example.com',
'smtp_port' => 587,
'smtp_username' => 'smtp-user',
'smtp_password' => 'smtp-password',
'smtp_encryption' => 'tls', // tls|ssl|none
'smtp_timeout_seconds' => 10,
'verification_link_template' => 'https://app.example.com/verify-email?token={{token}}',
'admin_registration_notify_to' => 'security@example.com,ops@example.com',
```

Email text is file-based by default. Template file lookup is:

- `//.subject.txt`
- `//.body.txt`
- fallback to language-only locale (for example `de` from `de-DE`)
- fallback to `en`

Example file-template config:

```
'email_template_locale' => 'de-DE',
'email_template_roots' => [
	__DIR__ . '/../../templates/email',
	'/opt/myapp/mail-templates',
],
```

Default template example:

- `templates/email/en/verify_email.subject.txt`
- `templates/email/en/verify_email.body.txt`

Default mail notification templates shipped:

- `verify_email`
- `password_reset_requested`
- `password_reset_completed`
- `admin_new_user_registered`

Template file contents are preformatted text with placeholders:

```
Please verify your account

```

```
Hi {{real_name}},

Your verification token: {{token}}

```

Optional array fallback when no file template exists:

```
'email_templates' => [
	'verify_email' => [
		'subject' => 'Please verify your account',
		'text' => "Hi {{real_name}},\n\nYour verification token: {{token}}",
	],
],
```

Available placeholders for `verify_email`:

- `{{token}}`
- `{{verify_link}}`
- `{{username}}`
- `{{email}}`
- `{{real_name}}`

Available placeholders for `admin_new_user_registered`:

- `{{user_id}}`
- `{{username}}`
- `{{email}}`
- `{{real_name}}`
- `{{source_ip}}`
- `{{request_id}}`

When `admin_registration_notify_to` is set (array or comma-separated list), admin notifications are emitted on successful registration using the `admin_new_user_registered` template.

### Host app database reuse (drop-in embedding)

[](#host-app-database-reuse-drop-in-embedding)

For host-app embedding, the config file can provide a **shared PDO instance** via `pdo`.

If `pdo` is present, the demo router and migration runner reuse it instead of opening a separate DB connection.

This lets the module use the same database/session context as the embedding application.

### Host app bootstrap example

[](#host-app-bootstrap-example)

For a concrete shared-PDO integration example, see:

- `examples/host_app_bootstrap.php`

Run it like this:

```
php -S 127.0.0.1:8090 examples/host_app_bootstrap.php
```

It exposes sample host-mounted routes:

- `POST /host/auth/register`
- `POST /host/auth/login`

Example endpoints (JSON)
------------------------

[](#example-endpoints-json)

- `POST /register`
- `POST /login`
- `POST /verify-email`
- `POST /password-reset/request`
- `POST /password-reset/confirm`
- `POST /totp/enroll/begin` (auth + CSRF)
- `POST /totp/enroll/confirm` (auth + CSRF)
- `POST /recovery-codes/regenerate` (auth + CSRF)
- `POST /step-up/verify`
- `POST /passkeys/register/begin` (auth + CSRF)
- `POST /passkeys/register/finish` (auth + CSRF)
- `POST /passkeys/authenticate/begin` (CSRF)
- `POST /passkeys/authenticate/finish` (CSRF)
- `GET /passkeys/list` (auth)
- `POST /passkeys/revoke` (auth + CSRF)
- `GET /sessions` (auth)
- `POST /sessions/revoke` (auth + CSRF)
- `GET /oidc/google/start`
- `GET /oidc/google/callback`

HTML modules
------------

[](#html-modules)

- Register/login/verify-email/password-reset
- TOTP enroll + recovery code regeneration
- Step-up verification
- Passkey list + revoke
- Sessions/devices list + revoke
- Profile

All `POST /ui/*` routes require valid CSRF tokens.

Testing
-------

[](#testing)

Fast security suite:

```
composer test:security
```

Full DB-backed security suite (ephemeral MariaDB):

```
composer test:security:db
```

Focused WebAuthn-enabled DB path:

```
composer test:security:db:webauthn
```

Security defaults
-----------------

[](#security-defaults)

- PDO prepared statements
- Argon2id password hashing (preferred)
- `random_bytes()` token generation
- Hashed tokens at rest
- Session ID regeneration on login
- CSRF enforcement on state-changing routes
- Generic auth failures (no account enumeration)
- Audit events for critical auth/security actions
- Pluggable risk engine with `allow`, `require_step_up`, `deny`

Architecture notes
------------------

[](#architecture-notes)

Key extension interfaces:

- `StepUpServiceInterface`
- `TotpServiceInterface`
- `RecoveryCodeServiceInterface`
- `PasskeyServiceInterface`
- `PasskeyCeremonyValidatorInterface`
- `OidcProviderInterface`
- `EventDispatcherInterface`

Primary composition roots:

- `examples/minimal_router.php`
- `migrations/run.php`

Current status
--------------

[](#current-status)

Phase-1 and planned Phase-2 capabilities are implemented in this repository, with DB-backed security regression coverage and CI workflow validation.

###  Health Score

35

—

LowBetter than 80% of packages

Maintenance84

Actively maintained with recent releases

Popularity3

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity41

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

6

Last Release

81d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/7cccaba6043f071bad533718ad36f7edf56a2ac063b54413e95359a1aed44f54?d=identicon)[SilverDay](/maintainers/SilverDay)

---

Top Contributors

[![SilverDay](https://avatars.githubusercontent.com/u/883931?v=4)](https://github.com/SilverDay "SilverDay (10 commits)")

### Embed Badge

![Health badge](/badges/silverday-nexus-dropin-user/health.svg)

```
[![Health](https://phpackages.com/badges/silverday-nexus-dropin-user/health.svg)](https://phpackages.com/packages/silverday-nexus-dropin-user)
```

###  Alternatives

[google/auth

Google Auth Library for PHP

1.4k272.7M162](/packages/google-auth)[simplesamlphp/simplesamlphp

A PHP implementation of a SAML 2.0 service provider and identity provider.

1.1k12.4M193](/packages/simplesamlphp-simplesamlphp)[jeffgreco13/filament-breezy

A custom package for Filament with login flow, profile and teams support.

1.0k1.7M41](/packages/jeffgreco13-filament-breezy)[simplesamlphp/saml2

SAML2 PHP library from SimpleSAMLphp

30317.2M40](/packages/simplesamlphp-saml2)[spatie/laravel-passkeys

Use passkeys in your Laravel app

444494.4k16](/packages/spatie-laravel-passkeys)[web-auth/webauthn-lib

FIDO2/Webauthn Support For PHP

1225.3M72](/packages/web-auth-webauthn-lib)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
