• Stars
    star
    134
  • Rank 270,967 (Top 6 %)
  • Language
    PHP
  • License
    Apache License 2.0
  • Created over 4 years ago
  • Updated about 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Hej! is a simple authentication boilerplate for Socialite.

Hej! - a Socialite authentication flow implementation

CI codecov StyleCI Latest Stable Version Total Downloads Monthly Downloads License

Hej! is a simple authentication flow implementation for Socialite. Out-of-the-box, Hej! can help you login and register users using Socialite providers, or link and unlink social accounts, just by extending a controller.

🀝 Supporting

If you are using one or more Renoki Co. open-source packages in your production apps, in presentation demos, hobby projects, school projects or so, sponsor our work with Github Sponsors. πŸ“¦

πŸš€ Installation

You can install the package via composer:

composer require renoki-co/hej

Publish the config:

$ php artisan vendor:publish --provider="RenokiCo\Hej\HejServiceProvider" --tag="config"

Publish the migrations:

$ php artisan vendor:publish --provider="RenokiCo\Hej\HejServiceProvider" --tag="migrations"

πŸ™Œ Usage

For the user (or any Authenticatable instance) you should add the HasSocialAccounts trait and the Sociable interface:

use RenokiCo\Hej\Concerns\HasSocialAccounts;
use RenokiCo\Hej\Contracts\Sociable;

class User extends Authenticatable implements Sociable
{
    use HasSocialAccounts;

    //
}

Out-of-the-box, it works with any Laravel application.

After you have configured Socialite, the only thing to do is to point your desired redirect and callback paths to the package controller:

Route::get('/social/{provider}/redirect', [\RenokiCo\Hej\Http\Controllers\SocialController::class, 'redirect']);
Route::get('/social/{provider}/callback', [\RenokiCo\Hej\Http\Controllers\SocialController::class, 'callback']);

Route::middleware('auth')->group(function () {
    Route::get('/social/{provider}/link', [\RenokiCo\Hej\Http\Controllers\SocialController::class, 'link']);
    Route::get('/social/{provider}/unlink', [\RenokiCo\Hej\Http\Controllers\SocialController::class, 'unlink']);
});

The paths can be any, as long as they contain a first parameter which is going to be the provider you try to authenticate with. For example, accessing this link will redirect to Github:

https://my-link.com/social/github/redirect

Extending Controllers

Hej! is really flexible and does a lot of things in the background to register or login using Socialite.

However, you need to extend the controller and you will then be able to replace some methods to customize the flow.

use RenokiCo\Hej\Http\Controllers\SocialController;

class MySocialController extends SocialController
{
    //
}

Then you should point the routes to the new controller.

Provider whitelisting

Due to the fact that the endpoints are opened to get any provider, you can whitelist the Socialite provider names that can be used:

/**
 * Whitelist social providers to be used.
 *
 * @var array
 */
protected static $allowedSocialiteProviders = [
    //
];

For example, allowing only Facebook and Github should look like this:

protected static $allowedSocialiteProviders = [
    'facebook',
    'github',
];

If one of the providers accessed via the URL is not whitelisted, a simple redirect is done automatically. However, you can replace it and redirect to your custom redirect action.

Custom Socialite Redirect & Retrieval

With Socialite, you can use ->redirect() to redirect the user and ->user() to retrieve it. You can customize the instances by replacing getSocialiteRedirect and getSocialiteUser.

Here is the default configuration:

/**
 * Get the Socialite direct instance that will redirect
 * the user to the right provider OAuth page.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  string  $provider
 * @return mixed
 */
protected function getSocialiteRedirect(Request $request, string $provider)
{
    return $this->socialite
        ->driver($provider)
        ->redirect();
}

/**
 * Get the Socialite User instance that will be
 * given after the OAuth authorization passes.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  string  $provider
 * @return \Laravel\Socialite\AbstractUser
 */
protected function getSocialiteUser(Request $request, string $provider)
{
    return $this->socialite
        ->driver($provider)
        ->user();
}

Registering new users

When the Social account that the user logged in is not registered within the database, it creates a new authenticatable model, but in order to do this, it should fill it with data.

By default, it fills in using Socialite Provider's given data and sets a random 64-letter word password:

/**
 * Get the Authenticatable model data to fill on register.
 * When the user gets created, it will receive these parameters
 * in the `::create()` method.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  string  $provider
 * @param  \Laravel\Socialite\AbstractUser  $providerUser
 * @return array
 */
