Compare commits
No commits in common. "master" and "2.0" have entirely different histories.
306
README.md
306
README.md
|
@ -1,217 +1,213 @@
|
||||||
# laravel-connect
|
# laravel-connect
|
||||||
|
|
||||||
Ce package permet d'utiliser [Bluesquare Connect](https://connect.bluesquare.io) comme méthode d'authentification grâce au protocole OAuth 2.0.
|
The Bluesquare Connect package allows you to use its OAuth server and sync its resources.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
Mettre à jour les sources de `composer.json` avec :
|
Update your `composer.json`:
|
||||||
|
|
||||||
```
|
```
|
||||||
composer config repositories.connect vcs https://git.bluesquare.io/bluesquare/laravel-connect.git -n
|
"repositories": [
|
||||||
|
{
|
||||||
|
"type": "vcs",
|
||||||
|
"url": "https://git.bluesquare.io/bluesquare/laravel-connect"
|
||||||
|
}
|
||||||
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
Puis installer le package :
|
Install the package:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
composer require bluesquare/laravel-connect "2.3"
|
composer require bluesquare/laravel-connect "1.2"
|
||||||
```
|
```
|
||||||
|
|
||||||
Mettre à jour le `.env` avec les identifiants du client OAuth généré sur [Bluesquare Connect](https://connect.bluesquare.io) :
|
Finally, update your `.env` with your client's credentials:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
BCONNECT_CLIENT_ID=your_client_id
|
BCONNECT_CLIENT_ID=your_client_id
|
||||||
BCONNECT_CLIENT_SECRET=your_client_secret
|
BCONNECT_CLIENT_SECRET=your_client_secret
|
||||||
BCONNECT_REDIRECT="${APP_URL}/connect/callback"
|
BCONNECT_REDIRECT=http://localhost:8000/connect/callback
|
||||||
```
|
```
|
||||||
|
|
||||||
Et optionnellement :
|
### Sign in with Bluesquare Connect
|
||||||
|
|
||||||
```bash
|
Follow there instructions to add Bluesquare Connect's authentication to your app.
|
||||||
# URL du serveur OAuth
|
|
||||||
BCONNECT_URL=https://connect.bluesquare.io
|
Update your `routes/web.php`:
|
||||||
|
|
||||||
# Données demandées (scopes)
|
|
||||||
BCONNECT_USER_SCOPES=profile
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Il est possible de modifier d'autres comportements, à savoir :
|
|
||||||
- Model utilisateur utilisé (par défaut `App\Models\User`)
|
|
||||||
- URL de connexion via Bluesquare Connect (par défaut `/connect/authorize`)
|
|
||||||
- Remember me : garder la session active post-connexion (par défaut `true`)
|
|
||||||
|
|
||||||
Pour cela, il suffit de modifier le fichier `config/bconnect.php` généré via la commande `php artisan vendor:publish`.
|
|
||||||
|
|
||||||
### Configuration minimale de `User`
|
|
||||||
|
|
||||||
À moins d'utiliser le trait `HasConnectData` (voir ci-dessous), il faut s'assurer que toutes les colonnes autres que `email` sont `nullable` dans la table `users` (y compris `password`).
|
|
||||||
La colonne `email` est alors utilisée comme identifiant de référence par Bluesquare Connect.
|
|
||||||
|
|
||||||
### Connexion
|
|
||||||
|
|
||||||
Pour activer la connexion via Bluesquare Connect, il faut mettre à jour `web.php` en y ajoutant :
|
|
||||||
|
|
||||||
```php
|
|
||||||
use Bluesquare\Connect\Facades\Connect;
|
|
||||||
|
|
||||||
Connect::routes();
|
Connect::routes();
|
||||||
```
|
```
|
||||||
|
|
||||||
Si Blade est utilisé, un bouton "Connexion via Bluesquare Connect" peut être ajouté ainsi :
|
Add the "Sign in with Bluesquare Connect" button in your blade login page:
|
||||||
|
|
||||||
```blade
|
```blade
|
||||||
<x-connect-button/>
|
<x-connect-button/>
|
||||||
```
|
```
|
||||||
|
|
||||||
Sinon il suffit de rediriger vers `/connect/authorize` pour déclencher le flux.
|
Make sure that the `password` column of users table is nullable.
|
||||||
|
|
||||||
### Configuration personnalisée de `User`
|
#### Keep user tokens (optional)
|
||||||
|
|
||||||
Le trait `HasConnectData` permet d'exploiter au maximum les données fournies par Bluesquare Connect. Notamment :
|
First, make sure that your model implements `HasConnectTokens` trait.
|
||||||
- Définir quelle colonne sert d'identifiant unique (par défaut `connect_id`) avec `$connectIdentifier` ;
|
|
||||||
- Définir quelles données sont à injectées dans le Model à la connexion, avec `$connectFillable`
|
|
||||||
|
|
||||||
Pour utiliser l'identifiant par défaut, il convient d'ajouter cette colonne à `User` :
|
Then, add the following columns to your table:
|
||||||
|
|
||||||
```php
|
|
||||||
$table->string('connect_id')->nullable();
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Ou alors, et pour revenir à l'utilisation de `email` comme identifiant :
|
|
||||||
|
|
||||||
```php
|
|
||||||
use HasConnectData;
|
|
||||||
|
|
||||||
protected $connectIdentifier = 'email';
|
|
||||||
```
|
|
||||||
|
|
||||||
Ensuite, pour injecter automatiquement les données fournies par Bluesquare Connect (liste indicative ci-dessous) :
|
|
||||||
|
|
||||||
```php
|
|
||||||
protected $connectFillable = [
|
|
||||||
'name',
|
|
||||||
'email'
|
|
||||||
];
|
|
||||||
```
|
|
||||||
|
|
||||||
Il est possible de mapper les colonnes avec des noms différents et des valeurs par defaut, voire même d'injecter dans plusieurs colonnes, comme ceci :
|
|
||||||
|
|
||||||
```php
|
|
||||||
protected $connectIdentifier = ['connect_id' => 'oauth_id'];
|
|
||||||
|
|
||||||
protected $connectFillable = [
|
|
||||||
'name' => 'fullname|Anonymous',
|
|
||||||
'firstname' => ['firstname', 'nickname'],
|
|
||||||
'email' => 'email_address',
|
|
||||||
'group' => 'role|user'
|
|
||||||
];
|
|
||||||
```
|
|
||||||
|
|
||||||
Un hook est disponible pour un post-traitement des données Connect (après création / mise à jour de l'utilisateur) ce qui peut être utile pour mettre à jour des relations :
|
|
||||||
|
|
||||||
```php
|
|
||||||
use HasConnectData;
|
|
||||||
|
|
||||||
public function postFillConnectData(array $data)
|
|
||||||
{
|
|
||||||
// Exemple
|
|
||||||
$this->roles()->sync(
|
|
||||||
Role::whereIn('name', $data['groups'])->pluck('id')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Synchronisation des données _(optionnel)_
|
|
||||||
|
|
||||||
Par défaut, les données des utilisateurs sont mises à jour à chaque nouvelle connexion.
|
|
||||||
Cependant, deux méthodes peuvent être utilisées pour conserver les données de tous les utilisateurs à jour sans reconnexion.
|
|
||||||
|
|
||||||
### 1. Synchronisation passive
|
|
||||||
|
|
||||||
Le trait `HasConnectTokens` permet de conserver les tokens OAuth pour une utilisation future (par exemple, pour synchroniser les utilisateurs périodiquement).
|
|
||||||
|
|
||||||
Avant tout, il faut ajouter ces colonnes dans la table `users` :
|
|
||||||
|
|
||||||
```php
|
|
||||||
$table->text('connect_access_token')->nullable();
|
$table->text('connect_access_token')->nullable();
|
||||||
$table->text('connect_refresh_token')->nullable();
|
$table->text('connect_refresh_token')->nullable();
|
||||||
$table->datetime('connect_expires_at')->nullable();
|
$table->dateTime('connect_expires_at')->nullable();
|
||||||
```
|
```
|
||||||
|
|
||||||
Il est ensuite possible de mettre à jour les utilisateurs avec cette commande :
|
### Database syncing
|
||||||
|
|
||||||
|
Follow these instructions to sync your database with Bluesquare Connect.
|
||||||
|
|
||||||
|
In your `AppServiceProvider`, specify in the `boot()` function which entities you want to sync:
|
||||||
|
|
||||||
|
```
|
||||||
|
$connect->setSynchronized([
|
||||||
|
Role::class,
|
||||||
|
Company::class,
|
||||||
|
Team::class,
|
||||||
|
User::class,
|
||||||
|
UserTeam::class
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
|
Your models must use `HasConnectSync` trait. This trait allows you to customize the syncing behavior.
|
||||||
|
|
||||||
|
You also need to add this column to your synced tables:
|
||||||
|
|
||||||
|
```
|
||||||
|
$table->unsignedBigInteger('connect_resource_id')->unique();
|
||||||
|
```
|
||||||
|
|
||||||
|
_You can customize this column name and the syncing behavior in your model. Take a look at `HasConnectSync`._
|
||||||
|
|
||||||
|
Finally, use this command to sync everything:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
php artisan connect:sync
|
php artisan connect:sync
|
||||||
```
|
```
|
||||||
|
|
||||||
Mais aussi de seulement mettre à jour les tokens avant expiration avec cette commande :
|
#### Live updates (optional)
|
||||||
|
|
||||||
```bash
|
First, configure a webhook on Bluesquare Connect :
|
||||||
php artisan connect:refresh
|
|
||||||
```
|
|
||||||
|
|
||||||
Il est conseillé d'appeler ces commandes périodiquement via une tâche CRON dans `Console/Kernel.php`.
|
|
||||||
|
|
||||||
### 2. Synchronisation active (webhook)
|
|
||||||
|
|
||||||
Avant tout, il est requis de créer une `App` liée au client utilisé sur Bluesquare Connect, et d'en activer le webhook.
|
|
||||||
|
|
||||||
Ensuite, pour pouvoir utiliser le webhook, il faut ajouter ceci à `routes/api.php`:
|
|
||||||
|
|
||||||
```
|
|
||||||
use Bluesquare\Connect\Facades\Connect;
|
|
||||||
|
|
||||||
Connect::apiRoutes();
|
|
||||||
```
|
|
||||||
|
|
||||||
Cela va permettre à Bluesquare Connect d'appeler cette URL à chaque modification d'un utilisateur :
|
|
||||||
|
|
||||||
```
|
```
|
||||||
https://your-app.com/api/connect/webhook
|
https://your-app.com/api/connect/webhook
|
||||||
```
|
```
|
||||||
|
|
||||||
Pour terminer, il suffit d'ajouter le trait `HasConnectWebhook` à `User`.
|
Then, update your `routes/api.php`:
|
||||||
|
|
||||||
#### Configurer le comportement du webhook
|
```
|
||||||
|
Connect::apiRoutes();
|
||||||
|
```
|
||||||
|
|
||||||
Par défaut, le webhook se comporte ainsi :
|
## Advanced usage
|
||||||
- Lorsqu'un utilisateur est créé, il est inséré dans `users` comme à la première connexion ;
|
|
||||||
- Lorsqu'un utilisateur est mis à jour, il est modifié comme à chaque connexion / synchronisation ;
|
|
||||||
- Lorsqu'un utilisateur est supprimé, deux cas se présentent :
|
|
||||||
- si `User` implémente `SoftDeletes`, alors le webhook fait appel à `$user->delete()` ;
|
|
||||||
- si `SoftDeletes` est absent, alors la session utilisateur est simplement expirée en repassant `remember_token` à `null`.
|
|
||||||
- Si l'utilisateur est restauré, deux cas se présentent :
|
|
||||||
- si `User` implémente `SoftDeletes` et que l'utilisateur est bien présent en base de données, alors le webhook fait appel à `$user->restore()` ;
|
|
||||||
- si `SoftDeletes` est absent ou que l'utilisateur n'existe pas, alors on recréé l'utilisateur (s'il existe, il est simplement mis à jour).
|
|
||||||
|
|
||||||
Il est recommandé de personnaliser le cas de la suppression en ajoutant la fonction suivante à `User.php` :
|
### OAuth (sign in)
|
||||||
|
|
||||||
```php
|
#### Authorization
|
||||||
public function onConnectDelete(array $data)
|
|
||||||
|
Redirect to Bluesquare Connect authorization page:
|
||||||
|
|
||||||
|
```
|
||||||
|
public function authorize(Connect $connect)
|
||||||
{
|
{
|
||||||
// Optionnel : avec cette fonction on met à jour une dernière fois l'utilisateur
|
return $connect->redirect($optional_custom_state);
|
||||||
$this->onConnectUpdate($data);
|
|
||||||
|
|
||||||
//...supprimer l'utilisateur comme souhaité...
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Les autres cas peuvent être personnalisés avec ces différentes fonctions :
|
#### Authorization callback
|
||||||
|
|
||||||
```php
|
Auto: check state, login and redirect
|
||||||
public function onConnectCreate(array $data);
|
|
||||||
public function onConnectUpdate(array $data);
|
```
|
||||||
public function onConnectRestore(array $data);
|
public function callback(Request $request, Connect $connect)
|
||||||
|
{
|
||||||
|
return $connect->loginFromCallback($request, $optional_redirect_to);
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Données fournies par Bluesquare Connect
|
Manual: check state
|
||||||
|
|
||||||
- `id` et `connect_id` : identifiant unique de l'utilisateur
|
```
|
||||||
- `email` : adresse e-mail
|
public function callback(Request $request, Connect $connect)
|
||||||
- `name` : nom complet
|
{
|
||||||
- `firstname` et `nickname` : prénom
|
$valid = $connect->checkState($request);
|
||||||
- `lastname` : nom de famille
|
// ...
|
||||||
- `avatar`, `picture` et `profile_picture` : URL de la photo de profil
|
}
|
||||||
- `company` : entreprise
|
```
|
||||||
- `job` : mêtier exercé dans l'entreprise
|
|
||||||
- `group` : rôle principal (les groupes sont personnalisées pour chaque App sur Bluesquare Connect)
|
#### Tokens management
|
||||||
- `groups` : tableau contenant tous les rôles associés à l'utilisateur
|
|
||||||
|
```
|
||||||
|
// Retrieve tokens from an authorization code
|
||||||
|
$connect_data = $connect->getAccessTokenFromAuthorizationCode($code);
|
||||||
|
|
||||||
|
// Retrieve tokens from a refresh token
|
||||||
|
$connect_data = $connect->getAccessTokenFromRefreshToken($connect_data['refresh_token']);
|
||||||
|
|
||||||
|
// With HasConnectTokens trait: get your local user tokens
|
||||||
|
$connect->getUserAccessToken($user);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### User data
|
||||||
|
|
||||||
|
```
|
||||||
|
// Retrieve user data from an access token
|
||||||
|
$user_data = $connect->getUserData($connect_data['access_token']);
|
||||||
|
|
||||||
|
// Example: find the corresponding user in your database
|
||||||
|
$user = User::where('email', $user_data['email'])->first();
|
||||||
|
```
|
||||||
|
|
||||||
|
### OAuth (client)
|
||||||
|
|
||||||
|
#### Token management
|
||||||
|
|
||||||
|
```
|
||||||
|
// Get an access token
|
||||||
|
$connect->getAccessToken();
|
||||||
|
|
||||||
|
// Delete the current access token from cache
|
||||||
|
$connect->deleteAccessToken();
|
||||||
|
```
|
||||||
|
|
||||||
|
#### API resources
|
||||||
|
|
||||||
|
```
|
||||||
|
// Fetch all users
|
||||||
|
$connect->getAll('User');
|
||||||
|
|
||||||
|
// Fetch an user
|
||||||
|
$connect->get('User', 1);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Syncing
|
||||||
|
|
||||||
|
```
|
||||||
|
// Sync everything
|
||||||
|
$optional_resource_types = ['User', ...];
|
||||||
|
$connect->syncAll($optional_resource_types);
|
||||||
|
|
||||||
|
// Sync a specific resource
|
||||||
|
$connect->sync('User', 1);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Webhook
|
||||||
|
|
||||||
|
```
|
||||||
|
// Handle a webhook request
|
||||||
|
$connect->handleWebhook($request);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
Publish our config file (`config/bconnect.php`) to customize the package configuration:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
php artisan vendor:publish
|
||||||
|
```
|
||||||
|
|
|
@ -4,7 +4,6 @@ namespace Bluesquare\Connect\Commands;
|
||||||
|
|
||||||
use Bluesquare\Connect\Connect;
|
use Bluesquare\Connect\Connect;
|
||||||
use Bluesquare\Connect\ConnectException;
|
use Bluesquare\Connect\ConnectException;
|
||||||
use Bluesquare\Connect\Traits\HasConnectData;
|
|
||||||
use Bluesquare\Connect\Traits\HasConnectTokens;
|
use Bluesquare\Connect\Traits\HasConnectTokens;
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
|
|
||||||
|
@ -33,10 +32,6 @@ class Sync extends Command
|
||||||
$data = $connect->getUserData($model->connect_access_token);
|
$data = $connect->getUserData($model->connect_access_token);
|
||||||
$connect->updateUserData($model, $data);
|
$connect->updateUserData($model, $data);
|
||||||
$model->save();
|
$model->save();
|
||||||
|
|
||||||
if (in_array(HasConnectData::class, class_uses($model))) {
|
|
||||||
$model->postFillConnectData($data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (\Exception $exception) {
|
catch (\Exception $exception) {
|
||||||
|
|
|
@ -6,7 +6,6 @@ use Bluesquare\Connect\Traits\HasConnectData;
|
||||||
use Bluesquare\Connect\Traits\HasConnectTokens;
|
use Bluesquare\Connect\Traits\HasConnectTokens;
|
||||||
use Bluesquare\Connect\Traits\HasConnectWebhook;
|
use Bluesquare\Connect\Traits\HasConnectWebhook;
|
||||||
use GuzzleHttp\Client;
|
use GuzzleHttp\Client;
|
||||||
use Illuminate\Contracts\Foundation\Application;
|
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Routing\Router;
|
use Illuminate\Routing\Router;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
@ -18,7 +17,7 @@ class Connect
|
||||||
{
|
{
|
||||||
protected $app;
|
protected $app;
|
||||||
|
|
||||||
public function __construct(Application $app)
|
public function __construct($app)
|
||||||
{
|
{
|
||||||
$this->app = $app;
|
$this->app = $app;
|
||||||
}
|
}
|
||||||
|
@ -95,7 +94,7 @@ class Connect
|
||||||
|
|
||||||
$url = $this->getUrl() . '/oauth/authorize?' . $query;
|
$url = $this->getUrl() . '/oauth/authorize?' . $query;
|
||||||
|
|
||||||
return redirect($url);
|
return redirect()->to($url);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function checkState(Request $request)
|
public function checkState(Request $request)
|
||||||
|
@ -210,7 +209,7 @@ class Connect
|
||||||
$model = $this->resolveUser($data, $hasSoftDeletes);
|
$model = $this->resolveUser($data, $hasSoftDeletes);
|
||||||
|
|
||||||
if ($model->exists()) {
|
if ($model->exists()) {
|
||||||
if ($hasSoftDeletes && $model->trashed()) {
|
if ($hasSoftDeletes) {
|
||||||
$event = 'restore';
|
$event = 'restore';
|
||||||
} else {
|
} else {
|
||||||
$event = 'update';
|
$event = 'update';
|
||||||
|
@ -224,10 +223,6 @@ class Connect
|
||||||
} else {
|
} else {
|
||||||
$this->updateUserData($model, $data);
|
$this->updateUserData($model, $data);
|
||||||
$model->save();
|
$model->save();
|
||||||
|
|
||||||
if (in_array(HasConnectData::class, class_uses($model))) {
|
|
||||||
$model->postFillConnectData($data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $model;
|
return $model;
|
||||||
|
|
|
@ -44,9 +44,4 @@ trait HasConnectData
|
||||||
foreach ($touched as $model)
|
foreach ($touched as $model)
|
||||||
$model->save();
|
$model->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function postFillConnectData(array $data)
|
|
||||||
{
|
|
||||||
// Intended for post-processing / relationship handling
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,10 +18,6 @@ trait HasConnectWebhook
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->save();
|
$this->save();
|
||||||
|
|
||||||
if (in_array(HasConnectData::class, class_uses(self::class))) {
|
|
||||||
$this->postFillConnectData($data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onConnectDelete(array $data)
|
public function onConnectDelete(array $data)
|
||||||
|
|
Loading…
Reference in New Issue