Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Singpass Login Laravel Package

accredifysg/singpass-login

Laravel package for SingPass Login, MyInfo, and CorpPass with a FAPI 2.0–style flow: PAR, DPoP, PKCE, and private-key JWT client assertions. Shared services handle discovery, token exchange, and JWE/JWS processing, with thin per-provider controllers.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. The package is structured the way a Laravel TPM would want an identity integration to be structured: a shared FAPI 2.0 layer (FapiAuthenticationService, FapiCallbackService, DPoPService, PARService, TokenExchangeService, JwtService, JwksService, OpenIdDiscoveryService, GetUserInfoService, PKCEService) with thin per-provider controllers for SingPass Login, MyInfo, and CorpPass. That means SingPass, MyInfo, and CorpPass share one hardened choreography instead of three drifting implementations, which materially reduces the security-review surface. The package is event-driven (SingPassSuccessfulLoginEvent, MyInfoDataRetrievedEvent, CorpPassSuccessfulLoginEvent, CorpPassDataRetrievedEvent) with an optional publishable default listener, and everything is env/config-driven across four published config files (ndi.php, singpass-login.php, myinfo.php, corppass-login.php). Modules can be toggled independently, and route paths are configurable, so partial adoption is viable.

Integration feasibility. Mechanically low-friction: composer require, publish config, populate env, decide whether to use the default listener or a custom one. Frontend contract is explicit and modern — auth controllers return { "redirect_url": ... } and expect the browser/SPA to call them with credentials: 'same-origin', then navigate. The /ndi/jwks endpoint and the *_controller config overrides give clean escape hatches. The real work is not code — it's provisioning: SingPass/MyInfo/CorpPass client IDs and redirect URIs, a private JWKS registered with the IdP, and correct SINGPASS_DOMAIN / discovery endpoints per environment.

Technical risk. Four clusters:

  • Vendor/adoption risk. 2 stars, 0 dependents, single publisher (Accredifysg), opportunity score 29.26. This is the only package standing between you and a mandatory national-identity auth path. There is no community to lean on and no visible contributor base. That is a supply-chain risk on your most security-sensitive flow.
  • Key custody. NDI_PRIVATE_JWKS in env implies a long-lived client assertion private key in application config. That is workable but must be reconciled with your secret-management standard (KMS/Secrets Manager, rotation, per-environment separation). DPoP keys appear ephemeral, which is better.
  • Shared-state dependencies. Discovery response caching and state validation imply cache/session backends. On multi-node deployments, a file or array cache silently breaks PAR/callback correlation.
  • Data-quality signal. The stated last release (2026-09-21) is anomalous; verify actual release cadence and whether the repo is actively maintained before committing.

Key questions. What Laravel and PHP versions are supported and tested (11/12, 8.2+)? Is the CI badge real — PHPStan max and coverage are advertised, but is there a runnable test suite and a security disclosure policy? Is the private JWKS expected to be a single static key, and is rotation documented? Where is discovery cached and is that cache driver-agnostic? Does the package ship any persistence/audit layer for MyInfo data, or is retention entirely my responsibility under PDPA? What is the support/escalation path if SingPass changes FAPI requirements — is there a paid relationship with the author?

Integration Approach

Stack fit. Strong for a Laravel monolith or modular monolith already using the web middleware group, session cookies, and Eloquent users keyed by NRIC/FIN. Weakest fit where you use a stateless API-only architecture (no session), a non-Laravel service, or a multi-tenant model requiring per-tenant SingPass clients — all three are solvable but are custom work, not package work.

Migration path. Two scenarios. (a) Greenfield: adopt the package as the sole SingPass path, wire the listener to your user provisioning, done. (b) Replacing a legacy SingPass OIDC/SAML or CorpPass integration: run the package on new routes (e.g. /ndi/sp/login alongside your existing /singpass/login) behind a feature flag, dual-run in staging, then cut over per-flow rather than big-bang. CorpPass is the highest-migration-cost flow because it introduces an entity+actor hierarchy (sub = UEN, act.sub = person) that your data model likely doesn't yet express.