protected function getRegisterData(Request $request, string $provider, $providerUser): array
{
    return [
        'name' => $providerUser->getName(),
        'email' => $providerUser->getEmail(),
        'email_verified_at' => now(),
        'password' => Hash::make(Str::random(64)),
    ];
}

Handling duplicated E-Mail addresses

Sometimes, it can happen for the users to have an account created with E-Mail address only, having no social accounts. A new social account with the same E-Mail address will trigger a new authenticatable record in the database on callback.

For this, a Redirect is made to handle this specific scenario.

Filling the Social table

After registration or login, the Socialite data gets created or updated, either the user existed or not.

By default, it's recommended to not get overwritten, excepting for the fact you want to change the table structure and extend the Social model that is also set in config/hej.php.

/**
 * Get the Social model data to fill on register or login.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  string  $provider
 * @param  \Illuminate\Database\Eloquent\Model  $model
 * @param  \Laravel\Socialite\AbstractUser  $providerUser
 * @return array
 */
protected function getSocialData(Request $request, string $provider, $model, $providerUser): array
{
    return [
        'provider_nickname' => $providerUser->getNickname(),
        'provider_name' => $providerUser->getName(),
        'provider_email' => $providerUser->getEmail(),
        'provider_avatar' => $providerUser->getAvatar(),
    ];
}

Callbacks

Right before the user is authenticated or registered successfully, there exist callback that trigger and you can replace them for some custom logic.

/**
 * Handle the callback after the registration process.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Illuminate\Database\Eloquent\Model  $model
 * @param  \Illuminate\Database\Eloquent\Model  $social
 * @param  \Laravel\Socialite\AbstractUser  $providerUser
 * @return void
 */
protected function registered(Request $request, $model, $social, $providerUser)
{
    //
}

/**
 * Handle the callback after the login process.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Illuminate\Database\Eloquent\Model  $model
 * @param  \Illuminate\Database\Eloquent\Model  $social
 * @param  \Laravel\Socialite\AbstractUser  $providerUser
 * @return void
 */
protected function authenticated(Request $request, $model, $social, $providerUser)
{
    //
}

/**
 * Handle the callback after the linking process.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Illuminate\Database\Eloquent\Model  $model
 * @param  \Illuminate\Database\Eloquent\Model  $social
 * @param  \Laravel\Socialite\AbstractUser  $providerUser
 * @return void
 */
protected function linked(Request $request, $model, $social, $providerUser)
{
    //
}

/**
 * Handle the callback after the unlink process.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Illuminate\Database\Eloquent\Model  $model
 * @param  string  $provider
 * @return void
 */
protected function unlinked(Request $request, $model, string $provider)
{
    //
}

Redirects

You are free to overwrite the actions' redirects within the controller:

use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\Session;

/**
 * Specify the redirection route after successful authentication.
 *
 * @param  \Illuminate\Database\Eloquent\Model  $model
 * @return \Illuminate\Http\RedirectResponse
 */
protected function redirectToAfterAuthentication($model)
{
    return Redirect::route('home');
}

/**
 * Specify the redirection route to let the users know
 * the authentication using the selected provider was rejected.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  string  $provider
 * @return \Illuminate\Http\RedirectResponse
 */
protected function redirectToAfterProviderIsRejected(Request $request, $provider)
{
    return Redirect::route('home');
}

/**
 * Specify the redirection route to let the users know
 * the E-Mail address used with this social account is
 * already existent as another account. This is most often
 * occuring during registrations with Social accounts.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  string  $provider
 * @param  \Laravel\Socialite\AbstractUser  $providerUser
 * @return \Illuminate\Http\RedirectResponse
 */
protected function redirectToAfterDuplicateEmail(Request $request, $provider, $providerUser)
{
    return Redirect::route('home');
}

Link & Unlink

Prior to creating new accounts or logging in with Socialite providers, Hej! comes with support to link and unlink Social accounts to and from your users.

You will need to have the routes accessible only for your authenticated users:

Route::middleware('auth')->group(function () {
    Route::get('/social/{provider}/link', [\RenokiCo\Hej\Http\Controllers\SocialController::class, 'link']);
    Route::get('/social/{provider}/unlink', [\RenokiCo\Hej\Http\Controllers\SocialController::class, 'unlink']);
});

