ids/login

IDS authentication package

Maintainers

Package info

repo.fnbpos.net/ids/ids-login

pkg:composer/ids/login

Transparency log

Statistics

Installs: 970

Dependents: 0

Suggesters: 0

v4.2.3 2026-08-28 00:33 UTC

README

Laravel authentication package for IDS (Identity Service). Provides login, registration, QR code authentication, account management, and UI customization — all backed by the IDS API.

Requires: PHP 8.2+ | Laravel 11 or 12

Installation

composer require ids/login

Then run the interactive setup wizard:

php artisan ids:install

This will prompt you for your IDS credentials, feature preferences, and automatically configure your .env, publish config/migrations/assets, and run migrations.

Manual Installation

If you prefer manual setup:

# Publish config
php artisan vendor:publish --tag=ids-login-config

# Publish migrations
php artisan vendor:publish --tag=ids-login-migrations

# Publish assets (CSS, JS, phone input plugin)
php artisan vendor:publish --tag=ids-login-assets

# Run migrations
php artisan migrate

Configuration

After installation, configure via .env:

# Required
IDS_HOST=https://your-ids-server.com
IDS_UDID=your-udid
IDS_PASSWORD_CLIENT_ID=your-client-id
IDS_PASSWORD_SECRET=your-client-secret
IDS_CLIENT_CREDENTIAL_CLIENT_ID=your-cc-client-id
IDS_CLIENT_CREDENTIAL_SECRET=your-cc-secret
IDS_LOGIN_REDIRECT_TO=/home

# Optional: space-separated OAuth scopes to request at login (e.g. "nric:read").
# Only granted if the IDS server allows them for your client.
IDS_OAUTH_SCOPES=

# Feature Flags (all optional)
IDS_QR_LOGIN_ENABLED=true
IDS_ACCOUNT_ENABLED=true
IDS_USE_LIVEWIRE=false
IDS_RECAPTCHA_ENABLED=false
IDS_LOGIN_RESTRICTED=false
IDS_LOGIN_ALLOW_LOCAL_AUTH=false

# OTP delivery: dial codes that may receive OTP via SMS (comma-separated).
# All other countries get WhatsApp only. Use '*' to allow SMS everywhere.
IDS_OTP_SMS_COUNTRY_CODES=+60

# QR Login (required if QR enabled)
IDS_QR_REDIRECT_ID=your-redirect-id

# QR realtime via WebSocket (optional — QR falls back to 3s polling without it).
# Uses the app's standard Laravel broadcasting config. Reverb:
BROADCAST_CONNECTION=reverb
REVERB_APP_ID=
REVERB_APP_KEY=
REVERB_APP_SECRET=
REVERB_HOST=broadcast.example.com
REVERB_PORT=443
REVERB_SCHEME=https
# ...or hosted Pusher instead:
# BROADCAST_CONNECTION=pusher
# PUSHER_APP_ID= / PUSHER_APP_KEY= / PUSHER_APP_SECRET= / PUSHER_APP_CLUSTER=ap1

# Recaptcha (required if recaptcha enabled)
RECAPTCHA_SITE_KEY=
RECAPTCHA_SECRET_KEY=

Full configuration reference: config/ids-login.php

Features

Authentication

  • Two-step phone-first login — enter a phone number first, then choose how to login: password, one-time code (SMS / WhatsApp / authenticator app) or QR code
  • Password login via IDS OAuth (password grant)
  • OTP login via the IDS otp grant — logging in with a one-time code also marks the phone number verified
  • QR code login with real-time WebSocket updates via Reverb or Pusher (toggleable, polling fallback; pusher-js is bundled)
  • Local auth fallback when IDS server is unreachable
  • Phone verification post-login flow
  • Registration with OTP verification
  • Password reset with OTP verification
  • OTP via SMS or WhatsApp — SMS is offered only for countries in IDS_OTP_SMS_COUNTRY_CODES (default: Malaysia); all other countries receive OTP via WhatsApp, enforced server-side
  • Recaptcha support (toggleable)

Two-Step Login Flow

GET /login is the phone step. Submitting the number calls the IDS /api/login/check endpoint; when the account exists the user picks a login method. Flow state is kept in the ids_login session under the keys country_code, phone_no, phone_full, name, channel and otp_sent_at; ids.login.reset clears it. OTP delivery honours IDS_OTP_SMS_COUNTRY_CODES (blocked countries fall back to WhatsApp) and the resend button has a 60s cooldown. An unverified account that logs in with a password is redirected to the OTP step, since completing an OTP login verifies the phone.

