PHPackages                             sun-asterisk/php-auth - 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. sun-asterisk/php-auth

ActiveLibrary[Authentication &amp; Authorization](/categories/authentication)

sun-asterisk/php-auth
=====================

Sun\* Auth | PHP

1.1.0(2y ago)06.5k3MITPHPPHP ^8.0

Since Feb 28Pushed 2y ago4 watchersCompare

[ Source](https://github.com/sun-asterisk/tech-standard-php-auth)[ Packagist](https://packagist.org/packages/sun-asterisk/php-auth)[ RSS](/packages/sun-asterisk-php-auth/feed)WikiDiscussions php Synced 1mo ago

READMEChangelog (8)Dependencies (10)Versions (10)Used By (0)

Tech Standard PHP Auth
======================

[](#tech-standard-php-auth)

[![CI](https://github.com/sun-asterisk/tech-standard-php-auth/actions/workflows/check_ci.yml/badge.svg)](https://github.com/sun-asterisk/tech-standard-php-auth/actions/workflows/check_ci.yml)[![License](https://camo.githubusercontent.com/d87eb1a0fa4a1b11555d255a6e9d341f20de6983e951730f3246a61d8f93abbc/68747470733a2f2f706f7365722e707567782e6f72672f726562696e672f6772617068716c2d6c61726176656c2f6c6963656e7365)](https://packagist.org/packages/rebing/graphql-laravel)

🌟 Introduction
--------------

[](#-introduction)

Sun\* Auth is a library designed to provide authentication and authorization features for web/mobile applications. It is built using modern technologies and provides a range of features that make it easy to integrate into existing applications.

One of the key reasons for using Sun\* Auth is its ease of use. It provides a simple library that makes it easy to add authentication and authorization to any application. Additionally, it is designed to be highly customizable, allowing developers to tailor it to their specific needs.

Using Sun\* Auth saves time and effort for developers, as we do not have to independently write and test complex authentication and authorization features. Additionally, Sun\* Auth provides a simple and easy-to-understand library that makes it easy to integrate into existing web/mobile applications.

Some of the features provided by Sun\* Auth include user registration and login, password reset and recovery.

---

- [🔌 Installation](#installation)
    - [Laravel](#laravel)
    - [Lumen](#lumen)
    - [Other](#other)
- [🔎 Usage](#usage)
    - [Configure Auth guard](#configure-auth-guard)
    - [Injection dependencies use JWT](#injection-dependencies-use-jwt)
    - [Injection dependencies use Session](#injection-dependencies-use-session)
    - [Login](#login)
    - [Logout](#logout)
    - [Register](#register)
    - [Forgot password](#forgot-password)
    - [Refresh token](#refresh-token)
    - [Social Login custom](#social-login-custom)
- [ ⚡ Architecture](#architecture)
    - [Login](#architecture-login)
    - [Logout](#architecture-logout)
    - [Register](#architecture-register)
    - [Forgot password](#architecture-forgot-password)
    - [Refresh token](#architecture-refresh-token)
    - [Social Login custom](#architecture-social-login-custom)

---

🔌 Installation
--------------

[](#-installation)

Require the package via Composer:

```
composer require sun-asterisk/php-auth
```

#### Laravel

[](#laravel)

Add the service provider to the providers array in the config/app.php config file as follows:

```
 [
        // ...
        SunAsterisk\Auth\SunServiceProvider::class
    ]
];
```

Publish the configuration file:

```
php artisan vendor:publish --provider="SunAsterisk\Auth\SunServiceProvider" --tag=sun-asterisk
```

#### Lumen

[](#lumen)

```
register(SunAsterisk\Auth\SunServiceProvider::class);
```

Configuration

```
mkdir -p config
cp vendor/sun-asterisk/config/sun-asterisk.php config/sun-asterisk.php
```

#### Other

[](#other)

```
use SunAsterisk\Auth\Factory;

$configs = config('/path/to/sun-asterisk.php')

$factory = (new Factory)->withConfig($configs);
$service = $factory->createAuthJwt();
```

Configuration

```
mkdir -p config
cp vendor/sun-asterisk/config/sun-asterisk.php config/sun-asterisk.php
```

### Review the configuration file:

[](#review-the-configuration-file)

```
config/sun-asterisk.php
```

 Detail```
 [
      /*
      |---------------------------------------------------------
      | Attribute login
      |---------------------------------------------------------
      |
      | E.g. 'email or username'
      |
      */
      'login_username' => 'email',
      /*
      |---------------------------------------------------------
      | Attribute field_credentials
      |---------------------------------------------------------
      | Use 1 of the list for authentication
      | E.g. 'username or email or phone'
      |
      */
      'field_credentials' => [
          'email',
      ],
      /*
      |---------------------------------------------------------
      | Attribute token_payload_fields
      |---------------------------------------------------------
      | Use the items in the list to create an access token
      |
      | E.g. 'id or email'
      |
      */
      'token_payload_fields' => [
          'id',
          'email',
      ],
      /*
      |---------------------------------------------------------
      | Attribute login
      |---------------------------------------------------------
      |
      | E.g. 'password or passwd'
      |
      */
      'login_password' => 'password',
      /*
      |---------------------------------------------------------
      | Model login
      |---------------------------------------------------------
      |
      | E.g. 'App\Models\User::class or App\Models\Admin::class'
      |
      */
      'model' => App\Models\User::class,
      /*
      |---------------------------------------------------------
      | Token forgot password
      |---------------------------------------------------------
      |
      | Default 5 minutes
      | E.g. '5'
      |
      */
      'token_expires' => 5, // minutes
      /*
      |---------------------------------------------------------
      | Key for jwt access token
      |---------------------------------------------------------
      |
      | E.g. 'xxxx'
      |
      */
      'jwt_key' => 'jwt_key',
      /*
      |---------------------------------------------------------
      | Key for jwt refresh access token
      |---------------------------------------------------------
      |
      | E.g. 'xxxx'
      |
      */
      'jwt_refresh_key' => 'jwt_refresh_key',
      /*
      |---------------------------------------------------------
      | TTL for jwt
      |---------------------------------------------------------
      |
      | Default 60 minutes
      | E.g. '60'
      |
      */
      'jwt_ttl' => 60, // minutes
      /*
      |---------------------------------------------------------
      | TTL for refresh access token
      |---------------------------------------------------------
      |
      | Default 20160 minutes
      | E.g. '60'
      |
      */
      'jwt_refresh_ttl' => 20160, // minutes
      /*
      |---------------------------------------------------------
      | use Socialite Providers for social login
      |---------------------------------------------------------
      |
      | Default false
      |
      */
      'enabled_social' => false,
  ],
];
```

### Usage

[](#usage)

We will take an example of usage in Laravel.

#### Configure Auth guard

[](#configure-auth-guard)

Inside the config/auth.php file you will need to make a few changes to configure

```
'guards' => [
    'api' => [
        'driver' => 'sun',
        'provider' => 'users',
    ],
]
```

Add auth:api middleware to routes that require login authentication

```
Route::group([
    'middleware' => 'auth:api',
], function ($router) {
    // routes
}
```

#### Injection dependencies use JWT

[](#injection-dependencies-use-jwt)

```
service = $service;
    }
    ...
}
```

#### Injection dependencies use Session

[](#injection-dependencies-use-session)

```
service = $service;
    }
    ...
}
```

#### Login:

[](#login)

```
POST /login

```

- Parameters

Request FieldField TypeRequiredField Descusernamestringtrueusername for userpasswordstringtruepassword for user- Responses

Response FieldField TypeRequiredField Descrefresh\_tokenstringtruerefresh\_token for user get access\_tokenaccess\_tokenstringtrueaccess\_token for user loggedtoken\_typestringtruetoken\_type for user loggedexpires\_atintegertrueexpires\_at for user loggedUsage with JWT

 Detail```
public function login(Request $request)
{
    $params = $request->only(['username', 'password']);
    // use service package
    $rs = $this->service->login($params, [], function ($entity) {
        return $entity->only(['id', 'email', 'username']);
    });

    return response()->json($rs['auth']);
}
```

Usage with Session

 Detail```
public function showLoginForm()
{
    return view('auth.login');
}

public function login(Request $request)
{
    $params = $request->only(['email', 'password']);

    $this->service->login($params, [], function ($entity) {
        //
    });

    return redirect()->intended('home');
}
```

Example
-------

[](#example)

```
curl -X 'POST' \
  'http://localhost/api/login' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "username": "user1234",
  "password": "passwordRequired@123"
}'
```

```
{
  "refresh_token": "eyJ0eXAiOiJKV1QiLC...",
  "access_token": "eyJ0eXAiOiJKV1...",
  "token_type": "bearer",
  "expires_at": 1676281826
}
```

#### Logout

[](#logout)

```
POST /logout

```

- Parameters

Request FieldField TypeRequiredField DescAuthorizationBearertrueaccess\_token for authenticate- Responses

Response FieldField TypeRequiredField DescN/AN/AN/Areturn code `204` - noContentUsage with JWT

 Detail```
public function logout(Request $request)
{
   auth('api')->logout();

   return response()->noContent();
}
```

Usage with Session

 Detail```
public function logout(Request $request)
{
    $this->service->logout($request);

    return view('auth.login');
}
```

Example

```
curl -X 'POST' \
  'http://localhost/api/logout' \
  -H 'accept: application/json' \
  -H 'Authorization: Bearer eyJ0eXAiOiJKV1...' \
  -d ''
```

```
{}
```

#### Register

[](#register)

```
POST /register

```

- Parameters

Request FieldField TypeRequiredField Descusernamestringtrueusername for userpasswordstringtruepassword for useremailstringtrueemail for user- Responses

Response FieldField TypeRequiredField Descidintegertrueid for userusernamestringtrueusername for useremailstringtrueemail for userUsage with JWT

 Detail```
public function register(Request $request)
{
    $rules = [];
    $fields = $request->only(['username', 'password', 'email']);

    $result = $this->service->register($fields, $rules, function ($entity) {
        return $entity->only(['id', 'email', 'username']);
    });

    return response()->json($result);
}
```

Usage with Session

 Detail```
public function showRegistrationForm()
{
    return view('auth.register');
}

public function register(Request $request)
{
    $fields = $request->only(['username', 'password', 'email']);
    $fields['name'] = $fields['username'];

    $this->service->register($fields, [], function ($entity) {
        //
    });

    return redirect()->intended('home');
}
```

If do you want after register, user will authenticated, Please set true for argument $setGuard as bellow

```
$this->service->register($fields, [], function ($entity) {
        //
    }, true);
```

Example:

```
curl -X 'POST' \
  'http://localhost/api/register' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "username": "user123456",
  "password": "passwordRequired@123",
  "email": "testuser02@local.ltd"
}'
```

```
{
  "id": 13,
  "email": "testuser02@local.ltd",
  "username": "user123456"
}
```

#### Forgot-password

[](#forgot-password)

```
POST /forgot-password

```

- Parameters

Request FieldField TypeRequiredField Descemailstringtrueemail for user- Responses

Response FieldField TypeRequiredField Descokbooleanfalsestatus for the requesttypestringfalsetype of the requestMake *postForgotPassword* function as the following:

 Detail```
# App\Http\Controllers\AuthController
public function postForgotPassword(Request $request)
{
    $email = $request->email;
    $status = $this->service->postForgotPassword($email, function ($token, $user) {
        // Use send mail from framework
        sendEmail($user, $token);
    });

    return response()->json([
        'ok' => $status,
        'type' => 'forgotPassword',
    ]);
}
```

Make *confirm* function as the following:

 Detail```
public function confirm(Request $request)
{
   $token = $request->token;
   $status = $this->service->verifyToken($token);

   return response()->json([
       'ok' => $status,
   ]);
}
```

Make *newPassword* function as the following:

 Detail```
# App\Http\Controllers\AuthController
public function postNewPassword(Request $request)
{
   $params = $request->only(['password', 'token']);
   $status = $this->service->changePassword($params, null, function ($user, &$attr) {
       // Update attr
   });

   return response()->json([
       'ok' => $status,
       'type' => 'newPassword',
   ]);
}
```

Example

```
curl -X 'POST' \
  'http://localhost/api/forgot-password' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "email": "testuser01@local.ltd"
}'
```

```
{
  "ok": true,
  "type": "forgotPassword"
}
```

### Verify

[](#verify)

```
GET /confirm

```

- Parameters

Request FieldField TypeRequiredField DesctokenstringtrueGet token from email- Responses

Response FieldField TypeRequiredField Descokbooleanfalsestatus for the request```
curl -X 'GET' \
  'http://localhost/api/confirm?token=eyJ0eXAiOiJKV1QiLC...' \
  -H 'accept: application/json'
```

```
{
  "ok": true
}
```

### New Password

[](#new-password)

```
POST /new-password

```

- Parameters

Request FieldField TypeRequiredField Descpasswordstringtruepassword for usertokenstringtruetoken from user's email- Responses

Response FieldField TypeRequiredField Descokbooleanfalsestatus for the requesttypestringfalsetype of the request```
curl -X 'POST' \
  'http://localhost/api/new-password' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "password": "passwordRequired@123",
  "token": "eyJ0eXAiOiJKV1QiLC..."
}'
```

```
{
  "ok": true,
  "type": "newPassword"
}
```

#### Refresh token

[](#refresh-token)

```
POST /refresh

```

- Parameters

Request FieldField TypeRequiredField Descrefresh\_tokenstringtruerefresh\_token for user get access\_token- Responses

Response FieldField TypeRequiredField Descrefresh\_tokenstringtruerefresh\_token for user get access\_tokenaccess\_tokenstringtrueaccess\_token for user loggedtoken\_typestringtruetoken\_type for user loggedexpires\_atintegertrueexpires\_at for user loggedMake Refresh function the following:

```
# App\Http\Controllers\AuthController;
public function refresh(Request $request)
{
    $token = $request->refresh_token;

    $rs = $this->service->refresh($token);

    return response()->json($rs);
}
```

Example

```
curl -X 'POST' \
  'http://localhost/api/refresh' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "refresh_token": "refresh_token_secret"
}'
```

```
{
  "refresh_token": "eyJ0eXAiOiJKV1QiLC...",
  "access_token": "eyJ0eXAiOiJKV1...",
  "token_type": "bearer",
  "expires_at": 1676281826
}
```

#### Social Login custom

[](#social-login-custom)

Login With Google

To use you need to install the *socialiteproviders/google* package via composer:

```
composer require socialiteproviders/google
```

Add configuration to config/services.php

```
# config/services.php
...
'google' => [
  'client_id' => env('GOOGLE_CLIENT_ID'),
  'client_secret' => env('GOOGLE_CLIENT_SECRET'),
  'redirect' => env('GOOGLE_REDIRECT_URI'),
],
```

Update config enabled\_social is true to config/sun-asterisk.php

**config/sun-asterisk.php**

 Detail```
# config/sun-asterisk.php
...
/*
|---------------------------------------------------------
| use Socialite Providers for social login
|---------------------------------------------------------
|
| Default false
|
*/
'enabled_social' => true,
```

**routes/web.php**

 Detail```
# routes/web.php
use Illuminate\Support\Facades\Route;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use SunAsterisk\Auth\Contracts\AuthSocialInterface;
...

// Redirect Endpoint
Route::get('social/{provider}/redirect', function (Request $request) {
    $provider = $request->provider;
    // use service from package
    return app(AuthSocialInterface::class)->socialSignIn($provider);
});

// Callback Endpoint
Route::get('social/{provider}/callback', function (Request $request) {
    $provider = $request->provider;
    // use service from package
    $socialUser = app(AuthSocialInterface::class)->socialCallback($provider);

    $user = \App\Models\User::updateOrCreate([
        'social_id' => $socialUser->id,
        'social_type' => $provider,
    ], [
        'name' => $socialUser->name,
        'email' => $socialUser->email,
        'avatar' => $socialUser->avatar,
    ]);

    Auth::login($user);

    return redirect('/dashboard');
});
```

### Architecture

[](#architecture)

#### Architecture Login

[](#architecture-login)

**Workflow**

[![Sun_ Auth _ Architecture Design-Login (1)](https://user-images.githubusercontent.com/49347026/217132347-4a150f53-9878-43d5-8989-b8d80f289f3b.jpg)](https://user-images.githubusercontent.com/49347026/217132347-4a150f53-9878-43d5-8989-b8d80f289f3b.jpg)

Explain

**Interface**

```
/**
* [login]
* @param  array         $credentials [The user's attributes for authentication.]
* @param  array|null    $attributes  [The attributes use for query.]
* @param  callable|null $callback    [The callback function has the entity model.]
* @return [array]
*/
public function login(array $credentials = [], ?array $attributes = [], ?callable $callback = null): array;
```

1. Validator

```
# SunAsterisk\Auth\Services\AuthJWTService;
public function login(array $credentials = [], ?array $attributes = [], ?callable $callback = null): array
{
  $this->loginValidator($credentials)->validate();
  ...
}
...
protected function loginValidator(array $data)
{
    return Validator::make($data, [
        $this->username()  => 'required',
        $this->passwd() => 'required',
    ]);
}
```

2. Find item by attribute

```
# SunAsterisk\Auth\Services\AuthJWTService;
public function login(array $credentials = [], ?array $attributes = [], ?callable $callback = null): array
{
    ...
    $item = $this->repository->findByAttribute($attributes);
}
```

3. Compare hash password

```
# SunAsterisk\Auth\Services\AuthJWTService;
public function login(array $credentials = [], ?array $attributes = [], ?callable $callback = null): array
{
    ...
    if (! $item || ! Hash::check(Arr::get($credentials, $this->passwd()), $item->{$this->passwd()})) {
        throw ValidationException::withMessages([
            'message' => $this->getFailedLoginMessage(),
        ]);
    }
}
```

4. Generate accessToken &amp; refreshToken from jwt

```
# SunAsterisk\Auth\Services\AuthJWTService;
public function login(array $credentials = [], ?array $attributes = [], ?callable $callback = null): array
{
    ...
    $payload = $this->jwt->make($itemArr)->toArray();
    $payloadRefresh = $this->jwt->make($itemArr, true)->toArray();

    $jwt = $this->jwt->encode($payload);
    $refresh = $this->jwt->encode($payloadRefresh, true);

    $this->tokenMapper->add($payload, $refresh);
}
```

Method login will return an array

```
'item' => $itemArr,
'auth' => [
    'refresh_token' => 'eyJhbGciOiJIUzI1NiIsIn...',
    'access_token' => 'eyJiwibmFtZSI6Ikpva...',
    'token_type' => 'bearer',
    'expires_at' => 1675742447,
],
```

- `$itemArr` is array of object user model. We can custom by callback function as follows

```
# App\Http\Controllers\AuthController
$rs = $this->service->login($params, [], function ($entity) {
    // Custom $itemArr
    return $entity->only(['id', 'email', 'username']);
});
```

BTW: Also we can change the sql query for the login flow as follows

```
# App\Http\Controllers\AuthController
$rs = $this->service->login(
    $params,
    [
        'username' => $params['username'],
        'is_active' => true, // custom query attributes
    ],
    function ($entity) {
        return $entity->only(['id', 'email', 'username']);
    },
);
```

#### Architecture Logout

[](#architecture-logout)

Workflow

 ```
sequenceDiagram
Controller->>SunGuard: 1. Logout
SunGuard->>SunJWT: 2. Revoke token & access token!
SunJWT-->>SunGuard: 3.a Throw JWT Exception
SunJWT-->>SunGuard: 3.b Successful!
SunGuard-->>Controller: 4. Successful!
```

      Loading Explain

1. Setting Guard to service provider

```
# SunAsterisk\Auth\SunServiceProvider
/**
 * Extend Laravel's Auth.
 *
 * @return void
 */
protected function extendAuthGuard(): void
{
    $this->app['auth']->extend('sun', function ($app, $name, array $config) {
    $storage = $app->make(Providers\Storage::class);
    $blackList = new SunBlacklist($storage);
    $jwt = new SunJWT($blackList, $app->config->get('sun-asterisk.auth'));
    $tokenMapper = new SunTokenMapper($storage);

    $guard = new SunGuard(
        $jwt,
        $app['auth']->createUserProvider($config['provider']),
        $app['request'],
        $tokenMapper
    );
    app()->refresh('request', $guard, 'setRequest');

    return $guard;
});
}
```

2. Create method logout in *SunGuard*

```
# SunAsterisk\Auth\SunGuard
/**
 * Logout the user, thus invalidating the token.
 *
 * @return void
 */
public function logout()
{
    try {
        $token = $this->request->bearerToken();
        $rawToken = $this->jwt->decode($token);
        $refreshToken = $this->tokenMapper->pullRefreshToken($rawToken['jti']);

        $this->jwt->invalidate($token);
        if ($refreshToken) {
            $this->jwt->invalidate($refreshToken, true);
        }
    } catch (\Exception $e) {
        throw new Exceptions\JWTException($e->getMessage());
    }
}
```

3. Invalidate *token* and *refreshToken*

```
# SunAsterisk\Auth\SunJWT
public function invalidate(string $token, bool $isRefresh = false): bool
{
    if (! $this->blackList) {
        throw new Exceptions\JWTException('You must have the blacklist enabled to invalidate a token.');
    }

    $payload = $this->decode($token, $isRefresh, false);

    return $this->blackList->add($payload);
}
```

#### Architecture Register

[](#architecture-register)

**Workflow**

[![Sun_ Auth _ Architecture Design-Register](https://user-images.githubusercontent.com/49347026/217147750-745b8349-c015-41ff-a969-c72a57ba055c.jpg)](https://user-images.githubusercontent.com/49347026/217147750-745b8349-c015-41ff-a969-c72a57ba055c.jpg)

**Explain**

**Interface**

```
/**
* [register]
* @param  array         $fields    [The user's attributes for register.]
* @param  array         $rules     [The rules for register validate.]
* @param  callable|null $callback  [The callback function has the entity model.]
* @return [array]
*/
public function register(array $params = [], array $rules = [], callable $callback = null): array;
```

1. Validator

```
# SunAsterisk\Auth\Services\AuthJWTService;
public function register(array $params = [], array $rules = [], callable $callback = null): array
{
    if (empty($rules)) {
        $rules = [
            'username' => ['required', 'string', "unique:{$table}," . $this->username()],
            'password' => [
                'required',
                'min:6',
                'regex:/^.*(?=.{3,})(?=.*[a-zA-Z])(?=.*[0-9])(?=.*[\d\x])(?=.*[!@#$%]).*$/',
            ],
        ];

        if (isset($params['email'])) {
            $rules['email'] = ['required', 'string', "unique:{$table},email"];
        }
    }
    ...
}
```

2. Hash Password

```
# SunAsterisk\Auth\Services\AuthJWTService;
public function register(array $params = [], array $rules = [], callable $callback = null): array
{
    ...
    $params[$this->passwd()] = Hash::make($params[$this->passwd()]);
}
```

3. Insert params to database

```
# SunAsterisk\Auth\Services\AuthJWTService;
public function register(array $params = [], array $rules = [], callable $callback = null): array
{
    ...
    $item = $this->repository->create($params);
}
```

Method register will return an array

**Custom register**

You can changes or validate attributes as following

```
# App\Http\Controllers\AuthController
public function register(Request $request)
{
    $fields = $request->only(['password', 'email']);
    // customer validate
    $rules = [
        'email' => 'required|email',
        'password' => 'required',
    ];

    $result = $this->service->register($fields, $rules);

    return response()->json($result);
}
```

#### Architecture Forgot password

[](#architecture-forgot-password)

**Workflow**

[![Sun_ Auth _ Architecture Design-Resending confirmation request_email](https://user-images.githubusercontent.com/49347026/218481379-936f17c2-f403-42ad-8db5-21b4520434ab.jpg)](https://user-images.githubusercontent.com/49347026/218481379-936f17c2-f403-42ad-8db5-21b4520434ab.jpg)

**Explain**

**Interface**

```
/**
* [postForgotPassword]
* @param  string        $email     [The user's email for receive token]
* @param  callable|null $callback  [The callback function response token & entity model.]
* @return [bool]
*/
public function postForgotPassword(string $email, callable $callback = null): bool;

/**
* [verifyForgotPasswordToken]
* @param  string        $token     [The token from user's email]
* @param  callable|null $callback  [The callback function has the token & entity model.]
* @return [bool]
*/
public function verifyToken(string $token, callable $callback = null): bool;

/**
* [changePassword]
* @param  array         $params    [The params for change password (passwd | ?old_passwd | ?token)]
* @param  int|null      $userId    [The user's id when user authenticate.]
* @param  callable|null $callback  [The callback function have the entity model & pointer of users's attributes.]
* @return [bool]
*/
public function changePassword(array $params = [], ?int $userId = null, callable $callback = null): bool;
```

1. Verify Email

```
# SunAsterisk\Auth\Services\AuthJWTService;
public function postForgotPassword(string $email, callable $callback = null): bool
{
   ...
   // Validate Email
   Validator::make(['email' => $email], [
       'email' => ['required', 'email'],
   ])->validate();

   // Check Email exists
   $item = $this->repository->findByAttribute(['email' => $email]);
   if (!$item) {
       throw ValidationException::withMessages([
           'message' => 'The email is invalid.',
       ]);
   }
   ...
}
```

2. Generate token

```
# SunAsterisk\Auth\Services\AuthJWTService;
public function postForgotPassword(string $email, callable $callback = null): bool
{
   ...
   $obj = [
       'id' => $item->id,
       'created_at' => Carbon::now()->timestamp,
   ];

   $token = Crypt::encryptString(json_encode($obj));
   ...
}
```

3. Verify token

```
# SunAsterisk\Auth\Services\AuthJWTService;
public function verifyToken(string $token, callable $callback = null): bool
{
     ...
     $objStr = Crypt::decryptString($token);
     $obj = json_decode($objStr, true);
     ...
     $diffSeconds = Carbon::now()->diffInSeconds(Carbon::createFromTimestamp($obj['created_at']));

     if ($diffSeconds >= $this->config['token_expires'] * 60) {
          throw new AuthException('Token is invalid!');
     }
}
```

4. Change password

```
# SunAsterisk\Auth\Services\AuthJWTService;
public function changePassword(array $params = [], ?int $userId = null, callable $callback = null): bool
{
   ...
   $user = null;
   $attr = [];

   // For usecase forgot password
   if (isset($params['token'])) {
       $this->verifyToken($params['token'], function ($entity) use (&$user) {
           $user = $entity;
       });
   }
   ...

   if ($user) {
       $attr[$this->passwd()] = Hash::make($params[$this->passwd()]);
       ...

       $this->repository->updateById($user->id, $attr);
   }
   ...
}
```

#### Architecture Refresh token

[](#architecture-refresh-token)

**Workflow**

[![Sun_ Auth _ Architecture Design-Refresh token](https://user-images.githubusercontent.com/49347026/217161566-be58ab38-2f71-476d-bddf-24e043ae43c7.jpg)](https://user-images.githubusercontent.com/49347026/217161566-be58ab38-2f71-476d-bddf-24e043ae43c7.jpg)

**Explain**

**Interface**

```
/**
* [refresh]
* @param  string $refreshToken     [refresh_token for user get access_token]
* @param  callable|null $callback  [The callback function has the entity model.]
* @return [array]
*/
public function refresh(?string $refreshToken, callable $callback = null): array;
```

1. Decode refresh token

```
# SunAsterisk\Auth\Services\AuthJWTService;
public function refresh(?string $refreshToken, callable $callback = null): array
{
    ...
    $payload = $this->jwt->decode($refreshToken ?: '', true);
}
```

2. Compare exp time of the refresh token

```
# SunAsterisk\Auth\Services\AuthJWTService;
public function refresh(?string $refreshToken, callable $callback = null): array
{
    ...
    if (Carbon::createFromTimestamp($payload['exp'])->lte(Carbon::now())) {
        throw new InvalidArgumentException('The RefreshToken is invalid.');
    }
}
```

3. Verify user exists

```
# SunAsterisk\Auth\Services\AuthJWTService;
public function refresh(?string $refreshToken, callable $callback = null): array
{
    ...
    $item = $this->repository->findById($sub?->id);
    if (!$item) {
        throw new InvalidArgumentException('The RefreshToken is invalid.');
    }
}
```

4. Revoke all access token

```
# SunAsterisk\Auth\Services\AuthJWTService;
public function revoke(array $keys = []): bool
    {
        try {
            return $this->jwt->revoke($keys);
        } catch (\Exception $e) {
            throw new Exceptions\JWTException('Revoke token is wrong.');
        }
    }
```

5. Re generate access token

```
# SunAsterisk\Auth\Services\AuthJWTService;
public function refresh(?string $refreshToken, callable $callback = null): array
{
    ...
    $payload = $this->jwt->make((array) $sub)->toArray();
    $jwt = $this->jwt->encode($payload);

    $this->tokenMapper->add($payload, $refreshToken);
}
```

Method refresh will return an array

```
# SunAsterisk\Auth\Services\AuthJWTService;
public function refresh(?string $refreshToken, callable $callback = null): array
{
    ...
    return [
        'refresh_token' => 'eyJhbGciOiJIUzI1NiIsIn...',
        'access_token' => 'eyJiwibmFtZSI6Ikpva...',
        'token_type' => 'bearer',
        'expires_at' => 1675742447,
    ];
}
```

#### Architecture Social Login custom

[](#architecture-social-login-custom)

**Workflow**

[![Sun_ Auth _ Architecture Design-Social sign-in (1)](https://user-images.githubusercontent.com/49347026/218634287-134ea1a2-785b-43bb-9baf-576bf61291c9.jpg)](https://user-images.githubusercontent.com/49347026/218634287-134ea1a2-785b-43bb-9baf-576bf61291c9.jpg)

**Explain**

**Interface**

```
/**
* [socialSignIn]
* @param  string $provider                   [The Provider should received from https://socialiteproviders.com/about/]
* @return [Illuminate\Http\RedirectResponse]
*/
public function socialSignIn(?string $provider): RedirectResponse;

/**
* [socialCallback]
* @param  string $provider     [The Provider should received from https://socialiteproviders.com/about/]
* @return [stdClass]
*/
public function socialCallback(?string $provider): stdClass;
```

1. Redirect

```
# SunAsterisk\Auth\Services\AuthSocialService
/**
 * [socialSignIn]
 * @param  string $provider [The Provider should received from https://socialiteproviders.com/about/]
 * @return [Illuminate\Http\RedirectResponse]
 */
public function socialSignIn(?string $provider): RedirectResponse
{
    try {
        return Socialite::driver($provider)->redirect();
    } catch (\Exception $e) {
        throw new InvalidArgumentException('provider is invalid!');

```

2. Callback

```
# SunAsterisk\Auth\Services\AuthSocialService
/**
 * [socialCallback]
 * @param  string $provider [The Provider should received from https://socialiteproviders.com/about/]
 * @return [stdClass]
 */
public function socialCallback(?string $provider): stdClass
{
    try {
        return Socialite::driver($provider)->user();
    } catch (\Exception $e) {
        throw new InvalidArgumentException('provider is invalid!');
    }
}
```

###  Health Score

30

—

LowBetter than 64% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity20

Limited adoption so far

Community16

Small or concentrated contributor base

Maturity56

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 53.7% 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 ~35 days

Total

8

Last Release

925d ago

### Community

Maintainers

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

---

Top Contributors

[![dungda-0794](https://avatars.githubusercontent.com/u/49347026?v=4)](https://github.com/dungda-0794 "dungda-0794 (29 commits)")[![khaicm-0897](https://avatars.githubusercontent.com/u/51064915?v=4)](https://github.com/khaicm-0897 "khaicm-0897 (14 commits)")[![tungnt-0092](https://avatars.githubusercontent.com/u/2981796?v=4)](https://github.com/tungnt-0092 "tungnt-0092 (7 commits)")[![anhnt-2136](https://avatars.githubusercontent.com/u/60587803?v=4)](https://github.com/anhnt-2136 "anhnt-2136 (2 commits)")[![phuongnn-0944](https://avatars.githubusercontent.com/u/45155411?v=4)](https://github.com/phuongnn-0944 "phuongnn-0944 (2 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/sun-asterisk-php-auth/health.svg)

```
[![Health](https://phpackages.com/badges/sun-asterisk-php-auth/health.svg)](https://phpackages.com/packages/sun-asterisk-php-auth)
```

###  Alternatives

[roots/acorn

Framework for Roots WordPress projects built with Laravel components.

9682.1M97](/packages/roots-acorn)[laravel/mcp

Rapidly build MCP servers for your Laravel applications.

74310.9M66](/packages/laravel-mcp)[laragear/two-factor

On-premises 2FA Authentication for out-of-the-box.

339785.3k8](/packages/laragear-two-factor)[aedart/athenaeum

Athenaeum is a mono repository; a collection of various PHP packages

245.2k](/packages/aedart-athenaeum)[galahad/laravel-addressing

Laravel package providing addressing functionality

70316.6k](/packages/galahad-laravel-addressing)[api-platform/laravel

API Platform support for Laravel

59126.4k6](/packages/api-platform-laravel)

PHPackages © 2026

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