Further, you may access the URLs to link or unlink providers.

Additionally, you may implement custom redirect for various events happening during link/unlink:

use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\Session;

/**
 * Specify the redirection route to let the users know
 * the social account is already associated with their account.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  string  $provider
 * @param  \Illuminate\Database\Eloquent\Model  $model
 * @return \Illuminate\Http\RedirectResponse
 */
protected function redirectToAfterProviderIsAlreadyLinked(Request $request, $provider, $model)
{
    return Redirect::route('home');
}

/**
 * Specify the redirection route to let the users know
 * the social account is associated with another account.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  string  $provider
 * @param  \Illuminate\Database\Eloquent\Model  $model
 * @param  \Laravel\Socialite\AbstractUser  $providerUser
 * @return \Illuminate\Http\RedirectResponse
 */
protected function redirectToAfterProviderAlreadyLinkedByAnotherAuthenticatable(
    Request $request, $provider, $model, $providerUser
) {
    return Redirect::route('home');
}

/**
 * Specify the redirection route to let the users know
 * they linked the social account.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Illuminate\Database\Eloquent\Model  $model
 * @param  \Illuminate\Database\Eloquent\Model  $social
 * @param  \Laravel\Socialite\AbstractUser  $providerUser
 * @return \Illuminate\Http\RedirectResponse
 */
protected function redirectToAfterLink(Request $request, $model, $social, $providerUser)
{
    return Redirect::route('home');
}

/**
 * Specify the redirection route to let the users
 * they have unlinked the social account.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Illuminate\Database\Eloquent\Model  $model
 * @param  string  $provider
 * @return \Illuminate\Http\RedirectResponse
 */
protected function redirectToAfterUnlink(Request $request, $model, string $provider)
{
    return Redirect::route('home');
}

Custom Authenticatable

When trying to login or register, the package uses the default App\User as defined in config/hej.php. However, this can easily be replaced at the request level:

/**
 * Get the model to login (or register).
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  string  $provider
 * @return string
 */
public function getAuthenticatable(Request $request, string $provider)
{
    return config('hej.default_authenticatable');
}

For example, you can change the model to authenticate as for different Socialite providers:

public function getAuthenticatable(Request $request, string $provider)
{
    if ($provider === 'medium') {
        return \App\AnotherUser::class;
    }

    return config('hej.default_authenticatable');
}

Keep in mind that the model should also use the Trait and the Interface and be Authenticatable.

πŸ› Testing

vendor/bin/phpunit

🀝 Contributing

Please see CONTRIBUTING for details.

πŸ”’ Security

If you discover any security related issues, please email [email protected] instead of using the issue tracker.

πŸŽ‰ Credits

More Repositories

1

laravel-eloquent-query-cache

Adding cache on your Laravel Eloquent queries' results is now a breeze.
PHP
1,045
star
2

befriended

Eloquent Befriended brings social media-like features like following, blocking and filtering content based on following or blocked models.
PHP
761
star
3

php-k8s

Unofficial PHP client for Kubernetes. It supports any form of authentication, the exec API, and it has an easy implementation for CRDs.
PHP
307
star
4

rating

Laravel Eloquent Rating allows you to assign ratings to any model.
PHP
190
star
5

jetstream-cashier-billing-portal

Cashierstream is a simple Spark alternative written for Laravel Jetstream, with the super-power of tracking plan quotas, like seats or projects number on a per-plan basis
PHP
163
star
6

laravel-sns-events

Laravel SNS Events eases the processing of incoming SNS webhooks using Laravel Events.
PHP
132
star
7

l1

Extend your PHP/Laravel application with Cloudflare bindings.
PHP
128
star
8

laravel-web3

Laravel SDK wrapper for the Web3 PHP API client that interacts with the Ethereum blockchain.
PHP
113
star
9

cashier-register

Cashier Register is a simple quota feature usage tracker for Laravel Cashier subscriptions.
PHP
90
star
10

clusteer

Clusteer is a Puppeteer wrapper written for Laravel, with the super-power of parallelizing pages across multiple browser instances.
PHP
88
star
11

laravel-php-k8s

Just a simple port of renoki-co/php-k8s for easier access in Laravel
PHP
86
star
12

eloquent-settings

Eloquent Settings allows you to bind key-value pairs to any Laravel Eloquent model. It supports even casting for boolean, float or integer types.
PHP
80
star
13

laravel-aws-webhooks

