PHPackages                             accredifysg/singpass-login - 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. accredifysg/singpass-login

ActiveLaravel-package[Authentication &amp; Authorization](/categories/authentication)

accredifysg/singpass-login
==========================

A Laravel package for integrating SingPass Login and MyInfo

v3.0.1(3w ago)12.4k2MITPHPPHP ^8.2CI passing

Since Feb 24Pushed 4w ago1 watchersCompare

[ Source](https://github.com/Accredifysg/SingPass-Login)[ Packagist](https://packagist.org/packages/accredifysg/singpass-login)[ Docs](https://github.com/accredifysg/singpass-login)[ RSS](/packages/accredifysg-singpass-login/feed)WikiDiscussions master Synced 3w ago

READMEChangelog (8)Dependencies (38)Versions (31)Used By (0)

SingPass-Login
==============

[](#singpass-login)

[![badge.svg](coverage/badge.svg)](coverage/badge.svg) [![](https://camo.githubusercontent.com/3d63a7e6e05ca0dafbdd1cb2da881539a5ccd543deb25f6d8d1174cd11815bfe/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048505374616e2d6c6576656c2532306d61782d627269676874677265656e2e7376673f7374796c653d666c6174)](https://camo.githubusercontent.com/3d63a7e6e05ca0dafbdd1cb2da881539a5ccd543deb25f6d8d1174cd11815bfe/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048505374616e2d6c6576656c2532306d61782d627269676874677265656e2e7376673f7374796c653d666c6174)

PHP Laravel Package for **SingPass Login**, **MyInfo**, and **CorpPass**. The authorization flow follows **FAPI 2.0–style** integration: **Pushed Authorization Requests (PAR)** with **DPoP** on the PAR, token, and UserInfo calls, **PKCE**, and private-key **JWT client assertions**. Your OpenID Provider metadata (discovery) must expose a `pushed_authorization_request_endpoint`; the package validates this when caching discovery.

[Official SingPass Login Docs](https://api.singpass.gov.sg/library/login/developers/overview-at-a-glance) · [Official CorpPass Docs](https://docs.corppass.gov.sg/technical-specifications/corppass-authorization-api-fapi-2.0/integration-guide)

Architecture
------------

[](#architecture)

The package separates **shared FAPI 2.0 choreography** from **provider-specific logic**:

- **Shared layer** (`FapiAuthenticationService`, `FapiCallbackService`) handles discovery, PAR, DPoP, PKCE, token exchange, and JWE/JWS processing.
- **Thin controllers** for each flow (SingPass Login, MyInfo, CorpPass) delegate to the shared layer and fire provider-specific events.
- A `ProviderConfig` DTO encapsulates per-provider configuration (client ID, redirect URI, cache key, scopes).

```
┌─────────────────────────────────────────────────────────────────┐
│                  Shared FAPI 2.0 Services                       │
│  FapiAuthenticationService · FapiCallbackService · DPoPService  │
│  PARService · TokenExchangeService · JwtService · JwksService   │
│  OpenIdDiscoveryService · GetUserInfoService · PKCEService      │
└──────────┬──────────────────┬──────────────────┬────────────────┘
           │                  │                  │
    ┌──────┴──────┐   ┌──────┴──────┐   ┌──────┴──────┐
    │  SingPass   │   │   MyInfo    │   │  CorpPass   │
    │  Login +    │   │  Login +    │   │  Login +    │
    │  Callback   │   │  Callback   │   │  Callback   │
    └─────────────┘   └─────────────┘   └─────────────┘

```

Installation
------------

[](#installation)

You can install the package via composer:

```
composer require accredifysg/singpass-login
```

Publish the config files:

```
php artisan vendor:publish --provider="Accredifysg\SingPassLogin\SingPassLoginServiceProvider" --tag="config"
```

This publishes four config files:

FilePurpose`config/ndi.php`Shared NDI infrastructure (JWKS, signing, DPoP, logging)`config/singpass-login.php`SingPass Login credentials, routes, listener`config/myinfo.php`MyInfo credentials, routes, scopes`config/corppass-login.php`CorpPass credentials, routes, listener, scopesOptionally, publish the default listener that logs in a user on `SingPassSuccessfulLoginEvent`:

```
php artisan vendor:publish --provider="Accredifysg\SingPassLogin\SingPassLoginServiceProvider" --tag="listener"
```

Configuration
-------------

[](#configuration)

### Shared NDI (`config/ndi.php`)

[](#shared-ndi-configndiphp)

JWKS, signing keys, DPoP algorithm, and logging — shared across all providers.

```
NDI_SIGNING_KID=
NDI_JWKS=
NDI_PRIVATE_JWKS=

# FAPI 2.0 / DPoP — ephemeral key algorithm for DPoP proofs (ES256, ES384, or ES512; default ES256)
NDI_DPOP_SIGNING_ALGORITHM=ES256

# Diagnostic logging (disabled by default)
NDI_LOGS_ENABLED=false

```

### SingPass Login (`config/singpass-login.php`)

[](#singpass-login-configsingpass-loginphp)

```
SINGPASS_CLIENT_ID=
SINGPASS_REDIRECT_URI=
# Must match the `issuer` from the FAPI discovery endpoint, e.g.
# Staging: https://stg-id.singpass.gov.sg/fapi
# Production: https://id.singpass.gov.sg/fapi
SINGPASS_DOMAIN=
# Must be the FAPI discovery URL (includes pushed_authorization_request_endpoint), e.g.
# Staging: https://stg-id.singpass.gov.sg/fapi/.well-known/openid-configuration
# Production: https://id.singpass.gov.sg/fapi/.well-known/openid-configuration
SINGPASS_DISCOVERY_ENDPOINT=

# Login app authentication context (see SingPass integration guide)
SINGPASS_AUTH_CONTEXT_TYPE=APP_AUTHENTICATION_DEFAULT
# SINGPASS_AUTH_CONTEXT_MESSAGE=

# Default Listener
SINGPASS_USE_DEFAULT_LISTENER=true

```

### MyInfo (`config/myinfo.php`)

[](#myinfo-configmyinfophp)

```
MYINFO_CLIENT_ID=
MYINFO_REDIRECT_URI=
MYINFO_DISCOVERY_ENDPOINT=
MYINFO_DOMAIN=

```

### CorpPass (`config/corppass-login.php`)

[](#corppass-configcorppass-loginphp)

```
CORPPASS_CLIENT_ID=
CORPPASS_REDIRECT_URI=
CORPPASS_DOMAIN=
CORPPASS_DISCOVERY_ENDPOINT=

# Default Listener (disabled by default)
CORPPASS_USE_DEFAULT_LISTENER=false

# Login app authentication context
CORPPASS_AUTH_CONTEXT_TYPE=APP_AUTHENTICATION_DEFAULT

```

### Enabling / Disabling Modules

[](#enabling--disabling-modules)

Each flow can be independently toggled via environment variables. All are enabled by default.

VariableConfig fileDefaultControls`SINGPASS_USE_DEFAULT_ROUTES``singpass-login.php``true`SingPass Login routes`MYINFO_USE_DEFAULT_ROUTES``myinfo.php``true`MyInfo routes`CORPPASS_USE_DEFAULT_ROUTES``corppass-login.php``true`CorpPass routesThe JWKS endpoint (`/ndi/jwks`) is always registered regardless of these flags, as it is shared across all providers.

Route URLs are also configurable:

```
SINGPASS_AUTHENTICATION_URL=/ndi/sp/login
SINGPASS_CALLBACK_URL=/ndi/sp/callback
MYINFO_AUTHENTICATION_URL=/ndi/mi/initiate
MYINFO_CALLBACK_URL=/ndi/mi/callback
NDI_JWKS_URL=/ndi/jwks
CORPPASS_AUTHENTICATION_URL=/ndi/cp/login
CORPPASS_CALLBACK_URL=/ndi/cp/callback

```

Routes
------

[](#routes)

The package registers the following routes under the `web` middleware group:

RouteControllerNamePurpose`GET /ndi/jwks``GetJwksEndpointController``singpass.jwks`Expose your application's JWKS (always active)`GET /ndi/sp/login``SingPass\LoginController``singpass.login`Initiate SingPass Login`GET /ndi/sp/callback``SingPass\LoginCallbackController``singpass.callback`Handle SingPass Login callback`GET /ndi/mi/initiate``MyInfo\MyInfoController``myinfo.login`Initiate MyInfo flow`GET /ndi/mi/callback``MyInfo\MyInfoCallbackController``myinfo.callback`Handle MyInfo callback`GET /ndi/cp/login``CorpPass\LoginController``corppass.login`Initiate CorpPass Login`GET /ndi/cp/callback``CorpPass\LoginCallbackController``corppass.callback`Handle CorpPass callbackEach auth controller returns **JSON** with a `redirect_url` the browser should navigate to. The callback controllers handle the OAuth redirect, validate `state` (CSRF), exchange the code using DPoP, and fire the appropriate event.

If you prefer custom controllers, override the `*_controller` keys in the respective config file.

SingPass Login
--------------

[](#singpass-login-1)

### Starting a Login

[](#starting-a-login)

`GET /ndi/sp/login` returns `200` JSON: `{ "redirect_url": "..." }`. The browser (or SPA) should request that URL with **same-origin credentials** so the session cookie is sent, then navigate to `redirect_url`.

Optional query parameters: `authentication_context_type` and `authentication_context_message` override config defaults for that request. See the [SingPass authorization request documentation](https://docs.developer.singpass.gov.sg/docs/technical-specifications/integration-guide/1.-authorization-request#possible-authentication_context_type-values) for valid values.

```
async function startSingPassLogin(scopes) {
  const qs = new URLSearchParams({ scopes: scopes.join(',') });
  const res = await fetch(`/ndi/sp/login?${qs}`, {
    credentials: 'same-origin',
    headers: { Accept: 'application/json' },
  });
  if (!res.ok) throw new Error('Login bootstrap failed');
  const { redirect_url } = await res.json();
  window.location.assign(redirect_url);
}

// Login scopes only (data returned in ID token)
await startSingPassLogin(['openid', 'name', 'email', 'mobileno']);
```

### Listener

[](#listener)

If you published the default listener, edit it to map your user retrieval via NRIC. Read the NRIC/FIN from the readonly **`nric`** property (populated from `sub_attributes.identity_number` when the **`user.identity`** scope is requested). **`SingPassUser::getNric()` is deprecated** and will be removed in a future major release; migrate listeners to `$singPassUser->nric`.

```
public function handle(SingPassSuccessfulLoginEvent $event): void
{
    $singPassUser = $event->getSingPassUser();
    $nric = $singPassUser->nric;

    if (! $nric) {
        // NRIC is only available when the 'user.identity' scope is requested.
        throw new SingPassLoginException;
    }

    $user = User::where('nric', '=', $nric)->first();

    if (! $user) {
        throw new SingPassLoginException;
    }

    Auth::login($user);
}
```

If you prefer a custom listener, set `SINGPASS_USE_DEFAULT_LISTENER=false` and replace `listener_class` in `singpass-login.php`.

MyInfo Integration
------------------

[](#myinfo-integration)

MyInfo has its own dedicated routes (`/ndi/mi/initiate` and `/ndi/mi/callback`), config file (`config/myinfo.php`), and separate client credentials (`MYINFO_CLIENT_ID` / `MYINFO_REDIRECT_URI`).

### Starting a MyInfo Flow

[](#starting-a-myinfo-flow)

```
async function startMyInfo(scopes) {
  const qs = new URLSearchParams({ scopes: scopes.join(',') });
  const res = await fetch(`/ndi/mi/initiate?${qs}`, {
    credentials: 'same-origin',
    headers: { Accept: 'application/json' },
  });
  if (!res.ok) throw new Error('MyInfo bootstrap failed');
  const { redirect_url } = await res.json();
  window.location.assign(redirect_url);
}

await startMyInfo(['openid', 'name', 'email', 'mobileno', 'nationality', 'dob']);
```

### How It Works

[](#how-it-works)

The MyInfo callback controller calls the UserInfo endpoint (with DPoP) to retrieve the requested data and emits `MyInfoDataRetrievedEvent`. Internally, `FapiCallbackService` uses `shouldCallUserInfo()` with the provider's `loginScopes` to determine the correct path: if the access token contains only login scopes, the ID token path is taken; otherwise the UserInfo endpoint is called.

Scope comparison reads the access token as an unverified JWT and expects a standard three-part compact JWT whose payload JSON includes a string `scope` claim (space-separated scope values, per OIDC). If the token is not a JWT, the payload cannot be decoded, or `scope` is missing or not a string, `UserInfoRequestException` is thrown instead of assuming `openid` only, so malformed tokens fail visibly during callback processing.

### Handling MyInfo Data

[](#handling-myinfo-data)

```
use Accredifysg\SingPassLogin\Events\MyInfoDataRetrievedEvent;

class MyInfoDataRetrievedListener
{
    public function handle(MyInfoDataRetrievedEvent $event): void
    {
        $myInfoData = $event->getMyInfoData();
        $state = $event->getState();

        $user->update([
            'name' => $myInfoData['name']['value'] ?? null,
            'email' => $myInfoData['email']['value'] ?? null,
            'mobile' => $myInfoData['mobileno']['value'] ?? null,
            'nationality' => $myInfoData['nationality']['value'] ?? null,
            'date_of_birth' => $myInfoData['dob']['value'] ?? null,
        ]);
    }
}
```

### Available MyInfo Scopes

[](#available-myinfo-scopes)

For the complete list, see the [MyInfo Data Catalog](https://docs.developer.singpass.gov.sg/docs/data-catalog-myinfo/catalog). The package validates requested scopes against the `available_scopes` in `config/myinfo.php`.

CorpPass Integration
--------------------

[](#corppass-integration)

CorpPass uses the same FAPI 2.0 flow as SingPass, with a hierarchical entity + actor identity model. The entity represents the company/organisation (`sub`), and the actor represents the individual user (`act.sub`).

### Starting a CorpPass Login

[](#starting-a-corppass-login)

```
async function startCorpPassLogin(scopes) {
  const qs = new URLSearchParams({ scopes: scopes.join(',') });
  const res = await fetch(`/ndi/cp/login?${qs}`, {
    credentials: 'same-origin',
    headers: { Accept: 'application/json' },
  });
  if (!res.ok) throw new Error('CorpPass login bootstrap failed');
  const { redirect_url } = await res.json();
  window.location.assign(redirect_url);
}

// Login scopes only (entity + actor data in ID token)
await startCorpPassLogin(['openid', 'entity.identity', 'user.identity', 'user.name']);

// With UserInfo scopes (authorization data via UserInfo endpoint)
await startCorpPassLogin(['openid', 'entity.identity', 'user.identity', 'authinfo']);
```

### CorpPass Scopes

[](#corppass-scopes)

ScopeSourceDescription`openid`RequiredCore OIDC scope`entity.identity`ID tokenEntity type, registration number, COI`entity.basic_profile.name`ID tokenEntity name`entity.basic_profile.uen_status`ID tokenEntity UEN status`user.identity`ID tokenActor identity number (NRIC/FIN), COI`user.name`ID tokenActor name`user.corppass.email`ID tokenActor CorpPass email`authinfo`UserInfoAuthorization info for the entity`tpauthinfo`UserInfoThird-party authorization info### Handling CorpPass Events

[](#handling-corppass-events)

The CorpPass callback controller fires up to two events:

- **`CorpPassSuccessfulLoginEvent`** — Always fired when an ID token payload is present. Carries a `CorpPassUser` model.
- **`CorpPassDataRetrievedEvent`** — Fired when UserInfo scopes (`authinfo`, `tpauthinfo`) were requested. Carries the authorization data array.

```
use Accredifysg\SingPassLogin\Events\CorpPassSuccessfulLoginEvent;

class CorpPassLoginListener
{
    public function handle(CorpPassSuccessfulLoginEvent $event): void
    {
        $corpPassUser = $event->getCorpPassUser();

        // Entity (company/organisation)
        $entityId = $corpPassUser->getEntityId();       // UEN
        $entityName = $corpPassUser->getEntityName();

        // Actor (individual user)
        $nric = $corpPassUser->getIdentityNumber();      // NRIC/FIN (requires user.identity scope)
        $name = $corpPassUser->getName();                // Requires user.name scope

        // Look up or create the user in your system
        $user = User::firstOrCreate(
            ['corppass_entity_id' => $entityId, 'nric' => $nric],
            ['name' => $name, 'entity_name' => $entityName],
        );

        Auth::login($user);
    }
}
```

```
use Accredifysg\SingPassLogin\Events\CorpPassDataRetrievedEvent;

class CorpPassDataListener
{
    public function handle(CorpPassDataRetrievedEvent $event): void
    {
        $data = $event->getCorpPassData();

        // Authorization data from the UserInfo endpoint
        $authInfo = $data['auth_info'] ?? [];
        $tpAuthInfo = $data['tp_auth_info'] ?? [];
    }
}
```

### Registering CorpPass Listeners

[](#registering-corppass-listeners)

Configure the built-in listener via `corppass-login.php`:

```
'use_default_listener' => true,
'listener_class' => \App\Listeners\CorpPassLoginListener::class,
```

Or register manually in your `EventServiceProvider`:

```
protected $listen = [
    CorpPassSuccessfulLoginEvent::class => [
        CorpPassLoginListener::class,
    ],
    CorpPassDataRetrievedEvent::class => [
        CorpPassDataListener::class,
    ],
];
```

Event Flow Summary
------------------

[](#event-flow-summary)

FlowInitiation RouteCallback RouteEventsSingPass Login`/ndi/sp/login``/ndi/sp/callback``SingPassSuccessfulLoginEvent`MyInfo`/ndi/mi/initiate``/ndi/mi/callback``MyInfoDataRetrievedEvent`CorpPass`/ndi/cp/login``/ndi/cp/callback``CorpPassSuccessfulLoginEvent`, `CorpPassDataRetrievedEvent`Diagnostic Logging
------------------

[](#diagnostic-logging)

Set `NDI_LOGS_ENABLED=true` in your `.env` to enable detailed logging of every step in the authentication flow. All log entries are prefixed with `[SingPass]` and sensitive values (`client_assertion`, `code_verifier`, `id_token`, `access_token`) are automatically redacted.

Logged steps include:

StepInfo loggedOpenID DiscoveryEndpoint, cached issuer, PAR endpointPAR RequestEndpoint, request params (redacted), `request_uri` on successAuth InitiationClient ID, redirect URI, scopes, state, session IDCallback ValidationSession ID match, state lookup, missing session data detailsToken ExchangeEndpoint, status, error details on failureJWE / JWSDecryption and signature verification stepsID Token ClaimsExpected vs actual `aud` and `iss` on verification failureJWKSFetch endpoint, success/failureUserInfoEndpoint, JWE decryption, JWT verificationThis is particularly useful for diagnosing session issues (mismatched session IDs between login and callback), issuer/audience mismatches, and PAR rejections.

Upgrading from pre–FAPI 2.0 versions
------------------------------------

[](#upgrading-from-prefapi-20-versions)

- The login route returns **JSON** with `redirect_url`; update clients to `fetch` (with credentials) then navigate.
- Ensure your app uses **session**-backed routes (default `web` middleware).
- Discovery metadata must include **`pushed_authorization_request_endpoint`**.
- Review `login_scopes` in `singpass-login.php` and `available_scopes` in `myinfo.php`.
- MyInfo now has **dedicated routes** (`/ndi/mi/initiate` and `/ndi/mi/callback`) and its own config file (`config/myinfo.php`) instead of sharing the login route and config.
- Configuration has been split into four files: `ndi.php` (shared), `singpass-login.php`, `myinfo.php`, and `corppass-login.php`. Several environment variables have been renamed (see Configuration section).
- The old `SingPassLoginFacade` and `SingPassLoginInterface` have been removed. If you were calling `SingPassLogin::handleCallback()` directly, the logic is now internal to the callback controllers.
- Exceptions have been renamed: `SingPassGetEndpointException` → `AuthFlowException`, `SingPassAuthenticationErrorException` → `AuthenticationErrorException`, `SingPassTokenException` → `TokenExchangeException`, `SingPassJwksException` → `JwksException`.
- Services have been renamed: `SingPassJwtService` → `JwtService`, `GetSingPassTokenService` → `TokenExchangeService`, `GetSingPassJwksService` → `JwksService`.
- **`SingPassUser::getNric()`** is deprecated; use the readonly **`nric`** property on `SingPassUser` instead.

Exceptions
----------

[](#exceptions)

```
use Accredifysg\SingPassLogin\Exceptions\AuthFlowException;
use Accredifysg\SingPassLogin\Exceptions\AuthenticationErrorException;
use Accredifysg\SingPassLogin\Exceptions\JwtPayloadException;
use Accredifysg\SingPassLogin\Exceptions\JweDecryptionFailedException;
use Accredifysg\SingPassLogin\Exceptions\JwksInvalidException;
use Accredifysg\SingPassLogin\Exceptions\JwksException;
use Accredifysg\SingPassLogin\Exceptions\JwtDecodeFailedException;
use Accredifysg\SingPassLogin\Exceptions\OpenIdDiscoveryException;
use Accredifysg\SingPassLogin\Exceptions\PushedAuthorizationRequestException;
use Accredifysg\SingPassLogin\Exceptions\SingPassLoginException;
use Accredifysg\SingPassLogin\Exceptions\TokenExchangeException;
use Accredifysg\SingPassLogin\Exceptions\MissingConfigException;
use Accredifysg\SingPassLogin\Exceptions\UserInfoRequestException;
use Accredifysg\SingPassLogin\Exceptions\UserInfoDecryptionException;
use Accredifysg\SingPassLogin\Exceptions\UserInfoVerificationException;
```

### Configuration Exceptions

[](#configuration-exceptions)

- **`MissingConfigException`**: A required config value (e.g. `singpass-login.client_id`) is `null`. Thrown by `ProviderConfig` factory methods with a message identifying the missing key.

### FAPI / PAR Exceptions

[](#fapi--par-exceptions)

- **`PushedAuthorizationRequestException`**: The PAR endpoint returned an error or an invalid response (includes OAuth error codes when provided).
- **`AuthenticationErrorException`**: The provider returned an OAuth error to the callback (`error` / `error_description` query parameters).
- **`AuthFlowException`**: The callback request was missing required parameters, failed CSRF/session validation, or the ID token payload was invalid.

### Token / JWT Exceptions

[](#token--jwt-exceptions)

- **`TokenExchangeException`**: The token endpoint returned an error, an unparseable response, or was missing `id_token`.
- **`JwtPayloadException`**: The decoded ID token payload failed validation (e.g. missing `sub` claim).
- **`JweDecryptionFailedException`** / **`JwtDecodeFailedException`**: JWE decryption or JWS verification of the ID token failed.
- **`JwksException`** / **`JwksInvalidException`**: JWKS retrieval or parsing failed.
- **`OpenIdDiscoveryException`**: OpenID discovery endpoint returned invalid or incomplete configuration.

### UserInfo Exceptions

[](#userinfo-exceptions)

- **`UserInfoRequestException`**: The UserInfo HTTP request failed, **or** the access token could not be inspected for scopes before choosing the ID token vs UserInfo path (invalid JWT shape, undecodable payload, missing or non-string `scope` claim). Callback handling treats these as hard failures rather than silently defaulting scopes.
- **`UserInfoDecryptionException`**: The UserInfo JWE token decryption failed.
- **`UserInfoVerificationException`**: The UserInfo JWS token verification failed.

###  Health Score

49

—

FairBetter than 94% of packages

Maintenance94

Actively maintained with recent releases

Popularity19

Limited adoption so far

Community13

Small or concentrated contributor base

Maturity61

Established project with proven stability

 Bus Factor1

Top contributor holds 53% 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 ~57 days

Recently: every ~87 days

Total

9

Last Release

27d ago

Major Versions

v1.3.0 → v2.0.02025-12-01

v2.0.1 → v3.0.02026-04-17

### Community

Maintainers

![](https://www.gravatar.com/avatar/baf5a0854c8d40389bb8d2177472f8d5d2fa063ec1a57064df36a9b819fac868?d=identicon)[skydudie](/maintainers/skydudie)

---

Top Contributors

[![skydudie](https://avatars.githubusercontent.com/u/28289296?v=4)](https://github.com/skydudie "skydudie (79 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (63 commits)")[![abbavivek](https://avatars.githubusercontent.com/u/101383853?v=4)](https://github.com/abbavivek "abbavivek (6 commits)")[![rezaramadhan](https://avatars.githubusercontent.com/u/15650702?v=4)](https://github.com/rezaramadhan "rezaramadhan (1 commits)")

---

Tags

corppasslaravelmyinfosingpasssingpass-loginlaravelloginMyInfoSingPass

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/accredifysg-singpass-login/health.svg)

```
[![Health](https://phpackages.com/badges/accredifysg-singpass-login/health.svg)](https://phpackages.com/packages/accredifysg-singpass-login)
```

###  Alternatives

[spatie/laravel-permission

Permission handling for Laravel 12 and up

12.9k98.0M1.3k](/packages/spatie-laravel-permission)[spatie/laravel-health

Monitor the health of a Laravel application

87411.3M153](/packages/spatie-laravel-health)[overtrue/socialite

A collection of OAuth 2 packages.

1.4k5.6M90](/packages/overtrue-socialite)[auth0/login

Auth0 Laravel SDK. Straight-forward and tested methods for implementing authentication, and accessing Auth0's Management API endpoints.

2745.2M3](/packages/auth0-login)[cesargb/laravel-magiclink

Create secure link for access to private data or login in Laravel without password

4631.4M](/packages/cesargb-laravel-magiclink)[spatie/laravel-passkeys

Use passkeys in your Laravel app

470755.5k32](/packages/spatie-laravel-passkeys)

PHPackages © 2026

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