authentication problem with azure active directory and laravel - php

I'm trying to configure the login to a laravel app with the azure active directory, locally everything works fine, but when I try to publish it in a test environment I get this error:
enter image description here
this is my auth controller:
class AuthController extends Controller
{
#https://warlord0blog.wordpress.com/2019/09/04/laravel-and-o365-authentication/
function login()
{
return Socialite::driver('azure')->redirect();
}
function redirect()
{
if (!request()->has('code')) {
abort(500, 'No se recibió un código de autenticación.');
}
$user = Socialite::driver('azure')->user();
//dd($user);
$usuario = User::select('id')->where('email', '=', $user['mail'])->where('estatus', '=', 'Activo')->first();
if (null == $usuario) {
abort(404, 'Usuario no encontrado: ' . $user['mail']);
}
//dd($usuario);
Auth::loginUsingId($usuario->id);
// Auth::login($user, true);
return redirect()->route('home');
}
I don't know if my problem is from the Azure active directory configuration, I was reading that it is a container problem, but the deployment is done through a merge in gitlab

Related

User not loged in after redirect from login with laravel socialite

Hello I am using Laravel Socialite for Oauth authentication with my remote Laravel Paspport app. After getting successfully the user autheticated with passport when I want to get the user to the aplication it redirects me back to login and acts as he is loged out. The client (Socialite is on this git https://gitlab.fit.cvut.cz/ouredma3/trackage ) I tried switching domain in settings but nothing worked. It worked fine before I implemented the Oauth. I ma using Socialite with https://socialiteproviders.netlify.app/providers/laravel-passport.html
I hope its all that u need but if anything lemme know and I shall add more info
Laravel 7.x, PHP 7.2
This is My loginController.
public function redirectToProvider()
{
return Socialite::driver('laravelpassport')->redirect();
}
/**
* Obtain the user information from Passport
*
* #return \Illuminate\Http\Response
*/
public function handleProviderCallback(Request $request)
{
try {
$userSocial = Socialite::driver('laravelpassport')->stateless()->user();
} catch (\Exception $e) {
return redirect('/login')->withError($e->getMessage());
}
$users = User::where(['email' => $userSocial->getEmail()])->first();
if($users){
Auth::login($users,true);
}else{
$user = User::create([
'email' => $userSocial->getEmail(),
'provider_id' => $userSocial->getId()
]);
Auth::login($user,true);
}
//session(['current_user' => $userSocial]);
return redirect('/');
}
Ok I tried to deploy my application to server and surprise surprise it worked.. The problem is probably with local sessions.

Laravel 6 - setting up a multi-tenant application with nested tenants

I am currently trying to figure out the best way to set up multi-tenancy for my system. The issue I'm facing is that a tenant doesn't always have to be a sub-domain but can be set up as part of a sub-domain, where the sub-domain can have multiple tenants. I can't seem to find anything online that would help me set this up in Laravel 6.
System Requirements:
A server can have many sub-domains
A sub-domain can be a tenant
A sub-domain can have many tenants
A tenant can have many users
a tenant can have different features
The system has to be set up with a single database that will use tenant_id to determine which data belongs to a tenant.
I am currently storing all sub-domain data in a table "subdomains" with the following structure:
id
subdomain (unique)
status
nested_tenants (yes/no)
where the column nested_tenants determines whether or not the sub-domain is a tenant(=0) itself or has multiple tenants(=1). if the sub-domain does not have nested tenants then we set tenant_id=subdomain
if the sub-domain does have nested tenants then we store all of these in a table with structure:
id
subdomain (the sub-domain it belongs to)
tenant (the tenant - unique field)
name
status
and we set tenant_id=tenant from this table.
if we have nested tenants for a sub-domain then we cannot determine what the current tenant is until the user logs in. we would have to get the tenant_id from the user details.
My current set up:
I've been following this article and have set up the following:
I have two models
Subdomain,
Tenant
Routes/web.php:
Route::group([
'middleware' => \App\Http\Middleware\IdentifySubdomain::class,
'as' => 'tenant:',
'namespace' => 'Tenant'
], function () {
// custom auth routes
Route::get('/login', 'Auth\LoginController#index')->name('login');
Route::post('/login', 'Auth\LoginController#login');
Route::get('/home', 'HomeController#index')->name('home');
});
Middleware IdentifySubdomain:
class IdentifySubdomain
{
protected $tenantManager;
public function __construct(TenantManager $tenantManager) {
$this->tenantManager = $tenantManager;
}
public function handle($request, Closure $next)
{
/** need to check whether subdomain is valid
* if subdomain is valid return the request page else error message.
* if subdomain is true it will check the nested_tenants value from db.
* if nested_tenants is false it will set the tenant to current subdomain
* else the tenant is not set yet.
*/
// get host domain and subdomain domain
$host = $request->getHost();
// get subdomain position
$pos = strpos($host, env('TENANT_DOMAIN'));
$subdomain = substr($host, 0, $pos - 1);
if ($pos !== false && $this->tenantManager->checkSubdomain($subdomain)) {
return $next($request);
}
throw new NotFoundHttpException;
}
}
TenantManager:
class TenantManager {
private $tenant;
public function setTenant(?Tenant $tenant) {
$this->tenant = $tenant;
return $this;
}
public function getTenant(): ?Tenant {
return $this->tenant;
}
public function loadTenant(string $identifier): bool {
$tenant = Tenant::query()->where('tenant', '=', $identifier)->first();
if ($tenant) {
$this->setTenant($tenant);
return true;
}
return false;
}
public function checkSubdomain(string $identifier) : bool {
$subdomain = Subdomain::query()->where('subdomain', '=', $identifier)->first();
if ($subdomain) {
if ($subdomain->nested_tenants) {
// tenant not found yet so do not set tenant
return true;
} else {
return $this->loadTenant($identifier);
}
}
return false;
}
}
Service Provider
class TenantServiceProvider extends ServiceProvider
{
public function register()
{
$manager = new TenantManager;
$this->app->instance(TenantManager::class, $manager);
$this->app->bind(Tenant::class, function() use ($manager) {
$tenant = $manager->getTenant();
if ($tenant === null) {
return new Tenant;
}
return $manager->getTenant();
});
}
}
Login Controller:
class LoginController extends Controller
{
public function __construct()
{
$this->middleware('guest')->except('logout');
}
...
public function login(Request $request, Tenant $tenant) {
$request->validate([
'email' => ['required', 'email', 'max:255'],
'password' => ['required'],
]);
$credentials = $request->only('email', 'password');
$credentials['status'] = 1;
if ($tenant->id) {
$credentials['tenant_id'] = $tenant->tenant;
}
if (Auth::attempt($credentials)) {
return redirect()->intended('home');
}
return Redirect::to('login')->withSuccess('Login Failed! You entered invalid credentials');
}
...
}
Issues
My main concern is that I don't feel like this is the best approach to keeping track of the tenant. I need it so that once the tenant is set I can use it throughout the application, without always first checking if the user is authenticated first - to then get the tenant. I am currently adding Tenant $tenant to the controller methods where I need tenant related data, but is a there better way of going about this?
Any advice on how I could improve my current set up would be helpful.
I think you should implement Traits to add tenant constraints for example:
in models:
BelongsToTenantModelTrait{
public static function bootBelongsToTenantModelTrait(){
static::addGlobalScope(function ($model){
model->where('tenant_id',auth()->user()->tenant->id);
//Or any similar logic
});
}
and other traits to controllers if needed.
You may also add middlewares like AuthTenant if needed as well.
I think this way should decouple the tenant-related logic as much as possible.
Let me know what you think.

How to redirect after login in laravel 4.2?

I'm used to working on laravel 5.4 and above, i just got this project with a problem in authentification that is rather weird.
Locally, the authentification works just fine but when i try to log using the project on prod i always get redirected to login page.
this is the login function:
public function loginadmin()
{
$pseudo = Input::get('pseudo');
$pass = Input::get('pass');
$user = Admin::where('pseudo',$pseudo)->where('pass',$pass)->get()->first();
if($user){
Auth::admin()->loginUsingId( $user->id );
return Redirect::back();
}
else{
Session::flash('errorAuth', "ok");
return Redirect::back();
}
}
this is the routes.php
/* Connexion */
Route::get('admin-igd', function(){
if( !Auth::admin()->get())
return View::make('admin.login');
return Redirect::to('admin-igd/slider');
});
and this is the filters.php:
Route::filter('loginadmin', function($route, $request)
{
if ( !Auth::admin()->get()) {
return Redirect::to('admin-igd');
}
});
Try once after executing below command on your project.
php artisan route:clear

Not Getting correct model record from query on Eloquent RelationShip Laravel 5.1

I'm working on a 5.1 Laravel app. In that app I have a OnetoMany Relationship between Bussiness Model (named Negocio in spanish) and User Model. When I register my user I create a token and save it in users table to use the token on email confimation....
When the user confirms it account I want to use the token received by controller to create a directory with then name of the business that user is related to in 'public/negocios/'.
So in my controller to userconfirmartion I have:
public function emailConfirm($token)
{
try {
//getting the bussiness that user is related to
$negocio = App\Negocio::with(['user' => function ($query) use($token) {
$query->where('token', 'like', $token);
}])->firstOrFail()->folderProfile();
//Then we activate the user account
$user = User::whereToken($token)->firstOrFail()->confirmEmail();
return redirect('/login')->with('mensaje', '¡Su cuenta de usuario se ha activado, ahora puede iniciar sesión en su cuenta!');
} catch (ModelNotFoundException $e) {
return redirect('/login')->with('mensaje', 'Ya se ha confirmado a este usuario, solo inicie sesión ¬¬');
}
}
In my Business Model I have the function to create the directory getting the bussiness name as the name of the directory:
public function folderProfile()
{
$name = str_replace(' ', '', $this->nombre_negocio);
$ruta_a_public = public_path().'/negocios/';
$ruta_a_public .= $name;
File::makeDirectory($ruta_a_public, $mode = 0777, true, true);
}
The problem is probing the code on php artisan tinker Eloquent gets all my bussiness recorded on database not just the business that user is related to.
It'd be appreciated from you if you could tell me the best way to make my "query" work as expected
The part that fails is (on business model):
$negocio = App\Negocio::with(['user' => function ($query) use($token) {
$query->where('token', 'like', $token);
}])->firstOrFail()->folderProfile();
I based it on what I read in https://laravel.com/docs/5.1/eloquent-relationships#querying-relations
EDIT:
In my Negocio model(bussiness model in spanish):
public function user()
{
return $this->hasMany('App\User', 'negocio', 'codigo_negocio');
}
And in User Model I have this:
public function negocio()
{
return $this->belongsTo('App\Negocio', 'negocio', 'codigo_negocio');
}
Thanks guys... Sorry for this long post.
It's a diffent logic but maybe help:
//First search for the user
$user = App\User::where('token','like','%' . $token . '%')->first();
//Then search for the business
$negocio = App\Negocio::where('user_id',$user->id)->first();
Do not forget to define the relations between the tables.
By the way, you forget the % here:
$query->where('token', 'like', '%' . $token . '%');
If you looking for exact the same token, you should use this:
Something::where('token',$token)
After further reading on laravel documentation https://laravel.com/docs/5.1/eloquent-relationships The way that works for me and get the expected record is:
$negocio = App\Negocio::whereHas('user', function ($query) use($token) {
$query->where('token', $token);
})->firstOrFail()->folderProfile();
This way I get the right business that token's owner is related to...
Thanks #szebasztian for some new tips for me about building querys on eloquent ORM.

iOS app communicate with Laravel webapp

I’m working on a project based on an iOS app (native) who use a webapp (Laravel framework) to communicate.
For exemple, ios user should use Laravel login to use the application.
The laravel part of the project is done and work good on a computer (login,register etc…)
But now i’m thinking how will i communicate with my futur ios App and my webapp using laravel framework. I dont know any ways to do that, maybe i need a special framwork on my ios app ?
I have no idea, can you help me ?
Thanks in advance
This is a loaded question.... My personal preference is to set up a set of API controllers so you can control them independently and version them.
1) Create a sub-set of controllers # /app/controllers/api/v1
2) Give them all a namespace of api/v1
<?php namespace api\v1;
3) Import whatever classes you need into the new namespace
<?php namespace api\v1;
use Illuminate\Support\Facades\Input;
use Illuminate\Support\Facades\Response;
use Usage;
use Auth;
4) Install an oAuth2 package
5) Set up routes that generate and validate tokens and place your protected routes in a route group. (my example below.)
Route::group(['prefix' => 'api/v1', 'before' => 'apiErrors'], function()
{
Route::post('accessToken', function()
{
return AuthorizationServer::performAccessTokenFlow();
});
Route::group(['before' => 'oauth|setUser'], function()
{
Route::resource('usages', 'api\v1\UsagesController');
Route::resource('connections', 'api\v1\ConnectionsController');
Route::resource('users', 'api\v1\UsersController');
});
});
6) Set up your new api controllers to return data in a manner that a mobile app can use (JSON)
public function index()
{
$usages = Usage::with('device.model.manufacturer')
->where('user_id', Auth::user()->id)
->get();
return Response::json($usages, $this->responseCode, $this->accessControl);
}
thanks for your complete answer ! but i have done an simple API controller without oAuth2 package. My controller for the moment just return true or false if login is okay and it works good. here my code for other people...
public function trylogin() {
if (Auth::attempt(array('email'=>Input::get('email'), 'password'=>Input::get('password'))) || Auth::attempt(array('username'=>Input::get('username'), 'password'=>Input::get('password')))) {
return Response::json(array('status' => 'OK'));
} else {
return Response::json(array('status' => 'FAIL'));
}
}
here my api routes
Route::resource('api/v1', 'ApiController');
Route::get('api/v1_hello', 'ApiController#sayhello');
Route::get('api/v1_login', 'ApiController#trylogin')
what do you think about security managment ? i can make my own token system validation on ios ?
EDIT
i finally found a solution, here the function in my ApiController :
you just need to send to your api from iOS the token generate by Facebook or Google connexion. and in my case add a network parameter.
public function registerOrLoginFromSocialNetWorkV1(){
if (Input::get('email') && Input::get('sn_id')) {
//sn = social network
if (User::where('email','=', Input::get('email'))->count() != 0) {
$user = User::where('email','=', Input::get('email'))->first();
$user->fb_id = Input::get('sn_id');
$user->save();
//return 'email already used';
}
else{
if (User::where('fb_id','=', Input::get('sn_id'))->count() == 0) {
$user = new User;
$user->firstname = Input::get('firstname');
$user->lastname = Input::get('lastname');
$user->username = Input::get('username');
$user->email = Input::get('email');
$user->fb_id = Input::get('sn_id');
$user->fk_role = 3;
$user->yearofbirth = Input::get('birthday');
//$user->yearofbirth = substr($me['birthday'],6,9);
if (Input::get('sex') == 'male') {
$user->sex = 1;
}
else{
$user->sex = 0;
}
$user->save();
Userslog::log('api_register_social_network');
}
else{
$user = User::where('fb_id','=', Input::get('sn_id'))->first();
if (!$user->yearofbirth){
$user->yearofbirth = Input::get('birthday');
$user->save();
}
}
}
//dd($user);
Auth::login($user);
$follows = Follow::where('user_id','=',$user->id)->get();
return Response::json(array('user' => $user,'follows' => $follows));
}
else{
return 'error';
}
}

Categories