Easy webhook handler for Laravel to catch AWS SNS notifications for various services.
PHP
72
star
14

elasticscout

ElasticScout is an optimized Laravel Scout driver for Elasticsearch 7.1+
PHP
63
star
15

laravel-helm-demo

Example of a horizontally-scaled Laravel 8 app that runs on Kubernetes with NGINX Ingress Controller.
PHP
62
star
16

laravel-healthchecks

Laravel Healthchecks is a simple controller class that helps you build your own healthchecks endpoint without issues.
PHP
55
star
17

echo-server

Echo Server is a container-ready, multi-scalable Node.js application used to host your own Socket.IO server for Laravel Broadcasting.
TypeScript
38
star
18

laravel-docker-base

Already-compiled PHP-based Images to use when deploying your Laravel application to Kubernetes using Laravel Helm charts.
33
star
19

octane-exporter

Export Laravel Octane metrics using this Prometheus exporter.
PHP
28
star
20

charts

Helm Charts from Renoki Co. πŸš€
Smarty
28
star
21

acl

Simple, JSON-based, AWS IAM-style ACL for PHP applications, leveraging granular permissions in your applications with strong declarations. πŸ”
PHP
27
star
22

laravel-package-skeleton

Default package scaffolding for Laravel/PHP packages.
PHP
25
star
23

horizon-exporter

Export Laravel Horizon metrics using this Prometheus exporter.
PHP
25
star
24

reddit-json-api

Reddit JSON API is a PHP wrapper for handling JSON information from public subreddits.
PHP
20
star
25

dynamodb

AWS DynamoDB Eloquent ORM for Laravel 6+
PHP
18
star
26

browser-streamer

Stream a (kiosked) website to a RMTP URL using a Firefox headless browser.
Shell
17
star
27

laravel-steampipe

Use Laravel's built-in ORM classes to query cloud resources with Steampipe.
PHP
14
star
28

thunder

Thunder is an advanced Laravel tool to track user consumption using Cashier's Metered Billing for Stripe. ⚑
PHP
13
star
29

php-helm

PHP Helm Processor is a process wrapper for Kubernetes' Helm v3 CLI. You can run programmatically Helm v3 commands, directly from PHP, with a simple syntax.
PHP
12
star
30

laravel-useful-casts

Laravel Useful Casts is a simple package for Laravel 7.0+ that comes with already-tested and already-written, useful casts for Eloquent models.
PHP
10
star
31

laravel-explicit-array

Improved Laravel dot notation for explicit array keys.
PHP
8
star
32

laravel-yaml-config

The usual Laravel .env file, but with YAML.
PHP
7
star
33

laravel-acl

Simple, AWS IAM-style ACL for Laravel applications, leveraging granular permissions in your applications with strong declarations. πŸ”
PHP
7
star
34

aws-elastic-client

Just a simple Elasticsearch Client handler that signs the requests for AWS Elasticsearch service with the provided credentials.
PHP
7
star
35

laravel-thermite

Laravel Thermite is an extended PostgreSQL Laravel database driver to connect to a CockroachDB cluster.
PHP
7
star
36

laravel-prerender

Prerender Laravel pages using Clusteer and this nice package.
PHP
6
star
37

tailwind-preset

Laravel TailwindCSS Preset extends the Laravel's UI command to add a new preset for TailwindCSS configuration, leveraged by AlpineJS.
Blade
6
star
38

laravel-chained-jobs-shared-data

Chained Jobs Shared Data is a package that helps you share some data (usually an array) between chained jobs.
PHP
4
star
39

laravel-ec2-metadata

Retrieve the EC2 Metadata using Laravel's eloquent syntax.
PHP
4
star
40

laravel-exporter-contracts

Base contracts implementation for Prometheus exports in Laravel.
PHP
4
star
41

blade-mdi

Material Design Icons for Laravel Blade views.
PHP
4
star
42

laravel-firebase-analytics

Laravel Firebase Analytics adds blade directives to initialize, log events and set user properties for Firebase Analytics.
PHP
4
star
43

echo-server-core

Echo Server Core is a Laravel utility package used for Socket.IO-based Echo Server application.
PHP
2
star
44

cloudflare-sdk

Cloudflare SDK generated automatically from the OpenAPI definitions.
PHP
1
star
45

blog

Blog backup for Hashnode.
1
star
46

laravel-eloquent-query-cache-docs

1
star