I'm making an app with Live Chat in Laravel 5 and I'm following this tutorial, https://github.com/dazzz1er/confer/tree/master I already followed all of them but I'm having an error in my web console:
Seems like it's making an ajax call on my url http://localhost/joene_/public/index.php/auth and since I don't have a route to handle that request, it says 404. I don't know if should make a route for it but what will I code on there? I have no idea. The tutorial doesn't even mention it.
Thanks
Whenever, you call Auth::check(), Laravel will verify if the user is authenticated by checking its session information.
What about Pusher? How will they know, which users are currently logged in on your laravel application?
The answer lies in the ajax call http://localhost/joene_/public/index.php/auth.
By calling the above URL, your laravel installation will let your Pusher application link with your users' laravel session.
Let's dive into some code:
1) Pusher Auth Controller
class PusherController extends Controller {
//accessed through '/pusher/'
//setup your routes.php accordingly
public function __construct() {
parent::__construct();
//Let's register our pusher application with the server.
//I have used my own config files. The config keys are self-explanatory.
//You have received these config values from pusher itself, when you signed up for their service.
$this->pusher = new Pusher(\Config::get('pusher.app_key'), \Config::get('pusher.app_secret'), \Config::get('pusher.app_id'));
}
/**
* Authenticates logged-in user in the Pusher JS app
* For presence channels
*/
public function postAuth()
{
//We see if the user is logged in our laravel application.
if(\Auth::check())
{
//Fetch User Object
$user = \Auth::user();
//Presence Channel information. Usually contains personal user information.
//See: https://pusher.com/docs/client_api_guide/client_presence_channels
$presence_data = array('name' => $user->first_name." ".$user->last_name);
//Registers users' presence channel.
echo $this->pusher->presence_auth(Input::get('channel_name'), Input::get('socket_id'), $user->id, $presence_data);
}
else
{
return Response::make('Forbidden',403);
}
}
}
2) JS used with Pusher
//replace 'xxx' below with your app key
var pusher = new Pusher('xxx',{authEndpoint : '/pusher/auth'});
var presenceChannelCurrent = pusher.subscribe('presence-myapp');
presenceChannelCurrent.bind('pusher:subscription_succeeded', function() {
alert(presenceChannelCurrent.members.me.info.name+' has successfully subscribed to the Pusher Presence Channel - My App');
});
Hope it helps you.
Related
I am looking for some clarification as for how exactly to proceed with Oauth auth code PKCE grant when it comes to authorizing my own SPA.
So I get this when I am redirected from my SPA to backend (after I log in of course):
Now I get this, makes sense if I want to login into my app with google or twitter for example.
But If I want to log in to the backend app to get the token with my SPA - is there a way to avoid that every time a user logs in? Does it make sense?
I would like to have it from user perspective like this:
click login
redirect to backend pretending to be SPA (visually)
login
go straight back to SPA without having to confirm that stuff
I just mainly want to understand the process for SPA. I assume and suspect that what I want is simply not possible?
Yes you can :)
Create your own Passport client.
<?php
declare(strict_types=1);
namespace App\Models;
class PassportClient extends \Laravel\Passport\Client
{
/**
* Determine if the client should skip the authorization prompt.
*
* #return bool
*/
public function skipsAuthorization()
{
// todo: add some checks, e.g. $this->name === 'spa-client'
return true;
}
}
And update your App\Providers\AuthServiceProvider.
public function boot()
{
// ...
Passport::useClientModel(PassportClient::class);
}
I have a project in Laravel where I am using the same method for both a web and api route. So for example i would have the following:
//routes/web.php
Route::post("/import-results", "ImportController#doImport");
//routes/api.php
Route::post("/import-results/{auto}", "ImportController#doImport");
So regardless of the route the doImport() function will be called in the ImportContoller.
The import controller has a function like this (there is validation in the function but I have taken it out for simplicity):
public function doImport($auto = null){
$importData = new DataImport();
$importData->type = $_POST['type'];
$importData->data = $_POST['data'];
$importData->user = Auth::user()->name;
$importData->save();
$data = [
"success" => true,
"message" => "Message Here!"
]
if($auto){
return json_encode($data);
}else{
return view('import-message', $data);
}
}
As you can see this method uses Auth::user()->name; to identify which user imported the data. This is fine if i am logging in and using a regular web route but what about if i'm using an API and using basic auth where no sessions are created and I don't want sessions to persist if the api routes are called.
How do i get the user info when calling API routes?
Also for the web routes i have customised my login as i'm using ldap but essentially the login happens by doing $this->guard()->login($user, false); in a class with the AuthenticatesUsers trait.
I could do this for my API routes too but does this creates a session and how do i clear this session once the request has ended? Or is there a better way??
To make session work for both page submitting and api. You need work in web.php
Make both route in web.php
//Web.php
Route::post("/import-results", "ImportController#doImport");
Route::post("/api/import-results/{auto}", "ImportController#doImport");
api.php is stateless mean no session exist in api.php . It's working with token based like JWT.
I have followed the steps of this tutorial in order to setup API authentication in Laravel 5.3 using the auth:api middleware.
Everything is working as expected apart from I am finding that in order to successfully access my API, I only need to provide an API token for any user in my users table rather than the token linked to the user currently logged in.
Is this expected behaviour because this middleware is stateless? I am using AdLdap2 to authenticate users but I can't see what I could be doing wrong especially as I have followed the steps in the tutorial above.
I have also had a look at TokenGuard which deals with API token validation but can't see any logic that ensures the token matches that of the user logged in.
Any help is much appreciated.
I think the authentication works like expected. The only thing auth:api does is making sure you are authenticated to access the protected routes. If you want to protect a specific route to only one user you could use Gates
So if you have a route to access a user like below and you want the user that's logged in to only access herself you can add a gate.
routes/web.php
Route::get('/user/{id}', function ($id) {
$userYourTryingToView = User::find($id);
if (Gate::allows('get-user', $userYourTryingToView)) {
// The user is allowed to access herself, return the user.
return response()->json($userYourTryingToView);
}
// User is not authenticated to view some other user.
return response('Unauthenticated', 403);
});
And in your app/Providers/AuthServiceProvider.php
/**
* Register any authentication / authorization services.
*
* #return void
*/
public function boot()
{
$this->registerPolicies();
Gate::define('get-user', function ($authenticatedUser, $userYourTryingToView) {
return $authenticatedUser->id == $userYourTryingToView->user_id;
});
}
I implemented phpCAS as a Service Provider in my app that is running Laravel 5.1. Every single page in my app needs to be authorized so I created a Helper function that authenticates with phpCAS on my main app.blade.php file. The Helper function authenticates and then retrieves user information from my database so I can get user properties (id, fullName, etc.)
Here is the helper function:
public static function full_authenticate() {
Cas::authenticate();
$username = Cas::getCurrentUser();
$userinfo = Users::where('username', '=', $username)->first();
return $userinfo;
if (!is_null($userinfo)) {
return "ERROR." //THIS DOES NOT WORK
} else {
return View::share('userinfo', $userinfo);
}
}
This is how it's used in app.blade.php (as an example)
{{ Helpers::full_authenticate()->fullname }}
The authentication works perfectly and if you are in the Users model, it will load up your information no problem. The issue I am having is when you authenticate successfully in CAS, but are not in the Users table, I want to be able to throw a 403 error or redirect to another view or just say some sort of message, but no matter what I put in the "return" section, it doesn't work. I think it has something to do with my helper function running behind a controller, but I have no idea.
Also looked into integrating CAS into middleware, but not sure how to pursue that.
Any ideas would be awesome! Thanks in advance!
I am having trouble finding a method for authenticating API users in my application. I set out to initially build a system that users could access and authenticate through the web, but requirements have changed and I need to implement some additional actions that can be available in a RESTful manner using a POST API call.
I have created a class that extends CBehaviour and forced a redirect to the login page for all unauthenticated users (found on the yii framework forum here). Problem is that all API calls are forced through the same logic and any POST requests simply spit out the HTML to the login page.
class ApplicationBehavior extends CBehavior {
private $_owner;
public function events() {
return array(
'onBeginRequest' => 'forceGuestLogin',
);
}
public function forceGuestLogin() {
$owner = $this->getOwner();
if ($owner->user->getIsGuest())
$owner->catchAllRequest = array("site/login");
}
}
How would I go about separating the authentication of API users from the Web users?
I would follow this guide on creating a REST API in Yii. After modifying the config urlManager entries, all of your API requests will use the APIController. You can then place the following code in the beforeAction of your APIController to return nothing if the user is a guest (Or an error message)
protected function beforeAction($event) {
if (Yii::app()->user->isGuest) {
echo "Invalid credentials";
Yii::app()->end();
}
}
Note: The code above works for my purposes because all REST requests are sent via the same browser. (Which is already logged in and has a login cookie)
If you replace that behavior with a new base controller placed in protected/controllers to force login, it will only apply to your pages that require a login and not your APIController. Here is an example of mine:
//Make sure all Controllers which require a login inherit from this
class ControllerLoginRequired extends CController {
public function runAction($action) {
if (Yii::app()->user->isGuest && 'site' != $this->route) {
Yii::app()->user->returnUrl = $this->route;
parent::redirect(array('site/login'));
} else {
parent::runAction($action);
}
}
}
Everything explained will work for REST requests via the same browser in which the user has logged onto Yii. If you will have the need to expose your REST service to consumers that are not a browser logged into Yii, I believe you would have to come up with a custom authentication/token scheme.