Comments (10)
To login into BookStack with a oauth2 provider is also one of my needs. +1
from bookstack.
Just setting up a local raspberry pi LDAP server now so I can get familiar with LDAP and implement it properly 😄
from bookstack.
+1 for LDAP
Bonus point, if you add reverse proxy auth compatibility via HTTP basic authentification (for SSO) I will probably make a Yunohost package.
from bookstack.
+1 for LDAP as well.
from bookstack.
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.
from bookstack.
@MVprobr Thanks for letting me know. In regards to oAuth, What exactly is it that you want implemented in BookStack?
- Some kind of generic oAuth implementation?
- A specific oAuth provider to login with?
- Do you want BookStack to act as a oAuth provider?
Sorry for the questions, I'm not too familiar with the actual use cases when it comes to oAuth.
from bookstack.
I need to setup a specific oauth2 provider in my case. This should be easy to implement.
I will also try to make the admin options for it.
from bookstack.
@younes0 did you ever get sorted with this? I'd like to experiment with it against identityserver4 and possibly use this system.
from bookstack.
@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();
}
});
}
from bookstack.
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.
from bookstack.
Related Issues (20)
- Ubunut Docker installation - Need help by link HOT 5
- WYSWIYG code editor lacks direction support
- Horizontally Scrolling Table for a Large Matrix? HOT 2
- BookStack v24.02.3 .pdf export failure "Maximum execution time of 30 seconds exceeded" HOT 3
- Unable to connect to BookStack after changing host machine/server IP address. HOT 2
- screen layout on large screen HOT 2
- Bookstack frontend is redirected to old domain name after updated URL HOT 2
- FileStorage.php line 40 Operation not permitted HOT 1
- Forms to supply table entries
- possibility to reduce dimensions of scaled images
- Custom Navigation Links and Popup
- Add Scala to list of supported languages in code blocks HOT 2
- Update Bookstack form BookStack v23.12.2 to BookStack v24.02.3 HOT 3
- BookStack https subinformation access show blank site HOT 5
- Popup containing permalink slug doesn't appear after text selection
- An upgrade is required on your databases HOT 2
- How change the domain name, or ip of url already installed HOT 1
- Differences of line-heights for paragraphs in table cells between editor and page view HOT 3
- About restore a backup HOT 2
- Request for help using the Logical Theme system to enable logging in via url parameters HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from bookstack.