Skip to content

Commit 7d500db

Browse files
committed
Proof of concept
1 parent 5744f64 commit 7d500db

File tree

7 files changed

+330
-1
lines changed

7 files changed

+330
-1
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/composer.lock
2+
/vendor/

.php_cs.dist

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
$finder = PhpCsFixer\Finder::create()
4+
->exclude('bootstrap')
5+
->exclude('resources')
6+
->exclude('vendor')
7+
->in(__DIR__)
8+
;
9+
10+
return PhpCsFixer\Config::create()
11+
->setRules([
12+
'@Symfony' => true,
13+
])
14+
->setFinder($finder)
15+
;

README.md

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,77 @@
1-
# flarum-laravel-session
1+
# Flarum Laravel Session <!-- omit in toc -->
2+
3+
**Disclaimer**: This package is still a proof of concept.
4+
5+
- [What it does](#what-it-does)
6+
- [Requirements](#requirements)
7+
- [Installation and configuration](#installation-and-configuration)
8+
- [Usage](#usage)
9+
- [Accessing session cookie from different domain](#accessing-session-cookie-from-different-domain)
10+
11+
## What it does
12+
This package allows to use the session of [Flarum](https://flarum.org/) for authentication within a Laravel application.
13+
It accesses Flarum's session cookie and reads the session data from the session storage.
14+
Based on the user information in the Flarum database an user in the Laravel application is created / updated and logged in.
15+
16+
## Requirements
17+
+ PHP 7.4
18+
+ Laravel 7
19+
+ Working installation of Flarum in the same filesystem as the Laravel application, so Flarum's session files can be accessed
20+
+ Flarum and Laravel need to share the same domain / subdomain, so Flarum's session cookie can be read
21+
22+
## Installation and configuration
23+
Install the package by executing `composer require lbausch/flarum-laravel-session:dev-master` and register the middleware in `app/Http/Kernel.php`:
24+
```php
25+
/**
26+
* The application's route middleware.
27+
*
28+
* These middleware may be assigned to groups or used individually.
29+
*
30+
* @var array
31+
*/
32+
protected $routeMiddleware = [
33+
// ...
34+
'flarum' => \Bausch\FlarumLaravelSession\FlarumMiddleware::class,
35+
// ...
36+
];
37+
```
38+
Define a database connection for the Flarum database in `config/database.php`:
39+
```php
40+
'flarum' => [
41+
'driver' => 'mysql',
42+
'url' => env('FLARUM_DATABASE_URL'),
43+
'host' => env('FLARUM_DB_HOST', '127.0.0.1'),
44+
'port' => env('FLARUM_DB_PORT', '3306'),
45+
'database' => env('FLARUM_DB_DATABASE', 'forge'),
46+
'username' => env('FLARUM_DB_USERNAME', 'forge'),
47+
'password' => env('FLARUM_DB_PASSWORD', ''),
48+
'unix_socket' => env('FLARUM_DB_SOCKET', ''),
49+
'charset' => 'utf8mb4',
50+
'collation' => 'utf8mb4_unicode_ci',
51+
'prefix' => '',
52+
'prefix_indexes' => true,
53+
'strict' => true,
54+
'engine' => null,
55+
'options' => extension_loaded('pdo_mysql') ? array_filter([
56+
PDO::MYSQL_ATTR_SSL_CA => env('FLARUM_MYSQL_ATTR_SSL_CA'),
57+
]) : [],
58+
],
59+
```
60+
Publish the package configuration using `php artisan vendor:publish --provider=Bausch\\FlarumLaravelSession\\ServiceProvider` and update `config/flarum.php` with your settings.
61+
62+
## Usage
63+
In `routes/web.php` you may assign the middleware as desired:
64+
```php
65+
Route::middleware(['flarum'])->group(function () {
66+
Route::get('/', function () {
67+
return view('welcome');
68+
});
69+
});
70+
```
71+
72+
## Accessing session cookie from different domain
73+
If Flarum is running on domain.tld and Laravel on sub.domain.tld you need to configure Flarum (`config.php`), so the session cookie can be accessed on the subdomain:
74+
```php
75+
// Note the dot before domain.tld
76+
'cookie' => ['domain' => '.domain.tld'],
77+
```

composer.json

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{
2+
"name": "lbausch/flarum-laravel-session",
3+
"description": "Use Flarum's session within Laravel",
4+
"type": "library",
5+
"require-dev": {
6+
"orchestra/testbench": "^5.3"
7+
},
8+
"license": "MIT",
9+
"authors": [
10+
{
11+
"name": "Lorenz Bausch",
12+
"email": "[email protected]"
13+
}
14+
],
15+
"require": {
16+
"php": "^7.4",
17+
"illuminate/auth": "^7.0",
18+
"illuminate/filesystem": "^7.0",
19+
"illuminate/http": "^7.0",
20+
"illuminate/session": "^7.0",
21+
"illuminate/support": "^7.0"
22+
},
23+
"autoload": {
24+
"psr-4": {
25+
"Bausch\\FlarumLaravelSession\\": "src/"
26+
}
27+
},
28+
"extra": {
29+
"laravel": {
30+
"providers": [
31+
"Bausch\\FlarumLaravelSession\\ServiceProvider"
32+
]
33+
}
34+
}
35+
}

config/flarum.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
return [
4+
/*
5+
* Flarum url
6+
*/
7+
'url' => env('FLARUM_URL'),
8+
9+
/*
10+
* Model which is authenticatable
11+
*/
12+
'model' => App\User::class,
13+
14+
/*
15+
* Flarum session configuration
16+
*/
17+
'session' => [
18+
/*
19+
* Name of the Flarum session cookie
20+
*/
21+
'cookie' => env('FLARUM_SESSION_COOKIE', 'flarum_session'),
22+
23+
/*
24+
* Absolute path to the session directory of Flarum
25+
*/
26+
'path' => base_path('flarum/storage/sessions'),
27+
],
28+
29+
/*
30+
* Flarum database connection as defined in config/database.php
31+
*/
32+
'db_connection' => env('FLARUM_DB_CONNECTION', 'flarum'),
33+
];

src/FlarumMiddleware.php

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
<?php
2+
3+
namespace Bausch\FlarumLaravelSession;
4+
5+
use Closure;
6+
use Illuminate\Filesystem\Filesystem;
7+
use Illuminate\Foundation\Auth\User;
8+
use Illuminate\Http\Request;
9+
use Illuminate\Session\FileSessionHandler;
10+
use Illuminate\Session\Store;
11+
use Illuminate\Support\Facades\App;
12+
use Illuminate\Support\Facades\Auth;
13+
use Illuminate\Support\Facades\Config;
14+
use Illuminate\Support\Facades\DB;
15+
use Illuminate\Support\Str;
16+
17+
class FlarumMiddleware
18+
{
19+
/**
20+
* Handle an incoming request.
21+
*
22+
* @return mixed
23+
*/
24+
public function handle(Request $request, Closure $next)
25+
{
26+
// If the user is already authenticated, continue
27+
if (Auth::check()) {
28+
return $next($request);
29+
}
30+
31+
// Get content of Flarum session cookie
32+
$flarum_session_id = $request->cookie(Config::get('flarum.session.cookie', false));
33+
34+
// Abort if no session id could be found
35+
if (!$flarum_session_id) {
36+
abort(403);
37+
}
38+
39+
// Create session store
40+
$session_store = new Store('flarum-laravel-session', $this->getFileSessionHandler(), $flarum_session_id);
41+
42+
// Start session
43+
$session_started = $session_store->start();
44+
45+
// Abort if session could'nt be started
46+
if (!$session_started) {
47+
abort(403);
48+
}
49+
50+
// Try to get user id
51+
$user_id = $session_store->get('user_id', false);
52+
53+
// Redirect if no user id was found
54+
if (!$user_id) {
55+
return redirect(Config::get('flarum.url'));
56+
}
57+
58+
// Get Flarum user from Flarum database
59+
$flarum_user = DB::connection(Config::get('flarum.database_connection'))->table('users')->find($user_id);
60+
61+
// Abort if no Flarum user is present in database
62+
if (!$flarum_user) {
63+
abort(403);
64+
}
65+
66+
// Find the corresponding local user
67+
$user = $this->getUser()->where('flarum_id', $flarum_user->id)->first();
68+
69+
// Create or update the corresponding local user
70+
$user = $this->createOrUpdateUser($user, $flarum_user);
71+
72+
// Login the local user and remember him
73+
Auth::login($user, true);
74+
75+
return $next($request);
76+
}
77+
78+
/**
79+
* Get FileSessionHandler.
80+
*/
81+
protected function getFileSessionHandler(): FileSessionHandler
82+
{
83+
// Create filesystem
84+
$filesystem = new Filesystem();
85+
86+
// Get path to session files
87+
$session_path = Config::get('flarum.session.path');
88+
89+
// Session lifetime in minutes
90+
$lifetime_minutes = 120;
91+
92+
return new FileSessionHandler(
93+
$filesystem,
94+
$session_path,
95+
$lifetime_minutes
96+
);
97+
}
98+
99+
/**
100+
* Create or update User.
101+
*/
102+
protected function createOrUpdateUser(?User $user, object $flarum_user): User
103+
{
104+
// Get a user instance
105+
if (is_null($user)) {
106+
$user = $this->getUser();
107+
}
108+
109+
// Attributes to update: local user => flarum user
110+
$attributes = [
111+
'username' => 'username',
112+
'nickname' => 'nickname',
113+
'flarum_id' => 'id',
114+
'email' => 'email',
115+
];
116+
117+
// Update attributes
118+
foreach ($attributes as $attribute) {
119+
$user->{$attribute} = $flarum_user->{$attribute};
120+
}
121+
122+
// Set a random password
123+
$user->password = bcrypt(Str::random(30));
124+
125+
// Save user
126+
$user->save();
127+
128+
// Return user
129+
return $user;
130+
}
131+
132+
/**
133+
* Get User instance.
134+
*/
135+
protected function getUser(): User
136+
{
137+
return App::make(config('flarum.model'));
138+
}
139+
}

src/ServiceProvider.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
namespace Bausch\FlarumLaravelSession;
4+
5+
use Illuminate\Support\ServiceProvider as BaseServiceProvider;
6+
7+
class ServiceProvider extends BaseServiceProvider
8+
{
9+
/**
10+
* Register any application services.
11+
*
12+
* @return void
13+
*/
14+
public function register()
15+
{
16+
}
17+
18+
/**
19+
* Bootstrap any application services.
20+
*
21+
* @return void
22+
*/
23+
public function boot()
24+
{
25+
$this->publishes([
26+
__DIR__.'/../config/flarum.php' => config_path('flarum.php'),
27+
]);
28+
}
29+
}

0 commit comments

Comments
 (0)