Compatibility considerations. Pin an exact version; do not use a floating constraint on a security-critical dependency. Confirm the package's Laravel version ceiling against your framework upgrade calendar — an auth package lagging a Laravel major blocks your whole upgrade. Verify the web middleware group is the right one for your SPA (CORS vs. same-origin), and that the /ndi/* prefix doesn't collide with existing routes or your WAF/reverse-proxy rules.

Sequencing.

  1. Spike (1–2 weeks): install in a throwaway Laravel app, generate a JWKS keypair, register with the SingPass staging environment, complete a full SingPass Login roundtrip plus one MyInfo nationality/dob fetch. This validates the discovery-cache path and proves the JWKS endpoint is publicly reachable.
  2. Security review: confirm key handling, state/PKCE enforcement, token scope validation (shouldCallUserInfo failing loudly on malformed tokens is a good sign), and that NRIC is only requested when user.identity is genuinely needed.
  3. Listener + domain model: implement SingPassSuccessfulLoginEvent handling against your User model; migrate from the deprecated SingPassUser::getNric() to the nric property immediately. For CorpPass, model entity/actor explicitly.
  4. Frontend contract: update the SPA to call the bootstrap endpoint with same-origin credentials and follow redirect_url; ensure the failure redirect (NDI_FAILURE_REDIRECT_URL or the login route fallback) renders a sane error state.
  5. Staging soak → production, flow by flow: SingPass Login first, then MyInfo, then CorpPass.

Operational Impact

Maintenance. The package is small and largely declarative, so day-to-day maintenance is low — but it is a security dependency, which means it needs an owner, a version pin, and a review cadence tied to SingPass/CorpPass specification changes (FAPI 2.0 profiles do evolve; the README's insistence on a pushed_authorization_request_endpoint is already a recent-generation requirement). Budget for a fork or vendor patch if upstream goes quiet — the code volume is small enough that forking is realistic.

Support. No commercial support is implied. Assume self-support, and plan for a named internal owner who understands OAuth/OIDC and DPoP. If the organisation cannot staff that, the vendor risk becomes existential for this flow. Establish a written escalation path before production, and consider a paid engagement with the author for guaranteed response.

Scaling. The flow is request/redirect-bound, not compute-bound, so throughput is not the constraint — the IdP's rate limits and your cache backend are. Enable NDI_LOGS_ENABLED selectively and with redaction (tokens, NRIC, MyInfo payloads must never land in logs). Cache discovery responses in a shared store (Redis) with sensible TTLs. The /ndi/jwks endpoint is public and cheap; put it behind your CDN and monitor it as a health signal, since IdP token validation depends on it.

Failure modes to instrument. (1) Discovery cache poisoned or stale → pushed_authorization_request_endpoint missing → all logins fail; monitor at the discovery-cache layer, not just at the login endpoint. (2) Clock skew → DPoP/JWT assertion rejection; ensure NTP across nodes. (3) Key mismatch or JWKS not yet propagated at the IdP → blanket token exchange failures after rotation; rotate with overlap. (4) state mismatch on multi-node with a non-shared session/cache driver — insidious, intermittent, hard to reproduce. (5) Scope mismatch: MyInfo requests outside available_scopes are rejected by the package; CorpPass authinfo/tpauthinfo requested without UserInfo handling yields an event you don't consume. (6) Malformed access token throwing UserInfoRequestException — deliberately loud, so alert on it rather than swallowing it. (7) NRIC absent because user.identity wasn't requested — this surfaces as a listener-level exception; make the error message actionable.

Ramp-up. Developer ramp-up is short — a day to read the README and trace one flow, since the architecture is well documented and the config surface is legible. Organisational ramp-up is longer: someone must own SingPass test-environment access, corporate key custody, the PDPA/consent story for MyInfo data retention, and the incident runbook for "nobody can log in." Treat the first integration as a 4–6 week effort with a security review gate, not a sprint ticket, and do not adopt it without an exit plan given the 0-dependents dependency profile.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
oxygen/data
oxygen/core
jengo/base
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin
artisan-build/community-prompts
vleroy/smart
ayles-software/laravel-australian-public-holidays
cboxdk/laravel-id-spatie
cboxdk/laravel-id-billing
cboxdk/laravel-id-billing-bridge
simple-as-fuck/php-performance-log
hsluv/hsluv
seampact/codegen
seampact/hooks
seampact/ir
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table