neamatrix / connex
Laravel package for Connex DCB login: protected-script, OTP via login-connex, confirm via login-confirm, customizable login UI, mobile Sanctum tokens.
Requires
- php: ^8.2
- illuminate/database: ^10.0|^11.0|^12.0|^13.0
- illuminate/http: ^10.0|^11.0|^12.0|^13.0
- illuminate/routing: ^10.0|^11.0|^12.0|^13.0
- illuminate/support: ^10.0|^11.0|^12.0|^13.0
- illuminate/view: ^10.0|^11.0|^12.0|^13.0
Suggests
- laravel/sanctum: Required for mobile Bearer tokens after OTP confirm (^3.3|^4.0)
This package is not auto-updated.
Last update: 2026-06-04 23:21:24 UTC
README
Laravel package for Connex DCB login: server-side auth-login + protected-script, browser-only dcbprotect / gateway-load, server-side login-connex + login-confirm-connex, customizable login UI, mobile Sanctum tokens.
Database (users table)
Package migrations add Connex subscriber fields from OTP confirm success:
| Column | Example | Source |
|---|---|---|
msisdn |
218920920110 |
success.msisdn |
subscriber |
exist |
success.subscriber |
status |
active |
success.status |
operator |
Libyana |
success.operator |
expiration_date |
2032-08-11 15:56:54 |
success.expiration_date |
php artisan migrate
Migrations live in packages/torgodly/connex/database/migrations/ (auto-loaded by the package).
Ensure your User model includes these in $fillable (and expiration_date cast as datetime).
Tests
From the Laravel app root:
php artisan test
Covers URL building, upstream HTTP (faked), user sync, OTP confirm API, Sanctum token issuance, and the login page.
Requirements
- PHP 8.2+
- Laravel 10, 11, 12, or 13
- laravel/sanctum (recommended for mobile API tokens after OTP confirm)
Install
From Packagist (after package is submitted)
Submit https://github.com/NeaMatrix/connex-package on Packagist.org, then:
composer require neamatrix/connex:^1.1
php artisan vendor:publish --tag=connex-config
php artisan migrate
composer require laravel/sanctum
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
php artisan migrate
Before Packagist / dev install
If you see "Could not find a version matching minimum-stability (stable)", use the GitHub repo directly:
"repositories": [ { "type": "vcs", "url": "https://github.com/NeaMatrix/connex-package.git" } ]
composer require neamatrix/connex:^1.1
Or allow dev stability once:
composer require neamatrix/connex:dev-main
Local path (development)
"repositories": [ { "type": "path", "url": "packages/torgodly/connex", "options": { "symlink": true } } ], "require": { "neamatrix/connex": "@dev" }
Environment
Upstream endpoints
Each call uses CONNEX_BASE_URL + CONNEX_*_ENDPOINT.
| Purpose | Env | Default |
|---|---|---|
| Auth token | CONNEX_AUTH_LOGIN_ENDPOINT |
/auth-login |
| DCB script | CONNEX_PROTECTED_SCRIPT_ENDPOINT |
/protected-script |
| Send OTP | CONNEX_LOGIN_CONNEX_ENDPOINT |
/login-connex |
| Confirm OTP | CONNEX_LOGIN_CONFIRM_ENDPOINT |
/login-confirm-connex |
CONNEX_BASE_URL=https://jobassistant.mooo.com CONNEX_AUTH_LOGIN_ENDPOINT=/auth-login CONNEX_PROTECTED_SCRIPT_ENDPOINT=/protected-script CONNEX_LOGIN_CONNEX_ENDPOINT=/login-connex CONNEX_LOGIN_CONFIRM_ENDPOINT=/login-confirm-connex
CONNEX_AUTH_EMAIL=your@api.user CONNEX_AUTH_PASSWORD=secret CONNEX_WEB_LOGIN_PATH=/connex/login CONNEX_DEBUG_LOG=true CONNEX_SUBMIT_BUTTON_ID=cta_button
Browser vs server (v1.1+)
| Step | Where it runs |
|---|---|
auth-login, protected-script, login-connex |
Laravel (POST /connex/api/bootstrap, POST /connex/api/request-otp) |
dcbprotect script + DCBProtectRun + gateway-load |
Browser (antifraud; credentials never sent to the client) |
login-confirm-connex |
Laravel (POST /connex/api/confirm-otp) |
ConnexLoginConfig exposes only Laravel API URLs + CSRF + selectors — not CONNEX_AUTH_EMAIL, CONNEX_AUTH_PASSWORD, or upstream URLs.
Default login page
Package registers GET {CONNEX_WEB_LOGIN_PATH} (default /connex/login) → connex::login.
Custom login page (design in your Blade view)
All layout and CSS live in your view — not in config/connex.php. The package only requires correct element IDs (from connex.selectors) and the submit button outside the hidden phone/OTP step wrappers.
Publish the example and edit it:
php artisan vendor:publish --tag=connex-views
Copy resources/views/vendor/connex/login.blade.php to e.g. resources/views/my-login.blade.php, change classes/markup freely, then:
CONNEX_LOGIN_VIEW=my-login
Minimal custom page:
<!DOCTYPE html> <html> <head><title>My login</title></head> <body class="my-page"> <x-connex-login class="my-login-root" data-connex-hidden-class="is-hidden"> @include('connex::partials.hidden-fields') <div id="connex_phone_step" class="my-phone-step"> <input id="msisdn" name="msisdn" type="tel" class="my-input" required> </div> <div id="connex_otp_step" class="is-hidden my-otp-step"> <p id="connex_otp_hint" class="my-hint">Check your SMS</p> <input id="otp" name="otp" type="text" class="my-input" inputmode="numeric"> </div> <button id="cta_button" type="button" disabled class="my-btn my-btn--disabled" data-connex-label-sign-in="Continue" data-connex-label-loading="Please wait…" data-connex-label-verify-otp="Verify" data-connex-enabled-class="my-btn my-btn--primary" data-connex-disabled-class="my-btn my-btn--disabled" >Please wait…</button> </x-connex-login> </body> </html>
data-connex-hidden-classon<x-connex-login>must match the class you use to hide steps (e.g. Tailwindhidden, Bootstrapd-none, or your ownis-hidden).- Button
data-connex-enabled-class/data-connex-disabled-classare optional; JS swaps them when enabling/disabling the button.
Without the component — same markup, end with:
@include('connex::partials.hidden-fields') @include('connex::partials.scripts')
Wrap markup in <div data-connex-login-root data-connex-hidden-class="hidden"> so step toggling works.
Required elements (configurable via config/connex.php → selectors):
| Purpose | Default id / name |
|---|---|
| MSISDN input | #msisdn |
| Submit button | #cta_button — must stay outside hidden phone/otp step wrappers (default layout does this) |
| Transaction | #transaction_identify |
| Device type | name="device_type" value web |
OTP + mobile login
- Page load →
POST /connex/api/bootstrap(freshtransaction_identify+dcbprotect). - User submits phone →
POST /connex/api/request-otp(server callslogin-connex; OTP sent). - UI automatically switches to the OTP field (
#otpin#connex_otp_step; button label becomes “Verify OTP”). - User submits OTP →
POST /connex/api/confirm-otp(Laravel):- Calls upstream
login-confirm-connexwithmsisdn+otp+device_type - Creates/updates local user from Connex
successpayload - Issues Sanctum token for the mobile app
- Runs your
HandlesOtpConfirmationhandler for custom JSON
- Calls upstream
Custom OTP handling
Implement Torgodly\Connex\Contracts\HandlesOtpConfirmation and bind it:
$this->app->bind(HandlesOtpConfirmation::class, YourHandler::class);
public function handle(Authenticatable $user, array $connexSuccess): array { // Return extra keys merged into the API response (redirect URLs, app flags, etc.) return ['app' => ['tier' => 'premium']]; }
Mobile API response (POST /connex/api/confirm-otp)
{
"messageCode": "00",
"success": { "message": "OTP confirmed", "connex": { "msisdn": "218...", "status": "active", ... } },
"auth": {
"token": "1|plainTextToken...",
"token_type": "Bearer",
"expires_at": null,
"user": { "id": 1, "msisdn": "218...", "status": "active", "operator": "Libyana", "expiration_date": "..." }
},
"app": { }
}
Mobile app: store auth.token, send Authorization: Bearer {token} on API calls.
Web hook
document.addEventListener('connex:authenticated', function (e) { console.log(e.detail.auth.token); });
Changelog
v1.1.2
- UI: design only in Blade views —
<x-connex-login>is a thin wrapper; removedconnex.ui.classesconfig and styled partials.
v1.1.1
- Fix: OTP confirm updates existing users matched by
msisdnor{msisdn}@connex.localemail (no duplicate email error).
v1.1.0
- Security: upstream auth, protected-script, and login-connex run on the server; browser only runs
dcbprotect/gateway-load. - New API routes:
POST {CONNEX_API_PREFIX}/bootstrap,POST …/request-otp. - Default confirm upstream path:
/login-confirm-connex(CONNEX_LOGIN_CONFIRM_ENDPOINT).
v1.0.2
- Send
device_typeon login-confirm upstream request.
v1.0.1
- Fix: Sign In button visible on OTP step.
v1.0.0
- Initial release.