Laravel - Pusher Authentication - Server Side - laravel

I'm working on an chat application with 2 components: a client side that is a mobile app and a server side that is developed with Laravel. Currently I can't seem to figure out how to do the pusher authentication side on the server for a user on a specific channel. After figuring the documentation I found that the authentication is done via js call from the frontend with the socket-id but for my application I need to do the authentication from the server because I'm keeping a history of the messages in a local DB. What I don't find is how can I do this on the server.
The code I use for authentication is just authenticating the client on db based on a key I created in the channel enrol:
public function authorizeUser(Request $request, $groupId, $conversationId) {
/*
$socket_id = $request->get('socket_id');
*/
$user = Auth::user();
$conversation = Conversation::find($conversationId)->where('group_id', $groupId)->first();
$user_conversation = DB::table('user_conversation')
->where('conversation_id', $conversation->id)
->where('user_id', $user->id)
->first();
if($user_conversation->authorized) {
return response()->json(['response' => 'You are authorized!'], 201);
}
$accessToken = Crypt::decryptString($request->get('key'));
//dd($conversation->access_token.' '.$accessToken);
if(Hash::check($accessToken, $conversation->access_token)) {
$conversation->users()
->wherePivot('authorized', false)
->updateExistingPivot($user->id,[
'authorized' => true
]);
// Some how, here I should authorize the user for pusher
return response()->json(['response' => 'You have been authorized!'], 201);
}
}
The documentation states that I should use the routes/channels.php file to authenticate the users but from the server side I can't use Laravel Echo for creating a connection. This is done automatically from the broadcast.php file where I have set the env for the pusher.
Thank you,
Armand

Related

Create session on consuming login with api on laravel

I have an api that has a method to start and I am calling it from a frontend project.
In the front end project I use Guzzle to make the call via post to the api and login, from which I get back a json with the user data and a jwt token.
But when I receive the token as I manage the session, I must create a session and save the token, since the laravel to authenticate I need a model user and have a database, which of course I do not have in this backend because I call the api to log in, which brings a token and user data, then as I manage it from the backend, I'm a little lost there.
$api = new Api();
$response = $api->loginapi(['user'=>'wings#test.com','password'=>'123']);
Because here I could not do Auth::login($user) to generate the session.
Because I don't have here the database because the login is done from the api.
There I call the api, of which the answer is the token, but how do I manage it from here, creating a session? saving the token?
thanks for your help.
With api, you don't usually manage a session. usually, you'd call something like
Auth::attempt([
'email' => 'me#example.com',
'password' => 'myPassword'
]);
If the credentials are correct, laravel will include a Set-Cookie header in response, and, that is how you authenticate with api. Via an auth cookie. You don't need to do anything else.
Let's show you how:
//AuthController.php
public function login(Request $request) {
$validatedData = $request->validate([
'email' => 'required|email',
'password' => 'required'
]);
if(Auth::attempt($validatedData)){
return ['success' => 'true'];
}
else{
return ['success' => false, 'message' => 'Email or password Invalid'];
}
}
public function currentUser (){
return Auth::user();
}
Now, the APi file
Route::post('/login', ['App\Http\Controllers\AuthController', 'login']);
Route::get('/current_user', ['App\Http\Controllers\AuthController', 'currentUser']);
Now if you make a call to /api/current_user initially, you'll get null response since you're not currently logged in. But once you make request to /api/login and you get a successful response, you are now logged in. Now if you go to /api/current_user, you should see that you're already logged in.
Important ::
If you are using fetch, you need to include credentials if you're using something other than fetch, check out how to use credentials with that library or api
You want to use the API to authenticate and then use the SessionGuard to create session including the remember_me handling.
This is the default login controller endpoint for logging in. You don't want to change this, as it makes sure that user's do not have endless login attempts (protects for brut-force attacks) and redirects to your current location.
public function login(Request $request)
{
$this->validateLogin($request);
// If the class is using the ThrottlesLogins trait, we can automatically throttle
// the login attempts for this application. We'll key this by the username and
// the IP address of the client making these requests into this application.
if (method_exists($this, 'hasTooManyLoginAttempts') &&
$this->hasTooManyLoginAttempts($request)) {
$this->fireLockoutEvent($request);
return $this->sendLockoutResponse($request);
}
if ($this->attemptLogin($request)) {
if ($request->hasSession()) {
$request->session()->put('auth.password_confirmed_at', time());
}
return $this->sendLoginResponse($request);
}
// If the login attempt was unsuccessful we will increment the number of attempts
// to login and redirect the user back to the login form. Of course, when this
// user surpasses their maximum number of attempts they will get locked out.
$this->incrementLoginAttempts($request);
return $this->sendFailedLoginResponse($request);
}
The core happens when we try to "attemptLogin" at
protected function attemptLogin(Request $request)
{
return $this->guard()->attempt(
$this->credentials($request), $request->boolean('remember')
);
}
When using the SessioGurad (which is default) the method attemptLogin fires a couple of events, checks if the user has valid credentials (by hashing the password and matching it with db) and then logs the user in, including the remember me functionality.
Now, if you don't care about events, you can just check from your API if the credentials match and then use the login method from the guard. This will also handle the remember me functionality. Something like this:
protected function attemptLogin(Request $request)
{
$username = $request->input($this->username());
$password = $request->input('password');
$result = \Illuminate\Support\Facades\Http::post(env('YOUR_API_DOMAIN') . '/api/v0/login' , [
'username' => $username,
'password' => $password
])->json();
if(empty($result['success'])){
return false;
}
// Maybe you need to create the user here if the login is for the first time?
$user = User::where('username', '=', $username)->first();
$this->guard()->login(
$user, $request->boolean('remember')
);
return true;
}

