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);
}
Related
all. I'm just trying to implement Single sign-on server using Laravel and passport app.
What I'm trying to achieve: A single sign-on server who listen to the request from the client and provide the authentication based on the requested parameter.
What I've achieved so far: The SSO server who listen to the client request and provide the authentication and redirect back to the client site only if the user already registered on the SSO server.
The problem is coming to the picture when the user is not registered on SSO server and try to register the account In this case Laravel register user and redirect back to the homepage instead client callback URL.
Please let me know if this is achievable in Laravel or someone does something special for it.
It is pretty much achievable, depends on how much effort you want to put towards it.
When the user is registering, you can save the callback URL in the session.
session(['callback' => $callback]);
Upon registration, redirect the user to their callback URL
return redirect()->away(session('callback'));
If you are still using the default Auth/RegisterController provided by laravel, you can change the redirect behavior by defining a custom redirect function
protected function redirectTo()
{
return redirect()->away(session('callback'));
}
Laravel will automatically pick it up.
Don't forget to delete the property
protected $redirectTo = '/home';
Yes you can do this with some customization in default registration functionality, you have to replace some code in RegistrationController as provided below:
app\Http\Controllers\Auth\RegistrationController
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use AuthenticatesUsers, RegistersUsers {
AuthenticatesUsers::redirectPath insteadof RegistersUsers;
AuthenticatesUsers::guard insteadof RegistersUsers;
}
public function register(Request $request)
{
$this->validator($request->all())->validate();
event(new Registered($user = $this->create($request->all())));
if ($this->attemptLogin($request)) {
if ($request->hasSession()) {
$request->session()->put('auth.password_confirmed_at', time());
}
return $this->sendLoginResponse($request);
}
}
I pretty new in PHP and absolutely new in Laravel and I have the following problem.
I am using Laravel to develop a front end application (so I use it only for route, controller and view). All the business logic is implemented by a Java back end application implementing REST web services.
I know that Laravel provide a pretty well done automatic login system creation using the statement:
php artisan make:auth
The problem is that this system directly interact with the database.
In my case the Laravel application have only to interact with the Java back end application (it is this application that interact with the database). So this system is not appropriate for me. At this development stage we have no token.
Basically the Laravel front end application is something like this:
1) A view showing the login form (username and password).
2) A controller class that contains a method that receive the submit of the previous form and that call the REST web service of the back end application (doing request having an authorization header containing the inserted username and password.
The backend application will return (into to previous Laravel controller method) a JSON containing the user information like this as response:
{
"userName": "Painkiller",
"email": "painkiller#gmail.com",
"enabled": true
}
or, in case the user is not authorized, something like this
{
"timestamp": 1485183649134,
"status": 401,
"error": "Unauthorized",
"message": "Credenziali non valide",
"path": "/Extranet/login"
}
So basically if the user in authenticate (if the Laravel controller receive the first JSON type), the JSON object i converted into a PHP model object representing the logged user, this object is put into the session and the user is redirected to the following page.
Could be a neat solution? or can create some kind of problem?
And here another doubt. Into the Laravel project structure I have the App\Http\Controllers\Auth namespace containing the autogenerated LoginController class, this:
class LoginController extends Controller
{
/*
|--------------------------------------------------------------------------
| Login Controller
|--------------------------------------------------------------------------
|
| This controller handles authenticating users for the application and
| redirecting them to your home screen. The controller uses a trait
| to conveniently provide its functionality to your applications.
|
*/
use AuthenticatesUsers;
/**
* Where to redirect users after login.
*
* #var string
*/
protected $redirectTo = '/home';
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('guest', ['except' => 'logout']);
}
}
From what I understood this class should be used for the Laravel native login system (the one implemented performing the php artisan make:auth statement).
So is it maybe better create a new controller class for my custom login that involves the call of my back end web service? Or what?
You can overright any method of the AuthenticatesUsers trait inside the LoginController. And thus, have the full control of what the build-in controller does.
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;
});
}
Building an app in Laravel 5.3, one of the functionalities is for the admin to be able to log into the app as a user, to be able to see what that specific user can see, while maintaining his admin session to be able to go back to the user list and be possible to log in as another user without having to re-authenticate.
Currently implemented the basic out-of-the-box Laravel Auth, meaning if I start another auth session it will terminate my admin session making me having to re-login.
I have checked Laravel Multi Auth but seems to work with two tables (user,admin), which in my case we use one user table and use an ACL for managing roles and deciding whos admin and whos user.
What programming logic ideas do you guys have for this solution? Trying to find other opinions/ideas in how this could be implemented in Laravel 5.x
I've implemented the feature on a project recently. I did this using the session and a middleware. This is how I did it:
Create a controller 'ImpersonateController' and Set two routes for impersonateIn and impersonateOut for the purpose.
Route::get('impersonateIn/{user}', 'ImpersonateController#impersonateIn');
Route::get('impersonateOut', 'ImpersonateController#impersonateOut');
In the ImpersonateController#impersonateIn method just set the user id you want to log in and the URL backUrl into the session variable.
public function impersonateIn($id)
{
session(['impersonated' => $id, 'backUrl' => \URL::previous()]);
return redirect()->to('dashboard');
}
public function impersonateOut()
{
$back_url = Request::session()->get('backUrl');
Request::session()->forget('impersonated', 'secretUrl');
return $back_url ?
redirect()->to($back_url) :
redirect()->to('dashboard');
}
The first part is done. Now every request need to check the if the session has the
impersonated variable set. A good place to do that is a middleware.
Create a middleware to check the session on the handle method. If the impersonated found then log as the user using the Auth::onceUsingId() for the current request only.
class ImpersonateMiddleware
{
public function handle($request, Closure $next)
{
if(Request::session()->has('impersonated'))
{
Auth::onceUsingId(Request::session()->get('impersonated'));
}
}
}
Now you just need to apply the middleware for every request. The best place to do this from the Http/Kernel.php
protected $middlewareGroups = [
'web' => [
//....
\App\Http\Middleware\ImpersonateMiddleware::class,
],
];
The only remaining thing is you need to check the session and replace the logout route to the impersonateOut. Now when the admin logged out from the user will be redirected to the old route.
That's it!
Are you sure you really have to login?
I would stay logged in as admin and simulate user login.
You can allow admin access to all the databases.
In your controller you can use User::find($user_id) instead of Auth::user() for accessing user's data.
https://laravel.com/docs/5.3/database
https://laravel.com/docs/5.3/eloquent
Personaly, I would do this with sessions. I have not used Laravel but I use PHP often, so my answer will be in PHP.
In the header page, you most likely have some kind of session check to see if the user is logged in. For example:
<? php
session_start();
if (isset($_SESSION['user'])){
//do stuff with the user session
} else {
die('User not logged in!');
}
?>
I would change this to something like:
<? php
session_start();
if (isset($_SESSION['fakeuser'])){
//do stuff with the user session
//change logout button to destroy this session instead of logging the user out
}
elseif (isset($_SESSION['user'])){
//do stuff with the user session
} else {
die('User not logged in!');
}
?>
In the page in which you swap users, you would just simply copy the way a session starts when a user logs in. To switch users, you destroy the new 'fakeuser' and you are back to your old session + admin permissions without having to log back in again.
That's the logical approach I would take anyways.
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.