How to link domain and sub-domain in Route with Azure Socialite Login
In my Laravel-5.8 application, I have a multi-company application using a single database without using package. Each table have a company_id derived from the company table as shown below:
id | company_name | subdomain
1 | Main |
2 | Company1 | company1
3 | Company2 | company2
Main=> localhost:8888/myapp
Company1=>localhost:8888/company1.myapp
Company2=>localhost:8888/company2.myapp
I have these models:
class Copmany extends Model
{
protected $table = 'organizations';
protected $fillable = [
'id',
'company_name',
'subdomain',
];
}
class User extends Authenticatable
{
protected $fillable = [
'name',
'username',
'email',
'password',
'company_id',
];
public function company()
{
return $this->belongsTo('App\Models\Company');
}
}
Also I am using Azure Socialite Login.
class LoginController extends Controller
{
use AuthenticatesUsers;
protected $redirectTo = '/dashboard';
protected $username = 'username';
public function redirectToProvider()
{
return Socialite::with('azure')->redirect();
}
public function handleProviderCallback()
{
$azureUser = Socialite::with('azure')->user();
try
{
$user = User::where('email', $azureUser->email)->orWhere('username', $azureUser->user['mailNickname'])->first();
if($user)
{
if(Auth::loginUsingId($user->id))
{
$user->update([
'last_login_at' => now(),
]);
return redirect()->intended('/dashboard');
}
}
}
catch(\Exception $e)
{
session()->flash("error", "Authentication failed, kindly contact the Administrator!");
return redirect(route('login'));
}
}
}
I created a middleware:
class VerifyDomain
{
public function handle($request, Closure $next)
{
$domain == "myapp"; // your company app name
$path = $request->getPathInfo(); // should return /company1.myapp or /company2.myapp or /myapp
if (strpos($path, ".") !== false) { // if path has dot.
list($subdomain, $main) = explode('.', $path);
if(strcmp($domain, $main) !== 0){
abort(404); // if domain is not myapp then throw 404 page error
}
} else{
if(strcmp($domain, $path) !== 0){
abort(404); // if domain is not myapp then throw 404 page error
}
$subdomain = ""; // considering for main domain value is empty string.
}
$company = Company::where('subdomain', $subdomain)->firstOrFail(); // if not found then will throw 404
$request->session()->put('subdomain', $company); //store it in session
return $next($request);
}
}
Already, I have two (2) route groups in the route/web.php wgich looks like this:
Route::get('/', ['as' => '/', 'uses' => 'IndexController@getLogin']);
Auth::routes();
Route::get('/dashboard', 'HomeController@index')->name('dashboard');
// Config Module
Route::group(['prefix' => 'config', 'as' => 'config.', 'namespace' => 'Config', 'middleware' => ['auth']], function () {
Route::resource('countries', 'ConfigCountriesController');
Route::resource('nationalities', 'ConfigNationalitiesController');
});
// HR Module
Route::group(['prefix' => 'hr', 'as' => 'hr.', 'namespace' => 'Hr', 'middleware' => ['auth']], function () {
Route::resource('designations', 'HrDesignationsController');
Route::resource('departments', 'HrDepartmentsController');
Route::resource('employee_categories', 'HrEmployeeCategoriesController');
});
A user can exit in more that one organization.
When a user logins in with azure socialite, I want the application to check the domain and sub-domain route and use it to get the company_id, then map it with the company_id in the user tables.
For instance, if user logs in using localhost:8888/myapp, the application use it to get the company_id in the user table, and if it is localhost:8888/company1.myapp, it does likewise and so on.
The user should only see the profile based on his company. Also should only see it's company data.
How do I achieve this from the route and LoginController?
Please or to participate in this conversation.