Strings live under the login.* keys of the ids::ids lang file (en / ms / zh).

Server requirement: the IDS identity-server must support grant_type=otp on /oauth/token plus the /api/login/check and /api/login/request_otp endpoints (identity-server feat/two-step-login or later).

Account Management (toggleable)

  • Update display name, email, phone, password, language, avatar
  • OTP verification for email and phone changes
  • Profile picture upload

UI Customization

  • Database-driven settings via /ids-settings
  • Custom logo, background, primary color, dark mode
  • Configurable layout alignment

Multi-Tenancy

Supports Stancl Tenancy with two modes:

# In config/ids-login.php
'tenancy' => [
    'enabled' => true,
    'mode' => 'multi_db',   // or 'single_db'
    'middleware' => ['tenant'],
],
  • multi_db — separate database per tenant (publish tenant migrations)
  • single_db — shared database with tenant_id column scoping

Views

Ships with Blade views (default) and optional Livewire components.

Blade (default)

Works out of the box. Vanilla JS, no jQuery. To customize:

php artisan vendor:publish --tag=ids-login-views

Livewire (opt-in)

Set IDS_USE_LIVEWIRE=true in .env. Requires livewire/livewire ^3.0:

composer require livewire/livewire

Components: ids-login-flow (two-step login), ids-login-form (legacy single-step), ids-register-form, ids-forgot-password-form, ids-account-manager

In Livewire mode the Blade views stay registered as a fallback, so pages without a Livewire counterpart (e.g. the QR step) keep working.

Routes

All routes are prefixed with ids.:

NameMethodURI
loginGET/login (phone step)
ids.login.phonePOST/login/phone
ids.login.methodGET/login/method
ids.login.passwordGET/login/password
ids.login.submitPOST/login
ids.login.otpGET/login/otp
ids.login.otp.verifyPOST/login/otp
ids.login.otp.channelPOST/login/otp/channel
ids.login.otp.resendPOST/login/otp/resend
ids.login.qrGET/login/qr
ids.login.resetGET/login/reset
ids.logoutPOST/logout
ids.registerGET/register
ids.register.submitPOST/register
ids.register.otpGET/register/otp
ids.register.verify-otpPOST/register/verify-otp
ids.password.requestGET/password/reset
ids.password.otpPOST/password/reset/otp
ids.password.resetPOST/password/reset
ids.phone.verifyGET/phone-verification
ids.qr.callbackPOST/qr-login/callback
ids.qr.statusGET/qr-login/status
ids.accountGET/my-account
ids.account.namePOST/account/name
ids.account.phonePOST/account/phone
ids.account.emailPOST/account/email
ids.account.passwordPOST/account/password
ids.account.languagePOST/account/language
ids.account.avatarPOST/account/avatar
ids.settingsGET/ids-settings
ids.settings.storePOST/ids-settings

QR and Account routes are only registered when their feature flags are enabled.

User Model

The package adds these columns to your users table:

ColumnTypeDescription
ids_idstringIDS system user ID
ids_hashstringEncrypted IDS identifier
phone_nostringFull phone number with country code (e.g. +60129718420)
country_codestringCountry code (e.g. +60)
country_phone_nostringLocal phone number without country code (e.g. 129718420)
is_activebooleanUser active status

Configure column mapping in config/ids-login.php under attributes if your column names differ.

Updating

composer update ids/login
php artisan ids:update

Translations

Supports English, Malay (ms), and Chinese (zh). Publish to customize:

php artisan vendor:publish --tag=ids-login-translations

Upgrading to v4.1

  • GET /login now renders the phone step instead of the combined phone + password form. The login and ids.login.submit route names are unchanged.
  • POST /login (ids.login.submit) now only accepts password; the phone number comes from the phone-step session. Direct posts without completing the phone step redirect back to /login.
  • The QR panel moved from the login page to its own /login/qr step.
  • The flat ids::ids.login lang key became the nested login.* array — if you published translations, republish or merge.
  • Requires an identity-server with the otp grant and login-check endpoints (see the server requirement note above).

Upgrading from v3

See the Migration Guide in the design spec.

Key breaking changes:

  • PHP 8.2+ required (was 8.1+)
  • Config keys restructured (run php artisan ids:install to regenerate)
  • Route names now prefixed with ids.
  • Account routes changed from /ajax/update/* to /account/*
  • jQuery removed — views use vanilla JS
  • All vplus references removed

License

Proprietary - IDS