Laravel - Alternative for Session in Laravel Socialite Login in Rest API

I am new to Laravel Socialite Login. In my Laravel-8 Application, I have used:
'Socialite' => Laravel\Socialite\Facades\Socialite::class,
for Azure Socialite Login, which works for the multi-company Login. I store the company id in Session.
public function getCompanies() {
$current_domain = request()->getHost(); // your company app name
$domain = explode('.', $current_domain);
return OrgCompany::where('subdomain', $domain[0])->firstOrFail();
}
public function redirectToProvider(Request $request, OrgSocialiteSetting $azureCredential)
{
$companies = $this->getCompanies();
if($companies){
$company_credentials = OrgSocialiteSetting::where('id', $companies->id)->first();
//when switching between different API Credentials
config(['services.azure.client_id' => $company_credentials->client_id]);
config(['services.azure.client_secret' => $company_credentials->client_secret]);
config(['services.azure.redirect' => $company_credentials->client_redirect]);
session(['id' => $request['company']]);
return Socialite::with('azure')->redirect();
}
return back()->with('status', 'Please select a Valid company');
}
Now I want to convert the same code to Laravel Rest API whereby I consume it in Angular-10
I am using Laravel-Passport and LaravelSocialite as shown above.
Since I am no more using Session, how do I now deal with
session(['id' => $request['company']]);
in the code above?
Thanks

Laravel SAML - user automatically logged out after log in

I have connected my Laravel app to the Azure, and I'm using the SAML2 protocol for user authentication. The issue which i have is that user is logged in application (Auth::login($user)), and after that when printing auth()->user() i get logged in user object. However, somehow user session is destroyed after that, and the user is redirected to the login page. Callback for SAML response is located in a service provider boot() method and looks like this:
public function boot()
{
Event::listen('Aacotroneo\Saml2\Events\Saml2LoginEvent', function (Saml2LoginEvent $event) {
$messageId = $event->getSaml2Auth()->getLastMessageId();
// Add your own code preventing reuse of a $messageId to stop replay attacks
$user = $event->getSaml2User();
$userMap = config('saml2_settings.user_map');
$emailAddress = $user->getAttribute($userMap['email']);
$laravelUser = User::where('email', '=', $emailAddress[0])->first();
if ($laravelUser) {
Auth::login($laravelUser);
return;
}
$azureService = new AzureService();
$newUser = $azureService->createNewUserFromSaml($userMap, $user);
if ($newUser){
Auth::login($newUser);
}
});
}

Laravel login from external system

I'm developing a module with Laravel 5 inside an external system, the external system has its own login and data in another DB, then I had to implement permissions into my Laravel module, so I had to configure a Middleware in the routes, and now i get 2 login screens, I just need to log into Laravel using the external system, i created the same credentials in laravel's user table, so i want to check external username against laravel username, get the password and auto-login into laravel.
where to do this is the main problem i face.
I need this screen to autologin
Routes middleware:
Route::group(['middleware' => ['role:admin,access_backend']], function(){
Route::get('dashboard', 'dashboardController#dashboard');
.....
.....
I Get username from external system using guzzle
$client = new Client(); //GuzzleHttp\Client
$result = $client->get($url);
$body = (string)$result->getBody();
this is what i'm trying in role middleware:(guess it fails with the password hash , i always get the login screen)
$resp = User::select('username','password')->where('username',trim($body))->first();
$password = (bcrypt($resp->password));
if (Auth::attempt(['username' =>$resp->username, 'password' => $password])){
dd('Hello world');
return redirect()->intended('dashboard');
/* ->route('admin/dashboard')
->with('Welcome! Your account has been successfully created!'); */
}
if (Auth::guest()) {
return redirect(url(config('backpack.base.route_prefix').'/login'));
}

Laravel auth loses session after redirect

Due to laravel's default auth system not working for my current project I used their manual authentication system. The authenticating works but after I redirect the authentication gets destroyed or it simply isn't getting stored properly.
My authController:
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\Auth;
class manualAuthController extends Controller {
public function authenticate(){
if (Auth::attempt(['email' => $_POST['email'], 'password' => $_POST['password']])) {
// Authentication passed...
$user = Auth::user();
//return '$user';
return redirect("test2");
}
return 'Auth failed!';
}
}
My route to test if the authenticated user is still stored:
Route::get('test2', function(){
echo 'test2<br>';
$user = Auth::user();
echo $user;
return '.';
});
If I uncomment "return '$user';" then the authenticated user gets returned properly.
I know that this question has been asked before but I couldn't find anybody with a working/ reliable solution to this problem so can someone here please help me with this problem(or finding the exact problem)?
Side note: I previously used the Socialite system which we had to switch for the laravel auth due to hosting problems. After this switch it worked in development for a while with my current session and db settings. Due to some other bugs I switched to manual authentication.

Resources