-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
support login via LDAP/OAuth #39
Comments
+1 for LDAP |
+1 for LDAP as well. |
Just setting up a local raspberry pi LDAP server now so I can get familiar with LDAP and implement it properly 😄 |
As of release 0.7 (commit 148e172) LDAP user auth is now part of BookStack. It's only basic at the moment, and experimental since it has only been tested by me. Setup/Usage instructions are in the readme. Since login is functional in some capacity I will close this issue. For any extra LDAP features or bugs new ,more focused, issues should be created. |
@MVprobr Thanks for letting me know. In regards to oAuth, What exactly is it that you want implemented in BookStack?
Sorry for the questions, I'm not too familiar with the actual use cases when it comes to oAuth. |
I need to setup a specific oauth2 provider in my case. This should be easy to implement. |
To login into BookStack with a oauth2 provider is also one of my needs. +1 |
@younes0 did you ever get sorted with this? I'd like to experiment with it against identityserver4 and possibly use this system. |
@dealproc I've setup Socialite on my bookstack instance, and I handle user creation from my main app. Socialite: namespace BookStack\Providers;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\ServiceProvider;
use BookStack\User;
use BookStack\Icra\IcramProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
// Custom validation methods
\Validator::extend('is_image', function($attribute, $value, $parameters, $validator) {
$imageMimes = ['image/png', 'image/bmp', 'image/gif', 'image/jpeg', 'image/jpg', 'image/tiff', 'image/webp'];
return in_array($value->getMimeType(), $imageMimes);
});
$socialite = $this->app->make('Laravel\Socialite\Contracts\Factory');
$socialite->extend('icram', function ($app) use ($socialite) {
$config = $app['config']['services.icram'];
return $socialite->buildProvider(IcramProvider::class, $config);
});
}
}
<?php
namespace BookStack\Icra;
use Laravel\Socialite\Two\AbstractProvider;
use Laravel\Socialite\Two\ProviderInterface;
use Laravel\Socialite\Two\User;
class IcramProvider extends AbstractProvider implements ProviderInterface
{
/**
* {@inheritdoc}
*/
protected function getAuthUrl($state)
{
return $this->buildAuthUrlFromBase(env('ICRAM_URL').'/oauth/authorize', $state);
}
/**
* {@inheritdoc}
*/
protected function getTokenUrl()
{
return env('ICRAM_URL').'/oauth/token';
}
/**
* {@inheritdoc}
*/
public function getAccessToken($code)
{
$response = $this->getHttpClient()->post($this->getTokenUrl(), [
'headers' => ['Authorization' => 'Basic ' . base64_encode($this->clientId . ':' . $this->clientSecret)],
'body' => $this->getTokenFields($code),
]);
return $this->parseAccessToken($response->getBody());
}
/**
* {@inheritdoc}
*/
protected function getTokenFields($code)
{
return array_add(
parent::getTokenFields($code), 'grant_type', 'authorization_code'
);
}
/**
* {@inheritdoc}
*/
protected function getUserByToken($token)
{
$response = $this->getHttpClient()->get(env('ICRAM_URL').'/api/me', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
],
]);
return json_decode($response->getBody(), true);
}
/**
* {@inheritdoc}
*/
protected function mapUserToObject(array $user)
{
return (new User)->setRaw($user)->map([
'id' => $user['id'],
'nickname' => $user['username'],
'name' => $user['firstname'].' '.$user['lastname'],
'avatar' => null,
]);
}
} User Creation: <?php
namespace Icram\Models;
use Yeb\Laravel\ExtendedModel;
use Carbon\Carbon;
class WikiUser extends ExtendedModel
{
protected $connection = 'wiki';
public static $unguarded = false;
public $table = 'users';
protected $guarded = [''];
/**
* Define the relationship with the user's roles.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function roles()
{
return $this->belongsToMany(WikiRole::class, 'role_user', 'user_id', 'role_id');
}
public function getUser()
{
return User::where('email', $this->email)->first();
}
public static function firstOrCreateFromUser(User $user, $delete = true)
{
if ($model = $user->getWikiUser()) {
if ($delete) {
$model->delete();
} else {
return $model;
}
}
$model = static::create(static::getDefaults($user));
// group
$roleName = $user->is_admin ? 'admin' : 'viewer';
$role = WikiRole::where('name', $roleName)->first();
$model->roles()->attach($role);
$model->save();
$con = \DB::connection('wiki');
// social account
$con->table('social_accounts')->insert([
'user_id' => $model->id,
'driver' => 'icram',
'driver_id' => $user->id,
'avatar' => '',
]);
// image
$imageId = $con->table('images')->insertGetId([
'name' => $user->id.'.jpg',
'url' => $user->photoUrl,
'path' => '/photos/'.$user->id.'.jpg',
'type' => 'jpeg',
'created_at' => Carbon::now(),
'updated_at' => Carbon::now(),
'created_by' => $model->id,
'updated_by' => $model->id,
]);
$model->update(['image_id' => $imageId]);
return $model;
}
public function syncInfos()
{
$this->update(static::getDefaults($this->getUser()));
return $this;
}
static protected function getDefaults($user)
{
return [
'name' => $user->fullname,
'email' => $user->email,
'email_confirmed' => true,
'password' => $user->password ?: str_random(),
'external_auth_id' => '',
'image_url' => $user->photoUrl,
];
}
}
<?php
namespace Icram\Models;
use Yeb\Laravel\ExtendedModel;
class WikiRole extends ExtendedModel
{
protected $connection = 'wiki';
public static $unguarded = false;
public $table = 'roles';
protected $guarded = [''];
/**
* Define the relationship with the group's users.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function users()
{
return $this->belongsToMany(WikiUser::class, 'role_user');
}
}
// usage from main app
/*
* Create/Update related when User is created/updated
*
* @return void
*/
public static function boot()
{
parent::boot();
// created
static::created(function($model) {
$model->profile()->create([]);
});
// updated
static::updated(function($model) {
// wiki
$wikiUser = $model->getWikiUser();
if ($wikiUser) {
$wikiUser->syncInfos();
} else if ($model->isComplete()) {
WikiUser::firstOrCreateFromUser($model);
}
});
// deleted
static::deleting(function($model) {
if ($wikiUser = WikiUser::where('email', $model->email)->first()) {
$wikiUser->delete();
}
});
} |
I have no idea of how to make that dance. Will have to bookmark this and come back to it once i get a little read through and see if its possible. my hope was to have a user directed to this, and let them create their user within the system as a "user", and then assign them into what categories they'd need thereafter. I like the idea of this system as you're publishing eBooks per topic/product/whatever, which is what intrigued me about it. |
No description provided.
The text was updated successfully, but these errors were encountered: