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

v2.0.1(3mo ago)12.4k2[6 PRs](https://github.com/Accredifysg/SingPass-Login/pulls)MITPHPPHP ^8.2CI passing

Since Feb 24Pushed 6d 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 today

READMEChangelog (7)Dependencies (12)Versions (15)Used By (0)

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

[](#singpass-login)

[![Coverage](https://camo.githubusercontent.com/082dca63a5b9e338610689b79580c58129e0e4376c3df9ff4be5f8d7e2486dda/68747470733a2f2f736f6e6172636c6f75642e696f2f6170692f70726f6a6563745f6261646765732f6d6561737572653f70726f6a6563743d41636372656469667973675f53696e67506173732d4c6f67696e266d65747269633d636f76657261676526746f6b656e3d31316238646432353236383763373031353834303638626535356534376535653433323035366338)](https://sonarcloud.io/summary/new_code?id=Accredifysg_SingPass-Login)

PHP Laravel Package for SingPass Login and MyInfo

[Official SingPass Login Docs](https://api.singpass.gov.sg/library/login/developers/overview-at-a-glance)

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

[](#installation)

You can install the package via composer:

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

Add the following variables to your `.env` file.

```
# SingPass variables
SINGPASS_CLIENT_ID=
SINGPASS_REDIRECT_URI=
SINGPASS_DOMAIN=
SINGPASS_DISCOVERY_ENDPOINT=
SINGPASS_SIGNING_KID=
SINGPASS_JWKS=
SINGPASS_PRIVATE_JWKS=

# Default Routes
SINGPASS_USE_DEFAULT_ROUTES=true
SINGPASS_JWKS_URL=/sp/jwks
SINGPASS_AUTHENTICATION_URL=/sp/login
SINGPASS_CALLBACK_URL=/sp/callback

# Default Listener
SINGPASS_USE_DEFAULT_LISTENER=true

# Optional MyInfo envs if you want to use MyInfo integration
SINGPASS_MYINFO_CLIENT_ID=
SINGPASS_MYINFO_REDIRECT_URI=

```

Publish the config file

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

Optionally, you can publish the listener that will listen to the SingPassLoginEvent and log the user in

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

Usage and Customisations
------------------------

[](#usage-and-customisations)

### Controllers and Routes

[](#controllers-and-routes)

There are three default controllers that handle the login process

`GetJwksEndpointController` exposes your application's JWKS endpoint to be registered with SingPass. The default route for this controller is `/sp/jwks`

`GetAuthenticationEndpointController` provides the authentication endpoint to redirect the client's browser to. The default route for this controller is `/sp/login`

`PostSingPassCallbackController` handles the callback from SingPass, and kick-starts the login process. The default route for this controller is `/sp/callback`

If you prefer to set your own routes you can set `SINGPASS_USE_DEFAULT_ROUTES` to `false`, then edit `SINGPASS_JWKS_URL`, `SINGPASS_CALLBACK_URL`, and `SINGPASS_AUTHENTICATION_URL` in your `.env` file and map your own routes.

If you prefer to write your own controllers you can define them in the config file `singpass-login.php` as `get_jwks_endpoint_controller`, `post_singpass_callback_controller` and `get_authentication_endpoint_controller`

### Listener

[](#listener)

If you published the default listener, you should edit it and map your user retrieval via NRIC accordingly.

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

        $user = User::where('nric', '=', $nric)->first(); // Map to your own model that stores the users' NRIC or UUID

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

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

If you prefer to write your own, you can set `SINGPASS_USE_DEFAULT_LISTENER` to `false` in your `.env` and replace `listener_class` in the config file `singpass-login.php`

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

[](#myinfo-integration)

This package supports retrieving user data from MyInfo through scope-based data retrieval. By default, the package performs authentication-only flow using the `openid` scope. To retrieve additional user data, you can request specific MyInfo scopes during the authentication process.

### How It Works

[](#how-it-works)

MyInfo functionality is scope-driven:

- **Authentication Only**: When only the `openid` scope is requested (default), the package performs standard authentication without calling the UserInfo endpoint
- **MyInfo Data Retrieval**: When additional MyInfo scopes are requested, the package calls the UserInfo endpoint after successful authentication to retrieve the consented user data

### Requesting MyInfo Scopes

[](#requesting-myinfo-scopes)

Pass scopes as query parameters when redirecting users to the authentication endpoint:

**From JavaScript/Frontend:**

```
// Basic authentication only (default behavior)
window.location.href = '/sp/login';

// Request basic profile information
const scopes = ['openid', 'name', 'email', 'mobileno'];
window.location.href = `/sp/login?scopes=${scopes.join(',')}`;

// Request extended user data
const extendedScopes = [
    'openid',
    'name',
    'email',
    'mobileno',
    'nationality',
    'dob'
];
window.location.href = `/sp/login?scopes=${extendedScopes.join(',')}`;
```

**From Laravel Controller:**

```
public function redirectToSingPass()
{
    $scopes = ['openid', 'name', 'email', 'mobileno'];
    return redirect('/sp/login?' . http_build_query(['scopes' => implode(',', $scopes)]));
}
```

### Available MyInfo Scopes

[](#available-myinfo-scopes)

For the complete and up-to-date list of available MyInfo data items and their descriptions, refer to the official MyInfo Data Catalog:

**[MyInfo Data Catalog Documentation](https://docs.developer.singpass.gov.sg/docs/data-catalog-myinfo/catalog)**

The package validates requested scopes against the `available_scopes` configuration. Invalid scopes are filtered out and logged as warnings.

### Handling MyInfo Data

[](#handling-myinfo-data)

When MyInfo scopes are requested and data is successfully retrieved, the package emits a `MyInfoDataRetrievedEvent` instead of the standard `SingPassSuccessfulLoginEvent`.

#### MyInfoDataRetrievedEvent

[](#myinfodataretrievedevent)

Create a listener to handle the MyInfo data:

```
